UNPKG

coupdoeil

Version:

Javascript for Ruby on Rails Coupdoeil gem

90 lines (80 loc) 3.58 kB
import {POPOVER_SELECTOR} from "../popover/config"; import {isAnyPopoverOpened} from "../popover/state_check"; import {notTriggeredOnHover} from "../popover/attributes"; import { cancelCloseRequest, closeChildrenNow, closeOnHoverChildrenLater, closeTriggeredOnHoverLater, closeTriggeredOnHoverNowUnlessAncestor } from "../popover/closing"; import {addToCurrents as addToCurrentPopovers} from "../popover/current"; export const onMouseOver = ({ target: hoveredElement }) => { const coupdoeilElement = hoveredElement.closest('coup-doeil') 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) } 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) { // popover is still open but was requested to close, then it clear this closing request // and ensures the popovers stays in current popovers register cancelCloseRequest(popover) addToCurrentPopovers(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) { // popover is still open but was requested to close, then it clears this closing request // and ensures the popovers stays in current popovers register // This typically happens when mouse was on coupdoeil element, then it moves toward the popover // but because of a small gap, it triggers the closing request, but when the mouse finally enters the popover // this closing request must be aborted. cancelCloseRequest(popover) addToCurrentPopovers(popover.coupdoeilElement) } 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) } }