toolkit/content/widgets/findbar.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 <?xml version="1.0"?>
michael@0 2
michael@0 3 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 6
michael@0 7 <!DOCTYPE bindings [
michael@0 8 <!ENTITY % findBarDTD SYSTEM "chrome://global/locale/findbar.dtd" >
michael@0 9 %findBarDTD;
michael@0 10 ]>
michael@0 11
michael@0 12 <bindings id="findbarBindings"
michael@0 13 xmlns="http://www.mozilla.org/xbl"
michael@0 14 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
michael@0 15 xmlns:xbl="http://www.mozilla.org/xbl">
michael@0 16
michael@0 17 <!-- Private binding -->
michael@0 18 <binding id="findbar-textbox"
michael@0 19 extends="chrome://global/content/bindings/textbox.xml#textbox">
michael@0 20 <implementation>
michael@0 21
michael@0 22 <field name="_findbar">null</field>
michael@0 23 <property name="findbar" readonly="true">
michael@0 24 <getter>
michael@0 25 return this._findbar ?
michael@0 26 this._findbar : this._findbar = document.getBindingParent(this);
michael@0 27 </getter>
michael@0 28 </property>
michael@0 29
michael@0 30 <method name="_handleEnter">
michael@0 31 <parameter name="aEvent"/>
michael@0 32 <body><![CDATA[
michael@0 33 if (this.findbar._findMode == this.findbar.FIND_NORMAL) {
michael@0 34 let findString = this.findbar._findField;
michael@0 35 if (!findString.value)
michael@0 36 return;
michael@0 37 #ifdef XP_MACOSX
michael@0 38 if (aEvent.metaKey) {
michael@0 39 #else
michael@0 40 if (aEvent.ctrlKey) {
michael@0 41 #endif
michael@0 42 this.findbar.getElement("highlight").click();
michael@0 43 return;
michael@0 44 }
michael@0 45
michael@0 46 this.findbar.onFindAgainCommand(aEvent.shiftKey);
michael@0 47 } else {
michael@0 48 this.findbar._finishFAYT(aEvent);
michael@0 49 }
michael@0 50 ]]></body>
michael@0 51 </method>
michael@0 52
michael@0 53 <method name="_handleTab">
michael@0 54 <parameter name="aEvent"/>
michael@0 55 <body><![CDATA[
michael@0 56 let shouldHandle = !aEvent.altKey && !aEvent.ctrlKey &&
michael@0 57 !aEvent.metaKey;
michael@0 58 if (shouldHandle &&
michael@0 59 this.findbar._findMode != this.findbar.FIND_NORMAL) {
michael@0 60
michael@0 61 this.findbar._finishFAYT(aEvent);
michael@0 62 }
michael@0 63 ]]></body>
michael@0 64 </method>
michael@0 65 </implementation>
michael@0 66
michael@0 67 <handlers>
michael@0 68 <handler event="input"><![CDATA[
michael@0 69 // We should do nothing during composition. E.g., composing string
michael@0 70 // before converting may matches a forward word of expected word.
michael@0 71 // After that, even if user converts the composition string to the
michael@0 72 // expected word, it may find second or later searching word in the
michael@0 73 // document.
michael@0 74 if (this.findbar._isIMEComposing) {
michael@0 75 return;
michael@0 76 }
michael@0 77 this.findbar._find(this.value);
michael@0 78 ]]></handler>
michael@0 79
michael@0 80 <handler event="keypress"><![CDATA[
michael@0 81 let shouldHandle = !event.altKey && !event.ctrlKey &&
michael@0 82 !event.metaKey && !event.shiftKey;
michael@0 83
michael@0 84 switch (event.keyCode) {
michael@0 85 case KeyEvent.DOM_VK_RETURN:
michael@0 86 this._handleEnter(event);
michael@0 87 break;
michael@0 88 case KeyEvent.DOM_VK_TAB:
michael@0 89 this._handleTab(event);
michael@0 90 break;
michael@0 91 case KeyEvent.DOM_VK_PAGE_UP:
michael@0 92 case KeyEvent.DOM_VK_PAGE_DOWN:
michael@0 93 if (shouldHandle) {
michael@0 94 this.findbar.browser.finder.keyPress(event);
michael@0 95 event.preventDefault();
michael@0 96 }
michael@0 97 break;
michael@0 98 case KeyEvent.DOM_VK_UP:
michael@0 99 case KeyEvent.DOM_VK_DOWN:
michael@0 100 this.findbar.browser.finder.keyPress(event);
michael@0 101 event.preventDefault();
michael@0 102 break;
michael@0 103 }
michael@0 104 ]]></handler>
michael@0 105
michael@0 106 <handler event="blur"><![CDATA[
michael@0 107 let findbar = this.findbar;
michael@0 108 // Note: This code used to remove the selection
michael@0 109 // if it matched an editable.
michael@0 110 findbar.browser.finder.enableSelection();
michael@0 111 ]]></handler>
michael@0 112
michael@0 113 #ifdef XP_MACOSX
michael@0 114 <handler event="focus"><![CDATA[
michael@0 115 let findbar = this.findbar;
michael@0 116 findbar._onFindFieldFocus();
michael@0 117 ]]></handler>
michael@0 118 #endif
michael@0 119
michael@0 120 <handler event="compositionstart"><![CDATA[
michael@0 121 // Don't close the find toolbar while IME is composing.
michael@0 122 let findbar = this.findbar;
michael@0 123 findbar._isIMEComposing = true;
michael@0 124 if (findbar._quickFindTimeout) {
michael@0 125 clearTimeout(findbar._quickFindTimeout);
michael@0 126 findbar._quickFindTimeout = null;
michael@0 127 }
michael@0 128 ]]></handler>
michael@0 129
michael@0 130 <handler event="compositionend"><![CDATA[
michael@0 131 let findbar = this.findbar;
michael@0 132 findbar._isIMEComposing = false;
michael@0 133 if (findbar._findMode != findbar.FIND_NORMAL)
michael@0 134 findbar._setFindCloseTimeout();
michael@0 135 ]]></handler>
michael@0 136
michael@0 137 <handler event="dragover"><![CDATA[
michael@0 138 if (event.dataTransfer.types.contains("text/plain"))
michael@0 139 event.preventDefault();
michael@0 140 ]]></handler>
michael@0 141
michael@0 142 <handler event="drop"><![CDATA[
michael@0 143 let value = event.dataTransfer.getData("text/plain");
michael@0 144 this.value = value;
michael@0 145 this.findbar._find(value);
michael@0 146 event.stopPropagation();
michael@0 147 event.preventDefault();
michael@0 148 ]]></handler>
michael@0 149 </handlers>
michael@0 150 </binding>
michael@0 151
michael@0 152 <binding id="findbar"
michael@0 153 extends="chrome://global/content/bindings/toolbar.xml#toolbar">
michael@0 154 <resources>
michael@0 155 <stylesheet src="chrome://global/skin/findBar.css"/>
michael@0 156 </resources>
michael@0 157
michael@0 158 <content hidden="true">
michael@0 159 <xul:hbox anonid="findbar-container" class="findbar-container" flex="1" align="center">
michael@0 160 <xul:hbox anonid="findbar-textbox-wrapper" align="stretch">
michael@0 161 <xul:textbox anonid="findbar-textbox"
michael@0 162 class="findbar-textbox findbar-find-fast"
michael@0 163 xbl:inherits="flash"/>
michael@0 164 <xul:toolbarbutton anonid="find-previous"
michael@0 165 class="findbar-find-previous tabbable"
michael@0 166 tooltiptext="&previous.tooltip;"
michael@0 167 oncommand="onFindAgainCommand(true);"
michael@0 168 disabled="true"
michael@0 169 xbl:inherits="accesskey=findpreviousaccesskey"/>
michael@0 170 <xul:toolbarbutton anonid="find-next"
michael@0 171 class="findbar-find-next tabbable"
michael@0 172 tooltiptext="&next.tooltip;"
michael@0 173 oncommand="onFindAgainCommand(false);"
michael@0 174 disabled="true"
michael@0 175 xbl:inherits="accesskey=findnextaccesskey"/>
michael@0 176 </xul:hbox>
michael@0 177 <xul:toolbarbutton anonid="highlight"
michael@0 178 class="findbar-highlight tabbable"
michael@0 179 label="&highlightAll.label;"
michael@0 180 accesskey="&highlightAll.accesskey;"
michael@0 181 tooltiptext="&highlightAll.tooltiptext;"
michael@0 182 oncommand="toggleHighlight(this.checked);"
michael@0 183 type="checkbox"
michael@0 184 xbl:inherits="accesskey=highlightaccesskey"/>
michael@0 185 <xul:toolbarbutton anonid="find-case-sensitive"
michael@0 186 class="findbar-case-sensitive tabbable"
michael@0 187 label="&caseSensitive.label;"
michael@0 188 accesskey="&caseSensitive.accesskey;"
michael@0 189 tooltiptext="&caseSensitive.tooltiptext;"
michael@0 190 oncommand="_setCaseSensitivity(this.checked);"
michael@0 191 type="checkbox"
michael@0 192 xbl:inherits="accesskey=matchcaseaccesskey"/>
michael@0 193 <xul:label anonid="match-case-status" class="findbar-find-fast"/>
michael@0 194 <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/>
michael@0 195 <xul:description anonid="find-status"
michael@0 196 control="findbar-textbox"
michael@0 197 class="findbar-find-fast findbar-find-status">
michael@0 198 <!-- Do not use value, first child is used because it provides a11y with text change events -->
michael@0 199 </xul:description>
michael@0 200 </xul:hbox>
michael@0 201 <xul:toolbarbutton anonid="find-closebutton"
michael@0 202 class="findbar-closebutton close-icon"
michael@0 203 tooltiptext="&findCloseButton.tooltip;"
michael@0 204 oncommand="close();"/>
michael@0 205 </content>
michael@0 206
michael@0 207 <implementation implements="nsIDOMEventListener, nsIEditActionListener">
michael@0 208 <field name="FIND_NORMAL">0</field>
michael@0 209 <field name="FIND_TYPEAHEAD">1</field>
michael@0 210 <field name="FIND_LINKS">2</field>
michael@0 211
michael@0 212 <field name="_findMode">0</field>
michael@0 213
michael@0 214 <field name="_flashFindBar">0</field>
michael@0 215 <field name="_initialFlashFindBarCount">6</field>
michael@0 216
michael@0 217 <property name="prefillWithSelection"
michael@0 218 onget="return this.getAttribute('prefillwithselection') != 'false'"
michael@0 219 onset="this.setAttribute('prefillwithselection', val); return val;"/>
michael@0 220 <field name="_selectionMaxLen">150</field>
michael@0 221
michael@0 222 <method name="getElement">
michael@0 223 <parameter name="aAnonymousID"/>
michael@0 224 <body><![CDATA[
michael@0 225 return document.getAnonymousElementByAttribute(this,
michael@0 226 "anonid",
michael@0 227 aAnonymousID)
michael@0 228 ]]></body>
michael@0 229 </method>
michael@0 230
michael@0 231 <property name="findMode"
michael@0 232 readonly="true"
michael@0 233 onget="return this._findMode;"/>
michael@0 234
michael@0 235 <property name="canClear" readonly="true">
michael@0 236 <getter><![CDATA[
michael@0 237 if (this._findField.value)
michael@0 238 return true;
michael@0 239
michael@0 240 // Watch out for lazy editor init
michael@0 241 if (this._findField.editor) {
michael@0 242 let tm = this._findField.editor.transactionManager;
michael@0 243 return !!(tm.numberOfUndoItems || tm.numberOfRedoItems);
michael@0 244 }
michael@0 245 return false;
michael@0 246 ]]></getter>
michael@0 247 </property>
michael@0 248
michael@0 249 <field name="_browser">null</field>
michael@0 250 <property name="browser">
michael@0 251 <getter><![CDATA[
michael@0 252 if (!this._browser) {
michael@0 253 this._browser =
michael@0 254 document.getElementById(this.getAttribute("browserid"));
michael@0 255 }
michael@0 256 return this._browser;
michael@0 257 ]]></getter>
michael@0 258 <setter><![CDATA[
michael@0 259 if (this._browser) {
michael@0 260 this._browser.removeEventListener("keypress", this, false);
michael@0 261 this._browser.removeEventListener("mouseup", this, false);
michael@0 262 let finder = this._browser.finder;
michael@0 263 if (finder)
michael@0 264 finder.removeResultListener(this);
michael@0 265 }
michael@0 266
michael@0 267 this._browser = val;
michael@0 268 if (this._browser) {
michael@0 269 this._browser.addEventListener("keypress", this, false);
michael@0 270 this._browser.addEventListener("mouseup", this, false);
michael@0 271 this._browser.finder.addResultListener(this);
michael@0 272
michael@0 273 this._findField.value = this._browser._lastSearchString;
michael@0 274 this.toggleHighlight(this.browser._lastSearchHighlight);
michael@0 275 }
michael@0 276 return val;
michael@0 277 ]]></setter>
michael@0 278 </property>
michael@0 279
michael@0 280 <field name="_observer"><![CDATA[({
michael@0 281 _self: this,
michael@0 282
michael@0 283 QueryInterface: function(aIID) {
michael@0 284 if (aIID.equals(Components.interfaces.nsIObserver) ||
michael@0 285 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
michael@0 286 aIID.equals(Components.interfaces.nsISupports))
michael@0 287 return this;
michael@0 288
michael@0 289 throw Components.results.NS_ERROR_NO_INTERFACE;
michael@0 290 },
michael@0 291
michael@0 292 observe: function(aSubject, aTopic, aPrefName) {
michael@0 293 if (aTopic != "nsPref:changed")
michael@0 294 return;
michael@0 295
michael@0 296 let prefsvc =
michael@0 297 aSubject.QueryInterface(Components.interfaces.nsIPrefBranch);
michael@0 298
michael@0 299 switch (aPrefName) {
michael@0 300 case "accessibility.typeaheadfind":
michael@0 301 this._self._useTypeAheadFind = prefsvc.getBoolPref(aPrefName);
michael@0 302 break;
michael@0 303 case "accessibility.typeaheadfind.linksonly":
michael@0 304 this._self._typeAheadLinksOnly = prefsvc.getBoolPref(aPrefName);
michael@0 305 break;
michael@0 306 case "accessibility.typeaheadfind.casesensitive":
michael@0 307 this._self._typeAheadCaseSensitive = prefsvc.getIntPref(aPrefName);
michael@0 308 this._self._updateCaseSensitivity();
michael@0 309 if (this._self.getElement("highlight").checked)
michael@0 310 this._self._setHighlightTimeout();
michael@0 311 break;
michael@0 312 }
michael@0 313 }
michael@0 314 })]]></field>
michael@0 315
michael@0 316 <field name="_destroyed">false</field>
michael@0 317
michael@0 318 <constructor><![CDATA[
michael@0 319 // These elements are accessed frequently and are therefore cached
michael@0 320 this._findField = this.getElement("findbar-textbox");
michael@0 321 this._findStatusIcon = this.getElement("find-status-icon");
michael@0 322 this._findStatusDesc = this.getElement("find-status");
michael@0 323
michael@0 324 this._foundURL = null;
michael@0 325
michael@0 326 let prefsvc =
michael@0 327 Components.classes["@mozilla.org/preferences-service;1"]
michael@0 328 .getService(Components.interfaces.nsIPrefBranch);
michael@0 329
michael@0 330 this._quickFindTimeoutLength =
michael@0 331 prefsvc.getIntPref("accessibility.typeaheadfind.timeout");
michael@0 332 this._flashFindBar =
michael@0 333 prefsvc.getIntPref("accessibility.typeaheadfind.flashBar");
michael@0 334
michael@0 335 prefsvc.addObserver("accessibility.typeaheadfind",
michael@0 336 this._observer, false);
michael@0 337 prefsvc.addObserver("accessibility.typeaheadfind.linksonly",
michael@0 338 this._observer, false);
michael@0 339 prefsvc.addObserver("accessibility.typeaheadfind.casesensitive",
michael@0 340 this._observer, false);
michael@0 341
michael@0 342 this._useTypeAheadFind =
michael@0 343 prefsvc.getBoolPref("accessibility.typeaheadfind");
michael@0 344 this._typeAheadLinksOnly =
michael@0 345 prefsvc.getBoolPref("accessibility.typeaheadfind.linksonly");
michael@0 346 this._typeAheadCaseSensitive =
michael@0 347 prefsvc.getIntPref("accessibility.typeaheadfind.casesensitive");
michael@0 348
michael@0 349 // Convenience
michael@0 350 this.nsITypeAheadFind = Components.interfaces.nsITypeAheadFind;
michael@0 351 this.nsISelectionController = Components.interfaces.nsISelectionController;
michael@0 352 this._findSelection = this.nsISelectionController.SELECTION_FIND;
michael@0 353
michael@0 354 this._findResetTimeout = -1;
michael@0 355
michael@0 356 // Make sure the FAYT keypress listener is attached by initializing the
michael@0 357 // browser property
michael@0 358 if (this.getAttribute("browserid"))
michael@0 359 setTimeout(function(aSelf) { aSelf.browser = aSelf.browser; }, 0, this);
michael@0 360 ]]></constructor>
michael@0 361
michael@0 362 <destructor><![CDATA[
michael@0 363 this.destroy();
michael@0 364 ]]></destructor>
michael@0 365
michael@0 366 <!-- This is necessary because the destructor isn't called when
michael@0 367 we are removed from a document that is not destroyed. This
michael@0 368 needs to be explicitly called in this case -->
michael@0 369 <method name="destroy">
michael@0 370 <body><![CDATA[
michael@0 371 if (this._destroyed)
michael@0 372 return;
michael@0 373 this._destroyed = true;
michael@0 374
michael@0 375 this.browser = null;
michael@0 376
michael@0 377 let prefsvc =
michael@0 378 Components.classes["@mozilla.org/preferences-service;1"]
michael@0 379 .getService(Components.interfaces.nsIPrefBranch);
michael@0 380 prefsvc.removeObserver("accessibility.typeaheadfind",
michael@0 381 this._observer);
michael@0 382 prefsvc.removeObserver("accessibility.typeaheadfind.linksonly",
michael@0 383 this._observer);
michael@0 384 prefsvc.removeObserver("accessibility.typeaheadfind.casesensitive",
michael@0 385 this._observer);
michael@0 386
michael@0 387 // Clear all timers that might still be running.
michael@0 388 this._cancelTimers();
michael@0 389 ]]></body>
michael@0 390 </method>
michael@0 391
michael@0 392 <method name="_cancelTimers">
michael@0 393 <body><![CDATA[
michael@0 394 if (this._flashFindBarTimeout) {
michael@0 395 clearInterval(this._flashFindBarTimeout);
michael@0 396 this._flashFindBarTimeout = null;
michael@0 397 }
michael@0 398 if (this._quickFindTimeout) {
michael@0 399 clearTimeout(this._quickFindTimeout);
michael@0 400 this._quickFindTimeout = null;
michael@0 401 }
michael@0 402 if (this._highlightTimeout) {
michael@0 403 clearTimeout(this._highlightTimeout);
michael@0 404 this._highlightTimeout = null;
michael@0 405 }
michael@0 406 if (this._findResetTimeout) {
michael@0 407 clearTimeout(this._findResetTimeout);
michael@0 408 this._findResetTimeout = null;
michael@0 409 }
michael@0 410 ]]></body>
michael@0 411 </method>
michael@0 412
michael@0 413 <method name="_setFindCloseTimeout">
michael@0 414 <body><![CDATA[
michael@0 415 if (this._quickFindTimeout)
michael@0 416 clearTimeout(this._quickFindTimeout);
michael@0 417
michael@0 418 // Don't close the find toolbar while IME is composing OR when the
michael@0 419 // findbar is already hidden.
michael@0 420 if (this._isIMEComposing || this.hidden) {
michael@0 421 this._quickFindTimeout = null;
michael@0 422 return;
michael@0 423 }
michael@0 424
michael@0 425 this._quickFindTimeout = setTimeout(() => {
michael@0 426 if (this._findMode != this.FIND_NORMAL)
michael@0 427 this.close();
michael@0 428 this._quickFindTimeout = null;
michael@0 429 }, this._quickFindTimeoutLength);
michael@0 430 ]]></body>
michael@0 431 </method>
michael@0 432
michael@0 433 <!--
michael@0 434 - Turns highlight on or off.
michael@0 435 - @param aHighlight (boolean)
michael@0 436 - Whether to turn the highlight on or off
michael@0 437 -->
michael@0 438 <method name="toggleHighlight">
michael@0 439 <parameter name="aHighlight"/>
michael@0 440 <body><![CDATA[
michael@0 441 if (!this._dispatchFindEvent("highlightallchange"))
michael@0 442 return;
michael@0 443
michael@0 444 let word = this._findField.value;
michael@0 445 // Bug 429723. Don't attempt to highlight ""
michael@0 446 if (aHighlight && !word)
michael@0 447 return;
michael@0 448
michael@0 449 this.browser._lastSearchHighlight = aHighlight;
michael@0 450 this.browser.finder.highlight(aHighlight, word);
michael@0 451 ]]></body>
michael@0 452 </method>
michael@0 453
michael@0 454 <!--
michael@0 455 - Updates the case-sensitivity mode of the findbar and its UI.
michael@0 456 - @param [optional] aString
michael@0 457 - The string for which case sensitivity might be turned on.
michael@0 458 - This only used when case-sensitivity is in auto mode,
michael@0 459 - @see _shouldBeCaseSensitive. The default value for this
michael@0 460 - parameter is the find-field value.
michael@0 461 -->
michael@0 462 <method name="_updateCaseSensitivity">
michael@0 463 <parameter name="aString"/>
michael@0 464 <body><![CDATA[
michael@0 465 let val = aString || this._findField.value;
michael@0 466
michael@0 467 let caseSensitive = this._shouldBeCaseSensitive(val);
michael@0 468 let checkbox = this.getElement("find-case-sensitive");
michael@0 469 let statusLabel = this.getElement("match-case-status");
michael@0 470 checkbox.checked = caseSensitive;
michael@0 471
michael@0 472 statusLabel.value = caseSensitive ? this._caseSensitiveStr : "";
michael@0 473
michael@0 474 // Show the checkbox on the full Find bar in non-auto mode.
michael@0 475 // Show the label in all other cases.
michael@0 476 let hideCheckbox = this._findMode != this.FIND_NORMAL ||
michael@0 477 (this._typeAheadCaseSensitive != 0 &&
michael@0 478 this._typeAheadCaseSensitive != 1);
michael@0 479 checkbox.hidden = hideCheckbox;
michael@0 480 statusLabel.hidden = !hideCheckbox;
michael@0 481
michael@0 482 this.browser.finder.caseSensitive = caseSensitive;
michael@0 483 ]]></body>
michael@0 484 </method>
michael@0 485
michael@0 486 <!--
michael@0 487 - Sets the findbar case-sensitivity mode
michael@0 488 - @param aCaseSensitive (boolean)
michael@0 489 - Whether or not case-sensitivity should be turned on.
michael@0 490 -->
michael@0 491 <method name="_setCaseSensitivity">
michael@0 492 <parameter name="aCaseSensitive"/>
michael@0 493 <body><![CDATA[
michael@0 494 let prefsvc =
michael@0 495 Components.classes["@mozilla.org/preferences-service;1"]
michael@0 496 .getService(Components.interfaces.nsIPrefBranch);
michael@0 497
michael@0 498 // Just set the pref; our observer will change the find bar behavior
michael@0 499 prefsvc.setIntPref("accessibility.typeaheadfind.casesensitive",
michael@0 500 aCaseSensitive ? 1 : 0);
michael@0 501
michael@0 502 this._dispatchFindEvent("casesensitivitychange");
michael@0 503 ]]></body>
michael@0 504 </method>
michael@0 505
michael@0 506 <!--
michael@0 507 - Opens and displays the find bar.
michael@0 508 -
michael@0 509 - @param aMode
michael@0 510 - the find mode to be used, which is either FIND_NORMAL,
michael@0 511 - FIND_TYPEAHEAD or FIND_LINKS. If not passed, the last
michael@0 512 - find mode if any or FIND_NORMAL.
michael@0 513 - @returns true if the find bar wasn't previously open, false otherwise.
michael@0 514 -->
michael@0 515 <method name="open">
michael@0 516 <parameter name="aMode"/>
michael@0 517 <body><![CDATA[
michael@0 518 if (aMode != undefined)
michael@0 519 this._findMode = aMode;
michael@0 520
michael@0 521 if (!this._notFoundStr) {
michael@0 522 let stringsBundle =
michael@0 523 Components.classes["@mozilla.org/intl/stringbundle;1"]
michael@0 524 .getService(Components.interfaces.nsIStringBundleService)
michael@0 525 .createBundle("chrome://global/locale/findbar.properties");
michael@0 526 this._notFoundStr = stringsBundle.GetStringFromName("NotFound");
michael@0 527 this._wrappedToTopStr =
michael@0 528 stringsBundle.GetStringFromName("WrappedToTop");
michael@0 529 this._wrappedToBottomStr =
michael@0 530 stringsBundle.GetStringFromName("WrappedToBottom");
michael@0 531 this._normalFindStr =
michael@0 532 stringsBundle.GetStringFromName("NormalFind");
michael@0 533 this._fastFindStr =
michael@0 534 stringsBundle.GetStringFromName("FastFind");
michael@0 535 this._fastFindLinksStr =
michael@0 536 stringsBundle.GetStringFromName("FastFindLinks");
michael@0 537 this._caseSensitiveStr =
michael@0 538 stringsBundle.GetStringFromName("CaseSensitive");
michael@0 539 }
michael@0 540
michael@0 541 this._findFailedString = null;
michael@0 542
michael@0 543 this._updateFindUI();
michael@0 544 if (this.hidden) {
michael@0 545 this.hidden = false;
michael@0 546
michael@0 547 this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
michael@0 548
michael@0 549 let event = document.createEvent("Events");
michael@0 550 event.initEvent("findbaropen", true, false);
michael@0 551 this.dispatchEvent(event);
michael@0 552
michael@0 553 return true;
michael@0 554 }
michael@0 555 return false;
michael@0 556 ]]></body>
michael@0 557 </method>
michael@0 558
michael@0 559 <!--
michael@0 560 - Closes the findbar.
michael@0 561 -->
michael@0 562 <method name="close">
michael@0 563 <body><![CDATA[
michael@0 564 if (this.hidden)
michael@0 565 return;
michael@0 566
michael@0 567 this.hidden = true;
michael@0 568
michael@0 569 this.browser.finder.focusContent();
michael@0 570 this.browser.finder.enableSelection();
michael@0 571 this._findField.blur();
michael@0 572
michael@0 573 this._cancelTimers();
michael@0 574
michael@0 575 this._findFailedString = null;
michael@0 576 ]]></body>
michael@0 577 </method>
michael@0 578
michael@0 579 <method name="clear">
michael@0 580 <body><![CDATA[
michael@0 581 this.browser.finder.removeSelection();
michael@0 582 this._findField.reset();
michael@0 583 this.toggleHighlight(false);
michael@0 584 this._updateStatusUI();
michael@0 585 this._enableFindButtons(false);
michael@0 586 ]]></body>
michael@0 587 </method>
michael@0 588
michael@0 589 <method name="_dispatchKeypressEvent">
michael@0 590 <parameter name="aTarget"/>
michael@0 591 <parameter name="aEvent"/>
michael@0 592 <body><![CDATA[
michael@0 593 if (!aTarget)
michael@0 594 return;
michael@0 595
michael@0 596 let event = document.createEvent("KeyEvents");
michael@0 597 event.initKeyEvent(aEvent.type, aEvent.bubbles, aEvent.cancelable,
michael@0 598 aEvent.view, aEvent.ctrlKey, aEvent.altKey,
michael@0 599 aEvent.shiftKey, aEvent.metaKey, aEvent.keyCode,
michael@0 600 aEvent.charCode);
michael@0 601 aTarget.dispatchEvent(event);
michael@0 602 ]]></body>
michael@0 603 </method>
michael@0 604
michael@0 605 <field name="_xulBrowserWindow">null</field>
michael@0 606 <method name="_updateStatusUIBar">
michael@0 607 <parameter name="aFoundURL"/>
michael@0 608 <body><![CDATA[
michael@0 609 if (!this._xulBrowserWindow) {
michael@0 610 try {
michael@0 611 this._xulBrowserWindow =
michael@0 612 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
michael@0 613 .getInterface(Components.interfaces.nsIWebNavigation)
michael@0 614 .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
michael@0 615 .treeOwner
michael@0 616 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
michael@0 617 .getInterface(Components.interfaces.nsIXULWindow)
michael@0 618 .XULBrowserWindow;
michael@0 619 }
michael@0 620 catch(ex) { }
michael@0 621 if (!this._xulBrowserWindow)
michael@0 622 return false;
michael@0 623 }
michael@0 624
michael@0 625 // Call this has the same effect like hovering over link,
michael@0 626 // the browser shows the URL as a tooltip.
michael@0 627 this._xulBrowserWindow.setOverLink(aFoundURL || "", null);
michael@0 628 return true;
michael@0 629 ]]></body>
michael@0 630 </method>
michael@0 631
michael@0 632 <method name="_finishFAYT">
michael@0 633 <parameter name="aKeypressEvent"/>
michael@0 634 <body><![CDATA[
michael@0 635 this.browser.finder.focusContent();
michael@0 636
michael@0 637 if (aKeypressEvent)
michael@0 638 aKeypressEvent.preventDefault();
michael@0 639
michael@0 640 this.browser.finder.keyPress(aKeypressEvent);
michael@0 641
michael@0 642 this.close();
michael@0 643 return true;
michael@0 644 ]]></body>
michael@0 645 </method>
michael@0 646
michael@0 647 <!--
michael@0 648 - Returns true if |aMimeType| is text-based, or false otherwise.
michael@0 649 -
michael@0 650 - @param aMimeType
michael@0 651 - The MIME type to check.
michael@0 652 -
michael@0 653 - if adding types to this function, please see the similar function
michael@0 654 - in browser/base/content/browser.js
michael@0 655 -->
michael@0 656 <method name="_mimeTypeIsTextBased">
michael@0 657 <parameter name="aMimeType"/>
michael@0 658 <body><![CDATA[
michael@0 659 return /^text\/|\+xml$/.test(aMimeType) ||
michael@0 660 aMimeType == "application/x-javascript" ||
michael@0 661 aMimeType == "application/javascript" ||
michael@0 662 aMimeType == "application/json" ||
michael@0 663 aMimeType == "application/xml";
michael@0 664 ]]></body>
michael@0 665 </method>
michael@0 666
michael@0 667 <!--
michael@0 668 - Returns whether FAYT can be used for the given event in
michael@0 669 - the current content state.
michael@0 670 -->
michael@0 671 <method name="_shouldFastFind">
michael@0 672 <parameter name="aEvent"/>
michael@0 673 <body><![CDATA[
michael@0 674 if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey ||
michael@0 675 aEvent.defaultPrevented)
michael@0 676 return false;
michael@0 677
michael@0 678 let {BrowserUtils} = Components.utils.import("resource://gre/modules/BrowserUtils.jsm", {});
michael@0 679 let [elt, win] = BrowserUtils.getFocusSync(document);
michael@0 680
michael@0 681 if (elt) {
michael@0 682 if (elt instanceof HTMLInputElement && elt.mozIsTextField(false))
michael@0 683 return false;
michael@0 684
michael@0 685 if (elt.isContentEditable)
michael@0 686 return false;
michael@0 687
michael@0 688 if (elt instanceof HTMLTextAreaElement ||
michael@0 689 elt instanceof HTMLSelectElement ||
michael@0 690 elt instanceof HTMLObjectElement ||
michael@0 691 elt instanceof HTMLEmbedElement)
michael@0 692 return false;
michael@0 693 }
michael@0 694
michael@0 695 if (win && !this._mimeTypeIsTextBased(win.document.contentType))
michael@0 696 return false;
michael@0 697
michael@0 698 // disable FAYT in about:blank to prevent FAYT opening unexpectedly.
michael@0 699 let url = this.browser.currentURI;
michael@0 700 if (url.spec == "about:blank")
michael@0 701 return false;
michael@0 702
michael@0 703 // disable FAYT in documents that ask for it to be disabled.
michael@0 704 if ((url.schemeIs("about") || url.schemeIs("chrome")) &&
michael@0 705 (win.document.documentElement &&
michael@0 706 win.document.documentElement.getAttribute("disablefastfind") == "true"))
michael@0 707 return false;
michael@0 708
michael@0 709 if (win) {
michael@0 710 try {
michael@0 711 let editingSession = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
michael@0 712 .getInterface(Components.interfaces.nsIWebNavigation)
michael@0 713 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
michael@0 714 .getInterface(Components.interfaces.nsIEditingSession);
michael@0 715 if (editingSession.windowIsEditable(win))
michael@0 716 return false;
michael@0 717 }
michael@0 718 catch (e) {
michael@0 719 // If someone built with composer disabled, we can't get an editing session.
michael@0 720 }
michael@0 721 }
michael@0 722
michael@0 723 return true;
michael@0 724 ]]></body>
michael@0 725 </method>
michael@0 726
michael@0 727 <method name="_shouldBeCaseSensitive">
michael@0 728 <parameter name="aString"/>
michael@0 729 <body><![CDATA[
michael@0 730 if (this._typeAheadCaseSensitive == 0)
michael@0 731 return false;
michael@0 732 if (this._typeAheadCaseSensitive == 1)
michael@0 733 return true;
michael@0 734
michael@0 735 return aString != aString.toLowerCase();
michael@0 736 ]]></body>
michael@0 737 </method>
michael@0 738
michael@0 739 <method name="_onBrowserKeypress">
michael@0 740 <parameter name="aEvent"/>
michael@0 741 <body><![CDATA[
michael@0 742 const TAF_LINKS_KEY = "'";
michael@0 743 const TAF_TEXT_KEY = "/";
michael@0 744
michael@0 745 if (!this._shouldFastFind(aEvent))
michael@0 746 return;
michael@0 747
michael@0 748 if (this._findMode != this.FIND_NORMAL && this._quickFindTimeout) {
michael@0 749 if (!aEvent.charCode)
michael@0 750 return;
michael@0 751
michael@0 752 this._findField.select();
michael@0 753 this._findField.focus();
michael@0 754 this._dispatchKeypressEvent(this._findField.inputField, aEvent);
michael@0 755 aEvent.preventDefault();
michael@0 756 return;
michael@0 757 }
michael@0 758
michael@0 759 let key = aEvent.charCode ? String.fromCharCode(aEvent.charCode) : null;
michael@0 760 let manualstartFAYT = (key == TAF_LINKS_KEY || key == TAF_TEXT_KEY);
michael@0 761 let autostartFAYT = !manualstartFAYT && this._useTypeAheadFind &&
michael@0 762 key && key != " ";
michael@0 763 if (manualstartFAYT || autostartFAYT) {
michael@0 764 let mode = (key == TAF_LINKS_KEY ||
michael@0 765 (autostartFAYT && this._typeAheadLinksOnly)) ?
michael@0 766 this.FIND_LINKS : this.FIND_TYPEAHEAD;
michael@0 767
michael@0 768 // Clear bar first, so that when openFindBar() calls setCaseSensitivity()
michael@0 769 // it doesn't get confused by a lingering value
michael@0 770 this._findField.value = "";
michael@0 771
michael@0 772 this.open(mode);
michael@0 773 this._setFindCloseTimeout();
michael@0 774 this._findField.select();
michael@0 775 this._findField.focus();
michael@0 776
michael@0 777 if (autostartFAYT)
michael@0 778 this._dispatchKeypressEvent(this._findField.inputField, aEvent);
michael@0 779 else
michael@0 780 this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
michael@0 781
michael@0 782 aEvent.preventDefault();
michael@0 783 }
michael@0 784 ]]></body>
michael@0 785 </method>
michael@0 786
michael@0 787 <!-- See nsIDOMEventListener -->
michael@0 788 <method name="handleEvent">
michael@0 789 <parameter name="aEvent"/>
michael@0 790 <body><![CDATA[
michael@0 791 switch (aEvent.type) {
michael@0 792 case "mouseup":
michael@0 793 if (!this.hidden && this._findMode != this.FIND_NORMAL)
michael@0 794 this.close();
michael@0 795
michael@0 796 break;
michael@0 797 case "keypress":
michael@0 798 this._onBrowserKeypress(aEvent);
michael@0 799 break;
michael@0 800 }
michael@0 801 ]]></body>
michael@0 802 </method>
michael@0 803
michael@0 804 <method name="_enableFindButtons">
michael@0 805 <parameter name="aEnable"/>
michael@0 806 <body><![CDATA[
michael@0 807 this.getElement("find-next").disabled =
michael@0 808 this.getElement("find-previous").disabled = !aEnable;
michael@0 809 ]]></body>
michael@0 810 </method>
michael@0 811
michael@0 812 <!--
michael@0 813 - Determines whether minimalist or general-purpose search UI is to be
michael@0 814 - displayed when the find bar is activated.
michael@0 815 -->
michael@0 816 <method name="_updateFindUI">
michael@0 817 <body><![CDATA[
michael@0 818 let showMinimalUI = this._findMode != this.FIND_NORMAL;
michael@0 819
michael@0 820 let nodes = this.getElement("findbar-container").childNodes;
michael@0 821 let wrapper = this.getElement("findbar-textbox-wrapper");
michael@0 822 for (let node of nodes) {
michael@0 823 if (node == wrapper)
michael@0 824 continue;
michael@0 825 node.hidden = showMinimalUI;
michael@0 826 }
michael@0 827 this.getElement("find-next").hidden =
michael@0 828 this.getElement("find-previous").hidden = showMinimalUI;
michael@0 829 this._updateCaseSensitivity();
michael@0 830
michael@0 831 if (showMinimalUI)
michael@0 832 this._findField.classList.add("minimal");
michael@0 833 else
michael@0 834 this._findField.classList.remove("minimal");
michael@0 835
michael@0 836 if (this._findMode == this.FIND_TYPEAHEAD)
michael@0 837 this._findField.placeholder = this._fastFindStr;
michael@0 838 else if (this._findMode == this.FIND_LINKS)
michael@0 839 this._findField.placeholder = this._fastFindLinksStr;
michael@0 840 else
michael@0 841 this._findField.placeholder = this._normalFindStr;
michael@0 842 ]]></body>
michael@0 843 </method>
michael@0 844
michael@0 845 <method name="_find">
michael@0 846 <parameter name="aValue"/>
michael@0 847 <body><![CDATA[
michael@0 848 if (!this._dispatchFindEvent(""))
michael@0 849 return;
michael@0 850
michael@0 851 let val = aValue || this._findField.value;
michael@0 852
michael@0 853 // We have to carry around an explicit version of this,
michael@0 854 // because finder.searchString doesn't update on failed
michael@0 855 // searches.
michael@0 856 this.browser._lastSearchString = val;
michael@0 857
michael@0 858 // Only search on input if we don't have a last-failed string,
michael@0 859 // or if the current search string doesn't start with it.
michael@0 860 if (!this._findFailedString ||
michael@0 861 !val.startsWith(this._findFailedString))
michael@0 862 {
michael@0 863 this._enableFindButtons(val);
michael@0 864 if (this.getElement("highlight").checked)
michael@0 865 this._setHighlightTimeout();
michael@0 866
michael@0 867 this._updateCaseSensitivity(val);
michael@0 868
michael@0 869 this.browser.finder.fastFind(val, this._findMode == this.FIND_LINKS,
michael@0 870 this._findMode != this.FIND_NORMAL);
michael@0 871 }
michael@0 872
michael@0 873 if (this._findMode != this.FIND_NORMAL)
michael@0 874 this._setFindCloseTimeout();
michael@0 875
michael@0 876 if (this._findResetTimeout != -1)
michael@0 877 clearTimeout(this._findResetTimeout);
michael@0 878
michael@0 879 // allow a search to happen on input again after a second has
michael@0 880 // expired since the previous input, to allow for dynamic
michael@0 881 // content and/or page loading
michael@0 882 this._findResetTimeout = setTimeout(() => {
michael@0 883 this._findFailedString = null;
michael@0 884 this._findResetTimeout = -1;
michael@0 885 }, 1000);
michael@0 886 ]]></body>
michael@0 887 </method>
michael@0 888
michael@0 889 <method name="_flash">
michael@0 890 <body><![CDATA[
michael@0 891 if (this._flashFindBarCount === undefined)
michael@0 892 this._flashFindBarCount = this._initialFlashFindBarCount;
michael@0 893
michael@0 894 if (this._flashFindBarCount-- == 0) {
michael@0 895 clearInterval(this._flashFindBarTimeout);
michael@0 896 this.removeAttribute("flash");
michael@0 897 this._flashFindBarCount = 6;
michael@0 898 return;
michael@0 899 }
michael@0 900
michael@0 901 this.setAttribute("flash",
michael@0 902 (this._flashFindBarCount % 2 == 0) ?
michael@0 903 "false" : "true");
michael@0 904 ]]></body>
michael@0 905 </method>
michael@0 906
michael@0 907 <method name="_setHighlightTimeout">
michael@0 908 <body><![CDATA[
michael@0 909 if (this._highlightTimeout)
michael@0 910 clearTimeout(this._highlightTimeout);
michael@0 911 this._highlightTimeout =
michael@0 912 setTimeout(function(aSelf) {
michael@0 913 aSelf.toggleHighlight(false);
michael@0 914 aSelf.toggleHighlight(true);
michael@0 915 }, 500, this);
michael@0 916 ]]></body>
michael@0 917 </method>
michael@0 918
michael@0 919 <method name="_findAgain">
michael@0 920 <parameter name="aFindPrevious"/>
michael@0 921 <body><![CDATA[
michael@0 922 this.browser.finder.findAgain(aFindPrevious,
michael@0 923 this._findMode == this.FIND_LINKS,
michael@0 924 this._findMode != this.FIND_NORMAL);
michael@0 925 ]]></body>
michael@0 926 </method>
michael@0 927
michael@0 928 <method name="_updateStatusUI">
michael@0 929 <parameter name="res"/>
michael@0 930 <parameter name="aFindPrevious"/>
michael@0 931 <body><![CDATA[
michael@0 932 switch (res) {
michael@0 933 case this.nsITypeAheadFind.FIND_WRAPPED:
michael@0 934 this._findStatusIcon.setAttribute("status", "wrapped");
michael@0 935 this._findStatusDesc.textContent =
michael@0 936 aFindPrevious ? this._wrappedToBottomStr : this._wrappedToTopStr;
michael@0 937 this._findField.removeAttribute("status");
michael@0 938 break;
michael@0 939 case this.nsITypeAheadFind.FIND_NOTFOUND:
michael@0 940 this._findStatusIcon.setAttribute("status", "notfound");
michael@0 941 this._findStatusDesc.textContent = this._notFoundStr;
michael@0 942 this._findField.setAttribute("status", "notfound");
michael@0 943 break;
michael@0 944 case this.nsITypeAheadFind.FIND_PENDING:
michael@0 945 this._findStatusIcon.setAttribute("status", "pending");
michael@0 946 this._findStatusDesc.textContent = "";
michael@0 947 this._findField.removeAttribute("status");
michael@0 948 break;
michael@0 949 case this.nsITypeAheadFind.FIND_FOUND:
michael@0 950 default:
michael@0 951 this._findStatusIcon.removeAttribute("status");
michael@0 952 this._findStatusDesc.textContent = "";
michael@0 953 this._findField.removeAttribute("status");
michael@0 954 break;
michael@0 955 }
michael@0 956 ]]></body>
michael@0 957 </method>
michael@0 958
michael@0 959 <method name="updateControlState">
michael@0 960 <parameter name="aResult"/>
michael@0 961 <parameter name="aFindPrevious"/>
michael@0 962 <body><![CDATA[
michael@0 963 this._updateStatusUI(aResult, aFindPrevious);
michael@0 964 this._enableFindButtons(aResult !== this.nsITypeAheadFind.FIND_NOTFOUND);
michael@0 965 ]]></body>
michael@0 966 </method>
michael@0 967
michael@0 968 <method name="_getInitialSelection">
michael@0 969 <body><![CDATA[
michael@0 970 let focusedElement = document.commandDispatcher.focusedElement;
michael@0 971 let selText;
michael@0 972
michael@0 973 if (focusedElement instanceof Components.interfaces.nsIDOMNSEditableElement &&
michael@0 974 focusedElement.editor &&
michael@0 975 focusedElement.ownerDocument.defaultView.top == this._browser.contentWindow)
michael@0 976 {
michael@0 977 // The user may have a selection in an input or textarea
michael@0 978 selText = focusedElement.editor.selectionController
michael@0 979 .getSelection(Components.interfaces.nsISelectionController.SELECTION_NORMAL)
michael@0 980 .toString();
michael@0 981 }
michael@0 982 else {
michael@0 983 // Look for any selected text on the actual page
michael@0 984 let focusedWindow = document.commandDispatcher.focusedWindow;
michael@0 985 if (focusedWindow.top == this._browser.contentWindow)
michael@0 986 selText = focusedWindow.getSelection().toString();
michael@0 987 }
michael@0 988
michael@0 989 if (!selText)
michael@0 990 return "";
michael@0 991
michael@0 992 // Process our text to get rid of unwanted characters
michael@0 993 if (selText.length > this._selectionMaxLen) {
michael@0 994 let pattern = new RegExp("^(?:\\s*.){0," + this._selectionMaxLen + "}");
michael@0 995 pattern.test(selText);
michael@0 996 selText = RegExp.lastMatch;
michael@0 997 }
michael@0 998 return selText.replace(/^\s+/, "")
michael@0 999 .replace(/\s+$/, "")
michael@0 1000 .replace(/\s+/g, " ")
michael@0 1001 .substr(0, this._selectionMaxLen);
michael@0 1002 ]]></body>
michael@0 1003 </method>
michael@0 1004
michael@0 1005 <method name="_dispatchFindEvent">
michael@0 1006 <parameter name="aType"/>
michael@0 1007 <parameter name="aFindPrevious"/>
michael@0 1008 <body><![CDATA[
michael@0 1009 let event = document.createEvent("CustomEvent");
michael@0 1010 event.initCustomEvent("find" + aType, true, true, {
michael@0 1011 query: this._findField.value,
michael@0 1012 caseSensitive: !!this._typeAheadCaseSensitive,
michael@0 1013 highlightAll: this.getElement("highlight").checked,
michael@0 1014 findPrevious: aFindPrevious
michael@0 1015 });
michael@0 1016 return this.dispatchEvent(event);
michael@0 1017 ]]></body>
michael@0 1018 </method>
michael@0 1019
michael@0 1020
michael@0 1021 <!--
michael@0 1022 - Opens the findbar, focuses the findfield and selects its contents.
michael@0 1023 - Also flashes the findbar the first time it's used.
michael@0 1024 - @param aMode
michael@0 1025 - the find mode to be used, which is either FIND_NORMAL,
michael@0 1026 - FIND_TYPEAHEAD or FIND_LINKS. If not passed, the last
michael@0 1027 - find mode if any or FIND_NORMAL.
michael@0 1028 -->
michael@0 1029 <method name="startFind">
michael@0 1030 <parameter name="aMode"/>
michael@0 1031 <body><![CDATA[
michael@0 1032 let prefsvc =
michael@0 1033 Components.classes["@mozilla.org/preferences-service;1"]
michael@0 1034 .getService(Components.interfaces.nsIPrefBranch);
michael@0 1035 let userWantsPrefill = true;
michael@0 1036 this.open(aMode);
michael@0 1037
michael@0 1038 if (this._flashFindBar) {
michael@0 1039 this._flashFindBarTimeout = setInterval(() => this._flash(), 500);
michael@0 1040 prefsvc.setIntPref("accessibility.typeaheadfind.flashBar",
michael@0 1041 --this._flashFindBar);
michael@0 1042 }
michael@0 1043
michael@0 1044 if (this.prefillWithSelection)
michael@0 1045 userWantsPrefill =
michael@0 1046 prefsvc.getBoolPref("accessibility.typeaheadfind.prefillwithselection");
michael@0 1047
michael@0 1048 let initialString = null;
michael@0 1049 if (this.prefillWithSelection && userWantsPrefill)
michael@0 1050 initialString = this._getInitialSelection();
michael@0 1051 #ifdef XP_MACOSX
michael@0 1052 if (!initialString) {
michael@0 1053 let clipboardSearchString = this.browser.finder.clipboardSearchString;
michael@0 1054 if (clipboardSearchString)
michael@0 1055 initialString = clipboardSearchString;
michael@0 1056 }
michael@0 1057 #endif
michael@0 1058
michael@0 1059 if (initialString)
michael@0 1060 this._findField.value = initialString;
michael@0 1061
michael@0 1062 this._enableFindButtons(!!this._findField.value);
michael@0 1063
michael@0 1064 this._findField.select();
michael@0 1065 this._findField.focus();
michael@0 1066 ]]></body>
michael@0 1067 </method>
michael@0 1068
michael@0 1069 <!--
michael@0 1070 - Convenient alias to startFind(gFindBar.FIND_NORMAL);
michael@0 1071 -
michael@0 1072 - You should generally map the window's find command to this method.
michael@0 1073 - e.g. <command name="cmd_find" oncommand="gFindBar.onFindCommand();"/>
michael@0 1074 -->
michael@0 1075 <method name="onFindCommand">
michael@0 1076 <body><![CDATA[
michael@0 1077 this.startFind(this.FIND_NORMAL);
michael@0 1078 ]]></body>
michael@0 1079 </method>
michael@0 1080
michael@0 1081 <!--
michael@0 1082 - Stub for find-next and find-previous commands
michael@0 1083 - @param aFindPrevious
michael@0 1084 - true for find-previous, false otherwise.
michael@0 1085 -->
michael@0 1086 <method name="onFindAgainCommand">
michael@0 1087 <parameter name="aFindPrevious"/>
michael@0 1088 <body><![CDATA[
michael@0 1089 let findString = this._browser.finder.searchString || this._findField.value;
michael@0 1090 if (!findString) {
michael@0 1091 this.startFind();
michael@0 1092 return;
michael@0 1093 }
michael@0 1094
michael@0 1095 // We dispatch the findAgain event here instead of in _findAgain since
michael@0 1096 // if there is a find event handler that prevents the default then
michael@0 1097 // finder.searchString will never get updated which in turn means
michael@0 1098 // there would never be findAgain events because of the logic below.
michael@0 1099 if (!this._dispatchFindEvent("again", aFindPrevious))
michael@0 1100 return;
michael@0 1101
michael@0 1102 // user explicitly requested another search, so do it even if we think it'll fail
michael@0 1103 this._findFailedString = null;
michael@0 1104
michael@0 1105 // Ensure the stored SearchString is in sync with what we want to find
michael@0 1106 if (this._findField.value != this._browser.finder.searchString)
michael@0 1107 this._find(this._findField.value);
michael@0 1108 else
michael@0 1109 this._findAgain(aFindPrevious);
michael@0 1110
michael@0 1111 ]]></body>
michael@0 1112 </method>
michael@0 1113
michael@0 1114 #ifdef XP_MACOSX
michael@0 1115 <!--
michael@0 1116 - Fetches the currently selected text and sets that as the text to search
michael@0 1117 - next. This is a MacOS specific feature.
michael@0 1118 -->
michael@0 1119 <method name="onFindSelectionCommand">
michael@0 1120 <body><![CDATA[
michael@0 1121 let searchString = this.browser.finder.setSearchStringToSelection();
michael@0 1122 if (searchString)
michael@0 1123 this._findField.value = searchString;
michael@0 1124 ]]></body>
michael@0 1125 </method>
michael@0 1126
michael@0 1127 <method name="_onFindFieldFocus">
michael@0 1128 <body><![CDATA[
michael@0 1129 let prefsvc =
michael@0 1130 Components.classes["@mozilla.org/preferences-service;1"]
michael@0 1131 .getService(Components.interfaces.nsIPrefBranch);
michael@0 1132 const kPref = "accessibility.typeaheadfind.prefillwithselection";
michael@0 1133 if (this.prefillWithSelection && prefsvc.getBoolPref(kPref))
michael@0 1134 return;
michael@0 1135
michael@0 1136 let clipboardSearchString = this._browser.finder.clipboardSearchString;
michael@0 1137 if (clipboardSearchString && this._findField.value != clipboardSearchString) {
michael@0 1138 this._findField.value = clipboardSearchString;
michael@0 1139 // Changing the search string makes the previous status invalid, so
michael@0 1140 // we better clear it here.
michael@0 1141 this._updateStatusUI();
michael@0 1142 }
michael@0 1143 ]]></body>
michael@0 1144 </method>
michael@0 1145 #endif
michael@0 1146
michael@0 1147 <!--
michael@0 1148 - This handles all the result changes for both
michael@0 1149 - type-ahead-find and highlighting.
michael@0 1150 - @param aResult
michael@0 1151 - One of the nsITypeAheadFind.FIND_* constants
michael@0 1152 - indicating the result of a search operation.
michael@0 1153 - @param aFindBackwards
michael@0 1154 - If the search was done from the bottom to
michael@0 1155 - the top. This is used for right error messages
michael@0 1156 - when reaching "the end of the page".
michael@0 1157 - @param aLinkURL
michael@0 1158 - When a link matched then its URK. Always null
michael@0 1159 - when not in FIND_LINKS mode.
michael@0 1160 -->
michael@0 1161 <method name="onFindResult">
michael@0 1162 <parameter name="aData"/>
michael@0 1163 <body><![CDATA[
michael@0 1164 if (aData.storeResult && this._findField.value != this.browser.finder.searchString)
michael@0 1165 this._findField.value = this.browser.finder.searchString;
michael@0 1166 this._updateStatusUI(aData.result, aData.findBackwards);
michael@0 1167 this._updateStatusUIBar(aData.linkURL);
michael@0 1168
michael@0 1169 if (aData.result == this.nsITypeAheadFind.FIND_NOTFOUND)
michael@0 1170 this._findFailedString = aData.searchString;
michael@0 1171 else
michael@0 1172 this._findFailedString = null;
michael@0 1173
michael@0 1174 if (this._findMode != this.FIND_NORMAL)
michael@0 1175 this._setFindCloseTimeout();
michael@0 1176 ]]></body>
michael@0 1177 </method>
michael@0 1178
michael@0 1179 <!--
michael@0 1180 - This handler may cancel a request to focus content by returning |false|
michael@0 1181 - explicitly.
michael@0 1182 -->
michael@0 1183 <method name="shouldFocusContent">
michael@0 1184 <body><![CDATA[
michael@0 1185 const fm = Components.classes["@mozilla.org/focus-manager;1"]
michael@0 1186 .getService(Components.interfaces.nsIFocusManager);
michael@0 1187 if (fm.focusedWindow != window)
michael@0 1188 return false;
michael@0 1189
michael@0 1190 let focusedElement = fm.focusedElement;
michael@0 1191 if (!focusedElement)
michael@0 1192 return false;
michael@0 1193
michael@0 1194 let bindingParent = document.getBindingParent(focusedElement);
michael@0 1195 if (bindingParent != this && bindingParent != this._findField)
michael@0 1196 return false;
michael@0 1197
michael@0 1198 return true;
michael@0 1199 ]]></body>
michael@0 1200 </method>
michael@0 1201
michael@0 1202 </implementation>
michael@0 1203
michael@0 1204 <handlers>
michael@0 1205 <!--
michael@0 1206 - We have to guard against `this.close` being |null| due to an unknown
michael@0 1207 - issue, which is tracked in bug 957999.
michael@0 1208 -->
michael@0 1209 <handler event="keypress" keycode="VK_ESCAPE" phase="capturing"
michael@0 1210 action="if (this.close) this.close();" preventdefault="true"/>
michael@0 1211 </handlers>
michael@0 1212 </binding>
michael@0 1213 </bindings>

mercurial