PageRenderTime 57ms CodeModel.GetById 19ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/toolkit/content/widgets/autocomplete.xml

http://github.com/zpao/v8monkey
XML | 1739 lines | 1442 code | 257 blank | 40 comment | 0 complexity | 3b18134aa42af92aae058b387b993807 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?xml version="1.0"?>
   2
   3# -*- Mode: HTML -*-
   4# ***** BEGIN LICENSE BLOCK *****
   5# Version: MPL 1.1/GPL 2.0/LGPL 2.1
   6#
   7# The contents of this file are subject to the Mozilla Public License Version
   8# 1.1 (the "License"); you may not use this file except in compliance with
   9# the License. You may obtain a copy of the License at
  10# http://www.mozilla.org/MPL/
  11#
  12# Software distributed under the License is distributed on an "AS IS" basis,
  13# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14# for the specific language governing rights and limitations under the
  15# License.
  16#
  17# The Original Code is mozilla.org browser.
  18#
  19# The Initial Developer of the Original Code is
  20# Joe Hewitt.
  21# Portions created by the Initial Developer are Copyright (C) 2003
  22# the Initial Developer. All Rights Reserved.
  23#
  24# Contributor(s):
  25#   Pierre Chanial (p_ch@verizon.net)
  26#   Dean Tessman   (dean_tessman@hotmail.com)
  27#   Masayuki Nakano (masayuki@d-toybox.com)
  28#   Pamela Greene (pamg.bugs@gmail.com)
  29#   Edward Lee (edward.lee@engineering.uiuc.edu)
  30#   Drew Willcoxon (adw@mozilla.com)
  31#
  32# Alternatively, the contents of this file may be used under the terms of
  33# either the GNU General Public License Version 2 or later (the "GPL"), or
  34# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  35# in which case the provisions of the GPL or the LGPL are applicable instead
  36# of those above. If you wish to allow use of your version of this file only
  37# under the terms of either the GPL or the LGPL, and not to allow others to
  38# use your version of this file under the terms of the MPL, indicate your
  39# decision by deleting the provisions above and replace them with the notice
  40# and other provisions required by the GPL or the LGPL. If you do not delete
  41# the provisions above, a recipient may use your version of this file under
  42# the terms of any one of the MPL, the GPL or the LGPL.
  43#
  44# ***** END LICENSE BLOCK *****
  45
  46<!DOCTYPE bindings [
  47<!ENTITY % actionsDTD SYSTEM "chrome://global/locale/actions.dtd">
  48%actionsDTD;
  49]>
  50
  51<bindings id="autocompleteBindings"
  52          xmlns="http://www.mozilla.org/xbl"
  53          xmlns:html="http://www.w3.org/1999/xhtml"
  54          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  55          xmlns:xbl="http://www.mozilla.org/xbl">
  56
  57  <binding id="autocomplete"
  58           extends="chrome://global/content/bindings/textbox.xml#textbox">
  59    <resources>
  60      <stylesheet src="chrome://global/skin/autocomplete.css"/>
  61    </resources>
  62
  63    <content sizetopopup="pref">
  64      <xul:hbox class="autocomplete-textbox-container" flex="1" xbl:inherits="focused">
  65        <children includes="image|deck|stack|box">
  66          <xul:image class="autocomplete-icon" allowevents="true"/>
  67        </children>
  68
  69        <xul:hbox anonid="textbox-input-box" class="textbox-input-box" flex="1" xbl:inherits="tooltiptext=inputtooltiptext">
  70          <children/>
  71          <html:input anonid="input" class="autocomplete-textbox textbox-input"
  72                      allowevents="true"
  73                      xbl:inherits="tooltiptext=inputtooltiptext,onfocus,onblur,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint"/>
  74        </xul:hbox>
  75        <children includes="hbox"/>
  76      </xul:hbox>
  77
  78      <xul:dropmarker anonid="historydropmarker" class="autocomplete-history-dropmarker"
  79                      allowevents="true"
  80                      xbl:inherits="open,enablehistory,parentfocused=focused"/>
  81
  82      <xul:popupset anonid="popupset" class="autocomplete-result-popupset"/>
  83
  84      <children includes="toolbarbutton"/>
  85    </content>
  86
  87    <implementation implements="nsIAccessibleProvider, nsIAutoCompleteInput, nsIDOMXULMenuListElement">
  88      <field name="mController">null</field>
  89      <field name="mSearchNames">null</field>
  90      <field name="mIgnoreInput">false</field>
  91      <field name="mEnterEvent">null</field>
  92      <field name="mConsumeRollupEvent">false</field>
  93
  94      <constructor><![CDATA[
  95        mController = Components.classes["@mozilla.org/autocomplete/controller;1"].
  96                        getService(Components.interfaces.nsIAutoCompleteController);
  97
  98        // For security reasons delay searches on pasted values.
  99        this.inputField.controllers.insertControllerAt(0, this._pasteController);
 100      ]]></constructor>
 101
 102      <destructor><![CDATA[
 103        this.inputField.controllers.removeController(this._pasteController);
 104      ]]></destructor>
 105
 106      <!-- =================== nsIAccessibleProvider =================== -->
 107
 108      <property name="accessibleType" readonly="true">
 109        <getter>
 110          <![CDATA[
 111            // Will be exposed as nsIAccessible::ROLE_AUTOCOMPLETE
 112            return Components.interfaces.nsIAccessibleProvider.XULCombobox;
 113          ]]>
 114        </getter>
 115      </property>
 116
 117      <!-- =================== nsIAutoCompleteInput =================== -->
 118
 119      <field name="popup"><![CDATA[
 120        // Wrap in a block so that the let statements don't
 121        // create properties on 'this' (bug 635252).
 122        {
 123          let popup = null;
 124          let popupId = this.getAttribute("autocompletepopup");
 125          if (popupId)
 126            popup = document.getElementById(popupId);
 127          if (!popup) {
 128            popup = document.createElement("panel");
 129            popup.setAttribute("type", "autocomplete");
 130            popup.setAttribute("noautofocus", "true");
 131
 132            let popupset = document.getAnonymousElementByAttribute(this, "anonid", "popupset");
 133            popupset.appendChild(popup);
 134          }
 135          popup.mInput = this;
 136          popup;
 137        }
 138      ]]></field>
 139
 140      <property name="controller" onget="return this.mController;" readonly="true"/>
 141
 142      <property name="popupOpen"
 143                onget="return this.popup.popupOpen;"
 144                onset="if (val) this.openPopup(); else this.closePopup();"/>
 145
 146      <property name="disableAutoComplete"
 147                onset="this.setAttribute('disableautocomplete', val); return val;"
 148                onget="return this.getAttribute('disableautocomplete') == 'true';"/>
 149
 150      <property name="completeDefaultIndex"
 151                onset="this.setAttribute('completedefaultindex', val); return val;"
 152                onget="return this.getAttribute('completedefaultindex') == 'true';"/>
 153
 154      <property name="completeSelectedIndex"
 155                onset="this.setAttribute('completeselectedindex', val); return val;"
 156                onget="return this.getAttribute('completeselectedindex') == 'true';"/>
 157
 158      <property name="forceComplete"
 159                onset="this.setAttribute('forcecomplete', val); return val;"
 160                onget="return this.getAttribute('forcecomplete') == 'true';"/>
 161
 162      <property name="minResultsForPopup"
 163                onset="this.setAttribute('minresultsforpopup', val); return val;"
 164                onget="var m = parseInt(this.getAttribute('minresultsforpopup')); return isNaN(m) ? 1 : m;"/>
 165
 166      <property name="showCommentColumn"
 167                onset="this.setAttribute('showcommentcolumn', val); return val;"
 168                onget="return this.getAttribute('showcommentcolumn') == 'true';"/>
 169
 170      <property name="showImageColumn"
 171                onset="this.setAttribute('showimagecolumn', val); return val;"
 172                onget="return this.getAttribute('showimagecolumn') == 'true';"/>
 173
 174      <property name="timeout"
 175                onset="this.setAttribute('timeout', val); return val;">
 176        <getter><![CDATA[
 177          // For security reasons delay searches on pasted values. 
 178          if (this._valueIsPasted) {
 179            let t = parseInt(this.getAttribute('pastetimeout'));
 180            return isNaN(t) ? 1000 : t;
 181          }
 182
 183          let t = parseInt(this.getAttribute('timeout'));
 184          return isNaN(t) ? 50 : t;
 185        ]]></getter>
 186      </property>
 187
 188      <property name="searchParam"
 189                onget="return this.getAttribute('autocompletesearchparam') || '';"
 190                onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
 191
 192      <property name="searchCount" readonly="true"
 193                onget="this.initSearchNames(); return this.mSearchNames.length;"/>
 194
 195      <property name="consumeRollupEvent" readonly="true"
 196                onget="return this.mConsumeRollupEvent;"/>
 197
 198      <!-- This is the maximum number of drop-down rows we get when we
 199            hit the drop marker beside fields that have it (like the URLbar).-->
 200      <field name="maxDropMarkerRows" readonly="true">14</field>
 201
 202      <method name="getSearchAt">
 203        <parameter name="aIndex"/>
 204        <body><![CDATA[
 205          this.initSearchNames();
 206          return this.mSearchNames[aIndex];
 207        ]]></body>
 208      </method>
 209
 210      <property name="textValue"
 211                onget="return this.value;">
 212        <setter><![CDATA[
 213          // Completing a result should simulate the user typing the result,
 214          // so fire an input event.
 215          // Trim popup selected values, but never trim results coming from
 216          // autofill.
 217          if (this.popup.selectedIndex == -1)
 218            this._disableTrim = true;
 219          this.value = val;
 220          this._disableTrim = false;
 221
 222          var evt = document.createEvent("UIEvents");
 223          evt.initUIEvent("input", true, false, window, 0);
 224          this.mIgnoreInput = true;
 225          this.dispatchEvent(evt);
 226          this.mIgnoreInput = false;
 227          return this.value;
 228        ]]></setter>
 229      </property>
 230
 231      <method name="selectTextRange">
 232        <parameter name="aStartIndex"/>
 233        <parameter name="aEndIndex"/>
 234        <body><![CDATA[
 235          this.inputField.setSelectionRange(aStartIndex, aEndIndex);
 236        ]]></body>
 237      </method>
 238
 239      <method name="onSearchBegin">
 240        <body><![CDATA[
 241          this.fireEvent("searchbegin");
 242        ]]></body>
 243      </method>
 244
 245      <method name="onSearchComplete">
 246        <body><![CDATA[
 247          if (this.mController.matchCount == 0)
 248            this.setAttribute("nomatch", "true");
 249          else
 250            this.removeAttribute("nomatch");
 251
 252          this.fireEvent("searchcomplete");
 253        ]]></body>
 254      </method>
 255
 256      <method name="onTextEntered">
 257        <body><![CDATA[
 258          var rv = this.fireEvent("textentered", this.mEnterEvent);
 259          this.mEnterEvent = null;
 260          return rv;
 261        ]]></body>
 262      </method>
 263
 264      <method name="onTextReverted">
 265        <body><![CDATA[
 266          return this.fireEvent("textreverted");
 267        ]]></body>
 268      </method>
 269
 270      <!-- =================== nsIDOMXULMenuListElement =================== -->
 271
 272      <property name="editable" readonly="true"
 273                onget="return true;" />
 274
 275      <property name="crop"
 276                onset="this.setAttribute('crop',val); return val;"
 277                onget="return this.getAttribute('crop');"/>
 278
 279      <property name="open"
 280                onget="return this.getAttribute('open') == 'true';">
 281        <setter><![CDATA[
 282          if (val)
 283            this.showHistoryPopup();
 284          else
 285            this.closePopup();
 286        ]]></setter>
 287      </property>
 288
 289      <!-- =================== PUBLIC MEMBERS =================== -->
 290
 291      <field name="valueIsTyped">false</field>
 292      <field name="_disableTrim">false</field>
 293      <property name="value">
 294        <getter><![CDATA[
 295          if (typeof this.onBeforeValueGet == "function") {
 296            var result = this.onBeforeValueGet();
 297            if (result)
 298              return result.value;
 299          }
 300          return this.inputField.value;
 301        ]]></getter>
 302        <setter><![CDATA[
 303          this.mIgnoreInput = true;
 304
 305          if (typeof this.onBeforeValueSet == "function")
 306            val = this.onBeforeValueSet(val);
 307
 308          if (typeof this.trimValue == "function" && !this._disableTrim)
 309            val = this.trimValue(val);
 310
 311          this.valueIsTyped = false;
 312          this.inputField.value = val;
 313
 314          if (typeof this.formatValue == "function")
 315            this.formatValue();
 316
 317          this.mIgnoreInput = false;
 318          var event = document.createEvent('Events');
 319          event.initEvent('ValueChange', true, true);
 320          this.inputField.dispatchEvent(event);
 321          return val;
 322        ]]></setter>
 323      </property>
 324
 325      <property name="focused" readonly="true"
 326                onget="return this.getAttribute('focused') == 'true';"/>
 327
 328      <!-- maximum number of rows to display at a time -->
 329      <property name="maxRows"
 330                onset="this.setAttribute('maxrows', val); return val;"
 331                onget="return parseInt(this.getAttribute('maxrows')) || 0;"/>
 332
 333      <!-- option to allow scrolling through the list via the tab key, rather than
 334           tab moving focus out of the textbox -->
 335      <property name="tabScrolling"
 336                onset="return this.setAttribute('tabscrolling', val); return val;"
 337                onget="return this.getAttribute('tabscrolling') == 'true';"/>
 338
 339      <!-- disable key navigation handling in the popup results -->
 340      <property name="disableKeyNavigation"
 341                onset="this.setAttribute('disablekeynavigation', val); return val;"
 342                onget="return this.getAttribute('disablekeynavigation') == 'true';"/>
 343
 344      <!-- option to completely ignore any blur events while
 345           searches are still going on.  This is useful so that nothing
 346           gets autopicked if the window is required to lose focus for
 347           some reason (eg in LDAP autocomplete, another window may be
 348           brought up so that the user can enter a password to authenticate
 349           to an LDAP server).  -->
 350      <property name="ignoreBlurWhileSearching"
 351                onset="this.setAttribute('ignoreblurwhilesearching', val); return val;"
 352                onget="return this.getAttribute('ignoreblurwhilesearching') == 'true';"/>
 353
 354      <!-- option to highlight entries that don't have any matches -->
 355      <property name="highlightNonMatches"
 356                onset="this.setAttribute('highlightnonmatches', val); return val;"
 357                onget="return this.getAttribute('highlightnonmatches') == 'true';"/>
 358
 359      <!-- =================== PRIVATE MEMBERS =================== -->
 360
 361      <!-- ::::::::::::: autocomplete controller ::::::::::::: -->
 362
 363      <method name="attachController">
 364        <body><![CDATA[
 365          this.mController.input = this;
 366        ]]></body>
 367      </method>
 368
 369      <method name="detachController">
 370        <body><![CDATA[
 371          try {
 372            if  (this.mController.input == this)
 373            this.mController.input = null;
 374          } catch (ex) {
 375            // nothing really to do.
 376          }
 377        ]]></body>
 378      </method>
 379
 380      <!-- ::::::::::::: popup opening ::::::::::::: -->
 381
 382      <method name="openPopup">
 383        <body><![CDATA[
 384          this.popup.openAutocompletePopup(this, this);
 385        ]]></body>
 386      </method>
 387
 388      <method name="closePopup">
 389        <body><![CDATA[
 390          this.mConsumeRollupEvent = false;
 391          this.popup.closePopup();
 392        ]]></body>
 393      </method>
 394
 395      <method name="showHistoryPopup">
 396        <body><![CDATA[
 397          // history dropmarker pushed state
 398          function cleanup(popup) {
 399            popup.removeEventListener("popupshowing", onShow, false);
 400          }
 401          function onShow(event) {
 402            var popup = event.target, input = popup.input;
 403            cleanup(popup);
 404            input.setAttribute("open", "true");
 405            function onHide() {
 406              input.removeAttribute("open");
 407              input.mConsumeRollupEvent = false;
 408              popup.removeEventListener("popuphiding", onHide, false);
 409            }
 410            popup.addEventListener("popuphiding", onHide, false);
 411          }
 412          this.popup.addEventListener("popupshowing", onShow, false);
 413          setTimeout(cleanup, 1000, this.popup);
 414
 415          // Store our "normal" maxRows on the popup, so that it can reset the
 416          // value when the popup is hidden.
 417          this.popup._normalMaxRows = this.maxRows;
 418
 419          // Increase our maxRows temporarily, since we want the dropdown to
 420          // be bigger in this case. The popup's popupshowing/popuphiding
 421          // handlers will take care of resetting this.
 422          this.maxRows = this.maxDropMarkerRows;
 423
 424          // Ensure that we have focus.
 425          if (!this.focused)
 426            this.focus();
 427          this.mConsumeRollupEvent = true;
 428          this.attachController();
 429          this.mController.startSearch("");
 430        ]]></body>
 431      </method>
 432
 433      <method name="toggleHistoryPopup">
 434        <body><![CDATA[
 435          if (!this.popup.mPopupOpen)
 436            this.showHistoryPopup();
 437          else
 438            this.closePopup();
 439        ]]></body>
 440      </method>
 441
 442      <!-- ::::::::::::: event dispatching ::::::::::::: -->
 443
 444      <method name="fireEvent">
 445        <parameter name="aEventType"/>
 446        <body><![CDATA[
 447          var cancel = false;
 448          // handle any xml attribute event handlers
 449          var handler = this.getAttribute("on"+aEventType);
 450          if (handler) {
 451            var fn = new Function("eventType", "param", handler);
 452            cancel = fn.apply(this, arguments);
 453          }
 454
 455          return cancel;
 456        ]]></body>
 457      </method>
 458
 459      <!-- ::::::::::::: key handling ::::::::::::: -->
 460
 461      <method name="onKeyPress">
 462        <parameter name="aEvent"/>
 463        <body><![CDATA[
 464          if (aEvent.target.localName != "textbox")
 465            return;  // Let child buttons of autocomplete take input
 466
 467          //XXXpch this is so bogus...
 468          if (aEvent.defaultPrevented)
 469            return false;
 470
 471          var cancel = false;
 472
 473          // Catch any keys that could potentially move the caret. Ctrl can be
 474          // used in combination with these keys on Windows and Linux; and Alt
 475          // can be used on OS X, so make sure the unused one isn't used.
 476          if (!this.disableKeyNavigation &&
 477#ifdef XP_MACOSX
 478              !aEvent.ctrlKey) {
 479#else
 480              !aEvent.altKey) {
 481#endif
 482            switch (aEvent.keyCode) {
 483              case KeyEvent.DOM_VK_LEFT:
 484              case KeyEvent.DOM_VK_RIGHT:
 485              case KeyEvent.DOM_VK_HOME:
 486                cancel = this.mController.handleKeyNavigation(aEvent.keyCode);
 487                break;
 488            }
 489          }
 490
 491          // Handle keys that are not part of a keyboard shortcut (no Ctrl or Alt)
 492          if (!this.disableKeyNavigation && !aEvent.ctrlKey && !aEvent.altKey) {
 493            switch (aEvent.keyCode) {
 494              case KeyEvent.DOM_VK_TAB:
 495                if (this.tabScrolling && this.popup.mPopupOpen)
 496                  cancel = this.mController.handleKeyNavigation(aEvent.shiftKey ?
 497                                                                KeyEvent.DOM_VK_UP :
 498                                                                KeyEvent.DOM_VK_DOWN);
 499                break;
 500              case KeyEvent.DOM_VK_UP:
 501              case KeyEvent.DOM_VK_DOWN:
 502              case KeyEvent.DOM_VK_PAGE_UP:
 503              case KeyEvent.DOM_VK_PAGE_DOWN:
 504                cancel = this.mController.handleKeyNavigation(aEvent.keyCode);
 505                break;
 506            }
 507          }
 508
 509          // Handle keys we know aren't part of a shortcut, even with Alt or
 510          // Ctrl.
 511          switch (aEvent.keyCode) {
 512            case KeyEvent.DOM_VK_ESCAPE:
 513              cancel = this.mController.handleEscape();
 514              break;
 515            case KeyEvent.DOM_VK_RETURN:
 516#ifdef XP_MACOSX
 517              // Prevent the default action, since it will beep on Mac
 518              if (aEvent.metaKey)
 519                aEvent.preventDefault();
 520#endif
 521              this.mEnterEvent = aEvent;
 522              cancel = this.mController.handleEnter(false);
 523              break;
 524            case KeyEvent.DOM_VK_DELETE:
 525#ifdef XP_MACOSX
 526            case KeyEvent.DOM_VK_BACK_SPACE:
 527              if (aEvent.shiftKey)
 528#endif
 529              cancel = this.mController.handleDelete();
 530              break;
 531            case KeyEvent.DOM_VK_DOWN:
 532            case KeyEvent.DOM_VK_UP:
 533              if (aEvent.altKey)
 534                this.toggleHistoryPopup();
 535              break;
 536#ifndef XP_MACOSX
 537            case KeyEvent.DOM_VK_F4:
 538              this.toggleHistoryPopup();
 539              break;
 540#endif
 541          }
 542
 543          if (cancel) {
 544            aEvent.stopPropagation();
 545            aEvent.preventDefault();
 546          }
 547
 548          return true;
 549        ]]></body>
 550      </method>
 551
 552      <!-- ::::::::::::: miscellaneous ::::::::::::: -->
 553
 554      <method name="initSearchNames">
 555        <body><![CDATA[
 556          if (!this.mSearchNames) {
 557            var names = this.getAttribute("autocompletesearch");
 558            if (!names)
 559              this.mSearchNames = [];
 560            else
 561              this.mSearchNames = names.split(" ");
 562          }
 563        ]]></body>
 564      </method>
 565
 566      <method name="_focus">
 567        <!-- doesn't reset this.mController -->
 568        <body><![CDATA[
 569          this._dontBlur = true;
 570          this.focus();
 571          this._dontBlur = false;
 572        ]]></body>
 573      </method>
 574
 575      <method name="resetActionType">
 576        <body><![CDATA[
 577          if (this.mIgnoreInput)
 578            return;
 579          this.removeAttribute("actiontype");
 580        ]]></body>
 581      </method>
 582
 583      <field name="_valueIsPasted">false</field>
 584      <field name="_pasteController"><![CDATA[
 585        ({
 586          _autocomplete: this,
 587          _kGlobalClipboard: Components.interfaces.nsIClipboard.kGlobalClipboard,
 588          supportsCommand: function(aCommand) aCommand == "cmd_paste",
 589          doCommand: function(aCommand) {
 590            this._autocomplete._valueIsPasted = true;
 591            this._autocomplete.editor.paste(this._kGlobalClipboard);
 592            this._autocomplete._valueIsPasted = false;
 593          },
 594          isCommandEnabled: function(aCommand) {
 595            return this._autocomplete.editor.isSelectionEditable &&
 596                   this._autocomplete.editor.canPaste(this._kGlobalClipboard);
 597          },
 598          onEvent: function() {}
 599        })
 600      ]]></field>
 601    </implementation>
 602
 603    <handlers>
 604      <handler event="input"><![CDATA[
 605        if (!this.mIgnoreInput && this.mController.input == this) {
 606          this.valueIsTyped = true;
 607          this.mController.handleText();
 608        }
 609        this.resetActionType();
 610      ]]></handler>
 611
 612      <handler event="keypress" phase="capturing"
 613               action="return this.onKeyPress(event);"/>
 614
 615      <handler event="compositionstart" phase="capturing"
 616               action="if (this.mController.input == this) this.mController.handleStartComposition();"/>
 617
 618      <handler event="compositionend" phase="capturing"
 619               action="if (this.mController.input == this) this.mController.handleEndComposition();"/>
 620
 621      <handler event="focus" phase="capturing"
 622               action="this.attachController();"/>
 623
 624      <handler event="blur" phase="capturing"
 625               action="if (!this._dontBlur) this.detachController();"/>
 626    </handlers>
 627  </binding>
 628
 629  <binding id="autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-base-popup">
 630    <resources>
 631      <stylesheet src="chrome://global/skin/tree.css"/>
 632      <stylesheet src="chrome://global/skin/autocomplete.css"/>
 633    </resources>
 634
 635    <content ignorekeys="true" level="top">
 636      <xul:tree anonid="tree" class="autocomplete-tree plain" hidecolumnpicker="true" flex="1" seltype="single">
 637        <xul:treecols anonid="treecols">
 638          <xul:treecol id="treecolAutoCompleteValue" class="autocomplete-treecol" flex="1" overflow="true"/>
 639        </xul:treecols>
 640        <xul:treechildren class="autocomplete-treebody"/>
 641      </xul:tree>
 642    </content>
 643
 644    <implementation>
 645      <field name="mShowCommentColumn">false</field>
 646      <field name="mShowImageColumn">false</field>
 647
 648      <property name="showCommentColumn"
 649                   onget="return this.mShowCommentColumn;">
 650        <setter>
 651          <![CDATA[
 652          if (!val && this.mShowCommentColumn) {
 653            // reset the flex on the value column and remove the comment column
 654            document.getElementById("treecolAutoCompleteValue").setAttribute("flex", 1);
 655            this.removeColumn("treecolAutoCompleteComment");
 656          } else if (val && !this.mShowCommentColumn) {
 657            // reset the flex on the value column and add the comment column
 658            document.getElementById("treecolAutoCompleteValue").setAttribute("flex", 2);
 659            this.addColumn({id: "treecolAutoCompleteComment", flex: 1});
 660          }
 661          this.mShowCommentColumn = val;
 662          return val;
 663        ]]>
 664        </setter>
 665      </property>
 666
 667      <property name="showImageColumn"
 668                onget="return this.mShowImageColumn;">
 669        <setter>
 670          <![CDATA[
 671          if (!val && this.mShowImageColumn) {
 672            // remove the image column
 673            this.removeColumn("treecolAutoCompleteImage");
 674          } else if (val && !this.mShowImageColumn) {
 675            // add the image column
 676            this.addColumn({id: "treecolAutoCompleteImage", flex: 1});
 677          }
 678          this.mShowImageColumn = val;
 679          return val;
 680        ]]>
 681        </setter>
 682      </property>
 683
 684
 685      <method name="addColumn">
 686        <parameter name="aAttrs"/>
 687        <body>
 688          <![CDATA[
 689          var col = document.createElement("treecol");
 690          col.setAttribute("class", "autocomplete-treecol");
 691          for (var name in aAttrs)
 692            col.setAttribute(name, aAttrs[name]);
 693          this.treecols.appendChild(col);
 694          return col;
 695        ]]>
 696        </body>
 697      </method>
 698
 699      <method name="removeColumn">
 700        <parameter name="aColId"/>
 701        <body>
 702          <![CDATA[
 703          return this.treecols.removeChild(document.getElementById(aColId));
 704        ]]>
 705        </body>
 706      </method>
 707
 708      <property name="selectedIndex"
 709                onget="return this.tree.currentIndex;">
 710        <setter>
 711          <![CDATA[
 712          this.tree.view.selection.select(val);
 713          if (this.tree.treeBoxObject.height > 0)
 714            this.tree.treeBoxObject.ensureRowIsVisible(val < 0 ? 0 : val);
 715          // Fire select event on xul:tree so that accessibility API
 716          // support layer can fire appropriate accessibility events.
 717          var event = document.createEvent('Events');
 718          event.initEvent("select", true, true);
 719          this.tree.dispatchEvent(event);
 720          return val;
 721        ]]></setter>
 722      </property>
 723
 724      <method name="adjustHeight">
 725        <body>
 726          <![CDATA[
 727          // detect the desired height of the tree
 728          var bx = this.tree.treeBoxObject;
 729          var view = this.tree.view;
 730          if (!view)
 731            return;
 732          var rows = this.maxRows;
 733          if (!view.rowCount || (rows && view.rowCount < rows))
 734            rows = view.rowCount;
 735
 736          var height = rows * bx.rowHeight;
 737
 738          if (height == 0)
 739            this.tree.setAttribute("collapsed", "true");
 740          else {
 741            if (this.tree.hasAttribute("collapsed"))
 742              this.tree.removeAttribute("collapsed");
 743
 744            this.tree.setAttribute("height", height);
 745          }
 746          this.tree.setAttribute("hidescrollbar", view.rowCount <= rows);
 747        ]]>
 748        </body>
 749      </method>
 750
 751      <method name="openAutocompletePopup">
 752        <parameter name="aInput"/>
 753        <parameter name="aElement"/>
 754        <body><![CDATA[
 755          // until we have "baseBinding", (see bug #373652) this allows
 756          // us to override openAutocompletePopup(), but still call
 757          // the method on the base class
 758          this._openAutocompletePopup(aInput, aElement);
 759        ]]></body>
 760      </method>
 761
 762      <method name="_openAutocompletePopup">
 763        <parameter name="aInput"/>
 764        <parameter name="aElement"/>
 765        <body><![CDATA[
 766          if (!this.mPopupOpen) {
 767            this.mInput = aInput;
 768            this.view = aInput.controller.QueryInterface(Components.interfaces.nsITreeView);
 769            this.invalidate();
 770
 771            this.showCommentColumn = this.mInput.showCommentColumn;
 772            this.showImageColumn = this.mInput.showImageColumn;
 773
 774            var rect = aElement.getBoundingClientRect();
 775            var nav = aElement.ownerDocument.defaultView.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 776                              .getInterface(Components.interfaces.nsIWebNavigation);
 777            var docShell = nav.QueryInterface(Components.interfaces.nsIDocShell);
 778            var docViewer = docShell.contentViewer.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
 779            var width = (rect.right - rect.left) * docViewer.fullZoom;
 780            this.setAttribute("width", width > 100 ? width : 100);
 781
 782            // Adjust the direction of the autocomplete popup list based on the textbox direction, bug 649840
 783            var popupDirection = aElement.ownerDocument.defaultView.getComputedStyle(aElement).direction;
 784            this.style.direction = popupDirection;
 785
 786            // setConsumeRollupEvent() before we call openPopup()
 787            var nsIPopupBO = Components.interfaces.nsIPopupBoxObject;
 788            this.popupBoxObject.setConsumeRollupEvent(
 789              this.mInput.consumeRollupEvent ?
 790                nsIPopupBO.ROLLUP_CONSUME :
 791                nsIPopupBO.ROLLUP_NO_CONSUME);
 792            this.openPopup(aElement, "after_start", 0, 0, false, false);
 793          }
 794        ]]></body>
 795      </method>
 796
 797      <method name="invalidate">
 798        <body><![CDATA[
 799          this.adjustHeight();
 800          this.tree.treeBoxObject.invalidate();
 801        ]]></body>
 802      </method>
 803
 804      <method name="selectBy">
 805        <parameter name="aReverse"/>
 806        <parameter name="aPage"/>
 807        <body><![CDATA[
 808          try {
 809            var amount = aPage ? 5 : 1;
 810            this.selectedIndex = this.getNextIndex(aReverse, amount, this.selectedIndex, this.tree.view.rowCount-1);
 811            if (this.selectedIndex == -1) {
 812              this.input._focus();
 813            }
 814          } catch (ex) {
 815            // do nothing - occasionally timer-related js errors happen here
 816            // e.g. "this.selectedIndex has no properties", when you type fast and hit a
 817            // navigation key before this popup has opened
 818          }
 819        ]]></body>
 820      </method>
 821
 822      <!-- =================== PUBLIC MEMBERS =================== -->
 823
 824      <field name="tree">
 825        document.getAnonymousElementByAttribute(this, "anonid", "tree");
 826      </field>
 827
 828      <field name="treecols">
 829        document.getAnonymousElementByAttribute(this, "anonid", "treecols");
 830      </field>
 831
 832      <property name="view"
 833                onget="return this.mView;">
 834        <setter><![CDATA[
 835          // We must do this by hand because the tree binding may not be ready yet
 836          this.mView = val;
 837          var bx = this.tree.boxObject;
 838          bx = bx.QueryInterface(Components.interfaces.nsITreeBoxObject);
 839          bx.view = val;
 840        ]]></setter>
 841      </property>
 842
 843    </implementation>
 844  </binding>
 845
 846  <binding id="autocomplete-base-popup" extends="chrome://global/content/bindings/popup.xml#popup">
 847    <implementation implements="nsIAutoCompletePopup">
 848      <!-- nsIAccessible from #popup -->
 849      <property name="accessibleType" readonly="true"
 850                onget="return Components.interfaces.nsIAccessibleProvider.NoAccessible;"/>
 851
 852      <field name="mInput">null</field>
 853      <field name="mPopupOpen">false</field>
 854
 855      <!-- =================== nsIAutoCompletePopup =================== -->
 856
 857      <property name="input" readonly="true"
 858                onget="return this.mInput"/>
 859
 860      <property name="overrideValue" readonly="true"
 861                onget="return null;"/>
 862
 863      <property name="popupOpen" readonly="true"
 864                onget="return this.mPopupOpen;"/>
 865
 866      <method name="closePopup">
 867        <body>
 868          <![CDATA[
 869          if (this.mPopupOpen) {
 870            this.hidePopup();
 871            this.removeAttribute("width");
 872          }
 873        ]]>
 874        </body>
 875      </method>
 876
 877      <!-- This is the default number of rows that we give the autocomplete
 878           popup when the textbox doesn't have a "maxrows" attribute
 879           for us to use. -->
 880      <field name="defaultMaxRows" readonly="true">6</field>
 881
 882      <!-- In some cases (e.g. when the input's dropmarker button is clicked),
 883           the input wants to display a popup with more rows. In that case, it
 884           should increase its maxRows property and store the "normal" maxRows
 885           in this field. When the popup is hidden, we restore the input's
 886           maxRows to the value stored in this field.
 887
 888           This field is set to -1 between uses so that we can tell when it's
 889           been set by the input and when we need to set it in the popupshowing
 890           handler. -->
 891      <field name="_normalMaxRows">-1</field>
 892
 893      <property name="maxRows" readonly="true">
 894        <getter>
 895          <![CDATA[
 896          return (this.mInput && this.mInput.maxRows) || this.defaultMaxRows;
 897        ]]>
 898        </getter>
 899      </property>
 900
 901      <method name="getNextIndex">
 902        <parameter name="aReverse"/>
 903        <parameter name="aAmount"/>
 904        <parameter name="aIndex"/>
 905        <parameter name="aMaxRow"/>
 906        <body><![CDATA[
 907          if (aMaxRow < 0)
 908            return -1;
 909
 910          var newIdx = aIndex + (aReverse?-1:1)*aAmount;
 911          if (aReverse && aIndex == -1 || newIdx > aMaxRow && aIndex != aMaxRow)
 912            newIdx = aMaxRow;
 913          else if (!aReverse && aIndex == -1 || newIdx < 0 && aIndex != 0)
 914            newIdx = 0;
 915
 916          if (newIdx < 0 && aIndex == 0 || newIdx > aMaxRow && aIndex == aMaxRow)
 917            aIndex = -1;
 918          else
 919            aIndex = newIdx;
 920
 921          return aIndex;
 922        ]]></body>
 923      </method>
 924
 925      <method name="onPopupClick">
 926        <parameter name="aEvent"/>
 927        <body><![CDATA[
 928          var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController);
 929          controller.handleEnter(true);
 930        ]]></body>
 931      </method>
 932    </implementation>
 933
 934    <handlers>
 935      <handler event="popupshowing"><![CDATA[
 936        // If normalMaxRows wasn't already set by the input, then set it here
 937        // so that we restore the correct number when the popup is hidden.
 938        if (this._normalMaxRows < 0)
 939          this._normalMaxRows = this.mInput.maxRows;
 940
 941        this.mPopupOpen = true;
 942      ]]></handler>
 943
 944      <handler event="popuphiding"><![CDATA[
 945        var isListActive = true;
 946        if (this.selectedIndex == -1)
 947          isListActive = false;
 948        var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController);
 949        controller.stopSearch();
 950
 951        this.mPopupOpen = false;
 952
 953        // Reset the maxRows property to the cached "normal" value, and reset
 954        // _normalMaxRows so that we can detect whether it was set by the input
 955        // when the popupshowing handler runs.
 956        this.mInput.maxRows = this._normalMaxRows;
 957        this._normalMaxRows = -1;
 958        // If the list was being navigated and then closed, make sure
 959        // we fire accessible focus event back to textbox
 960        if (isListActive) {
 961          this.mInput.mIgnoreFocus = true;
 962          this.mInput._focus();
 963          this.mInput.mIgnoreFocus = false;
 964        }
 965      ]]></handler>
 966    </handlers>
 967  </binding>
 968
 969  <binding id="autocomplete-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-base-popup">
 970    <resources>
 971      <stylesheet src="chrome://global/skin/autocomplete.css"/>
 972    </resources>
 973
 974    <content ignorekeys="true" level="top">
 975      <xul:richlistbox anonid="richlistbox" class="autocomplete-richlistbox" flex="1"/>
 976      <xul:hbox>
 977        <children/>
 978      </xul:hbox>
 979    </content>
 980
 981    <implementation implements="nsIAutoCompletePopup">
 982      <field name="_currentIndex">0</field>
 983
 984      <!-- =================== nsIAutoCompletePopup =================== -->
 985
 986      <property name="selectedIndex"
 987                onget="return this.richlistbox.selectedIndex;">
 988        <setter>
 989          <![CDATA[
 990          this.richlistbox.selectedIndex = val;
 991
 992          // when clearing the selection (val == -1, so selectedItem will be
 993          // null), we want to scroll back to the top.  see bug #406194
 994          this.richlistbox.ensureElementIsVisible(
 995            this.richlistbox.selectedItem || this.richlistbox.firstChild);
 996
 997          return val;
 998        ]]>
 999        </setter>
1000      </property>
1001
1002      <method name="openAutocompletePopup">
1003        <parameter name="aInput"/>
1004        <parameter name="aElement"/>
1005        <body>
1006          <![CDATA[
1007          // until we have "baseBinding", (see bug #373652) this allows
1008          // us to override openAutocompletePopup(), but still call
1009          // the method on the base class
1010          this._openAutocompletePopup(aInput, aElement);
1011        ]]>
1012        </body>
1013      </method>
1014
1015      <method name="_openAutocompletePopup">
1016        <parameter name="aInput"/>
1017        <parameter name="aElement"/>
1018        <body>
1019          <![CDATA[
1020          if (!this.mPopupOpen) {
1021            this.mInput = aInput;
1022            // clear any previous selection, see bugs 400671 and 488357
1023            this.selectedIndex = -1;
1024
1025            var width = aElement.getBoundingClientRect().width;
1026            this.setAttribute("width", width > 100 ? width : 100);
1027            // invalidate() depends on the width attribute
1028            this._invalidate();
1029
1030            // setConsumeRollupEvent() before we call openPopup()
1031            var nsIPopupBO = Components.interfaces.nsIPopupBoxObject;
1032            this.popupBoxObject.setConsumeRollupEvent(
1033              this.mInput.consumeRollupEvent ?
1034                nsIPopupBO.ROLLUP_CONSUME :
1035                nsIPopupBO.ROLLUP_NO_CONSUME);
1036            this.openPopup(aElement, "after_start", 0, 0, false, false);
1037          }
1038        ]]>
1039        </body>
1040      </method>
1041
1042      <method name="invalidate">
1043        <body>
1044          <![CDATA[
1045          // Don't bother doing work if we're not even showing
1046          if (!this.mPopupOpen)
1047            return;
1048
1049          this._invalidate();
1050          ]]>
1051        </body>
1052      </method>
1053
1054      <method name="_invalidate">
1055        <body>
1056          <![CDATA[
1057          if (!this.hasAttribute("height")) {
1058            // collapsed if no matches
1059            this.richlistbox.collapsed = (this._matchCount == 0);
1060
1061            // Dynamically update height until richlistbox.rows works (bug 401939)
1062            // Adjust the height immediately and after the row contents update
1063            this.adjustHeight();
1064            setTimeout(function(self) self.adjustHeight(), 0, this);
1065          }
1066
1067          // make sure to collapse any existing richlistitems
1068          // that aren't going to be used
1069          var existingItemsCount = this.richlistbox.childNodes.length;
1070          for (var i = this._matchCount; i < existingItemsCount; i++)
1071            this.richlistbox.childNodes[i].collapsed = true;
1072
1073          this._currentIndex = 0;
1074          this._appendCurrentResult();
1075        ]]>
1076        </body>
1077      </method>
1078
1079      <property name="maxResults" readonly="true">
1080        <getter>
1081          <![CDATA[
1082            // this is how many richlistitems will be kept around
1083            // (note, this getter may be overridden)
1084            return 20;
1085          ]]>
1086        </getter>
1087      </property>
1088
1089      <property name="_matchCount" readonly="true">
1090        <getter>
1091          <![CDATA[
1092          return Math.min(this.mInput.controller.matchCount, this.maxResults);
1093          ]]>
1094        </getter>
1095      </property>
1096
1097      <method name="adjustHeight">
1098        <body>
1099          <![CDATA[
1100          // Figure out how many rows to show
1101          let rows = this.richlistbox.childNodes;
1102          let numRows = Math.min(this._matchCount, this.maxRows, rows.length);
1103
1104          // Default the height to 0 if we have no rows to show
1105          let height = 0;
1106          if (numRows) {
1107            let firstRowRect = rows[0].getBoundingClientRect();
1108            let lastRowRect = rows[numRows - 1].getBoundingClientRect();
1109
1110            // Calculate the height to have the first row to last row shown
1111            height = lastRowRect.bottom - firstRowRect.top;
1112          }
1113
1114          // Only update the height if we have a non-zero height and if it
1115          // changed (the richlistbox is collapsed if there are no results)
1116          if (height && height != this.richlistbox.height)
1117            this.richlistbox.height = height;
1118          ]]>
1119        </body>
1120      </method>
1121
1122      <method name="_appendCurrentResult">
1123        <body>
1124          <![CDATA[
1125          var controller = this.mInput.controller;
1126          var matchCount = this._matchCount;
1127          var existingItemsCount = this.richlistbox.childNodes.length;
1128
1129          // Process maxRows per chunk to improve performance and user experience
1130          for (let i = 0; i < this.maxRows; i++) {
1131            if (this._currentIndex >= matchCount)
1132              return;
1133
1134            var item;
1135
1136            // trim the leading/trailing whitespace
1137            var trimmedSearchString = controller.searchString.replace(/^\s+/, "").replace(/\s+$/, "");
1138
1139            // Unescape the URI spec for showing as an entry in the popup
1140            let url = Components.classes["@mozilla.org/intl/texttosuburi;1"].
1141              getService(Components.interfaces.nsITextToSubURI).
1142              unEscapeURIForUI("UTF-8", controller.getValueAt(this._currentIndex));
1143
1144            if (typeof this.input.trimValue == "function")
1145              url = this.input.trimValue(url);
1146
1147            if (this._currentIndex < existingItemsCount) {
1148              // re-use the existing item
1149              item = this.richlistbox.childNodes[this._currentIndex];
1150
1151              // Completely re-use the existing richlistitem if it's the same
1152              if (item.getAttribute("text") == trimmedSearchString &&
1153                  item.getAttribute("url") == url) {
1154                item.collapsed = false;
1155                this._currentIndex++;
1156                continue;
1157              }
1158            }
1159            else {
1160              // need to create a new item
1161              item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem");
1162            }
1163
1164            // set these attributes before we set the class
1165            // so that we can use them from the constructor
1166            item.setAttribute("image", controller.getImageAt(this._currentIndex));
1167            item.setAttribute("url", url);
1168            item.setAttribute("title", controller.getCommentAt(this._currentIndex));
1169            item.setAttribute("type", controller.getStyleAt(this._currentIndex));
1170            item.setAttribute("text", trimmedSearchString);
1171
1172            if (this._currentIndex < existingItemsCount) {
1173              // re-use the existing item
1174              item._adjustAcItem();
1175              item.collapsed = false;
1176            }
1177            else {
1178              // set the class at the end so we can use the attributes
1179              // in the xbl constructor
1180              item.className = "autocomplete-richlistitem";
1181              this.richlistbox.appendChild(item);
1182            }
1183
1184            this._currentIndex++;
1185          }
1186
1187          // yield after each batch of items so that typing the url bar is responsive
1188          setTimeout(function (self) { self._appendCurrentResult(); }, 0, this);
1189        ]]>
1190        </body>
1191      </method>
1192
1193      <method name="selectBy">
1194        <parameter name="aReverse"/>
1195        <parameter name="aPage"/>
1196        <body>
1197          <![CDATA[
1198          try {
1199            var amount = aPage ? 5 : 1;
1200
1201            // because we collapsed unused items, we can't use this.richlistbox.getRowCount(), we need to use the matchCount
1202            this.selectedIndex = this.getNextIndex(aReverse, amount, this.selectedIndex, this._matchCount - 1);
1203            if (this.selectedIndex == -1) {
1204              this.input._focus();
1205            }
1206          } catch (ex) {
1207            // do nothing - occasionally timer-related js errors happen here
1208            // e.g. "this.selectedIndex has no properties", when you type fast and hit a
1209            // navigation key before this popup has opened
1210          }
1211            ]]>
1212        </body>
1213      </method>
1214
1215      <field name="richlistbox">
1216        document.getAnonymousElementByAttribute(this, "anonid", "richlistbox");
1217      </field>
1218
1219      <property name="view"
1220                onget="return this.mInput.controller;"
1221                onset="return val;"/>
1222
1223    </implementation>
1224  </binding>
1225
1226  <binding id="autocomplete-richlistitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
1227    <content>
1228      <xul:hbox align="center" class="ac-title-box">
1229        <xul:image xbl:inherits="src=image" class="ac-site-icon"/>
1230        <xul:hbox anonid="title-box" class="ac-title" flex="1"
1231                  onunderflow="_doUnderflow('_title');"
1232                  onoverflow="_doOverflow('_title');">
1233          <xul:description anonid="title" class="ac-normal-text ac-comment" xbl:inherits="selected"/>
1234        </xul:hbox>
1235        <xul:label anonid="title-overflow-ellipsis" xbl:inherits="selected"
1236                   class="ac-ellipsis-after ac-comment"/>
1237        <xul:hbox anonid="extra-box" class="ac-extra" align="center" hidden="true">
1238          <xul:image class="ac-result-type-tag"/>
1239          <xul:label class="ac-normal-text ac-comment" xbl:inherits="selected" value=":"/>
1240          <xul:description anonid="extra" class="ac-normal-text ac-comment" xbl:inherits="selected"/>
1241        </xul:hbox>
1242        <xul:image anonid="type-image" class="ac-type-icon"/>
1243      </xul:hbox>
1244      <xul:hbox align="center" class="ac-url-box">
1245        <xul:spacer class="ac-site-icon"/>
1246        <xul:image class="ac-action-icon"/>
1247        <xul:hbox anonid="url-box" class="ac-url" flex="1"
1248                  onunderflow="_doUnderflow('_url');"
1249                  onoverflow="_doOverflow('_url');">
1250          <xul:description anonid="url" class="ac-normal-text ac-url-text"
1251                           xbl:inherits="selected type"/>
1252          <xul:description anonid="action" class="ac-normal-text ac-action-text"
1253                           xbl:inherits="selected type"/>
1254        </xul:hbox>
1255        <xul:label anonid="url-overflow-ellipsis" xbl:inherits="selected"
1256                   class="ac-ellipsis-after ac-url-text"/>
1257        <xul:spacer class="ac-type-icon"/>
1258      </xul:hbox>
1259    </content>
1260    <implementation implements="nsIDOMXULSelectControlItemElement">
1261      <constructor>
1262        <![CDATA[
1263            let ellipsis = "\u2026";
1264            try {
1265              ellipsis = Components.classes["@mozilla.org/preferences-service;1"].
1266                getService(Components.interfaces.nsIPrefBranch).
1267                getComplexValue("intl.ellipsis",
1268                  Components.interfaces.nsIPrefLocalizedString).data;
1269            } catch (ex) {
1270              // Do nothing.. we already have a default
1271            }
1272
1273            this._urlOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "url-overflow-ellipsis");
1274            this._titleOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "title-overflow-ellipsis");
1275
1276            this._urlOverflowEllipsis.value = ellipsis;
1277            this._titleOverflowEllipsis.value = ellipsis;
1278
1279            this._typeImage = document.getAnonymousElementByAttribute(this, "anonid", "type-image");
1280
1281            this._urlBox = document.getAnonymousElementByAttribute(this, "anonid", "url-box");
1282            this._url = document.getAnonymousElementByAttribute(this, "anonid", "url");
1283            this._action = document.getAnonymousElementByAttribute(this, "anonid", "action");
1284
1285            this._titleBox = document.getAnonymousElementByAttribute(this, "anonid", "title-box");
1286            this._title = document.getAnonymousElementByAttribute(this, "anonid", "title");
1287
1288            this._extraBox = document.getAnonymousElementByAttribute(this, "anonid", "extra-box");
1289            this._extra = document.getAnonymousElementByAttribute(this, "anonid", "extra");
1290
1291            this._adjustAcItem();
1292          ]]>
1293      </constructor>
1294
1295      <property name="label" readonly="true">
1296        <getter>
1297          <![CDATA[
1298            var title = this.getAttribute("title");
1299            var url = this.getAttribute("url");
1300            var panel = this.parentNode.parentNode;
1301
1302            // allow consumers that have extended popups to override
1303            // the label values for the richlistitems
1304            if (panel.createResultLabel)
1305              return panel.createResultLabel(title, url, this.getAttribute("type"));
1306
1307            // aType (ex: "ac-result-type-<aType>") is related to the class of the image,
1308            // and is not "visible" text so don't use it for the label (for accessibility).
1309            return title + " " + url;
1310          ]]>
1311        </getter>
1312      </property>
1313
1314      <field name="_boundaryCutoff">null</field>
1315
1316      <property name="boundaryCutoff" readonly="true">
1317        <getter>
1318          <![CDATA[
1319          if (!this._boundaryCutoff) {
1320            this._boundaryCutoff =
1321              Components.classes["@mozilla.org/preferences-service;1"].
1322              getService(Components.interfaces.nsIPrefBranch).
1323              getIntPref("toolkit.autocomplete.richBoundaryCutoff");
1324          }
1325          return this._boundaryCutoff;
1326          ]]>
1327        </getter>
1328      </property>
1329
1330      <method name="_getBoundaryIndices">
1331        <parameter name="aText"/>
1332        <parameter name="aSearchToke…

Large files files are truncated, but you can click here to view the full file