/* 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} ` ); MozXULElement.insertFTLIfNeeded("toolkit/global/textActions.ftl"); 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 => { let input = this._input; 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; try { ChromeUtils.import( "resource://gre/modules/InlineSpellChecker.jsm", this ); this.InlineSpellCheckerUI = new this.InlineSpellChecker( this._input.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); } get _input() { return ( this.getElementsByAttribute("anonid", "input")[0] || this.querySelector(".textbox-input") ); } } customElements.define("moz-input-box", MozInputBox); }