home *** CD-ROM | disk | FTP | other *** search
/ PC Advisor 2006 January / PCA126_DVD.iso / internet / nsb-setup.exe / chrome / browser.jar / content / browser / search / search-panel.js < prev    next >
Encoding:
Text File  |  2005-05-03  |  39.0 KB  |  1,244 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Netscape Public License
  6.  * Version 1.1 (the "License"); you may not use this file except in
  7.  * compliance with the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/NPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is 
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *    Robert John Churchill   <rjc@netscape.com> (Original Author)
  24.  *    Peter Annema            <disttsc@bart.nl>
  25.  *    Blake Ross              <blakeross@telocity.com>
  26.  *    Ben Goodger             <ben@netscape.com>
  27.  *    Rob Ginda               <rginda@netscape.com>
  28.  *    Steve Lamm              <slamm@netscape.com>
  29.  *    Samir Gehani            <sgehani@netscape.com>
  30.  *
  31.  * Alternatively, the contents of this file may be used under the terms of
  32.  * either the GNU General Public License Version 2 or later (the "GPL"), or 
  33.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  34.  * in which case the provisions of the GPL or the LGPL are applicable instead
  35.  * of those above. If you wish to allow use of your version of this file only
  36.  * under the terms of either the GPL or the LGPL, and not to allow others to
  37.  * use your version of this file under the terms of the NPL, indicate your
  38.  * decision by deleting the provisions above and replace them with the notice
  39.  * and other provisions required by the GPL or the LGPL. If you do not delete
  40.  * the provisions above, a recipient may use your version of this file under
  41.  * the terms of any one of the NPL, the GPL or the LGPL.
  42.  *
  43.  * ***** END LICENSE BLOCK ***** */
  44.  
  45. const ISEARCH_CONTRACTID       = "@mozilla.org/rdf/datasource;1?name=internetsearch";
  46. const RDFSERVICE_CONTRACTID    = "@mozilla.org/rdf/rdf-service;1";
  47. const BMARKS_CONTRACTID        = "@mozilla.org/browser/bookmarks-service;1";
  48.  
  49. const nsIBookmarksService      = Components.interfaces.nsIBookmarksService;
  50. const nsIRDFService            = Components.interfaces.nsIRDFService;
  51. const nsIRDFLiteral            = Components.interfaces.nsIRDFLiteral;
  52. const nsIRDFDataSource         = Components.interfaces.nsIRDFDataSource;
  53. const nsIRDFRemoteDataSource   = Components.interfaces.nsIRDFRemoteDataSource;
  54. const nsIInternetSearchService = Components.interfaces.nsIInternetSearchService;
  55.  
  56. const DEBUG = false;
  57.  
  58. var debug;
  59. if (!DEBUG)
  60. {
  61.   debug = function(msg) {};
  62. }
  63. else
  64. {
  65.   debug = function(msg)
  66.   {
  67.     dump("\t ^^^ search-panel.js: " + msg + "\n");
  68.   };
  69. }
  70.  
  71. var rootNode;
  72. var textArc;
  73. var modeArc;
  74. var searchBundle;
  75. var regionalBundle;
  76. var gSearchButtonText = null;
  77. var gStopButtonText = null;
  78.  
  79. var sidebarInitiatedSearch = false;
  80.  
  81. var RDF_observer =
  82. {
  83.   onAssert : function(ds, src, prop, target)
  84.   {
  85.     if (src == rootNode) {
  86.       if (prop == textArc)
  87.         rememberSearchText(target);
  88.       else if (prop == modeArc)
  89.         updateSearchMode();
  90.     }
  91.   },
  92.  
  93.   onUnassert : function(ds, src, prop, target)
  94.   {
  95.   },
  96.  
  97.   onChange : function(ds, src, prop, old_target, new_target)
  98.   {
  99.     if (src == rootNode) {
  100.       if (prop == textArc)
  101.         rememberSearchText(new_target);
  102.       else if (prop == modeArc)
  103.         updateSearchMode();
  104.     }
  105.   },
  106.  
  107.   onMove : function(ds, old_src, new_src, prop, target)
  108.   {
  109.   },
  110.  
  111.   onBeginUpdateBatch : function(ds)
  112.   {
  113.   },
  114.  
  115.   onEndUpdateBatch   : function(ds)
  116.   {
  117.   }
  118. }
  119.  
  120. function rememberSearchText(target)
  121. {
  122.   if (sidebarInitiatedSearch) {
  123.     // this avoids updating the sidebar textbox twice
  124.     return;
  125.   }
  126.   if (target) {
  127.     target = target.QueryInterface(nsIRDFLiteral).Value;
  128.     if (target) {
  129.       // convert plusses (+) back to spaces
  130.       target = target.replace(/\+/g, " ");
  131.       var textNode = document.getElementById("sidebar-search-text");
  132.  
  133.       if (target != textNode.value) {
  134.         // category is unknown, therefore use "All Engines"
  135.         var categoryPopup = document.getElementById( "categoryPopup" );
  136.         var categoryList = document.getElementById( "categoryList" );
  137.         if (categoryPopup && categoryList) {
  138.           categoryList.selectedItem = categoryPopup.childNodes[0];
  139.         }
  140.       }
  141.  
  142.       textNode.value = decodeURI(target);
  143.       doEnabling();
  144.     }
  145.   }
  146.   // show the results tab
  147.   switchTab(0);
  148. }
  149.  
  150. function getIndexToSelect(haveDefault, defaultEngine, enginePopup)
  151. {
  152.     if (haveDefault)
  153.     {
  154.         // iterate over constrained engine list for a default engine match
  155.         for (var i = 0; i < enginePopup.childNodes.length; ++i)
  156.         {
  157.             if (enginePopup.childNodes[i].id == defaultEngine)
  158.             {
  159.                 // found match with default engine!
  160.                 return i;
  161.             }
  162.         }
  163.     }
  164.  
  165.     return 0; // default to first engine at index '0'
  166. }
  167.  
  168. function getMinVer()
  169. {
  170.   var minVerStr = nsPreferences.
  171.     copyUnicharPref("browser.search.basic.min_ver");
  172.   var minVer = parseFloat(minVerStr);
  173.   if (isNaN(minVer))
  174.     minVer = 0; // no pref or not a number so default to min ver 0.0
  175.  
  176.   debug("Float value of minVer = " + minVer);
  177.   return minVer;
  178. }
  179.  
  180. /** 
  181.  * Constrain the list of engines to only those that
  182.  * contain ver >= browser.search.basic.min_ver pref 
  183.  * value to be displayed in the basic popup list of 
  184.  * engines.
  185.  */
  186. function constrainBasicList()
  187. {
  188.   debug("constrainBasicList");
  189.  
  190.   var basicEngineMenu = document.getElementById("basicEngineMenu");
  191.   if (!basicEngineMenu)
  192.   {
  193.     debug("Ack!  basicEngineList is empty!");
  194.     return;
  195.   }
  196.  
  197.   var basicEngines = basicEngineMenu.childNodes[1];
  198.   var len = basicEngines.childNodes.length;
  199.   var currDesc;
  200.   var currVer;
  201.   var haveDefault = false;
  202.  
  203.   debug("Found " + len + " sherlock plugins.");
  204.  
  205.   // MERC - JCH: GET THE PERSISTED SEARCH ENGINE AS SET IN SIDEBAR SEARCH OR NAV BAR SEARCH DROPDOWN MENUS
  206.   var broadcaster = window.top.document.getElementById('searchEngineBroadcaster');
  207.   var defaultEngine = broadcaster.getAttribute("searchengine");
  208.  
  209.   //var defaultEngine = nsPreferences.
  210.    // copyUnicharPref("browser.search.defaultengine");
  211.  
  212.   // we constrain the basic list to all engines with ver >= minVer
  213.   var minVer = getMinVer();
  214.  
  215.   for (var i = 0; i < len; ++i)
  216.   {
  217.     currDesc = basicEngines.childNodes[i].getAttribute("desc");
  218.     debug("Engine[" + i + "] = " + currDesc);
  219.  
  220.     // make sure we leave the default engine (check if we already have 
  221.     // the default to avoid duplicates)
  222.     if (basicEngines.childNodes[i].id == defaultEngine && !haveDefault)
  223.     {
  224.       haveDefault = true;
  225.     }
  226.     else
  227.     {
  228.       // remove if not a basic engine
  229.       currVer = basicEngines.childNodes[i].getAttribute("ver");
  230.       if (!currVer || isNaN(parseFloat(currVer)))
  231.       {
  232.         // missing version attr or not a number: default to ver 1.0
  233.         currVer = 1;
  234.       }
  235.       debug("Version of " + (currDesc ? currDesc : "<unknown>") + 
  236.             " is: " + currVer);
  237.  
  238.       if (parseFloat(currVer) < minVer)
  239.       {
  240.         try
  241.         {
  242.           basicEngines.removeChild(basicEngines.childNodes[i]);
  243.           --i;
  244.           --len;
  245.         }
  246.         catch (ex)
  247.         {
  248.           debug("Exception: Couldn't remove " + currDesc +
  249.                 " from engine list!");
  250.         }
  251.       }
  252.     }
  253.   }
  254.  
  255.   // mark selected engine
  256.   var selected = getIndexToSelect(haveDefault, defaultEngine, basicEngines);
  257.   basicEngineMenu.selectedItem = basicEngines.childNodes[selected];
  258. }
  259.  
  260. function updateSearchMode()
  261. {
  262.   debug("updateSearchMode");
  263.  
  264.   var searchMode = nsPreferences.getIntPref("browser.search.mode");
  265.   var categoryBox = document.getElementById("categoryBox");
  266.   var basicBox = document.getElementById("basicBox");
  267.  
  268.   debug("search mode is " + searchMode);
  269.   if (searchMode == 0)
  270.   {
  271.     categoryBox.setAttribute("collapsed", "true");
  272.     basicBox.removeAttribute("collapsed");
  273.     switchTab(0);
  274.  
  275.     constrainBasicList();
  276.   }
  277.   else
  278.   {
  279.     categoryBox.removeAttribute("collapsed");
  280.     basicBox.setAttribute("collapsed", "true");
  281.     switchTab(1);
  282.   }
  283.  
  284.   return searchMode;
  285. }
  286.  
  287. function readRDFString(aDS,aRes,aProp) {
  288.   var n = aDS.GetTarget(aRes, aProp, true);
  289.   if (n)
  290.     return n.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
  291.   return null;
  292. }
  293.  
  294.  
  295. function ensureDefaultEnginePrefs(aRDF,aDS) 
  296. {
  297.   var prefbranch = Components.classes["@mozilla.org/preferences-service;1"]
  298.                              .getService(Components.interfaces.nsIPrefBranch);
  299.   var defaultName = prefbranch.getComplexValue("browser.search.defaultenginename",
  300.                                                Components.interfaces.nsIPrefLocalizedString).data;
  301.   var kNC_Root = aRDF.GetResource("NC:SearchEngineRoot");
  302.   var kNC_child = aRDF.GetResource("http://home.netscape.com/NC-rdf#child");
  303.   var kNC_Name = aRDF.GetResource("http://home.netscape.com/NC-rdf#Name");
  304.           
  305.   var arcs = aDS.GetTargets(kNC_Root, kNC_child, true);
  306.   while (arcs.hasMoreElements()) {
  307.     var engineRes = arcs.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
  308.     var name = readRDFString(aDS, engineRes, kNC_Name);
  309.     if (name == defaultName)
  310.       prefbranch.setCharPref("browser.search.defaultengine", engineRes.Value);
  311.   }
  312. }
  313.  
  314. function AskChangeDefaultEngine(aSelectedEngine)
  315. {
  316.   const kDontAskAgainPref  = "browser.search.set_default.dont_ask_again";
  317.   const kDefaultEnginePref = "browser.search.defaultengine";
  318.  
  319.   // don't prompt user if selection is same as old default engine
  320.   var oldDefault = nsPreferences.copyUnicharPref(kDefaultEnginePref);
  321.   if (aSelectedEngine.getAttribute("value") == oldDefault)
  322.     return;
  323.  
  324.   // check "don't ask again" pref
  325.   var dontAskAgain = nsPreferences.getBoolPref(kDontAskAgainPref, false);
  326.   var change = false; // should we change the default engine?
  327.  
  328.   // if "don't ask again" pref was set
  329.   if (dontAskAgain)
  330.   {
  331.     change = true;
  332.   }
  333.   else
  334.   {
  335.     // prompt user if we should change their default engine
  336.     var promptSvc = Components.
  337.                       classes["@mozilla.org/embedcomp/prompt-service;1"].
  338.                       getService(Components.interfaces.nsIPromptService);
  339.     if (!promptSvc)
  340.       return;
  341.     var title = searchBundle.getString("changeEngineTitle"); 
  342.     var dontAskAgainMsg = searchBundle.getString("dontAskAgainMsg"); 
  343.     var engineName = aSelectedEngine.getAttribute("label");
  344.     if (!engineName || engineName == "")
  345.       engineName = searchBundle.getString("thisEngine");
  346.     var changeEngineMsg = searchBundle.stringBundle.formatStringFromName(
  347.                           "changeEngineMsg", [engineName], 1); 
  348.  
  349.     var checkbox = {value:0};
  350.     change = promptSvc.confirmCheck(window, title, changeEngineMsg, 
  351.                dontAskAgainMsg, checkbox);
  352.  
  353.     // store "don't ask again" pref from checkbox value (if changed)
  354.     debug("dontAskAgain: " + dontAskAgain);
  355.     debug("checkbox.value: " + checkbox.value);
  356.     if (checkbox.value != dontAskAgain)
  357.       nsPreferences.setBoolPref(kDontAskAgainPref, checkbox.value);
  358.   }
  359.  
  360.   // if confirmed true, i.e., change default engine, then set pref
  361.   if (change)
  362.     nsPreferences.setUnicharPref(kDefaultEnginePref, aSelectedEngine.value);
  363.  
  364.   disableNavButtons();
  365. }
  366.  
  367. function disableNavButtons()
  368. {
  369.   var nextButton = document.getElementById("next-results");
  370.   var prevButton = document.getElementById("prev-results");
  371.   if (nextButton && nextButton.getAttribute("disabled") != "true")
  372.     nextButton.setAttribute("disabled", "true");
  373.   if (prevButton && prevButton.getAttribute("disabled") != "true")
  374.     prevButton.setAttribute("disabled", "true");
  375. }
  376.  
  377. function ensureSearchPref()
  378. {
  379.   var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  380.                       .getService(Components.interfaces.nsIRDFService);
  381.   var prefbranch = Components.classes["@mozilla.org/preferences-service;1"]
  382.                              .getService(Components.interfaces.nsIPrefBranch);
  383.   var ds = rdf.GetDataSource("rdf:internetsearch");
  384.   var kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name");
  385.   var defaultEngine;
  386.  
  387.   try {
  388.     defaultEngine = prefbranch.getCharPref("browser.search.defaultengine");
  389.   } catch(ex) {
  390.     ensureDefaultEnginePrefs(rdf, ds);
  391.     defaultEngine = prefbranch.getCharPref("browser.search.defaultengine");
  392.   }
  393. }
  394.  
  395. // Initialize the Search panel:
  396. // 1) init the category list
  397. // 2) load the search engines associated with this category
  398. // 3) initialize the checked state of said engines
  399. function SearchPanelStartup()
  400. {
  401.  
  402.   searchBundle = document.getElementById("searchBundle");
  403.  
  404.   var rdf  = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  405.   rootNode = rdf.GetResource("NC:LastSearchRoot", true);
  406.   textArc  = rdf.GetResource("http://home.netscape.com/NC-rdf#LastText", true);
  407.   modeArc  = rdf.GetResource("http://home.netscape.com/NC-rdf#SearchMode", true);
  408.   
  409.   ensureSearchPref()
  410.   
  411.   var resultList = document.getElementById("resultList");
  412.   resultList.database.AddObserver(RDF_observer);
  413.  
  414.   var categoryList = document.getElementById("categoryList");
  415.   var internetSearch = Components.classes[ISEARCH_CONTRACTID].getService(nsIInternetSearchService);
  416.   var catDS = internetSearch.GetCategoryDataSource();
  417.   if (catDS) {
  418.     catDS = catDS.QueryInterface(nsIRDFDataSource);
  419.     categoryList.database.AddDataSource(catDS);
  420.     categoryList.builder.rebuild();
  421.     var engineList = document.getElementById("searchengines");
  422.     engineList.database.AddDataSource(catDS);
  423.     engineList.builder.rebuild();
  424.     engineList.addEventListener("CheckboxStateChange", saveEngine, false);
  425.   }
  426.  
  427.   // try and determine last category name used
  428.   var lastCategoryName = nsPreferences.copyUnicharPref("browser.search.last_search_category", "");
  429.   if (lastCategoryName) {
  430.     // strip off the prefix if necessary
  431.     var prefix = "NC:SearchCategory?category=";
  432.     if (lastCategoryName.indexOf(prefix) == 0)
  433.       lastCategoryName = lastCategoryName.substr(prefix.length);
  434.   }
  435.  
  436.   // select the appropriate category
  437.   var categoryPopup = document.getElementById("categoryPopup");
  438.   var found = false;
  439.   for (var i = 0; i < categoryPopup.childNodes.length; ++i) {
  440.     if (lastCategoryName == "" &&
  441.         categoryPopup.childNodes[i].getAttribute("value") == "NC:SearchEngineRoot" ||
  442.         categoryPopup.childNodes[i].getAttribute("id") == lastCategoryName)
  443.     {
  444.       categoryList.selectedItem = categoryPopup.childNodes[i];
  445.       found = true;
  446.       break;
  447.     }
  448.   }
  449.   if (!found)
  450.     categoryList.selectedItem = categoryPopup.childNodes[0];
  451.  
  452.   if (!lastCategoryName)
  453.     lastCategoryName = "NC:SearchEngineRoot";
  454.   else if (lastCategoryName != "NC:SearchEngineRoot")
  455.     lastCategoryName = "NC:SearchCategory?category=" + lastCategoryName;
  456.  
  457.   var treeNode = document.getElementById("searchengines");
  458.   treeNode.setAttribute("ref", lastCategoryName);
  459.  
  460.   loadEngines(lastCategoryName);
  461.  
  462.   // MERC (ccampbell): now observes a broadcaster in browser.xul scope
  463.   var broadcaster = window.top.document.getElementById('searchEngineBroadcaster');
  464.   debug('initializing search engine observer [ broadcaster: '+broadcaster+' ]');
  465.   var engineList = document.getElementById('basicEngineMenu');
  466.   //document.addBroadcastListenerFor(broadcaster, engineList, 'searchengine');
  467.   //document.addBroadcastListenerFor(broadcaster, engineList, 'src');
  468.   broadcaster.addEventListener("DOMAttrModified", onSearchEngineChanged, false);
  469.  
  470.   // if we have search results, show them, otherwise show engines
  471.   if (updateSearchMode() != 0)
  472.   {
  473.     if (haveSearchResults())
  474.       switchTab(0);
  475.     else
  476.       switchTab(1);
  477.   }
  478. }
  479.  
  480.  
  481. // MERC (ccampbell)
  482. function onSearchEngineChanged(evt) {
  483.   debug('onSearchEngineChanged()');
  484.  
  485.   // We are only going to react to changes to the 'searchengine' attribute
  486.   if (evt.attrName != 'searchengine')
  487.     return;
  488.  
  489.   // If the new value is the same as the current engine selection, bail out
  490.   var engineList = document.getElementById('basicEngineMenu');
  491.   if (evt.newValue == engineList.getAttribute('value')) {
  492.     debug('  no change!');
  493.     return;
  494.   }
  495.   debug('  changing engine to: '+evt.newValue+'\n');
  496.  
  497.   var engines = engineList.menupopup;
  498.   debug('  there are '+engines.childNodes.length+' items to check against');
  499.   for (var i = 0; i < engines.childNodes.length; i++) {
  500.     var thisVal = engines.childNodes[i].getAttribute('value');
  501.     debug('    checking against: '+thisVal);
  502.     if (thisVal == evt.newValue) {
  503.       debug('      CHANGING MENU!\n');
  504.       engineList.selectedItem = engines.childNodes[i];
  505.       return;
  506.     }
  507.   }
  508. }
  509.  
  510.  
  511. // MERC (ccampbell)
  512. function searchEngineSelected(evt) {
  513.   debug('searchEngineSelected()');
  514.   var broadcaster = window.top.document.getElementById('searchEngineBroadcaster');
  515.   var engineList = document.getElementById('basicEngineMenu');
  516.  
  517.   broadcaster.setAttribute('searchengine',engineList.getAttribute('value'));
  518.   broadcaster.setAttribute('src',engineList.getAttribute('src'));
  519. }
  520.  
  521.  
  522. function haveSearchResults()
  523. {
  524.   var ds = document.getElementById("resultList").database;
  525.   if (!ds)
  526.     return false;
  527.  
  528.   var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  529.   var source = rdf.GetResource("NC:LastSearchRoot", true);
  530.   var childProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#LastText", true);
  531.   var target = ds.GetTarget(source, childProperty, true);
  532.   if (target) {
  533.     target = target.QueryInterface(nsIRDFLiteral).Value;
  534.     if (target) {
  535.       // convert plusses (+) back to spaces
  536.       target = target.replace(/\+/g, " ");
  537.       var textNode = document.getElementById("sidebar-search-text");
  538.       textNode.value = decodeURI(target);
  539.       return true;
  540.     }
  541.   }
  542.   return false;
  543. }
  544.  
  545. function getNumEngines()
  546. {
  547.   var listbox = document.getElementById("searchengines");
  548.   return listbox.getElementsByTagName("listitem").length;
  549. }
  550.  
  551. function chooseCategory(aNode)
  552. {
  553.   var category = !aNode.id ? "NC:SearchEngineRoot" :
  554.                              "NC:SearchCategory?category=" + aNode.getAttribute("id");
  555.   nsPreferences.setUnicharPref("browser.search.last_search_category", category);
  556.  
  557.   var treeNode = document.getElementById("searchengines");
  558.   treeNode.setAttribute("ref", category);
  559.  
  560.   loadEngines(category);
  561. }
  562.  
  563. function saveEngine(event)
  564. {
  565.   var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  566.   var localStore = rdf.GetDataSource("rdf:local-store");
  567.   if (!localStore)
  568.     return;
  569.  
  570.   var checkedProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#checked", true);
  571.   var engines = event.currentTarget;
  572.   var categorySRC = rdf.GetResource(engines.ref, true);
  573.  
  574.   var itemNode = event.target;
  575.   var engineSRC = rdf.GetResource(itemNode.id, true);
  576.  
  577.   if (itemNode.checked)
  578.     localStore.Assert(categorySRC, checkedProperty, engineSRC, true);
  579.   else
  580.     localStore.Unassert(categorySRC, checkedProperty, engineSRC, true);
  581.  
  582.   // save changes; flush out the localstore
  583.   try {
  584.     var flushableStore = localStore.QueryInterface(nsIRDFRemoteDataSource);
  585.     flushableStore.Flush();
  586.   }
  587.   catch (ex) {}
  588. }
  589.  
  590. // initialize the appropriate engine list, and the checked state of the engines
  591. function loadEngines(aCategory)
  592. {
  593.   var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  594.   var localStore = rdf.GetDataSource("rdf:local-store");
  595.   if (localStore) {
  596.     var engineBox = document.getElementById("searchengines");
  597.     var numEngines = engineBox.childNodes.length;
  598.     var checkedProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#checked", true);
  599.     var categorySRC = rdf.GetResource(aCategory, true);
  600.     for (var x = 0; x < numEngines; ++x) {
  601.       var listitemNode = engineBox.childNodes[x];
  602.       if (listitemNode.localName == "listitem") {
  603.         var engineURI = listitemNode.getAttribute("id");
  604.         var engineSRC = rdf.GetResource(engineURI, true);
  605.   
  606.         var hasAssertion = localStore.HasAssertion(categorySRC, checkedProperty, engineSRC, true);
  607.         if (hasAssertion)
  608.           listitemNode.checked = true;
  609.       }
  610.     }
  611.   }
  612. }
  613.  
  614. function SearchPanelShutdown()
  615. {
  616.   var tree = document.getElementById("resultList");
  617.   tree.database.RemoveObserver(RDF_observer);
  618. }
  619.  
  620. function doStop()
  621. {
  622.   if (!gSearchButtonText)
  623.     gSearchButtonText = searchBundle.getString("searchButtonText");
  624.  
  625.   var searchButtonNode = document.getElementById("searchButton");
  626.   searchButtonNode.removeAttribute("stop");
  627.   searchButtonNode.setAttribute("label", gSearchButtonText);
  628.  
  629.   // should stop button press also stop the load of the page in the browser? I think so.
  630.   var progressNode = parent.document.getElementById("statusbar-icon");
  631.   if (progressNode)
  632.     progressNode.setAttribute("mode", "normal");
  633.  
  634.   // stop any network connections
  635.   var internetSearchService = Components.classes[ISEARCH_CONTRACTID].getService(nsIInternetSearchService);
  636.   internetSearchService.Stop();
  637.  
  638.   // show appropriate column(s)
  639.   var navWindow = getNavigatorWindow(false);
  640.   var resultsList = navWindow ? navWindow._content.document.getElementById("resultsList") : null;
  641.   if (!resultsList)
  642.     return;
  643.  
  644.   var searchURL = resultsList.getAttribute("ref");
  645.   if (!searchURL)
  646.     return;
  647.  
  648.   var internetSearch = internetSearchService.QueryInterface(nsIRDFDataSource);
  649.  
  650.   // get various services
  651.   var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  652.  
  653.   var searchResource       = rdf.GetResource(searchURL, true);
  654.   var priceProperty        = rdf.GetResource("http://home.netscape.com/NC-rdf#Price", true);
  655.   var availabilityProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#Availability", true);
  656.   var relevanceProperty    = rdf.GetResource("http://home.netscape.com/NC-rdf#Relevance", true);
  657.   var dateProperty         = rdf.GetResource("http://home.netscape.com/NC-rdf#Date", true);
  658.   var trueProperty         = rdf.GetLiteral("true");
  659.   var hasPriceFlag         = internetSearch.HasAssertion(searchResource, priceProperty, trueProperty, true);
  660.   var hasAvailabilityFlag  = internetSearch.HasAssertion(searchResource, availabilityProperty, trueProperty, true);
  661.   var hasRelevanceFlag     = internetSearch.HasAssertion(searchResource, relevanceProperty, trueProperty, true);
  662.   var hasDateFlag          = internetSearch.HasAssertion(searchResource, dateProperty, trueProperty, true);
  663.   var colNode;
  664.   var sortSetFlag = false;
  665.  
  666.   if (hasPriceFlag) {
  667.     colNode = navWindow._content.document.getElementById("PriceColumn");
  668.     if (colNode) {
  669.       colNode.removeAttribute("hidden");
  670.       if (!sortSetFlag) {
  671.         top._content.setInitialSort(colNode, "ascending");
  672.         sortSetFlag = true;
  673.       }
  674.     }
  675.   }
  676.  
  677.   if (hasAvailabilityFlag) {
  678.     colNode = navWindow._content.document.getElementById("AvailabilityColumn");
  679.     if (colNode)
  680.       colNode.removeAttribute("hidden");
  681.   }
  682.  
  683.   if (hasDateFlag) {
  684.     colNode = navWindow._content.document.getElementById("DateColumn");
  685.     if (colNode)
  686.       colNode.removeAttribute("hidden");
  687.   }
  688.  
  689.   if (hasRelevanceFlag) {
  690.     colNode = navWindow._content.document.getElementById("RelevanceColumn");
  691.     if (colNode) {
  692.       colNode.removeAttribute("hidden");
  693.       if (!sortSetFlag) {
  694.         navWindow._content.setInitialSort(colNode, "descending");
  695.         sortSetFlag = true;
  696.       }
  697.     }
  698.   }
  699.  
  700.   if (!sortSetFlag) {
  701.     colNode = navWindow._content.document.getElementById("PageRankColumn");
  702.     if (colNode)
  703.       navWindow._content.setInitialSort(colNode, "ascending");
  704.   }
  705.  
  706.   switchTab(0);
  707. }
  708.  
  709. function doSearch()
  710. {
  711.   var navWindow = getNavigatorWindow(true);
  712.   if (navWindow._content)
  713.     onNavWindowLoad();
  714.   else
  715.     navWindow.addEventListener("load", onNavWindowLoad, false);
  716. }
  717.  
  718. function onNavWindowLoad() {
  719.   var navWindow = getNavigatorWindow(true);
  720.  
  721.   // hide various columns
  722.   if (navWindow && "_content" in navWindow && "isMozillaSearchWindow" in navWindow._content) {
  723.     colNode = navWindow._content.document.getElementById("RelevanceColumn");
  724.     if (colNode)
  725.       colNode.setAttribute("hidden", "true");
  726.  
  727.     colNode = navWindow._content.document.getElementById("PriceColumn");
  728.     if (colNode)
  729.       colNode.setAttribute("hidden", "true");
  730.  
  731.     colNode = navWindow._content.document.getElementById("AvailabilityColumn");
  732.     if (colNode)
  733.       colNode.setAttribute("hidden", "true");
  734.   }
  735.  
  736.   // get user text to find
  737.   var textNode = document.getElementById("sidebar-search-text");
  738.  
  739.   if (!textNode.value) {
  740.     alert(searchBundle.getString("enterstringandlocation"));
  741.     return;
  742.   }
  743.  
  744.   var searchMode = nsPreferences.getIntPref("browser.search.mode", 0);
  745.   var engineURIs = [];
  746.   if (searchMode > 0) {
  747.     var foundEngine = false;
  748.     var itemNode;
  749.     var engineBox = document.getElementById("searchengines");
  750.  
  751.     // in advanced search mode, get selected search engines
  752.     // (for the current search category)
  753.     for (var x = 0; x < engineBox.childNodes.length; ++x) {
  754.       itemNode = engineBox.childNodes[x];
  755.  
  756.       if (itemNode.localName == "listitem" && itemNode.checked) {
  757.         var engineURI = itemNode.id;
  758.  
  759.         if (engineURI) {
  760.           engineURIs[engineURIs.length] = engineURI;
  761.           foundEngine = true;
  762.         }
  763.       }
  764.     }
  765.  
  766.     if (!foundEngine) {
  767.       if (getNumEngines() == 1) {
  768.         // only one engine in this category, check it
  769.         itemNode = engineBox.firstChild;
  770.         engineURIs[engineURIs.length] = itemNode.id;
  771.       }
  772.       else {
  773.         for (var i = 0; i < engineBox.childNodes.length; ++i) {
  774.           itemNode = engineBox.childNodes[i];
  775.           var theID = itemNode.id;
  776.           if (theID.indexOf("NetscapeSearch.src") != -1) {
  777.             engineURIs[engineURIs.length] = theID;
  778.             foundEngine = true;
  779.             break;
  780.           }
  781.         }
  782.  
  783.         if (!foundEngine) {
  784.           alert(searchBundle.getString("enterstringandlocation"));
  785.           return;
  786.         }
  787.       }
  788.     }
  789.   }
  790.   else
  791.   {
  792.     var basicEngines = document.getElementById("basicEngineMenu");
  793.     engineURIs[0] = basicEngines.selectedItem.id;
  794.     debug("basic mode URI = " + engineURIs[0]);
  795.   }
  796.  
  797.   if (!gStopButtonText)
  798.     gStopButtonText = searchBundle.getString("stopButtonText");
  799.  
  800.   var searchButtonNode = document.getElementById("searchButton");
  801.   searchButtonNode.setAttribute("stop", "true");
  802.   searchButtonNode.setAttribute("label", gStopButtonText);
  803.  
  804.   var progressNode = top.document.getElementById("statusbar-icon");
  805.   if (progressNode)
  806.     progressNode.setAttribute("mode", "undetermined");
  807.  
  808.   // run the search
  809.   OpenSearch(textNode.value, engineURIs);
  810.   switchTab(0);
  811. }
  812.  
  813. function checkSearchProgress()
  814. {
  815.   var activeSearchFlag = false;
  816.   var navWindow = getNavigatorWindow(false);
  817.  
  818.   if (navWindow) {
  819.     var resultsList = navWindow._content.document.getElementById("resultsList");
  820.     if (resultsList) {
  821.       var treeref = resultsList.getAttribute("ref");
  822.       var ds = resultsList.database;
  823.       if (ds && treeref) {
  824.         try {
  825.           var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  826.           var source = rdf.GetResource(treeref, true);
  827.           var loadingProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#loading", true);
  828.           var target = ds.GetTarget(source, loadingProperty, true);
  829.           if (target)
  830.             target = target.QueryInterface(nsIRDFLiteral).Value;
  831.           activeSearchFlag = target == "true" ? true : false;
  832.         }
  833.         catch (ex) {
  834.           activeSearchFlag = false;
  835.         }
  836.       }
  837.     }
  838.   }
  839.  
  840.   if (activeSearchFlag)
  841.     setTimeout("checkSearchProgress()", 1000);
  842.   else
  843.     doStop();
  844.  
  845.   return activeSearchFlag;
  846. }
  847.  
  848. function sidebarOpenURL(listitem)
  849. {
  850.   var id = listitem.id;
  851.   if (!id)
  852.     return;
  853.  
  854.   // rjc: add support for anonymous resources; if the node has
  855.   // a "#URL" property, use it, otherwise default to using the id
  856.   try {
  857.     var ds = document.getElementById("resultList").database;
  858.     if (ds) {
  859.       var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  860.       var src = rdf.GetResource(id, true);
  861.       var prop = rdf.GetResource("http://home.netscape.com/NC-rdf#URL", true);
  862.       var target = ds.GetTarget(src, prop, true);
  863.       if (target) {
  864.         target = target.QueryInterface(nsIRDFLiteral).Value;
  865.         if (target)
  866.           id = target;
  867.       }
  868.     }
  869.   } catch (ex) {
  870.   }
  871.  
  872.   // mark result as visited
  873.   listitem.setAttribute("visited", "true");
  874.   
  875.   loadURLInContent(id);
  876. }
  877.  
  878. function OpenSearch(aSearchStr, engineURIs)
  879. {
  880.   var searchEngineURI = nsPreferences.copyUnicharPref("browser.search.defaultengine", null);
  881.   var defaultSearchURL = nsPreferences.getLocalizedUnicharPref("browser.search.defaulturl", null);
  882.  
  883.   if (!defaultSearchURL) {
  884.     regionalBundle = document.getElementById("regionalBundle");
  885.     defaultSearchURL = regionalBundle.getString("defaultSearchURL");
  886.   }
  887.  
  888.   var searchDS = Components.classes[ISEARCH_CONTRACTID].getService(nsIInternetSearchService);
  889.  
  890.   var escapedSearchStr = encodeURIComponent(aSearchStr);
  891.   sidebarInitiatedSearch = true;
  892.   searchDS.RememberLastSearchText(escapedSearchStr);
  893.   sidebarInitiatedSearch = false;
  894.  
  895.   try {
  896.     var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  897.                         .getService(Components.interfaces.nsIRDFService);
  898.     var rEngine = rdf.GetResource(searchEngineURI);
  899.     var kNC_Root = rdf.GetResource("NC:SearchEngineRoot");
  900.     var kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name");
  901.     var engineID = 'searchpanel:'+readRDFString(searchDS, rEngine, kNC_Name);
  902.     var searchPanel = document.getElementById('searchPanel');
  903.     searchPanel.setAttribute('perfmon', engineID);
  904.     window.top.perfmon.trackData(searchPanel);
  905.   } catch (ex) {
  906.     dump('search-panel.js: ERROR tracking search provider hits\n'+ex+'\n');
  907.   }
  908.  
  909.   var gURL;
  910.   var suppressSearchService = false;
  911.   try {
  912.     if (!engineURIs || engineURIs.length <= 1) {
  913.       // not called from sidebar or only one engine selected
  914.       if (engineURIs && engineURIs.length == 1) {
  915.         searchEngineURI = engineURIs[0];
  916.         gURL = "internetsearch:engine=" + searchEngineURI + "&text=" + escapedSearchStr;
  917.       }
  918.  
  919.       if (!searchEngineURI)
  920.         searchEngineURI = regionalBundle.getString("defaultSearchURL");
  921.  
  922.       // look up the correct search URL format for the given engine
  923.       try {
  924.         var whichButtons = new Object;
  925.         whichButtons.value = 0;
  926.         var searchURL = searchDS.GetInternetSearchURL(searchEngineURI, escapedSearchStr, 0, 0, whichButtons);
  927.         doNavButtonEnabling(whichButtons.value, searchDS, 0);
  928.         dump("JMC: searchEngineURI is : " + searchEngineURI + "\n");
  929.         // JMC: Hackish fix for fromPage urls, should generalize this
  930.         if (searchEngineURI.indexOf('NetscapeSearch') > -1)
  931.         {
  932.           var pref = Components.classes['@mozilla.org/preferences-service;1']
  933.                .getService(Components.interfaces.nsIPrefService)
  934.                .getBranch(null);
  935.           searchURL = pref.getCharPref('browser.sidebarSearch.URL') + escapedSearchStr;
  936.           // suppressSearchService = true;
  937.           // getNavigatorWindow(true).loadURI(searchURL);
  938.           //return;
  939.         }
  940.         
  941.       }
  942.       catch (ex) {
  943.         dump("Exception when calling GetInternetSearchURL: " + ex);
  944.         searchURL = "";
  945.       }
  946.  
  947.       defaultSearchURL = searchURL ? searchURL : defaultSearchURL + escapedSearchStr;
  948.       if (!searchURL)
  949.         gURL = "";
  950.  
  951.       // load the results page of selected or default engine in the content area
  952.       if (defaultSearchURL)
  953.         loadURLInContent(defaultSearchURL, suppressSearchService);
  954.     }
  955.     else {
  956.       // multiple providers
  957.       searchURL = "";
  958.       for (var i = 0; i < engineURIs.length; ++i) {
  959.         searchURL += !searchURL ? "internetsearch:" : "&";
  960.         searchURL += "engine=" + engineURIs[i];
  961.       }
  962.       searchURL += ("&text=" + escapedSearchStr);
  963.       gURL = searchURL;
  964.       loadURLInContent(encodeURI("chrome://browser/content/search/internetresults.xul?" + searchURL));
  965.     }
  966.   }
  967.   catch (ex) {
  968.     debug("Exception: " + ex);
  969.   }
  970.  
  971.   setTimeout("checkSearchProgress()", 1000);
  972. }
  973.  
  974. function saveSearch()
  975. {
  976.   var ds = document.getElementById("resultList").database;
  977.   if (!ds)
  978.     return;
  979.  
  980.   var lastSearchURI = "";
  981.   var lastSearchText = "";
  982.  
  983.   var rdf = Components.classes[RDFSERVICE_CONTRACTID].getService(nsIRDFService);
  984.   // look for last search URI
  985.   var source = rdf.GetResource("NC:LastSearchRoot", true);
  986.   var childProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#ref", true);
  987.   var target = ds.GetTarget(source, childProperty, true);
  988.   if (target) {
  989.     target = target.QueryInterface(nsIRDFLiteral).Value;
  990.     if (target)
  991.       lastSearchURI = target;
  992.   }
  993.  
  994.   // look for last search text
  995.   childProperty = rdf.GetResource("http://home.netscape.com/NC-rdf#LastText", true);
  996.   target = ds.GetTarget(source, childProperty, true);
  997.   if (target) {
  998.     target = target.QueryInterface(nsIRDFLiteral).Value;
  999.     if (target) {
  1000.       // convert plusses (+) back to spaces
  1001.       target = target.replace(/\+/g, " ");
  1002.       lastSearchText = decodeURI(target);
  1003.     }
  1004.   }
  1005.  
  1006.   if (!lastSearchURI)
  1007.     return;
  1008.  
  1009.   // rjc says: if lastSearchText is empty/null, that's still OK, synthesize the text
  1010.   if (!lastSearchText) {
  1011.     lastSearchText = lastSearchURI;
  1012.     var siteOffset = lastSearchText.indexOf("://");
  1013.     if (siteOffset > 0) {
  1014.       siteOffset += 3;
  1015.       var endOffset = lastSearchText.indexOf("/", siteOffset);
  1016.       if (endOffset > 0)
  1017.         lastSearchText = lastSearchText.substr(0, endOffset+1);
  1018.     }
  1019.   }
  1020.  
  1021.   var searchTitle = searchBundle.stringBundle.formatStringFromName(
  1022.                       "searchTitle", [lastSearchText], 1);
  1023.  
  1024.   var bmks = Components.classes[BMARKS_CONTRACTID].getService(nsIBookmarksService);
  1025.   bmks.addBookmarkImmediately(lastSearchURI, searchTitle, bmks.BOOKMARK_SEARCH_TYPE, null);
  1026. }
  1027.  
  1028. var gPageNumber = 0;
  1029. /**
  1030.  * showMoreResults
  1031.  *
  1032.  * Run a query to show the next/previous page of search results for the
  1033.  * current search term.
  1034.  * 
  1035.  * @param direction : -1 => previous
  1036.  *                     1 => next
  1037.  */
  1038. function showMoreResults(direction)
  1039. {
  1040.   // XXX check if we are in basic search mode
  1041.  
  1042.   // get search engine
  1043.   var engine = document.getElementById("basicEngineMenu").selectedItem;
  1044.   var engineURI = engine.id;
  1045.  
  1046.   // get search term
  1047.   var searchTerm = document.getElementById("sidebar-search-text").value;
  1048.   searchTerm = encodeURIComponent(searchTerm);
  1049.  
  1050.   // change page number
  1051.   if (direction > 0)
  1052.     ++gPageNumber;
  1053.   else
  1054.     --gPageNumber;
  1055.  
  1056.   // get qualified URL
  1057.   var searchService = Components.classes[ISEARCH_CONTRACTID].
  1058.                         getService(nsIInternetSearchService);
  1059.   var whichButtons = new Object;
  1060.   whichButtons.value = 0;
  1061.   var searchURL = searchService.GetInternetSearchURL(engineURI, searchTerm, 
  1062.                     direction, gPageNumber, whichButtons);
  1063.  
  1064.   doNavButtonEnabling(whichButtons.value, searchService, gPageNumber);
  1065.  
  1066.   // load URL in navigator
  1067.   loadURLInContent(searchURL);
  1068. }
  1069.  
  1070. function doNavButtonEnabling(whichButtons, searchService, pageNumber)
  1071. {
  1072.   var nextButton = document.getElementById("next-results");
  1073.   var nextDisabled = nextButton.getAttribute("disabled");
  1074.   var prevButton = document.getElementById("prev-results");
  1075.   var prevDisabled = prevButton.getAttribute("disabled");
  1076.  
  1077.   if (whichButtons & searchService.kHaveNext)
  1078.   {
  1079.     if (nextDisabled)
  1080.       nextButton.removeAttribute("disabled");
  1081.   }
  1082.   else 
  1083.   {
  1084.     if (!nextDisabled)
  1085.       nextButton.setAttribute("disabled", "true");
  1086.   }
  1087.   
  1088.   if ((pageNumber > 0) && (whichButtons & searchService.kHavePrev))
  1089.   {
  1090.     if (prevDisabled)
  1091.       prevButton.removeAttribute("disabled");
  1092.   }
  1093.   else 
  1094.   {
  1095.     if (!prevDisabled)
  1096.       prevButton.setAttribute("disabled", "true");
  1097.   }
  1098. }
  1099.  
  1100. function doCustomize()
  1101. {
  1102.   //Switching from Edit Categories back to All Engines then launching customize window
  1103.   var category = document.getElementById("categoryList");
  1104.   category.selectedIndex = 0;
  1105.   window.openDialog("chrome://browser/content/search/search-editor.xul", "internetsearch:editor", "centerscreen,chrome,resizable");
  1106. }
  1107.  
  1108. function loadURLInContent(url, suppressSearchService)
  1109. {
  1110.   getNavigatorWindow(true).SearchLoadURL(url);
  1111.     
  1112.     
  1113.   /*
  1114.   if(pref.getCharPref("browser.tabs.searchbarresult.open") == 'overwrite') {
  1115.     navigatorWindow.loadURI(url);
  1116.   } else { // else == 'new'
  1117.    
  1118.     // open link in new tab
  1119.     var browser = top.document.getElementById("content");
  1120.     var theTab = browser.addTabAt(url);
  1121.     if (!pref.getBoolPref("browser.tabs.loadInBackground"))
  1122.       browser.selectedTab = theTab;
  1123.  
  1124.   }
  1125.   var internetSearch = Components.classes[ISEARCH_CONTRACTID].getService(nsIInternetSearchService);
  1126.   internetSearch.FindInternetSearchResults(url);
  1127.   */
  1128. }
  1129.  
  1130. function search_getBrowserURL()
  1131. {
  1132.   return nsPreferences.copyUnicharPref("browser.chromeURL", "chrome://browser/content/browser.xul");
  1133. }
  1134.  
  1135. function doEnabling()
  1136. {
  1137.   var searchButton = document.getElementById("searchButton");
  1138.   var sidebarSearchText = document.getElementById("sidebar-search-text");
  1139.   searchButton.disabled = !sidebarSearchText.value;
  1140. }
  1141.  
  1142. //Step up the dom until getting the desired node.
  1143. function getItemNode(aNode,nodeName)
  1144. {
  1145.   var node = aNode;
  1146.   while (node.localName != nodeName) {
  1147.     node = node.parentNode;
  1148.   }
  1149.   return node ? node : null;
  1150. }
  1151.  
  1152. function getArcValueForID(aArc, aID)
  1153. {
  1154.   var val = null;
  1155.  
  1156.   try
  1157.   {
  1158.     var ds = document.getElementById("resultList").database;
  1159.     if (ds)
  1160.     {
  1161.       var rdf = Components.classes[RDFSERVICE_CONTRACTID].
  1162.                   getService(nsIRDFService);
  1163.       var src = rdf.GetResource(aID, true);
  1164.       var prop = rdf.GetResource(
  1165.                   "http://home.netscape.com/NC-rdf#"+aArc, true);
  1166.       val = ds.GetTarget(src, prop, true);        
  1167.       if (val)
  1168.         val = val.QueryInterface(nsIRDFLiteral).Value;
  1169.     }
  1170.   } 
  1171.   catch (ex)
  1172.   {
  1173.     dump("Exception: no value for " + aArc + "!\t" + ex + "\n");
  1174.     val = null;
  1175.   }
  1176.  
  1177.   return val;
  1178. }
  1179.  
  1180. //Fill in tooltip in teh search results panel
  1181. function FillInDescTooltip(tipElement)
  1182. {
  1183.   var retValue = false;
  1184.  
  1185.   //Get the Name of the listitem for first item in the tooltip
  1186.   var nodeLabel = tipElement.getAttribute("label");
  1187.   var nodeID = tipElement.id;
  1188.  
  1189.   //Query RDF to get URL of listitem
  1190.   if (nodeID)
  1191.     var url = getArcValueForID("URL", nodeID);
  1192.  
  1193.   //Fill in the the text nodes
  1194.   //collapse them if there is not a node
  1195.   if (nodeLabel || url) {
  1196.     var tooltipTitle = document.getElementById("titleText");
  1197.     var tooltipUrl = document.getElementById("urlText"); 
  1198.     if (nodeLabel) {
  1199.       if (tooltipTitle.getAttribute("hidden") == "true")
  1200.         tooltipTitle.removeAttribute("hidden");
  1201.       tooltipTitle.setAttribute("value",nodeLabel);
  1202.     } 
  1203.     else  {
  1204.       tooltipTitle.setAttribute("hidden", "true");
  1205.     }
  1206.     if (url) {
  1207.       if (tooltipUrl.getAttribute("hidden") == "true")
  1208.         tooltipUrl.removeAttribute("hidden");
  1209.       if (url.length > 100)
  1210.         url = url.substr(0,100) + "...";
  1211.       tooltipUrl.setAttribute("value",url);
  1212.     }
  1213.     else {
  1214.       tooltipUrl.setAttribute("hidden", "true");
  1215.     }
  1216.     retValue = true;
  1217.   }
  1218.   return retValue;
  1219. }
  1220.  
  1221. var nsResultDNDObserver = 
  1222. {
  1223.   onDragStart: function(aEvent, aXferData, aDragAction)
  1224.   {
  1225.     var node = getItemNode(aEvent.target, "listitem");
  1226.     var URL = getArcValueForID("URL", node.id);
  1227.     var title = getArcValueForID("Name", node.id);
  1228.     var htmlString = "<a href=\"" + URL + "\">" + title + "</a>";
  1229.     var urlString = URL + "\n" + title;
  1230.  
  1231.     aXferData.data = new TransferData();
  1232.     aXferData.data.addDataForFlavour("text/x-moz-url", URL);
  1233.     aXferData.data.addDataForFlavour("text/unicode", urlString);
  1234.     aXferData.data.addDataForFlavour("text/html", htmlString); 
  1235.   }
  1236. };
  1237.  
  1238. function HandleResultDragGesture(aEvent)
  1239. {
  1240.   nsDragAndDrop.startDrag(aEvent, nsResultDNDObserver);
  1241.   return true;  
  1242. }
  1243.  
  1244.