toolkit/content/widgets/textbox.xml

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 <?xml version="1.0"?>
michael@0 2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 5
michael@0 6
michael@0 7 <!DOCTYPE bindings [
michael@0 8 <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
michael@0 9 %textcontextDTD;
michael@0 10 ]>
michael@0 11
michael@0 12 <bindings id="textboxBindings"
michael@0 13 xmlns="http://www.mozilla.org/xbl"
michael@0 14 xmlns:html="http://www.w3.org/1999/xhtml"
michael@0 15 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
michael@0 16 xmlns:xbl="http://www.mozilla.org/xbl">
michael@0 17
michael@0 18 <binding id="textbox" extends="xul:box" role="xul:textbox">
michael@0 19 <resources>
michael@0 20 <stylesheet src="chrome://global/content/textbox.css"/>
michael@0 21 <stylesheet src="chrome://global/skin/textbox.css"/>
michael@0 22 </resources>
michael@0 23
michael@0 24 <content>
michael@0 25 <children/>
michael@0 26 <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck">
michael@0 27 <html:input class="textbox-input" anonid="input"
michael@0 28 xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,noinitialfocus,mozactionhint,spellcheck"/>
michael@0 29 </xul:hbox>
michael@0 30 </content>
michael@0 31
michael@0 32 <implementation implements="nsIDOMXULTextBoxElement, nsIDOMXULLabeledControlElement">
michael@0 33 <!-- nsIDOMXULLabeledControlElement -->
michael@0 34 <field name="crop">""</field>
michael@0 35 <field name="image">""</field>
michael@0 36 <field name="command">""</field>
michael@0 37 <field name="accessKey">""</field>
michael@0 38
michael@0 39 <field name="mInputField">null</field>
michael@0 40 <field name="mIgnoreClick">false</field>
michael@0 41 <field name="mIgnoreFocus">false</field>
michael@0 42 <field name="mEditor">null</field>
michael@0 43
michael@0 44 <property name="inputField" readonly="true">
michael@0 45 <getter><![CDATA[
michael@0 46 if (!this.mInputField)
michael@0 47 this.mInputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
michael@0 48 return this.mInputField;
michael@0 49 ]]></getter>
michael@0 50 </property>
michael@0 51
michael@0 52 <property name="value" onset="this.inputField.value = val; return val;"
michael@0 53 onget="return this.inputField.value;"/>
michael@0 54 <property name="defaultValue" onset="this.inputField.defaultValue = val; return val;"
michael@0 55 onget="return this.inputField.defaultValue;"/>
michael@0 56 <property name="label" onset="this.setAttribute('label', val); return val;"
michael@0 57 onget="return this.getAttribute('label') ||
michael@0 58 (this.labelElement ? this.labelElement.value :
michael@0 59 this.placeholder);"/>
michael@0 60 <property name="placeholder" onset="this.inputField.placeholder = val; return val;"
michael@0 61 onget="return this.inputField.placeholder;"/>
michael@0 62 <property name="emptyText" onset="this.placeholder = val; return val;"
michael@0 63 onget="return this.placeholder;"/>
michael@0 64 <property name="type" onset="if (val) this.setAttribute('type', val);
michael@0 65 else this.removeAttribute('type'); return val;"
michael@0 66 onget="return this.getAttribute('type');"/>
michael@0 67 <property name="maxLength" onset="this.inputField.maxLength = val; return val;"
michael@0 68 onget="return this.inputField.maxLength;"/>
michael@0 69 <property name="disabled" onset="this.inputField.disabled = val;
michael@0 70 if (val) this.setAttribute('disabled', 'true');
michael@0 71 else this.removeAttribute('disabled'); return val;"
michael@0 72 onget="return this.inputField.disabled;"/>
michael@0 73 <property name="tabIndex" onget="return parseInt(this.getAttribute('tabindex'));"
michael@0 74 onset="this.inputField.tabIndex = val;
michael@0 75 if (val) this.setAttribute('tabindex', val);
michael@0 76 else this.removeAttribute('tabindex'); return val;"/>
michael@0 77 <property name="size" onset="this.inputField.size = val; return val;"
michael@0 78 onget="return this.inputField.size;"/>
michael@0 79 <property name="readOnly" onset="this.inputField.readOnly = val;
michael@0 80 if (val) this.setAttribute('readonly', 'true');
michael@0 81 else this.removeAttribute('readonly'); return val;"
michael@0 82 onget="return this.inputField.readOnly;"/>
michael@0 83 <property name="clickSelectsAll"
michael@0 84 onget="return this.getAttribute('clickSelectsAll') == 'true';"
michael@0 85 onset="if (val) this.setAttribute('clickSelectsAll', 'true');
michael@0 86 else this.removeAttribute('clickSelectsAll'); return val;" />
michael@0 87
michael@0 88 <property name="editor" readonly="true">
michael@0 89 <getter><![CDATA[
michael@0 90 if (!this.mEditor) {
michael@0 91 const nsIDOMNSEditableElement = Components.interfaces.nsIDOMNSEditableElement;
michael@0 92 this.mEditor = this.inputField.QueryInterface(nsIDOMNSEditableElement).editor;
michael@0 93 }
michael@0 94 return this.mEditor;
michael@0 95 ]]></getter>
michael@0 96 </property>
michael@0 97
michael@0 98 <method name="reset">
michael@0 99 <body><![CDATA[
michael@0 100 this.value = this.defaultValue;
michael@0 101 try {
michael@0 102 this.editor.transactionManager.clear();
michael@0 103 return true;
michael@0 104 }
michael@0 105 catch(e) {}
michael@0 106 return false;
michael@0 107 ]]></body>
michael@0 108 </method>
michael@0 109
michael@0 110 <method name="select">
michael@0 111 <body>
michael@0 112 this.inputField.select();
michael@0 113 </body>
michael@0 114 </method>
michael@0 115
michael@0 116 <property name="controllers" readonly="true" onget="return this.inputField.controllers"/>
michael@0 117 <property name="textLength" readonly="true"
michael@0 118 onget="return this.inputField.textLength;"/>
michael@0 119 <property name="selectionStart" onset="this.inputField.selectionStart = val; return val;"
michael@0 120 onget="return this.inputField.selectionStart;"/>
michael@0 121 <property name="selectionEnd" onset="this.inputField.selectionEnd = val; return val;"
michael@0 122 onget="return this.inputField.selectionEnd;"/>
michael@0 123
michael@0 124 <method name="setSelectionRange">
michael@0 125 <parameter name="aSelectionStart"/>
michael@0 126 <parameter name="aSelectionEnd"/>
michael@0 127 <body>
michael@0 128 this.inputField.setSelectionRange( aSelectionStart, aSelectionEnd );
michael@0 129 </body>
michael@0 130 </method>
michael@0 131
michael@0 132 <method name="_setNewlineHandling">
michael@0 133 <body><![CDATA[
michael@0 134 var str = this.getAttribute("newlines");
michael@0 135 if (str && this.editor) {
michael@0 136 const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
michael@0 137 for (var x in nsIPlaintextEditor) {
michael@0 138 if (/^eNewlines/.test(x)) {
michael@0 139 if (str == RegExp.rightContext.toLowerCase()) {
michael@0 140 this.editor.QueryInterface(nsIPlaintextEditor)
michael@0 141 .newlineHandling = nsIPlaintextEditor[x];
michael@0 142 break;
michael@0 143 }
michael@0 144 }
michael@0 145 }
michael@0 146 }
michael@0 147 ]]></body>
michael@0 148 </method>
michael@0 149
michael@0 150 <method name="_maybeSelectAll">
michael@0 151 <body><![CDATA[
michael@0 152 if (!this.mIgnoreClick && this.clickSelectsAll &&
michael@0 153 document.activeElement == this.inputField &&
michael@0 154 this.inputField.selectionStart == this.inputField.selectionEnd)
michael@0 155 this.editor.selectAll();
michael@0 156 ]]></body>
michael@0 157 </method>
michael@0 158
michael@0 159 <constructor><![CDATA[
michael@0 160 var str = this.boxObject.getProperty("value");
michael@0 161 if (str) {
michael@0 162 this.inputField.value = str;
michael@0 163 this.boxObject.removeProperty("value");
michael@0 164 }
michael@0 165
michael@0 166 this._setNewlineHandling();
michael@0 167
michael@0 168 if (this.hasAttribute("emptytext"))
michael@0 169 this.placeholder = this.getAttribute("emptytext");
michael@0 170 ]]></constructor>
michael@0 171
michael@0 172 <destructor>
michael@0 173 <![CDATA[
michael@0 174 if (this.inputField.value)
michael@0 175 this.boxObject.setProperty('value', this.inputField.value);
michael@0 176 this.mInputField = null;
michael@0 177 ]]>
michael@0 178 </destructor>
michael@0 179
michael@0 180 </implementation>
michael@0 181
michael@0 182 <handlers>
michael@0 183 <handler event="focus" phase="capturing">
michael@0 184 <![CDATA[
michael@0 185 if (this.hasAttribute("focused"))
michael@0 186 return;
michael@0 187
michael@0 188 switch (event.originalTarget) {
michael@0 189 case this:
michael@0 190 // Forward focus to actual HTML input
michael@0 191 this.inputField.focus();
michael@0 192 break;
michael@0 193 case this.inputField:
michael@0 194 if (this.mIgnoreFocus) {
michael@0 195 this.mIgnoreFocus = false;
michael@0 196 } else if (this.clickSelectsAll) {
michael@0 197 try {
michael@0 198 const nsIEditorIMESupport =
michael@0 199 Components.interfaces.nsIEditorIMESupport;
michael@0 200 let imeEditor = this.editor.QueryInterface(nsIEditorIMESupport);
michael@0 201 if (!imeEditor || !imeEditor.composing)
michael@0 202 this.editor.selectAll();
michael@0 203 } catch (e) {}
michael@0 204 }
michael@0 205 break;
michael@0 206 default:
michael@0 207 // Allow other children (e.g. URL bar buttons) to get focus
michael@0 208 return;
michael@0 209 }
michael@0 210 this.setAttribute("focused", "true");
michael@0 211 ]]>
michael@0 212 </handler>
michael@0 213
michael@0 214 <handler event="blur" phase="capturing">
michael@0 215 <![CDATA[
michael@0 216 this.removeAttribute("focused");
michael@0 217
michael@0 218 // don't trigger clickSelectsAll when switching application windows
michael@0 219 if (window == window.top &&
michael@0 220 window.constructor == ChromeWindow &&
michael@0 221 document.activeElement == this.inputField)
michael@0 222 this.mIgnoreFocus = true;
michael@0 223 ]]>
michael@0 224 </handler>
michael@0 225
michael@0 226 <handler event="mousedown">
michael@0 227 <![CDATA[
michael@0 228 this.mIgnoreClick = this.hasAttribute("focused");
michael@0 229
michael@0 230 if (!this.mIgnoreClick) {
michael@0 231 this.mIgnoreFocus = true;
michael@0 232 this.inputField.setSelectionRange(0, 0);
michael@0 233 if (event.originalTarget == this ||
michael@0 234 event.originalTarget == this.inputField.parentNode)
michael@0 235 this.inputField.focus();
michael@0 236 }
michael@0 237 ]]>
michael@0 238 </handler>
michael@0 239
michael@0 240 <handler event="click" action="this._maybeSelectAll();"/>
michael@0 241
michael@0 242 #ifndef XP_WIN
michael@0 243 <handler event="contextmenu">
michael@0 244 if (!event.button) // context menu opened via keyboard shortcut
michael@0 245 return;
michael@0 246 this._maybeSelectAll();
michael@0 247 // see bug 576135 comment 4
michael@0 248 let box = this.inputField.parentNode;
michael@0 249 let menu = document.getAnonymousElementByAttribute(box, "anonid", "input-box-contextmenu");
michael@0 250 box._doPopupItemEnabling(menu);
michael@0 251 </handler>
michael@0 252 #endif
michael@0 253 </handlers>
michael@0 254 </binding>
michael@0 255
michael@0 256 <binding id="timed-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
michael@0 257 <implementation>
michael@0 258 <constructor><![CDATA[
michael@0 259 try {
michael@0 260 var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
michael@0 261 .getService(Components.interfaces.nsIConsoleService);
michael@0 262 var scriptError = Components.classes["@mozilla.org/scripterror;1"]
michael@0 263 .createInstance(Components.interfaces.nsIScriptError);
michael@0 264 scriptError.init("Timed textboxes are deprecated. Consider using type=\"search\" instead.",
michael@0 265 this.ownerDocument.location.href, null, null,
michael@0 266 null, scriptError.warningFlag, "XUL Widgets");
michael@0 267 consoleService.logMessage(scriptError);
michael@0 268 } catch (e) {}
michael@0 269 ]]></constructor>
michael@0 270 <field name="_timer">null</field>
michael@0 271 <property name="timeout"
michael@0 272 onset="this.setAttribute('timeout', val); return val;"
michael@0 273 onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
michael@0 274 <property name="value"
michael@0 275 onget="return this.inputField.value;">
michael@0 276 <setter><![CDATA[
michael@0 277 this.inputField.value = val;
michael@0 278 if (this._timer)
michael@0 279 clearTimeout(this._timer);
michael@0 280 return val;
michael@0 281 ]]></setter>
michael@0 282 </property>
michael@0 283 <method name="_fireCommand">
michael@0 284 <parameter name="me"/>
michael@0 285 <body>
michael@0 286 <![CDATA[
michael@0 287 me._timer = null;
michael@0 288 me.doCommand();
michael@0 289 ]]>
michael@0 290 </body>
michael@0 291 </method>
michael@0 292 </implementation>
michael@0 293 <handlers>
michael@0 294 <handler event="input">
michael@0 295 <![CDATA[
michael@0 296 if (this._timer)
michael@0 297 clearTimeout(this._timer);
michael@0 298 this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
michael@0 299 ]]>
michael@0 300 </handler>
michael@0 301 <handler event="keypress" keycode="VK_RETURN">
michael@0 302 <![CDATA[
michael@0 303 if (this._timer)
michael@0 304 clearTimeout(this._timer);
michael@0 305 this._fireCommand(this);
michael@0 306 event.preventDefault();
michael@0 307 ]]>
michael@0 308 </handler>
michael@0 309 </handlers>
michael@0 310 </binding>
michael@0 311
michael@0 312 <binding id="search-textbox" extends="chrome://global/content/bindings/textbox.xml#textbox">
michael@0 313 <content>
michael@0 314 <children/>
michael@0 315 <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck" align="center">
michael@0 316 <html:input class="textbox-input" anonid="input" mozactionhint="search"
michael@0 317 xbl:inherits="value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,spellcheck"/>
michael@0 318 <xul:deck class="textbox-search-icons" anonid="search-icons">
michael@0 319 <xul:image class="textbox-search-icon"
michael@0 320 onclick="document.getBindingParent(this)._iconClick();"
michael@0 321 xbl:inherits="src=image,searchbutton,disabled"/>
michael@0 322 <xul:image class="textbox-search-clear"
michael@0 323 onclick="document.getBindingParent(this)._clearSearch();"
michael@0 324 xbl:inherits="disabled"/>
michael@0 325 </xul:deck>
michael@0 326 </xul:hbox>
michael@0 327 </content>
michael@0 328 <implementation>
michael@0 329 <field name="_timer">null</field>
michael@0 330 <field name="_searchIcons">
michael@0 331 document.getAnonymousElementByAttribute(this, "anonid", "search-icons");
michael@0 332 </field>
michael@0 333 <property name="timeout"
michael@0 334 onset="this.setAttribute('timeout', val); return val;"
michael@0 335 onget="return parseInt(this.getAttribute('timeout')) || 500;"/>
michael@0 336 <property name="searchButton"
michael@0 337 onget="return this.getAttribute('searchbutton') == 'true';">
michael@0 338 <setter><![CDATA[
michael@0 339 if (val) {
michael@0 340 this.setAttribute("searchbutton", "true");
michael@0 341 this.removeAttribute("aria-autocomplete");
michael@0 342 } else {
michael@0 343 this.removeAttribute("searchbutton");
michael@0 344 this.setAttribute("aria-autocomplete", "list");
michael@0 345 }
michael@0 346 return val;
michael@0 347 ]]></setter>
michael@0 348 </property>
michael@0 349 <property name="value"
michael@0 350 onget="return this.inputField.value;">
michael@0 351 <setter><![CDATA[
michael@0 352 this.inputField.value = val;
michael@0 353
michael@0 354 if (val)
michael@0 355 this._searchIcons.selectedIndex = this.searchButton ? 0 : 1;
michael@0 356 else
michael@0 357 this._searchIcons.selectedIndex = 0;
michael@0 358
michael@0 359 if (this._timer)
michael@0 360 clearTimeout(this._timer);
michael@0 361
michael@0 362 return val;
michael@0 363 ]]></setter>
michael@0 364 </property>
michael@0 365 <constructor><![CDATA[
michael@0 366 if (this.searchButton)
michael@0 367 this.removeAttribute("aria-autocomplete");
michael@0 368 else
michael@0 369 this.setAttribute("aria-autocomplete", "list");
michael@0 370 ]]></constructor>
michael@0 371 <method name="_fireCommand">
michael@0 372 <parameter name="me"/>
michael@0 373 <body><![CDATA[
michael@0 374 if (me._timer)
michael@0 375 clearTimeout(me._timer);
michael@0 376 me._timer = null;
michael@0 377 me.doCommand();
michael@0 378 ]]></body>
michael@0 379 </method>
michael@0 380 <method name="_iconClick">
michael@0 381 <body><![CDATA[
michael@0 382 if (this.searchButton)
michael@0 383 this._enterSearch();
michael@0 384 else
michael@0 385 this.focus();
michael@0 386 ]]></body>
michael@0 387 </method>
michael@0 388 <method name="_enterSearch">
michael@0 389 <body><![CDATA[
michael@0 390 if (this.disabled)
michael@0 391 return;
michael@0 392 if (this.searchButton && this.value && !this.readOnly)
michael@0 393 this._searchIcons.selectedIndex = 1;
michael@0 394 this._fireCommand(this);
michael@0 395 ]]></body>
michael@0 396 </method>
michael@0 397 <method name="_clearSearch">
michael@0 398 <body><![CDATA[
michael@0 399 if (!this.disabled && !this.readOnly && this.value) {
michael@0 400 this.value = "";
michael@0 401 this._fireCommand(this);
michael@0 402 this._searchIcons.selectedIndex = 0;
michael@0 403 return true;
michael@0 404 }
michael@0 405 return false;
michael@0 406 ]]></body>
michael@0 407 </method>
michael@0 408 </implementation>
michael@0 409 <handlers>
michael@0 410 <handler event="input">
michael@0 411 <![CDATA[
michael@0 412 if (this.searchButton) {
michael@0 413 this._searchIcons.selectedIndex = 0;
michael@0 414 return;
michael@0 415 }
michael@0 416 if (this._timer)
michael@0 417 clearTimeout(this._timer);
michael@0 418 this._timer = this.timeout && setTimeout(this._fireCommand, this.timeout, this);
michael@0 419 this._searchIcons.selectedIndex = this.value ? 1 : 0;
michael@0 420 ]]>
michael@0 421 </handler>
michael@0 422 <handler event="keypress" keycode="VK_ESCAPE">
michael@0 423 <![CDATA[
michael@0 424 if (this._clearSearch()) {
michael@0 425 event.preventDefault();
michael@0 426 event.stopPropagation();
michael@0 427 }
michael@0 428 ]]>
michael@0 429 </handler>
michael@0 430 <handler event="keypress" keycode="VK_RETURN">
michael@0 431 <![CDATA[
michael@0 432 this._enterSearch();
michael@0 433 event.preventDefault();
michael@0 434 event.stopPropagation();
michael@0 435 ]]>
michael@0 436 </handler>
michael@0 437 </handlers>
michael@0 438 </binding>
michael@0 439
michael@0 440 <binding id="textarea" extends="chrome://global/content/bindings/textbox.xml#textbox">
michael@0 441 <content>
michael@0 442 <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,spellcheck">
michael@0 443 <html:textarea class="textbox-textarea" anonid="input"
michael@0 444 xbl:inherits="xbl:text=value,disabled,tabindex,rows,cols,readonly,wrap,placeholder,mozactionhint,spellcheck"><children/></html:textarea>
michael@0 445 </xul:hbox>
michael@0 446 </content>
michael@0 447 </binding>
michael@0 448
michael@0 449 <binding id="input-box">
michael@0 450 <content context="_child">
michael@0 451 <children/>
michael@0 452 <xul:menupopup anonid="input-box-contextmenu"
michael@0 453 class="textbox-contextmenu"
michael@0 454 onpopupshowing="var input =
michael@0 455 this.parentNode.getElementsByAttribute('anonid', 'input')[0];
michael@0 456 if (document.commandDispatcher.focusedElement != input)
michael@0 457 input.focus();
michael@0 458 this.parentNode._doPopupItemEnabling(this);"
michael@0 459 oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.doCommand(cmd); event.stopPropagation(); }">
michael@0 460 <xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/>
michael@0 461 <xul:menuseparator/>
michael@0 462 <xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/>
michael@0 463 <xul:menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;" cmd="cmd_copy"/>
michael@0 464 <xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/>
michael@0 465 <xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/>
michael@0 466 <xul:menuseparator/>
michael@0 467 <xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/>
michael@0 468 </xul:menupopup>
michael@0 469 </content>
michael@0 470
michael@0 471 <implementation>
michael@0 472 <method name="_doPopupItemEnabling">
michael@0 473 <parameter name="popupNode"/>
michael@0 474 <body>
michael@0 475 <![CDATA[
michael@0 476 var children = popupNode.childNodes;
michael@0 477 for (var i = 0; i < children.length; i++) {
michael@0 478 var command = children[i].getAttribute("cmd");
michael@0 479 if (command) {
michael@0 480 var controller = document.commandDispatcher.getControllerForCommand(command);
michael@0 481 var enabled = controller.isCommandEnabled(command);
michael@0 482 if (enabled)
michael@0 483 children[i].removeAttribute("disabled");
michael@0 484 else
michael@0 485 children[i].setAttribute("disabled", "true");
michael@0 486 }
michael@0 487 }
michael@0 488 ]]>
michael@0 489 </body>
michael@0 490 </method>
michael@0 491
michael@0 492 <method name="_setMenuItemVisibility">
michael@0 493 <parameter name="anonid"/>
michael@0 494 <parameter name="visible"/>
michael@0 495 <body><![CDATA[
michael@0 496 document.getAnonymousElementByAttribute(this, "anonid", anonid).
michael@0 497 hidden = ! visible;
michael@0 498 ]]></body>
michael@0 499 </method>
michael@0 500
michael@0 501 <method name="doCommand">
michael@0 502 <parameter name="command"/>
michael@0 503 <body>
michael@0 504 <![CDATA[
michael@0 505 var controller = document.commandDispatcher.getControllerForCommand(command);
michael@0 506 controller.doCommand(command);
michael@0 507 ]]>
michael@0 508 </body>
michael@0 509 </method>
michael@0 510 </implementation>
michael@0 511 </binding>
michael@0 512
michael@0 513 <binding id="input-box-spell" extends="chrome://global/content/bindings/textbox.xml#input-box">
michael@0 514 <content context="_child">
michael@0 515 <children/>
michael@0 516 <xul:menupopup anonid="input-box-contextmenu"
michael@0 517 class="textbox-contextmenu"
michael@0 518 onpopupshowing="var input =
michael@0 519 this.parentNode.getElementsByAttribute('anonid', 'input')[0];
michael@0 520 if (document.commandDispatcher.focusedElement != input)
michael@0 521 input.focus();
michael@0 522 this.parentNode._doPopupItemEnablingSpell(this);"
michael@0 523 onpopuphiding="this.parentNode._doPopupItemDisabling(this);"
michael@0 524 oncommand="var cmd = event.originalTarget.getAttribute('cmd'); if(cmd) { this.parentNode.doCommand(cmd); event.stopPropagation(); }">
michael@0 525 <xul:menuitem label="&spellNoSuggestions.label;" anonid="spell-no-suggestions" disabled="true"/>
michael@0 526 <xul:menuitem label="&spellAddToDictionary.label;" accesskey="&spellAddToDictionary.accesskey;" anonid="spell-add-to-dictionary"
michael@0 527 oncommand="this.parentNode.parentNode.spellCheckerUI.addToDictionary();"/>
michael@0 528 <xul:menuitem label="&spellUndoAddToDictionary.label;" accesskey="&spellUndoAddToDictionary.accesskey;" anonid="spell-undo-add-to-dictionary"
michael@0 529 oncommand="this.parentNode.parentNode.spellCheckerUI.undoAddToDictionary();"/>
michael@0 530 <xul:menuseparator anonid="spell-suggestions-separator"/>
michael@0 531 <xul:menuitem label="&undoCmd.label;" accesskey="&undoCmd.accesskey;" cmd="cmd_undo"/>
michael@0 532 <xul:menuseparator/>
michael@0 533 <xul:menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;" cmd="cmd_cut"/>
michael@0 534 <xul:menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;" cmd="cmd_copy"/>
michael@0 535 <xul:menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" cmd="cmd_paste"/>
michael@0 536 <xul:menuitem label="&deleteCmd.label;" accesskey="&deleteCmd.accesskey;" cmd="cmd_delete"/>
michael@0 537 <xul:menuseparator/>
michael@0 538 <xul:menuitem label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;" cmd="cmd_selectAll"/>
michael@0 539 <xul:menuseparator anonid="spell-check-separator"/>
michael@0 540 <xul:menuitem label="&spellCheckToggle.label;" type="checkbox" accesskey="&spellCheckToggle.accesskey;" anonid="spell-check-enabled"
michael@0 541 oncommand="this.parentNode.parentNode.spellCheckerUI.toggleEnabled();"/>
michael@0 542 <xul:menu label="&spellDictionaries.label;" accesskey="&spellDictionaries.accesskey;" anonid="spell-dictionaries">
michael@0 543 <xul:menupopup anonid="spell-dictionaries-menu"
michael@0 544 onpopupshowing="event.stopPropagation();"
michael@0 545 onpopuphiding="event.stopPropagation();"/>
michael@0 546 </xul:menu>
michael@0 547 </xul:menupopup>
michael@0 548 </content>
michael@0 549
michael@0 550 <implementation>
michael@0 551 <field name="_spellCheckInitialized">false</field>
michael@0 552 <field name="_enabledCheckbox">
michael@0 553 document.getAnonymousElementByAttribute(this, "anonid", "spell-check-enabled");
michael@0 554 </field>
michael@0 555 <field name="_suggestionsSeparator">
michael@0 556 document.getAnonymousElementByAttribute(this, "anonid", "spell-no-suggestions");
michael@0 557 </field>
michael@0 558 <field name="_dictionariesMenu">
michael@0 559 document.getAnonymousElementByAttribute(this, "anonid", "spell-dictionaries-menu");
michael@0 560 </field>
michael@0 561
michael@0 562 <property name="spellCheckerUI" readonly="true">
michael@0 563 <getter><![CDATA[
michael@0 564 if (!this._spellCheckInitialized) {
michael@0 565 this._spellCheckInitialized = true;
michael@0 566
michael@0 567 const CI = Components.interfaces;
michael@0 568 if (!(document instanceof CI.nsIDOMXULDocument))
michael@0 569 return null;
michael@0 570
michael@0 571 var textbox = document.getBindingParent(this);
michael@0 572 if (!textbox || !(textbox instanceof CI.nsIDOMXULTextBoxElement))
michael@0 573 return null;
michael@0 574
michael@0 575 try {
michael@0 576 Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm", this);
michael@0 577 this.InlineSpellCheckerUI = new this.InlineSpellChecker(textbox.editor);
michael@0 578 } catch(ex) { }
michael@0 579 }
michael@0 580
michael@0 581 return this.InlineSpellCheckerUI;
michael@0 582 ]]></getter>
michael@0 583 </property>
michael@0 584
michael@0 585 <method name="_doPopupItemEnablingSpell">
michael@0 586 <parameter name="popupNode"/>
michael@0 587 <body>
michael@0 588 <![CDATA[
michael@0 589 var spellui = this.spellCheckerUI;
michael@0 590 if (!spellui || !spellui.canSpellCheck) {
michael@0 591 this._setMenuItemVisibility("spell-no-suggestions", false);
michael@0 592 this._setMenuItemVisibility("spell-check-enabled", false);
michael@0 593 this._setMenuItemVisibility("spell-check-separator", false);
michael@0 594 this._setMenuItemVisibility("spell-add-to-dictionary", false);
michael@0 595 this._setMenuItemVisibility("spell-undo-add-to-dictionary", false);
michael@0 596 this._setMenuItemVisibility("spell-suggestions-separator", false);
michael@0 597 this._setMenuItemVisibility("spell-dictionaries", false);
michael@0 598 return;
michael@0 599 }
michael@0 600
michael@0 601 spellui.initFromEvent(document.popupRangeParent,
michael@0 602 document.popupRangeOffset);
michael@0 603
michael@0 604 var enabled = spellui.enabled;
michael@0 605 var showUndo = spellui.canSpellCheck && spellui.canUndo();
michael@0 606 this._enabledCheckbox.setAttribute("checked", enabled);
michael@0 607
michael@0 608 var overMisspelling = spellui.overMisspelling;
michael@0 609 this._setMenuItemVisibility("spell-add-to-dictionary", overMisspelling);
michael@0 610 this._setMenuItemVisibility("spell-undo-add-to-dictionary", showUndo);
michael@0 611 this._setMenuItemVisibility("spell-suggestions-separator", overMisspelling || showUndo);
michael@0 612
michael@0 613 // suggestion list
michael@0 614 var numsug = spellui.addSuggestionsToMenu(popupNode, this._suggestionsSeparator, 5);
michael@0 615 this._setMenuItemVisibility("spell-no-suggestions", overMisspelling && numsug == 0);
michael@0 616
michael@0 617 // dictionary list
michael@0 618 var numdicts = spellui.addDictionaryListToMenu(this._dictionariesMenu, null);
michael@0 619 this._setMenuItemVisibility("spell-dictionaries", enabled && numdicts > 1);
michael@0 620
michael@0 621 this._doPopupItemEnabling(popupNode);
michael@0 622 ]]>
michael@0 623 </body>
michael@0 624 </method>
michael@0 625 <method name="_doPopupItemDisabling">
michael@0 626 <body><![CDATA[
michael@0 627 if (this.spellCheckerUI) {
michael@0 628 this.spellCheckerUI.clearSuggestionsFromMenu();
michael@0 629 this.spellCheckerUI.clearDictionaryListFromMenu();
michael@0 630 }
michael@0 631 ]]></body>
michael@0 632 </method>
michael@0 633 </implementation>
michael@0 634 </binding>
michael@0 635
michael@0 636 </bindings>

mercurial