Highlight chat item when generating permalink
related to !1367 (merged)
UX improvement - right now when user clicks on chat item timestamp to generate permalink, the only feedback they get is change of URL in address bar. It would be nice to highlight the chat item to show them that something happened.
Current behavior
Desired
These are notes for suggested implementation
- if we trigger
navigate
in router-app,router-chat
recognizes that new location contains permalink and triggerschatCollectionView:permalinkHighlight
which scrolls to permalinked chat item and highlights it.
There are two situations when this happens:
- opening URL in browser - here the scroll is acceptable because user hasn't started interacting with the site yet
- navigation happened as a consequence of generating permalink by clicking on chat item timestamp - here the scroll is not desireable
It would be great if the scroll only occurred when the chat item is outside of the viewport
- suggested change to the
public/js/utils/rollers
/*
* Checks whether the argument is positioned in the viewport
* taken from https://stackoverflow.com/a/7557433/606571
* returns true if it is
*/
isElementInViewport: function(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
},
/*
* Scroll to given element with following options:
* - no options - positions element to the top of the page
* - center: true - positions element to the center of the viewport
* - skipIfVisible: true - doesn't scroll at all if the element is in viewport
*/
scrollToElement: function(element, options = {}) {
var target = this._target;
var scrollTop;
if (options.skipIfVisible && this.isElementInViewport(element)) {
return;
}
if (options.centre) {
// Centre the element in the viewport
var elementHeight = element.offsetHeight;
var viewportHeight = target.clientHeight;
if (elementHeight < viewportHeight) {
scrollTop = Math.floor(element.offsetTop + elementHeight / 2 - viewportHeight / 2);
}
}
if (!scrollTop) {
scrollTop = element.offsetTop - TOP_OFFSET;
}
if (scrollTop < 0) scrollTop = 0;
this.scroll(scrollTop);
this.stable(element);
},
this new functionality then can be used in chatCollectionView.js
:
scrollToChat: function(chat) {
var view = this.children.findByModel(chat);
if (!view) return;
this.rollers.scrollToElement(view.el, { centre: true, skipIfVisible: true });
return true;
},
This code works out of the box for logged in user chat but not for archive and not logged in user thanks to inconsistent event handling.
router-app.js
handles navigation to permalink like this this mechanism would have to be copied/extracted to router-nli-app.js
(router for not logged in users) which doesn't contain necessary code and dependencies (e.g. urlParser
) yet.
Then there is a permalink.navigate
event handling in router-chat.js
which needs to be copied to router-nli-chat.js
.
Ideally this same chain would be replicated not only for router-nli-chat.js
but for router-archive-chat.js
as well.