("click", HTMLEditor.#stopPropagation); // Avoid the hijack of the backspace key by the markup when the // html editor is open. this.#editorInner.addEventListener("keydown", HTMLEditor.#stopPropagation); this.editor = new Editor(config); this.editor.appendToLocalElement(this.#editorInner); this.hide(false); } editor = null; doc = null; #container = null; #editorInner = null; #attachedElement = null; #originalValue; static #ctrl(k) { return (Services.appinfo.OS == "Darwin" ? "Cmd-" : "Ctrl-") + k; } static #stopPropagation(e) { e.stopPropagation(); } /** * Need to refresh position by manually setting CSS values, so this will * need to be called on resizes and other sizing changes. */ refresh = () => { const element = this.#attachedElement; if (element) { this.#container.style.top = element.offsetTop + "px"; this.#container.style.left = element.offsetLeft + "px"; this.#container.style.width = element.offsetWidth + "px"; this.#container.style.height = element.parentNode.offsetHeight + "px"; } }; /** * Anchor the editor to a particular element. * * @param {DOMNode} element * The element that the editor will be anchored to. * Should belong to the HTMLDocument passed into the constructor. */ #attach(element) { this.#detach(); this.#attachedElement = element; element.classList.add("html-editor-container"); this.refresh(); } /** * Unanchor the editor from an element. */ #detach() { if (this.#attachedElement) { this.#attachedElement.classList.remove("html-editor-container"); this.#attachedElement = undefined; } } /** * Anchor the editor to a particular element, and show the editor. * * @param {DOMNode} element * The element that the editor will be anchored to. * Should belong to the HTMLDocument passed into the constructor. * @param {string} text * Value to set the contents of the editor to * @param {Function} cb * The function to call when hiding */ show = (element, text) => { if (this.isVisible) { return; } this.#originalValue = text; this.editor.setText(text, { saveTransactionToHistory: false }); this.#attach(element); this.#container.style.display = "flex"; this.isVisible = true; this.editor.focus(); this.emit("popupshown"); }; /** * Hide the editor, optionally committing the changes * * @param {boolean} shouldCommit * A change will be committed by default. If this param * strictly equals false, no change will occur. */ hide = shouldCommit => { if (!this.isVisible) { return; } this.#container.style.display = "none"; this.#detach(); const newValue = this.editor.getText(); const valueHasChanged = this.#originalValue !== newValue; const preventCommit = shouldCommit === false || !valueHasChanged; this.#originalValue = undefined; this.isVisible = undefined; this.emit("popuphidden", !preventCommit, newValue); }; /** * Destroy this object and unbind all event handlers */ destroy() { this.doc.defaultView.removeEventListener("resize", this.refresh, true); this.#container.removeEventListener("click", this.hide); this.#editorInner.removeEventListener("click", HTMLEditor.#stopPropagation); this.#editorInner.removeEventListener( "keydown", HTMLEditor.#stopPropagation ); this.hide(false); this.#container.remove(); this.editor.destroy(); } } module.exports = HTMLEditor; PK