deleted file mode 100644
--- a/xpfe/components/autocomplete/resources/content/autocomplete.xml
+++ /dev/null
@@ -1,1644 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-
-<bindings id="autocompleteBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="autocomplete" role="xul:combobox"
- extends="chrome://global/content/bindings/textbox.xml#textbox">
- <resources>
- <stylesheet src="chrome://communicator/content/autocomplete.css"/>
- <stylesheet src="chrome://global/skin/autocomplete.css"/>
- </resources>
-
- <content>
- <children includes="menupopup"/>
-
- <xul:hbox class="autocomplete-textbox-container" flex="1" align="center">
- <children includes="image|deck|stack|box">
- <xul:image class="autocomplete-icon" allowevents="true"/>
- </children>
-
- <xul:hbox class="textbox-input-box" flex="1" xbl:inherits="context,tooltiptext=inputtooltiptext">
- <children/>
- <html:input anonid="input" class="autocomplete-textbox textbox-input"
- allowevents="true"
- xbl:inherits="tooltiptext=inputtooltiptext,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey,mozactionhint,userAction"/>
- </xul:hbox>
- <children includes="hbox"/>
- </xul:hbox>
-
- <xul:dropmarker class="autocomplete-history-dropmarker" allowevents="true"
- xbl:inherits="open,enablehistory" anonid="historydropmarker"/>
-
- <xul:popupset>
- <xul:panel type="autocomplete" anonid="popup"
- ignorekeys="true" noautofocus="true" level="top"
- xbl:inherits="for=id,nomatch"/>
- </xul:popupset>
- </content>
-
- <implementation implements="nsIDOMXULMenuListElement">
-
- <constructor><![CDATA[
- // XXX bug 90337 band-aid until we figure out what's going on here
- if (this.value != this.mInputElt.value)
- this.mInputElt.value = this.value;
- delete this.value;
-
- // listen for pastes
- this.mInputElt.controllers.insertControllerAt(0, this.mPasteController);
-
- // listen for menubar activation
- window.top.addEventListener("DOMMenuBarActive", this.mMenuBarListener, true);
-
- // set default property values
- this.ifSetAttribute("timeout", 50);
- this.ifSetAttribute("pastetimeout", 1000);
- this.ifSetAttribute("maxrows", 5);
- this.ifSetAttribute("showpopup", true);
- this.ifSetAttribute("disableKeyNavigation", true);
-
- // initialize the search sessions
- if (this.hasAttribute("autocompletesearch"))
- this.initAutoCompleteSearch();
-
- // hack to work around lack of bottom-up constructor calling
- if ("initialize" in this.popup)
- this.popup.initialize();
- ]]></constructor>
-
- <destructor><![CDATA[
- this.clearResults(false);
- window.top.removeEventListener("DOMMenuBarActive", this.mMenuBarListener, true);
- this.mInputElt.controllers.removeController(this.mPasteController);
- ]]></destructor>
-
- <!-- =================== nsIAutoCompleteInput =================== -->
- <!-- XXX: This implementation is currently incomplete. -->
-
- <!-- reference to the results popup element -->
- <field name="popup"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "popup");
- ]]></field>
-
- <property name="popupOpen"
- onget="return this.mMenuOpen;"
- onset="if (val) this.openPopup(); else this.closePopup(); return val;"/>
-
- <!-- option to turn off autocomplete -->
- <property name="disableAutoComplete"
- onset="this.setAttribute('disableautocomplete', val); return val;"
- onget="return this.getAttribute('disableautocomplete') == 'true';"/>
-
- <!-- if the resulting match string is not at the beginning of the typed string,
- this will optionally autofill like this "bar |>> foobar|" -->
- <property name="completeDefaultIndex"
- onset="this.setAttribute('completedefaultindex', val); return val;"
- onget="return this.getAttribute('completedefaultindex') == 'true';"/>
-
- <!-- option for completing to the default result whenever the user hits
- enter or the textbox loses focus -->
- <property name="forceComplete"
- onset="this.setAttribute('forcecomplete', val); return val;"
- onget="return this.getAttribute('forcecomplete') == 'true';"/>
-
- <property name="minResultsForPopup"
- onset="this.setAttribute('minresultsforpopup', val); return val;"
- onget="var t = this.getAttribute('minresultsforpopup'); return t ? parseInt(t) : 1;"/>
-
- <!-- maximum number of rows to display -->
- <property name="maxRows"
- onset="this.setAttribute('maxrows', val); return val;"
- onget="return parseInt(this.getAttribute('maxrows')) || 0;"/>
-
- <!-- toggles a second column in the results list which contains
- the string in the comment field of each autocomplete result -->
- <property name="showCommentColumn"
- onget="return this.getAttribute('showcommentcolumn') == 'true';">
- <setter><![CDATA[
- this.popup.showCommentColumn = val;
- this.setAttribute('showcommentcolumn', val);
- return val;
- ]]></setter>
- </property>
-
- <!-- number of milliseconds after a keystroke before a search begins -->
- <property name="timeout"
- onset="this.setAttribute('timeout', val); return val;"
- onget="return parseInt(this.getAttribute('timeout')) || 0;"/>
-
- <property name="searchParam"
- onget="return this.getAttribute('autocompletesearchparam') || '';"
- onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
-
- <property name="searchCount" readonly="true"
- onget="return this.sessionCount;"/>
-
- <method name="getSearchAt">
- <parameter name="aIndex"/>
- <body><![CDATA[
- var idx = -1;
- for (var name in this.mSessions)
- if (++idx == aIndex)
- return name;
-
- return null;
- ]]></body>
- </method>
-
- <property name="textValue"
- onget="return this.value;"
- onset="this.setTextValue(val); return val;"/>
-
- <method name="onSearchBegin">
- <body><![CDATA[
- this._fireEvent("searchbegin");
- ]]></body>
- </method>
-
- <method name="onSearchComplete">
- <body><![CDATA[
- if (this.noMatch)
- this.setAttribute("nomatch", "true");
- else
- this.removeAttribute("nomatch");
-
- this._fireEvent("searchcomplete");
- ]]></body>
- </method>
-
- <method name="onTextReverted">
- <body><![CDATA[
- return this._fireEvent("textreverted");
- ]]></body>
- </method>
-
- <!-- =================== nsIDOMXULMenuListElement =================== -->
-
- <property name="editable" readonly="true"
- onget="return true;" />
-
- <property name="crop"
- onset="this.setAttribute('crop', val); return val;"
- onget="return this.getAttribute('crop');"/>
-
- <property name="label" readonly="true"
- onget="return this.mInputElt.value;"/>
-
- <property name="open"
- onget="return this.getAttribute('open') == 'true';">
- <setter>
- <![CDATA[
- var historyPopup = document.getAnonymousElementByAttribute(this, "anonid", "historydropmarker");
- if (val) {
- this.setAttribute('open', true);
- historyPopup.showPopup();
- } else {
- this.removeAttribute('open');
- historyPopup.hidePopup();
- }
- ]]>
- </setter>
- </property>
-
- <!-- =================== PUBLIC PROPERTIES =================== -->
-
- <property name="value"
- onget="return this.mInputElt.value;">
- <setter><![CDATA[
- this.ignoreInputEvent = true;
- this.mInputElt.value = val;
- this.ignoreInputEvent = false;
- var event = document.createEvent('Events');
- event.initEvent('ValueChange', true, true);
- this.mInputElt.dispatchEvent(event);
- return val;
- ]]></setter>
- </property>
-
- <property name="focused"
- onget="return this.getAttribute('focused') == 'true';"/>
-
- <method name="initAutoCompleteSearch">
- <body><![CDATA[
- var list = this.getAttribute("autocompletesearch").split(" ");
- for (var i = 0; i < list.length; i++) {
- var name = list[i];
- var contractid = "@mozilla.org/autocomplete/search;1?name=" + name;
- if (contractid in Components.classes) {
- try {
- this.mSessions[name] =
- Components.classes[contractid].getService(Components.interfaces.nsIAutoCompleteSearch);
- this.mLastResults[name] = null;
- this.mLastRows[name] = 0;
- ++this.sessionCount;
- } catch (e) {
- dump("### ERROR - unable to create search \"" + name + "\".\n");
- }
- } else {
- dump("search \"" + name + "\" not found - skipping.\n");
- }
- }
- ]]></body>
- </method>
-
- <!-- the number of sessions currently in use -->
- <field name="sessionCount">0</field>
-
- <!-- number of milliseconds after a paste before a search begins -->
- <property name="pasteTimeout"
- onset="this.setAttribute('pastetimeout', val); return val;"
- onget="var t = parseInt(this.getAttribute('pastetimeout')); return t ? t : 0;"/>
-
- <!-- option for filling the textbox with the best match while typing
- and selecting the difference -->
- <property name="autoFill"
- onset="this.setAttribute('autofill', val); return val;"
- onget="return this.getAttribute('autofill') == 'true';"/>
-
- <!-- if this attribute is set, allow different style for
- non auto-completed lines -->
- <property name="highlightNonMatches"
- onset="this.setAttribute('highlightnonmatches', val); return val;"
- onget="return this.getAttribute('highlightnonmatches') == 'true';"/>
-
- <!-- option to show the popup containing the results -->
- <property name="showPopup"
- onset="this.setAttribute('showpopup', val); return val;"
- onget="return this.getAttribute('showpopup') == 'true';"/>
-
- <!-- option to allow scrolling through the list via the tab key, rather than
- tab moving focus out of the textbox -->
- <property name="tabScrolling"
- onset="this.setAttribute('tabscrolling', val); return val;"
- onget="return this.getAttribute('tabscrolling') == 'true';"/>
-
- <!-- option to completely ignore any blur events while
- searches are still going on. This is useful so that nothing
- gets autopicked if the window is required to lose focus for
- some reason (eg in LDAP autocomplete, another window may be
- brought up so that the user can enter a password to authenticate
- to an LDAP server). -->
- <property name="ignoreBlurWhileSearching"
- onset="this.setAttribute('ignoreblurwhilesearching', val); return val;"
- onget="return this.getAttribute('ignoreblurwhilesearching') == 'true';"/>
-
- <!-- state which indicates the current action being performed by the user.
- Possible values are : none, typing, scrolling -->
- <property name="userAction"
- onset="this.setAttribute('userAction', val); return val;"
- onget="return this.getAttribute('userAction');"/>
-
- <!-- state which indicates if the last search had no matches -->
- <field name="noMatch">true</field>
-
- <!-- state which indicates a search is currently happening -->
- <field name="isSearching">false</field>
-
- <!-- state which indicates a search timeout is current waiting -->
- <property name="isWaiting"
- onget="return this.mAutoCompleteTimer != 0;"/>
-
- <!-- =================== PRIVATE PROPERTIES =================== -->
-
- <field name="mSessions">({})</field>
- <field name="mLastResults">({})</field>
- <field name="mLastRows">({})</field>
- <field name="mLastKeyCode">null</field>
- <field name="mAutoCompleteTimer">0</field>
- <field name="mMenuOpen">false</field>
- <field name="mFireAfterSearch">false</field>
- <field name="mFinishAfterSearch">false</field>
- <field name="mNeedToFinish">false</field>
- <field name="mNeedToComplete">false</field>
- <field name="mTransientValue">false</field>
- <field name="mView">null</field>
- <field name="currentSearchString">""</field>
- <field name="ignoreInputEvent">false</field>
- <field name="oninit">null</field>
- <field name="mDefaultMatchFilled">false</field>
- <field name="mFirstReturn">true</field>
- <field name="mIsPasting">false</field>
-
- <field name="mPasteController"><![CDATA[
- ({
- self: this,
- kGlobalClipboard: Components.interfaces.nsIClipboard.kGlobalClipboard,
- supportsCommand: function(aCommand) {
- return aCommand == "cmd_paste";
- },
- isCommandEnabled: function(aCommand) {
- return aCommand == "cmd_paste" &&
- this.self.editor.isSelectionEditable &&
- this.self.editor.canPaste(this.kGlobalClipboard);
- },
- doCommand: function(aCommand) {
- if (aCommand == "cmd_paste") {
- this.self.mIsPasting = true;
- this.self.editor.paste(this.kGlobalClipboard);
- this.self.mIsPasting = false;
- }
- },
- onEvent: function() {}
- })
- ]]></field>
-
- <field name="mMenuBarListener"><![CDATA[
- ({
- self: this,
- handleEvent: function(aEvent) {
- try {
- this.self.finishAutoComplete(false, false, aEvent);
- this.self.clearTimer();
- this.self.closePopup();
- } catch (e) {
- window.top.removeEventListener("DOMMenuBarActive", this, true);
- }
- }
- })
- ]]></field>
-
- <field name="mAutoCompleteObserver"><![CDATA[
- ({
- self: this,
- onSearchResult: function(aSearch, aResult) {
- for (var name in this.self.mSessions)
- if (this.self.mSessions[name] == aSearch)
- this.self.processResults(name, aResult);
- }
- })
- ]]></field>
-
- <field name="mInputElt"><![CDATA[
- document.getAnonymousElementByAttribute(this, "anonid", "input");
- ]]></field>
-
- <field name="mMenuAccessKey"><![CDATA[
- Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch)
- .getIntPref("ui.key.menuAccessKey");
- ]]></field>
-
- <!-- =================== PUBLIC METHODS =================== -->
-
- <method name="getErrorAt">
- <parameter name="aIndex"/>
- <body><![CDATA[
- var obj = aIndex < 0 ? null : this.convertIndexToSession(aIndex);
- return obj && this.mLastResults[obj.session] &&
- this.mLastResults[obj.session].errorDescription;
- ]]></body>
- </method>
-
- <!-- get a value from the autocomplete results as a string via an absolute index-->
- <method name="getResultValueAt">
- <parameter name="aIndex"/>
- <body><![CDATA[
- var obj = this.convertIndexToSession(aIndex);
- return obj ? this.getSessionValueAt(obj.session, obj.index) : null;
- ]]></body>
- </method>
-
- <!-- get a value from the autocomplete results as a string from a specific session -->
- <method name="getSessionValueAt">
- <parameter name="aSession"/>
- <parameter name="aIndex"/>
- <body><![CDATA[
- var result = this.mLastResults[aSession];
- return result.errorDescription || result.getValueAt(aIndex);
- ]]></body>
- </method>
-
- <!-- get the total number of results overall -->
- <method name="getResultCount">
- <body><![CDATA[
- return this.view.rowCount;
- ]]></body>
- </method>
-
- <!-- get the first session that has results -->
- <method name="getDefaultSession">
- <body><![CDATA[
- for (var name in this.mLastResults) {
- var results = this.mLastResults[name];
- if (results && results.matchCount > 0 && !results.errorDescription)
- return name;
- }
- return null;
- ]]></body>
- </method>
-
- <!-- empty the cached result data and empty the results popup -->
- <method name="clearResults">
- <parameter name="aInvalidate"/>
- <body><![CDATA[
- this.clearResultData();
- this.clearResultElements(aInvalidate);
- ]]></body>
- </method>
-
- <!-- =================== PRIVATE METHODS =================== -->
-
- <!-- ::::::::::::: session searching ::::::::::::: -->
-
- <!-- -->
- <method name="callListener">
- <parameter name="me"/>
- <parameter name="aAction"/>
- <body><![CDATA[
- // bail if the binding was detached or the element removed from
- // document during the timeout
- if (!("startLookup" in me) || !me.ownerDocument || !me.parentNode)
- return;
-
- me.clearTimer();
-
- if (me.disableAutoComplete)
- return;
-
- switch (aAction) {
- case "startLookup":
- me.startLookup();
- break;
-
- case "stopLookup":
- me.stopLookup();
- break;
- }
- ]]></body>
- </method>
-
- <!-- -->
- <method name="startLookup">
- <body><![CDATA[
- var str = this.currentSearchString;
- if (!str) {
- this.clearResults(false);
- this.closePopup();
- return;
- }
-
- this.isSearching = true;
- this.mFirstReturn = true;
- this.mSessionReturns = this.sessionCount;
- this.mFailureItems = 0;
- this.mDefaultMatchFilled = false; // clear out our prefill state.
-
- // Notify the input that the search is beginning.
- this.onSearchBegin();
-
- // tell each session to start searching...
- for (var name in this.mSessions)
- try {
- this.mSessions[name].startSearch(str, this.searchParam, this.mLastResults[name], this.mAutoCompleteObserver);
- } catch (e) {
- --this.mSessionReturns;
- this.searchFailed();
- }
- ]]></body>
- </method>
-
- <!-- -->
- <method name="stopLookup">
- <body><![CDATA[
- for (var name in this.mSessions)
- this.mSessions[name].stopSearch();
- ]]></body>
- </method>
-
- <!-- -->
- <method name="processResults">
- <parameter name="aSessionName"/>
- <parameter name="aResults"/>
- <body><![CDATA[
- if (this.disableAutoComplete)
- return;
-
- const ACR = Components.interfaces.nsIAutoCompleteResult;
- var status = aResults.searchResult;
- if (status != ACR.RESULT_NOMATCH_ONGOING &&
- status != ACR.RESULT_SUCCESS_ONGOING)
- --this.mSessionReturns;
-
- // check the many criteria for failure
- if (aResults.errorDescription)
- ++this.mFailureItems;
- else if (status == ACR.RESULT_IGNORED ||
- status == ACR.RESULT_FAILURE ||
- status == ACR.RESULT_NOMATCH ||
- status == ACR.RESULT_NOMATCH_ONGOING ||
- aResults.matchCount == 0 ||
- aResults.searchString != this.currentSearchString)
- {
- this.mLastResults[aSessionName] = null;
- if (this.mFirstReturn)
- this.clearResultElements(false);
- this.mFirstReturn = false;
- this.searchFailed();
- return;
- }
-
- if (this.mFirstReturn) {
- if (this.view.mTree)
- this.view.mTree.beginUpdateBatch();
- this.clearResultElements(false); // clear results, but don't repaint yet
- }
-
- // always call openPopup...we may not have opened it
- // if a previous search session didn't return enough search results.
- // it's smart and doesn't try to open itself multiple times...
- // be sure to add our result elements before calling openPopup as we need
- // to know the total # of results found so far.
- this.addResultElements(aSessionName, aResults);
-
- this.autoFillInput(aSessionName, aResults, false);
- if (this.mFirstReturn && this.view.mTree)
- this.view.mTree.endUpdateBatch();
- this.openPopup();
- this.mFirstReturn = false;
-
- // if this is the last session to return...
- if (this.mSessionReturns == 0)
- this.postSearchCleanup();
-
- if (this.mFinishAfterSearch)
- this.finishAutoComplete(false, this.mFireAfterSearch, null);
- ]]></body>
- </method>
-
- <!-- called each time a search fails, except when failure items need
- to be displayed. If all searches have failed, clear the list
- and close the popup -->
- <method name="searchFailed">
- <body><![CDATA[
- // if all searches are done and they all failed...
- if (this.mSessionReturns == 0 && this.getResultCount() == 0) {
- if (this.minResultsForPopup == 0) {
- this.clearResults(true); // clear data and repaint empty
- this.openPopup();
- } else {
- this.closePopup();
- }
- }
-
- // if it's the last session to return, time to clean up...
- if (this.mSessionReturns == 0)
- this.postSearchCleanup();
- ]]></body>
- </method>
-
- <!-- does some stuff after a search is done (success or failure) -->
- <method name="postSearchCleanup">
- <body><![CDATA[
- this.isSearching = false;
-
- // figure out if there are no matches in all search sessions
- var failed = true;
- for (var name in this.mSessions) {
- if (this.mLastResults[name])
- failed = this.mLastResults[name].errorDescription ||
- this.mLastResults[name].matchCount == 0;
- if (!failed)
- break;
- }
- this.noMatch = failed;
-
- // if we have processed all of our searches, and none of them gave us a default index,
- // then we should try to auto fill the input field with the first match.
- // note: autoFillInput is smart enough to kick out if we've already prefilled something...
- if (!this.noMatch) {
- var defaultSession = this.getDefaultSession();
- if (defaultSession)
- this.autoFillInput(defaultSession, this.mLastResults[defaultSession], true);
- }
-
- // Notify the input that the search is complete.
- this.onSearchComplete();
- ]]></body>
- </method>
-
- <!-- when the focus exits the widget or user hits return,
- determine what value to leave in the textbox -->
- <method name="finishAutoComplete">
- <parameter name="aForceComplete"/>
- <parameter name="aFireTextCommand"/>
- <parameter name="aTriggeringEvent"/>
- <body><![CDATA[
- this.mFinishAfterSearch = false;
- this.mFireAfterSearch = false;
- if (this.mNeedToFinish && !this.disableAutoComplete) {
- // set textbox value to either override value, or default search result
- var val = this.popup.overrideValue;
- if (val) {
- this.setTextValue(val);
- this.mNeedToFinish = false;
- } else if (this.mTransientValue ||
- !(this.forceComplete ||
- (aForceComplete &&
- this.mDefaultMatchFilled &&
- this.mNeedToComplete))) {
- this.mNeedToFinish = false;
- } else if (this.isWaiting) {
- // if the user typed, the search results are out of date, so let
- // the search finish, and tell it to come back here when it's done
- this.mFinishAfterSearch = true;
- this.mFireAfterSearch = aFireTextCommand;
- return;
- } else {
- // we want to use the default item index for the first session which gave us a valid
- // default item index...
- for (var name in this.mLastResults) {
- var results = this.mLastResults[name];
- if (results && results.matchCount > 0 &&
- !results.errorDescription && results.defaultIndex != -1)
- {
- val = results.getValueAt(results.defaultIndex);
- this.setTextValue(val);
- this.mDefaultMatchFilled = true;
- this.mNeedToFinish = false;
- break;
- }
- }
-
- if (this.mNeedToFinish) {
- // if a search is happening at this juncture, bail out of this function
- // and let the search finish, and tell it to come back here when it's done
- if (this.isSearching) {
- this.mFinishAfterSearch = true;
- this.mFireAfterSearch = aFireTextCommand;
- return;
- }
-
- this.mNeedToFinish = false;
- var defaultSession = this.getDefaultSession();
- if (defaultSession)
- {
- // preselect the first one
- var first = this.getSessionValueAt(defaultSession, 0);
- this.setTextValue(first);
- this.mDefaultMatchFilled = true;
- }
- }
- }
-
- this.stopLookup();
-
- this.closePopup();
- }
-
- this.mNeedToComplete = false;
- this.clearTimer();
-
- if (aFireTextCommand)
- this._fireEvent("textentered", this.userAction, aTriggeringEvent);
- ]]></body>
- </method>
-
- <!-- when the user clicks an entry in the autocomplete popup -->
- <method name="onResultClick">
- <body><![CDATA[
- // set textbox value to either override value, or the clicked result
- var errItem = this.getErrorAt(this.popup.selectedIndex);
- var val = this.popup.overrideValue;
- if (val)
- this.setTextValue(val);
- else if (this.popup.selectedIndex != -1) {
- if (errItem) {
- this.setTextValue(this.currentSearchString);
- this.mTransientValue = true;
- } else {
- this.setTextValue(this.getResultValueAt(
- this.popup.selectedIndex));
- }
- }
-
- this.mNeedToFinish = false;
- this.mNeedToComplete = false;
-
- this.closePopup();
-
- this.currentSearchString = "";
-
- if (errItem)
- this._fireEvent("errorcommand", errItem);
- this._fireEvent("textentered", "clicking");
- ]]></body>
- </method>
-
- <!-- when the user hits escape, revert the previously typed value in the textbox -->
- <method name="undoAutoComplete">
- <body><![CDATA[
- var val = this.currentSearchString;
-
- var ok = this.onTextReverted();
- if ((ok || ok == undefined) && val)
- this.setTextValue(val);
-
- this.userAction = "typing";
-
- this.currentSearchString = this.value;
- this.mNeedToComplete = false;
- ]]></body>
- </method>
-
- <!-- convert an absolute result index into a session name/index pair -->
- <method name="convertIndexToSession">
- <parameter name="aIndex"/>
- <body><![CDATA[
- for (var name in this.mLastRows) {
- if (aIndex < this.mLastRows[name])
- return { session: name, index: aIndex };
- aIndex -= this.mLastRows[name];
- }
- return null;
- ]]></body>
- </method>
-
- <!-- ::::::::::::: user input handling ::::::::::::: -->
-
- <!-- -->
- <method name="processInput">
- <body><![CDATA[
- // stop current lookup in case it's async.
- this.stopLookup();
- // stop the queued up lookup on a timer
- this.clearTimer();
-
- if (this.disableAutoComplete)
- return;
-
- this.userAction = "typing";
- this.mFinishAfterSearch = false;
- this.mNeedToFinish = true;
- this.mTransientValue = false;
- this.mNeedToComplete = true;
- var str = this.value;
- this.currentSearchString = str;
- this.popup.clearSelection();
-
- var timeout = this.mIsPasting ? this.pasteTimeout : this.timeout;
- this.mAutoCompleteTimer = setTimeout(this.callListener, timeout, this, "startLookup");
- ]]></body>
- </method>
-
- <!-- -->
- <method name="processKeyPress">
- <parameter name="aEvent"/>
- <body><![CDATA[
- this.mLastKeyCode = aEvent.keyCode;
-
- var killEvent = false;
-
- switch (aEvent.keyCode) {
- case KeyEvent.DOM_VK_TAB:
- if (this.tabScrolling) {
- // don't kill this event if alt-tab or ctrl-tab is hit
- if (!aEvent.altKey && !aEvent.ctrlKey) {
- killEvent = this.mMenuOpen;
- if (killEvent)
- this.keyNavigation(aEvent);
- }
- }
- break;
-
- case KeyEvent.DOM_VK_RETURN:
-
- // if this is a failure item, save it for fireErrorCommand
- var errItem = this.getErrorAt(this.popup.selectedIndex);
-
- killEvent = this.mMenuOpen;
- this.finishAutoComplete(true, true, aEvent);
- this.closePopup();
- if (errItem) {
- this._fireEvent("errorcommand", errItem);
- }
- break;
-
- case KeyEvent.DOM_VK_ESCAPE:
- this.clearTimer();
- killEvent = this.mMenuOpen;
- this.undoAutoComplete();
- this.closePopup();
- break;
-
- case KeyEvent.DOM_VK_LEFT:
- case KeyEvent.DOM_VK_RIGHT:
- case KeyEvent.DOM_VK_HOME:
- case KeyEvent.DOM_VK_END:
- this.finishAutoComplete(true, false, aEvent);
- this.clearTimer();
- this.closePopup();
- break;
-
- case KeyEvent.DOM_VK_DOWN:
- if (!aEvent.altKey) {
- this.clearTimer();
- killEvent = this.keyNavigation(aEvent);
- break;
- }
- // Alt+Down falls through to history popup toggling code
-
- case KeyEvent.DOM_VK_F4:
- if (!aEvent.ctrlKey && !aEvent.shiftKey && this.getAttribute("enablehistory") == "true") {
- var historyPopup = document.getAnonymousElementByAttribute(this, "anonid", "historydropmarker");
- if (historyPopup)
- historyPopup.showPopup();
- else
- historyPopup.hidePopup();
- }
- break;
- case KeyEvent.DOM_VK_PAGE_UP:
- case KeyEvent.DOM_VK_PAGE_DOWN:
- case KeyEvent.DOM_VK_UP:
- if (!aEvent.ctrlKey && !aEvent.metaKey) {
- this.clearTimer();
- killEvent = this.keyNavigation(aEvent);
- }
- break;
-
- case KeyEvent.DOM_VK_BACK_SPACE:
- if (!aEvent.ctrlKey && !aEvent.altKey && !aEvent.shiftKey &&
- this.selectionStart == this.currentSearchString.length &&
- this.selectionEnd == this.value.length &&
- this.mDefaultMatchFilled) {
- this.mDefaultMatchFilled = false;
- this.value = this.currentSearchString;
- }
-
- if (!/Mac/.test(navigator.platform))
- break;
- case KeyEvent.DOM_VK_DELETE:
- if (/Mac/.test(navigator.platform) && !aEvent.shiftKey)
- break;
-
- if (this.mMenuOpen && this.popup.selectedIndex != -1) {
- var obj = this.convertIndexToSession(this.popup.selectedIndex);
- if (obj) {
- var result = this.mLastResults[obj.session];
- if (!result.errorDescription) {
- var count = result.matchCount;
- result.removeValueAt(obj.index, true);
- this.view.updateResults(this.popup.selectedIndex, result.matchCount - count);
- killEvent = true;
- }
- }
- }
- break;
- }
-
- if (killEvent) {
- aEvent.preventDefault();
- aEvent.stopPropagation();
- }
-
- return true;
- ]]></body>
- </method>
-
- <!-- -->
- <method name="processStartComposition">
- <body><![CDATA[
- this.finishAutoComplete(false, false, null);
- this.clearTimer();
- this.closePopup();
- ]]></body>
- </method>
-
- <!-- -->
- <method name="keyNavigation">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var k = aEvent.keyCode;
- if (k == KeyEvent.DOM_VK_TAB ||
- k == KeyEvent.DOM_VK_UP || k == KeyEvent.DOM_VK_DOWN ||
- k == KeyEvent.DOM_VK_PAGE_UP || k == KeyEvent.DOM_VK_PAGE_DOWN)
- {
- if (!this.mMenuOpen) {
- // Original xpfe style was to allow the up and down keys to have
- // their default Mac action if the popup could not be opened.
- // For compatibility for toolkit we now have to predict which
- // keys have a default action that we can always allow to fire.
- if (/Mac/.test(navigator.platform) &&
- ((k == KeyEvent.DOM_VK_UP &&
- (this.selectionStart != 0 ||
- this.selectionEnd != 0)) ||
- (k == KeyEvent.DOM_VK_DOWN &&
- (this.selectionStart != this.value.length ||
- this.selectionEnd != this.value.length))))
- return false;
- if (this.currentSearchString != this.value) {
- this.processInput();
- return true;
- }
- if (this.view.rowCount < this.minResultsForPopup)
- return true; // used to be false, see above
-
- this.mNeedToFinish = true;
- this.openPopup();
- return true;
- }
-
- this.userAction = "scrolling";
- this.mNeedToComplete = false;
-
- var reverse = k == KeyEvent.DOM_VK_TAB && aEvent.shiftKey ||
- k == KeyEvent.DOM_VK_UP ||
- k == KeyEvent.DOM_VK_PAGE_UP;
- var page = k == KeyEvent.DOM_VK_PAGE_UP ||
- k == KeyEvent.DOM_VK_PAGE_DOWN;
- var selected = this.popup.selectBy(reverse, page);
-
- // determine which value to place in the textbox
- this.ignoreInputEvent = true;
- if (selected != -1) {
- if (this.getErrorAt(selected)) {
- if (this.currentSearchString)
- this.setTextValue(this.currentSearchString);
- } else {
- this.setTextValue(this.getResultValueAt(selected));
- }
- this.mTransientValue = true;
- } else {
- if (this.currentSearchString)
- this.setTextValue(this.currentSearchString);
- this.mTransientValue = false;
- }
-
- // move cursor to the end
- this.mInputElt.setSelectionRange(this.value.length, this.value.length);
- this.ignoreInputEvent = false;
- }
- return true;
- ]]></body>
- </method>
-
- <!-- while the user is typing, fill the textbox with the "default" value
- if one can be assumed, and select the end of the text -->
- <method name="autoFillInput">
- <parameter name="aSessionName"/>
- <parameter name="aResults"/>
- <parameter name="aUseFirstMatchIfNoDefault"/>
- <body><![CDATA[
- if (this.mInputElt.selectionEnd < this.currentSearchString.length ||
- this.mDefaultMatchFilled)
- return;
-
- if (!this.mFinishAfterSearch &&
- (this.autoFill || this.completeDefaultIndex) &&
- this.mLastKeyCode != KeyEvent.DOM_VK_BACK_SPACE &&
- this.mLastKeyCode != KeyEvent.DOM_VK_DELETE) {
- var indexToUse = aResults.defaultIndex;
- if (aUseFirstMatchIfNoDefault && indexToUse == -1)
- indexToUse = 0;
-
- if (indexToUse != -1) {
- var resultValue = this.getSessionValueAt(aSessionName, indexToUse);
- var match = resultValue.toLowerCase();
- var entry = this.currentSearchString.toLowerCase();
- this.ignoreInputEvent = true;
- if (match.indexOf(entry) == 0) {
- var endPoint = this.value.length;
- this.setTextValue(this.value + resultValue.substr(endPoint));
- this.mInputElt.setSelectionRange(endPoint, this.value.length);
- } else {
- if (this.completeDefaultIndex) {
- this.setTextValue(this.value + " >> " + resultValue);
- this.mInputElt.setSelectionRange(entry.length, this.value.length);
- } else {
- var postIndex = resultValue.indexOf(this.value);
- if (postIndex >= 0) {
- var startPt = this.value.length;
- this.setTextValue(this.value +
- resultValue.substr(startPt+postIndex));
- this.mInputElt.setSelectionRange(startPt, this.value.length);
- }
- }
- }
- this.mNeedToComplete = true;
- this.ignoreInputEvent = false;
- this.mDefaultMatchFilled = true;
- }
- }
- ]]></body>
- </method>
-
- <!-- ::::::::::::: popup and tree ::::::::::::: -->
-
- <!-- -->
- <method name="openPopup">
- <body><![CDATA[
- if (!this.mMenuOpen && this.focused &&
- (this.getResultCount() >= this.minResultsForPopup ||
- this.mFailureItems)) {
- var w = this.boxObject.width;
- if (w != this.popup.boxObject.width)
- this.popup.setAttribute("width", w);
- this.popup.showPopup(this, -1, -1, "popup", "bottomleft", "topleft");
- this.mMenuOpen = true;
- }
- ]]></body>
- </method>
-
- <!-- -->
- <method name="closePopup">
- <body><![CDATA[
- if (this.popup && this.mMenuOpen) {
- this.popup.hidePopup();
- this.mMenuOpen = false;
- }
- ]]></body>
- </method>
-
- <!-- -->
- <method name="addResultElements">
- <parameter name="aSession"/>
- <parameter name="aResults"/>
- <body><![CDATA[
- var count = aResults.errorDescription ? 1 : aResults.matchCount;
- if (this.focused && this.showPopup) {
- var row = 0;
- for (var name in this.mSessions) {
- row += this.mLastRows[name];
- if (name == aSession)
- break;
- }
- this.view.updateResults(row, count - this.mLastRows[name]);
- this.popup.adjustHeight();
- }
- this.mLastResults[aSession] = aResults;
- this.mLastRows[aSession] = count;
- ]]></body>
- </method>
-
- <!-- -->
- <method name="clearResultElements">
- <parameter name="aInvalidate"/>
- <body><![CDATA[
- for (var name in this.mSessions)
- this.mLastRows[name] = 0;
- this.view.clearResults();
- if (aInvalidate)
- this.popup.adjustHeight();
-
- this.noMatch = true;
- ]]></body>
- </method>
-
- <!-- -->
- <method name="setTextValue">
- <parameter name="aValue"/>
- <body><![CDATA[
- this.value = aValue;
-
- // Completing a result should simulate the user typing the result,
- // so fire an input event.
- var evt = document.createEvent("UIEvents");
- evt.initUIEvent("input", true, false, window, 0);
- var oldIgnoreInput = this.ignoreInputEvent;
- this.ignoreInputEvent = true;
- this.dispatchEvent(evt);
- this.ignoreInputEvent = oldIgnoreInput;
- ]]></body>
- </method>
-
- <!-- -->
- <method name="clearResultData">
- <body><![CDATA[
- for (var name in this.mSessions)
- this.mLastResults[name] = null;
- ]]></body>
- </method>
-
- <!-- ::::::::::::: miscellaneous ::::::::::::: -->
-
- <!-- -->
- <method name="ifSetAttribute">
- <parameter name="aAttr"/>
- <parameter name="aVal"/>
- <body><![CDATA[
- if (!this.hasAttribute(aAttr))
- this.setAttribute(aAttr, aVal);
- ]]></body>
- </method>
-
- <!-- -->
- <method name="clearTimer">
- <body><![CDATA[
- if (this.mAutoCompleteTimer) {
- clearTimeout(this.mAutoCompleteTimer);
- this.mAutoCompleteTimer = 0;
- }
- ]]></body>
- </method>
-
- <!-- ::::::::::::: event dispatching ::::::::::::: -->
-
- <method name="_fireEvent">
- <parameter name="aEventType"/>
- <parameter name="aEventParam"/>
- <parameter name="aTriggeringEvent"/>
- <body>
- <![CDATA[
- var noCancel = true;
- // handle any xml attribute event handlers
- var handler = this.getAttribute("on"+aEventType);
- if (handler) {
- var fn = new Function("eventParam", "domEvent", handler);
- var returned = fn.apply(this, [aEventParam, aTriggeringEvent]);
- if (returned == false)
- noCancel = false;
- }
-
- return noCancel;
- ]]>
- </body>
- </method>
-
- <!-- =================== TREE VIEW =================== -->
-
- <field name="view"><![CDATA[
- ({
- mTextbox: this,
- mTree: null,
- mSelection: null,
- mRowCount: 0,
-
- clearResults: function()
- {
- var oldCount = this.mRowCount;
- this.mRowCount = 0;
-
- if (this.mTree) {
- this.mTree.rowCountChanged(0, -oldCount);
- this.mTree.scrollToRow(0);
- }
- },
-
- updateResults: function(aRow, aCount)
- {
- this.mRowCount += aCount;
-
- if (this.mTree)
- this.mTree.rowCountChanged(aRow, aCount);
- },
-
- //////////////////////////////////////////////////////////
- // nsIAutoCompleteController interface
-
- // this is the only method required by the treebody mouseup handler
- handleEnter: function(aIsPopupSelection) {
- this.mTextbox.onResultClick();
- },
-
- //////////////////////////////////////////////////////////
- // nsITreeView interface
-
- get rowCount() {
- return this.mRowCount;
- },
-
- get selection() {
- return this.mSelection;
- },
-
- set selection(aVal) {
- return this.mSelection = aVal;
- },
-
- setTree: function(aTree)
- {
- this.mTree = aTree;
- },
-
- getCellText: function(aRow, aCol)
- {
- for (var name in this.mTextbox.mSessions) {
- if (aRow < this.mTextbox.mLastRows[name]) {
- var result = this.mTextbox.mLastResults[name];
- switch (aCol.id) {
- case "treecolAutoCompleteValue":
- return result.errorDescription || result.getLabelAt(aRow);
- case "treecolAutoCompleteComment":
- if (!result.errorDescription)
- return result.getCommentAt(aRow);
- default:
- return "";
- }
- }
- aRow -= this.mTextbox.mLastRows[name];
- }
- return "";
- },
-
- getRowProperties: function(aIndex)
- {
- return "";
- },
-
- getCellProperties: function(aIndex, aCol)
- {
- // for the value column, append nsIAutoCompleteItem::className
- // to the property list so that we can style this column
- // using that property
- if (aCol.id == "treecolAutoCompleteValue") {
- for (var name in this.mTextbox.mSessions) {
- if (aIndex < this.mTextbox.mLastRows[name]) {
- var result = this.mTextbox.mLastResults[name];
- if (result.errorDescription)
- return "";
- return result.getStyleAt(aIndex);
- }
- aIndex -= this.mTextbox.mLastRows[name];
- }
- }
- return "";
- },
-
- getColumnProperties: function(aCol)
- {
- return "";
- },
-
- getImageSrc: function(aRow, aCol)
- {
- if (aCol.id == "treecolAutoCompleteValue") {
- for (var name in this.mTextbox.mSessions) {
- if (aRow < this.mTextbox.mLastRows[name]) {
- var result = this.mTextbox.mLastResults[name];
- if (result.errorDescription)
- return "";
- return result.getImageAt(aRow);
- }
- aRow -= this.mTextbox.mLastRows[name];
- }
- }
- return "";
- },
-
- getParentIndex: function(aRowIndex) { },
- hasNextSibling: function(aRowIndex, aAfterIndex) { },
- getLevel: function(aIndex) {},
- getProgressMode: function(aRow, aCol) {},
- getCellValue: function(aRow, aCol) {},
- isContainer: function(aIndex) {},
- isContainerOpen: function(aIndex) {},
- isContainerEmpty: function(aIndex) {},
- isSeparator: function(aIndex) {},
- isSorted: function() {},
- toggleOpenState: function(aIndex) {},
- selectionChanged: function() {},
- cycleHeader: function(aCol) {},
- cycleCell: function(aRow, aCol) {},
- isEditable: function(aRow, aCol) {},
- isSelectable: function(aRow, aCol) {},
- setCellValue: function(aRow, aCol, aValue) {},
- setCellText: function(aRow, aCol, aValue) {},
- performAction: function(aAction) {},
- performActionOnRow: function(aAction, aRow) {},
- performActionOnCell: function(aAction, aRow, aCol) {}
- });
- ]]></field>
-
- </implementation>
-
- <handlers>
- <handler event="input"
- action="if (!this.ignoreInputEvent) this.processInput();"/>
-
- <handler event="keypress" phase="capturing"
- action="return this.processKeyPress(event);"/>
-
- <handler event="compositionstart" phase="capturing"
- action="this.processStartComposition();"/>
-
- <handler event="focus" phase="capturing"
- action="this.userAction = 'typing';"/>
-
- <handler event="blur" phase="capturing"
- action="if ( !(this.ignoreBlurWhileSearching && this.isSearching) ) {this.userAction = 'none'; this.finishAutoComplete(false, false, event);}"/>
-
- <handler event="mousedown" phase="capturing"
- action="if ( !this.mMenuOpen ) this.finishAutoComplete(false, false, event);"/>
- </handlers>
- </binding>
-
- <binding id="autocomplete-result-popup" extends="chrome://global/content/bindings/popup.xml#popup">
- <resources>
- <stylesheet src="chrome://communicator/content/autocomplete.css"/>
- <stylesheet src="chrome://global/skin/autocomplete.css"/>
- </resources>
-
- <content ignorekeys="true" level="top">
- <xul:tree anonid="tree" class="autocomplete-tree plain" flex="1">
- <xul:treecols anonid="treecols">
- <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteValue" flex="2"/>
- <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteComment" flex="1" hidden="true"/>
- </xul:treecols>
- <xul:treechildren anonid="treebody" class="autocomplete-treebody"/>
- </xul:tree>
- </content>
-
- <implementation implements="nsIAutoCompletePopup">
- <constructor><![CDATA[
- if (this.textbox && this.textbox.view)
- this.initialize();
- ]]></constructor>
-
- <destructor><![CDATA[
- if (this.view)
- this.tree.view = null;
- ]]></destructor>
-
- <field name="textbox">
- document.getBindingParent(this);
- </field>
-
- <field name="tree">
- document.getAnonymousElementByAttribute(this, "anonid", "tree");
- </field>
-
- <field name="treecols">
- document.getAnonymousElementByAttribute(this, "anonid", "treecols");
- </field>
-
- <field name="treebody">
- document.getAnonymousElementByAttribute(this, "anonid", "treebody");
- </field>
-
- <field name="view">
- null
- </field>
-
- <!-- Setting tree.view doesn't always immediately create a selection,
- so we ensure the selection by asking the tree for the view. Note:
- this.view.selection is quicker if we know the selection exists. -->
- <property name="selection" onget="return this.tree.view.selection;"/>
-
- <property name="pageCount"
- onget="return this.tree.treeBoxObject.getPageLength();"/>
-
- <field name="maxRows">0</field>
- <field name="mLastRows">0</field>
-
- <method name="initialize">
- <body><![CDATA[
- this.showCommentColumn = this.textbox.showCommentColumn;
- this.tree.view = this.textbox.view;
- this.view = this.textbox.view;
- this.maxRows = this.textbox.maxRows;
- ]]></body>
- </method>
-
- <property name="showCommentColumn"
- onget="return !this.treecols.lastChild.hidden;"
- onset="this.treecols.lastChild.hidden = !val; return val;"/>
-
- <method name="adjustHeight">
- <body><![CDATA[
- // detect the desired height of the tree
- var bx = this.tree.treeBoxObject;
- var view = this.view;
- var rows = this.maxRows || 6;
- if (!view.rowCount || (rows && view.rowCount < rows))
- rows = view.rowCount;
-
- var height = rows * bx.rowHeight;
-
- if (height == 0)
- this.tree.setAttribute("collapsed", "true");
- else {
- if (this.tree.hasAttribute("collapsed"))
- this.tree.removeAttribute("collapsed");
- this.tree.setAttribute("height", height);
- }
- ]]></body>
- </method>
-
- <method name="clearSelection">
- <body>
- this.selection.clearSelection();
- </body>
- </method>
-
- <method name="getNextIndex">
- <parameter name="aReverse"/>
- <parameter name="aPage"/>
- <parameter name="aIndex"/>
- <parameter name="aMaxRow"/>
- <body><![CDATA[
- if (aMaxRow < 0)
- return -1;
-
- if (aIndex == -1)
- return aReverse ? aMaxRow : 0;
- if (aIndex == (aReverse ? 0 : aMaxRow))
- return -1;
-
- var amount = aPage ? this.pageCount - 1 : 1;
- aIndex = aReverse ? aIndex - amount : aIndex + amount;
- if (aIndex > aMaxRow)
- return aMaxRow;
- if (aIndex < 0)
- return 0;
- return aIndex;
- ]]></body>
- </method>
-
- <!-- =================== nsIAutoCompletePopup =================== -->
-
- <field name="input">
- null
- </field>
-
- <!-- This property is meant to be overriden by bindings extending
- this one. When the user selects an item from the list by
- hitting enter or clicking, this method can set the value
- of the textbox to a different value if it wants to. -->
- <property name="overrideValue" readonly="true" onget="return null;"/>
-
- <property name="selectedIndex">
- <getter>
- if (!this.view || !this.selection.count)
- return -1;
- var start = {}, end = {};
- this.view.selection.getRangeAt(0, start, end);
- return start.value;
- </getter>
- <setter>
- if (this.view) {
- this.selection.select(val);
- if (val >= 0) {
- this.view.selection.currentIndex = -1;
- this.tree.treeBoxObject.ensureRowIsVisible(val);
- }
- }
- return val;
- </setter>
- </property>
-
- <property name="popupOpen" onget="return !!this.input;" readonly="true"/>
-
- <method name="openAutocompletePopup">
- <parameter name="aInput"/>
- <parameter name="aElement"/>
- <body><![CDATA[
- if (!this.input) {
- this.tree.view = aInput.controller;
- this.view = this.tree.view;
- this.showCommentColumn = aInput.showCommentColumn;
- this.maxRows = aInput.maxRows;
- this.invalidate();
-
- var viewer = aElement.ownerGlobal
- .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
- .getInterface(Components.interfaces.nsIWebNavigation)
- .QueryInterface(Components.interfaces.nsIDocShell)
- .contentViewer;
- var rect = aElement.getBoundingClientRect();
- var width = Math.round((rect.right - rect.left) * viewer.fullZoom);
- this.setAttribute("width", width > 100 ? width : 100);
- // Adjust the direction (which is not inherited) of the autocomplete
- // popup list, based on the textbox direction. (Bug 707039)
- this.style.direction = aElement.ownerGlobal
- .getComputedStyle(aElement)
- .direction;
- this.popupBoxObject.setConsumeRollupEvent(aInput.consumeRollupEvent
- ? PopupBoxObject.ROLLUP_CONSUME
- : PopupBoxObject.ROLLUP_NO_CONSUME);
- this.openPopup(aElement, "after_start", 0, 0, false, false);
- if (this.state != "closed")
- this.input = aInput;
- }
- ]]></body>
- </method>
-
- <method name="closePopup">
- <body>
- this.hidePopup();
- </body>
- </method>
-
- <method name="invalidate">
- <body>
- if (this.view)
- this.adjustHeight();
- this.tree.treeBoxObject.invalidate();
- </body>
- </method>
-
- <method name="selectBy">
- <parameter name="aReverse"/>
- <parameter name="aPage"/>
- <body><![CDATA[
- try {
- return this.selectedIndex = this.getNextIndex(aReverse, aPage, this.selectedIndex, this.view.rowCount - 1);
- } catch (ex) {
- // do nothing - occasionally timer-related js errors happen here
- // e.g. "this.selectedIndex has no properties", when you type fast and hit a
- // navigation key before this popup has opened
- return -1;
- }
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="popupshowing">
- if (this.textbox)
- this.textbox.mMenuOpen = true;
- </handler>
-
- <handler event="popuphiding">
- if (this.textbox)
- this.textbox.mMenuOpen = false;
- this.clearSelection();
- this.input = null;
- </handler>
- </handlers>
- </binding>
-
- <binding id="autocomplete-treebody">
- <implementation>
- <field name="popup">document.getBindingParent(this);</field>
-
- <field name="mLastMoveTime">Date.now()</field>
- </implementation>
-
- <handlers>
- <handler event="mouseout" action="this.popup.selectedIndex = -1;"/>
-
- <handler event="mouseup"><![CDATA[
- var rc = this.parentNode.treeBoxObject.getRowAt(event.clientX, event.clientY);
- if (rc != -1) {
- this.popup.selectedIndex = rc;
- this.popup.view.handleEnter(true);
- }
- ]]></handler>
-
- <handler event="mousemove"><![CDATA[
- if (Date.now() - this.mLastMoveTime > 30) {
- var rc = this.parentNode.treeBoxObject.getRowAt(event.clientX, event.clientY);
- if (rc != -1 && rc != this.popup.selectedIndex)
- this.popup.selectedIndex = rc;
- this.mLastMoveTime = Date.now();
- }
- ]]></handler>
- </handlers>
- </binding>
-
- <binding id="autocomplete-history-popup"
- extends="chrome://global/content/bindings/popup.xml#popup-scrollbars">
- <resources>
- <stylesheet src="chrome://communicator/content/autocomplete.css"/>
- <stylesheet src="chrome://global/skin/autocomplete.css"/>
- </resources>
-
- <implementation>
- <method name="removeOpenAttribute">
- <parameter name="parentNode"/>
- <body><![CDATA[
- parentNode.removeAttribute("open");
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="popuphiding"><![CDATA[
- setTimeout(this.removeOpenAttribute, 0, this.parentNode);
- ]]></handler>
- </handlers>
- </binding>
-
- <binding id="history-dropmarker" extends="chrome://global/content/bindings/general.xml#dropmarker">
-
- <implementation>
- <method name="showPopup">
- <body><![CDATA[
- var textbox = document.getBindingParent(this);
- var kids = textbox.getElementsByClassName("autocomplete-history-popup");
- if (kids.item(0) && textbox.getAttribute("open") != "true") { // Open history popup
- var w = textbox.boxObject.width;
- if (w != kids[0].boxObject.width)
- kids[0].width = w;
- kids[0].showPopup(textbox, -1, -1, "popup", "bottomleft", "topleft");
- textbox.setAttribute("open", "true");
- }
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="mousedown"><![CDATA[
- this.showPopup();
- ]]></handler>
- </handlers>
- </binding>
-
-</bindings>