I\'m trying to mimic other mobile chatting apps where when you select the send-message
textbox and it opens the virtual keyboard, the bottom-most message is still i
I have finally found a solution that actually works. Although it may not be ideal, it actually works in all cases. Here is the code:
bottomScroller(document.querySelector(".messages"));
bottomScroller = scroller => {
let pxFromBottom = 0;
let calcPxFromBottom = () => pxFromBottom = scroller.scrollHeight - (scroller.scrollTop + scroller.clientHeight);
setInterval(calcPxFromBottom, 500);
window.addEventListener('resize', () => {
scroller.scrollTop = scroller.scrollHeight - pxFromBottom - scroller.clientHeight;
});
}
Some epiphanies I had along the way:
When closing the virtual keyboard, a scroll
event occurs instantly before the resize
event. This seems to only happen when closing the keyboard, not opening it. This is the reason you cannot use the scroll
event to set pxFromBottom
, because if you are near the bottom it will set itself to 0 in the scroll
event right before the resize
event, messing up the calculation.
Another reason why all the solutions had difficulty near the bottom of the messages div is a bit tricky to understand. For example, in my resize solution I just add or subtract 250 (mobile keyboard height) to scrollTop
when opening or closing the virtual keyboard. This works perfectly except near the bottom. Why? Because let's say you are 50 pixels from the bottom and close the keyboard. It will subtract 250 from scrollTop
(the keyboard height), but it should only subtract 50! So it will always reset to the wrong fixed position when closing the keyboard near the bottom.
I also believe you cannot use onFocus
and onBlur
events for this solution, because those only occur when initially selecting the textbox to open the keyboard. You are perfectly able to open and close the mobile keyboard without activating these events, and as such, they are not able to used here.
I believe the above points are important to developing a solution, because they are non-obvious at first, but prevent a robust solution from developing.
I don't like this solution (interval is a bit inefficient and prone to race conditions), but I cannot find anything better that always works.