class Popover extends View { static get POPOVER_SCREEN_PADDING() { return 24; } static get POPOVER_ARROW_SIZE() { return 15; } /** * The constructor accepts a DOM element as a parameter. This is the content view of the popover. */ constructor(element = null) { super(element); this.contentElement = document.createElement("DIV"); this.contentElement.className = "popover-content"; while (this.element.children.length > 0) { this.contentElement.appendChild(this.element.firstChild); } this.element.appendChild(this.contentElement); this.arrowElement = document.createElement("DIV"); this.arrowElement.className = "popover-arrow-container"; this.arrowBoxElement = document.createElement("DIV"); this.arrowBoxElement.className = "popover-arrow-box"; this.arrowTipElement = document.createElement("DIV"); this.arrowTipElement.className = "popover-arrow-tip"; this.arrowBoxElement.appendChild(this.arrowTipElement); this.arrowElement.appendChild(this.arrowBoxElement); this.element.appendChild(this.arrowElement); this.element.addEventListener("click", this.onPopoverClicked.bind(this)); document.body.addEventListener("click", this.onBodyClicked.bind(this)); } /** * The build function is called in the constructor when no element was passed as the base. * Override it to create custom subviews or manipulate the root element. * Don't forget to return the element in the end! */ build(element) { return element; } /** * Called once the view has been processed by UIKit during the view controller initialization. */ viewDidLoad() { } /** * Called everytime before the view is shown. * The layout is already done at this step, so it's safe to use scrollWidth and scrollHeight and what not. */ viewWillAppear() { } /** * Called everytime after the view is shown. */ viewDidAppear() { } /** * Called everytime before the view is hidden. */ viewWillDisappear() { } /** * Called everytime after the view is hidden. */ viewDidDisappear() { } /** * Shows the popover for the specified element. * Will automatically position the popover to be located next to the element on screen. * You can optionally specify the side of the element on which the popover should appear. */ showForElement(element, side = "right") { this.element.classList.add("preparing"); UIKit.activeScene.showPopover(this); var elementBounds = element.getBoundingClientRect(); var popoverBounds = this.element.getBoundingClientRect(); var elementCenterY = elementBounds.top + (elementBounds.height / 2); var popoverTop = elementCenterY - (popoverBounds.height / 2); if (popoverTop < Popover.POPOVER_SCREEN_PADDING) { popoverTop = Popover.POPOVER_SCREEN_PADDING; } else if (popoverTop + popoverBounds.height > window.innerHeight - Popover.POPOVER_SCREEN_PADDING) { popoverTop = window.innerHeight - Popover.POPOVER_SCREEN_PADDING - popoverBounds.height; } this.element.style.top = popoverTop + "px"; if (side == "right") { this.element.style.left = elementBounds.left + elementBounds.width + Popover.POPOVER_ARROW_SIZE + "px"; } else if (side == "left") { this.element.style.left = elementBounds.left - popoverBounds.width - Popover.POPOVER_ARROW_SIZE + "px"; } this.element.className = side; this.element.classList.remove("preparing"); this.visible = true; } /** * Dismisses the popover. */ dismiss() { this.element.className = ""; this.visible = false; UIKit.activeScene.dismissPopover(); } /** * This is called when a click is performed inside the popover. * Used to stop the event from propagating to the body to prevent the popover from being hidden. */ onPopoverClicked(event) { event.stopPropagation(); } onBodyClicked(event) { if (this.visible) { this.dismiss(); } } } UIKit.registerPopoverType(Popover, "popover");