home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 March / PCWorld_2007-03_cd.bin / komunikace / nvu / nvu-1.0-cs-CZ.win32.installer.exe / chrome / helpcs.jar / content / help / help.js < prev    next >
Text File  |  2005-06-21  |  26KB  |  801 lines

  1.  
  2. var helpBrowser;
  3. var helpWindow;
  4. var helpSearchPanel;
  5. var emptySearch;
  6. var emptySearchText
  7. var emptySearchLink
  8. var helpTocPanel;
  9. var helpIndexPanel;
  10. var helpGlossaryPanel;
  11.  
  12. const NC = "http://home.netscape.com/NC-rdf#";
  13. const SN = "rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  14. const XML = "http://www.w3.org/XML/1998/namespace#"
  15. const MAX_LEVEL = 40; // maximum depth of recursion in search datasources.
  16. const MAX_HISTORY_MENU_ITEMS = 6;
  17.  
  18. const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  19.     .getService(Components.interfaces.nsIRDFService);
  20. const RDF_ROOT = RDF.GetResource("urn:root");
  21. const NC_PANELLIST = RDF.GetResource(NC + "panellist");
  22. const NC_PANELID = RDF.GetResource(NC + "panelid");
  23. const NC_EMPTY_SEARCH_TEXT = RDF.GetResource(NC + "emptysearchtext");
  24. const NC_EMPTY_SEARCH_LINK = RDF.GetResource(NC + "emptysearchlink");
  25. const NC_DATASOURCES = RDF.GetResource(NC + "datasources");
  26. const NC_SUBHEADINGS = RDF.GetResource(NC + "subheadings");
  27. const NC_NAME = RDF.GetResource(NC + "name");
  28. const NC_CHILD = RDF.GetResource(NC + "child");
  29. const NC_LINK = RDF.GetResource(NC + "link");
  30. const NC_TITLE = RDF.GetResource(NC + "title");
  31. const NC_BASE = RDF.GetResource(NC + "base");
  32. const NC_DEFAULTTOPIC = RDF.GetResource(NC + "defaulttopic");
  33.  
  34. const RDFCUtils = Components.classes["@mozilla.org/rdf/container-utils;1"]
  35.     .getService().QueryInterface(Components.interfaces.nsIRDFContainerUtils);
  36. const RDFContainer = Components.classes["@mozilla.org/rdf/container;1"]
  37.     .getService(Components.interfaces.nsIRDFContainer);
  38. const CONSOLE_SERVICE = Components.classes['@mozilla.org/consoleservice;1']
  39.     .getService(Components.interfaces.nsIConsoleService);
  40.  
  41. var urnID = 0;
  42. var RE;
  43.  
  44. var helpFileURI;
  45. var helpFileDS;
  46. var helpBaseURI;
  47.  
  48. const defaultHelpFile = "chrome://help/locale/help.rdf";
  49. const defaultTopic = "use-help";
  50. var searchDatasources = "rdf:null";
  51. var searchDS = null;
  52.  
  53. const NSRESULT_RDF_SYNTAX_ERROR = 0x804e03f7;
  54.  
  55. function displayTopic(topic) {
  56.     // Get the page to open.
  57.     var uri = getLink(topic);
  58.  
  59.     // Use default topic if specified topic is not found.
  60.     if (!uri) {
  61.         uri = getLink(defaultTopic);
  62.     }
  63.  
  64.     // Load the page.
  65.     loadURI(uri);
  66. }
  67.  
  68. function init() {
  69.     // Cache panel references.
  70.     helpWindow = document.getElementById("help");
  71.     helpSearchPanel = document.getElementById("help-search-panel");
  72.     helpTocPanel = document.getElementById("help-toc-panel");
  73.     helpIndexPanel = document.getElementById("help-index-panel");
  74.     helpGlossaryPanel = document.getElementById("help-glossary-panel");
  75.     helpBrowser = document.getElementById("help-content");
  76.  
  77.     // Get the content pack, base URL, and help topic
  78.     var helpTopic = defaultTopic;
  79.     if ("arguments" in window
  80.             && window.arguments[0]
  81.             instanceof Components.interfaces.nsIDialogParamBlock) {
  82.         helpFileURI = window.arguments[0].GetString(0);
  83.         // trailing "/" included.
  84.         helpBaseURI = helpFileURI.substring(0, helpFileURI.lastIndexOf("/")+1);
  85.         helpTopic = window.arguments[0].GetString(1);
  86.     }
  87.  
  88.     loadHelpRDF();
  89.     displayTopic(helpTopic);
  90.  
  91.     // Move to Center of Screen
  92.     const width = document.documentElement.getAttribute("width");
  93.     const height = document.documentElement.getAttribute("height");
  94.     window.moveTo((screen.availWidth - width) / 2, (screen.availHeight - height) / 2);
  95.  
  96.     // Initialize history.
  97.     getWebNavigation().sessionHistory = Components.classes["@mozilla.org/browser/shistory;1"]
  98.         .createInstance(Components.interfaces.nsISHistory);
  99.     window.XULBrowserWindow = new nsHelpStatusHandler();
  100.  
  101.     //Start the status handler.
  102.     window.XULBrowserWindow.init();
  103.  
  104.     // Hook up UI through Progress Listener
  105.     const interfaceRequestor = helpBrowser.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  106.     const webProgress = interfaceRequestor.getInterface(Components.interfaces.nsIWebProgress);
  107.  
  108.     webProgress.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  109.  
  110.     //Display the Table of Contents
  111.     showPanel("help-toc");
  112.  
  113.     // initialize the customizeDone method on the customizeable toolbar
  114.     var toolbox = document.getElementById("help-toolbox");
  115.     toolbox.customizeDone = ToolboxCustomizeDone;
  116.  
  117.     var toolbarset = document.getElementById("customToolbars");
  118.     toolbox.toolbarset = toolbarset;
  119.  
  120.     // Set the text of the sidebar toolbar button to "Hide Sidebar" taken the properties file.
  121.     // This is needed so that it says "Toggle Sidebar" in toolbar customization, but outside
  122.     // of it, it says either "Show Sidebar" or "Hide Sidebar".
  123.     document.getElementById("help-sidebar-button").label =
  124.            document.getElementById("bundle_help").getString("hideSidebarLabel");
  125. }
  126.  
  127. function loadHelpRDF() {
  128.     if (!helpFileDS) {
  129.         try {
  130.             helpFileDS = RDF.GetDataSourceBlocking(helpFileURI);
  131.         } catch (e if (e.result == NSRESULT_RDF_SYNTAX_ERROR)) {
  132.             log("Help file: " + helpFileURI + " contains a syntax error.");
  133.         } catch (e) {
  134.             log("Help file: " + helpFileURI + " was not found.");
  135.         }
  136.         try {
  137.             helpWindow.setAttribute("title",
  138.                 getAttribute(helpFileDS, RDF_ROOT, NC_TITLE, ""));
  139.             helpBaseURI = getAttribute(helpFileDS, RDF_ROOT, NC_BASE, helpBaseURI);
  140.             defaultTopic = getAttribute(helpFileDS,
  141.                 RDF_ROOT, NC_DEFAULTTOPIC, "welcome");
  142.  
  143.             var panelDefs = helpFileDS.GetTarget(RDF_ROOT, NC_PANELLIST, true);
  144.             RDFContainer.Init(helpFileDS, panelDefs);
  145.             var iterator = RDFContainer.GetElements();
  146.             while (iterator.hasMoreElements()) {
  147.                 var panelDef = iterator.getNext();
  148.                 var panelID = getAttribute(helpFileDS, panelDef, NC_PANELID,
  149.                     null);
  150.  
  151.                 var datasources = getAttribute(helpFileDS, panelDef,
  152.                     NC_DATASOURCES, "rdf:none");
  153.                 datasources = normalizeLinks(helpBaseURI, datasources);
  154.                 // Cache Additional Datasources to Augment Search Datasources.
  155.                 if (panelID == "search") {
  156.                     emptySearchText = getAttribute(helpFileDS, panelDef,
  157.                         NC_EMPTY_SEARCH_TEXT, null) || "No search items found.";
  158.                     emptySearchLink = getAttribute(helpFileDS, panelDef,
  159.                         NC_EMPTY_SEARCH_LINK, null) || "about:blank";
  160.                     searchDatasources = datasources;
  161.                     // Don't try to display them yet!
  162.                     datasources = "rdf:null";
  163.                 }
  164.  
  165.                 // Cache TOC Datasources for Use by ID Lookup.
  166.                 var tree = document.getElementById("help-" + panelID + "-panel");
  167.                 loadDatabasesBlocking(datasources);
  168.                 tree.setAttribute("datasources", datasources);
  169.             }
  170.         } catch (e) {
  171.             log(e + "");
  172.         }
  173.     }
  174. }
  175.  
  176. function loadDatabasesBlocking(datasources) {
  177.     var ds = datasources.split(/\s+/);
  178.     for (var i=0; i < ds.length; ++i) {
  179.         if (ds[i] == "rdf:null" || ds[i] == "")
  180.             continue;
  181.         try {
  182.             // We need blocking here to ensure the database is loaded so
  183.             // getLink(topic) works.
  184.             var datasource = RDF.GetDataSourceBlocking(ds[i]);
  185.         } catch (e) {
  186.             log("Datasource: " + ds[i] + " was not found.");
  187.         }
  188.     }
  189. }
  190.  
  191. function normalizeLinks(helpBaseURI, links) {
  192.     if (!helpBaseURI) {
  193.         return links;
  194.     }
  195.     var ls = links.split(/\s+/);
  196.     if (ls.length == 0) {
  197.         return links;
  198.     }
  199.     for (var i=0; i < ls.length; ++i) {
  200.         if (ls[i] == "") {
  201.             continue;
  202.         }
  203.         if (ls[i].substr(0,7) != "chrome:" && ls[i].substr(0,4) != "rdf:") {
  204.             ls[i] = helpBaseURI + ls[i];
  205.         }
  206.     }
  207.     return ls.join(" ");
  208. }
  209.  
  210. function getLink(ID) {
  211.     if (!ID) {
  212.         return null;
  213.     }
  214.     // Note resources are stored in fileURL#ID format.
  215.     // We have one possible source for an ID for each datasource in the
  216.     // composite datasource.
  217.     // The first ID which matches is returned.
  218.     var tocTree = document.getElementById("help-toc-panel");
  219.     var tocDS = tocTree.database;
  220.     if (tocDS == null) {
  221.         return null;
  222.     }
  223.     var tocDatasources = tocTree.getAttribute("datasources");
  224.     var ds = tocDatasources.split(/\s+/);
  225.     for (var i=0; i < ds.length; ++i) {
  226.         if (ds[i] == "rdf:null" || ds[i] == "") {
  227.             continue;
  228.         }
  229.         try {
  230.             var rdfID = ds[i] + "#" + ID;
  231.             var resource = RDF.GetResource(rdfID);
  232.             if (resource) {
  233.                 var link = tocDS.GetTarget(resource, NC_LINK, true);
  234.                 if (link) {
  235.                     link = link.QueryInterface(Components.interfaces
  236.                         .nsIRDFLiteral);
  237.                     if (link) {
  238.                         return link.Value;
  239.                     } else {
  240.                         return null;
  241.                     }
  242.                 }
  243.             }
  244.         } catch (e) {
  245.             log(rdfID + " " + e);
  246.         }
  247.     }
  248.     return null;
  249. }
  250.  
  251. function getHelpFileURI() {
  252.     return helpFileURI;
  253. }
  254.  
  255. function getBrowser() {
  256.   return helpBrowser;
  257. }
  258.  
  259. function getWebNavigation() {
  260.   try {
  261.     return helpBrowser.webNavigation;
  262.   } catch (e)
  263.   {
  264.     return null;
  265.   }
  266. }
  267.  
  268. function loadURI(uri) {
  269.     if (uri.substr(0,7) != "chrome:") {
  270.         uri = helpBaseURI + uri;
  271.     }
  272.     getWebNavigation().loadURI(uri, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE,
  273.         null, null, null);
  274. }
  275.  
  276. function goBack() {
  277.   try
  278.   {
  279.     getWebNavigation().goBack();
  280.   } catch (e)
  281.   {
  282.   }
  283. }
  284.  
  285. /* copied from browser.js */
  286. function BrowserReloadWithFlags(reloadFlags) {
  287.     /* First, we'll try to use the session history object to reload so 
  288.      * that framesets are handled properly. If we're in a special 
  289.      * window (such as view-source) that has no session history, fall 
  290.      * back on using the web navigation's reload method.
  291.      */
  292.  
  293.     var webNav = getWebNavigation();
  294.     try {
  295.       var sh = webNav.sessionHistory;
  296.       if (sh)
  297.         webNav = sh.QueryInterface(Components.interfaces.nsIWebNavigation);
  298.     } catch (e) {
  299.     }
  300.  
  301.     try {
  302.       webNav.reload(reloadFlags);
  303.     } catch (e) {
  304.     }
  305. }
  306.  
  307. function reload() {
  308.   const reloadFlags = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE;
  309.   return BrowserReloadWithFlags(reloadFlags);
  310. }
  311.  
  312. function goForward() {
  313.     try
  314.     {
  315.       getWebNavigation().goForward();
  316.     } catch(e)
  317.     {
  318.     }
  319. }
  320.  
  321. function goHome() {
  322.     // Load "Welcome" page
  323.     //loadURI("chrome://help/locale/firefox_welcome.xhtml");
  324.     loadURI("chrome://help/locale/welcome.xhtml");
  325. }
  326.  
  327. function print() {
  328.     try {
  329.         _content.print();
  330.     } catch (e) {
  331.     }
  332. }
  333.  
  334. function FillHistoryMenu(aParent, aMenu)
  335.   {
  336.     // Remove old entries if any
  337.     deleteHistoryItems(aParent);
  338.  
  339.     var sessionHistory = getWebNavigation().sessionHistory;
  340.  
  341.     var count = sessionHistory.count;
  342.     var index = sessionHistory.index;
  343.     var end;
  344.     var j;
  345.     var entry;
  346.  
  347.     switch (aMenu)
  348.       {
  349.         case "back":
  350.           end = (index > MAX_HISTORY_MENU_ITEMS) ? index - MAX_HISTORY_MENU_ITEMS : 0;
  351.           if ((index - 1) < end) return false;
  352.           for (j = index - 1; j >= end; j--)
  353.             {
  354.               entry = sessionHistory.getEntryAtIndex(j, false);
  355.               if (entry)
  356.                 createMenuItem(aParent, j, entry.title);
  357.             }
  358.           break;
  359.         case "forward":
  360.           end  = ((count-index) > MAX_HISTORY_MENU_ITEMS) ? index + MAX_HISTORY_MENU_ITEMS : count;
  361.           if ((index + 1) >= end) return false;
  362.           for (j = index + 1; j < end; j++)
  363.             {
  364.               entry = sessionHistory.getEntryAtIndex(j, false);
  365.               if (entry)
  366.                 createMenuItem(aParent, j, entry.title);
  367.             }
  368.           break;
  369.       }
  370.     return true;
  371.   }
  372.  
  373. function createMenuItem( aParent, aIndex, aLabel)
  374.   {
  375.     var menuitem = document.createElement( "menuitem" );
  376.     menuitem.setAttribute( "label", aLabel );
  377.     menuitem.setAttribute( "index", aIndex );
  378.     aParent.appendChild( menuitem );
  379.   }
  380.  
  381. function deleteHistoryItems(aParent)
  382. {
  383.   var children = aParent.childNodes;
  384.   for (var i = children.length - 1; i >= 0; --i)
  385.     {
  386.       var index = children[i].getAttribute("index");
  387.       if (index)
  388.         aParent.removeChild(children[i]);
  389.     }
  390. }
  391.  
  392. function createBackMenu(event) {
  393.     return FillHistoryMenu(event.target, "back");
  394. }
  395.  
  396. function createForwardMenu(event) {
  397.     return FillHistoryMenu(event.target, "forward");
  398. }
  399.  
  400. function gotoHistoryIndex(aEvent) {
  401.     var index = aEvent.target.getAttribute("index");
  402.     if (!index) {
  403.         return false;
  404.     }
  405.     try {
  406.         getWebNavigation().gotoIndex(index);
  407.     } catch(ex) {
  408.         return false;
  409.     }
  410.     return true;
  411. }
  412.  
  413. function nsHelpStatusHandler() {
  414.   this.init();
  415. }
  416.  
  417. nsHelpStatusHandler.prototype = {
  418.  
  419.     onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
  420.     {
  421.       const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  422.  
  423.       if (aStateFlags & nsIWebProgressListener.STATE_START) {
  424.         if (this.throbberElement)
  425.           this.throbberElement.setAttribute("busy", "true");
  426.       } else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
  427.         if (aRequest && this.throbberElement) {
  428.           this.throbberElement.removeAttribute("busy");
  429.         }
  430.       }
  431.     },
  432.     onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
  433.         aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
  434.     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
  435.     onSecurityChange : function(aWebProgress, aRequest, state) {},
  436.     onLocationChange : function(aWebProgress, aRequest, aLocation) {
  437.         UpdateBackForwardButtons();
  438.     },
  439.     QueryInterface : function(aIID) {
  440.         if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  441.                 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  442.                 aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
  443.                 aIID.equals(Components.interfaces.nsISupports)) {
  444.             return this;
  445.         }
  446.         throw Components.results.NS_NOINTERFACE;
  447.     },
  448.  
  449.     init : function()
  450.     {
  451.       this.throbberElement = document.getElementById("help-throbber");
  452.     },
  453.  
  454.     destroy : function()
  455.     {
  456.       //this needed to avoid memory leaks, see bug 60729
  457.       this.throbberElement = null;
  458.     },
  459.  
  460.     setJSStatus : function(status) {},
  461.     setJSDefaultStatus : function(status) {},
  462.     setOverLink : function(link) {}
  463. }
  464.  
  465. function UpdateBackForwardButtons() {
  466.     var backBroadcaster = document.getElementById("canGoBack");
  467.     var forwardBroadcaster = document.getElementById("canGoForward");
  468.     var webNavigation = getWebNavigation();
  469.  
  470.     // Avoid setting attributes on broadcasters if the value hasn't changed!
  471.     // Remember, guys, setting attributes on elements is expensive!  They
  472.     // get inherited into anonymous content, broadcast to other widgets, etc.!
  473.     // Don't do it if the value hasn't changed! - dwh
  474.  
  475.     var backDisabled = (backBroadcaster.getAttribute("disabled") == "true");
  476.     var forwardDisabled = (forwardBroadcaster.getAttribute("disabled") == "true");
  477.  
  478.     if (backDisabled == webNavigation.canGoBack) {
  479.       if (backDisabled)
  480.         backBroadcaster.removeAttribute("disabled");
  481.       else
  482.         backBroadcaster.setAttribute("disabled", true);
  483.     }
  484.  
  485.     if (forwardDisabled == webNavigation.canGoForward) {
  486.       if (forwardDisabled)
  487.         forwardBroadcaster.removeAttribute("disabled");
  488.       else
  489.         forwardBroadcaster.setAttribute("disabled", true);
  490.     }
  491. }
  492.  
  493. function getMarkupDocumentViewer() {
  494.     return helpBrowser.markupDocumentViewer;
  495. }
  496.  
  497. function showPanel(panelId) {
  498.     //hide other sidebar panels and show the panel name taken in.
  499.     helpSearchPanel.setAttribute("hidden", "true");
  500.     helpTocPanel.setAttribute("hidden", "true");
  501.     helpIndexPanel.setAttribute("hidden", "true");
  502.     helpGlossaryPanel.setAttribute("hidden", "true");
  503.     var thePanel = document.getElementById(panelId + "-panel");
  504.     thePanel.setAttribute("hidden","false");
  505.  
  506.     //remove the selected style from the previous panel selected.
  507.     var theButton = document.getElementById(panelId + "-btn");
  508.     document.getElementById("help-glossary-btn").removeAttribute("selected");
  509.     document.getElementById("help-index-btn").removeAttribute("selected");
  510.     document.getElementById("help-search-btn").removeAttribute("selected");
  511.     document.getElementById("help-toc-btn").removeAttribute("selected");
  512.     //add the selected style to the correct panel.
  513.     theButton.setAttribute("selected", "true");
  514.  
  515.     //focus the searchbox if the search sidebar panel is shown.
  516.     if (panelId == "help-search")
  517.       document.getElementById("findText").focus();
  518. }
  519.  
  520. function findParentNode(node, parentNode)
  521. {
  522.   if (node && node.nodeType == Node.TEXT_NODE) {
  523.     node = node.parentNode;
  524.   }
  525.   while (node) {
  526.     var nodeName = node.localName;
  527.     if (!nodeName)
  528.       return null;
  529.     nodeName = nodeName.toLowerCase();
  530.     if (nodeName == "body" || nodeName == "html" ||
  531.         nodeName == "#document") {
  532.       return null;
  533.     }
  534.     if (nodeName == parentNode)
  535.       return node;
  536.     node = node.parentNode;
  537.   }
  538.   return null;
  539. }
  540.  
  541. function onselect_loadURI(tree) {
  542.     try {
  543.         var resource = tree.view.getResourceAtIndex(tree.currentIndex);
  544.     var link = tree.database.GetTarget(resource, NC_LINK, true);
  545.     if (link) {
  546.             link = link.QueryInterface(Components.interfaces.nsIRDFLiteral);
  547.             loadURI(link.Value);
  548.         }
  549.     } catch (e) {
  550.     }// when switching between tabs a spurious row number is returned.
  551. }
  552.  
  553. function doFind() {
  554.     var searchTree = document.getElementById("help-search-tree");
  555.     var findText = document.getElementById("findText");
  556.  
  557.     // clear any previous results.
  558.     clearDatabases(searchTree.database);
  559.  
  560.     // split search string into separate terms and compile into regexp's
  561.     RE = findText.value.split(/\s+/);
  562.     for (var i=0; i < RE.length; ++i) {
  563.         if (RE[i] == "")
  564.             continue;
  565.  
  566.         RE[i] = new RegExp(RE[i], "i");
  567.     }
  568.     emptySearch = true;
  569.     // search TOC
  570.     var resultsDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
  571.         .createInstance(Components.interfaces.nsIRDFDataSource);
  572.     var tree = helpTocPanel;
  573.     var sourceDS = tree.database;
  574.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  575.  
  576.     // search glossary.
  577.     tree = helpGlossaryPanel;
  578.     sourceDS = tree.database;
  579.     // If the glossary has never been displayed this will be null (sigh!).
  580.     if (!sourceDS)
  581.         sourceDS = loadCompositeDS(tree.datasources);
  582.  
  583.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  584.  
  585.     // search index
  586.     tree = helpIndexPanel;
  587.     sourceDS = tree.database;
  588.     //If the index has never been displayed this will be null
  589.     if (!sourceDS)
  590.       sourceDS = loadCompositeDS(tree.datasources);
  591.  
  592.     doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
  593.  
  594.     if (emptySearch)
  595.         assertSearchEmpty(resultsDS);
  596.     // Add the datasource to the search tree
  597.     searchTree.database.AddDataSource(resultsDS);
  598.     searchTree.builder.rebuild();
  599. }
  600.  
  601. function doEnabling() {
  602.     var findButton = document.getElementById("findButton");
  603.     var findTextbox = document.getElementById("findText");
  604.     findButton.disabled = !findTextbox.value;
  605. }
  606.  
  607. function clearDatabases(compositeDataSource) {
  608.     var enumDS = compositeDataSource.GetDataSources()
  609.     while (enumDS.hasMoreElements()) {
  610.         var ds = enumDS.getNext();
  611.         compositeDataSource.RemoveDataSource(ds);
  612.     }
  613. }
  614.  
  615. function doFindOnDatasource(resultsDS, sourceDS, resource, level) {
  616.     if (level > MAX_LEVEL) {
  617.         try {
  618.             log("Recursive reference to resource: " + resource.Value + ".");
  619.         } catch (e) {
  620.             log("Recursive reference to unknown resource.");
  621.         }
  622.         return;
  623.     }
  624.     // find all SUBHEADING children of current resource.
  625.     var targets = sourceDS.GetTargets(resource, NC_SUBHEADINGS, true);
  626.     while (targets.hasMoreElements()) {
  627.         var target = targets.getNext();
  628.         target = target.QueryInterface(Components.interfaces.nsIRDFResource);
  629.         // The first child of a rdf:subheading should (must) be a rdf:seq.
  630.         // Should we test for a SEQ here?
  631.         doFindOnSeq(resultsDS, sourceDS, target, level+1);
  632.     }
  633. }
  634.  
  635. function doFindOnSeq(resultsDS, sourceDS, resource, level) {
  636.     // load up an RDFContainer so we can access the contents of the current
  637.     // rdf:seq.
  638.     RDFContainer.Init(sourceDS, resource);
  639.     var targets = RDFContainer.GetElements();
  640.     while (targets.hasMoreElements()) {
  641.         var target = targets.getNext();
  642.         target = target.QueryInterface(Components.interfaces.nsIRDFResource);
  643.         var name = sourceDS.GetTarget(target, NC_NAME, true);
  644.         name = name.QueryInterface(Components.interfaces.nsIRDFLiteral);
  645.  
  646.         if (isMatch(name.Value)) {
  647.             // we have found a search entry - add it to the results datasource.
  648.  
  649.             // Get URL of html for this entry.
  650.             var link = sourceDS.GetTarget(target, NC_LINK, true);
  651.             link = link.QueryInterface(Components.interfaces.nsIRDFLiteral);
  652.  
  653.             urnID++;
  654.             resultsDS.Assert(RDF_ROOT,
  655.                 RDF.GetResource("http://home.netscape.com/NC-rdf#child"),
  656.                 RDF.GetResource("urn:" + urnID),
  657.                 true);
  658.             resultsDS.Assert(RDF.GetResource("urn:" + urnID),
  659.                  RDF.GetResource("http://home.netscape.com/NC-rdf#name"),
  660.                  name,
  661.                  true);
  662.              resultsDS.Assert(RDF.GetResource("urn:" + urnID),
  663.                 RDF.GetResource("http://home.netscape.com/NC-rdf#link"),
  664.                 link,
  665.                 true);
  666.             emptySearch = false;
  667.         }
  668.         // process any nested rdf:seq elements.
  669.         doFindOnDatasource(resultsDS, sourceDS, target, level+1);
  670.     }
  671. }
  672.  
  673. function assertSearchEmpty(resultsDS) {
  674.     var resSearchEmpty = RDF.GetResource("urn:emptySearch");
  675.     resultsDS.Assert(RDF_ROOT,
  676.         NC_CHILD,
  677.         resSearchEmpty,
  678.         true);
  679.     resultsDS.Assert(resSearchEmpty,
  680.         NC_NAME,
  681.         RDF.GetLiteral(emptySearchText),
  682.         true);
  683.     resultsDS.Assert(resSearchEmpty,
  684.         NC_LINK,
  685.         RDF.GetLiteral(emptySearchLink),
  686.         true);
  687. }
  688.  
  689. function isMatch(text) {
  690.     for (var i=0; i < RE.length; ++i ) {
  691.         if (!RE[i].test(text)) {
  692.             return false;
  693.         }
  694.     }
  695.     return true;
  696. }
  697.  
  698. function loadCompositeDS(datasources) {
  699.     var compositeDS =  Components.classes["@mozilla.org/rdf/datasource;1?name=composite-datasource"]
  700.         .createInstance(Components.interfaces.nsIRDFCompositeDataSource);
  701.  
  702.     var ds = datasources.split(/\s+/);
  703.     for (var i=0; i < ds.length; ++i) {
  704.         if (ds[i] == "rdf:null" || ds[i] == "") {
  705.             continue;
  706.         }
  707.         try {
  708.             // we need blocking here to ensure the database is loaded.
  709.             var sourceDS = RDF.GetDataSourceBlocking(ds[i]);
  710.             compositeDS.AddDataSource(sourceDS);
  711.         } catch (e) {
  712.             log("Datasource: " + ds[i] + " was not found.");
  713.         }
  714.     }
  715.     return compositeDS;
  716. }
  717.  
  718. function getAttribute(datasource, resource, attributeResourceName,
  719.         defaultValue) {
  720.     var literal = datasource.GetTarget(resource, attributeResourceName, true);
  721.     if (!literal) {
  722.         return defaultValue;
  723.     }
  724.     return getLiteralValue(literal, defaultValue);
  725. }
  726.  
  727. function getLiteralValue(literal, defaultValue) {
  728.     if (literal) {
  729.         literal = literal.QueryInterface(Components.interfaces.nsIRDFLiteral);
  730.         if (literal) {
  731.             return literal.Value;
  732.         }
  733.     }
  734.     if (defaultValue) {
  735.         return defaultValue;
  736.     }
  737.     return null;
  738. }
  739.  
  740. function log(aText) {
  741.     CONSOLE_SERVICE.logStringMessage(aText);
  742. }
  743.  
  744. function expandAllIndexEntries() {
  745.     var treeview = helpIndexPanel.view;
  746.     var i = treeview.rowCount;
  747.     while (i--) {
  748.         if (!treeview.getLevel(i) && !treeview.isContainerOpen(i)) {
  749.             treeview.toggleOpenState(i);
  750.         }
  751.     }
  752. }
  753.  
  754. function toggleSidebar()
  755. {
  756.     var sidebar = document.getElementById("helpsidebar-box");
  757.     var separator = document.getElementById("helpsidebar-splitter");
  758.     var sidebarButton = document.getElementById("help-sidebar-button");
  759.  
  760.     //Use the string bundle to retrieve the text "Hide Sidebar"
  761.     //and "Show Sidebar" from the locale directory.
  762.     var strBundle = document.getElementById("bundle_help");
  763.     if (sidebar.hidden) {
  764.       sidebar.removeAttribute("hidden");
  765.       sidebarButton.label = strBundle.getString("hideSidebarLabel");
  766.  
  767.       separator.removeAttribute("hidden");
  768.     } else {
  769.       sidebar.setAttribute("hidden","true");
  770.       sidebarButton.label = strBundle.getString("showSidebarLabel");
  771.  
  772.       separator.setAttribute("hidden","true");
  773.     }
  774. }
  775.  
  776. // Shows the panel relative to the currently selected panel.
  777. // Takes a boolean parameter - if true it will show the next panel, 
  778. // otherwise it will show the previous panel.
  779. function showRelativePanel(goForward) {
  780.   var selectedIndex = -1;
  781.   var sidebarBox = document.getElementById("helpsidebar-box");
  782.   var sidebarButtons = new Array();
  783.   for (var i = 0; i < sidebarBox.childNodes.length; i++) {
  784.     var btn = sidebarBox.childNodes[i];
  785.     if (btn.nodeName == "toolbarbutton") {
  786.       if (btn.getAttribute("selected") == "true")
  787.         selectedIndex = sidebarButtons.length;
  788.       sidebarButtons.push(btn);
  789.     }
  790.   }
  791.   if (selectedIndex == -1)
  792.     return;
  793.   selectedIndex += goForward ? 1 : -1;
  794.   if (selectedIndex >= sidebarButtons.length)
  795.     selectedIndex = 0;
  796.   else if (selectedIndex < 0)
  797.     selectedIndex = sidebarButtons.length - 1;
  798.   sidebarButtons[selectedIndex].doCommand();
  799. }
  800.  
  801.