Fossil SCM
Disabled position:sticky on the input area when in bottom-up chat mode pending resolution of a scrolling misbehaviour for messages with IMG tags. IMG.src is loaded async, so the scrolling is actually working but loading of the IMG.src is then pushing the message back down behind/under the input field.
Commit
8e12b61b50bf90dd70aa37a6fb1129af925cb90b57598530f79c02623ed20d25
Parent
dfc20f429713e4c…
2 files changed
+32
-7
+6
-1
+32
-7
| --- src/chat.js | ||
| +++ src/chat.js | ||
| @@ -15,10 +15,11 @@ | ||
| 15 | 15 | e:{/*map of certain DOM elements.*/ |
| 16 | 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | 17 | pageTitle: E1('head title'), |
| 18 | 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | 19 | inputWrapper: E1("#chat-input-area"), |
| 20 | + fileSelectWrapper: E1('#chat-input-file-area'), | |
| 20 | 21 | messagesWrapper: E1('#chat-messages-wrapper'), |
| 21 | 22 | inputForm: E1('#chat-form'), |
| 22 | 23 | btnSubmit: E1('#chat-message-submit'), |
| 23 | 24 | inputSingle: E1('#chat-input-single'), |
| 24 | 25 | inputMulti: E1('#chat-input-multi'), |
| @@ -115,20 +116,41 @@ | ||
| 115 | 116 | injectMessageElem: function f(e, atEnd){ |
| 116 | 117 | const mip = atEnd ? this.e.loadToolbar : this.e.messageInjectPoint; |
| 117 | 118 | if(atEnd){ |
| 118 | 119 | mip.parentNode.insertBefore(e, mip); |
| 119 | 120 | }else{ |
| 120 | - if(mip.nextSibling) mip.parentNode.insertBefore(e, mip.nextSibling); | |
| 121 | - else mip.parentNode.appendChild(e); | |
| 122 | - if(this.isUiFlipped()){ | |
| 121 | + const self = this; | |
| 122 | + if(false && this.isUiFlipped()){ | |
| 123 | 123 | /* When UI is flipped, new messages start out under the |
| 124 | 124 | text input area because of its position:sticky |
| 125 | 125 | style. We have to scroll them up. When the page footer |
| 126 | 126 | is not hidden but is not on-screen, this causes a |
| 127 | 127 | slight amount of UI jarring as the footer is *also* |
| 128 | - scrolled into view (for whatever reason). */ | |
| 129 | - setTimeout(()=>e.scrollIntoView(), 0); | |
| 128 | + scrolled into view (for whatever reason). | |
| 129 | + | |
| 130 | + The remaining problem here is messages with IMG tags. | |
| 131 | + At this point in the process their IMG.src has not yet | |
| 132 | + been loaded - that's async. We scroll the message into | |
| 133 | + view, but then the downstream loading of IMG.src pushes | |
| 134 | + the message content back down, sliding the message | |
| 135 | + behind the input field. This can be verified by delaying the | |
| 136 | + message scroll by a second or so to give the image time | |
| 137 | + to load (from a local server instance). | |
| 138 | + */ | |
| 139 | + D.addClass(self.e.inputWrapper,'unsticky'); | |
| 140 | + } | |
| 141 | + if(mip.nextSibling) mip.parentNode.insertBefore(e, mip.nextSibling); | |
| 142 | + else mip.parentNode.appendChild(e); | |
| 143 | + if(this.isUiFlipped()){ | |
| 144 | + //e.scrollIntoView(); | |
| 145 | + setTimeout(function(){ | |
| 146 | + //self.e.inputWrapper.scrollIntoView(); | |
| 147 | + //self.e.fileSelectWrapper.scrollIntoView(); | |
| 148 | + //e.scrollIntoView(); | |
| 149 | + //D.removeClass(self.e.inputWrapper,'unsticky'); | |
| 150 | + self.e.inputWrapper.scrollIntoView(); | |
| 151 | + },0); | |
| 130 | 152 | } |
| 131 | 153 | } |
| 132 | 154 | }, |
| 133 | 155 | /** Returns true if chat-only mode is enabled. */ |
| 134 | 156 | isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'), |
| @@ -447,11 +469,11 @@ | ||
| 447 | 469 | } |
| 448 | 470 | }, false); |
| 449 | 471 | /* Add help button for drag/drop/paste zone */ |
| 450 | 472 | Chat.e.inputFile.parentNode.insertBefore( |
| 451 | 473 | F.helpButtonlets.create( |
| 452 | - document.querySelector('#chat-input-file-area .help-buttonlet') | |
| 474 | + Chat.e.fileSelectWrapper.querySelector('.help-buttonlet') | |
| 453 | 475 | ), Chat.e.inputFile |
| 454 | 476 | ); |
| 455 | 477 | //////////////////////////////////////////////////////////// |
| 456 | 478 | // File drag/drop visual notification. |
| 457 | 479 | const dropHighlight = Chat.e.inputFile /* target zone */; |
| @@ -820,14 +842,17 @@ | ||
| 820 | 842 | .catch(e=>console.error(e)) |
| 821 | 843 | /* ^^^ we don't use Chat.reportError(e) here b/c the polling |
| 822 | 844 | fails exepectedly when it times out, but is then immediately |
| 823 | 845 | resumed, and reportError() produces a loud error message. */ |
| 824 | 846 | .finally(function(x){ |
| 825 | - if(isFirstCall) Chat.ajaxEnd(); | |
| 847 | + if(isFirstCall){ | |
| 848 | + Chat.ajaxEnd(); | |
| 849 | + Chat.e.inputWrapper.scrollIntoView(); | |
| 850 | + } | |
| 826 | 851 | poll.running=false; |
| 827 | 852 | }); |
| 828 | 853 | } |
| 829 | 854 | poll.running = false; |
| 830 | 855 | poll(true); |
| 831 | 856 | setInterval(poll, 1000); |
| 832 | 857 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 833 | 858 | })(); |
| 834 | 859 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -15,10 +15,11 @@ | |
| 15 | e:{/*map of certain DOM elements.*/ |
| 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | pageTitle: E1('head title'), |
| 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | inputWrapper: E1("#chat-input-area"), |
| 20 | messagesWrapper: E1('#chat-messages-wrapper'), |
| 21 | inputForm: E1('#chat-form'), |
| 22 | btnSubmit: E1('#chat-message-submit'), |
| 23 | inputSingle: E1('#chat-input-single'), |
| 24 | inputMulti: E1('#chat-input-multi'), |
| @@ -115,20 +116,41 @@ | |
| 115 | injectMessageElem: function f(e, atEnd){ |
| 116 | const mip = atEnd ? this.e.loadToolbar : this.e.messageInjectPoint; |
| 117 | if(atEnd){ |
| 118 | mip.parentNode.insertBefore(e, mip); |
| 119 | }else{ |
| 120 | if(mip.nextSibling) mip.parentNode.insertBefore(e, mip.nextSibling); |
| 121 | else mip.parentNode.appendChild(e); |
| 122 | if(this.isUiFlipped()){ |
| 123 | /* When UI is flipped, new messages start out under the |
| 124 | text input area because of its position:sticky |
| 125 | style. We have to scroll them up. When the page footer |
| 126 | is not hidden but is not on-screen, this causes a |
| 127 | slight amount of UI jarring as the footer is *also* |
| 128 | scrolled into view (for whatever reason). */ |
| 129 | setTimeout(()=>e.scrollIntoView(), 0); |
| 130 | } |
| 131 | } |
| 132 | }, |
| 133 | /** Returns true if chat-only mode is enabled. */ |
| 134 | isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'), |
| @@ -447,11 +469,11 @@ | |
| 447 | } |
| 448 | }, false); |
| 449 | /* Add help button for drag/drop/paste zone */ |
| 450 | Chat.e.inputFile.parentNode.insertBefore( |
| 451 | F.helpButtonlets.create( |
| 452 | document.querySelector('#chat-input-file-area .help-buttonlet') |
| 453 | ), Chat.e.inputFile |
| 454 | ); |
| 455 | //////////////////////////////////////////////////////////// |
| 456 | // File drag/drop visual notification. |
| 457 | const dropHighlight = Chat.e.inputFile /* target zone */; |
| @@ -820,14 +842,17 @@ | |
| 820 | .catch(e=>console.error(e)) |
| 821 | /* ^^^ we don't use Chat.reportError(e) here b/c the polling |
| 822 | fails exepectedly when it times out, but is then immediately |
| 823 | resumed, and reportError() produces a loud error message. */ |
| 824 | .finally(function(x){ |
| 825 | if(isFirstCall) Chat.ajaxEnd(); |
| 826 | poll.running=false; |
| 827 | }); |
| 828 | } |
| 829 | poll.running = false; |
| 830 | poll(true); |
| 831 | setInterval(poll, 1000); |
| 832 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 833 | })(); |
| 834 |
| --- src/chat.js | |
| +++ src/chat.js | |
| @@ -15,10 +15,11 @@ | |
| 15 | e:{/*map of certain DOM elements.*/ |
| 16 | messageInjectPoint: E1('#message-inject-point'), |
| 17 | pageTitle: E1('head title'), |
| 18 | loadToolbar: undefined /* the load-posts toolbar (dynamically created) */, |
| 19 | inputWrapper: E1("#chat-input-area"), |
| 20 | fileSelectWrapper: E1('#chat-input-file-area'), |
| 21 | messagesWrapper: E1('#chat-messages-wrapper'), |
| 22 | inputForm: E1('#chat-form'), |
| 23 | btnSubmit: E1('#chat-message-submit'), |
| 24 | inputSingle: E1('#chat-input-single'), |
| 25 | inputMulti: E1('#chat-input-multi'), |
| @@ -115,20 +116,41 @@ | |
| 116 | injectMessageElem: function f(e, atEnd){ |
| 117 | const mip = atEnd ? this.e.loadToolbar : this.e.messageInjectPoint; |
| 118 | if(atEnd){ |
| 119 | mip.parentNode.insertBefore(e, mip); |
| 120 | }else{ |
| 121 | const self = this; |
| 122 | if(false && this.isUiFlipped()){ |
| 123 | /* When UI is flipped, new messages start out under the |
| 124 | text input area because of its position:sticky |
| 125 | style. We have to scroll them up. When the page footer |
| 126 | is not hidden but is not on-screen, this causes a |
| 127 | slight amount of UI jarring as the footer is *also* |
| 128 | scrolled into view (for whatever reason). |
| 129 | |
| 130 | The remaining problem here is messages with IMG tags. |
| 131 | At this point in the process their IMG.src has not yet |
| 132 | been loaded - that's async. We scroll the message into |
| 133 | view, but then the downstream loading of IMG.src pushes |
| 134 | the message content back down, sliding the message |
| 135 | behind the input field. This can be verified by delaying the |
| 136 | message scroll by a second or so to give the image time |
| 137 | to load (from a local server instance). |
| 138 | */ |
| 139 | D.addClass(self.e.inputWrapper,'unsticky'); |
| 140 | } |
| 141 | if(mip.nextSibling) mip.parentNode.insertBefore(e, mip.nextSibling); |
| 142 | else mip.parentNode.appendChild(e); |
| 143 | if(this.isUiFlipped()){ |
| 144 | //e.scrollIntoView(); |
| 145 | setTimeout(function(){ |
| 146 | //self.e.inputWrapper.scrollIntoView(); |
| 147 | //self.e.fileSelectWrapper.scrollIntoView(); |
| 148 | //e.scrollIntoView(); |
| 149 | //D.removeClass(self.e.inputWrapper,'unsticky'); |
| 150 | self.e.inputWrapper.scrollIntoView(); |
| 151 | },0); |
| 152 | } |
| 153 | } |
| 154 | }, |
| 155 | /** Returns true if chat-only mode is enabled. */ |
| 156 | isChatOnlyMode: ()=>document.body.classList.contains('chat-only-mode'), |
| @@ -447,11 +469,11 @@ | |
| 469 | } |
| 470 | }, false); |
| 471 | /* Add help button for drag/drop/paste zone */ |
| 472 | Chat.e.inputFile.parentNode.insertBefore( |
| 473 | F.helpButtonlets.create( |
| 474 | Chat.e.fileSelectWrapper.querySelector('.help-buttonlet') |
| 475 | ), Chat.e.inputFile |
| 476 | ); |
| 477 | //////////////////////////////////////////////////////////// |
| 478 | // File drag/drop visual notification. |
| 479 | const dropHighlight = Chat.e.inputFile /* target zone */; |
| @@ -820,14 +842,17 @@ | |
| 842 | .catch(e=>console.error(e)) |
| 843 | /* ^^^ we don't use Chat.reportError(e) here b/c the polling |
| 844 | fails exepectedly when it times out, but is then immediately |
| 845 | resumed, and reportError() produces a loud error message. */ |
| 846 | .finally(function(x){ |
| 847 | if(isFirstCall){ |
| 848 | Chat.ajaxEnd(); |
| 849 | Chat.e.inputWrapper.scrollIntoView(); |
| 850 | } |
| 851 | poll.running=false; |
| 852 | }); |
| 853 | } |
| 854 | poll.running = false; |
| 855 | poll(true); |
| 856 | setInterval(poll, 1000); |
| 857 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 858 | })(); |
| 859 |
+6
-1
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -1672,12 +1672,17 @@ | ||
| 1672 | 1672 | body.chat.chat-bottom-up #chat-input-area { |
| 1673 | 1673 | border-bottom: none; |
| 1674 | 1674 | border-top: 1px solid black; |
| 1675 | 1675 | margin-bottom: 0; |
| 1676 | 1676 | margin-top: 0.5em; |
| 1677 | - position: sticky; | |
| 1677 | + position: initial /*sticky currently disabled due to scrolling-related issues*/; | |
| 1678 | 1678 | bottom: 0; |
| 1679 | +} | |
| 1680 | +/* An internal hack to try to help resolve a message-scrolling quirk | |
| 1681 | + when #chat-input-area is sticky on the bottom of the screen. */ | |
| 1682 | +body.chat.chat-bottom-up #chat-input-area.unsticky { | |
| 1683 | + position: initial; | |
| 1679 | 1684 | } |
| 1680 | 1685 | /* Widget holding the chat message input field, send button, and |
| 1681 | 1686 | settings button. */ |
| 1682 | 1687 | body.chat #chat-input-line { |
| 1683 | 1688 | display: flex; |
| 1684 | 1689 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1672,12 +1672,17 @@ | |
| 1672 | body.chat.chat-bottom-up #chat-input-area { |
| 1673 | border-bottom: none; |
| 1674 | border-top: 1px solid black; |
| 1675 | margin-bottom: 0; |
| 1676 | margin-top: 0.5em; |
| 1677 | position: sticky; |
| 1678 | bottom: 0; |
| 1679 | } |
| 1680 | /* Widget holding the chat message input field, send button, and |
| 1681 | settings button. */ |
| 1682 | body.chat #chat-input-line { |
| 1683 | display: flex; |
| 1684 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1672,12 +1672,17 @@ | |
| 1672 | body.chat.chat-bottom-up #chat-input-area { |
| 1673 | border-bottom: none; |
| 1674 | border-top: 1px solid black; |
| 1675 | margin-bottom: 0; |
| 1676 | margin-top: 0.5em; |
| 1677 | position: initial /*sticky currently disabled due to scrolling-related issues*/; |
| 1678 | bottom: 0; |
| 1679 | } |
| 1680 | /* An internal hack to try to help resolve a message-scrolling quirk |
| 1681 | when #chat-input-area is sticky on the bottom of the screen. */ |
| 1682 | body.chat.chat-bottom-up #chat-input-area.unsticky { |
| 1683 | position: initial; |
| 1684 | } |
| 1685 | /* Widget holding the chat message input field, send button, and |
| 1686 | settings button. */ |
| 1687 | body.chat #chat-input-line { |
| 1688 | display: flex; |
| 1689 |