toolkit/components/help/content/help.js

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:eca6d558febf
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 # Global Variables
6 var helpBrowser;
7 var helpSearchPanel;
8 var emptySearch;
9 var emptySearchText;
10 var emptySearchLink = "about:blank";
11 var helpTocPanel;
12 var helpIndexPanel;
13 var helpGlossaryPanel;
14 var strBundle;
15 var gTocDSList = "";
16
17 # Namespaces
18 const NC = "http://home.netscape.com/NC-rdf#";
19 const MAX_LEVEL = 40; // maximum depth of recursion in search datasources.
20 const MAX_HISTORY_MENU_ITEMS = 6;
21
22 # ifdef logic ripped from toolkit/components/help/content/platformClasses.css
23 #ifdef XP_WIN
24 const platform = "win";
25 #else
26 #ifdef XP_MACOSX
27 const platform = "mac";
28 #else
29 const platform = "unix";
30 #endif
31 #endif
32
33 # Resources
34 const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
35 .getService(Components.interfaces.nsIRDFService);
36 const RDF_ROOT = RDF.GetResource("urn:root");
37 const NC_PANELLIST = RDF.GetResource(NC + "panellist");
38 const NC_PANELID = RDF.GetResource(NC + "panelid");
39 const NC_EMPTY_SEARCH_TEXT = RDF.GetResource(NC + "emptysearchtext");
40 const NC_EMPTY_SEARCH_LINK = RDF.GetResource(NC + "emptysearchlink");
41 const NC_DATASOURCES = RDF.GetResource(NC + "datasources");
42 const NC_PLATFORM = RDF.GetResource(NC + "platform");
43 const NC_SUBHEADINGS = RDF.GetResource(NC + "subheadings");
44 const NC_NAME = RDF.GetResource(NC + "name");
45 const NC_CHILD = RDF.GetResource(NC + "child");
46 const NC_LINK = RDF.GetResource(NC + "link");
47 const NC_TITLE = RDF.GetResource(NC + "title");
48 const NC_BASE = RDF.GetResource(NC + "base");
49 const NC_DEFAULTTOPIC = RDF.GetResource(NC + "defaulttopic");
50
51 var RDFContainer =
52 Components.classes["@mozilla.org/rdf/container;1"]
53 .createInstance(Components.interfaces.nsIRDFContainer);
54 const CONSOLE_SERVICE = Components.classes['@mozilla.org/consoleservice;1']
55 .getService(Components.interfaces.nsIConsoleService);
56
57 var RE;
58
59 var helpFileURI;
60 var helpFileDS;
61 # Set from nc:base attribute on help rdf file. It may be used for prefix
62 # reduction on all links within the current help set.
63 var helpBaseURI;
64
65 /* defaultTopic is either set
66 1. in the openHelp() call, passed as an argument to the Help window and
67 evaluated in init(), or
68 2. in nc:defaulttopic in the content pack (e.g. firebirdhelp.rdf),
69 evaluated in loadHelpRDF(), or
70 3. "welcome" as a fallback, specified in loadHelpRDF() as well;
71 displayTopic() then uses defaultTopic because topic is null. */
72 var defaultTopic;
73
74 const NSRESULT_RDF_SYNTAX_ERROR = 0x804e03f7;
75
76 # This function is called by dialogs/windows that want to display
77 # context-sensitive help
78 # These dialogs/windows should include the script
79 # chrome://help/content/contextHelp.js
80 function displayTopic(topic) {
81 // Get the page to open.
82 var uri = getLink(topic);
83 // Use default topic if specified topic is not found.
84 if (!uri) {
85 uri = getLink(defaultTopic);
86 }
87 // Load the page.
88 if (uri)
89 loadURI(uri);
90 }
91
92 # Initialize the Help window
93 function init() {
94 // Cache panel references.
95 helpSearchPanel = document.getElementById("help-search-panel");
96 helpTocPanel = document.getElementById("help-toc-panel");
97 helpIndexPanel = document.getElementById("help-index-panel");
98 helpGlossaryPanel = document.getElementById("help-glossary-panel");
99 helpBrowser = document.getElementById("help-content");
100
101 // Turn off unnecessary features for security
102 helpBrowser.docShell.allowJavascript = false;
103 helpBrowser.docShell.allowPlugins = false;
104 helpBrowser.docShell.allowSubframes = false;
105 helpBrowser.docShell.allowMetaRedirects = false;
106
107 strBundle = document.getElementById("bundle_help");
108 emptySearchText = strBundle.getString("emptySearchText");
109
110 // Get the content pack, base URL, and help topic
111 var helpTopic = defaultTopic;
112 if ("arguments" in window &&
113 window.arguments[0] instanceof Components.interfaces.nsIDialogParamBlock) {
114 helpFileURI = window.arguments[0].GetString(0);
115 // trailing "/" included.
116 helpBaseURI = helpFileURI.substring(0, helpFileURI.lastIndexOf("/")+1);
117 helpTopic = window.arguments[0].GetString(1);
118 }
119
120 loadHelpRDF();
121 displayTopic(helpTopic);
122
123 // Move to Center of Screen
124 const width = document.documentElement.getAttribute("width");
125 const height = document.documentElement.getAttribute("height");
126 window.moveTo((screen.availWidth - width) / 2, (screen.availHeight - height) / 2);
127
128 // Initialize history.
129 getWebNavigation().sessionHistory =
130 Components.classes["@mozilla.org/browser/shistory;1"]
131 .createInstance(Components.interfaces.nsISHistory);
132 window.XULBrowserWindow = new nsHelpStatusHandler();
133
134 //Start the status handler.
135 window.XULBrowserWindow.init();
136
137 // Hook up UI through Progress Listener
138 const interfaceRequestor = helpBrowser.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
139 const webProgress = interfaceRequestor.getInterface(Components.interfaces.nsIWebProgress);
140
141 webProgress.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
142
143 var searchBox = document.getElementById("findText");
144 searchBox.clickSelectsAll = getBoolPref("browser.urlbar.clickSelectsAll", true);
145
146 setTimeout(focusSearch, 0);
147 }
148
149 function showSearchSidebar() {
150 // if you tab too quickly, you end up with stuck focus, revert focus to the searchbar
151 var searchTree = document.getElementById("help-toc-panel");
152 if (searchTree.treeBoxObject.focused) {
153 focusSearch();
154 }
155
156 var tableOfContents = document.getElementById("help-toc-sidebar");
157 tableOfContents.setAttribute("hidden", "true");
158
159 var sidebar = document.getElementById("help-search-sidebar");
160 sidebar.removeAttribute("hidden");
161 }
162
163 function hideSearchSidebar(aEvent) {
164 // if we're focused in the search results, focus content
165 var searchTree = document.getElementById("help-search-tree");
166 if (searchTree.treeBoxObject.focused) {
167 content.focus();
168 }
169
170 var sidebar = document.getElementById("help-search-sidebar");
171 sidebar.setAttribute("hidden", "true");
172
173 var tableOfContents = document.getElementById("help-toc-sidebar");
174 tableOfContents.removeAttribute("hidden");
175 }
176
177 # loadHelpRDF
178 # Parse the provided help content pack RDF file, and use it to
179 # populate the datasources attached to the trees in the viewer.
180 # Filter out any information not applicable to the user's platform.
181 function loadHelpRDF() {
182 if (!helpFileDS) {
183 try {
184 helpFileDS = RDF.GetDataSourceBlocking(helpFileURI);
185 } catch (e if (e.result == NSRESULT_RDF_SYNTAX_ERROR)) {
186 log("Help file: " + helpFileURI + " contains a syntax error.");
187 } catch (e) {
188 log("Help file: " + helpFileURI + " was not found.");
189 }
190
191 try {
192 document.title = getAttribute(helpFileDS, RDF_ROOT, NC_TITLE, "");
193 helpBaseURI = getAttribute(helpFileDS, RDF_ROOT, NC_BASE, helpBaseURI);
194 // if there's no nc:defaulttopic in the content pack, set "welcome"
195 // as the default topic
196 defaultTopic = getAttribute(helpFileDS,
197 RDF_ROOT, NC_DEFAULTTOPIC, "welcome");
198
199 var panelDefs = helpFileDS.GetTarget(RDF_ROOT, NC_PANELLIST, true);
200 RDFContainer.Init(helpFileDS, panelDefs);
201 var iterator = RDFContainer.GetElements();
202 while (iterator.hasMoreElements()) {
203 var panelDef = iterator.getNext();
204
205 var panelID = getAttribute(helpFileDS, panelDef, NC_PANELID, null);
206 var datasources = getAttribute(helpFileDS, panelDef, NC_DATASOURCES, "");
207 var panelPlatforms = getAttribute(helpFileDS, panelDef, NC_PLATFORM, null);
208
209 if (panelPlatforms && panelPlatforms.split(/\s+/).indexOf(platform) == -1)
210 continue; // ignore datasources for other platforms
211
212 // empty datasources are valid on search panel definitions
213 // convert them to "rdf:null" which can be filtered and ignored
214 if (!datasources)
215 datasources = "rdf:null";
216
217 datasources = normalizeLinks(helpBaseURI, datasources);
218
219 var datasourceArray = datasources.split(/\s+/)
220 .filter(function(x) { return x != "rdf:null"; })
221 .map(RDF.GetDataSourceBlocking);
222
223 // Cache Additional Datasources to Augment Search Datasources.
224 if (panelID == "search") {
225 emptySearchText = getAttribute(helpFileDS, panelDef, NC_EMPTY_SEARCH_TEXT, emptySearchText);
226 emptySearchLink = getAttribute(helpFileDS, panelDef, NC_EMPTY_SEARCH_LINK, emptySearchLink);
227
228 datasourceArray.forEach(helpSearchPanel.database.AddDataSource,
229 helpSearchPanel.database);
230 if (!panelPlatforms)
231 filterDatasourceByPlatform(helpSearchPanel.database);
232
233 continue; // to next panel definition
234 }
235
236 // cache toc datasources list for use in getLink()
237 if (panelID == "toc")
238 gTocDSList += " " + datasources;
239
240 var tree = document.getElementById("help-" + panelID + "-panel");
241
242 // add each datasource to the current tree
243 datasourceArray.forEach(tree.database.AddDataSource,
244 tree.database);
245
246 // filter and display the current tree
247 if (!panelPlatforms)
248 filterDatasourceByPlatform(tree.database);
249 tree.builder.rebuild();
250 }
251 } catch (e) {
252 log(e + "");
253 }
254 }
255 }
256
257 # filterDatasourceByPlatform
258 # Remove statements for other platforms from a datasource.
259 function filterDatasourceByPlatform(aDatasource) {
260 filterNodeByPlatform(aDatasource, RDF_ROOT, 0);
261 }
262
263 # filterNodeByPlatform
264 # Remove statements for other platforms from the provided datasource.
265 function filterNodeByPlatform(aDatasource, aCurrentResource, aCurrentLevel) {
266 if (aCurrentLevel > MAX_LEVEL) {
267 log("Datasources over " + MAX_LEVEL + " levels deep are unsupported.");
268 return;
269 }
270
271 // get the subheadings under aCurrentResource and filter them
272 var nodes = aDatasource.GetTargets(aCurrentResource, NC_SUBHEADINGS, true);
273 while (nodes.hasMoreElements()) {
274 var node = nodes.getNext();
275 node = node.QueryInterface(Components.interfaces.nsIRDFResource);
276 // should we test for rdf:Seq here? see also doFindOnDatasource
277 filterSeqByPlatform(aDatasource, node, aCurrentLevel+1);
278 }
279 }
280
281 # filterSeqByPlatform
282 # Go through the children of aNode, if any, removing statements applicable
283 # only on other platforms.
284 function filterSeqByPlatform(aDatasource, aNode, aCurrentLevel) {
285 // get nc:subheading children into an enumerator
286 var RDFC = Components.classes["@mozilla.org/rdf/container;1"]
287 .createInstance(Components.interfaces.nsIRDFContainer);
288 RDFC.Init(aDatasource, aNode);
289 var targets = RDFC.GetElements();
290
291 // process items in the rdf:Seq
292 while (targets.hasMoreElements()) {
293 var currentTarget = targets.getNext();
294
295 // find out on which platforms this node is meaningful
296 var nodePlatforms = getAttribute(aDatasource,
297 currentTarget.QueryInterface(Components.interfaces.nsIRDFResource),
298 NC_PLATFORM,
299 platform);
300
301 if (nodePlatforms.split(/\s+/).indexOf(platform) == -1) { // node is for another platform
302 var currentNode = currentTarget.QueryInterface(Components.interfaces.nsIRDFNode);
303 // "false" because we don't want to renumber elements in the container
304 RDFC.RemoveElement(currentNode, false);
305
306 // move to next node - ignore the children, because 1) they might be
307 // needed elsewhere and 2) nodes not connected to RDF_ROOT are ignored
308 continue;
309 }
310
311 // filter any children
312 filterNodeByPlatform(aDatasource, currentTarget, aCurrentLevel+1);
313 }
314 }
315
316 # Prepend helpBaseURI to list of space separated links if they don't start with
317 # "chrome:"
318 function normalizeLinks(helpBaseURI, links) {
319 if (!helpBaseURI) {
320 return links;
321 }
322 var ls = links.split(/\s+/);
323 if (ls.length == 0) {
324 return links;
325 }
326 for (var i=0; i < ls.length; ++i) {
327 if (ls[i] == "")
328 continue;
329
330 if (ls[i].substr(0,7) != "chrome:" && ls[i].substr(0,4) != "rdf:")
331 ls[i] = helpBaseURI + ls[i];
332 }
333 return ls.join(" ");
334 }
335
336 function getLink(ID) {
337 if (!ID)
338 return null;
339
340 var tocDS = document.getElementById("help-toc-panel").database;
341 if (!tocDS)
342 return null;
343
344 // URIs include both the ID part and the base file name,
345 // so we need to check for a matching ID in each datasource
346 var tocDSArray = gTocDSList.split(/\s+/)
347 .filter(function(x) { return x != "rdf:null"; });
348
349 for (var i = 0; i < tocDSArray.length; i++) {
350 var resource = RDF.GetResource(tocDSArray[i] + "#" + ID);
351 var link = tocDS.GetTarget(resource, NC_LINK, true);
352 if (!link) // no such rdf:ID found
353 continue;
354 return link.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
355 }
356 return null;
357 }
358
359 # Called by contextHelp.js to determine if this window is displaying the
360 # requested help file.
361 function getHelpFileURI() {
362 return helpFileURI;
363 }
364
365 function getBrowser() {
366 return helpBrowser;
367 }
368
369 function getWebNavigation() {
370 try {
371 return helpBrowser.webNavigation;
372 } catch (e)
373 {
374 return null;
375 }
376 }
377
378 function loadURI(uri) {
379 if (uri.substr(0,7) != "chrome:") {
380 uri = helpBaseURI + uri;
381 }
382 getWebNavigation().loadURI(uri, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE,
383 null, null, null);
384 }
385
386 function goBack() {
387 try
388 {
389 getWebNavigation().goBack();
390 } catch (e)
391 {
392 }
393 }
394
395 function goForward() {
396 try
397 {
398 getWebNavigation().goForward();
399 } catch(e)
400 {
401 }
402 }
403
404 function goHome() {
405 // Load "Welcome" page
406 displayTopic(defaultTopic);
407 }
408
409 function print() {
410 try {
411 _content.print();
412 } catch (e) {
413 }
414 }
415
416 function FillHistoryMenu(aParent, aMenu)
417 {
418 // Remove old entries if any
419 deleteHistoryItems(aParent);
420
421 var sessionHistory = getWebNavigation().sessionHistory;
422
423 var count = sessionHistory.count;
424 var index = sessionHistory.index;
425 var end;
426 var j;
427 var entry;
428
429 switch (aMenu)
430 {
431 case "back":
432 end = (index > MAX_HISTORY_MENU_ITEMS) ? index - MAX_HISTORY_MENU_ITEMS : 0;
433 if ((index - 1) < end) return false;
434 for (j = index - 1; j >= end; j--)
435 {
436 entry = sessionHistory.getEntryAtIndex(j, false);
437 if (entry)
438 createMenuItem(aParent, j, entry.title);
439 }
440 break;
441 case "forward":
442 end = ((count-index) > MAX_HISTORY_MENU_ITEMS) ? index + MAX_HISTORY_MENU_ITEMS : count - 1;
443 if ((index + 1) > end) return false;
444 for (j = index + 1; j <= end; j++)
445 {
446 entry = sessionHistory.getEntryAtIndex(j, false);
447 if (entry)
448 createMenuItem(aParent, j, entry.title);
449 }
450 break;
451 }
452 return true;
453 }
454
455 function createMenuItem( aParent, aIndex, aLabel)
456 {
457 var menuitem = document.createElement( "menuitem" );
458 menuitem.setAttribute( "label", aLabel );
459 menuitem.setAttribute( "index", aIndex );
460 aParent.appendChild( menuitem );
461 }
462
463 function deleteHistoryItems(aParent)
464 {
465 var children = aParent.childNodes;
466 for (var i = children.length - 1; i >= 0; --i)
467 {
468 var index = children[i].getAttribute("index");
469 if (index)
470 aParent.removeChild(children[i]);
471 }
472 }
473
474 function createBackMenu(event) {
475 return FillHistoryMenu(event.target, "back");
476 }
477
478 function createForwardMenu(event) {
479 return FillHistoryMenu(event.target, "forward");
480 }
481
482 function gotoHistoryIndex(aEvent) {
483 var index = aEvent.target.getAttribute("index");
484 if (!index) {
485 return false;
486 }
487 try {
488 getWebNavigation().gotoIndex(index);
489 } catch(ex) {
490 return false;
491 }
492 return true;
493 }
494
495 function nsHelpStatusHandler() {
496 this.init();
497 }
498
499 nsHelpStatusHandler.prototype = {
500
501 onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {},
502 onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
503 aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
504 onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
505 onSecurityChange : function(aWebProgress, aRequest, state) {},
506 onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {
507 UpdateBackForwardButtons();
508 },
509 QueryInterface : function(aIID) {
510 if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
511 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
512 aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
513 aIID.equals(Components.interfaces.nsISupports)) {
514 return this;
515 }
516 throw Components.results.NS_NOINTERFACE;
517 },
518
519 init : function() {},
520
521 destroy : function() {},
522
523 setJSStatus : function(status) {},
524 setOverLink : function(link, context) {},
525 onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {}
526 }
527
528 function UpdateBackForwardButtons() {
529 var backBroadcaster = document.getElementById("canGoBack");
530 var forwardBroadcaster = document.getElementById("canGoForward");
531 var webNavigation = getWebNavigation();
532
533 // Avoid setting attributes on broadcasters if the value hasn't changed!
534 // Remember, guys, setting attributes on elements is expensive! They
535 // get inherited into anonymous content, broadcast to other widgets, etc.!
536 // Don't do it if the value hasn't changed! - dwh
537
538 var backDisabled = (backBroadcaster.getAttribute("disabled") == "true");
539 var forwardDisabled = (forwardBroadcaster.getAttribute("disabled") == "true");
540
541 if (backDisabled == webNavigation.canGoBack) {
542 if (backDisabled)
543 backBroadcaster.removeAttribute("disabled");
544 else
545 backBroadcaster.setAttribute("disabled", true);
546 }
547
548 if (forwardDisabled == webNavigation.canGoForward) {
549 if (forwardDisabled)
550 forwardBroadcaster.removeAttribute("disabled");
551 else
552 forwardBroadcaster.setAttribute("disabled", true);
553 }
554 }
555
556 function onselect_loadURI(tree) {
557 try {
558 var resource = tree.view.getResourceAtIndex(tree.currentIndex);
559 var link = tree.database.GetTarget(resource, NC_LINK, true);
560 if (link) {
561 link = link.QueryInterface(Components.interfaces.nsIRDFLiteral);
562 loadURI(link.Value);
563 }
564 } catch (e) {
565 }// when switching between tabs a spurious row number is returned.
566 }
567
568 function focusSearch() {
569 var searchBox = document.getElementById("findText");
570 searchBox.focus();
571 }
572
573 # doFind - Searches the help files for what is located in findText and outputs into
574 # the find search tree.
575 function doFind() {
576 if (document.getElementById("help-search-sidebar").hidden)
577 showSearchSidebar();
578
579 var searchTree = document.getElementById("help-search-tree");
580 var findText = document.getElementById("findText");
581
582 // clear any previous results.
583 clearDatabases(searchTree.database);
584
585 // if the search string is empty or contains only whitespace, purge the results tree and return
586 RE = findText.value.match(/\S+/g);
587 if (!RE) {
588 searchTree.builder.rebuild();
589 hideSearchSidebar();
590 return;
591 }
592
593 // compile the search string, which has already been split up above, into regexps
594 for (var i=0; i < RE.length; ++i) {
595 RE[i] = new RegExp(RE[i], "i");
596 }
597 emptySearch = true;
598
599 // search TOC
600 var resultsDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
601 .createInstance(Components.interfaces.nsIRDFDataSource);
602 var sourceDS = helpTocPanel.database;
603 doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
604
605 // search glossary.
606 sourceDS = helpGlossaryPanel.database;
607 doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
608
609 // search index
610 sourceDS = helpIndexPanel.database;
611 doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
612
613 // search additional search datasources
614 sourceDS = helpSearchPanel.database;
615 doFindOnDatasource(resultsDS, sourceDS, RDF_ROOT, 0);
616
617 if (emptySearch)
618 assertSearchEmpty(resultsDS);
619 // Add the datasource to the search tree
620 searchTree.database.AddDataSource(resultsDS);
621 searchTree.builder.rebuild();
622 }
623
624 function clearDatabases(compositeDataSource) {
625 var enumDS = compositeDataSource.GetDataSources()
626 while (enumDS.hasMoreElements()) {
627 var ds = enumDS.getNext();
628 compositeDataSource.RemoveDataSource(ds);
629 }
630 }
631
632 function doFindOnDatasource(resultsDS, sourceDS, resource, level) {
633 if (level > MAX_LEVEL) {
634 try {
635 log("Recursive reference to resource: " + resource.Value + ".");
636 } catch (e) {
637 log("Recursive reference to unknown resource.");
638 }
639 return;
640 }
641 // find all SUBHEADING children of current resource.
642 var targets = sourceDS.GetTargets(resource, NC_SUBHEADINGS, true);
643 while (targets.hasMoreElements()) {
644 var target = targets.getNext();
645 target = target.QueryInterface(Components.interfaces.nsIRDFResource);
646 // The first child of a rdf:subheading should (must) be a rdf:seq.
647 // Should we test for a SEQ here?
648 doFindOnSeq(resultsDS, sourceDS, target, level+1);
649 }
650 }
651
652 function doFindOnSeq(resultsDS, sourceDS, resource, level) {
653 // load up an RDFContainer so we can access the contents of the current
654 // rdf:seq.
655 RDFContainer.Init(sourceDS, resource);
656 var targets = RDFContainer.GetElements();
657 while (targets.hasMoreElements()) {
658 var target = targets.getNext();
659 var link = sourceDS.GetTarget(target, NC_LINK, true);
660 var name = sourceDS.GetTarget(target, NC_NAME, true);
661
662 if (link &&
663 name instanceof Components.interfaces.nsIRDFLiteral &&
664 isMatch(name.Value)) {
665 // we have found a search entry - add it to the results datasource.
666 var urn = RDF.GetAnonymousResource();
667 resultsDS.Assert(urn, NC_NAME, name, true);
668 resultsDS.Assert(urn, NC_LINK, link, true);
669 resultsDS.Assert(RDF_ROOT, NC_CHILD, urn, true);
670
671 emptySearch = false;
672 }
673 // process any nested rdf:seq elements.
674 doFindOnDatasource(resultsDS, sourceDS, target, level+1);
675 }
676 }
677
678 function assertSearchEmpty(resultsDS) {
679 var resSearchEmpty = RDF.GetResource("urn:emptySearch");
680 resultsDS.Assert(RDF_ROOT,
681 NC_CHILD,
682 resSearchEmpty,
683 true);
684 resultsDS.Assert(resSearchEmpty,
685 NC_NAME,
686 RDF.GetLiteral(emptySearchText),
687 true);
688 resultsDS.Assert(resSearchEmpty,
689 NC_LINK,
690 RDF.GetLiteral(emptySearchLink),
691 true);
692 }
693
694 function isMatch(text) {
695 for (var i=0; i < RE.length; ++i ) {
696 if (!RE[i].test(text)) {
697 return false;
698 }
699 }
700 return true;
701 }
702
703 function getAttribute(datasource, resource, attributeResourceName,
704 defaultValue) {
705 var literal = datasource.GetTarget(resource, attributeResourceName, true);
706 if (!literal) {
707 return defaultValue;
708 }
709 return getLiteralValue(literal, defaultValue);
710 }
711
712 function getLiteralValue(literal, defaultValue) {
713 if (literal) {
714 literal = literal.QueryInterface(Components.interfaces.nsIRDFLiteral);
715 if (literal) {
716 return literal.Value;
717 }
718 }
719 if (defaultValue) {
720 return defaultValue;
721 }
722 return null;
723 }
724
725 # Write debug string to error console.
726 function log(aText) {
727 CONSOLE_SERVICE.logStringMessage(aText);
728 }
729
730 function getBoolPref (aPrefname, aDefault)
731 {
732 try {
733 var pref = Components.classes["@mozilla.org/preferences-service;1"]
734 .getService(Components.interfaces.nsIPrefBranch);
735 return pref.getBoolPref(aPrefname);
736 }
737 catch(e) {
738 return aDefault;
739 }
740 }
741
742 # getXulWin - Returns the current Help window as a nsIXULWindow.
743 function getXulWin()
744 {
745 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
746 var webnav = window.getInterface(Components.interfaces.nsIWebNavigation);
747 var dsti = webnav.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
748 var treeowner = dsti.treeOwner;
749 var ifreq = treeowner.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
750
751 return ifreq.getInterface(Components.interfaces.nsIXULWindow);
752 }
753
754 # toggleZLevel - Toggles whether or not the window will always appear on top. Because
755 # alwaysRaised is not supported on an OS other than Windows, this code will not
756 # appear in those builds.
757 #
758 # element - The DOM node that persists the checked state.
759 #ifdef XP_WIN
760 #define HELP_ALWAYS_RAISED_TOGGLE
761 #endif
762 #ifdef HELP_ALWAYS_RAISED_TOGGLE
763 function toggleZLevel(element)
764 {
765 var xulwin = getXulWin();
766
767 // Now we can flip the zLevel, and set the attribute so that it persists correctly
768 if (xulwin.zLevel > xulwin.normalZ) {
769 xulwin.zLevel = xulwin.normalZ;
770 element.setAttribute("checked", "false");
771 } else {
772 xulwin.zLevel = xulwin.raisedZ;
773 element.setAttribute("checked", "true");
774 }
775 }
776 #endif

mercurial