coupdoeil
Version:
Javascript for Ruby on Rails Coupdoeil gem
162 lines (135 loc) • 4.58 kB
JavaScript
import {triggeredOnHover, triggeredOnClick} from "./attributes"
import {CLOSING_DELAY_MS} from "./config"
import {leave} from "el-transition"
import {addToCurrents, CURRENT_POPOVERS_BY_ID, removeFromCurrents} from "./current"
function detachFromParent(controller) {
if (controller.parent) {
controller.parent.children.delete(controller)
controller.parent = null
}
}
export function cancelOpenCloseActions(controller) {
cancelOpening(controller)
cancelClosingRequest(controller)
}
function cancelOpening(controller) {
delete controller.coupdoeilElement.openingPopover
}
export function cancelClosingRequest(controller) {
if (controller.closingRequest) {
clearTimeout(controller.closingRequest)
controller.closingRequest = null
}
}
export function closeNow(controller, allowAnimation = true) {
if (controller.closing || (controller.isClosed && !controller.coupdoeilElement.openingPopover)) return
cancelClosingRequest(controller)
controller.closing = true
cancelOpenCloseActions(controller)
controller.children.forEach((childController) => {
closeNow(childController)
})
detachFromParent(controller)
if (allowAnimation && controller.card && controller.card.dataset.animation) {
closeWithAnimation(controller).then(() => {
removeFromCurrents(controller.coupdoeilElement)
})
} else {
closeWithoutAnimation(controller)
removeFromCurrents(controller.coupdoeilElement)
}
}
async function closeWithAnimation(controller) {
await leave(controller.card, 'popover')
closeWithoutAnimation(controller)
}
function closeWithoutAnimation(controller) {
if (controller.card) {
controller.card.remove()
controller.card = null
}
delete controller.closing
delete controller.coupdoeilElement.dataset.popoverOpen
}
export function clear(controller) {
closeNow(controller, false)
}
export function closeLater(controller) {
cancelOpenCloseActions(controller)
controller.closingRequest = setTimeout(() => {
closeNow(controller)
}, CLOSING_DELAY_MS)
}
export function closeChildrenNow(controller) {
controller.children.forEach((childController) => {
closeNow(childController)
})
}
export function closeChildrenLater(controller) {
controller.children.forEach((childController) => {
closeLater(childController)
})
}
export function closeOnHoverChildrenLater(controller) {
controller.children.forEach((childController) => {
if (triggeredOnHover(childController)) {
closeLater(childController)
}
})
}
export function closeOnHoverNotParentsLater(controller) {
let topMostParent = controller
while (topMostParent.parent) {
topMostParent = topMostParent.parent
}
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
if (
// SKIP If:
// popover has a parent (Closing topmost parent will close children)
coupdoeilElement.popoverController.parent !== null ||
// popover is topmost parent of currently hovered popover (the one whose controller was passed as an argument)
coupdoeilElement.uniqueId === topMostParent.coupdoeilElement.uniqueId ||
// popover is triggered on click
triggeredOnClick(coupdoeilElement.popoverController)
) {
continue
}
closeLater(coupdoeilElement.popoverController)
}
}
export function closeAllNow() {
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
closeNow(coupdoeilElement.popoverController)
}
}
export function clearAll() {
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
clear(coupdoeilElement.popoverController)
}
}
export function closeTriggeredOnHoverNow() {
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
if (triggeredOnHover(coupdoeilElement.popoverController)) {
closeNow(coupdoeilElement.popoverController)
}
}
}
export function closeTriggeredOnHoverLater() {
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
if (triggeredOnHover(coupdoeilElement.popoverController)) {
closeLater(coupdoeilElement.popoverController)
}
}
}
export function closeTriggeredOnHoverNowUnlessAncestor(controller) {
let topMostParent = controller
while (topMostParent.parent) {
topMostParent = topMostParent.parent
}
const idToSkip = topMostParent.coupdoeilElement.uniqueId
for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
if (coupdoeilElement.uniqueId !== idToSkip && triggeredOnHover(coupdoeilElement.popoverController)) {
closeNow(coupdoeilElement.popoverController)
}
}
}