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