home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / AIMP2 / aimp_2.61.583.exe / $TEMP / YandexPackSetup.msi / filA498F2EC89E811547297CEC985988237 < prev    next >
Extensible Markup Language  |  2010-07-12  |  81KB  |  2,246 lines

  1. <?xml version="1.0"?>
  2. <!DOCTYPE bindings [
  3.   <!ENTITY % yasearchDTD SYSTEM "chrome://yasearch/locale/yasearch.dtd">
  4.   %yasearchDTD;
  5.   <!ENTITY % yaSearchboxDTD SYSTEM "chrome://yasearch/locale/searchbox/searchbox.dtd">
  6.   %yaSearchboxDTD;
  7. ]>
  8. <bindings xmlns="http://www.mozilla.org/xbl"
  9.           xmlns:xbl="http://www.mozilla.org/xbl"
  10.           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  11.   
  12.   <binding id="searchbox-base">
  13.     <resources>
  14.       <stylesheet src="chrome://yasearch/skin/searchbox/searchbox.css"/>
  15.     </resources>
  16.   </binding>
  17.   
  18.   <binding id="searchbox-resizer"
  19.            extends="chrome://yasearch/content/searchbox/searchbox.xml#searchbox-base">
  20.     <implementation implements="nsIDOMEventListener">
  21.       <field name="dragging"/>
  22.       <field name="lastX"/>
  23.  
  24.       <method name="resizerMouseMove">
  25.         <parameter name="event"/>
  26.         <body><![CDATA[
  27.           if (!this.dragging)
  28.             return;
  29.           
  30.           var xDiff = this.lastX - event.screenX;
  31.           
  32.           if (xDiff == 0)
  33.             return;
  34.           
  35.           var currWidth = parseInt(this.parentNode.boxObject.width, 10);
  36.           if (xDiff > 0) {
  37.             currWidth -= xDiff;
  38.           } else {
  39.             var toolbar = this.parentNode.parentNode.parentNode;
  40.             var toolbarWidth = parseInt(toolbar.boxObject.width, 10) - 150;
  41.             
  42.             if (currWidth < toolbarWidth)
  43.               currWidth -= xDiff;
  44.           }
  45.           
  46.           this.parentNode.setAttribute("width", currWidth);
  47.           
  48.           this.lastX = event.screenX;
  49.         ]]></body>
  50.       </method>
  51.       
  52.       <method name="resizerMouseUp">
  53.         <parameter name="event"/>
  54.           <body><![CDATA[
  55.             this.dragging = false;
  56.             this.ownerDocument.documentElement.style.cursor = "";
  57.             
  58.             window.removeEventListener("mouseup", this, true);
  59.             window.removeEventListener("mousemove", this, true);
  60.             
  61.             var parent = document.getBindingParent(this);
  62.             parent.updateWidthOnResize();
  63.           ]]></body>
  64.       </method>
  65.       
  66.       <constructor><![CDATA[
  67.         this.dragging = false;
  68.       ]]></constructor>
  69.       
  70.       <method name="handleEvent">
  71.         <parameter name="aEvent"/>
  72.         <body><![CDATA[
  73.           switch (aEvent.type) {
  74.             case "mouseup":
  75.               this.resizerMouseUp(aEvent);
  76.               break;
  77.             
  78.             case "mousemove":
  79.               this.resizerMouseMove(aEvent);
  80.               break;
  81.             
  82.             default:
  83.               break;
  84.           }
  85.         ]]></body>
  86.       </method>
  87.     </implementation>
  88.     
  89.     <handlers>
  90.       <handler event="mousedown" button="0"><![CDATA[
  91.         this.dragging = true;
  92.         this.lastX = event.screenX;
  93.         
  94.         this.ownerDocument.documentElement.style.cursor = "e-resize";
  95.         
  96.         window.addEventListener("mouseup", this, true);
  97.         window.addEventListener("mousemove", this, true);
  98.       ]]></handler>
  99.     </handlers>
  100.   </binding>
  101.   
  102.   <binding id="searchbox"
  103.            extends="chrome://yasearch/content/searchbox/searchbox.xml#searchbox-base">
  104.     
  105.     <content yaSHistoryHeight="230"
  106.              persist="yaSHistoryWidth,yaSHistoryHeight,searchengine,src,width,yaSButtonDisabled">
  107.       
  108.       <xul:stringbundle src="chrome://yasearch/locale/searchbox/searchbox.properties"
  109.                         anonid="yasearchbar-stringbundle"/>
  110.       <xul:popupset>
  111.         <xul:popup id="yasearchbar-search-button-context">
  112.           <xul:menuitem label="&yasearchox.button.context.label;"
  113.                         oncommand="_textbox.yasearchbarController.doCommand('cmd_showsearchbutton')"/>
  114.         </xul:popup>
  115.         
  116.         <xul:panel id="yasearch-popup-autocomplete-panel"
  117.                    type="autocomplete"
  118.                    class="autocomplete-history-popup"
  119.                    anonid="autocomplete-history-popup"
  120.                    noautofocus="true"
  121.                    hidden="true"
  122.                    yaEmptyResultList="true"
  123.                    xbl:inherits="yaSHistoryWidth,yaSHistoryHeight"/>
  124.       </xul:popupset>
  125.       
  126.       <xul:textbox class="yasearchbar-textbox"
  127.                    anonid="yasearchbar-textbox"
  128.                    type="autocomplete"
  129.                    flex="1"
  130.                    autocompletepopup="yasearch-popup-autocomplete-panel"
  131.                    autocompletesearch="yasearch-autocomplete"
  132.                    autocompletesearchparam="yasearch-history"
  133.                    timeout="250"
  134.                    maxrows="20"
  135.                    completeselectedindex="true"
  136.                    showcommentcolumn="true"
  137.                    tabscrolling="true"
  138.                    enablehistory="true"
  139.                    newlines="replacewithspaces"
  140.                    xbl:inherits="disabled,searchengine,src">
  141.         
  142.         <xul:button class="yasearchbar-engine-button"
  143.                     type="menu"
  144.                     anonid="yasearchbar-engine-button">
  145.           <xul:image class="yasearchbar-engine-image" xbl:inherits="src"/>
  146.           <xul:image class="yasearchbar-dropmarker-image"/>
  147.           
  148.           <xul:menupopup class="yasearchbar-popup"
  149.                          anonid="yasearchbar-popup"
  150.                          position="after_start">
  151.             <xul:menuseparator anonid="engines-list-separator-yandex"/>
  152.             <xul:menuseparator anonid="engines-list-separator-browser"/>
  153.             <xul:menuitem class="open-engine-manager"
  154.                           anonid="open-engine-manager"
  155.                           label="&cmd_engineManager.label;"
  156.                           oncommand="openManager(event);"/>
  157.           </xul:menupopup>
  158.         </xul:button>
  159.       </xul:textbox>
  160.       
  161.       <xul:toolbarbutton class="yasearchbar-search-button"
  162.                          anonid="yasearchbar-search-button"
  163.                          label="&yasearchox.button.label;"
  164.                          disabled="false"
  165.                          context="yasearchbar-search-button-context"
  166.                          oncommand="handleSearchCommand(event)"/>
  167.       
  168.       <xul:yasearchboxresizer tooltiptext="&yasearchox.resizer.tooltiptext;"/>
  169.       
  170.       <xul:yasearchboxhighlighter anonid="highlighter" hidden="false"/>
  171.     </content>
  172.     
  173.     <implementation implements="nsIObserver">
  174.       <method name="updateCursorVisibility">
  175.         <body><![CDATA[
  176.           if (!this._textbox.editor)
  177.             return;
  178.           
  179.           const nsISelectionController = Components.interfaces.nsISelectionController;
  180.           this._textbox.editor.selectionController.scrollSelectionIntoView(
  181.               nsISelectionController.SELECTION_NORMAL,
  182.               nsISelectionController.SELECTION_FOCUS_REGION,
  183.               false
  184.           );
  185.         ]]></body>
  186.       </method>
  187.       
  188.       <method name="updateWidthOnResize">
  189.         <body><![CDATA[
  190.           var width = parseInt(this.ownerDocument.defaultView.getComputedStyle(this._textbox, "").width, 10);
  191.           this.setAttribute("yaSHistoryWidth", width);
  192.           
  193.           this.updateCursorVisibility();
  194.         ]]></body>
  195.       </method>
  196.       
  197.       <method name="getElementByAnonid">
  198.         <parameter name="aAnonidAttr"/>
  199.         <body><![CDATA[
  200.           return document.getAnonymousElementByAttribute(this, "anonid", aAnonidAttr);
  201.         ]]></body>
  202.       </method>
  203.       
  204.       <property name="_isCanInit" readonly="true"
  205.                 onget="return this.parentNode.parentNode.localName != 'toolbarpaletteitem';"/>
  206.       
  207.       <constructor><![CDATA[
  208.         if (!this._isCanInit)
  209.           return;
  210.         
  211.         setTimeout(function(me) { me.init(); }, 0, this);
  212.       ]]></constructor>
  213.       
  214.       <destructor><![CDATA[
  215.         if (!this._isInited)
  216.           return;
  217.         
  218.         this._currentEngine = null;
  219.         
  220.         YaProgressListener.removeListener(this.mLocationListener);
  221.         
  222.         var os = Components.classes["@mozilla.org/observer-service;1"]
  223.                            .getService(Components.interfaces.nsIObserverService);
  224.         os.removeObserver(this, "browser-search-engine-modified");
  225.         
  226.         if (this._textbox.mController.input == this)
  227.           this._textbox.mController.input = null;
  228.         
  229.         this._isInited = false;
  230.       ]]></destructor>
  231.       
  232.       <field name="_stringBundle">this.getElementByAnonid("yasearchbar-stringbundle")</field>
  233.       <field name="_textbox">this.getElementByAnonid("yasearchbar-textbox")</field>
  234.       <field name="_popup">this.getElementByAnonid("yasearchbar-popup")</field>
  235.       <field name="_engineButton">this.getElementByAnonid("yasearchbar-engine-button")</field>
  236.       <field name="_searchButton">this.getElementByAnonid("yasearchbar-search-button")</field>
  237.       <field name="_acompletepopup">this.getElementByAnonid("autocomplete-history-popup")</field>
  238.       <field name="_highlighter">this.getElementByAnonid("highlighter")</field>
  239.       <field name="_userTextInput">false</field>
  240.       
  241.       <property name="value" onget="return this._textbox.value;"
  242.                              onset="return this._textbox.value = val;"/>
  243.       
  244.       <method name="focus">
  245.         <body><![CDATA[
  246.           this._textbox.focus();
  247.         ]]></body>
  248.       </method>
  249.       
  250.       <method name="select">
  251.         <body><![CDATA[
  252.           this._textbox.select();
  253.         ]]></body>
  254.       </method>
  255.       
  256.       <property name="nsIYa">
  257.         <getter><![CDATA[
  258.           if (!this._nsIYa)
  259.             this._nsIYa = Components.classes["@yandex.ru/yasearch;1"]
  260.                                     .getService(Components.interfaces.nsIYaSearch)
  261.                                     .wrappedJSObject;
  262.           return this._nsIYa;
  263.         ]]></getter>
  264.       </property>
  265.       
  266.       <method name="getYaTabHandlerData">
  267.         <parameter name="aBrowser"/>
  268.         <body><![CDATA[
  269.           var yaTabHandler = (aBrowser || gBrowser.mCurrentBrowser).yaSearchTHandler;
  270.           
  271.           if (!(yaTabHandler && yaTabHandler.tabData))
  272.             return {};
  273.           
  274.           if (!yaTabHandler.tabData.searchbox) {
  275.             yaTabHandler.tabData.searchbox = {
  276.               inputValue: "",
  277.               userTextInput: false,
  278.               lastLocationSpec: null
  279.             }
  280.           }
  281.           
  282.           if (!yaTabHandler.tabData.highlighter) {
  283.             yaTabHandler.tabData.highlighter = {
  284.               enabled: false,
  285.               lastHighlightString: "",
  286.               lastHighlightWords: null,
  287.               serpText: null,
  288.               highlightDone: false,
  289.               keyListener: null,
  290.               keyDown: null
  291.             }
  292.           }
  293.           
  294.           return yaTabHandler.tabData;
  295.         ]]></body>
  296.       </method>
  297.       
  298.       <field name="mLocationListener">
  299.         <![CDATA[({
  300.         _self: this,
  301.         
  302.         observe: function() {
  303.           switch (arguments[0]) {
  304.             case "onWindowLocationChange":
  305.               var [, aWebProgress, aRequest, aLocation] = arguments;
  306.               
  307.               let _self = this._self;
  308.               
  309.               var serpText = _self.getYaTabHandlerData().highlighter.serpText;
  310.               if (serpText) {
  311.                 _self.value = serpText;
  312.                 var event = document.createEvent("Events");
  313.                 event.initEvent("input", true, true);
  314.                 _self.dispatchEvent(event);
  315.                 return;
  316.               }
  317.               
  318.               var tabSearchData = _self.getYaTabHandlerData().searchbox;
  319.               
  320.               var inputValue = tabSearchData.inputValue;
  321.               var locationSpec = aLocation ? aLocation.spec : null;
  322.               
  323.               if (locationSpec !== tabSearchData.lastLocationSpec) {
  324.                 tabSearchData.lastLocationSpec = locationSpec;
  325.                 
  326.                 if (locationSpec && /http(s)?/.test(aLocation.scheme)) {
  327.                   if (aLocation.scheme == "http") {
  328.                     var searchWord = YaUtils.getSearchTextFromLocation(aLocation, aWebProgress);
  329.                     
  330.                     if (searchWord) {
  331.                       _self.addSearchHistoryEntry(searchWord);
  332.                       
  333.                       if (!tabSearchData.userTextInput) {
  334.                         inputValue = searchWord;
  335.                         tabSearchData.inputValue = searchWord;
  336.                       }
  337.                     }
  338.                   }
  339.                 }
  340.                 
  341.                 _self._acompletepopup.updateAppendix();
  342.               }
  343.               
  344.               _self.value = inputValue;
  345.               _self._userTextInput = tabSearchData.userTextInput;
  346.               
  347.               break;
  348.             
  349.             default:
  350.               break;
  351.           }
  352.         }
  353.       })]]>
  354.       </field>
  355.       
  356.       <property name="searchableHost" readonly="true">
  357.         <getter><![CDATA[
  358.           var currentLocation = (gBrowser && gBrowser.currentURI) ? gBrowser.currentURI : null;
  359.           
  360.           return (currentLocation && /http(s)?/.test(currentLocation.scheme) &&
  361.                   this._currentEngine.searchSite && this.nsIYa.prefs.showSiteSearch) ?
  362.             currentLocation.host : false;
  363.         ]]></getter>
  364.       </property>
  365.       
  366.       <property name="searchService" readonly="true">
  367.         <getter><![CDATA[
  368.           return this.nsIYa.searchService;
  369.         ]]></getter>
  370.       </property>
  371.       
  372.       <method name="init">
  373.         <body><![CDATA[
  374.           if (this.hasAttribute("yaDefaultWidth") && !this.hasAttribute("width")) {
  375.             this.setAttribute("width", this.getAttribute("yaDefaultWidth"));
  376.             this.updateWidthOnResize();
  377.           }
  378.           
  379.           YaProgressListener.addListener(this.mLocationListener);
  380.           
  381.           this.rebuildPopupServices();
  382.           
  383.           var os = Components.classes["@mozilla.org/observer-service;1"]
  384.                              .getService(Components.interfaces.nsIObserverService);
  385.           os.addObserver(this, "browser-search-engine-modified", false);
  386.           
  387.           if (BrowserSearch && !BrowserSearch.yaSearchBar && BrowserSearch.addEngine) {
  388.             var searchboxId = this.id;
  389.             BrowserSearch.__defineGetter__("yaSearchBar",
  390.                 function() {return document.getElementById(searchboxId);}
  391.             );
  392.             
  393.             eval("BrowserSearch.addEngine =" + BrowserSearch.addEngine.toString().replace(
  394.               "if (!this.searchBar)",
  395.               "if (!this.searchBar && !this.yaSearchBar)"
  396.             ));
  397.           }
  398.           
  399.           this._isInited = true;
  400.         ]]></body>
  401.       </method>
  402.       
  403.       <field name="_currentEngine">null</field>
  404.       
  405.       <property name="currentEngine"
  406.                 onget="return this.getAttribute('searchengine')">
  407.         <setter><![CDATA[
  408.           if (!val)
  409.             return;
  410.           
  411.           val = val.replace(/yasearchbox\-engine\-/, "");
  412.           
  413.           var engine = this.nsIYa.setCurrentSearchEngine(val);
  414.           if (engine) {
  415.             this.setAttribute("searchengine", val);
  416.             this.setAttribute("src", engine.image);
  417.             
  418.             var toolTipText = this._stringBundle.getFormattedString("searchtip", [engine.label]);
  419.             this._textbox.setAttribute("tooltiptext", toolTipText);
  420.             
  421.             this._currentEngine = engine;
  422.           }
  423.           
  424.           if (this._textbox.focused)
  425.             this._acompletepopup.checkNeedRefreshOnEngineChanged();
  426.         ]]></setter>
  427.       </property>
  428.       
  429.       <property name="currentEngineId" readonly="true">
  430.         <getter><![CDATA[
  431.           var currentEngine = this.currentEngine;
  432.           return (/^__/.test(currentEngine) ? "" : "yasearchbox-engine-") + currentEngine;
  433.         ]]></getter>
  434.       </property>
  435.       
  436.       <method name="checkCurrentEngine">
  437.         <body><![CDATA[
  438.           var currentEngine = this.currentEngine;
  439.           
  440.           if (currentEngine && !document.getAnonymousElementByAttribute(this, "id", this.currentEngineId))
  441.             currentEngine = null;
  442.           
  443.           if (!currentEngine)
  444.             this.currentEngine = this.nsIYa.getDefaultSearchEngine();
  445.           
  446.           this.currentEngine = this.currentEngine;
  447.         ]]></body>
  448.       </method>
  449.       
  450.       <method name="selectEngine">
  451.         <parameter name="aNewEngineId"/>
  452.         <parameter name="aEvent"/>
  453.         <parameter name="isNextEngine"/>
  454.         <body><![CDATA[
  455.           var newEngineId = aNewEngineId ||
  456.                             this.getNeighbourEngineId(this.currentEngineId,
  457.                                                       isNextEngine ? "next" : "previous");
  458.           if (newEngineId)
  459.             this.currentEngine = newEngineId;
  460.           
  461.           aEvent.preventDefault();
  462.           aEvent.stopPropagation();
  463.         ]]></body>
  464.       </method>
  465.       
  466.       <method name="getNeighbourEngineId">
  467.         <parameter name="aId"/>
  468.         <parameter name="aDirection"/>
  469.         <body><![CDATA[
  470.           var searchEngineMenuitem = document.getAnonymousElementByAttribute(this, "id", aId);
  471.           if (!searchEngineMenuitem)
  472.             return false;
  473.           
  474.           var newEngine = searchEngineMenuitem[aDirection + "Sibling"];
  475.           
  476.           while (newEngine && newEngine.localName != "menuitem")
  477.             newEngine = newEngine[aDirection + "Sibling"];
  478.           
  479.           if (!newEngine)
  480.             return false;
  481.           
  482.           if (document.defaultView.getComputedStyle(newEngine, "").display == "none")
  483.             return this.getNeighbourEngineId(newEngine.id, aDirection);
  484.           
  485.           return newEngine.id;
  486.         ]]></body>
  487.       </method>
  488.       
  489.       <method name="rebuildPopupServices">
  490.         <body>
  491.           <![CDATA[
  492.             var popup = this._popup;
  493.             var yandexSeparator = this.getElementByAnonid("engines-list-separator-yandex");
  494.             
  495.             var nodeToRemove;
  496.             while ((nodeToRemove = popup.firstChild) && nodeToRemove != yandexSeparator)
  497.               popup.removeChild(nodeToRemove);
  498.             
  499.             var menu = this.nsIYa.DOMUtils.adoptNode(this.nsIYa.getDOMDocContent("bar-search"), this.ownerDocument);
  500.             var menuItems = menu.childNodes;
  501.             
  502.             for (var i = 0, len = menuItems.length; i < len; i++)
  503.               this._popup.insertBefore(menuItems[i].cloneNode(true), yandexSeparator);
  504.             
  505.             this._needToBuildPopup = true;
  506.             this.rebuildPopup();
  507.           ]]>
  508.         </body>
  509.       </method>
  510.       
  511.       <method name="rebuildPopupDynamic">
  512.         <body><![CDATA[
  513.           if (this._needToBuildPopup)
  514.             this.rebuildPopup();
  515.           
  516.           var popup = this._popup,
  517.               items = popup.childNodes;
  518.           
  519.           for (var i = items.length; i-- > 0;) {
  520.             if (items[i].getAttribute("class").indexOf("addengine") != -1)
  521.               popup.removeChild(items[i]);
  522.           }
  523.           
  524.           var addengines = getBrowser().mCurrentBrowser.engines;
  525.           
  526.           if (addengines && addengines.length > 0) {
  527.             const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  528.             
  529.             var browserSeparator = this.getElementByAnonid("engines-list-separator-browser");
  530.             
  531.             var addengineSeparator = document.createElementNS(kXULNS, "menuseparator");
  532.             addengineSeparator.setAttribute("class", "addengine-separator");
  533.             popup.insertBefore(addengineSeparator, browserSeparator);
  534.             
  535.             addengines.forEach(function(engine) {
  536.               var menuitem = document.createElementNS(kXULNS, "menuitem");
  537.               menuitem.setAttribute("class", "menuitem-iconic addengine-item");
  538.               menuitem.setAttribute("label", this._stringBundle.getFormattedString("cmd_addFoundEngine", [engine.title]));
  539.               menuitem.setAttribute("title", engine.title);
  540.               menuitem.setAttribute("uri", engine.uri);
  541.               if (engine.icon)
  542.                 menuitem.setAttribute("src", engine.icon);
  543.               
  544.               popup.insertBefore(menuitem, browserSeparator);
  545.             }, this)
  546.           }
  547.         ]]></body>
  548.       </method>
  549.       
  550.       <method name="_popupFireKeyboardEvent">
  551.         <parameter name="aType"/>
  552.         <parameter name="aCount"/>
  553.         <body><![CDATA[
  554.           const kEvent = Components.interfaces.nsIDOMKeyEvent;
  555.           while (aCount-- > 0) {
  556.             var evt = document.createEvent("KeyboardEvent");
  557.             evt.initKeyEvent("keypress", true, true, null, false, false, false, false, kEvent["DOM_VK_" + aType], 0);
  558.             this._popup.dispatchEvent(evt);
  559.           }
  560.         ]]></body>
  561.       </method>
  562.       
  563.       <method name="rebuildPopupOnShowing">
  564.         <parameter name="aEvent"/>
  565.         <body><![CDATA[
  566.           this.rebuildPopupDynamic();
  567.           
  568.           setTimeout(function(_self) {
  569.             var keyMoveArray = [];
  570.             var currItem = document.getAnonymousElementByAttribute(_self, "id", _self.currentEngineId);
  571.             
  572.             if (!currItem)
  573.               return;
  574.             
  575.             var currPopup = currItem.parentNode;
  576.             
  577.             while (currItem) {
  578.               var i = 0, prevItem = currItem.previousSibling;
  579.               while (prevItem) {
  580.                 if ((prevItem.localName == "menuitem" || prevItem.localName == "menu") &&
  581.                     prevItem.style.display != "none")
  582.                   i++;
  583.                 prevItem = prevItem.previousSibling;
  584.               }
  585.               
  586.               keyMoveArray.push(i);
  587.               
  588.               var parent = currItem.parentNode.parentNode;
  589.               
  590.               currItem = parent.nodeName == "menu" ? parent : null;
  591.             }
  592.             
  593.             for (var i = keyMoveArray.length; i-- > 0;) {
  594.               _self._popupFireKeyboardEvent("RIGHT", 1);
  595.               _self._popupFireKeyboardEvent("DOWN", keyMoveArray[i]);
  596.             }
  597.             
  598.             _self.__bugCurrentPopup = keyMoveArray.length > 1 ? currPopup : null;
  599.           }, 0, this);
  600.         ]]></body>
  601.       </method>
  602.       
  603.       <method name="rebuildPopup">
  604.         <body><![CDATA[
  605.           var popup = this._popup;
  606.           var yandexSeparator = this.getElementByAnonid("engines-list-separator-yandex");
  607.           var browserSeparator = this.getElementByAnonid("engines-list-separator-browser");
  608.           
  609.           while (yandexSeparator.nextSibling && yandexSeparator.nextSibling != browserSeparator)
  610.             popup.removeChild(yandexSeparator.nextSibling);
  611.           
  612.           const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  613.           
  614.           var engines = this.searchService.getVisibleEngines({});
  615.           
  616.           engines.forEach(function(engine) {
  617.             if (engine.name != "╨»╨╜╨┤╨╡╨║╤ü") {
  618.               var menuitem = document.createElementNS(kXULNS, "menuitem");
  619.               menuitem.setAttribute("label", engine.name);
  620.               menuitem.setAttribute("id", "__" + engine.name);
  621.               menuitem.setAttribute("class", "menuitem-iconic searchbar-engine-menuitem");
  622.               if (engine.iconURI)
  623.                 menuitem.setAttribute("src", engine.iconURI.spec);
  624.               
  625.               popup.insertBefore(menuitem, browserSeparator);
  626.             }
  627.           })
  628.           
  629.           this.checkCurrentEngine();
  630.           
  631.           this._needToBuildPopup = false;
  632.         ]]></body>
  633.       </method>
  634.       
  635.       <method name="openManager">
  636.         <parameter name="aEvent"/>
  637.         <body><![CDATA[
  638.           var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  639.                              .getService(Components.interfaces.nsIWindowMediator);
  640.           
  641.           var window = wm.getMostRecentWindow("Browser:SearchManager");
  642.           if (window)
  643.             window.focus()
  644.           else {
  645.             setTimeout(function () {
  646.               openDialog("chrome://browser/content/search/engineManager.xul",
  647.                          "_blank", "chrome,dialog,modal,centerscreen");
  648.             }, 0);
  649.           }
  650.         ]]></body>
  651.       </method>
  652.       
  653.       <method name="observe">
  654.         <parameter name="aEngine"/>
  655.         <parameter name="aTopic"/>
  656.         <parameter name="aVerb"/>
  657.         <body><![CDATA[
  658.           switch (aTopic) {
  659.             case "browser-search-engine-modified":
  660.               switch (aVerb) {
  661.                 case "engine-removed":
  662.                   this.offerNewEngine(aEngine);
  663.                   break;
  664.                 
  665.                 case "engine-added":
  666.                   this.hideNewEngine(aEngine);
  667.                   break;
  668.                 
  669.                 case "engine-current":
  670.                   this._popup.hidePopup();
  671.                   break;
  672.                 
  673.                 default:
  674.                   break;
  675.               }
  676.               
  677.               this.rebuildPopup();
  678.               
  679.               break;
  680.             
  681.             default:
  682.               break;
  683.           }
  684.         ]]></body>
  685.       </method>
  686.       
  687.       <method name="addSearchHistoryEntry">
  688.         <parameter name="aText"/>
  689.         <body><![CDATA[
  690.           if (!this.nsIYa.prefs.searchHistoryEnabled)
  691.             return;
  692.           
  693.           var textBox = this._textbox,
  694.               textValue = arguments.length ? aText : textBox.value;
  695.           
  696.           if (textValue)
  697.             textBox._formHistSvc.addEntry(textBox.getAttribute("autocompletesearchparam"), textValue);
  698.         ]]></body>
  699.       </method>
  700.       
  701.       <method name="offerNewEngine">
  702.         <parameter name="aEngine"/>
  703.         <body><![CDATA[
  704.           if (!BrowserSearch || BrowserSearch.searchBar)
  705.             return;
  706.           
  707.           var allbrowsers = getBrowser().mPanelContainer.childNodes;
  708.           for (var tab = 0; tab < allbrowsers.length; tab++) {
  709.             var browser = getBrowser().getBrowserAtIndex(tab);
  710.             if (browser.hiddenEngines) {
  711.               var removeTitle = aEngine.wrappedJSObject.name;
  712.               for (var i = 0; i < browser.hiddenEngines.length; i++) {
  713.                 if (browser.hiddenEngines[i].title == removeTitle) {
  714.                   if (!browser.engines)
  715.                     browser.engines = [];
  716.                   browser.engines.push(browser.hiddenEngines[i]);
  717.                   browser.hiddenEngines.splice(i, 1);
  718.                   break;
  719.                 }
  720.               }
  721.             }
  722.           }
  723.         ]]></body>
  724.       </method>
  725.       
  726.       <method name="hideNewEngine">
  727.         <parameter name="aEngine"/>
  728.         <body><![CDATA[
  729.           if (!BrowserSearch || BrowserSearch.searchBar)
  730.             return;
  731.           
  732.           var allbrowsers = getBrowser().mPanelContainer.childNodes;
  733.           for (var tab = 0; tab < allbrowsers.length; tab++) {
  734.             var browser = getBrowser().getBrowserAtIndex(tab);
  735.             if (browser.engines) {
  736.               var removeTitle = aEngine.wrappedJSObject.name;
  737.               for (var i = 0; i < browser.engines.length; i++) {
  738.                 if (browser.engines[i].title == removeTitle) {
  739.                   if (!browser.hiddenEngines)
  740.                     browser.hiddenEngines = [];
  741.                   browser.hiddenEngines.push(browser.engines[i]);
  742.                   browser.engines.splice(i, 1);
  743.                   break;
  744.                 }
  745.               }
  746.             }
  747.           }
  748.         ]]></body>
  749.       </method>
  750.       
  751.       <method name="handleSearchCommand">
  752.         <parameter name="aEvent"/>
  753.         <body><![CDATA[
  754.           var textBox = this._textbox,
  755.               textValue = textBox.value;
  756.           
  757.           if (textValue.replace(/\s/g, "")) {
  758.             this.addSearchHistoryEntry(textValue);
  759.             
  760.             var searchHost = this.searchableHost;
  761.             searchHost = searchHost && this._acompletepopup.isSiteSearchChecked ? searchHost : false;
  762.             
  763.             var searchUrl = this.nsIYa.getSearchEngineUrl(this.currentEngine, textValue, searchHost);
  764.             if (searchUrl) {
  765.               if (aEvent && aEvent.altKey)
  766.                 aEvent = "tab";
  767.               
  768.               this._textbox.inputField.blur();
  769.               
  770.               if (/^http:\/\/slovari\.yandex\.ru/.test(searchUrl.url))
  771.                 this.nsIYa.getSearchSettingsForSlovari(textValue, aEvent, this.doSearch);
  772.               else
  773.                 this.doSearch(searchUrl.url, aEvent, searchUrl.statData, searchUrl.postData);
  774.             }
  775.           }
  776.         ]]></body>
  777.       </method>
  778.  
  779.       <method name="doSearch">
  780.         <parameter name="aURL"/>
  781.         <parameter name="aEvent"/>
  782.         <parameter name="aStatData"/>
  783.         <parameter name="aPostData"/>
  784.         <body><![CDATA[
  785.           Ya.loadURI(aURL, aEvent, aStatData || null, aPostData || null);
  786.         ]]></body>
  787.       </method>
  788.     </implementation>
  789.     
  790.     <handlers>
  791.       <handler event="click" button="0" phase="capturing"><![CDATA[
  792.         if (event.originalTarget.localName == "div") {
  793.           setTimeout(function(aTextbox) {
  794.             if (!aTextbox.popup.mPopupOpen)
  795.               aTextbox.openPopup();
  796.           }, 0, this._textbox)
  797.         }
  798.       ]]></handler>
  799.       
  800.       <handler event="input"><![CDATA[
  801.         this._userTextInput = !(this.value == "");
  802.         
  803.         var tabData = this.getYaTabHandlerData();
  804.         if (tabData) {
  805.           tabData.searchbox.userTextInput = this._userTextInput;
  806.           tabData.searchbox.inputValue = this.value;
  807.           
  808.           if (tabData.highlighter.serpText)
  809.             tabData.highlighter.serpText = this.value;
  810.           
  811.           this._highlighter.refreshHighlight(gBrowser.mCurrentBrowser);
  812.         }
  813.       ]]></handler>
  814.       
  815.       <handler event="command"><![CDATA[
  816.         const target = event.originalTarget;
  817.         
  818.         if (target.getAttribute("class").indexOf("addengine-item") != -1) {
  819.           var type = Components.interfaces.nsISearchEngine.DATA_XML;
  820.           this.searchService.addEngine(target.getAttribute("uri"), type,
  821.                                        target.getAttribute("src"), false);
  822.         } else if (target.getAttribute("class").indexOf("searchbar-engine-menuitem") != -1) {
  823.           this.currentEngine = target.id;
  824.         } else {
  825.           return;
  826.         }
  827.         
  828.         this.focus();
  829.         this.select();
  830.       ]]></handler>
  831.       
  832.       <handler event="popupshowing"><![CDATA[
  833.         var popup = event.originalTarget;
  834.         popup.yaPopupIsOpen = true;
  835.         
  836.         if (popup == this._popup)
  837.           this.rebuildPopupOnShowing(event);
  838.       ]]></handler>
  839.       
  840.       <handler event="popuphiding"><![CDATA[
  841.         setTimeout(function(popup, me) {
  842.           popup.yaPopupIsOpen = false;
  843.           
  844.           if (popup == me._popup || popup == me._textbox._contextmenu)
  845.             me._textbox.focus();
  846.         
  847.         }, 0, event.originalTarget, this);
  848.       ]]></handler>
  849.       
  850.       <handler event="DOMMouseScroll"
  851.                phase="capturing"
  852.                action="if (event.ctrlKey) this.selectEngine(null, event, (event.detail > 0));"/>
  853.       
  854.       <handler event="mouseover" phase="capturing">
  855.         <![CDATA[
  856.           var target = event.originalTarget;
  857.           if (this.__bugCurrentPopup && target.localName == "menuitem") {
  858.             if (target.parentNode != this.__bugCurrentPopup) {
  859.               this.__bugCurrentPopup.hidePopup();
  860.             }
  861.             
  862.             delete this.__bugCurrentPopup;
  863.           }
  864.         ]]>
  865.       </handler>
  866.     </handlers>
  867.   </binding>
  868.   
  869.   <binding id="searchbox-search-button"
  870.            extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
  871.     <implementation>
  872.       <field name="_xulSearchbox">document.getBindingParent(this)</field>
  873.       
  874.       <constructor><![CDATA[
  875.         if (this._xulSearchbox.hasAttribute("yaSButtonDisabled"))
  876.           this.setAttribute("hidden", this._xulSearchbox.getAttribute("yaSButtonDisabled"));
  877.       ]]></constructor>
  878.       
  879.       <property name="hidden">
  880.         <getter><![CDATA[
  881.           return this.getAttribute("hidden") == "true";
  882.         ]]></getter>
  883.         <setter><![CDATA[
  884.           this.setAttribute("hidden", !!val);
  885.           this._xulSearchbox.setAttribute("yaSButtonDisabled", !!val);
  886.         ]]></setter>
  887.       </property>
  888.     </implementation>
  889.     
  890.     <handlers>
  891.       <handler event="click" button="1"><![CDATA[
  892.         this._xulSearchbox.handleSearchCommand(event);
  893.       ]]></handler>
  894.     </handlers>
  895.   </binding>
  896.   
  897.   <binding id="searchbox-textbox"
  898.            extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
  899.     <implementation implements="nsIAutoCompleteInput, nsIObserver, nsIDOMEventListener">
  900.       <constructor><![CDATA[
  901.         if (!document.getBindingParent(this)._isCanInit)
  902.           return;
  903.         
  904.         setTimeout(function(me) {
  905.           if (me && "init" in me)
  906.             me.init();
  907.         }, 0, this);
  908.       ]]></constructor>
  909.       
  910.       <destructor><![CDATA[
  911.         try {
  912.           gBrowser.tabContainer.removeEventListener("TabSelect", this, false);
  913.         } catch(e) {}
  914.         
  915.         try {
  916.           this.controllers.removeController(this.yasearchbarController);
  917.         } catch(e) {}
  918.         
  919.         delete this.handleEvent;
  920.       ]]></destructor>
  921.  
  922.       <field name="_formHistSvc"/>
  923.       <field name="_contextmenu"/>
  924.       <field name="_lastTabSelectedTime">0</field>
  925.       
  926.       <method name="init">
  927.         <body><![CDATA[
  928.           this._formHistSvc = Components.classes["@mozilla.org/satchel/form-history;1"]
  929.                                         .getService(Components.interfaces.nsIFormHistory2);
  930.           
  931.           var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
  932.                                      .getService(Components.interfaces.nsIPrefBranch);
  933.           
  934.           if (prefBranch.getBoolPref("browser.urlbar.clickSelectsAll"))
  935.             this.setAttribute("clickSelectsAll", true);
  936.           
  937.           var stringBundle = document.getBindingParent(this)._stringBundle;
  938.           
  939.           var textbox = document.getAnonymousElementByAttribute(this, "anonid", "textbox-input-box");
  940.           var contextMenu = document.getAnonymousElementByAttribute(textbox, "anonid", "input-box-contextmenu");
  941.           
  942.           this._contextmenu = contextMenu;
  943.           
  944.           const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  945.           
  946.           var element = document.createElementNS(XULNS, "menuseparator");
  947.           contextMenu.appendChild(element);
  948.           
  949.           element = document.createElementNS(XULNS, "menuitem");
  950.           element.setAttribute("cmd", "cmd_clearhistory");
  951.           element.setAttribute("label", stringBundle.getString("cmd_clearHistory"));
  952.           element.setAttribute("accesskey", stringBundle.getString("cmd_clearHistory_accesskey"));
  953.           
  954.           contextMenu.appendChild(element);
  955.           
  956.           element = document.createElementNS(XULNS, "menuitem");
  957.           element.setAttribute("cmd", "cmd_showsearchbutton");
  958.           element.setAttribute("type", "checkbox");
  959.           element.setAttribute("label", stringBundle.getString("cmd_showSearchButton"));
  960.           element.setAttribute("accesskey", stringBundle.getString("cmd_showSearchButton_accesskey"));
  961.           
  962.           contextMenu.appendChild(element);
  963.           
  964.           this.controllers.appendController(this.yasearchbarController);
  965.           
  966.           this.handleEvent = this.handleEvent;
  967.           
  968.           var _gBrowser = document.getElementById("content");
  969.           if (_gBrowser && _gBrowser.tabContainer)
  970.             _gBrowser.tabContainer.addEventListener("TabSelect", this, false);
  971.         ]]></body>
  972.       </method>
  973.       
  974.       <method name="handleEvent">
  975.         <parameter name="aEvent"/>
  976.         <body><![CDATA[
  977.           switch (aEvent.type) {
  978.             case "TabSelect":
  979.               this.lastTabSelectedTime = true;
  980.               break;
  981.             
  982.             default:
  983.               break;
  984.           }
  985.         ]]></body>
  986.       </method>
  987.       
  988.       <property name="lastTabSelectedTime">
  989.         <getter><![CDATA[
  990.           var res = false;
  991.           
  992.           if (this._lastTabSelectedTime) {
  993.             res = (Date.now() - this._lastTabSelectedTime) < 10;
  994.             this._lastTabSelectedTime = 0;
  995.           }
  996.           
  997.           return res;
  998.         ]]></getter>
  999.         
  1000.         <setter><![CDATA[
  1001.           this._lastTabSelectedTime = val ? Date.now() : 0;
  1002.         ]]></setter>
  1003.       </property>
  1004.       
  1005.       <method name="closePopup">
  1006.         <body><![CDATA[
  1007.           var popup = this.popup;
  1008.           if (popup.mPopupOpen) {
  1009.             popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
  1010.             popup.invalidate();
  1011.             
  1012.             var searchbox = document.getBindingParent(this);
  1013.             
  1014.             var searchSiteEnabled = searchbox._currentEngine &&
  1015.                                     searchbox._currentEngine.searchSite &&
  1016.                                     searchbox.nsIYa.prefs.showSiteSearch;
  1017.             
  1018.             if (this.mController.matchCount == 0 && !searchSiteEnabled)
  1019.               this.realClosePopup();
  1020.           }
  1021.         ]]></body>
  1022.       </method>
  1023.       
  1024.       <method name="realClosePopup">
  1025.         <body><![CDATA[
  1026.           var popup = this.popup;
  1027.           if (popup.mPopupOpen) {
  1028.             popup.hidePopup();
  1029.             document.popupNode = null;
  1030.           }
  1031.         ]]></body>
  1032.       </method>
  1033.       
  1034.       <method name="openPopup">
  1035.         <body><![CDATA[
  1036.           var popup = this.popup;
  1037.           
  1038.           if (popup.mPopupOpen) {
  1039.             popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
  1040.             popup.invalidate();
  1041.           } else {
  1042.             popup.hidden = false;
  1043.             
  1044.             popup.mInput = this;
  1045.             popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
  1046.             popup.invalidate();
  1047.             
  1048.             popup.showCommentColumn = this.showCommentColumn;
  1049.             popup.showImageColumn = this.showImageColumn;
  1050.             
  1051.             document.popupNode = null;
  1052.             
  1053.             var x = this.boxObject.screenX;
  1054.             var y = this.boxObject.screenY + this.boxObject.height;
  1055.             
  1056.             popup.showPopup(document.documentElement, x, y, "popup", null, null);
  1057.           }
  1058.         ]]></body>
  1059.       </method>
  1060.       
  1061.       <method name="onSearchComplete">
  1062.         <body><![CDATA[
  1063.           var searchbox = document.getBindingParent(this);
  1064.           
  1065.           var searchSiteEnabled = searchbox._currentEngine &&
  1066.                                   searchbox._currentEngine.searchSite &&
  1067.                                   searchbox.nsIYa.prefs.showSiteSearch;
  1068.           
  1069.           if (this.mController.matchCount == 0) {
  1070.             if (searchSiteEnabled) {
  1071.               this.openPopup();
  1072.             } else {
  1073.               this.realClosePopup();
  1074.             }
  1075.           }
  1076.         ]]></body>
  1077.       </method>
  1078.       
  1079.       <method name="openSearch">
  1080.         <body>
  1081.           <![CDATA[
  1082.             this.realClosePopup();
  1083.             
  1084.             document.getBindingParent(this)._engineButton.open = true;
  1085.             return false;
  1086.           ]]>
  1087.         </body>
  1088.       </method>
  1089.       
  1090.       <!-- overload |onTextEntered| in autocomplete.xml -->
  1091.       <method name="onTextEntered">
  1092.         <parameter name="aEvent"/>
  1093.         <body><![CDATA[
  1094.           var evt = aEvent || this.mEnterEvent;
  1095.           document.getBindingParent(this).handleSearchCommand(evt);
  1096.           this.mEnterEvent = null;
  1097.           this.realClosePopup();
  1098.         ]]></body>
  1099.       </method>
  1100.       
  1101.       <!-- nsIController -->
  1102.       <field name="yasearchbarController" readonly="true">
  1103.         <![CDATA[({
  1104.         _self: this,
  1105.         
  1106.         supportsCommand: function(aCommand) {
  1107.           return aCommand === "cmd_clearhistory" ||
  1108.                  aCommand === "cmd_showsearchbutton";
  1109.         },
  1110.         
  1111.         isCommandEnabled: function(aCommand) {
  1112.           switch (aCommand) {
  1113.             case "cmd_clearhistory":
  1114.               let param = this._self.getAttribute("autocompletesearchparam");
  1115.               return this._self._formHistSvc.nameExists(param);
  1116.               
  1117.             case "cmd_showsearchbutton":
  1118.               let textbox = document.getAnonymousElementByAttribute(this._self, "anonid", "textbox-input-box");
  1119.               let contextMenu = document.getAnonymousElementByAttribute(textbox, "anonid", "input-box-contextmenu");
  1120.               let contextMenuItem = contextMenu.getElementsByAttribute("cmd", aCommand)[0];
  1121.               
  1122.               let searchButton = document.getBindingParent(this._self)._searchButton;
  1123.               contextMenuItem.setAttribute("checked", !searchButton.hidden);
  1124.               break;
  1125.           }
  1126.           
  1127.           return true;
  1128.         },
  1129.         
  1130.         doCommand: function (aCommand) {
  1131.           switch (aCommand) {
  1132.             case "cmd_showsearchbutton":
  1133.               let parent = document.getBindingParent(this._self);
  1134.               let searchButton = parent._searchButton;
  1135.               searchButton.hidden = !searchButton.hidden;
  1136.               parent.updateCursorVisibility();
  1137.               break;
  1138.             
  1139.             case "cmd_clearhistory":
  1140.               let param = this._self.getAttribute("autocompletesearchparam");
  1141.               this._self._formHistSvc.removeEntriesForName(param);
  1142.               break;
  1143.           }
  1144.         }
  1145.       })]]>
  1146.       </field>
  1147.  
  1148.       <!-- DND Observer -->
  1149.       <field name="yasearchbarDNDObserver" readonly="true">
  1150.         <![CDATA[({
  1151.         mOuter: this,
  1152.         
  1153.         onDrop: function (aEvent, aXferData, aDragSession) {
  1154.           var data = transferUtils.retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);
  1155.           if (data) {
  1156.             this.mOuter.value = data;
  1157.             this.mOuter.onTextEntered(aEvent);
  1158.           }
  1159.         },
  1160.         
  1161.         getSupportedFlavours: function () {
  1162.           var flavourSet = new FlavourSet();
  1163.  
  1164.           flavourSet.appendFlavour("text/unicode");
  1165.           flavourSet.appendFlavour("text/x-moz-url");
  1166.           flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  1167.           return flavourSet;
  1168.         }
  1169.       })]]>
  1170.       </field>
  1171.     </implementation>
  1172.     
  1173.     <handlers>
  1174.       <handler event="focus" phase="capturing">
  1175.         <![CDATA[
  1176.           if (event.originalTarget.localName == "input" &&
  1177.               !this.popup.mPopupOpen &&
  1178.               !document.getBindingParent(this)._popup.yaPopupIsOpen &&
  1179.               !this._contextmenu.yaPopupIsOpen &&
  1180.               !this.lastTabSelectedTime)
  1181.           {
  1182.             if (this.value) {
  1183.               setTimeout(function(me) {
  1184.                 me.mConsumeRollupEvent = true;
  1185.                 me.attachController();
  1186.                 me.mController.startSearch(me.value);
  1187.               }, 0, this)
  1188.             } else {
  1189.               this.onSearchComplete();
  1190.             }
  1191.           }
  1192.         ]]>
  1193.       </handler>
  1194.       
  1195.       <handler event="blur" phase="capturing">
  1196.         <![CDATA[
  1197.           if (this.popup.mPopupOpen)
  1198.             this.realClosePopup();
  1199.           
  1200.           document.commandDispatcher.focusedElement = null;
  1201.         ]]>
  1202.       </handler>
  1203.       
  1204.       <handler event="keypress" keycode="VK_UP" modifiers="accel"
  1205.                phase="capturing"
  1206.                action="document.getBindingParent(this).selectEngine(null, event, false);"/>
  1207.       
  1208.       <handler event="keypress" keycode="VK_DOWN" modifiers="accel"
  1209.                phase="capturing"
  1210.                action="document.getBindingParent(this).selectEngine(null, event, true);"/>
  1211.       
  1212.       <handler event="keypress" keycode="VK_DOWN" modifiers="alt"
  1213.                phase="capturing"
  1214.                action="return this.openSearch();"/>
  1215.       
  1216.       <handler event="keypress" keycode="VK_UP" modifiers="alt"
  1217.                phase="capturing"
  1218.                action="return this.openSearch();"/>
  1219.       
  1220.       <handler event="keypress" keycode="VK_F4"
  1221.                phase="capturing"
  1222.                action="return this.openSearch();"/>
  1223.       
  1224.       <handler event="dragdrop" phase="capturing">
  1225.         nsDragAndDrop.drop(event, this.yasearchbarDNDObserver);
  1226.       </handler>
  1227.       
  1228.       <handler event="keypress" phase="capturing">
  1229.         <![CDATA[
  1230.           if (event.keyCode === event.DOM_VK_TAB &&
  1231.               this.popup.mPopupOpen &&
  1232.               this.popup.isEmptyResultList) {
  1233.             this.realClosePopup();
  1234.           }
  1235.         ]]>
  1236.       </handler>
  1237.     </handlers>
  1238.   </binding>
  1239.   
  1240.   <binding id="searchbox-popup-autocomplete"
  1241.            extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup">
  1242.     <resources>
  1243.       <stylesheet src="chrome://global/skin/tree.css"/>
  1244.       <stylesheet src="chrome://global/skin/autocomplete.css"/>
  1245.       <stylesheet src="chrome://yasearch/skin/searchbox/popup-autocomplete.css"/>
  1246.     </resources>
  1247.  
  1248.     <content ignorekeys="true">
  1249.       <xul:tree anonid="tree" class="autocomplete-tree plain" flex="1"
  1250.                 hidescrollbar="true" hidecolumnpicker="true" seltype="single"
  1251.                 xbl:inherits="width=yaSHistoryWidth,height=yaSHistoryHeight,collapsed=yaEmptyResultList">
  1252.         <xul:treecols anonid="treecols">
  1253.           <xul:treecol id="treecolAutoCompleteValue" class="autocomplete-treecol" flex="2" overflow="true"/>
  1254.         </xul:treecols>
  1255.         <xul:treechildren class="autocomplete-treebody"/>
  1256.       </xul:tree>
  1257.       
  1258.       <xul:hbox anonid="popup-appendix" onmousedown="return false">
  1259.         <xul:vbox flex="1">
  1260.           <xul:hbox>
  1261.             <xul:checkbox anonid="site-search-checkbox" label="&yasearchox.checkbox.site.label;"/>
  1262.           </xul:hbox>
  1263.         </xul:vbox>
  1264.         
  1265.         <xul:vbox pack="end">
  1266.           <xul:image anonid="popup-resizer"/>
  1267.         </xul:vbox>
  1268.       </xul:hbox>
  1269.     </content>
  1270.     
  1271.     <implementation>
  1272.       <property name="isEmptyResultList"
  1273.                 readonly="true"
  1274.                 onget="return this.getAttribute('yaEmptyResultList') == 'true';"/>
  1275.       
  1276.       <method name="adjustHeight">
  1277.         <body><![CDATA[
  1278.           var bx = this.tree.treeBoxObject;
  1279.           var view = this.tree.view;
  1280.           if (!view)
  1281.             return;
  1282.           
  1283.           var height = view.rowCount * bx.rowHeight;
  1284.           
  1285.           if (height == 0) {
  1286.             this.setAttribute("yaEmptyResultList", "true");
  1287.           } else {
  1288.             if (this.hasAttribute("yaEmptyResultList"))
  1289.               this.removeAttribute("yaEmptyResultList");
  1290.           }
  1291.           
  1292.           this.tree.setAttribute("hidescrollbar", height <= bx.height);
  1293.         ]]></body>
  1294.       </method>
  1295.       
  1296.       <field name="_searchbox">document.getBindingParent(this)</field>
  1297.       <field name="_siteSearchCheckbox">document.getAnonymousElementByAttribute(this, "anonid", "site-search-checkbox")</field>
  1298.       
  1299.       <method name="resizeTo">
  1300.         <parameter name="aSizeObject"/>
  1301.         <body><![CDATA[
  1302.           this._searchbox.setAttribute("yaSHistoryWidth", aSizeObject.width);
  1303.           
  1304.           if (!this.isEmptyResultList)
  1305.             this._searchbox.setAttribute("yaSHistoryHeight", aSizeObject.height);
  1306.           
  1307.           this.adjustHeight();
  1308.         ]]></body>
  1309.       </method>
  1310.       
  1311.       <property name="isSiteSearchChecked"
  1312.                 readonly="true"
  1313.                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'site-search-checkbox').checked;"/>
  1314.       
  1315.       <method name="updateAppendix">
  1316.         <body><![CDATA[
  1317.           var searchbox = this._searchbox;
  1318.           
  1319.           var enabled = !!(searchbox._currentEngine &&
  1320.                            searchbox._currentEngine.searchSite &&
  1321.                            searchbox.nsIYa.prefs.showSiteSearch);
  1322.           
  1323.           var curEnabled = this.hasAttribute("yaSiteSearchEnabled");
  1324.           
  1325.           if (enabled != curEnabled) {
  1326.             if (enabled) {
  1327.               this.setAttribute("yaSiteSearchEnabled", "true");
  1328.             } else {
  1329.               this.removeAttribute("yaSiteSearchEnabled");
  1330.             }
  1331.           }
  1332.         ]]></body>
  1333.       </method>
  1334.       
  1335.       <method name="invalidate">
  1336.         <parameter name="aScope"/>
  1337.         <body><![CDATA[
  1338.           var me = aScope || this;
  1339.           
  1340.           me.updateAppendix();
  1341.           me.adjustHeight();
  1342.           me.tree.treeBoxObject.invalidate();
  1343.         ]]></body>
  1344.       </method>
  1345.       
  1346.       <method name="checkNeedRefreshOnEngineChanged">
  1347.         <body><![CDATA[
  1348.           let textbox = this._searchbox._textbox,
  1349.               searchController = textbox.mController;
  1350.           
  1351.           if (searchController) {
  1352.             if (searchController.input)
  1353.               textbox.onSearchComplete();
  1354.             
  1355.             if (textbox.value)
  1356.               searchController.startSearch(textbox.value);
  1357.           }
  1358.         ]]></body>
  1359.       </method>
  1360.     </implementation>
  1361.     
  1362.     <handlers>
  1363.       <handler event="popupshowing"><![CDATA[
  1364.         this.mPopupOpen = true;
  1365.         this.updateAppendix();
  1366.       ]]></handler>
  1367.       
  1368.       <handler event="popuphiding"><![CDATA[
  1369.         this.mPopupOpen = false;
  1370.         
  1371.         this.selectedIndex = -1;
  1372.       ]]></handler>
  1373.     </handlers>
  1374.   </binding>
  1375.   
  1376.   <binding id="searchbox-popup-autocomplete-resizer"
  1377.            extends="chrome://global/content/bindings/general.xml#image">
  1378.     <implementation implements="nsIDOMEventListener">
  1379.       <field name="_selectedIndexBeforeResize">-1</field>
  1380.       
  1381.       <field name="dragging">false</field>
  1382.       
  1383.       <constructor><![CDATA[
  1384.         this.addEventListener("mousedown", this, true);
  1385.       ]]></constructor>
  1386.       
  1387.       <destructor><![CDATA[
  1388.         this.removeEventListener("mousedown", this, true);
  1389.       ]]></destructor>
  1390.       
  1391.       <field name="popupNode">document.getBindingParent(this)</field>
  1392.       
  1393.       <field name="mLastResizerMoveTime">Date.now()</field>
  1394.       
  1395.       <property name="popupTreeSize">
  1396.         <getter><![CDATA[
  1397.           var treeBox = this.popupNode.tree.boxObject;
  1398.           return treeBox && treeBox.width ?
  1399.                     { width: treeBox.width, height: treeBox.height } :
  1400.                     { width: this.popupNode.boxObject.width, height: 0 }
  1401.         ]]></getter>
  1402.       </property>
  1403.       
  1404.       <method name="onResizerMouseDown">
  1405.         <parameter name="aEvent"/>
  1406.         <body><![CDATA[
  1407.           this.dragging = true;
  1408.           
  1409.           this.lastX = aEvent.screenX;
  1410.           this.lastY = aEvent.screenY;
  1411.           
  1412.           window.addEventListener("mouseup", this, true);
  1413.           window.addEventListener("mousemove", this, true);
  1414.           
  1415.           this._selectedIndexBeforeResize = this.popupNode.selectedIndex;
  1416.           
  1417.           return false;
  1418.         ]]></body>
  1419.       </method>
  1420.       
  1421.       <method name="onWindowMouseMove">
  1422.         <parameter name="aEvent"/>
  1423.         <body><![CDATA[
  1424.           if (!this.dragging || (Date.now() - this.mLastResizerMoveTime < 60))
  1425.             return;
  1426.           
  1427.           var diffX = aEvent.screenX - this.lastX;
  1428.           var diffY = aEvent.screenY - this.lastY;
  1429.           
  1430.           if (!(diffX || diffY))
  1431.             return;
  1432.           
  1433.           this.lastX = aEvent.screenX;
  1434.           this.lastY = aEvent.screenY;
  1435.           
  1436.           this.mLastResizerMoveTime = Date.now();
  1437.           
  1438.           var curSize = this.popupTreeSize;
  1439.           
  1440.           curSize.width += diffX;
  1441.           curSize.height += diffY;
  1442.           
  1443.           this.popupNode.selectedIndex = -1;
  1444.           
  1445.           this.popupNode.resizeTo(curSize);
  1446.         ]]></body>
  1447.       </method>
  1448.       
  1449.       <method name="onWindowMouseUp">
  1450.         <parameter name="aEvent"/>
  1451.         <body><![CDATA[
  1452.           if (!this.dragging)
  1453.             return;
  1454.           
  1455.           window.removeEventListener("mouseup", this, true);
  1456.           window.removeEventListener("mousemove", this, true);
  1457.           
  1458.           this.popupNode.selectedIndex = this._selectedIndexBeforeResize;
  1459.           this._selectedIndexBeforeResize = -1;
  1460.           
  1461.           this.dragging = false;
  1462.         ]]></body>
  1463.       </method>
  1464.       
  1465.       <method name="handleEvent">
  1466.         <parameter name="aEvent"/>
  1467.         <body><![CDATA[
  1468.           switch (aEvent.type) {
  1469.             case "mousedown":
  1470.               this.onResizerMouseDown(aEvent);
  1471.               break;
  1472.             
  1473.             case "mouseup":
  1474.               this.onWindowMouseUp(aEvent);
  1475.               aEvent.stopPropagation();
  1476.               break;
  1477.             
  1478.             case "mousemove":
  1479.               this.onWindowMouseMove(aEvent);
  1480.               aEvent.stopPropagation();
  1481.               break;
  1482.           }
  1483.         ]]></body>
  1484.       </method>
  1485.     </implementation>
  1486.   </binding>
  1487.   
  1488.   <binding id="searchbox-highlighter"
  1489.            extends="chrome://yasearch/content/searchbox/searchbox.xml#searchbox-base">
  1490.     <content>
  1491.       <xul:toolbarbutton anonid="menu-button" type="menu-button"
  1492.                          tooltiptext="&yasearchbox.highlighter.tooltiptext;">
  1493.         <xul:menupopup>
  1494.           <xul:menuitem anonid="highlight" type="checkbox"
  1495.                         label="&yasearchbox.highlighter.highlight.label;"/>
  1496.           <xul:menuseparator/>
  1497.           <xul:menuitem anonid="teleport" type="checkbox"
  1498.                         label="&yasearchbox.highlighter.teleport.label;"/>
  1499.           <xul:menuitem anonid="serp" type="checkbox"
  1500.                         label="&yasearchbox.highlighter.serp.label;"/>
  1501.         </xul:menupopup>
  1502.       </xul:toolbarbutton>
  1503.     </content>
  1504.     
  1505.     <implementation implements="nsIObserver">
  1506.       <field name="mPrefsNamePrefix">"yasearch.general.ui.highlighter."</field>
  1507.       
  1508.       <field name="_prefBranch">Components.classes["@mozilla.org/preferences-service;1"]
  1509.                                           .getService(Components.interfaces.nsIPrefBranch2)</field>
  1510.       
  1511.       <field name="_button">document.getAnonymousElementByAttribute(this, "anonid", "menu-button")</field>
  1512.       <field name="_searchbox">document.getBindingParent(this)</field>
  1513.       
  1514.       <field name="mHighlightNodeClassName">"__yasearchhighlighterclass" + Date.now()</field>
  1515.       <field name="mHighBackColor">"yellow"</field>
  1516.       <field name="mHighTextColor">"black"</field>
  1517.       
  1518.       <field name="mMaxHighlightCount">100</field>
  1519.       
  1520.       <field name="_isInited">false</field>
  1521.       
  1522.       <property name="enabled">
  1523.         <getter><![CDATA[
  1524.           return this.getAttribute("hidden") != "true";
  1525.         ]]></getter>
  1526.         <setter><![CDATA[
  1527.           this.setAttribute("hidden", !val);
  1528.           
  1529.           val ? this.init() : this.destroy();
  1530.           
  1531.           return this.enabled;
  1532.         ]]></setter>
  1533.       </property>
  1534.       
  1535.       <method name="getElement">
  1536.         <parameter name="aAnonymousID"/>
  1537.         <body><![CDATA[
  1538.           return document.getAnonymousElementByAttribute(this, "anonid", aAnonymousID);
  1539.         ]]></body>
  1540.       </method>
  1541.       
  1542.       <field name="_refreshHighlightTimeout">null</field>
  1543.       
  1544.       <field name="_smoothScrollInterval">null</field>
  1545.       
  1546.       <method name="setTimeout">
  1547.         <body><![CDATA[
  1548.           var args = Array.slice(arguments);
  1549.           var timeoutName = "_" + args.shift() + "Timeout";
  1550.           
  1551.           if (!(timeoutName in this))
  1552.             return;
  1553.           
  1554.           if (this[timeoutName])
  1555.             window.clearTimeout(this[timeoutName]);
  1556.           
  1557.           if (args.length)
  1558.             this[timeoutName] = window.setTimeout.apply(null, args);
  1559.         ]]></body>
  1560.       </method>
  1561.       
  1562.       <constructor><![CDATA[
  1563.         if (!this._searchbox._isCanInit)
  1564.           return;
  1565.         
  1566.         Components.classes["@mozilla.org/preferences-service;1"]
  1567.                   .getService(Components.interfaces.nsIPrefBranchInternal)
  1568.                   .addObserver(this.mPrefsNamePrefix + "enabled", this, false);
  1569.         
  1570.         this.enabled = this._prefBranch.getBoolPref(this.mPrefsNamePrefix + "enabled");
  1571.       ]]></constructor>
  1572.       
  1573.       <destructor><![CDATA[
  1574.         this.enabled = false;
  1575.         
  1576.         Components.classes["@mozilla.org/preferences-service;1"]
  1577.                   .getService(Components.interfaces.nsIPrefBranchInternal)
  1578.                   .removeObserver(this.mPrefsNamePrefix + "enabled", this, false);
  1579.         
  1580.         this._isInited = false;
  1581.       ]]></destructor>
  1582.       
  1583.       <method name="init">
  1584.         <body><![CDATA[
  1585.           if (this._isInited || !this._searchbox._isCanInit)
  1586.             return;
  1587.           
  1588.           this._highlightEnabled = false;
  1589.           this.mTeleportEnabled = this._prefBranch.getBoolPref(this.mPrefsNamePrefix + "teleport");
  1590.           this.mSerpEnabled = this._prefBranch.getBoolPref(this.mPrefsNamePrefix + "serp");
  1591.  
  1592.           Components.classes["@mozilla.org/preferences-service;1"]
  1593.                     .getService(Components.interfaces.nsIPrefBranchInternal)
  1594.                     .addObserver(this.mPrefsNamePrefix, this, false);
  1595.           
  1596.           YaProgressListener.addListener(this.mLocationListener);
  1597.           
  1598.           this._isInited = true;
  1599.         ]]></body>
  1600.       </method>
  1601.       
  1602.       <method name="destroy">
  1603.         <body><![CDATA[
  1604.           if (!this._isInited)
  1605.             return;
  1606.           
  1607.           YaProgressListener.removeListener(this.mLocationListener);
  1608.  
  1609.           Components.classes["@mozilla.org/preferences-service;1"]
  1610.                     .getService(Components.interfaces.nsIPrefBranchInternal)
  1611.                     .removeObserver(this.mPrefsNamePrefix, this);
  1612.           
  1613.           var l = gBrowser.mPanelContainer.childNodes.length;
  1614.           for (var i = 0; i < l; i++) {
  1615.             try {
  1616.               var browser = gBrowser.getBrowserAtIndex(i);
  1617.               var tabData = this.getYaHLTabHandlerData(browser);
  1618.               if (!tabData)
  1619.                 continue;
  1620.               
  1621.               this._refreshHighlight(browser, tabData, null);
  1622.             } catch(e) {}
  1623.           }
  1624.           
  1625.           this._isInited = false;
  1626.         ]]></body>
  1627.       </method>
  1628.       
  1629.       <method name="getYaHLTabHandlerData">
  1630.         <parameter name="aBrowser"/>
  1631.         <body><![CDATA[
  1632.           return this._searchbox.getYaTabHandlerData(aBrowser).highlighter || null;
  1633.         ]]></body>
  1634.       </method>
  1635.       
  1636.       <property name="mTeleportEnabled">
  1637.         <getter><![CDATA[
  1638.           return this._teleportEnabled;
  1639.         ]]></getter>
  1640.         <setter><![CDATA[
  1641.           var enabled = !!val;
  1642.           
  1643.           if (enabled !== this._teleportEnabled) {
  1644.             this.setAttribute("teleportEnabled", enabled);
  1645.             this._teleportEnabled = enabled;
  1646.           }
  1647.           
  1648.           return this.mTeleportEnabled;
  1649.         ]]></setter>
  1650.       </property>
  1651.       
  1652.       <property name="mSerpEnabled">
  1653.         <getter><![CDATA[
  1654.           return this._serpEnabled;
  1655.         ]]></getter>
  1656.         <setter><![CDATA[
  1657.           var enabled = !!val;
  1658.           
  1659.           if (enabled !== this._serpEnabled) {
  1660.             this._serpEnabled = enabled;
  1661.           }
  1662.           
  1663.           return this.mSerpEnabled;
  1664.         ]]></setter>
  1665.       </property>
  1666.       
  1667.       <property name="mHighlightEnabled">
  1668.         <getter><![CDATA[
  1669.           return this._highlightEnabled;
  1670.         ]]></getter>
  1671.         <setter><![CDATA[
  1672.           var enabled = !!val;
  1673.           
  1674.           var browser = gBrowser.mCurrentBrowser;
  1675.           var tabData = this.getYaHLTabHandlerData(browser);
  1676.           if (tabData) {
  1677.             tabData.enabled = enabled;
  1678.             this.checkHighlightState(browser);
  1679.           }
  1680.           
  1681.           return this.mHighlightEnabled;
  1682.         ]]></setter>
  1683.       </property>
  1684.       
  1685.       <method name="refreshHighlight">
  1686.         <parameter name="aBrowser"/>
  1687.         <body><![CDATA[
  1688.           if (!this._isInited)
  1689.             return;
  1690.           
  1691.           var tabData = this.getYaHLTabHandlerData(aBrowser);
  1692.           if (!tabData)
  1693.             return;
  1694.           
  1695.           var words = "",
  1696.               serpAutoHighlight = false;
  1697.           
  1698.           if (tabData.highlightDone === false && tabData.serpText && this.mSerpEnabled) {
  1699.             words = tabData.serpText;
  1700.             serpAutoHighlight = true;
  1701.           } else {
  1702.             words = tabData.enabled ? this._searchbox.value : "";
  1703.           }
  1704.           
  1705.           words = words.replace(/^\s+/, "")
  1706.                        .replace(/\s+$/, "")
  1707.                        .replace(/\s+/g, " ");
  1708.           
  1709.           var wordsLength = words.length;
  1710.           
  1711.           var refreshTimeout = !wordsLength ? 0 : (wordsLength > 2 ? 0.5 : (wordsLength > 1 ? 1 : 2))
  1712.           
  1713.           this.setTimeout(
  1714.             "refreshHighlight",
  1715.             function(me, aBrowser, tabData, words, serpAutoHighlight) {
  1716.               me._refreshHighlight(aBrowser, tabData, words, serpAutoHighlight);
  1717.             },
  1718.             refreshTimeout * 1000, this, aBrowser, tabData, words, serpAutoHighlight
  1719.           )
  1720.         ]]></body>
  1721.       </method>
  1722.       
  1723.       <method name="_refreshHighlight">
  1724.         <parameter name="aBrowser"/>
  1725.         <parameter name="aTabData"/>
  1726.         <parameter name="words"/>
  1727.         <parameter name="serpAutoHighlight"/>
  1728.         <body><![CDATA[
  1729.           aTabData.highlightDone = true;
  1730.           
  1731.           if (words != aTabData.lastHighlightString) {
  1732.             if (aTabData.lastHighlightString)
  1733.               this.toggleHighlight(null, aBrowser, aTabData);
  1734.             
  1735.             if (words)
  1736.               this.toggleHighlight(words, aBrowser, aTabData, serpAutoHighlight);
  1737.             
  1738.             aTabData.lastHighlightString = words;
  1739.           }
  1740.         ]]></body>
  1741.       </method>
  1742.       
  1743.       <method name="toggleHighlight">
  1744.         <parameter name="aWords"/>
  1745.         <parameter name="aBrowser"/>
  1746.         <parameter name="aTabData"/>
  1747.         <parameter name="aSerpAutoHighlight"/>
  1748.         <body><![CDATA[
  1749.           var contentWindow = aBrowser.contentWindow;
  1750.           
  1751.           if (!contentWindow)
  1752.             return;
  1753.           
  1754.           if (this._smoothScrollInterval)
  1755.             window.clearInterval(this._smoothScrollInterval);
  1756.           
  1757.           aTabData._highlightedCount = 0;
  1758.           
  1759.           if (aWords) {
  1760.             aTabData._windowSizeProps = {
  1761.               scrollX: contentWindow.scrollX,
  1762.               scrollY: contentWindow.scrollY,
  1763.               elemScrollX: contentWindow.scrollX,
  1764.               elemScrollY: contentWindow.scrollY,
  1765.               bottomScrollFound: false
  1766.             }
  1767.             
  1768.             if (this._highlightDoc(aTabData, this.mHighBackColor, this.mHighTextColor, aWords, contentWindow) &&
  1769.                 this.mTeleportEnabled)
  1770.             {
  1771.               window.setTimeout(function(me, aKeyDown, aWindowSizeProps) {
  1772.                 if (!aSerpAutoHighlight || !(aKeyDown || contentWindow.scrollX || contentWindow.scrollY)) {
  1773.                   me.smoothScrollToElement(contentWindow, {
  1774.                     x: aWindowSizeProps.elemScrollX,
  1775.                     y: aWindowSizeProps.elemScrollY
  1776.                   })
  1777.                 }
  1778.               }, 10, this, aTabData.keyDown, aTabData._windowSizeProps);
  1779.             }
  1780.             
  1781.           } else {
  1782.             this._highlightDoc(aTabData, null, null, null, contentWindow);
  1783.             aTabData.lastHighlightString = "";
  1784.           }
  1785.         ]]></body>
  1786.       </method>
  1787.       
  1788.       <method name="_setSearchRange">
  1789.         <parameter name="aDocument"/>
  1790.         <body><![CDATA[
  1791.           let body = aDocument.body;
  1792.           let count = body.childNodes.length;
  1793.           
  1794.           this._searchRange = aDocument.createRange();
  1795.           this._startPt = aDocument.createRange();
  1796.           this._endPt = aDocument.createRange();
  1797.  
  1798.           this._searchRange.setStart(body, 0);
  1799.           this._searchRange.setEnd(body, count);
  1800.  
  1801.           this._startPt.setStart(body, 0);
  1802.           this._startPt.setEnd(body, 0);
  1803.           this._endPt.setStart(body, count);
  1804.           this._endPt.setEnd(body, count);
  1805.         ]]></body>
  1806.       </method>
  1807.       
  1808.       <method name="_highlightDoc">
  1809.         <parameter name="aTabData"/>
  1810.         <parameter name="aHighBackColor"/>
  1811.         <parameter name="aHighTextColor"/>
  1812.         <parameter name="aWord"/>
  1813.         <parameter name="aWindow"/>
  1814.         <body><![CDATA[
  1815.           var win = aWindow;
  1816.           
  1817.           var textFound = false;
  1818.           for (var i = 0; win.frames && i < win.frames.length; i++) {
  1819.             if (this._highlightDoc(aTabData, aHighBackColor, aHighTextColor, aWord, win.frames[i]))
  1820.               textFound = true;
  1821.           }
  1822.           
  1823.           var doc = win.document;
  1824.           if (!doc || !(doc instanceof HTMLDocument))
  1825.             return textFound;
  1826.           
  1827.           var body = doc.body;
  1828.           if (!body)
  1829.             return textFound;
  1830.           
  1831.           if (!aHighBackColor) {
  1832.             if (!aTabData.lastHighlightString)
  1833.               return textFound;
  1834.             
  1835.             if (aTabData.lastHighlightWords) {
  1836.               let hlNodes = YaUtils.evaluateXPath(doc, "//xhtml:yabarhighlightertag[@class='" + this.mHighlightNodeClassName + "']");
  1837.               textFound = !!hlNodes.length;
  1838.               
  1839.               for (let i = hlNodes.length; --i >= 0;) {
  1840.                 let elem = hlNodes[i];
  1841.                 
  1842.                 let child = null;
  1843.                 let docfrag = doc.createDocumentFragment();
  1844.                 let next = elem.nextSibling;
  1845.                 let parent = elem.parentNode;
  1846.                 
  1847.                 while ((child = elem.firstChild))
  1848.                   docfrag.appendChild(child);
  1849.                 
  1850.                 this._startPt = doc.createRange();
  1851.                 this._startPt.setStartAfter(elem);
  1852.                 
  1853.                 parent.removeChild(elem);
  1854.                 parent.insertBefore(docfrag, next);
  1855.                 parent.normalize();
  1856.                 
  1857.                 this._startPt.collapse(true);
  1858.               }
  1859.               
  1860.             }
  1861.             
  1862.             return textFound;
  1863.           }
  1864.           
  1865.           let baseNode = doc.createElementNS("http://www.w3.org/1999/xhtml", "yabarhighlightertag");
  1866.           baseNode.style.backgroundColor = aHighBackColor;
  1867.           baseNode.style.color = aHighTextColor;
  1868.           baseNode.style.display = "inline";
  1869.           baseNode.style.fontSize = "inherit";
  1870.           baseNode.style.padding = "0";
  1871.           baseNode.className = this.mHighlightNodeClassName;
  1872.           
  1873.           let wordRe = YaUtils.RegExp.escape(aWord).replace(/[╨╡╤æ]/ig, "[╨╡╤æ]");
  1874.           wordRe = new RegExp(wordRe, "ig");
  1875.           
  1876.           let matchedWords = body.textContent.match(wordRe);
  1877.           if (matchedWords) {
  1878.             function unique(aArray) {
  1879.               let ret = [];
  1880.               aArray.forEach(function(elem) {
  1881.                 elem = elem.toLowerCase();
  1882.                 if (ret.indexOf(elem) === -1)
  1883.                   ret.push(elem);
  1884.               });
  1885.                   return ret;
  1886.               };
  1887.               
  1888.               matchedWords.unshift(aWord);
  1889.             matchedWords = unique(matchedWords);
  1890.             
  1891.             matchedWords.forEach(function(wrd) {
  1892.               this._setSearchRange(doc);
  1893.               textFound = this._highlightText(aTabData, wrd, baseNode) || textFound;
  1894.             }, this);
  1895.             
  1896.             aTabData.lastHighlightWords = matchedWords;
  1897.             
  1898.           } else {
  1899.             aTabData.lastHighlightWords = null;
  1900.           }
  1901.           
  1902.           return textFound;
  1903.         ]]></body>
  1904.       </method>
  1905.       
  1906.       <method name="_highlightText">
  1907.         <parameter name="aTabData"/>
  1908.         <parameter name="aWord"/>
  1909.         <parameter name="aBaseNode"/>
  1910.         <body><![CDATA[
  1911.           let rangeOwnerDocument = this._searchRange.startContainer.ownerDocument;
  1912.           let body = rangeOwnerDocument.body;
  1913.           
  1914.           let bodyScroll = {
  1915.             top: parseInt(Math.max(rangeOwnerDocument.documentElement.scrollTop, body.scrollTop),10),
  1916.             left: parseInt(Math.max(rangeOwnerDocument.documentElement.scrollLeft, body.scrollLeft),10)
  1917.           };
  1918.           
  1919.           let retRange = null;
  1920.           let finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"]
  1921.                                  .createInstance()
  1922.                                  .QueryInterface(Components.interfaces.nsIFind);
  1923.  
  1924.           finder.caseSensitive = false;
  1925.           
  1926.           let textFound = false;
  1927.           let winSizeProps = aTabData._windowSizeProps;
  1928.           
  1929.           let NBCR = null;
  1930.           
  1931.           while (aTabData._highlightedCount++ < this.mMaxHighlightCount &&
  1932.                  (retRange = finder.Find(aWord, this._searchRange, this._startPt, this._endPt))) {
  1933.             
  1934.             let nodeSurround = aBaseNode.cloneNode(true);
  1935.             let node = this._highlight(retRange, nodeSurround);
  1936.             
  1937.             if (!node) {
  1938.               if (--aTabData._highlightedCount < 0)
  1939.                 aTabData._highlightedCount = 0;
  1940.               
  1941.               this._startPt = retRange.endContainer.ownerDocument.createRange();
  1942.               this._startPt.setStart(retRange.endContainer, retRange.endOffset);
  1943.               this._startPt.setEnd(retRange.endContainer, retRange.endOffset);
  1944.             
  1945.             } else {
  1946.               let childNodesLength = node.childNodes.length;
  1947.               
  1948.               this._startPt = node.ownerDocument.createRange();
  1949.               this._startPt.setStart(node, childNodesLength);
  1950.               this._startPt.setEnd(node, childNodesLength);
  1951.               
  1952.               let nodeBCR = node.getBoundingClientRect();
  1953.               let nodeScrollY = parseInt(nodeBCR.top,10) + bodyScroll.top;
  1954.               
  1955.               if (aTabData._highlightedCount == 1) {
  1956.                 winSizeProps.elemScrollY = nodeScrollY;
  1957.                 NBCR = nodeBCR;
  1958.               }
  1959.               
  1960.               if (!winSizeProps.bottomScrollFound) {
  1961.                 if (nodeScrollY >= winSizeProps.scrollY || nodeScrollY < winSizeProps.elemScrollY) {
  1962.                   if (nodeScrollY >= winSizeProps.scrollY) {
  1963.                     winSizeProps.bottomScrollFound = true;
  1964.                   }
  1965.                   
  1966.                   winSizeProps.elemScrollY = nodeScrollY;
  1967.                   NBCR = nodeBCR;
  1968.                 }
  1969.               }
  1970.               
  1971.               if (winSizeProps.bottomScrollFound &&
  1972.                   nodeScrollY >= winSizeProps.scrollY &&
  1973.                   nodeScrollY <= winSizeProps.elemScrollY)
  1974.               {
  1975.                 winSizeProps.elemScrollY = nodeScrollY;
  1976.                 NBCR = nodeBCR;
  1977.               }
  1978.               
  1979.               textFound = true;
  1980.             }
  1981.           }
  1982.           
  1983.           if (NBCR) {
  1984.             let nodeBO = {
  1985.               left: parseInt(NBCR.left,10),
  1986.               right: parseInt(NBCR.right,10)
  1987.             };
  1988.             
  1989.             if (nodeBO.left <= 0) {
  1990.               winSizeProps.elemScrollX = nodeBO.left + bodyScroll.left;
  1991.             } else {
  1992.               let clientWidth = parseInt(Math.max(rangeOwnerDocument.documentElement.clientWidth, body.clientWidth),10);
  1993.               if (nodeBO.right > clientWidth) {
  1994.                 winSizeProps.elemScrollX = Math.min(nodeBO.left, nodeBO.right - clientWidth) + bodyScroll.left;
  1995.               }
  1996.             }
  1997.           }
  1998.           
  1999.           aTabData.lastHighlightString = aWord;
  2000.           
  2001.           return textFound;
  2002.         ]]></body>
  2003.       </method>
  2004.       
  2005.       <method name="_getEditableNode">
  2006.         <parameter name="aNode"/>
  2007.         <body><![CDATA[
  2008.           while (aNode) {
  2009.             if (aNode instanceof Components.interfaces.nsIDOMNSEditableElement)
  2010.               return aNode.editor ? aNode : null;
  2011.             
  2012.             aNode = aNode.parentNode;
  2013.           }
  2014.           
  2015.           return null;           
  2016.         ]]></body>
  2017.       </method>
  2018.       
  2019.       <method name="_highlight">
  2020.         <parameter name="aRange"/>
  2021.         <parameter name="aNode"/>
  2022.         <body><![CDATA[
  2023.           let startContainer = aRange.startContainer;
  2024.           
  2025.           if (this._getEditableNode(startContainer))
  2026.             return false;
  2027.           
  2028.           let startOffset = aRange.startOffset;
  2029.           let docfrag = aRange.extractContents();
  2030.           let before = startContainer.splitText(startOffset);
  2031.           let parent = before.parentNode;
  2032.           
  2033.           aNode.appendChild(docfrag);
  2034.           parent.insertBefore(aNode, before);
  2035.           
  2036.           return aNode;
  2037.         ]]></body>
  2038.       </method>
  2039.       
  2040.       <method name="smoothScrollToElement">
  2041.         <parameter name="aWindow"/>
  2042.         <parameter name="aScrollData"/>
  2043.         <body><![CDATA[
  2044.           if (this._smoothScrollInterval)
  2045.             window.clearInterval(this._smoothScrollInterval);
  2046.           
  2047.           function sign(x) {
  2048.             if (x > 0) return 1;
  2049.             if (x < 0) return -1;
  2050.             return 0;
  2051.           }
  2052.           
  2053.           let ox, oy,
  2054.               dx, dy,
  2055.               cx, cy;
  2056.           
  2057.           let me = this;
  2058.           
  2059.           function fx() {
  2060.             ox = aWindow.scrollX;
  2061.             oy = aWindow.scrollY;
  2062.             
  2063.             dx = (aScrollData.x - ox) / 10;
  2064.             dx = sign(dx) * Math.ceil(Math.abs(dx));
  2065.             
  2066.             dy = (aScrollData.y - oy) / 10;
  2067.             dy = sign(dy) * Math.ceil(Math.abs(dy));
  2068.             
  2069.             aWindow.scrollBy(dx, dy);
  2070.             
  2071.             cx = aWindow.scrollX;
  2072.             cy = aWindow.scrollY;
  2073.             
  2074.             if ((ox-cx) == 0 && (oy-cy) == 0)
  2075.               window.clearInterval(me._smoothScrollInterval);
  2076.           }
  2077.           
  2078.           me._smoothScrollInterval = setInterval(fx, 20);
  2079.         ]]></body>
  2080.       </method>
  2081.       
  2082.       <method name="checkHighlightState">
  2083.         <parameter name="aBrowser"/>
  2084.         <body><![CDATA[
  2085.           if (aBrowser !== gBrowser.mCurrentBrowser)
  2086.             return;
  2087.           
  2088.           var tabData = this.getYaHLTabHandlerData(aBrowser);
  2089.           if (tabData) {
  2090.             var enabled = !!tabData.enabled;
  2091.             
  2092.             if (this._highlightEnabled !== enabled) {
  2093.               this._highlightEnabled = enabled;
  2094.               this._button.checked = enabled;
  2095.             }
  2096.             
  2097.             if (enabled && tabData.highlightDone === false)
  2098.               this.refreshHighlight(aBrowser);
  2099.           }
  2100.         ]]></body>
  2101.       </method>
  2102.       
  2103.       <method name="checkIsOnSerpLocation">
  2104.         <parameter name="aBrowser"/>
  2105.         <body><![CDATA[
  2106.           var tabData = this.getYaHLTabHandlerData(aBrowser);
  2107.           if (tabData && tabData.serpText === null &&
  2108.               (tabData.serpText = YaUtils.getSearchTextFromWebProgress(aBrowser.webProgress)) &&
  2109.               this.mSerpEnabled)
  2110.           {
  2111.               if (!tabData.keyListener) {
  2112.                 tabData.keyListener = function(e) {
  2113.                   if (e.isTrusted)
  2114.                     tabData.keyDown = true;
  2115.                 }
  2116.                 aBrowser.addEventListener("keydown", tabData.keyListener, false, true)
  2117.               }
  2118.               
  2119.               tabData.enabled = true;
  2120.               this.checkHighlightState(aBrowser);
  2121.           }
  2122.         ]]></body>
  2123.       </method>
  2124.       
  2125.       <field name="mLocationListener">
  2126.       <![CDATA[({
  2127.         _self: this,
  2128.         
  2129.         observe: function() {
  2130.           var [topic, browser] = arguments;
  2131.           
  2132.           if (topic == "onWindowLocationChange")
  2133.             browser = browser.chromeEventHandler.getTabBrowser().mCurrentTab.linkedBrowser;
  2134.           
  2135.           switch (topic) {
  2136.             case "onWindowLocationChange":
  2137.               this._self.checkIsOnSerpLocation(browser);
  2138.               this._self.checkHighlightState(browser);
  2139.               break;
  2140.             
  2141.             case "DOMContentLoaded":
  2142.               var tabData = this._self.getYaHLTabHandlerData(browser);
  2143.               tabData.highlightDone = false;
  2144.               tabData.lastHighlightString = "";
  2145.               this._self.checkHighlightState(browser);
  2146.               
  2147.               break;
  2148.             
  2149.             case "pagehide":
  2150.               var tabData = this._self.getYaHLTabHandlerData(browser);
  2151.               if (tabData) {
  2152.                 if (tabData.lastHighlightString != "") {
  2153.                   tabData.lastHighlightString = "";
  2154.                   this._self.toggleHighlight(null, browser, tabData);
  2155.                 }
  2156.                 
  2157.                 if (tabData.keyListener) {
  2158.                   browser.removeEventListener("keydown", tabData.keyListener, false, true);
  2159.                   tabData.keyListener = null;
  2160.                 }
  2161.                 
  2162.                 tabData.enabled = false;
  2163.                 tabData.highlightDone = null;
  2164.                 tabData.serpText = null;
  2165.                 tabData.keyDown = null;
  2166.               }
  2167.               
  2168.               break;
  2169.             
  2170.             default:
  2171.               break;
  2172.           }
  2173.         }
  2174.       })]]>
  2175.       </field>
  2176.       
  2177.       <method name="observe">
  2178.         <parameter name="aSubject"/>
  2179.         <parameter name="aTopic"/>
  2180.         <parameter name="aData"/>
  2181.         <body><![CDATA[
  2182.           switch (aTopic) {
  2183.             case "nsPref:changed":
  2184.               var prefName = aData.split(this.mPrefsNamePrefix)[1];
  2185.               
  2186.               switch (prefName) {
  2187.                 case "teleport":
  2188.                 case "serp":
  2189.                   prefName = "m" + prefName.replace(/^./, function(s){return s.toUpperCase()}) + "Enabled";
  2190.                   this[prefName] = this._prefBranch.getBoolPref(aData);
  2191.                   break;
  2192.                 
  2193.                 case "enabled":
  2194.                   this.enabled = this._prefBranch.getBoolPref(aData);
  2195.                   break;
  2196.                 
  2197.                 default:
  2198.                   break;
  2199.               }
  2200.               break;
  2201.             
  2202.             default:
  2203.               break;
  2204.           }
  2205.         ]]></body>
  2206.       </method>
  2207.     </implementation>
  2208.     
  2209.     <handlers>
  2210.       <handler event="command"><![CDATA[
  2211.         var target = event.originalTarget;
  2212.         
  2213.         if (target.hasAttribute("anonid")) {
  2214.           var anonid = target.getAttribute("anonid");
  2215.           
  2216.           switch (anonid) {
  2217.             case "teleport":
  2218.             case "serp":
  2219.               this._prefBranch.setBoolPref(this.mPrefsNamePrefix + anonid,
  2220.                                            (target.getAttribute("checked") == "true"));
  2221.               
  2222.               event.stopPropagation();
  2223.               break;
  2224.             
  2225.             case "highlight":
  2226.             default:
  2227.               var browser = gBrowser.mCurrentBrowser;
  2228.               var tabData = this.getYaHLTabHandlerData(browser);
  2229.               if (tabData)
  2230.                 tabData.highlightDone = true;
  2231.               
  2232.               this.mHighlightEnabled = !this.mHighlightEnabled;
  2233.               this.refreshHighlight(browser);
  2234.               
  2235.               break;
  2236.           }
  2237.         }
  2238.       ]]></handler>
  2239.       
  2240.       <handler event="popupshowing"><![CDATA[
  2241.         for each (var prop in ["highlight", "teleport", "serp"])
  2242.           this.getElement(prop).setAttribute("checked", !!this["_" + prop + "Enabled"]);
  2243.       ]]></handler>
  2244.     </handlers>
  2245.   </binding>
  2246. </bindings>