Fossil SCM
/chat: reuse the window-resize listener to cap the max-size of the input field to approx. half the height of the screen, per user feedback.
Commit
84d4a0e8517292768383df51ea64e5ca27418073b52458a7e9075762283c776f
Parent
1fc2a2657720530…
1 file changed
+29
-20
+29
-20
| --- src/fossil.page.chat.js | ||
| +++ src/fossil.page.chat.js | ||
| @@ -63,62 +63,70 @@ | ||
| 63 | 63 | /* This can inadvertently influence our flexbox layouts, so move |
| 64 | 64 | it out of the way. */ |
| 65 | 65 | D.append(document.body,dbg); |
| 66 | 66 | } |
| 67 | 67 | })(); |
| 68 | - const ForceResizeKludge = 0 ? function(){} : (function f(){ | |
| 68 | + const ForceResizeKludge = (function(){ | |
| 69 | 69 | /* Workaround for Safari mayhem regarding use of vh CSS units.... |
| 70 | 70 | We tried to use vh units to set the content area size for the |
| 71 | 71 | chat layout, but Safari chokes on that, so we calculate that |
| 72 | 72 | height here: 85% when in "normal" mode and 95% in chat-only |
| 73 | 73 | mode. Larger than ~95% is too big for Firefox on Android, |
| 74 | - causing the input area to move off-screen. */ | |
| 75 | - if(!f.elemsToCount){ | |
| 76 | - f.elemsToCount = [ | |
| 77 | - document.querySelector('body > div.header'), | |
| 78 | - document.querySelector('body > div.mainmenu'), | |
| 79 | - document.querySelector('body > #hbdrop'), | |
| 80 | - document.querySelector('body > div.footer') | |
| 81 | - ]; | |
| 82 | - f.contentArea = E1('div.content'); | |
| 83 | - } | |
| 74 | + causing the input area to move off-screen. | |
| 75 | + | |
| 76 | + While we're here, we also use this to cap the max-height | |
| 77 | + of the input field so that pasting huge text does not scroll | |
| 78 | + the upper area of the input widget off-screen. */ | |
| 79 | + const elemsToCount = [ | |
| 80 | + document.querySelector('body > div.header'), | |
| 81 | + document.querySelector('body > div.mainmenu'), | |
| 82 | + document.querySelector('body > #hbdrop'), | |
| 83 | + document.querySelector('body > div.footer') | |
| 84 | + ]; | |
| 85 | + const contentArea = E1('div.content'); | |
| 84 | 86 | const bcl = document.body.classList; |
| 85 | - const resized = function(){ | |
| 87 | + const resized = function f(){ | |
| 88 | + if(f.$disabled) return; | |
| 86 | 89 | const wh = window.innerHeight, |
| 87 | 90 | com = bcl.contains('chat-only-mode'); |
| 88 | 91 | var ht; |
| 89 | 92 | var extra = 0; |
| 90 | 93 | if(com){ |
| 91 | 94 | ht = wh; |
| 92 | 95 | }else{ |
| 93 | - f.elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false); | |
| 96 | + elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false); | |
| 94 | 97 | ht = wh - extra; |
| 95 | 98 | } |
| 96 | - f.contentArea.style.height = | |
| 97 | - f.contentArea.style.maxHeight = [ | |
| 99 | + f.chat.e.inputField.style.maxHeight = (ht/2)+"px"; | |
| 100 | + /* ^^^^ this is a middle ground between having no size cap | |
| 101 | + on the input field and having a fixed arbitrary cap. */; | |
| 102 | + contentArea.style.height = | |
| 103 | + contentArea.style.maxHeight = [ | |
| 98 | 104 | "calc(", (ht>=100 ? ht : 100), "px", |
| 99 | 105 | " - 0.75em"/*fudge value*/,")" |
| 100 | 106 | /* ^^^^ hypothetically not needed, but both Chrome/FF on |
| 101 | 107 | Linux will force scrollbars on the body if this value is |
| 102 | 108 | too small (<0.75em in my tests). */ |
| 103 | 109 | ].join(''); |
| 104 | 110 | if(false){ |
| 105 | 111 | console.debug("resized.",wh, extra, ht, |
| 106 | - window.getComputedStyle(f.contentArea).maxHeight, | |
| 107 | - f.contentArea); | |
| 112 | + window.getComputedStyle(contentArea).maxHeight, | |
| 113 | + contentArea); | |
| 114 | + console.debug("Set input max height to: ", | |
| 115 | + f.chat.e.inputField.style.maxHeight); | |
| 108 | 116 | } |
| 109 | 117 | }; |
| 110 | 118 | var doit; |
| 111 | 119 | window.addEventListener('resize',function(ev){ |
| 112 | 120 | clearTimeout(doit); |
| 113 | 121 | doit = setTimeout(resized, 100); |
| 114 | 122 | }, false); |
| 115 | - resized(); | |
| 116 | 123 | return resized; |
| 117 | 124 | })(); |
| 125 | + ForceResizeKludge.$disabled = true/*gets deleted when setup is finished*/; | |
| 118 | 126 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 119 | - const Chat = (function(){ | |
| 127 | + const Chat = ForceResizeKludge.chat = (function(){ | |
| 120 | 128 | const cs = { |
| 121 | 129 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 122 | 130 | error messages may be sent to the console. */, |
| 123 | 131 | e:{/*map of certain DOM elements.*/ |
| 124 | 132 | messageInjectPoint: E1('#message-inject-point'), |
| @@ -1805,9 +1813,10 @@ | ||
| 1805 | 1813 | const flip = (ev)=>Chat.animate(ev.target,'anim-flip-h'); |
| 1806 | 1814 | document.querySelectorAll('#chat-buttons-wrapper .cbutton').forEach(function(e){ |
| 1807 | 1815 | e.addEventListener('click',flip, false); |
| 1808 | 1816 | }); |
| 1809 | 1817 | } |
| 1818 | + delete ForceResizeKludge.$disabled; | |
| 1819 | + ForceResizeKludge(); | |
| 1810 | 1820 | setTimeout( ()=>Chat.inputFocus(), 0 ); |
| 1811 | - Chat.animate.$disabled = false; | |
| 1812 | 1821 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 1813 | 1822 | }); |
| 1814 | 1823 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -63,62 +63,70 @@ | |
| 63 | /* This can inadvertently influence our flexbox layouts, so move |
| 64 | it out of the way. */ |
| 65 | D.append(document.body,dbg); |
| 66 | } |
| 67 | })(); |
| 68 | const ForceResizeKludge = 0 ? function(){} : (function f(){ |
| 69 | /* Workaround for Safari mayhem regarding use of vh CSS units.... |
| 70 | We tried to use vh units to set the content area size for the |
| 71 | chat layout, but Safari chokes on that, so we calculate that |
| 72 | height here: 85% when in "normal" mode and 95% in chat-only |
| 73 | mode. Larger than ~95% is too big for Firefox on Android, |
| 74 | causing the input area to move off-screen. */ |
| 75 | if(!f.elemsToCount){ |
| 76 | f.elemsToCount = [ |
| 77 | document.querySelector('body > div.header'), |
| 78 | document.querySelector('body > div.mainmenu'), |
| 79 | document.querySelector('body > #hbdrop'), |
| 80 | document.querySelector('body > div.footer') |
| 81 | ]; |
| 82 | f.contentArea = E1('div.content'); |
| 83 | } |
| 84 | const bcl = document.body.classList; |
| 85 | const resized = function(){ |
| 86 | const wh = window.innerHeight, |
| 87 | com = bcl.contains('chat-only-mode'); |
| 88 | var ht; |
| 89 | var extra = 0; |
| 90 | if(com){ |
| 91 | ht = wh; |
| 92 | }else{ |
| 93 | f.elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false); |
| 94 | ht = wh - extra; |
| 95 | } |
| 96 | f.contentArea.style.height = |
| 97 | f.contentArea.style.maxHeight = [ |
| 98 | "calc(", (ht>=100 ? ht : 100), "px", |
| 99 | " - 0.75em"/*fudge value*/,")" |
| 100 | /* ^^^^ hypothetically not needed, but both Chrome/FF on |
| 101 | Linux will force scrollbars on the body if this value is |
| 102 | too small (<0.75em in my tests). */ |
| 103 | ].join(''); |
| 104 | if(false){ |
| 105 | console.debug("resized.",wh, extra, ht, |
| 106 | window.getComputedStyle(f.contentArea).maxHeight, |
| 107 | f.contentArea); |
| 108 | } |
| 109 | }; |
| 110 | var doit; |
| 111 | window.addEventListener('resize',function(ev){ |
| 112 | clearTimeout(doit); |
| 113 | doit = setTimeout(resized, 100); |
| 114 | }, false); |
| 115 | resized(); |
| 116 | return resized; |
| 117 | })(); |
| 118 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 119 | const Chat = (function(){ |
| 120 | const cs = { |
| 121 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 122 | error messages may be sent to the console. */, |
| 123 | e:{/*map of certain DOM elements.*/ |
| 124 | messageInjectPoint: E1('#message-inject-point'), |
| @@ -1805,9 +1813,10 @@ | |
| 1805 | const flip = (ev)=>Chat.animate(ev.target,'anim-flip-h'); |
| 1806 | document.querySelectorAll('#chat-buttons-wrapper .cbutton').forEach(function(e){ |
| 1807 | e.addEventListener('click',flip, false); |
| 1808 | }); |
| 1809 | } |
| 1810 | setTimeout( ()=>Chat.inputFocus(), 0 ); |
| 1811 | Chat.animate.$disabled = false; |
| 1812 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 1813 | }); |
| 1814 |
| --- src/fossil.page.chat.js | |
| +++ src/fossil.page.chat.js | |
| @@ -63,62 +63,70 @@ | |
| 63 | /* This can inadvertently influence our flexbox layouts, so move |
| 64 | it out of the way. */ |
| 65 | D.append(document.body,dbg); |
| 66 | } |
| 67 | })(); |
| 68 | const ForceResizeKludge = (function(){ |
| 69 | /* Workaround for Safari mayhem regarding use of vh CSS units.... |
| 70 | We tried to use vh units to set the content area size for the |
| 71 | chat layout, but Safari chokes on that, so we calculate that |
| 72 | height here: 85% when in "normal" mode and 95% in chat-only |
| 73 | mode. Larger than ~95% is too big for Firefox on Android, |
| 74 | causing the input area to move off-screen. |
| 75 | |
| 76 | While we're here, we also use this to cap the max-height |
| 77 | of the input field so that pasting huge text does not scroll |
| 78 | the upper area of the input widget off-screen. */ |
| 79 | const elemsToCount = [ |
| 80 | document.querySelector('body > div.header'), |
| 81 | document.querySelector('body > div.mainmenu'), |
| 82 | document.querySelector('body > #hbdrop'), |
| 83 | document.querySelector('body > div.footer') |
| 84 | ]; |
| 85 | const contentArea = E1('div.content'); |
| 86 | const bcl = document.body.classList; |
| 87 | const resized = function f(){ |
| 88 | if(f.$disabled) return; |
| 89 | const wh = window.innerHeight, |
| 90 | com = bcl.contains('chat-only-mode'); |
| 91 | var ht; |
| 92 | var extra = 0; |
| 93 | if(com){ |
| 94 | ht = wh; |
| 95 | }else{ |
| 96 | elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false); |
| 97 | ht = wh - extra; |
| 98 | } |
| 99 | f.chat.e.inputField.style.maxHeight = (ht/2)+"px"; |
| 100 | /* ^^^^ this is a middle ground between having no size cap |
| 101 | on the input field and having a fixed arbitrary cap. */; |
| 102 | contentArea.style.height = |
| 103 | contentArea.style.maxHeight = [ |
| 104 | "calc(", (ht>=100 ? ht : 100), "px", |
| 105 | " - 0.75em"/*fudge value*/,")" |
| 106 | /* ^^^^ hypothetically not needed, but both Chrome/FF on |
| 107 | Linux will force scrollbars on the body if this value is |
| 108 | too small (<0.75em in my tests). */ |
| 109 | ].join(''); |
| 110 | if(false){ |
| 111 | console.debug("resized.",wh, extra, ht, |
| 112 | window.getComputedStyle(contentArea).maxHeight, |
| 113 | contentArea); |
| 114 | console.debug("Set input max height to: ", |
| 115 | f.chat.e.inputField.style.maxHeight); |
| 116 | } |
| 117 | }; |
| 118 | var doit; |
| 119 | window.addEventListener('resize',function(ev){ |
| 120 | clearTimeout(doit); |
| 121 | doit = setTimeout(resized, 100); |
| 122 | }, false); |
| 123 | return resized; |
| 124 | })(); |
| 125 | ForceResizeKludge.$disabled = true/*gets deleted when setup is finished*/; |
| 126 | fossil.FRK = ForceResizeKludge/*for debugging*/; |
| 127 | const Chat = ForceResizeKludge.chat = (function(){ |
| 128 | const cs = { |
| 129 | verboseErrors: false /* if true then certain, mostly extraneous, |
| 130 | error messages may be sent to the console. */, |
| 131 | e:{/*map of certain DOM elements.*/ |
| 132 | messageInjectPoint: E1('#message-inject-point'), |
| @@ -1805,9 +1813,10 @@ | |
| 1813 | const flip = (ev)=>Chat.animate(ev.target,'anim-flip-h'); |
| 1814 | document.querySelectorAll('#chat-buttons-wrapper .cbutton').forEach(function(e){ |
| 1815 | e.addEventListener('click',flip, false); |
| 1816 | }); |
| 1817 | } |
| 1818 | delete ForceResizeKludge.$disabled; |
| 1819 | ForceResizeKludge(); |
| 1820 | setTimeout( ()=>Chat.inputFocus(), 0 ); |
| 1821 | F.page.chat = Chat/* enables testing the APIs via the dev tools */; |
| 1822 | }); |
| 1823 |