All Classes Namespaces Files Functions Variables
search.js
Go to the documentation of this file.
1 // Search script generated by doxygen
2 // Copyright (C) 2009 by Dimitri van Heesch.
3 
4 // The code in this file is loosly based on main.js, part of Natural Docs,
5 // which is Copyright (C) 2003-2008 Greg Valure
6 // Natural Docs is licensed under the GPL.
7 
9 {
10  0: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101111111001101101111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
11  1: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101101100001101001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
12  2: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
13  3: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101000001100001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
14  4: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101101111001101001111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
15  5: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101010101000001101110100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
16 };
17 
19 {
20  0: "all",
21  1: "classes",
22  2: "namespaces",
23  3: "files",
24  4: "functions",
25  5: "variables"
26 };
27 
28 function convertToId(search)
29 {
30  var result = '';
31  for (i=0;i<search.length;i++)
32  {
33  var c = search.charAt(i);
34  var cn = c.charCodeAt(0);
35  if (c.match(/[a-z0-9]/))
36  {
37  result+=c;
38  }
39  else if (cn<16)
40  {
41  result+="_0"+cn.toString(16);
42  }
43  else
44  {
45  result+="_"+cn.toString(16);
46  }
47  }
48  return result;
49 }
50 
51 function getXPos(item)
52 {
53  var x = 0;
54  if (item.offsetWidth)
55  {
56  while (item && item!=document.body)
57  {
58  x += item.offsetLeft;
59  item = item.offsetParent;
60  }
61  }
62  return x;
63 }
64 
65 function getYPos(item)
66 {
67  var y = 0;
68  if (item.offsetWidth)
69  {
70  while (item && item!=document.body)
71  {
72  y += item.offsetTop;
73  item = item.offsetParent;
74  }
75  }
76  return y;
77 }
78 
79 /* A class handling everything associated with the search panel.
80 
81  Parameters:
82  name - The name of the global variable that will be
83  storing this instance. Is needed to be able to set timeouts.
84  resultPath - path to use for external files
85 */
86 function SearchBox(name, resultsPath, inFrame, label)
87 {
88  if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
89 
90  // ---------- Instance variables
91  this.name = name;
92  this.resultsPath = resultsPath;
93  this.keyTimeout = 0;
94  this.keyTimeoutLength = 500;
95  this.closeSelectionTimeout = 300;
96  this.lastSearchValue = "";
97  this.lastResultsPage = "";
98  this.hideTimeout = 0;
99  this.searchIndex = 0;
100  this.searchActive = false;
101  this.insideFrame = inFrame;
102  this.searchLabel = label;
103 
104  // ----------- DOM Elements
105 
106  this.DOMSearchField = function()
107  { return document.getElementById("MSearchField"); }
108 
109  this.DOMSearchSelect = function()
110  { return document.getElementById("MSearchSelect"); }
111 
112  this.DOMSearchSelectWindow = function()
113  { return document.getElementById("MSearchSelectWindow"); }
114 
115  this.DOMPopupSearchResults = function()
116  { return document.getElementById("MSearchResults"); }
117 
118  this.DOMPopupSearchResultsWindow = function()
119  { return document.getElementById("MSearchResultsWindow"); }
120 
121  this.DOMSearchClose = function()
122  { return document.getElementById("MSearchClose"); }
123 
124  this.DOMSearchBox = function()
125  { return document.getElementById("MSearchBox"); }
126 
127  // ------------ Event Handlers
128 
129  // Called when focus is added or removed from the search field.
130  this.OnSearchFieldFocus = function(isActive)
131  {
132  this.Activate(isActive);
133  }
134 
135  this.OnSearchSelectShow = function()
136  {
137  var searchSelectWindow = this.DOMSearchSelectWindow();
138  var searchField = this.DOMSearchSelect();
139 
140  if (this.insideFrame)
141  {
142  var left = getXPos(searchField);
143  var top = getYPos(searchField);
144  left += searchField.offsetWidth + 6;
145  top += searchField.offsetHeight;
146 
147  // show search selection popup
148  searchSelectWindow.style.display='block';
149  left -= searchSelectWindow.offsetWidth;
150  searchSelectWindow.style.left = left + 'px';
151  searchSelectWindow.style.top = top + 'px';
152  }
153  else
154  {
155  var left = getXPos(searchField);
156  var top = getYPos(searchField);
157  top += searchField.offsetHeight;
158 
159  // show search selection popup
160  searchSelectWindow.style.display='block';
161  searchSelectWindow.style.left = left + 'px';
162  searchSelectWindow.style.top = top + 'px';
163  }
164 
165  // stop selection hide timer
166  if (this.hideTimeout)
167  {
168  clearTimeout(this.hideTimeout);
169  this.hideTimeout=0;
170  }
171  return false; // to avoid "image drag" default event
172  }
173 
174  this.OnSearchSelectHide = function()
175  {
176  this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
177  this.closeSelectionTimeout);
178  }
179 
180  // Called when the content of the search field is changed.
181  this.OnSearchFieldChange = function(evt)
182  {
183  if (this.keyTimeout) // kill running timer
184  {
185  clearTimeout(this.keyTimeout);
186  this.keyTimeout = 0;
187  }
188 
189  var e = (evt) ? evt : window.event; // for IE
190  if (e.keyCode==40 || e.keyCode==13)
191  {
192  if (e.shiftKey==1)
193  {
194  this.OnSearchSelectShow();
195  var win=this.DOMSearchSelectWindow();
196  for (i=0;i<win.childNodes.length;i++)
197  {
198  var child = win.childNodes[i]; // get span within a
199  if (child.className=='SelectItem')
200  {
201  child.focus();
202  return;
203  }
204  }
205  return;
206  }
207  else if (window.frames.MSearchResults.searchResults)
208  {
209  var elem = window.frames.MSearchResults.searchResults.NavNext(0);
210  if (elem) elem.focus();
211  }
212  }
213  else if (e.keyCode==27) // Escape out of the search field
214  {
215  this.DOMSearchField().blur();
216  this.DOMPopupSearchResultsWindow().style.display = 'none';
217  this.DOMSearchClose().style.display = 'none';
218  this.lastSearchValue = '';
219  this.Activate(false);
220  return;
221  }
222 
223  // strip whitespaces
224  var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
225 
226  if (searchValue != this.lastSearchValue) // search value has changed
227  {
228  if (searchValue != "") // non-empty search
229  {
230  // set timer for search update
231  this.keyTimeout = setTimeout(this.name + '.Search()',
232  this.keyTimeoutLength);
233  }
234  else // empty search field
235  {
236  this.DOMPopupSearchResultsWindow().style.display = 'none';
237  this.DOMSearchClose().style.display = 'none';
238  this.lastSearchValue = '';
239  }
240  }
241  }
242 
243  this.SelectItemCount = function(id)
244  {
245  var count=0;
246  var win=this.DOMSearchSelectWindow();
247  for (i=0;i<win.childNodes.length;i++)
248  {
249  var child = win.childNodes[i]; // get span within a
250  if (child.className=='SelectItem')
251  {
252  count++;
253  }
254  }
255  return count;
256  }
257 
258  this.SelectItemSet = function(id)
259  {
260  var i,j=0;
261  var win=this.DOMSearchSelectWindow();
262  for (i=0;i<win.childNodes.length;i++)
263  {
264  var child = win.childNodes[i]; // get span within a
265  if (child.className=='SelectItem')
266  {
267  var node = child.firstChild;
268  if (j==id)
269  {
270  node.innerHTML='&#8226;';
271  }
272  else
273  {
274  node.innerHTML='&#160;';
275  }
276  j++;
277  }
278  }
279  }
280 
281  // Called when an search filter selection is made.
282  // set item with index id as the active item
283  this.OnSelectItem = function(id)
284  {
285  this.searchIndex = id;
286  this.SelectItemSet(id);
287  var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
288  if (searchValue!="" && this.searchActive) // something was found -> do a search
289  {
290  this.Search();
291  }
292  }
293 
294  this.OnSearchSelectKey = function(evt)
295  {
296  var e = (evt) ? evt : window.event; // for IE
297  if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
298  {
299  this.searchIndex++;
300  this.OnSelectItem(this.searchIndex);
301  }
302  else if (e.keyCode==38 && this.searchIndex>0) // Up
303  {
304  this.searchIndex--;
305  this.OnSelectItem(this.searchIndex);
306  }
307  else if (e.keyCode==13 || e.keyCode==27)
308  {
309  this.OnSelectItem(this.searchIndex);
310  this.CloseSelectionWindow();
311  this.DOMSearchField().focus();
312  }
313  return false;
314  }
315 
316  // --------- Actions
317 
318  // Closes the results window.
319  this.CloseResultsWindow = function()
320  {
321  this.DOMPopupSearchResultsWindow().style.display = 'none';
322  this.DOMSearchClose().style.display = 'none';
323  this.Activate(false);
324  }
325 
326  this.CloseSelectionWindow = function()
327  {
328  this.DOMSearchSelectWindow().style.display = 'none';
329  }
330 
331  // Performs a search.
332  this.Search = function()
333  {
334  this.keyTimeout = 0;
335 
336  // strip leading whitespace
337  var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
338 
339  var code = searchValue.toLowerCase().charCodeAt(0);
340  var hexCode;
341  if (code<16)
342  {
343  hexCode="0"+code.toString(16);
344  }
345  else
346  {
347  hexCode=code.toString(16);
348  }
349 
350  var resultsPage;
351  var resultsPageWithSearch;
352  var hasResultsPage;
353 
354  if (indexSectionsWithContent[this.searchIndex].charAt(code) == '1')
355  {
356  resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
357  resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
358  hasResultsPage = true;
359  }
360  else // nothing available for this search term
361  {
362  resultsPage = this.resultsPath + '/nomatches.html';
363  resultsPageWithSearch = resultsPage;
364  hasResultsPage = false;
365  }
366 
367  window.frames.MSearchResults.location = resultsPageWithSearch;
368  var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
369 
370  if (domPopupSearchResultsWindow.style.display!='block')
371  {
372  var domSearchBox = this.DOMSearchBox();
373  this.DOMSearchClose().style.display = 'inline';
374  if (this.insideFrame)
375  {
376  var domPopupSearchResults = this.DOMPopupSearchResults();
377  domPopupSearchResultsWindow.style.position = 'relative';
378  domPopupSearchResultsWindow.style.display = 'block';
379  var width = document.body.clientWidth - 8; // the -8 is for IE :-(
380  domPopupSearchResultsWindow.style.width = width + 'px';
381  domPopupSearchResults.style.width = width + 'px';
382  }
383  else
384  {
385  var domPopupSearchResults = this.DOMPopupSearchResults();
386  var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
387  var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1;
388  domPopupSearchResultsWindow.style.display = 'block';
389  left -= domPopupSearchResults.offsetWidth;
390  domPopupSearchResultsWindow.style.top = top + 'px';
391  domPopupSearchResultsWindow.style.left = left + 'px';
392  }
393  }
394 
395  this.lastSearchValue = searchValue;
396  this.lastResultsPage = resultsPage;
397  }
398 
399  // -------- Activation Functions
400 
401  // Activates or deactivates the search panel, resetting things to
402  // their default values if necessary.
403  this.Activate = function(isActive)
404  {
405  if (isActive || // open it
406  this.DOMPopupSearchResultsWindow().style.display == 'block'
407  )
408  {
409  this.DOMSearchBox().className = 'MSearchBoxActive';
410 
411  var searchField = this.DOMSearchField();
412 
413  if (searchField.value == this.searchLabel) // clear "Search" term upon entry
414  {
415  searchField.value = '';
416  this.searchActive = true;
417  }
418  }
419  else if (!isActive) // directly remove the panel
420  {
421  this.DOMSearchBox().className = 'MSearchBoxInactive';
422  this.DOMSearchField().value = this.searchLabel;
423  this.searchActive = false;
424  this.lastSearchValue = ''
425  this.lastResultsPage = '';
426  }
427  }
428 }
429 
430 // -----------------------------------------------------------------------
431 
432 // The class that handles everything on the search results page.
433 function SearchResults(name)
434 {
435  // The number of matches from the last run of <Search()>.
436  this.lastMatchCount = 0;
437  this.lastKey = 0;
438  this.repeatOn = false;
439 
440  // Toggles the visibility of the passed element ID.
441  this.FindChildElement = function(id)
442  {
443  var parentElement = document.getElementById(id);
444  var element = parentElement.firstChild;
445 
446  while (element && element!=parentElement)
447  {
448  if (element.nodeName == 'DIV' && element.className == 'SRChildren')
449  {
450  return element;
451  }
452 
453  if (element.nodeName == 'DIV' && element.hasChildNodes())
454  {
455  element = element.firstChild;
456  }
457  else if (element.nextSibling)
458  {
459  element = element.nextSibling;
460  }
461  else
462  {
463  do
464  {
465  element = element.parentNode;
466  }
467  while (element && element!=parentElement && !element.nextSibling);
468 
469  if (element && element!=parentElement)
470  {
471  element = element.nextSibling;
472  }
473  }
474  }
475  }
476 
477  this.Toggle = function(id)
478  {
479  var element = this.FindChildElement(id);
480  if (element)
481  {
482  if (element.style.display == 'block')
483  {
484  element.style.display = 'none';
485  }
486  else
487  {
488  element.style.display = 'block';
489  }
490  }
491  }
492 
493  // Searches for the passed string. If there is no parameter,
494  // it takes it from the URL query.
495  //
496  // Always returns true, since other documents may try to call it
497  // and that may or may not be possible.
498  this.Search = function(search)
499  {
500  if (!search) // get search word from URL
501  {
502  search = window.location.search;
503  search = search.substring(1); // Remove the leading '?'
504  search = unescape(search);
505  }
506 
507  search = search.replace(/^ +/, ""); // strip leading spaces
508  search = search.replace(/ +$/, ""); // strip trailing spaces
509  search = search.toLowerCase();
510  search = convertToId(search);
511 
512  var resultRows = document.getElementsByTagName("div");
513  var matches = 0;
514 
515  var i = 0;
516  while (i < resultRows.length)
517  {
518  var row = resultRows.item(i);
519  if (row.className == "SRResult")
520  {
521  var rowMatchName = row.id.toLowerCase();
522  rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
523 
524  if (search.length<=rowMatchName.length &&
525  rowMatchName.substr(0, search.length)==search)
526  {
527  row.style.display = 'block';
528  matches++;
529  }
530  else
531  {
532  row.style.display = 'none';
533  }
534  }
535  i++;
536  }
537  document.getElementById("Searching").style.display='none';
538  if (matches == 0) // no results
539  {
540  document.getElementById("NoMatches").style.display='block';
541  }
542  else // at least one result
543  {
544  document.getElementById("NoMatches").style.display='none';
545  }
546  this.lastMatchCount = matches;
547  return true;
548  }
549 
550  // return the first item with index index or higher that is visible
551  this.NavNext = function(index)
552  {
553  var focusItem;
554  while (1)
555  {
556  var focusName = 'Item'+index;
557  focusItem = document.getElementById(focusName);
558  if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
559  {
560  break;
561  }
562  else if (!focusItem) // last element
563  {
564  break;
565  }
566  focusItem=null;
567  index++;
568  }
569  return focusItem;
570  }
571 
572  this.NavPrev = function(index)
573  {
574  var focusItem;
575  while (1)
576  {
577  var focusName = 'Item'+index;
578  focusItem = document.getElementById(focusName);
579  if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
580  {
581  break;
582  }
583  else if (!focusItem) // last element
584  {
585  break;
586  }
587  focusItem=null;
588  index--;
589  }
590  return focusItem;
591  }
592 
593  this.ProcessKeys = function(e)
594  {
595  if (e.type == "keydown")
596  {
597  this.repeatOn = false;
598  this.lastKey = e.keyCode;
599  }
600  else if (e.type == "keypress")
601  {
602  if (!this.repeatOn)
603  {
604  if (this.lastKey) this.repeatOn = true;
605  return false; // ignore first keypress after keydown
606  }
607  }
608  else if (e.type == "keyup")
609  {
610  this.lastKey = 0;
611  this.repeatOn = false;
612  }
613  return this.lastKey!=0;
614  }
615 
616  this.Nav = function(evt,itemIndex)
617  {
618  var e = (evt) ? evt : window.event; // for IE
619  if (e.keyCode==13) return true;
620  if (!this.ProcessKeys(e)) return false;
621 
622  if (this.lastKey==38) // Up
623  {
624  var newIndex = itemIndex-1;
625  var focusItem = this.NavPrev(newIndex);
626  if (focusItem)
627  {
628  var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
629  if (child && child.style.display == 'block') // children visible
630  {
631  var n=0;
632  var tmpElem;
633  while (1) // search for last child
634  {
635  tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
636  if (tmpElem)
637  {
638  focusItem = tmpElem;
639  }
640  else // found it!
641  {
642  break;
643  }
644  n++;
645  }
646  }
647  }
648  if (focusItem)
649  {
650  focusItem.focus();
651  }
652  else // return focus to search field
653  {
654  parent.document.getElementById("MSearchField").focus();
655  }
656  }
657  else if (this.lastKey==40) // Down
658  {
659  var newIndex = itemIndex+1;
660  var focusItem;
661  var item = document.getElementById('Item'+itemIndex);
662  var elem = this.FindChildElement(item.parentNode.parentNode.id);
663  if (elem && elem.style.display == 'block') // children visible
664  {
665  focusItem = document.getElementById('Item'+itemIndex+'_c0');
666  }
667  if (!focusItem) focusItem = this.NavNext(newIndex);
668  if (focusItem) focusItem.focus();
669  }
670  else if (this.lastKey==39) // Right
671  {
672  var item = document.getElementById('Item'+itemIndex);
673  var elem = this.FindChildElement(item.parentNode.parentNode.id);
674  if (elem) elem.style.display = 'block';
675  }
676  else if (this.lastKey==37) // Left
677  {
678  var item = document.getElementById('Item'+itemIndex);
679  var elem = this.FindChildElement(item.parentNode.parentNode.id);
680  if (elem) elem.style.display = 'none';
681  }
682  else if (this.lastKey==27) // Escape
683  {
684  parent.searchBox.CloseResultsWindow();
685  parent.document.getElementById("MSearchField").focus();
686  }
687  else if (this.lastKey==13) // Enter
688  {
689  return true;
690  }
691  return false;
692  }
693 
694  this.NavChild = function(evt,itemIndex,childIndex)
695  {
696  var e = (evt) ? evt : window.event; // for IE
697  if (e.keyCode==13) return true;
698  if (!this.ProcessKeys(e)) return false;
699 
700  if (this.lastKey==38) // Up
701  {
702  if (childIndex>0)
703  {
704  var newIndex = childIndex-1;
705  document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
706  }
707  else // already at first child, jump to parent
708  {
709  document.getElementById('Item'+itemIndex).focus();
710  }
711  }
712  else if (this.lastKey==40) // Down
713  {
714  var newIndex = childIndex+1;
715  var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
716  if (!elem) // last child, jump to parent next parent
717  {
718  elem = this.NavNext(itemIndex+1);
719  }
720  if (elem)
721  {
722  elem.focus();
723  }
724  }
725  else if (this.lastKey==27) // Escape
726  {
727  parent.searchBox.CloseResultsWindow();
728  parent.document.getElementById("MSearchField").focus();
729  }
730  else if (this.lastKey==13) // Enter
731  {
732  return true;
733  }
734  return false;
735  }
736 }
737 
738 function setKeyActions(elem,action)
739 {
740  elem.setAttribute('onkeydown',action);
741  elem.setAttribute('onkeypress',action);
742  elem.setAttribute('onkeyup',action);
743 }
744 
745 function setClassAttr(elem,attr)
746 {
747  elem.setAttribute('class',attr);
748  elem.setAttribute('className',attr);
749 }
750 
751 function createResults()
752 {
753  var results = document.getElementById("SRResults");
754  for (var e=0; e<searchData.length; e++)
755  {
756  var id = searchData[e][0];
757  var srResult = document.createElement('div');
758  srResult.setAttribute('id','SR_'+id);
759  setClassAttr(srResult,'SRResult');
760  var srEntry = document.createElement('div');
761  setClassAttr(srEntry,'SREntry');
762  var srLink = document.createElement('a');
763  srLink.setAttribute('id','Item'+e);
764  setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
765  setClassAttr(srLink,'SRSymbol');
766  srLink.innerHTML = searchData[e][1][0];
767  srEntry.appendChild(srLink);
768  if (searchData[e][1].length==2) // single result
769  {
770  srLink.setAttribute('href',searchData[e][1][1][0]);
771  if (searchData[e][1][1][1])
772  {
773  srLink.setAttribute('target','_parent');
774  }
775  var srScope = document.createElement('span');
776  setClassAttr(srScope,'SRScope');
777  srScope.innerHTML = searchData[e][1][1][2];
778  srEntry.appendChild(srScope);
779  }
780  else // multiple results
781  {
782  srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
783  var srChildren = document.createElement('div');
784  setClassAttr(srChildren,'SRChildren');
785  for (var c=0; c<searchData[e][1].length-1; c++)
786  {
787  var srChild = document.createElement('a');
788  srChild.setAttribute('id','Item'+e+'_c'+c);
789  setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
790  setClassAttr(srChild,'SRScope');
791  srChild.setAttribute('href',searchData[e][1][c+1][0]);
792  if (searchData[e][1][c+1][1])
793  {
794  srChild.setAttribute('target','_parent');
795  }
796  srChild.innerHTML = searchData[e][1][c+1][2];
797  srChildren.appendChild(srChild);
798  }
799  srEntry.appendChild(srChildren);
800  }
801  srResult.appendChild(srEntry);
802  results.appendChild(srResult);
803  }
804 }
805