<?xml version="1.0"?> <!-- 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/. --> <!DOCTYPE bindings [ <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" > %textcontextDTD; ]> <bindings id="textboxBindings" xmlns="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:xbl="http://www.mozilla.org/xbl"> <binding id="textbox" extends="xul:box" role="xul:textbox"> <resources> <stylesheet src="chrome://global/content/textbox.css"/> <stylesheet src="chrome://global/skin/textbox.css"/> </resources> <content> <children/> <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck"> <html:input class="textbox-input" anonid="input" xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,noinitialfocus,mozactionhint,spellcheck"/> </xul:hbox> </content> <implementation implements="nsIDOMXULTextBoxElement, nsIDOMXULLabeledControlElement"> <!-- nsIDOMXULLabeledControlElement --> <field name="crop">""</field> <field name="image">""</field> <field name="command">""</field> <field name="accessKey">""</field> <field name="mInputField">null</field> <field name="mIgnoreClick">false</field> <field name="mIgnoreFocus">false</field> <field name="mEditor">null</field> <property name="inputField" readonly="true"> <getter><![CDATA[ if (!this.mInputField) this.mInputField = document.getAnonymousElementByAttribute(this, "anonid", "input"); return this.mInputField; ]]></getter> </property> <property name="value" onset="this.inputField.value = val; return val;" onget="return this.inputField.value;"/> <property name="defaultValue" onset="this.inputField.defaultValue = val; return val;" onget="return this.inputField.defaultValue;"/> <property name="label" onset="this.setAttribute('label', val); return val;" onget="return this.getAttribute('label') || (this.labelElement ? this.labelElement.value : this.placeholder);"/> <property name="placeholder" onset="this.inputField.placeholder = val; return val;" onget="return this.inputField.placeholder;"/> <property name="emptyText" onset="this.placeholder = val; return val;" onget="return this.placeholder;"/> <property name="type" onset="if (val) this.setAttribute('type', val); else this.removeAttribute('type'); return val;" onget="return this.getAttribute('type');"/> <property name="maxLength" onset="this.inputField.maxLength = val; return val;" onget="return this.inputField.maxLength;"/> <property name="disabled" onset="this.inputField.disabled = val; if (val) this.setAttribute('disabled', 'true'); else this.removeAttribute('disabled'); return val;" onget="return this.inputField.disabled;"/> <property name="tabIndex" onget="return parseInt(this.getAttribute('tabindex'));" onset="this.inputField.tabIndex = val; if (val) this.setAttribute('tabindex', val); else this.removeAttribute('tabindex'); return val;"/> <property name="size" onset="this.inputField.size = val; return val;" onget="return this.inputField.size;"/> <property name="readOnly" onset="this.inputField.readOnly = val; if (val) this.setAttribute('readonly', 'true'); else this.removeAttribute('readonly'); return val;" onget="return this.inputField.readOnly;"/> <property name="clickSelectsAll" onget="return this.getAttribute('clickSelectsAll') == 'true';" onset="if (val) this.setAttribute('clickSelectsAll', 'true'); else this.removeAttribute('clickSelectsAll'); return val;" /> <property name="editor" readonly="true"> <getter><![CDATA[ if (!this.mEditor) { const nsIDOMNSEditableElement = Components.interfaces.nsIDOMNSEditableElement; this.mEditor = this.inputField.QueryInterface(nsIDOMNSEditableElement).editor; } return this.mEditor; ]]></getter> </property> <method name="reset"> <body><![CDATA[ this.value = this.defaultValue; try { this.editor.transactionManager.clear(); return true; } catch (e) {} return false; ]]></body> </method> <method name="select"> <body> this.inputField.select(); </body> </method> <property name="controllers" readonly="true" onget="return this.inputField.controllers"/> <property name="textLength" readonly="true" onget="return this.inputField.textLength;"/> <property name="selectionStart" onset="this.inputField.selectionStart = val; return val;" onget="return this.inputField.selectionStart;"/> <property name="selectionEnd" onset="this.inputField.selectionEnd = val; return val;" onget="return this.inputField.selectionEnd;"/> <method name="setSelectionRange"> <parameter name="aSelectionStart"/> <parameter name="aSelectionEnd"/> <body> this.inputField.setSelectionRange( aSelectionStart, aSelectionEnd ); </body> </method> <method name="_setNewlineHandling"> <body><![CDATA[ var str = this.getAttribute("newlines"); if (str && this.editor) { const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor; for (var x in nsIPlaintextEditor) { if (/^eNewlines/.test(x)) { if (str == RegExp.rightContext.toLowerCase()) { this.editor.QueryInterface(nsIPlaintextEditor) .newlineHandling = nsIPlaintextEditor[x]; break; } } } } ]]></body> </method> <method name="_maybeSelectAll"> <body><![CDATA[ if (!this.mIgnoreClick && this.clickSelectsAll && document.activeElement == this.inputField && this.inputField.selectionStart == this.inputField.selectionEnd) this.editor.selectAll(); ]]></body> </method> <constructor><![CDATA[ var str = this.boxObject.getProperty("value"); if (str) { this.inputField.value = str; this.boxObject.removeProperty("value"); } this._setNewlineHandling(); if (this.hasAttribute("emptytext")) this.placeholder = this.getAttribute("emptytext"); ]]></constructor> <destructor> <![CDATA[ var field = this.inputField; if (field && field.value) this.boxObject.setProperty('value', field.value); this.mInputField = null; ]]> </destructor> </implementation> <handlers> <handler event="focus" phase="capturing"> <![CDATA[ if (this.hasAttribute("focused")) return; switch (event.originalTarget) { case this: // Forward focus to actual HTML input this.inputField.focus(); break; case this.inputField: if (this.mIgnoreFocus) { this.mIgnoreFocus = false; } else if (this.clickSelectsAll) { try { const nsIEditorIMESupport = Components.interfaces.nsIEditorIMESupport; let imeEditor = this.editor.QueryInterface(nsIEditorIMESupport); if (!imeEditor || !imeEditor.composing) this.editor.selectAll(); } catch (e) {} } break; default: // Allow other children (e.g. URL bar buttons) to get focus return; } this.setAttribute("focused", "true"); ]]> </handler> <handler event="blur" phase="capturing"> <![CDATA[ this.removeAttribute("focused"); // don't trigger clickSelectsAll when switching application windows if (window == window.top && window.constructor == ChromeWindow && document.activeElement == this.inputField) this.mIgnoreFocus = true; ]]> </handler> <handler event="mousedown"> <![CDATA[ this.mIgnoreClick = this.hasAttribute("focused"); if (!this.mIgnoreClick) { this.mIgnoreFocus = true; this.inputField.setSelectionRange(0, 0); if (event.originalTarget == this || event.originalTarget == this.inputField.parentNode) this.inputField.focus(); } ]]> </handler> <handler event="click" action="this._maybeSelectAll();"/> #ifndef XP_WIN <handler event="contextmenu"> // Only care about context clicks on the textbox itself. if (event.target != this) return; if (!event.button) // context menu opened via keyboard shortcut return; this._maybeSelectAll(); // see bug 576135 comment 4 let box = this.inputField.parentNode; let menu = document.getAnonymousElementByAttribute(box, "anonid", "input-box-contextmenu"); box._doPopupItemEnabling(menu); </handler> #endif </handlers> </binding> <binding id="timed-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox"> <implementation> <constructor><![CDATA[ try { var consoleService = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); var scriptError = Components.classes["@mozilla.org/scripterror;1"] .createInstance(Components.interfaces.nsIScriptError); scriptError.init("Timed textboxes are deprecated. Consider using type=\"search\" instead.", this.ownerDocument.location.href, null, null, null, scriptError.warningFlag, "XUL Widgets"); consoleService.logMessage(scriptError); } catch (e) {} ]]></constructor> <field name="_timer">null</field> <property name="timeout" onset="this.setAttribute('timeout', val); return val;" onget="return parseInt(this.getAttribute('timeout')) || 0;"/> <property name="value" onget="return this.inputField.value;"> <setter><![CDATA[ this.inputField.value = val; if (this._timer) clearTimeout(this._timer); return val; ]]></setter> </property> <method name="_fireCommand"> <parameter name="me"/> <body> <![CDATA[ me._timer = null; me.doCommand(); ]]> </body> </method> </implementation> <handlers> <handler event="input"> <![CDATA[ if (this._timer) clearTimeout(this._timer); this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this); ]]> </handler> <handler event="keypress" keycode="VK_RETURN"> <![CDATA[ if (this._timer) clearTimeout(this._timer); this._fireCommand(this); event.preventDefault(); ]]> </handler> </handlers> </binding> <binding id="search-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox"> <content> <children/> <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck" align="center"> <html:input class="textbox-input" anonid="input" mozactionhint="search" xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,spellcheck"/> <xul:deck class="textbox-search-icons" anonid="search-icons"> <xul:image class="textbox-search-icon" anonid="searchbutton-icon" xbl:inherits="src=image,label=searchbuttonlabel,searchbutton,disabled"/> <xul:image class="textbox-search-clear" onclick="document.getBindingParent(this)._clearSearch();" label="&searchTextBox.clear.label;" xbl:inherits="disabled"/> </xul:deck> </xul:hbox> </content> <implementation> <field name="_timer">null</field> <field name="_searchIcons"> document.getAnonymousElementByAttribute(this, "anonid", "search-icons"); </field> <field name="_searchButtonIcon"> document.getAnonymousElementByAttribute(this, "anonid", "searchbutton-icon"); </field> <property name="timeout" onset="this.setAttribute('timeout', val); return val;" onget="return parseInt(this.getAttribute('timeout')) || 500;"/> <property name="searchButton" onget="return this.getAttribute('searchbutton') == 'true';"> <setter><![CDATA[ if (val) { this.setAttribute("searchbutton", "true"); this.removeAttribute("aria-autocomplete"); // Hack for the button to get the right accessible: this._searchButtonIcon.setAttribute("onclick", "true"); } else { this.removeAttribute("searchbutton"); this._searchButtonIcon.removeAttribute("onclick"); this.setAttribute("aria-autocomplete", "list"); } return val; ]]></setter> </property> <property name="value" onget="return this.inputField.value;"> <setter><![CDATA[ this.inputField.value = val; if (val) this._searchIcons.selectedIndex = this.searchButton ? 0 : 1; else this._searchIcons.selectedIndex = 0; if (this._timer) clearTimeout(this._timer); return val; ]]></setter> </property> <constructor><![CDATA[ // Ensure the button state is up to date: this.searchButton = this.searchButton; this._searchButtonIcon.addEventListener("click", (e) => this._iconClick(e), false); ]]></constructor> <method name="_fireCommand"> <parameter name="me"/> <body><![CDATA[ if (me._timer) clearTimeout(me._timer); me._timer = null; me.doCommand(); ]]></body> </method> <method name="_iconClick"> <body><![CDATA[ if (this.searchButton) this._enterSearch(); else this.focus(); ]]></body> </method> <method name="_enterSearch"> <body><![CDATA[ if (this.disabled) return; if (this.searchButton && this.value && !this.readOnly) this._searchIcons.selectedIndex = 1; this._fireCommand(this); ]]></body> </method> <method name="_clearSearch"> <body><![CDATA[ if (!this.disabled && !this.readOnly && this.value) { this.value = ""; this._fireCommand(this); this._searchIcons.selectedIndex = 0; return true; } return false; ]]></body> </method> </implementation> <handlers> <handler event="input"> <![CDATA[ if (this.searchButton) { this._searchIcons.selectedIndex = 0; return; } if (this._timer) clearTimeout(this._timer); this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this); this._searchIcons.selectedIndex = this.value ? 1 : 0; ]]> </handler> <handler event="keypress" keycode="VK_ESCAPE"> <![CDATA[ if (this._clearSearch()) { event.preventDefault(); event.stopPropagation(); } ]]> </handler> <handler event="keypress" keycode="VK_RETURN"> <![CDATA[ this._enterSearch(); event.preventDefault(); event.stopPropagation(); ]]> </handler> </handlers> </binding> <binding id="textarea" extends="chrome://global/content/bindings/textbox.xml#textbox"> <content> <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck"> <html:textarea class="textbox-textarea" anonid="input" xbl:inherits="xbl:text=value,disabled,tabindex,rows,cols,readonly,wrap,placeholder,mozactionhint,spellcheck"><children/></html:textarea> </xul:hbox> </content> </binding> <binding id="input-box"> <content context="_child"> <children/> <xul:menupopup anonid="input-box-contextmenu" class="textbox-contextmenu" onpopupshowing="var input = this.parentNode.getElementsByAttribute('anonid', 'input')[0]; if (document.commandDispatcher.focusedElement != input) input.focus(); this.parentNode._doPopupItemEnabling(this);" oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.doCommand(cmd); event.stopPropagation(); }"> <xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/> <xul:menuseparator/> <xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/> <xul:menuitem label="©Cmd.label;" accesskey="©Cmd.accesskey;" cmd="cmd_copy"/> <xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/> <xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/> <xul:menuseparator/> <xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/> </xul:menupopup> </content> <implementation> <method name="_doPopupItemEnabling"> <parameter name="popupNode"/> <body> <![CDATA[ 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"); } } ]]> </body> </method> <method name="_setMenuItemVisibility"> <parameter name="anonid"/> <parameter name="visible"/> <body><![CDATA[ document.getAnonymousElementByAttribute(this, "anonid", anonid). hidden = ! visible; ]]></body> </method> <method name="doCommand"> <parameter name="command"/> <body> <![CDATA[ var controller = document.commandDispatcher.getControllerForCommand(command); controller.doCommand(command); ]]> </body> </method> </implementation> </binding> <binding id="input-box-spell" extends="chrome://global/content/bindings/textbox.xml#input-box"> <content context="_child"> <children/> <xul:menupopup anonid="input-box-contextmenu" class="textbox-contextmenu" onpopupshowing="var input = this.parentNode.getElementsByAttribute('anonid', 'input')[0]; if (document.commandDispatcher.focusedElement != input) input.focus(); this.parentNode._doPopupItemEnablingSpell(this);" onpopuphiding="this.parentNode._doPopupItemDisabling(this);" oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.doCommand(cmd); event.stopPropagation(); }"> <xul:menuitem label="&spellNoSuggestions.label;" anonid="spell-no-suggestions" disabled="true"/> <xul:menuitem label="&spellAddToDictionary.label;" accesskey="&spellAddToDictionary.accesskey;" anonid="spell-add-to-dictionary" oncommand="this.parentNode.parentNode.spellCheckerUI.addToDictionary();"/> <xul:menuitem label="&spellUndoAddToDictionary.label;" accesskey="&spellUndoAddToDictionary.accesskey;" anonid="spell-undo-add-to-dictionary" oncommand="this.parentNode.parentNode.spellCheckerUI.undoAddToDictionary();"/> <xul:menuseparator anonid="spell-suggestions-separator"/> <xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/> <xul:menuseparator/> <xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/> <xul:menuitem label="©Cmd.label;" accesskey="©Cmd.accesskey;" cmd="cmd_copy"/> <xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/> <xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/> <xul:menuseparator/> <xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/> <xul:menuseparator anonid="spell-check-separator"/> <xul:menuitem label="&spellCheckToggle.label;" type="checkbox" accesskey="&spellCheckToggle.accesskey;" anonid="spell-check-enabled" oncommand="this.parentNode.parentNode.spellCheckerUI.toggleEnabled();"/> <xul:menu label="&spellDictionaries.label;" accesskey="&spellDictionaries.accesskey;" anonid="spell-dictionaries"> <xul:menupopup anonid="spell-dictionaries-menu" onpopupshowing="event.stopPropagation();" onpopuphiding="event.stopPropagation();"/> </xul:menu> </xul:menupopup> </content> <implementation> <field name="_spellCheckInitialized">false</field> <field name="_enabledCheckbox"> document.getAnonymousElementByAttribute(this, "anonid", "spell-check-enabled"); </field> <field name="_suggestionsSeparator"> document.getAnonymousElementByAttribute(this, "anonid", "spell-no-suggestions"); </field> <field name="_dictionariesMenu"> document.getAnonymousElementByAttribute(this, "anonid", "spell-dictionaries-menu"); </field> <property name="spellCheckerUI" readonly="true"> <getter><![CDATA[ if (!this._spellCheckInitialized) { this._spellCheckInitialized = true; const CI = Components.interfaces; if (!(document instanceof CI.nsIDOMXULDocument)) return null; var textbox = document.getBindingParent(this); if (!textbox || !(textbox instanceof CI.nsIDOMXULTextBoxElement)) return null; try { Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm", this); this.InlineSpellCheckerUI = new this.InlineSpellChecker(textbox.editor); } catch (ex) { } } return this.InlineSpellCheckerUI; ]]></getter> </property> <method name="_doPopupItemEnablingSpell"> <parameter name="popupNode"/> <body> <![CDATA[ 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(); this._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 numsug = spellui.addSuggestionsToMenu(popupNode, this._suggestionsSeparator, 5); this._setMenuItemVisibility("spell-no-suggestions", overMisspelling && numsug == 0); // dictionary list var numdicts = spellui.addDictionaryListToMenu(this._dictionariesMenu, null); this._setMenuItemVisibility("spell-dictionaries", enabled && numdicts > 1); this._doPopupItemEnabling(popupNode); ]]> </body> </method> <method name="_doPopupItemDisabling"> <body><![CDATA[ if (this.spellCheckerUI) { this.spellCheckerUI.clearSuggestionsFromMenu(); this.spellCheckerUI.clearDictionaryListFromMenu(); } ]]></body> </method> </implementation> </binding> </bindings>