mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 13:03:29 +00:00
buddy_tooltips: Destroy tooltips if reference is not visible.
We destroy the tooltips for which `reference` was either removed from DOM or is hidden. We only need to do this for tooltips contained in simplebar containers for which tooltips can overflow the boundary of the simplebar container. There are 4 approaches we could have done this: 1. Asked tippy.js maintainers to do this for us. In https://github.com/atomiks/tippyjs/issues/938 the maintainer said that it is the responsibility of the user to do so. 2. Tracked whenever we update the DOM for such elements and hide tooltips when we were hiding the `reference` elements. This had various problems like it is hard trigger events when certain elements have been removed from DOM when `html()` method is used to render new content. 3. Run an `optimized` periodic job to destroy tooltips when `reference` elements are hidden. This isn't a good method to do this since it sucks power and adds latency. 4. Use a `MutationObserver` on the parent element and watch for changes. This methods seems to work well with no bad side effects. We use this approach.
This commit is contained in:
@@ -529,6 +529,7 @@ export function initialize() {
|
||||
|
||||
function do_render_buddy_list_tooltip(elem, title_data) {
|
||||
let placement = "left";
|
||||
let observer;
|
||||
if (window.innerWidth < media_breakpoints_num.md) {
|
||||
// On small devices display tooltips based on available space.
|
||||
// This will default to "bottom" placement for this tooltip.
|
||||
@@ -546,6 +547,32 @@ export function initialize() {
|
||||
showOnCreate: true,
|
||||
onHidden: (instance) => {
|
||||
instance.destroy();
|
||||
observer.disconnect();
|
||||
},
|
||||
onShow: (instance) => {
|
||||
// For both buddy list and top left corner pm list, `target_node`
|
||||
// is their parent `ul` element. We cannot use MutationObserver
|
||||
// directly on the reference element because it will be removed
|
||||
// and we need to attach it on an element which will remain in the
|
||||
// DOM which is their parent `ul`.
|
||||
const target_node = $(instance.reference).parents("ul").get(0);
|
||||
// We only need to know if any of the `li` elements were removed.
|
||||
const config = {attributes: false, childList: true, subtree: false};
|
||||
const callback = function (mutationsList) {
|
||||
for (const mutation of mutationsList) {
|
||||
// Hide instance if reference is in the removed node list.
|
||||
if (
|
||||
Array.prototype.includes.call(
|
||||
mutation.removedNodes,
|
||||
instance.reference.parentElement,
|
||||
)
|
||||
) {
|
||||
instance.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
observer = new MutationObserver(callback);
|
||||
observer.observe(target_node, config);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user