/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; // This is loaded into chrome windows with the subscript loader. Wrap in // a block to prevent accidentally leaking globals onto `window`. { const cachedFragments = { get entities() { return [ "chrome://global/locale/textcontext.dtd", ]; }, get editMenuItems() { return ` `; }, get normal() { delete this.normal; this.normal = MozXULElement.parseXULToFragment(` ${this.editMenuItems} `, this.entities); return this.normal; }, get spellcheck() { delete this.spellcheck; this.spellcheck = MozXULElement.parseXULToFragment(` ${this.editMenuItems} `, this.entities); return this.spellcheck; }, }; class MozInputBox extends MozXULElement { static get observedAttributes() { return ["spellcheck"]; } attributeChangedCallback(name, oldValue, newValue) { if (name === "spellcheck" && oldValue != newValue) { this._initUI(); } } connectedCallback() { this._initUI(); } _initUI() { this.spellcheck = this.hasAttribute("spellcheck"); if (this.menupopup) { this.menupopup.remove(); } this.setAttribute("context", "_child"); this.appendChild(this.spellcheck ? cachedFragments.spellcheck.cloneNode(true) : cachedFragments.normal.cloneNode(true)); this.menupopup = this.querySelector(".textbox-contextmenu"); this.menupopup.addEventListener("popupshowing", event => { var input = this.getElementsByAttribute("anonid", "input")[0]; if (document.commandDispatcher.focusedElement != input) input.focus(); this._doPopupItemEnabling(event.target); }); if (this.spellcheck) { this.menupopup.addEventListener("popuphiding", event => { if (this.spellCheckerUI) { this.spellCheckerUI.clearSuggestionsFromMenu(); this.spellCheckerUI.clearDictionaryListFromMenu(); } }); } this.menupopup.addEventListener("command", event => { var cmd = event.originalTarget.getAttribute("cmd"); if (cmd) { this.doCommand(cmd); event.stopPropagation(); } }); } _doPopupItemEnablingSpell(popupNode) { var spellui = this.spellCheckerUI; if (!spellui || !spellui.canSpellCheck) { this._setMenuItemVisibility("spell-no-suggestions", false); this._setMenuItemVisibility("spell-check-enabled", false); this._setMenuItemVisibility("spell-check-separator", false); this._setMenuItemVisibility("spell-add-to-dictionary", false); this._setMenuItemVisibility("spell-undo-add-to-dictionary", false); this._setMenuItemVisibility("spell-suggestions-separator", false); this._setMenuItemVisibility("spell-dictionaries", false); return; } spellui.initFromEvent(document.popupRangeParent, document.popupRangeOffset); var enabled = spellui.enabled; var showUndo = spellui.canSpellCheck && spellui.canUndo(); var enabledCheckbox = this.getMenuItem("spell-check-enabled"); enabledCheckbox.setAttribute("checked", enabled); var overMisspelling = spellui.overMisspelling; this._setMenuItemVisibility("spell-add-to-dictionary", overMisspelling); this._setMenuItemVisibility("spell-undo-add-to-dictionary", showUndo); this._setMenuItemVisibility("spell-suggestions-separator", overMisspelling || showUndo); // suggestion list var suggestionsSeparator = this.getMenuItem("spell-no-suggestions"); var numsug = spellui.addSuggestionsToMenu(popupNode, suggestionsSeparator, 5); this._setMenuItemVisibility("spell-no-suggestions", overMisspelling && numsug == 0); // dictionary list var dictionariesMenu = this.getMenuItem("spell-dictionaries-menu"); var numdicts = spellui.addDictionaryListToMenu(dictionariesMenu, null); this._setMenuItemVisibility("spell-dictionaries", enabled && numdicts > 1); } _doPopupItemEnabling(popupNode) { if (this.spellcheck) { this._doPopupItemEnablingSpell(popupNode); } var children = popupNode.childNodes; for (var i = 0; i < children.length; i++) { var command = children[i].getAttribute("cmd"); if (command) { var controller = document.commandDispatcher.getControllerForCommand(command); var enabled = controller.isCommandEnabled(command); if (enabled) children[i].removeAttribute("disabled"); else children[i].setAttribute("disabled", "true"); } } } get spellCheckerUI() { if (!this._spellCheckInitialized) { this._spellCheckInitialized = true; if (ChromeUtils.getClassName(document) != "XULDocument") return null; var textbox = document.getBindingParent(this); if (!textbox || textbox.localName != "textbox") return null; try { ChromeUtils.import("resource://gre/modules/InlineSpellChecker.jsm", this); this.InlineSpellCheckerUI = new this.InlineSpellChecker(textbox.editor); } catch (ex) {} } return this.InlineSpellCheckerUI; } getMenuItem(anonid) { return this.querySelector(`[anonid="${anonid}"]`); } _setMenuItemVisibility(anonid, visible) { this.getMenuItem(anonid).hidden = !visible; } doCommand(command) { var controller = document.commandDispatcher.getControllerForCommand(command); controller.doCommand(command); } } customElements.define("moz-input-box", MozInputBox); }