UNPKG

coupdoeil

Version:

Javascript for Ruby on Rails Coupdoeil gem

103 lines (93 loc) 4.3 kB
import {POPOVER_SELECTOR} from "../popover/config"; import {notTriggeredOnHover} from "../popover/attributes"; import { cancelClosingRequest, closeChildrenNow, closeOnHoverChildrenLater, closeOnHoverNotParentsLater, closeTriggeredOnHoverLater, closeTriggeredOnHoverNowUnlessAncestor } from "../popover/closing"; import {addToCurrents as addToCurrentPopovers} from "../popover/current"; import {isAnyPopoverOpened} from "../popover/utils"; import {upgradeNativeElement} from "../elements/coupdoeil_element"; export const onMouseOver = ({ target: hoveredElement }) => { const coupdoeilElement = hoveredElement.closest('coup-doeil, [data-popover-options]') upgradeNativeElement(coupdoeilElement) const popoverElement = hoveredElement.closest(POPOVER_SELECTOR) if (coupdoeilElement && popoverElement) { handleMouseOverCoupdoeilWithinPopover(coupdoeilElement, popoverElement, hoveredElement) } else if (coupdoeilElement) { handleMouseOverCoupdoeilOutsidePopover(coupdoeilElement, hoveredElement) } else if (popoverElement) { handleOverOutsideCoupdoeilButWithinPopover(popoverElement) } else { handleOverOutsideCoupdoeilAndPopover() } } function handleMouseOverCoupdoeilWithinPopover(coupdoeilElement, popoverElement, hoveredElement) { const childPopover = coupdoeilElement.popoverController const parentPopover = popoverElement.popoverController if(notTriggeredOnHover(childPopover)) return; if (childPopover.isOpen) { // when the mouse goes back from child popover to its coupdoeil element within parent popover // it means that this child popover was already open closeChildrenNow(childPopover) // it should also prevent closing the child popover cancelClosingRequest(childPopover) addToCurrentPopovers(childPopover.coupdoeilElement) } else { // ensures to close other children popovers before opening the one that current one closeChildrenNow(parentPopover) // should also close any open popover outside of parent coupdoeilElement.openPopover(hoveredElement) } } function handleMouseOverCoupdoeilOutsidePopover(coupdoeilElement, hoveredElement) { const popover = coupdoeilElement.popoverController if(notTriggeredOnHover(popover)) return; if (popover.isClosed) { // Close any other open popover before opening this one coupdoeilElement.openPopover(hoveredElement, { beforeDisplay: closeTriggeredOnHoverNowUnlessAncestor }) } else if (popover.closingRequest) { // If popover is still open but was requested to close, then it must clear this closing request // and ensures the popovers stays in current popovers register. cancelClosingRequest(popover) addToCurrentPopovers(popover.coupdoeilElement) } } function handleOverOutsideCoupdoeilAndPopover() { // mouse is not within any popover and not over any coupdoeil element // Therefore all popovers that trigger on hover should be closed if any is open. if (isAnyPopoverOpened()) { closeTriggeredOnHoverLater() } } function handleOverOutsideCoupdoeilButWithinPopover(popoverElement) { const popover = popoverElement.popoverController if (popover.closingRequest) { // If popover is still open but was requested to close, then it must clear this closing request // and ensures the popovers stays in current popovers register. // This typically happens when the mouse was on coupdoeil element and moved toward the popover. // But because of a small gap, it triggered the closing request. When the mouse finally enters the popover // the closing request must be aborted. Since it typically happens in a child popover, it means it should also // prevent all parents of this popover to close. let topMostParent = popover while (topMostParent) { cancelClosingRequest(topMostParent) addToCurrentPopovers(topMostParent.coupdoeilElement) topMostParent = topMostParent.parent } } else if (popover.children.size > 0) { // Happens when a child popover was open but mouse moved outside of it or its coupdoeil element, // but stays within the parent popover closeOnHoverChildrenLater(popover) } // Closes all other on hover popovers that are not parents of the current popover nor children. closeOnHoverNotParentsLater(popover) }