Documentation
For Arduino users
search.js
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 
8 var indexSectionsWithContent =
9 {
10  0: "acdeghnprstw~",
11  1: "n",
12  2: "dn",
13  3: "adegnprsw~",
14  4: "n",
15  5: "cgnt",
16  6: "hr"
17 };
18 
19 var indexSectionNames =
20 {
21  0: "all",
22  1: "classes",
23  2: "files",
24  3: "functions",
25  4: "typedefs",
26  5: "groups",
27  6: "pages"
28 };
29 
30 function convertToId(search)
31 {
32  var result = '';
33  for (i=0;i<search.length;i++)
34  {
35  var c = search.charAt(i);
36  var cn = c.charCodeAt(0);
37  if (c.match(/[a-z0-9\u0080-\uFFFF]/))
38  {
39  result+=c;
40  }
41  else if (cn<16)
42  {
43  result+="_0"+cn.toString(16);
44  }
45  else
46  {
47  result+="_"+cn.toString(16);
48  }
49  }
50  return result;
51 }
52 
53 function getXPos(item)
54 {
55  var x = 0;
56  if (item.offsetWidth)
57  {
58  while (item && item!=document.body)
59  {
60  x += item.offsetLeft;
61  item = item.offsetParent;
62  }
63  }
64  return x;
65 }
66 
67 function getYPos(item)
68 {
69  var y = 0;
70  if (item.offsetWidth)
71  {
72  while (item && item!=document.body)
73  {
74  y += item.offsetTop;
75  item = item.offsetParent;
76  }
77  }
78  return y;
79 }
80 
81 /* A class handling everything associated with the search panel.
82 
83  Parameters:
84  name - The name of the global variable that will be
85  storing this instance. Is needed to be able to set timeouts.
86  resultPath - path to use for external files
87 */
88 function SearchBox(name, resultsPath, inFrame, label)
89 {
90  if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); }
91 
92  // ---------- Instance variables
93  this.name = name;
94  this.resultsPath = resultsPath;
95  this.keyTimeout = 0;
96  this.keyTimeoutLength = 500;
97  this.closeSelectionTimeout = 300;
98  this.lastSearchValue = "";
99  this.lastResultsPage = "";
100  this.hideTimeout = 0;
101  this.searchIndex = 0;
102  this.searchActive = false;
103  this.insideFrame = inFrame;
104  this.searchLabel = label;
105 
106  // ----------- DOM Elements
107 
108  this.DOMSearchField = function()
109  { return document.getElementById("MSearchField"); }
110 
111  this.DOMSearchSelect = function()
112  { return document.getElementById("MSearchSelect"); }
113 
114  this.DOMSearchSelectWindow = function()
115  { return document.getElementById("MSearchSelectWindow"); }
116 
117  this.DOMPopupSearchResults = function()
118  { return document.getElementById("MSearchResults"); }
119 
120  this.DOMPopupSearchResultsWindow = function()
121  { return document.getElementById("MSearchResultsWindow"); }
122 
123  this.DOMSearchClose = function()
124  { return document.getElementById("MSearchClose"); }
125 
126  this.DOMSearchBox = function()
127  { return document.getElementById("MSearchBox"); }
128 
129  // ------------ Event Handlers
130 
131  // Called when focus is added or removed from the search field.
132  this.OnSearchFieldFocus = function(isActive)
133  {
134  this.Activate(isActive);
135  }
136 
137  this.OnSearchSelectShow = function()
138  {
139  var searchSelectWindow = this.DOMSearchSelectWindow();
140  var searchField = this.DOMSearchSelect();
141 
142  if (this.insideFrame)
143  {
144  var left = getXPos(searchField);
145  var top = getYPos(searchField);
146  left += searchField.offsetWidth + 6;
147  top += searchField.offsetHeight;
148 
149  // show search selection popup
150  searchSelectWindow.style.display='block';
151  left -= searchSelectWindow.offsetWidth;
152  searchSelectWindow.style.left = left + 'px';
153  searchSelectWindow.style.top = top + 'px';
154  }
155  else
156  {
157  var left = getXPos(searchField);
158  var top = getYPos(searchField);
159  top += searchField.offsetHeight;
160 
161  // show search selection popup
162  searchSelectWindow.style.display='block';
163  searchSelectWindow.style.left = left + 'px';
164  searchSelectWindow.style.top = top + 'px';
165  }
166 
167  // stop selection hide timer
168  if (this.hideTimeout)
169  {
170  clearTimeout(this.hideTimeout);
171  this.hideTimeout=0;
172  }
173  return false; // to avoid "image drag" default event
174  }
175 
176  this.OnSearchSelectHide = function()
177  {
178  this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
179  this.closeSelectionTimeout);
180  }
181 
182  // Called when the content of the search field is changed.
183  this.OnSearchFieldChange = function(evt)
184  {
185  if (this.keyTimeout) // kill running timer
186  {
187  clearTimeout(this.keyTimeout);
188  this.keyTimeout = 0;
189  }
190 
191  var e = (evt) ? evt : window.event; // for IE
192  if (e.keyCode==40 || e.keyCode==13)
193  {
194  if (e.shiftKey==1)
195  {
196  this.OnSearchSelectShow();
197  var win=this.DOMSearchSelectWindow();
198  for (i=0;i<win.childNodes.length;i++)
199  {
200  var child = win.childNodes[i]; // get span within a
201  if (child.className=='SelectItem')
202  {
203  child.focus();
204  return;
205  }
206  }
207  return;
208  }
209  else if (window.frames.MSearchResults.searchResults)
210  {
211  var elem = window.frames.MSearchResults.searchResults.NavNext(0);
212  if (elem) elem.focus();
213  }
214  }
215  else if (e.keyCode==27) // Escape out of the search field
216  {
217  this.DOMSearchField().blur();
218  this.DOMPopupSearchResultsWindow().style.display = 'none';
219  this.DOMSearchClose().style.display = 'none';
220  this.lastSearchValue = '';
221  this.Activate(false);
222  return;
223  }
224 
225  // strip whitespaces
226  var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
227 
228  if (searchValue != this.lastSearchValue) // search value has changed
229  {
230  if (searchValue != "") // non-empty search
231  {
232  // set timer for search update
233  this.keyTimeout = setTimeout(this.name + '.Search()',
234  this.keyTimeoutLength);
235  }
236  else // empty search field
237  {
238  this.DOMPopupSearchResultsWindow().style.display = 'none';
239  this.DOMSearchClose().style.display = 'none';
240  this.lastSearchValue = '';
241  }
242  }
243  }
244 
245  this.SelectItemCount = function(id)
246  {
247  var count=0;
248  var win=this.DOMSearchSelectWindow();
249  for (i=0;i<win.childNodes.length;i++)
250  {
251  var child = win.childNodes[i]; // get span within a
252  if (child.className=='SelectItem')
253  {
254  count++;
255  }
256  }
257  return count;
258  }
259 
260  this.SelectItemSet = function(id)
261  {
262  var i,j=0;
263  var win=this.DOMSearchSelectWindow();
264  for (i=0;i<win.childNodes.length;i++)
265  {
266  var child = win.childNodes[i]; // get span within a
267  if (child.className=='SelectItem')
268  {
269  var node = child.firstChild;
270  if (j==id)
271  {
272  node.innerHTML='&#8226;';
273  }
274  else
275  {
276  node.innerHTML='&#160;';
277  }
278  j++;
279  }
280  }
281  }
282 
283  // Called when an search filter selection is made.
284  // set item with index id as the active item
285  this.OnSelectItem = function(id)
286  {
287  this.searchIndex = id;
288  this.SelectItemSet(id);
289  var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
290  if (searchValue!="" && this.searchActive) // something was found -> do a search
291  {
292  this.Search();
293  }
294  }
295 
296  this.OnSearchSelectKey = function(evt)
297  {
298  var e = (evt) ? evt : window.event; // for IE
299  if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
300  {
301  this.searchIndex++;
302  this.OnSelectItem(this.searchIndex);
303  }
304  else if (e.keyCode==38 && this.searchIndex>0) // Up
305  {
306  this.searchIndex--;
307  this.OnSelectItem(this.searchIndex);
308  }
309  else if (e.keyCode==13 || e.keyCode==27)
310  {
311  this.OnSelectItem(this.searchIndex);
312  this.CloseSelectionWindow();
313  this.DOMSearchField().focus();
314  }
315  return false;
316  }
317 
318  // --------- Actions
319 
320  // Closes the results window.
321  this.CloseResultsWindow = function()
322  {
323  this.DOMPopupSearchResultsWindow().style.display = 'none';
324  this.DOMSearchClose().style.display = 'none';
325  this.Activate(false);
326  }
327 
328  this.CloseSelectionWindow = function()
329  {
330  this.DOMSearchSelectWindow().style.display = 'none';
331  }
332 
333  // Performs a search.
334  this.Search = function()
335  {
336  this.keyTimeout = 0;
337 
338  // strip leading whitespace
339  var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
340 
341  var code = searchValue.toLowerCase().charCodeAt(0);
342  var idxChar = searchValue.substr(0, 1).toLowerCase();
343  if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
344  {
345  idxChar = searchValue.substr(0, 2);
346  }
347 
348  var resultsPage;
349  var resultsPageWithSearch;
350  var hasResultsPage;
351 
352  var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
353  if (idx!=-1)
354  {
355  var hexCode=idx.toString(16);
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