toolkit/content/widgets/findbar.xml

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/content/widgets/findbar.xml	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1213 @@
     1.4 +<?xml version="1.0"?>
     1.5 +
     1.6 +<!-- This Source Code Form is subject to the terms of the Mozilla Public
     1.7 +   - License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
     1.9 +
    1.10 +<!DOCTYPE bindings [
    1.11 +<!ENTITY % findBarDTD SYSTEM "chrome://global/locale/findbar.dtd" >
    1.12 +%findBarDTD;
    1.13 +]>
    1.14 +
    1.15 +<bindings id="findbarBindings"
    1.16 +   xmlns="http://www.mozilla.org/xbl"
    1.17 +   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    1.18 +   xmlns:xbl="http://www.mozilla.org/xbl">
    1.19 +
    1.20 +  <!-- Private binding -->
    1.21 +  <binding id="findbar-textbox"
    1.22 +           extends="chrome://global/content/bindings/textbox.xml#textbox">
    1.23 +    <implementation>
    1.24 +
    1.25 +      <field name="_findbar">null</field>
    1.26 +      <property name="findbar" readonly="true">
    1.27 +        <getter>
    1.28 +          return this._findbar ?
    1.29 +                 this._findbar : this._findbar = document.getBindingParent(this);
    1.30 +        </getter>
    1.31 +      </property>
    1.32 +
    1.33 +      <method name="_handleEnter">
    1.34 +        <parameter name="aEvent"/>
    1.35 +        <body><![CDATA[
    1.36 +          if (this.findbar._findMode == this.findbar.FIND_NORMAL) {
    1.37 +            let findString = this.findbar._findField;
    1.38 +            if (!findString.value)
    1.39 +              return;
    1.40 +#ifdef XP_MACOSX
    1.41 +            if (aEvent.metaKey) {
    1.42 +#else
    1.43 +            if (aEvent.ctrlKey) {
    1.44 +#endif
    1.45 +              this.findbar.getElement("highlight").click();
    1.46 +              return;
    1.47 +            }
    1.48 +
    1.49 +            this.findbar.onFindAgainCommand(aEvent.shiftKey);
    1.50 +          } else {
    1.51 +            this.findbar._finishFAYT(aEvent);
    1.52 +          }
    1.53 +        ]]></body>
    1.54 +      </method>
    1.55 +
    1.56 +      <method name="_handleTab">
    1.57 +        <parameter name="aEvent"/>
    1.58 +        <body><![CDATA[
    1.59 +          let shouldHandle = !aEvent.altKey && !aEvent.ctrlKey &&
    1.60 +                             !aEvent.metaKey;
    1.61 +          if (shouldHandle &&
    1.62 +              this.findbar._findMode != this.findbar.FIND_NORMAL) {
    1.63 +
    1.64 +            this.findbar._finishFAYT(aEvent);
    1.65 +          }
    1.66 +        ]]></body>
    1.67 +      </method>
    1.68 +    </implementation>
    1.69 +
    1.70 +    <handlers>
    1.71 +      <handler event="input"><![CDATA[
    1.72 +        // We should do nothing during composition.  E.g., composing string
    1.73 +        // before converting may matches a forward word of expected word.
    1.74 +        // After that, even if user converts the composition string to the
    1.75 +        // expected word, it may find second or later searching word in the
    1.76 +        // document.
    1.77 +        if (this.findbar._isIMEComposing) {
    1.78 +          return;
    1.79 +        }
    1.80 +        this.findbar._find(this.value);
    1.81 +      ]]></handler>
    1.82 +
    1.83 +      <handler event="keypress"><![CDATA[
    1.84 +        let shouldHandle = !event.altKey && !event.ctrlKey &&
    1.85 +                           !event.metaKey && !event.shiftKey;
    1.86 +
    1.87 +        switch (event.keyCode) {
    1.88 +          case KeyEvent.DOM_VK_RETURN:
    1.89 +            this._handleEnter(event);
    1.90 +            break;
    1.91 +          case KeyEvent.DOM_VK_TAB:
    1.92 +            this._handleTab(event);
    1.93 +            break;
    1.94 +          case KeyEvent.DOM_VK_PAGE_UP:
    1.95 +          case KeyEvent.DOM_VK_PAGE_DOWN:
    1.96 +            if (shouldHandle) {
    1.97 +              this.findbar.browser.finder.keyPress(event);
    1.98 +              event.preventDefault();
    1.99 +            }
   1.100 +            break;
   1.101 +          case KeyEvent.DOM_VK_UP:
   1.102 +          case KeyEvent.DOM_VK_DOWN:
   1.103 +            this.findbar.browser.finder.keyPress(event);
   1.104 +            event.preventDefault();
   1.105 +            break;
   1.106 +        }
   1.107 +      ]]></handler>
   1.108 +
   1.109 +      <handler event="blur"><![CDATA[
   1.110 +        let findbar = this.findbar;
   1.111 +        // Note: This code used to remove the selection
   1.112 +        // if it matched an editable.
   1.113 +        findbar.browser.finder.enableSelection();
   1.114 +      ]]></handler>
   1.115 +
   1.116 +#ifdef XP_MACOSX
   1.117 +      <handler event="focus"><![CDATA[
   1.118 +        let findbar = this.findbar;
   1.119 +        findbar._onFindFieldFocus();
   1.120 +      ]]></handler>
   1.121 +#endif
   1.122 +
   1.123 +      <handler event="compositionstart"><![CDATA[
   1.124 +        // Don't close the find toolbar while IME is composing.
   1.125 +        let findbar = this.findbar;
   1.126 +        findbar._isIMEComposing = true;
   1.127 +        if (findbar._quickFindTimeout) {
   1.128 +          clearTimeout(findbar._quickFindTimeout);
   1.129 +          findbar._quickFindTimeout = null;
   1.130 +        }
   1.131 +      ]]></handler>
   1.132 +
   1.133 +      <handler event="compositionend"><![CDATA[
   1.134 +        let findbar = this.findbar;
   1.135 +        findbar._isIMEComposing = false;
   1.136 +        if (findbar._findMode != findbar.FIND_NORMAL)
   1.137 +          findbar._setFindCloseTimeout();
   1.138 +      ]]></handler>
   1.139 +
   1.140 +      <handler event="dragover"><![CDATA[
   1.141 +        if (event.dataTransfer.types.contains("text/plain"))
   1.142 +          event.preventDefault();
   1.143 +      ]]></handler>
   1.144 +
   1.145 +      <handler event="drop"><![CDATA[
   1.146 +        let value = event.dataTransfer.getData("text/plain");
   1.147 +        this.value = value;
   1.148 +        this.findbar._find(value);
   1.149 +        event.stopPropagation();
   1.150 +        event.preventDefault();
   1.151 +      ]]></handler>
   1.152 +    </handlers>
   1.153 +  </binding>
   1.154 +
   1.155 +  <binding id="findbar"
   1.156 +           extends="chrome://global/content/bindings/toolbar.xml#toolbar">
   1.157 +    <resources>
   1.158 +      <stylesheet src="chrome://global/skin/findBar.css"/>
   1.159 +    </resources>
   1.160 +
   1.161 +    <content hidden="true">
   1.162 +    <xul:hbox anonid="findbar-container" class="findbar-container" flex="1" align="center">
   1.163 +      <xul:hbox anonid="findbar-textbox-wrapper" align="stretch">
   1.164 +        <xul:textbox anonid="findbar-textbox"
   1.165 +                     class="findbar-textbox findbar-find-fast"
   1.166 +                     xbl:inherits="flash"/>
   1.167 +        <xul:toolbarbutton anonid="find-previous"
   1.168 +                           class="findbar-find-previous tabbable"
   1.169 +                           tooltiptext="&previous.tooltip;"
   1.170 +                           oncommand="onFindAgainCommand(true);"
   1.171 +                           disabled="true"
   1.172 +                           xbl:inherits="accesskey=findpreviousaccesskey"/>
   1.173 +        <xul:toolbarbutton anonid="find-next"
   1.174 +                           class="findbar-find-next tabbable"
   1.175 +                           tooltiptext="&next.tooltip;"
   1.176 +                           oncommand="onFindAgainCommand(false);"
   1.177 +                           disabled="true"
   1.178 +                           xbl:inherits="accesskey=findnextaccesskey"/>
   1.179 +      </xul:hbox>
   1.180 +      <xul:toolbarbutton anonid="highlight"
   1.181 +                         class="findbar-highlight tabbable"
   1.182 +                         label="&highlightAll.label;"
   1.183 +                         accesskey="&highlightAll.accesskey;"
   1.184 +                         tooltiptext="&highlightAll.tooltiptext;"
   1.185 +                         oncommand="toggleHighlight(this.checked);"
   1.186 +                         type="checkbox"
   1.187 +                         xbl:inherits="accesskey=highlightaccesskey"/>
   1.188 +      <xul:toolbarbutton anonid="find-case-sensitive"
   1.189 +                         class="findbar-case-sensitive tabbable"
   1.190 +                         label="&caseSensitive.label;"
   1.191 +                         accesskey="&caseSensitive.accesskey;"
   1.192 +                         tooltiptext="&caseSensitive.tooltiptext;"
   1.193 +                         oncommand="_setCaseSensitivity(this.checked);"
   1.194 +                         type="checkbox"
   1.195 +                         xbl:inherits="accesskey=matchcaseaccesskey"/>
   1.196 +      <xul:label anonid="match-case-status" class="findbar-find-fast"/>
   1.197 +      <xul:image anonid="find-status-icon" class="findbar-find-fast find-status-icon"/>
   1.198 +      <xul:description anonid="find-status"
   1.199 +                       control="findbar-textbox"
   1.200 +                       class="findbar-find-fast findbar-find-status">
   1.201 +      <!-- Do not use value, first child is used because it provides a11y with text change events -->
   1.202 +      </xul:description>
   1.203 +    </xul:hbox>
   1.204 +    <xul:toolbarbutton anonid="find-closebutton"
   1.205 +                       class="findbar-closebutton close-icon"
   1.206 +                       tooltiptext="&findCloseButton.tooltip;"
   1.207 +                       oncommand="close();"/>
   1.208 +    </content>
   1.209 +
   1.210 +    <implementation implements="nsIDOMEventListener, nsIEditActionListener">
   1.211 +      <field name="FIND_NORMAL">0</field>
   1.212 +      <field name="FIND_TYPEAHEAD">1</field>
   1.213 +      <field name="FIND_LINKS">2</field>
   1.214 +
   1.215 +      <field name="_findMode">0</field>
   1.216 +
   1.217 +      <field name="_flashFindBar">0</field>
   1.218 +      <field name="_initialFlashFindBarCount">6</field>
   1.219 +
   1.220 +      <property name="prefillWithSelection"
   1.221 +                onget="return this.getAttribute('prefillwithselection') != 'false'"
   1.222 +                onset="this.setAttribute('prefillwithselection', val); return val;"/>
   1.223 +      <field name="_selectionMaxLen">150</field>
   1.224 +
   1.225 +      <method name="getElement">
   1.226 +        <parameter name="aAnonymousID"/>
   1.227 +        <body><![CDATA[
   1.228 +          return document.getAnonymousElementByAttribute(this,
   1.229 +                                                         "anonid",
   1.230 +                                                         aAnonymousID)
   1.231 +        ]]></body>
   1.232 +      </method>
   1.233 +
   1.234 +      <property name="findMode"
   1.235 +                readonly="true"
   1.236 +                onget="return this._findMode;"/>
   1.237 +
   1.238 +      <property name="canClear" readonly="true">
   1.239 +        <getter><![CDATA[
   1.240 +          if (this._findField.value)
   1.241 +            return true;
   1.242 +
   1.243 +          // Watch out for lazy editor init
   1.244 +          if (this._findField.editor) {
   1.245 +            let tm = this._findField.editor.transactionManager;
   1.246 +            return !!(tm.numberOfUndoItems || tm.numberOfRedoItems);
   1.247 +          }
   1.248 +          return false;
   1.249 +        ]]></getter>
   1.250 +      </property>
   1.251 +
   1.252 +      <field name="_browser">null</field>
   1.253 +      <property name="browser">
   1.254 +        <getter><![CDATA[
   1.255 +          if (!this._browser) {
   1.256 +            this._browser =
   1.257 +              document.getElementById(this.getAttribute("browserid"));
   1.258 +          }
   1.259 +          return this._browser;
   1.260 +        ]]></getter>
   1.261 +        <setter><![CDATA[
   1.262 +          if (this._browser) {
   1.263 +            this._browser.removeEventListener("keypress", this, false);
   1.264 +            this._browser.removeEventListener("mouseup", this, false);
   1.265 +            let finder = this._browser.finder;
   1.266 +            if (finder)
   1.267 +              finder.removeResultListener(this);
   1.268 +          }
   1.269 +
   1.270 +          this._browser = val;
   1.271 +          if (this._browser) {
   1.272 +            this._browser.addEventListener("keypress", this, false);
   1.273 +            this._browser.addEventListener("mouseup", this, false);
   1.274 +            this._browser.finder.addResultListener(this);
   1.275 +
   1.276 +            this._findField.value = this._browser._lastSearchString;
   1.277 +            this.toggleHighlight(this.browser._lastSearchHighlight);
   1.278 +          }
   1.279 +          return val;
   1.280 +        ]]></setter>
   1.281 +      </property>
   1.282 +
   1.283 +      <field name="_observer"><![CDATA[({
   1.284 +        _self: this,
   1.285 +
   1.286 +        QueryInterface: function(aIID) {
   1.287 +          if (aIID.equals(Components.interfaces.nsIObserver) ||
   1.288 +              aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
   1.289 +              aIID.equals(Components.interfaces.nsISupports))
   1.290 +            return this;
   1.291 +
   1.292 +          throw Components.results.NS_ERROR_NO_INTERFACE;
   1.293 +        },
   1.294 +
   1.295 +        observe: function(aSubject, aTopic, aPrefName) {
   1.296 +          if (aTopic != "nsPref:changed")
   1.297 +            return;
   1.298 +
   1.299 +          let prefsvc =
   1.300 +            aSubject.QueryInterface(Components.interfaces.nsIPrefBranch);
   1.301 +
   1.302 +          switch (aPrefName) {
   1.303 +            case "accessibility.typeaheadfind":
   1.304 +              this._self._useTypeAheadFind = prefsvc.getBoolPref(aPrefName);
   1.305 +              break;
   1.306 +            case "accessibility.typeaheadfind.linksonly":
   1.307 +              this._self._typeAheadLinksOnly = prefsvc.getBoolPref(aPrefName);
   1.308 +              break;
   1.309 +            case "accessibility.typeaheadfind.casesensitive":
   1.310 +              this._self._typeAheadCaseSensitive = prefsvc.getIntPref(aPrefName);
   1.311 +              this._self._updateCaseSensitivity();
   1.312 +              if (this._self.getElement("highlight").checked)
   1.313 +                this._self._setHighlightTimeout();
   1.314 +              break;
   1.315 +          }
   1.316 +        }
   1.317 +      })]]></field>
   1.318 +
   1.319 +      <field name="_destroyed">false</field>
   1.320 +
   1.321 +      <constructor><![CDATA[
   1.322 +        // These elements are accessed frequently and are therefore cached
   1.323 +        this._findField = this.getElement("findbar-textbox");
   1.324 +        this._findStatusIcon = this.getElement("find-status-icon");
   1.325 +        this._findStatusDesc = this.getElement("find-status");
   1.326 +
   1.327 +        this._foundURL = null;
   1.328 +
   1.329 +        let prefsvc =
   1.330 +          Components.classes["@mozilla.org/preferences-service;1"]
   1.331 +                    .getService(Components.interfaces.nsIPrefBranch);
   1.332 +
   1.333 +        this._quickFindTimeoutLength =
   1.334 +          prefsvc.getIntPref("accessibility.typeaheadfind.timeout");
   1.335 +        this._flashFindBar =
   1.336 +          prefsvc.getIntPref("accessibility.typeaheadfind.flashBar");
   1.337 +
   1.338 +        prefsvc.addObserver("accessibility.typeaheadfind",
   1.339 +                            this._observer, false);
   1.340 +        prefsvc.addObserver("accessibility.typeaheadfind.linksonly",
   1.341 +                            this._observer, false);
   1.342 +        prefsvc.addObserver("accessibility.typeaheadfind.casesensitive",
   1.343 +                            this._observer, false);
   1.344 +
   1.345 +        this._useTypeAheadFind =
   1.346 +          prefsvc.getBoolPref("accessibility.typeaheadfind");
   1.347 +        this._typeAheadLinksOnly =
   1.348 +          prefsvc.getBoolPref("accessibility.typeaheadfind.linksonly");
   1.349 +        this._typeAheadCaseSensitive =
   1.350 +          prefsvc.getIntPref("accessibility.typeaheadfind.casesensitive");
   1.351 +
   1.352 +        // Convenience
   1.353 +        this.nsITypeAheadFind = Components.interfaces.nsITypeAheadFind;
   1.354 +        this.nsISelectionController = Components.interfaces.nsISelectionController;
   1.355 +        this._findSelection = this.nsISelectionController.SELECTION_FIND;
   1.356 +
   1.357 +        this._findResetTimeout = -1;
   1.358 +
   1.359 +        // Make sure the FAYT keypress listener is attached by initializing the
   1.360 +        // browser property
   1.361 +        if (this.getAttribute("browserid"))
   1.362 +          setTimeout(function(aSelf) { aSelf.browser = aSelf.browser; }, 0, this);
   1.363 +      ]]></constructor>
   1.364 +
   1.365 +      <destructor><![CDATA[
   1.366 +        this.destroy();
   1.367 +      ]]></destructor>
   1.368 +
   1.369 +      <!-- This is necessary because the destructor isn't called when
   1.370 +           we are removed from a document that is not destroyed. This
   1.371 +           needs to be explicitly called in this case -->
   1.372 +      <method name="destroy">
   1.373 +        <body><![CDATA[
   1.374 +          if (this._destroyed)
   1.375 +            return;
   1.376 +          this._destroyed = true;
   1.377 +
   1.378 +          this.browser = null;
   1.379 +
   1.380 +          let prefsvc =
   1.381 +            Components.classes["@mozilla.org/preferences-service;1"]
   1.382 +                      .getService(Components.interfaces.nsIPrefBranch);
   1.383 +          prefsvc.removeObserver("accessibility.typeaheadfind",
   1.384 +                                 this._observer);
   1.385 +          prefsvc.removeObserver("accessibility.typeaheadfind.linksonly",
   1.386 +                                 this._observer);
   1.387 +          prefsvc.removeObserver("accessibility.typeaheadfind.casesensitive",
   1.388 +                                 this._observer);
   1.389 +
   1.390 +          // Clear all timers that might still be running.
   1.391 +          this._cancelTimers();
   1.392 +        ]]></body>
   1.393 +      </method>
   1.394 +
   1.395 +      <method name="_cancelTimers">
   1.396 +        <body><![CDATA[
   1.397 +          if (this._flashFindBarTimeout) {
   1.398 +            clearInterval(this._flashFindBarTimeout);
   1.399 +            this._flashFindBarTimeout = null;
   1.400 +          }
   1.401 +          if (this._quickFindTimeout) {
   1.402 +            clearTimeout(this._quickFindTimeout);
   1.403 +            this._quickFindTimeout = null;
   1.404 +          }
   1.405 +          if (this._highlightTimeout) {
   1.406 +            clearTimeout(this._highlightTimeout);
   1.407 +            this._highlightTimeout = null;
   1.408 +          }
   1.409 +          if (this._findResetTimeout) {
   1.410 +            clearTimeout(this._findResetTimeout);
   1.411 +            this._findResetTimeout = null;
   1.412 +          }
   1.413 +        ]]></body>
   1.414 +      </method>
   1.415 +
   1.416 +      <method name="_setFindCloseTimeout">
   1.417 +        <body><![CDATA[
   1.418 +          if (this._quickFindTimeout)
   1.419 +            clearTimeout(this._quickFindTimeout);
   1.420 +
   1.421 +          // Don't close the find toolbar while IME is composing OR when the
   1.422 +          // findbar is already hidden.
   1.423 +          if (this._isIMEComposing || this.hidden) {
   1.424 +            this._quickFindTimeout = null;
   1.425 +            return;
   1.426 +          }
   1.427 +
   1.428 +          this._quickFindTimeout = setTimeout(() => {
   1.429 +             if (this._findMode != this.FIND_NORMAL)
   1.430 +               this.close();
   1.431 +             this._quickFindTimeout = null;
   1.432 +           }, this._quickFindTimeoutLength);
   1.433 +        ]]></body>
   1.434 +      </method>
   1.435 +
   1.436 +      <!--
   1.437 +        - Turns highlight on or off.
   1.438 +        - @param aHighlight (boolean)
   1.439 +        -        Whether to turn the highlight on or off
   1.440 +        -->
   1.441 +      <method name="toggleHighlight">
   1.442 +        <parameter name="aHighlight"/>
   1.443 +        <body><![CDATA[
   1.444 +          if (!this._dispatchFindEvent("highlightallchange"))
   1.445 +            return;
   1.446 +
   1.447 +          let word = this._findField.value;
   1.448 +          // Bug 429723. Don't attempt to highlight ""
   1.449 +          if (aHighlight && !word)
   1.450 +            return;
   1.451 +
   1.452 +          this.browser._lastSearchHighlight = aHighlight;
   1.453 +          this.browser.finder.highlight(aHighlight, word);
   1.454 +        ]]></body>
   1.455 +      </method>
   1.456 +
   1.457 +      <!--
   1.458 +        - Updates the case-sensitivity mode of the findbar and its UI.
   1.459 +        - @param [optional] aString
   1.460 +        -        The string for which case sensitivity might be turned on.
   1.461 +        -        This only used when case-sensitivity is in auto mode,
   1.462 +        -        @see _shouldBeCaseSensitive. The default value for this
   1.463 +        -        parameter is the find-field value.
   1.464 +        -->
   1.465 +      <method name="_updateCaseSensitivity">
   1.466 +        <parameter name="aString"/>
   1.467 +        <body><![CDATA[
   1.468 +          let val = aString || this._findField.value;
   1.469 +
   1.470 +          let caseSensitive = this._shouldBeCaseSensitive(val);
   1.471 +          let checkbox = this.getElement("find-case-sensitive");
   1.472 +          let statusLabel = this.getElement("match-case-status");
   1.473 +          checkbox.checked = caseSensitive;
   1.474 +
   1.475 +          statusLabel.value = caseSensitive ? this._caseSensitiveStr : "";
   1.476 +
   1.477 +          // Show the checkbox on the full Find bar in non-auto mode.
   1.478 +          // Show the label in all other cases.
   1.479 +          let hideCheckbox = this._findMode != this.FIND_NORMAL ||
   1.480 +            (this._typeAheadCaseSensitive != 0 &&
   1.481 +             this._typeAheadCaseSensitive != 1);
   1.482 +          checkbox.hidden = hideCheckbox;
   1.483 +          statusLabel.hidden = !hideCheckbox;
   1.484 +
   1.485 +          this.browser.finder.caseSensitive = caseSensitive;
   1.486 +        ]]></body>
   1.487 +      </method>
   1.488 +
   1.489 +      <!--
   1.490 +        - Sets the findbar case-sensitivity mode
   1.491 +        - @param aCaseSensitive (boolean)
   1.492 +        -        Whether or not case-sensitivity should be turned on.
   1.493 +        -->
   1.494 +      <method name="_setCaseSensitivity">
   1.495 +        <parameter name="aCaseSensitive"/>
   1.496 +        <body><![CDATA[
   1.497 +          let prefsvc =
   1.498 +            Components.classes["@mozilla.org/preferences-service;1"]
   1.499 +                      .getService(Components.interfaces.nsIPrefBranch);
   1.500 +
   1.501 +          // Just set the pref; our observer will change the find bar behavior
   1.502 +          prefsvc.setIntPref("accessibility.typeaheadfind.casesensitive",
   1.503 +                             aCaseSensitive ? 1 : 0);
   1.504 +
   1.505 +          this._dispatchFindEvent("casesensitivitychange");
   1.506 +        ]]></body>
   1.507 +      </method>
   1.508 +
   1.509 +      <!--
   1.510 +        - Opens and displays the find bar.
   1.511 +        -
   1.512 +        - @param aMode
   1.513 +        -        the find mode to be used, which is either FIND_NORMAL,
   1.514 +        -        FIND_TYPEAHEAD or FIND_LINKS. If not passed, the last
   1.515 +        -        find mode if any or FIND_NORMAL.
   1.516 +        - @returns true if the find bar wasn't previously open, false otherwise.
   1.517 +        -->
   1.518 +      <method name="open">
   1.519 +        <parameter name="aMode"/>
   1.520 +        <body><![CDATA[
   1.521 +          if (aMode != undefined)
   1.522 +            this._findMode = aMode;
   1.523 +
   1.524 +          if (!this._notFoundStr) {
   1.525 +            let stringsBundle =
   1.526 +              Components.classes["@mozilla.org/intl/stringbundle;1"]
   1.527 +                        .getService(Components.interfaces.nsIStringBundleService)
   1.528 +                        .createBundle("chrome://global/locale/findbar.properties");
   1.529 +            this._notFoundStr = stringsBundle.GetStringFromName("NotFound");
   1.530 +            this._wrappedToTopStr =
   1.531 +              stringsBundle.GetStringFromName("WrappedToTop");
   1.532 +            this._wrappedToBottomStr =
   1.533 +              stringsBundle.GetStringFromName("WrappedToBottom");
   1.534 +            this._normalFindStr =
   1.535 +              stringsBundle.GetStringFromName("NormalFind");
   1.536 +            this._fastFindStr =
   1.537 +              stringsBundle.GetStringFromName("FastFind");
   1.538 +            this._fastFindLinksStr =
   1.539 +              stringsBundle.GetStringFromName("FastFindLinks");
   1.540 +            this._caseSensitiveStr =
   1.541 +              stringsBundle.GetStringFromName("CaseSensitive");
   1.542 +          }
   1.543 +
   1.544 +          this._findFailedString = null;
   1.545 +
   1.546 +          this._updateFindUI();
   1.547 +          if (this.hidden) {
   1.548 +            this.hidden = false;
   1.549 +
   1.550 +            this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
   1.551 +
   1.552 +            let event = document.createEvent("Events");
   1.553 +            event.initEvent("findbaropen", true, false);
   1.554 +            this.dispatchEvent(event);
   1.555 +
   1.556 +            return true;
   1.557 +          }
   1.558 +          return false;
   1.559 +        ]]></body>
   1.560 +      </method>
   1.561 +
   1.562 +      <!--
   1.563 +        - Closes the findbar.
   1.564 +        -->
   1.565 +      <method name="close">
   1.566 +        <body><![CDATA[
   1.567 +          if (this.hidden)
   1.568 +            return;
   1.569 +
   1.570 +          this.hidden = true;
   1.571 +
   1.572 +          this.browser.finder.focusContent();
   1.573 +          this.browser.finder.enableSelection();
   1.574 +          this._findField.blur();
   1.575 +
   1.576 +          this._cancelTimers();
   1.577 +
   1.578 +          this._findFailedString = null;
   1.579 +        ]]></body>
   1.580 +      </method>
   1.581 +
   1.582 +      <method name="clear">
   1.583 +        <body><![CDATA[
   1.584 +          this.browser.finder.removeSelection();
   1.585 +          this._findField.reset();
   1.586 +          this.toggleHighlight(false);
   1.587 +          this._updateStatusUI();
   1.588 +          this._enableFindButtons(false);
   1.589 +        ]]></body>
   1.590 +      </method>
   1.591 +
   1.592 +      <method name="_dispatchKeypressEvent">
   1.593 +        <parameter name="aTarget"/>
   1.594 +        <parameter name="aEvent"/>
   1.595 +        <body><![CDATA[
   1.596 +          if (!aTarget)
   1.597 +            return;
   1.598 +
   1.599 +          let event = document.createEvent("KeyEvents");
   1.600 +          event.initKeyEvent(aEvent.type, aEvent.bubbles, aEvent.cancelable,
   1.601 +                             aEvent.view, aEvent.ctrlKey, aEvent.altKey,
   1.602 +                             aEvent.shiftKey, aEvent.metaKey, aEvent.keyCode,
   1.603 +                             aEvent.charCode);
   1.604 +          aTarget.dispatchEvent(event);
   1.605 +        ]]></body>
   1.606 +      </method>
   1.607 +
   1.608 +      <field name="_xulBrowserWindow">null</field>
   1.609 +      <method name="_updateStatusUIBar">
   1.610 +        <parameter name="aFoundURL"/>
   1.611 +        <body><![CDATA[
   1.612 +          if (!this._xulBrowserWindow) {
   1.613 +            try {
   1.614 +              this._xulBrowserWindow =
   1.615 +                window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   1.616 +                      .getInterface(Components.interfaces.nsIWebNavigation)
   1.617 +                      .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
   1.618 +                      .treeOwner
   1.619 +                      .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   1.620 +                      .getInterface(Components.interfaces.nsIXULWindow)
   1.621 +                      .XULBrowserWindow;
   1.622 +            }
   1.623 +            catch(ex) { }
   1.624 +            if (!this._xulBrowserWindow)
   1.625 +              return false;
   1.626 +          }
   1.627 +
   1.628 +          // Call this has the same effect like hovering over link,
   1.629 +          // the browser shows the URL as a tooltip.
   1.630 +          this._xulBrowserWindow.setOverLink(aFoundURL || "", null);
   1.631 +          return true;
   1.632 +        ]]></body>
   1.633 +      </method>
   1.634 +
   1.635 +      <method name="_finishFAYT">
   1.636 +        <parameter name="aKeypressEvent"/>
   1.637 +        <body><![CDATA[
   1.638 +          this.browser.finder.focusContent();
   1.639 +
   1.640 +          if (aKeypressEvent)
   1.641 +            aKeypressEvent.preventDefault();
   1.642 +
   1.643 +          this.browser.finder.keyPress(aKeypressEvent);
   1.644 +
   1.645 +          this.close();
   1.646 +          return true;
   1.647 +        ]]></body>
   1.648 +      </method>
   1.649 +
   1.650 +      <!--
   1.651 +        - Returns true if |aMimeType| is text-based, or false otherwise.
   1.652 +        -
   1.653 +        - @param aMimeType
   1.654 +        -        The MIME type to check.
   1.655 +        -
   1.656 +        - if adding types to this function, please see the similar function
   1.657 +        - in browser/base/content/browser.js
   1.658 +        -->
   1.659 +      <method name="_mimeTypeIsTextBased">
   1.660 +        <parameter name="aMimeType"/>
   1.661 +        <body><![CDATA[
   1.662 +          return /^text\/|\+xml$/.test(aMimeType) ||
   1.663 +                 aMimeType == "application/x-javascript" ||
   1.664 +                 aMimeType == "application/javascript" ||
   1.665 +                 aMimeType == "application/json" ||
   1.666 +                 aMimeType == "application/xml";
   1.667 +        ]]></body>
   1.668 +      </method>
   1.669 +
   1.670 +      <!--
   1.671 +        - Returns whether FAYT can be used for the given event in
   1.672 +        - the current content state.
   1.673 +        -->
   1.674 +      <method name="_shouldFastFind">
   1.675 +        <parameter name="aEvent"/>
   1.676 +        <body><![CDATA[
   1.677 +          if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey ||
   1.678 +              aEvent.defaultPrevented)
   1.679 +            return false;
   1.680 +
   1.681 +          let {BrowserUtils} = Components.utils.import("resource://gre/modules/BrowserUtils.jsm", {});
   1.682 +          let [elt, win] = BrowserUtils.getFocusSync(document);
   1.683 +
   1.684 +          if (elt) {
   1.685 +            if (elt instanceof HTMLInputElement && elt.mozIsTextField(false))
   1.686 +              return false;
   1.687 +
   1.688 +            if (elt.isContentEditable)
   1.689 +              return false;
   1.690 +
   1.691 +            if (elt instanceof HTMLTextAreaElement ||
   1.692 +                elt instanceof HTMLSelectElement ||
   1.693 +                elt instanceof HTMLObjectElement ||
   1.694 +                elt instanceof HTMLEmbedElement)
   1.695 +              return false;
   1.696 +          }
   1.697 +
   1.698 +          if (win && !this._mimeTypeIsTextBased(win.document.contentType))
   1.699 +              return false;
   1.700 +
   1.701 +          // disable FAYT in about:blank to prevent FAYT opening unexpectedly.
   1.702 +          let url = this.browser.currentURI;
   1.703 +          if (url.spec == "about:blank")
   1.704 +            return false;
   1.705 +
   1.706 +          // disable FAYT in documents that ask for it to be disabled.
   1.707 +          if ((url.schemeIs("about") || url.schemeIs("chrome")) &&
   1.708 +              (win.document.documentElement &&
   1.709 +               win.document.documentElement.getAttribute("disablefastfind") == "true"))
   1.710 +            return false;
   1.711 +
   1.712 +          if (win) {
   1.713 +            try {
   1.714 +              let editingSession = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   1.715 +                                   .getInterface(Components.interfaces.nsIWebNavigation)
   1.716 +                                   .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   1.717 +                                   .getInterface(Components.interfaces.nsIEditingSession);
   1.718 +              if (editingSession.windowIsEditable(win))
   1.719 +                return false;
   1.720 +            }
   1.721 +            catch (e) {
   1.722 +              // If someone built with composer disabled, we can't get an editing session.
   1.723 +            }
   1.724 +         }
   1.725 +
   1.726 +          return true;
   1.727 +        ]]></body>
   1.728 +      </method>
   1.729 +
   1.730 +      <method name="_shouldBeCaseSensitive">
   1.731 +        <parameter name="aString"/>
   1.732 +        <body><![CDATA[
   1.733 +          if (this._typeAheadCaseSensitive == 0)
   1.734 +            return false;
   1.735 +          if (this._typeAheadCaseSensitive == 1)
   1.736 +            return true;
   1.737 +
   1.738 +          return aString != aString.toLowerCase();
   1.739 +        ]]></body>
   1.740 +      </method>
   1.741 +
   1.742 +      <method name="_onBrowserKeypress">
   1.743 +        <parameter name="aEvent"/>
   1.744 +        <body><![CDATA[
   1.745 +          const TAF_LINKS_KEY = "'";
   1.746 +          const TAF_TEXT_KEY = "/";
   1.747 +
   1.748 +          if (!this._shouldFastFind(aEvent))
   1.749 +            return;
   1.750 +
   1.751 +          if (this._findMode != this.FIND_NORMAL && this._quickFindTimeout) {
   1.752 +            if (!aEvent.charCode)
   1.753 +              return;
   1.754 +
   1.755 +            this._findField.select();
   1.756 +            this._findField.focus();
   1.757 +            this._dispatchKeypressEvent(this._findField.inputField, aEvent);
   1.758 +            aEvent.preventDefault();
   1.759 +            return;
   1.760 +          }
   1.761 +
   1.762 +          let key = aEvent.charCode ? String.fromCharCode(aEvent.charCode) : null;
   1.763 +          let manualstartFAYT = (key == TAF_LINKS_KEY || key == TAF_TEXT_KEY);
   1.764 +          let autostartFAYT = !manualstartFAYT && this._useTypeAheadFind &&
   1.765 +                              key && key != " ";
   1.766 +          if (manualstartFAYT || autostartFAYT) {
   1.767 +            let mode = (key == TAF_LINKS_KEY ||
   1.768 +                        (autostartFAYT && this._typeAheadLinksOnly)) ?
   1.769 +              this.FIND_LINKS : this.FIND_TYPEAHEAD;
   1.770 +
   1.771 +            // Clear bar first, so that when openFindBar() calls setCaseSensitivity()
   1.772 +            // it doesn't get confused by a lingering value
   1.773 +            this._findField.value = "";
   1.774 +
   1.775 +            this.open(mode);
   1.776 +            this._setFindCloseTimeout();
   1.777 +            this._findField.select();
   1.778 +            this._findField.focus();
   1.779 +
   1.780 +            if (autostartFAYT)
   1.781 +              this._dispatchKeypressEvent(this._findField.inputField, aEvent);
   1.782 +            else
   1.783 +              this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
   1.784 +
   1.785 +            aEvent.preventDefault();
   1.786 +          }
   1.787 +        ]]></body>
   1.788 +      </method>
   1.789 +
   1.790 +      <!-- See nsIDOMEventListener -->
   1.791 +      <method name="handleEvent">
   1.792 +        <parameter name="aEvent"/>
   1.793 +        <body><![CDATA[
   1.794 +          switch (aEvent.type) {
   1.795 +            case "mouseup":
   1.796 +              if (!this.hidden && this._findMode != this.FIND_NORMAL)
   1.797 +                this.close();
   1.798 +
   1.799 +              break;
   1.800 +            case "keypress":
   1.801 +              this._onBrowserKeypress(aEvent);
   1.802 +              break;
   1.803 +          }
   1.804 +        ]]></body>
   1.805 +      </method>
   1.806 +
   1.807 +      <method name="_enableFindButtons">
   1.808 +        <parameter name="aEnable"/>
   1.809 +        <body><![CDATA[
   1.810 +          this.getElement("find-next").disabled =
   1.811 +            this.getElement("find-previous").disabled = !aEnable;
   1.812 +        ]]></body>
   1.813 +      </method>
   1.814 +
   1.815 +      <!--
   1.816 +        - Determines whether minimalist or general-purpose search UI is to be
   1.817 +        - displayed when the find bar is activated.
   1.818 +        -->
   1.819 +      <method name="_updateFindUI">
   1.820 +        <body><![CDATA[
   1.821 +          let showMinimalUI = this._findMode != this.FIND_NORMAL;
   1.822 +
   1.823 +          let nodes = this.getElement("findbar-container").childNodes;
   1.824 +          let wrapper = this.getElement("findbar-textbox-wrapper");
   1.825 +          for (let node of nodes) {
   1.826 +            if (node == wrapper)
   1.827 +               continue;
   1.828 +            node.hidden = showMinimalUI;
   1.829 +          }
   1.830 +          this.getElement("find-next").hidden =
   1.831 +            this.getElement("find-previous").hidden = showMinimalUI;
   1.832 +          this._updateCaseSensitivity();
   1.833 +
   1.834 +          if (showMinimalUI)
   1.835 +            this._findField.classList.add("minimal");
   1.836 +          else
   1.837 +            this._findField.classList.remove("minimal");
   1.838 +
   1.839 +          if (this._findMode == this.FIND_TYPEAHEAD)
   1.840 +            this._findField.placeholder = this._fastFindStr;
   1.841 +          else if (this._findMode == this.FIND_LINKS)
   1.842 +            this._findField.placeholder = this._fastFindLinksStr;
   1.843 +          else
   1.844 +            this._findField.placeholder = this._normalFindStr;
   1.845 +        ]]></body>
   1.846 +      </method>
   1.847 +
   1.848 +      <method name="_find">
   1.849 +        <parameter name="aValue"/>
   1.850 +        <body><![CDATA[
   1.851 +          if (!this._dispatchFindEvent(""))
   1.852 +            return;
   1.853 +
   1.854 +          let val = aValue || this._findField.value;
   1.855 +
   1.856 +          // We have to carry around an explicit version of this,
   1.857 +          // because finder.searchString doesn't update on failed
   1.858 +          // searches.
   1.859 +          this.browser._lastSearchString = val;
   1.860 +
   1.861 +          // Only search on input if we don't have a last-failed string,
   1.862 +          // or if the current search string doesn't start with it.
   1.863 +          if (!this._findFailedString ||
   1.864 +              !val.startsWith(this._findFailedString))
   1.865 +          {
   1.866 +            this._enableFindButtons(val);
   1.867 +            if (this.getElement("highlight").checked)
   1.868 +              this._setHighlightTimeout();
   1.869 +
   1.870 +            this._updateCaseSensitivity(val);
   1.871 +
   1.872 +            this.browser.finder.fastFind(val, this._findMode == this.FIND_LINKS,
   1.873 +                                         this._findMode != this.FIND_NORMAL);
   1.874 +          }
   1.875 +
   1.876 +          if (this._findMode != this.FIND_NORMAL)
   1.877 +            this._setFindCloseTimeout();
   1.878 +
   1.879 +          if (this._findResetTimeout != -1)
   1.880 +            clearTimeout(this._findResetTimeout);
   1.881 +
   1.882 +          // allow a search to happen on input again after a second has
   1.883 +          // expired since the previous input, to allow for dynamic
   1.884 +          // content and/or page loading
   1.885 +          this._findResetTimeout = setTimeout(() => {
   1.886 +            this._findFailedString = null;
   1.887 +            this._findResetTimeout = -1;
   1.888 +          }, 1000);
   1.889 +        ]]></body>
   1.890 +      </method>
   1.891 +
   1.892 +      <method name="_flash">
   1.893 +        <body><![CDATA[
   1.894 +          if (this._flashFindBarCount === undefined)
   1.895 +            this._flashFindBarCount = this._initialFlashFindBarCount;
   1.896 +
   1.897 +          if (this._flashFindBarCount-- == 0) {
   1.898 +            clearInterval(this._flashFindBarTimeout);
   1.899 +            this.removeAttribute("flash");
   1.900 +            this._flashFindBarCount = 6;
   1.901 +            return;
   1.902 +          }
   1.903 +
   1.904 +          this.setAttribute("flash",
   1.905 +                            (this._flashFindBarCount % 2 == 0) ?
   1.906 +                            "false" : "true");
   1.907 +        ]]></body>
   1.908 +      </method>
   1.909 +
   1.910 +      <method name="_setHighlightTimeout">
   1.911 +        <body><![CDATA[
   1.912 +          if (this._highlightTimeout)
   1.913 +            clearTimeout(this._highlightTimeout);
   1.914 +          this._highlightTimeout =
   1.915 +            setTimeout(function(aSelf) {
   1.916 +                         aSelf.toggleHighlight(false);
   1.917 +                         aSelf.toggleHighlight(true);
   1.918 +                       }, 500, this);
   1.919 +        ]]></body>
   1.920 +      </method>
   1.921 +
   1.922 +      <method name="_findAgain">
   1.923 +        <parameter name="aFindPrevious"/>
   1.924 +        <body><![CDATA[
   1.925 +          this.browser.finder.findAgain(aFindPrevious,
   1.926 +                                        this._findMode == this.FIND_LINKS,
   1.927 +                                        this._findMode != this.FIND_NORMAL);
   1.928 +        ]]></body>
   1.929 +      </method>
   1.930 +
   1.931 +      <method name="_updateStatusUI">
   1.932 +        <parameter name="res"/>
   1.933 +        <parameter name="aFindPrevious"/>
   1.934 +        <body><![CDATA[
   1.935 +          switch (res) {
   1.936 +            case this.nsITypeAheadFind.FIND_WRAPPED:
   1.937 +              this._findStatusIcon.setAttribute("status", "wrapped");
   1.938 +              this._findStatusDesc.textContent =
   1.939 +                aFindPrevious ? this._wrappedToBottomStr : this._wrappedToTopStr;
   1.940 +              this._findField.removeAttribute("status");
   1.941 +              break;
   1.942 +            case this.nsITypeAheadFind.FIND_NOTFOUND:
   1.943 +              this._findStatusIcon.setAttribute("status", "notfound");
   1.944 +              this._findStatusDesc.textContent = this._notFoundStr;
   1.945 +              this._findField.setAttribute("status", "notfound");
   1.946 +              break;
   1.947 +            case this.nsITypeAheadFind.FIND_PENDING:
   1.948 +              this._findStatusIcon.setAttribute("status", "pending");
   1.949 +              this._findStatusDesc.textContent = "";
   1.950 +              this._findField.removeAttribute("status");
   1.951 +              break;
   1.952 +            case this.nsITypeAheadFind.FIND_FOUND:
   1.953 +            default:
   1.954 +              this._findStatusIcon.removeAttribute("status");
   1.955 +              this._findStatusDesc.textContent = "";
   1.956 +              this._findField.removeAttribute("status");
   1.957 +              break;
   1.958 +          }
   1.959 +        ]]></body>
   1.960 +      </method>
   1.961 +
   1.962 +      <method name="updateControlState">
   1.963 +        <parameter name="aResult"/>
   1.964 +        <parameter name="aFindPrevious"/>
   1.965 +        <body><![CDATA[
   1.966 +          this._updateStatusUI(aResult, aFindPrevious);
   1.967 +          this._enableFindButtons(aResult !== this.nsITypeAheadFind.FIND_NOTFOUND);
   1.968 +        ]]></body>
   1.969 +      </method>
   1.970 +
   1.971 +      <method name="_getInitialSelection">
   1.972 +        <body><![CDATA[
   1.973 +          let focusedElement = document.commandDispatcher.focusedElement;
   1.974 +          let selText;
   1.975 +
   1.976 +          if (focusedElement instanceof Components.interfaces.nsIDOMNSEditableElement &&
   1.977 +              focusedElement.editor &&
   1.978 +              focusedElement.ownerDocument.defaultView.top == this._browser.contentWindow)
   1.979 +          {
   1.980 +            // The user may have a selection in an input or textarea
   1.981 +            selText = focusedElement.editor.selectionController
   1.982 +              .getSelection(Components.interfaces.nsISelectionController.SELECTION_NORMAL)
   1.983 +              .toString();
   1.984 +          }
   1.985 +          else {
   1.986 +            // Look for any selected text on the actual page
   1.987 +            let focusedWindow = document.commandDispatcher.focusedWindow;
   1.988 +            if (focusedWindow.top == this._browser.contentWindow)
   1.989 +              selText = focusedWindow.getSelection().toString();
   1.990 +          }
   1.991 +
   1.992 +          if (!selText)
   1.993 +            return "";
   1.994 +
   1.995 +          // Process our text to get rid of unwanted characters
   1.996 +          if (selText.length > this._selectionMaxLen) {
   1.997 +            let pattern = new RegExp("^(?:\\s*.){0," + this._selectionMaxLen + "}");
   1.998 +            pattern.test(selText);
   1.999 +            selText = RegExp.lastMatch;
  1.1000 +          }
  1.1001 +          return selText.replace(/^\s+/, "")
  1.1002 +                        .replace(/\s+$/, "")
  1.1003 +                        .replace(/\s+/g, " ")
  1.1004 +                        .substr(0, this._selectionMaxLen);
  1.1005 +        ]]></body>
  1.1006 +      </method>
  1.1007 +
  1.1008 +      <method name="_dispatchFindEvent">
  1.1009 +        <parameter name="aType"/>
  1.1010 +        <parameter name="aFindPrevious"/>
  1.1011 +        <body><![CDATA[
  1.1012 +          let event = document.createEvent("CustomEvent");
  1.1013 +          event.initCustomEvent("find" + aType, true, true, {
  1.1014 +            query: this._findField.value,
  1.1015 +            caseSensitive: !!this._typeAheadCaseSensitive,
  1.1016 +            highlightAll: this.getElement("highlight").checked,
  1.1017 +            findPrevious: aFindPrevious
  1.1018 +          });
  1.1019 +          return this.dispatchEvent(event);
  1.1020 +        ]]></body>
  1.1021 +      </method>
  1.1022 +
  1.1023 +
  1.1024 +      <!--
  1.1025 +        - Opens the findbar, focuses the findfield and selects its contents.
  1.1026 +        - Also flashes the findbar the first time it's used.
  1.1027 +        - @param aMode
  1.1028 +        -        the find mode to be used, which is either FIND_NORMAL,
  1.1029 +        -        FIND_TYPEAHEAD or FIND_LINKS. If not passed, the last
  1.1030 +        -        find mode if any or FIND_NORMAL.
  1.1031 +        -->
  1.1032 +      <method name="startFind">
  1.1033 +        <parameter name="aMode"/>
  1.1034 +        <body><![CDATA[
  1.1035 +          let prefsvc =
  1.1036 +            Components.classes["@mozilla.org/preferences-service;1"]
  1.1037 +                      .getService(Components.interfaces.nsIPrefBranch);
  1.1038 +          let userWantsPrefill = true;
  1.1039 +          this.open(aMode);
  1.1040 +
  1.1041 +          if (this._flashFindBar) {
  1.1042 +            this._flashFindBarTimeout = setInterval(() => this._flash(), 500);
  1.1043 +            prefsvc.setIntPref("accessibility.typeaheadfind.flashBar",
  1.1044 +                               --this._flashFindBar);
  1.1045 +          }
  1.1046 +
  1.1047 +          if (this.prefillWithSelection)
  1.1048 +            userWantsPrefill =
  1.1049 +              prefsvc.getBoolPref("accessibility.typeaheadfind.prefillwithselection");
  1.1050 +
  1.1051 +          let initialString = null;
  1.1052 +          if (this.prefillWithSelection && userWantsPrefill)
  1.1053 +            initialString = this._getInitialSelection();
  1.1054 +#ifdef XP_MACOSX
  1.1055 +          if (!initialString) {
  1.1056 +            let clipboardSearchString = this.browser.finder.clipboardSearchString;
  1.1057 +            if (clipboardSearchString)
  1.1058 +              initialString = clipboardSearchString;
  1.1059 +          }
  1.1060 +#endif
  1.1061 +
  1.1062 +          if (initialString)
  1.1063 +            this._findField.value = initialString;
  1.1064 +
  1.1065 +          this._enableFindButtons(!!this._findField.value);
  1.1066 +
  1.1067 +          this._findField.select();
  1.1068 +          this._findField.focus();
  1.1069 +        ]]></body>
  1.1070 +      </method>
  1.1071 +
  1.1072 +      <!--
  1.1073 +        - Convenient alias to startFind(gFindBar.FIND_NORMAL);
  1.1074 +        -
  1.1075 +        - You should generally map the window's find command to this method.
  1.1076 +        -   e.g. <command name="cmd_find" oncommand="gFindBar.onFindCommand();"/>
  1.1077 +        -->
  1.1078 +      <method name="onFindCommand">
  1.1079 +        <body><![CDATA[
  1.1080 +          this.startFind(this.FIND_NORMAL);
  1.1081 +        ]]></body>
  1.1082 +      </method>
  1.1083 +
  1.1084 +      <!--
  1.1085 +        - Stub for find-next and find-previous commands
  1.1086 +        - @param aFindPrevious
  1.1087 +        -        true for find-previous, false otherwise.
  1.1088 +        -->
  1.1089 +      <method name="onFindAgainCommand">
  1.1090 +        <parameter name="aFindPrevious"/>
  1.1091 +        <body><![CDATA[
  1.1092 +          let findString = this._browser.finder.searchString || this._findField.value;
  1.1093 +          if (!findString) {
  1.1094 +            this.startFind();
  1.1095 +            return;
  1.1096 +          }
  1.1097 +
  1.1098 +          // We dispatch the findAgain event here instead of in _findAgain since
  1.1099 +          // if there is a find event handler that prevents the default then
  1.1100 +          // finder.searchString will never get updated which in turn means
  1.1101 +          // there would never be findAgain events because of the logic below.
  1.1102 +          if (!this._dispatchFindEvent("again", aFindPrevious))
  1.1103 +            return;
  1.1104 +
  1.1105 +          // user explicitly requested another search, so do it even if we think it'll fail
  1.1106 +          this._findFailedString = null;
  1.1107 +
  1.1108 +          // Ensure the stored SearchString is in sync with what we want to find
  1.1109 +          if (this._findField.value != this._browser.finder.searchString)
  1.1110 +            this._find(this._findField.value);
  1.1111 +          else
  1.1112 +            this._findAgain(aFindPrevious);
  1.1113 +
  1.1114 +        ]]></body>
  1.1115 +      </method>
  1.1116 +
  1.1117 +#ifdef XP_MACOSX
  1.1118 +      <!--
  1.1119 +        - Fetches the currently selected text and sets that as the text to search
  1.1120 +        - next. This is a MacOS specific feature.
  1.1121 +      -->
  1.1122 +      <method name="onFindSelectionCommand">
  1.1123 +        <body><![CDATA[
  1.1124 +          let searchString = this.browser.finder.setSearchStringToSelection();
  1.1125 +          if (searchString)
  1.1126 +            this._findField.value = searchString;
  1.1127 +        ]]></body>
  1.1128 +      </method>
  1.1129 +
  1.1130 +      <method name="_onFindFieldFocus">
  1.1131 +        <body><![CDATA[
  1.1132 +          let prefsvc =
  1.1133 +            Components.classes["@mozilla.org/preferences-service;1"]
  1.1134 +                      .getService(Components.interfaces.nsIPrefBranch);
  1.1135 +          const kPref = "accessibility.typeaheadfind.prefillwithselection";
  1.1136 +          if (this.prefillWithSelection && prefsvc.getBoolPref(kPref))
  1.1137 +            return;
  1.1138 +
  1.1139 +          let clipboardSearchString = this._browser.finder.clipboardSearchString;
  1.1140 +          if (clipboardSearchString && this._findField.value != clipboardSearchString) {
  1.1141 +            this._findField.value = clipboardSearchString;
  1.1142 +            // Changing the search string makes the previous status invalid, so
  1.1143 +            // we better clear it here.
  1.1144 +            this._updateStatusUI();
  1.1145 +          }
  1.1146 +        ]]></body>
  1.1147 +      </method>
  1.1148 +#endif
  1.1149 +
  1.1150 +      <!--
  1.1151 +        - This handles all the result changes for both
  1.1152 +        - type-ahead-find and highlighting.
  1.1153 +        - @param aResult
  1.1154 +        -   One of the nsITypeAheadFind.FIND_* constants
  1.1155 +        -   indicating the result of a search operation.
  1.1156 +        - @param aFindBackwards
  1.1157 +        -   If the search was done from the bottom to
  1.1158 +        -   the top. This is used for right error messages
  1.1159 +        -   when reaching "the end of the page".
  1.1160 +        - @param aLinkURL
  1.1161 +        -   When a link matched then its URK. Always null
  1.1162 +        -   when not in FIND_LINKS mode.
  1.1163 +        -->
  1.1164 +      <method name="onFindResult">
  1.1165 +        <parameter name="aData"/>
  1.1166 +        <body><![CDATA[
  1.1167 +          if (aData.storeResult && this._findField.value != this.browser.finder.searchString)
  1.1168 +            this._findField.value = this.browser.finder.searchString;
  1.1169 +          this._updateStatusUI(aData.result, aData.findBackwards);
  1.1170 +          this._updateStatusUIBar(aData.linkURL);
  1.1171 +
  1.1172 +          if (aData.result == this.nsITypeAheadFind.FIND_NOTFOUND)
  1.1173 +            this._findFailedString = aData.searchString;
  1.1174 +          else
  1.1175 +            this._findFailedString = null;
  1.1176 +
  1.1177 +          if (this._findMode != this.FIND_NORMAL)
  1.1178 +            this._setFindCloseTimeout();
  1.1179 +        ]]></body>
  1.1180 +      </method>
  1.1181 +
  1.1182 +      <!--
  1.1183 +        - This handler may cancel a request to focus content by returning |false|
  1.1184 +        - explicitly.
  1.1185 +        -->
  1.1186 +      <method name="shouldFocusContent">
  1.1187 +        <body><![CDATA[
  1.1188 +          const fm = Components.classes["@mozilla.org/focus-manager;1"]
  1.1189 +                               .getService(Components.interfaces.nsIFocusManager);
  1.1190 +          if (fm.focusedWindow != window)
  1.1191 +            return false;
  1.1192 +
  1.1193 +          let focusedElement = fm.focusedElement;
  1.1194 +          if (!focusedElement)
  1.1195 +            return false;
  1.1196 +
  1.1197 +          let bindingParent = document.getBindingParent(focusedElement);
  1.1198 +          if (bindingParent != this && bindingParent != this._findField)
  1.1199 +            return false;
  1.1200 +
  1.1201 +          return true;
  1.1202 +        ]]></body>
  1.1203 +      </method>
  1.1204 +
  1.1205 +    </implementation>
  1.1206 +
  1.1207 +    <handlers>
  1.1208 +      <!--
  1.1209 +        - We have to guard against `this.close` being |null| due to an unknown
  1.1210 +        - issue, which is tracked in bug 957999.
  1.1211 +        -->
  1.1212 +      <handler event="keypress" keycode="VK_ESCAPE" phase="capturing"
  1.1213 +               action="if (this.close) this.close();" preventdefault="true"/>
  1.1214 +    </handlers>
  1.1215 +  </binding>
  1.1216 +</bindings>

mercurial