Project

General

Profile

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