Fossil

Check-in [ca7aae80ad]
Login

Check-in [ca7aae80ad]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:chat: ARIA-related attribute changes suggested in the forum.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ca7aae80ad701e4d4b91b911599ccd01260b43e28bfc7c69367ff18ba4ceec3c
User & Date: stephan 2020-12-27 09:05:18.297
Context
2020-12-27
09:37
Added an ARIA role=alert to the fossil.toast.message/warning/error() popup, per form request. Toast API doc corrections. ... (check-in: 23d6b4570a user: stephan tags: trunk)
09:05
chat: ARIA-related attribute changes suggested in the forum. ... (check-in: ca7aae80ad user: stephan tags: trunk)
08:32
chat: added buttons to jump to top/bottom of message list. Added a huge margin under the input area because Safari demands it. Improved the div.content auto-resize calculation to get a more precise fit. ... (check-in: 2408082760 user: stephan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/chat.c.
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
  @     <input type="text" name="msg" id="chat-input-single" \
  @      placeholder="Type message here." autocomplete="off">
  @     <textarea rows="8" id="chat-input-multi" \
  @      placeholder="Type message here" class="hidden"></textarea>
  @     <input type="submit" value="Send" id="chat-message-submit">
  @     <button id="chat-scroll-bottom">&darr;</button>
  @     <button id="chat-scroll-top">&uarr;</button>
  @     <span id="chat-settings-button" class="settings-icon"></span>

  @   </div>
  @   <div id='chat-input-file-area'>
  @     <div class='file-selection-wrapper'>
  @       <div class='help-buttonlet'>
  @        Select a file to upload, drag/drop a file into this spot,
  @        or paste an image from the clipboard if supported by
  @        your environment.







|
>







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  @     <input type="text" name="msg" id="chat-input-single" \
  @      placeholder="Type message here." autocomplete="off">
  @     <textarea rows="8" id="chat-input-multi" \
  @      placeholder="Type message here" class="hidden"></textarea>
  @     <input type="submit" value="Send" id="chat-message-submit">
  @     <button id="chat-scroll-bottom">&darr;</button>
  @     <button id="chat-scroll-top">&uarr;</button>
  @     <span id="chat-settings-button" class="settings-icon" \
  @       aria-label="Settings..." aria-haspopup="true" ></span>
  @   </div>
  @   <div id='chat-input-file-area'>
  @     <div class='file-selection-wrapper'>
  @       <div class='help-buttonlet'>
  @        Select a file to upload, drag/drop a file into this spot,
  @        or paste an image from the clipboard if supported by
  @        your environment.
Changes to src/chat.js.
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
          the scroll until the image is loaded, at which point it will
          scroll to either the newest message, if one is set or to
          eMsg (the liklihood is good, at least on initial page load,
          that the the image won't be loaded until other messages have
          been injected). */
      scheduleScrollOfMsg: function(eMsg){
        if(1===+eMsg.dataset.hasImage){
          console.debug("Delaying scroll for IMG.");
          eMsg.querySelector('img').addEventListener(
            'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView()
          );
        }else{
          eMsg.scrollIntoView();
        }
        return this;
      },
      /* Injects element e as a new row in the chat, at the top of the
         list if atEnd is falsy, else at the end of the list, before
         the load-history widget. */
      injectMessageElem: function f(e, atEnd){







<

|


|







181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199
          the scroll until the image is loaded, at which point it will
          scroll to either the newest message, if one is set or to
          eMsg (the liklihood is good, at least on initial page load,
          that the the image won't be loaded until other messages have
          been injected). */
      scheduleScrollOfMsg: function(eMsg){
        if(1===+eMsg.dataset.hasImage){

          eMsg.querySelector('img').addEventListener(
            'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
          );
        }else{
          eMsg.scrollIntoView(false);
        }
        return this;
      },
      /* Injects element e as a new row in the chat, at the top of the
         list if atEnd is falsy, else at the end of the list, before
         the load-history widget. */
      injectMessageElem: function f(e, atEnd){
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
             For such cases we have to delay the scroll until the
             image loads (and we hope it does so before another
             message arrives).
          */
          if(1===+e.dataset.hasImage){
            e.querySelector('img').addEventListener('load',()=>e.scrollIntoView());
          }else if(!prevMessage || (prevMessage && isInViewport(prevMessage))){
            e.scrollIntoView();
          }
        }
      },
      /** Returns true if chat-only mode is enabled. */
      isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
      /**
         Enters (if passed a truthy value or no arguments) or leaves







|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
             For such cases we have to delay the scroll until the
             image loads (and we hope it does so before another
             message arrives).
          */
          if(1===+e.dataset.hasImage){
            e.querySelector('img').addEventListener('load',()=>e.scrollIntoView());
          }else if(!prevMessage || (prevMessage && isInViewport(prevMessage))){
            e.scrollIntoView(false);
          }
        }
      },
      /** Returns true if chat-only mode is enabled. */
      isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'),
      /**
         Enters (if passed a truthy value or no arguments) or leaves
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
       show their current values.
    */
    settingsPopup.options.refresh = function(){
      D.clearElement(this.e);
      settingsOps.forEach(function(op){
        const line = D.addClass(D.span(), 'menu-entry');
        const btn = D.append(D.addClass(D.span(), 'button'), op.label);
        D.attr(btn, 'role', 'button');
        const callback = function(ev){
          settingsPopup.hide();
          op.callback.call(this,ev);
        };
        D.append(line, btn);
        if(op.hasOwnProperty('boolValue')){
          const check = D.checkbox(1, op.boolValue());

          D.append(line, check);
          check.addEventListener('click', callback);
        }
        D.append(settingsPopup.e, line);
        btn.addEventListener('click', callback);
      });
    };







<






|
>







801
802
803
804
805
806
807

808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
       show their current values.
    */
    settingsPopup.options.refresh = function(){
      D.clearElement(this.e);
      settingsOps.forEach(function(op){
        const line = D.addClass(D.span(), 'menu-entry');
        const btn = D.append(D.addClass(D.span(), 'button'), op.label);

        const callback = function(ev){
          settingsPopup.hide();
          op.callback.call(this,ev);
        };
        D.append(line, btn);
        if(op.hasOwnProperty('boolValue')){
          const check = D.attr(D.checkbox(1, op.boolValue()),
                                          'aria-label', op.label);
          D.append(line, check);
          check.addEventListener('click', callback);
        }
        D.append(settingsPopup.e, line);
        btn.addEventListener('click', callback);
      });
    };