/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ import { attachClickEvent } from "./dom/clickEvent"; import findUpAsChild from "./dom/findUpAsChild"; import EventListenerBase from "./eventListenerBase"; import ListenerSetter from "./listenerSetter"; import IS_TOUCH_SUPPORTED from "../environment/touchSupport"; import safeAssign from "./object/safeAssign"; const KEEP_OPEN = false; const TOGGLE_TIMEOUT = 200; const ANIMATION_DURATION = 200; export default class DropdownHover extends EventListenerBase<{ open: () => Promise | void, opened: () => any, close: () => any, closed: () => any }> { protected element: HTMLElement; protected displayTimeout: number; protected forceClose = false; protected inited = false; constructor(options: { element: DropdownHover['element'] }) { super(false); safeAssign(this, options); } public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) { let firstTime = true; if(IS_TOUCH_SUPPORTED) { attachClickEvent(button, () => { if(firstTime) { firstTime = false; this.toggle(true); } else { this.toggle(); } }, {listenerSetter}); } else { listenerSetter.add(button)('mouseover', (e) => { //console.log('onmouseover button'); if(firstTime) { listenerSetter.add(button)('mouseout', this.onMouseOut); firstTime = false; } clearTimeout(this.displayTimeout); this.displayTimeout = window.setTimeout(() => { this.toggle(true); }, TOGGLE_TIMEOUT); }); } } private onMouseOut = (e: MouseEvent) => { if(KEEP_OPEN) return; clearTimeout(this.displayTimeout); if(!this.isActive()) return; const toElement = (e as any).toElement as Element; if(toElement && findUpAsChild(toElement, this.element)) { return; } this.displayTimeout = window.setTimeout(() => { this.toggle(false); }, TOGGLE_TIMEOUT); }; protected init() { if(!IS_TOUCH_SUPPORTED) { this.element.onmouseout = this.onMouseOut; this.element.onmouseover = (e) => { if(this.forceClose) { return; } //console.log('onmouseover element'); clearTimeout(this.displayTimeout); }; } } public toggle = async(enable?: boolean) => { //if(!this.element) return; const willBeActive = (!!this.element.style.display && enable === undefined) || enable; if(this.init) { if(willBeActive) { this.init(); this.init = null; } else { return; } } if(willBeActive === this.isActive()) { return; } if((this.element.style.display && enable === undefined) || enable) { const res = this.dispatchResultableEvent('open'); await Promise.all(res); this.element.style.display = ''; void this.element.offsetLeft; // reflow this.element.classList.add('active'); clearTimeout(this.displayTimeout); this.displayTimeout = window.setTimeout(() => { this.forceClose = false; this.dispatchEvent('opened'); }, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION); // ! can't use together with resizeObserver /* if(isTouchSupported) { const height = this.element.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10; console.log('[ESG]: toggle: enable height', height); appImManager.chat.bubbles.scrollable.scrollTop += height; } */ /* if(touchSupport) { this.restoreScroll(); } */ } else { this.dispatchEvent('close'); this.element.classList.remove('active'); clearTimeout(this.displayTimeout); this.displayTimeout = window.setTimeout(() => { this.element.style.display = 'none'; this.forceClose = false; this.dispatchEvent('closed'); }, IS_TOUCH_SUPPORTED ? 0 : ANIMATION_DURATION); /* if(isTouchSupported) { const scrollHeight = this.container.scrollHeight; if(scrollHeight) { const height = this.container.scrollHeight + appImManager.chat.input.inputContainer.scrollHeight - 10; appImManager.chat.bubbles.scrollable.scrollTop -= height; } } */ /* if(touchSupport) { this.restoreScroll(); } */ } //animationIntersector.checkAnimations(false, EMOTICONSSTICKERGROUP); }; public isActive() { return this.element.classList.contains('active'); } }