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