UNPKG

@etsoo/editor

Version:

ETSOO Free WYSIWYG HTML Editor

122 lines (118 loc) 3.99 kB
'use strict'; var shared = require('@etsoo/shared'); /** * EOEditor Popup */ class EOPopup extends HTMLElement { // Layout update cancel updateCancel; /** * Auto close when click outside */ autoClose = true; constructor() { super(); const template = document.createElement("template"); template.innerHTML = `<style>:host { position: fixed; background-color: #fff; border-radius: 4px; box-shadow: 0 2px 6px 2px rgba(60, 64, 67, 0.15); z-index: 990; user-select: none;}</style><slot></slot>`; const shadowRoot = this.attachShadow({ mode: "open" }); shadowRoot.appendChild(template.content); document.addEventListener("mousedown", this.clickHandler.bind(this)); } updatePos(location, insideIFrame = false) { let { clientWidth: maxWidth, clientHeight: maxHeight } = window.document.body; let prect = this.getBoundingClientRect(); if (this.offsetParent && this.offsetParent.nodeName !== "BODY") { const prect2 = this.offsetParent.getBoundingClientRect(); maxWidth = prect2.width; maxHeight = prect2.height; } const rect = location ?? new DOMRect((maxWidth - prect.width) / 2, (maxHeight - prect.height) / 2, 0, 0); // Left let left = rect.left; if (left + prect.width > maxWidth) { // Right left = rect.right - prect.width; if (left < 0) { // Middle left = rect.left - (prect.width - rect.width) / 2; // Still more than screen width (16px spacing considered to avoid too close to right side) const gap = 8; const stillMore = left + prect.width + gap - maxWidth; if (stillMore > 0) { left -= stillMore; } if (left < gap) left = gap; } } this.style.left = `${(insideIFrame ? 0 : window.scrollX) + left}px`; this.style.top = `${(insideIFrame ? 0 : window.scrollY) + rect.bottom + 2}px`; } clickHandler(event) { // https://stackoverflow.com/questions/57963312/get-event-target-inside-a-web-component const cp = event.composedPath(); if (!this.autoClose || this.style.visibility === "hidden" || cp.includes(this) || (this.nodeName !== "EO-PALETTE" && cp.some((p) => p instanceof HTMLElement && (p.nodeName === "EO-PALETTE" || p.nodeName === "EO-IMAGE-EDITOR")))) { return; } this.hide(); } connectedCallback() { this.hide(); } disconnectedCallback() { document.removeEventListener("mousedown", this.clickHandler.bind(this)); this.clearUpdateSeed(); this.hide(); } /** * Hide the popup */ hide() { //console.trace(); this.style.visibility = "hidden"; } /** * Is visible * @returns result */ isVisible() { return this.style.visibility === "visible"; } clearUpdateSeed() { if (this.updateCancel) { this.updateCancel(); this.updateCancel = undefined; } } /** * Reshow the popup */ reshow() { this.style.visibility = "visible"; } /** * Show the popup * @param message Message * @param location Location deciding rect * @param ready Ready callback * @param insideIFrame Inside iframe or not */ show(message, location, ready, insideIFrame = false) { this.autoClose = true; this.clearUpdateSeed(); this.innerHTML = message; this.updateCancel = shared.ExtendUtils.waitFor(() => { this.updatePos(location, insideIFrame); this.reshow(); if (ready) ready(); }, 20); } } exports.EOPopup = EOPopup;