xref: /aosp_15_r20/external/tinyxml2/docs/search/search.js (revision 7485b22521f577cf944e5687361548d8993d8d2c)
1*7485b225SElliott Hughes/*
2*7485b225SElliott Hughes @licstart  The following is the entire license notice for the JavaScript code in this file.
3*7485b225SElliott Hughes
4*7485b225SElliott Hughes The MIT License (MIT)
5*7485b225SElliott Hughes
6*7485b225SElliott Hughes Copyright (C) 1997-2020 by Dimitri van Heesch
7*7485b225SElliott Hughes
8*7485b225SElliott Hughes Permission is hereby granted, free of charge, to any person obtaining a copy of this software
9*7485b225SElliott Hughes and associated documentation files (the "Software"), to deal in the Software without restriction,
10*7485b225SElliott Hughes including without limitation the rights to use, copy, modify, merge, publish, distribute,
11*7485b225SElliott Hughes sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
12*7485b225SElliott Hughes furnished to do so, subject to the following conditions:
13*7485b225SElliott Hughes
14*7485b225SElliott Hughes The above copyright notice and this permission notice shall be included in all copies or
15*7485b225SElliott Hughes substantial portions of the Software.
16*7485b225SElliott Hughes
17*7485b225SElliott Hughes THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
18*7485b225SElliott Hughes BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*7485b225SElliott Hughes NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20*7485b225SElliott Hughes DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*7485b225SElliott Hughes OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*7485b225SElliott Hughes
23*7485b225SElliott Hughes @licend  The above is the entire license notice for the JavaScript code in this file
24*7485b225SElliott Hughes */
25*7485b225SElliott Hughesconst SEARCH_COOKIE_NAME = ''+'search_grp';
26*7485b225SElliott Hughes
27*7485b225SElliott Hughesconst searchResults = new SearchResults();
28*7485b225SElliott Hughes
29*7485b225SElliott Hughes/* A class handling everything associated with the search panel.
30*7485b225SElliott Hughes
31*7485b225SElliott Hughes   Parameters:
32*7485b225SElliott Hughes   name - The name of the global variable that will be
33*7485b225SElliott Hughes          storing this instance.  Is needed to be able to set timeouts.
34*7485b225SElliott Hughes   resultPath - path to use for external files
35*7485b225SElliott Hughes*/
36*7485b225SElliott Hughesfunction SearchBox(name, resultsPath, extension) {
37*7485b225SElliott Hughes  if (!name || !resultsPath) {  alert("Missing parameters to SearchBox."); }
38*7485b225SElliott Hughes  if (!extension || extension == "") { extension = ".html"; }
39*7485b225SElliott Hughes
40*7485b225SElliott Hughes  function getXPos(item) {
41*7485b225SElliott Hughes    let x = 0;
42*7485b225SElliott Hughes    if (item.offsetWidth) {
43*7485b225SElliott Hughes      while (item && item!=document.body) {
44*7485b225SElliott Hughes        x   += item.offsetLeft;
45*7485b225SElliott Hughes        item = item.offsetParent;
46*7485b225SElliott Hughes      }
47*7485b225SElliott Hughes    }
48*7485b225SElliott Hughes    return x;
49*7485b225SElliott Hughes  }
50*7485b225SElliott Hughes
51*7485b225SElliott Hughes  function getYPos(item) {
52*7485b225SElliott Hughes    let y = 0;
53*7485b225SElliott Hughes    if (item.offsetWidth) {
54*7485b225SElliott Hughes      while (item && item!=document.body) {
55*7485b225SElliott Hughes        y   += item.offsetTop;
56*7485b225SElliott Hughes        item = item.offsetParent;
57*7485b225SElliott Hughes      }
58*7485b225SElliott Hughes    }
59*7485b225SElliott Hughes    return y;
60*7485b225SElliott Hughes  }
61*7485b225SElliott Hughes
62*7485b225SElliott Hughes  // ---------- Instance variables
63*7485b225SElliott Hughes  this.name                  = name;
64*7485b225SElliott Hughes  this.resultsPath           = resultsPath;
65*7485b225SElliott Hughes  this.keyTimeout            = 0;
66*7485b225SElliott Hughes  this.keyTimeoutLength      = 500;
67*7485b225SElliott Hughes  this.closeSelectionTimeout = 300;
68*7485b225SElliott Hughes  this.lastSearchValue       = "";
69*7485b225SElliott Hughes  this.lastResultsPage       = "";
70*7485b225SElliott Hughes  this.hideTimeout           = 0;
71*7485b225SElliott Hughes  this.searchIndex           = 0;
72*7485b225SElliott Hughes  this.searchActive          = false;
73*7485b225SElliott Hughes  this.extension             = extension;
74*7485b225SElliott Hughes
75*7485b225SElliott Hughes  // ----------- DOM Elements
76*7485b225SElliott Hughes
77*7485b225SElliott Hughes  this.DOMSearchField              = () => document.getElementById("MSearchField");
78*7485b225SElliott Hughes  this.DOMSearchSelect             = () => document.getElementById("MSearchSelect");
79*7485b225SElliott Hughes  this.DOMSearchSelectWindow       = () => document.getElementById("MSearchSelectWindow");
80*7485b225SElliott Hughes  this.DOMPopupSearchResults       = () => document.getElementById("MSearchResults");
81*7485b225SElliott Hughes  this.DOMPopupSearchResultsWindow = () => document.getElementById("MSearchResultsWindow");
82*7485b225SElliott Hughes  this.DOMSearchClose              = () => document.getElementById("MSearchClose");
83*7485b225SElliott Hughes  this.DOMSearchBox                = () => document.getElementById("MSearchBox");
84*7485b225SElliott Hughes
85*7485b225SElliott Hughes  // ------------ Event Handlers
86*7485b225SElliott Hughes
87*7485b225SElliott Hughes  // Called when focus is added or removed from the search field.
88*7485b225SElliott Hughes  this.OnSearchFieldFocus = function(isActive) {
89*7485b225SElliott Hughes    this.Activate(isActive);
90*7485b225SElliott Hughes  }
91*7485b225SElliott Hughes
92*7485b225SElliott Hughes  this.OnSearchSelectShow = function() {
93*7485b225SElliott Hughes    const searchSelectWindow = this.DOMSearchSelectWindow();
94*7485b225SElliott Hughes    const searchField        = this.DOMSearchSelect();
95*7485b225SElliott Hughes
96*7485b225SElliott Hughes    const left = getXPos(searchField);
97*7485b225SElliott Hughes    const top  = getYPos(searchField) + searchField.offsetHeight;
98*7485b225SElliott Hughes
99*7485b225SElliott Hughes    // show search selection popup
100*7485b225SElliott Hughes    searchSelectWindow.style.display='block';
101*7485b225SElliott Hughes    searchSelectWindow.style.left =  left + 'px';
102*7485b225SElliott Hughes    searchSelectWindow.style.top  =  top  + 'px';
103*7485b225SElliott Hughes
104*7485b225SElliott Hughes    // stop selection hide timer
105*7485b225SElliott Hughes    if (this.hideTimeout) {
106*7485b225SElliott Hughes      clearTimeout(this.hideTimeout);
107*7485b225SElliott Hughes      this.hideTimeout=0;
108*7485b225SElliott Hughes    }
109*7485b225SElliott Hughes    return false; // to avoid "image drag" default event
110*7485b225SElliott Hughes  }
111*7485b225SElliott Hughes
112*7485b225SElliott Hughes  this.OnSearchSelectHide = function() {
113*7485b225SElliott Hughes    this.hideTimeout = setTimeout(this.CloseSelectionWindow.bind(this),
114*7485b225SElliott Hughes                                  this.closeSelectionTimeout);
115*7485b225SElliott Hughes  }
116*7485b225SElliott Hughes
117*7485b225SElliott Hughes  // Called when the content of the search field is changed.
118*7485b225SElliott Hughes  this.OnSearchFieldChange = function(evt) {
119*7485b225SElliott Hughes    if (this.keyTimeout) { // kill running timer
120*7485b225SElliott Hughes      clearTimeout(this.keyTimeout);
121*7485b225SElliott Hughes      this.keyTimeout = 0;
122*7485b225SElliott Hughes    }
123*7485b225SElliott Hughes
124*7485b225SElliott Hughes    const e = evt ? evt : window.event; // for IE
125*7485b225SElliott Hughes    if (e.keyCode==40 || e.keyCode==13) {
126*7485b225SElliott Hughes      if (e.shiftKey==1) {
127*7485b225SElliott Hughes        this.OnSearchSelectShow();
128*7485b225SElliott Hughes        const win=this.DOMSearchSelectWindow();
129*7485b225SElliott Hughes        for (let i=0;i<win.childNodes.length;i++) {
130*7485b225SElliott Hughes          const child = win.childNodes[i]; // get span within a
131*7485b225SElliott Hughes          if (child.className=='SelectItem') {
132*7485b225SElliott Hughes            child.focus();
133*7485b225SElliott Hughes            return;
134*7485b225SElliott Hughes          }
135*7485b225SElliott Hughes        }
136*7485b225SElliott Hughes        return;
137*7485b225SElliott Hughes      } else {
138*7485b225SElliott Hughes        const elem = searchResults.NavNext(0);
139*7485b225SElliott Hughes        if (elem) elem.focus();
140*7485b225SElliott Hughes      }
141*7485b225SElliott Hughes    } else if (e.keyCode==27) { // Escape out of the search field
142*7485b225SElliott Hughes      e.stopPropagation();
143*7485b225SElliott Hughes      this.DOMSearchField().blur();
144*7485b225SElliott Hughes      this.DOMPopupSearchResultsWindow().style.display = 'none';
145*7485b225SElliott Hughes      this.DOMSearchClose().style.display = 'none';
146*7485b225SElliott Hughes      this.lastSearchValue = '';
147*7485b225SElliott Hughes      this.Activate(false);
148*7485b225SElliott Hughes      return;
149*7485b225SElliott Hughes    }
150*7485b225SElliott Hughes
151*7485b225SElliott Hughes    // strip whitespaces
152*7485b225SElliott Hughes    const searchValue = this.DOMSearchField().value.replace(/ +/g, "");
153*7485b225SElliott Hughes
154*7485b225SElliott Hughes    if (searchValue != this.lastSearchValue) { // search value has changed
155*7485b225SElliott Hughes      if (searchValue != "") { // non-empty search
156*7485b225SElliott Hughes        // set timer for search update
157*7485b225SElliott Hughes        this.keyTimeout = setTimeout(this.Search.bind(this), this.keyTimeoutLength);
158*7485b225SElliott Hughes      } else { // empty search field
159*7485b225SElliott Hughes        this.DOMPopupSearchResultsWindow().style.display = 'none';
160*7485b225SElliott Hughes        this.DOMSearchClose().style.display = 'none';
161*7485b225SElliott Hughes        this.lastSearchValue = '';
162*7485b225SElliott Hughes      }
163*7485b225SElliott Hughes    }
164*7485b225SElliott Hughes  }
165*7485b225SElliott Hughes
166*7485b225SElliott Hughes  this.SelectItemCount = function() {
167*7485b225SElliott Hughes    let count=0;
168*7485b225SElliott Hughes    const win=this.DOMSearchSelectWindow();
169*7485b225SElliott Hughes    for (let i=0;i<win.childNodes.length;i++) {
170*7485b225SElliott Hughes      const child = win.childNodes[i]; // get span within a
171*7485b225SElliott Hughes      if (child.className=='SelectItem') {
172*7485b225SElliott Hughes        count++;
173*7485b225SElliott Hughes      }
174*7485b225SElliott Hughes    }
175*7485b225SElliott Hughes    return count;
176*7485b225SElliott Hughes  }
177*7485b225SElliott Hughes
178*7485b225SElliott Hughes  this.GetSelectionIdByName = function(name) {
179*7485b225SElliott Hughes    let j=0;
180*7485b225SElliott Hughes    const win=this.DOMSearchSelectWindow();
181*7485b225SElliott Hughes    for (let i=0;i<win.childNodes.length;i++) {
182*7485b225SElliott Hughes      const child = win.childNodes[i];
183*7485b225SElliott Hughes      if (child.className=='SelectItem') {
184*7485b225SElliott Hughes        if (child.childNodes[1].nodeValue==name) {
185*7485b225SElliott Hughes          return j;
186*7485b225SElliott Hughes        }
187*7485b225SElliott Hughes        j++;
188*7485b225SElliott Hughes      }
189*7485b225SElliott Hughes    }
190*7485b225SElliott Hughes    return 0;
191*7485b225SElliott Hughes  }
192*7485b225SElliott Hughes
193*7485b225SElliott Hughes  this.SelectItemSet = function(id) {
194*7485b225SElliott Hughes    let j=0;
195*7485b225SElliott Hughes    const win=this.DOMSearchSelectWindow();
196*7485b225SElliott Hughes    for (let i=0;i<win.childNodes.length;i++) {
197*7485b225SElliott Hughes      const child = win.childNodes[i]; // get span within a
198*7485b225SElliott Hughes      if (child.className=='SelectItem') {
199*7485b225SElliott Hughes        const node = child.firstChild;
200*7485b225SElliott Hughes        if (j==id) {
201*7485b225SElliott Hughes          node.innerHTML='&#8226;';
202*7485b225SElliott Hughes          Cookie.writeSetting(SEARCH_COOKIE_NAME, child.childNodes[1].nodeValue, 0)
203*7485b225SElliott Hughes        } else {
204*7485b225SElliott Hughes          node.innerHTML='&#160;';
205*7485b225SElliott Hughes        }
206*7485b225SElliott Hughes        j++;
207*7485b225SElliott Hughes      }
208*7485b225SElliott Hughes    }
209*7485b225SElliott Hughes  }
210*7485b225SElliott Hughes
211*7485b225SElliott Hughes  // Called when an search filter selection is made.
212*7485b225SElliott Hughes  // set item with index id as the active item
213*7485b225SElliott Hughes  this.OnSelectItem = function(id) {
214*7485b225SElliott Hughes    this.searchIndex = id;
215*7485b225SElliott Hughes    this.SelectItemSet(id);
216*7485b225SElliott Hughes    const searchValue = this.DOMSearchField().value.replace(/ +/g, "");
217*7485b225SElliott Hughes    if (searchValue!="" && this.searchActive) { // something was found -> do a search
218*7485b225SElliott Hughes      this.Search();
219*7485b225SElliott Hughes    }
220*7485b225SElliott Hughes  }
221*7485b225SElliott Hughes
222*7485b225SElliott Hughes  this.OnSearchSelectKey = function(evt) {
223*7485b225SElliott Hughes    const e = (evt) ? evt : window.event; // for IE
224*7485b225SElliott Hughes    if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) { // Down
225*7485b225SElliott Hughes      this.searchIndex++;
226*7485b225SElliott Hughes      this.OnSelectItem(this.searchIndex);
227*7485b225SElliott Hughes    } else if (e.keyCode==38 && this.searchIndex>0) { // Up
228*7485b225SElliott Hughes      this.searchIndex--;
229*7485b225SElliott Hughes      this.OnSelectItem(this.searchIndex);
230*7485b225SElliott Hughes    } else if (e.keyCode==13 || e.keyCode==27) {
231*7485b225SElliott Hughes      e.stopPropagation();
232*7485b225SElliott Hughes      this.OnSelectItem(this.searchIndex);
233*7485b225SElliott Hughes      this.CloseSelectionWindow();
234*7485b225SElliott Hughes      this.DOMSearchField().focus();
235*7485b225SElliott Hughes    }
236*7485b225SElliott Hughes    return false;
237*7485b225SElliott Hughes  }
238*7485b225SElliott Hughes
239*7485b225SElliott Hughes  // --------- Actions
240*7485b225SElliott Hughes
241*7485b225SElliott Hughes  // Closes the results window.
242*7485b225SElliott Hughes  this.CloseResultsWindow = function() {
243*7485b225SElliott Hughes    this.DOMPopupSearchResultsWindow().style.display = 'none';
244*7485b225SElliott Hughes    this.DOMSearchClose().style.display = 'none';
245*7485b225SElliott Hughes    this.Activate(false);
246*7485b225SElliott Hughes  }
247*7485b225SElliott Hughes
248*7485b225SElliott Hughes  this.CloseSelectionWindow = function() {
249*7485b225SElliott Hughes    this.DOMSearchSelectWindow().style.display = 'none';
250*7485b225SElliott Hughes  }
251*7485b225SElliott Hughes
252*7485b225SElliott Hughes  // Performs a search.
253*7485b225SElliott Hughes  this.Search = function() {
254*7485b225SElliott Hughes    this.keyTimeout = 0;
255*7485b225SElliott Hughes
256*7485b225SElliott Hughes    // strip leading whitespace
257*7485b225SElliott Hughes    const searchValue = this.DOMSearchField().value.replace(/^ +/, "");
258*7485b225SElliott Hughes
259*7485b225SElliott Hughes    const code = searchValue.toLowerCase().charCodeAt(0);
260*7485b225SElliott Hughes    let idxChar = searchValue.substr(0, 1).toLowerCase();
261*7485b225SElliott Hughes    if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) { // surrogate pair
262*7485b225SElliott Hughes      idxChar = searchValue.substr(0, 2);
263*7485b225SElliott Hughes    }
264*7485b225SElliott Hughes
265*7485b225SElliott Hughes    let jsFile;
266*7485b225SElliott Hughes    let idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
267*7485b225SElliott Hughes    if (idx!=-1) {
268*7485b225SElliott Hughes      const hexCode=idx.toString(16);
269*7485b225SElliott Hughes      jsFile = this.resultsPath + indexSectionNames[this.searchIndex] + '_' + hexCode + '.js';
270*7485b225SElliott Hughes    }
271*7485b225SElliott Hughes
272*7485b225SElliott Hughes    const loadJS = function(url, impl, loc) {
273*7485b225SElliott Hughes      const scriptTag = document.createElement('script');
274*7485b225SElliott Hughes      scriptTag.src = url;
275*7485b225SElliott Hughes      scriptTag.onload = impl;
276*7485b225SElliott Hughes      scriptTag.onreadystatechange = impl;
277*7485b225SElliott Hughes      loc.appendChild(scriptTag);
278*7485b225SElliott Hughes    }
279*7485b225SElliott Hughes
280*7485b225SElliott Hughes    const domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
281*7485b225SElliott Hughes    const domSearchBox = this.DOMSearchBox();
282*7485b225SElliott Hughes    const domPopupSearchResults = this.DOMPopupSearchResults();
283*7485b225SElliott Hughes    const domSearchClose = this.DOMSearchClose();
284*7485b225SElliott Hughes    const resultsPath = this.resultsPath;
285*7485b225SElliott Hughes
286*7485b225SElliott Hughes    const handleResults = function() {
287*7485b225SElliott Hughes      document.getElementById("Loading").style.display="none";
288*7485b225SElliott Hughes      if (typeof searchData !== 'undefined') {
289*7485b225SElliott Hughes        createResults(resultsPath);
290*7485b225SElliott Hughes        document.getElementById("NoMatches").style.display="none";
291*7485b225SElliott Hughes      }
292*7485b225SElliott Hughes
293*7485b225SElliott Hughes      if (idx!=-1) {
294*7485b225SElliott Hughes        searchResults.Search(searchValue);
295*7485b225SElliott Hughes      } else { // no file with search results => force empty search results
296*7485b225SElliott Hughes        searchResults.Search('====');
297*7485b225SElliott Hughes      }
298*7485b225SElliott Hughes
299*7485b225SElliott Hughes      if (domPopupSearchResultsWindow.style.display!='block') {
300*7485b225SElliott Hughes        domSearchClose.style.display = 'inline-block';
301*7485b225SElliott Hughes        let left = getXPos(domSearchBox) + 150;
302*7485b225SElliott Hughes        let top  = getYPos(domSearchBox) + 20;
303*7485b225SElliott Hughes        domPopupSearchResultsWindow.style.display = 'block';
304*7485b225SElliott Hughes        left -= domPopupSearchResults.offsetWidth;
305*7485b225SElliott Hughes        const maxWidth  = document.body.clientWidth;
306*7485b225SElliott Hughes        const maxHeight = document.body.clientHeight;
307*7485b225SElliott Hughes        let width = 300;
308*7485b225SElliott Hughes        if (left<10) left=10;
309*7485b225SElliott Hughes        if (width+left+8>maxWidth) width=maxWidth-left-8;
310*7485b225SElliott Hughes        let height = 400;
311*7485b225SElliott Hughes        if (height+top+8>maxHeight) height=maxHeight-top-8;
312*7485b225SElliott Hughes        domPopupSearchResultsWindow.style.top     = top  + 'px';
313*7485b225SElliott Hughes        domPopupSearchResultsWindow.style.left    = left + 'px';
314*7485b225SElliott Hughes        domPopupSearchResultsWindow.style.width   = width + 'px';
315*7485b225SElliott Hughes        domPopupSearchResultsWindow.style.height  = height + 'px';
316*7485b225SElliott Hughes      }
317*7485b225SElliott Hughes    }
318*7485b225SElliott Hughes
319*7485b225SElliott Hughes    if (jsFile) {
320*7485b225SElliott Hughes      loadJS(jsFile, handleResults, this.DOMPopupSearchResultsWindow());
321*7485b225SElliott Hughes    } else {
322*7485b225SElliott Hughes      handleResults();
323*7485b225SElliott Hughes    }
324*7485b225SElliott Hughes
325*7485b225SElliott Hughes    this.lastSearchValue = searchValue;
326*7485b225SElliott Hughes  }
327*7485b225SElliott Hughes
328*7485b225SElliott Hughes  // -------- Activation Functions
329*7485b225SElliott Hughes
330*7485b225SElliott Hughes  // Activates or deactivates the search panel, resetting things to
331*7485b225SElliott Hughes  // their default values if necessary.
332*7485b225SElliott Hughes  this.Activate = function(isActive) {
333*7485b225SElliott Hughes    if (isActive || // open it
334*7485b225SElliott Hughes      this.DOMPopupSearchResultsWindow().style.display == 'block'
335*7485b225SElliott Hughes    ) {
336*7485b225SElliott Hughes      this.DOMSearchBox().className = 'MSearchBoxActive';
337*7485b225SElliott Hughes      this.searchActive = true;
338*7485b225SElliott Hughes    } else if (!isActive) { // directly remove the panel
339*7485b225SElliott Hughes      this.DOMSearchBox().className = 'MSearchBoxInactive';
340*7485b225SElliott Hughes      this.searchActive             = false;
341*7485b225SElliott Hughes      this.lastSearchValue          = ''
342*7485b225SElliott Hughes      this.lastResultsPage          = '';
343*7485b225SElliott Hughes      this.DOMSearchField().value   = '';
344*7485b225SElliott Hughes    }
345*7485b225SElliott Hughes  }
346*7485b225SElliott Hughes}
347*7485b225SElliott Hughes
348*7485b225SElliott Hughes// -----------------------------------------------------------------------
349*7485b225SElliott Hughes
350*7485b225SElliott Hughes// The class that handles everything on the search results page.
351*7485b225SElliott Hughesfunction SearchResults() {
352*7485b225SElliott Hughes
353*7485b225SElliott Hughes  function convertToId(search) {
354*7485b225SElliott Hughes    let result = '';
355*7485b225SElliott Hughes    for (let i=0;i<search.length;i++) {
356*7485b225SElliott Hughes      const c = search.charAt(i);
357*7485b225SElliott Hughes      const cn = c.charCodeAt(0);
358*7485b225SElliott Hughes      if (c.match(/[a-z0-9\u0080-\uFFFF]/)) {
359*7485b225SElliott Hughes        result+=c;
360*7485b225SElliott Hughes      } else if (cn<16) {
361*7485b225SElliott Hughes        result+="_0"+cn.toString(16);
362*7485b225SElliott Hughes      } else {
363*7485b225SElliott Hughes        result+="_"+cn.toString(16);
364*7485b225SElliott Hughes      }
365*7485b225SElliott Hughes    }
366*7485b225SElliott Hughes    return result;
367*7485b225SElliott Hughes  }
368*7485b225SElliott Hughes
369*7485b225SElliott Hughes  // The number of matches from the last run of <Search()>.
370*7485b225SElliott Hughes  this.lastMatchCount = 0;
371*7485b225SElliott Hughes  this.lastKey = 0;
372*7485b225SElliott Hughes  this.repeatOn = false;
373*7485b225SElliott Hughes
374*7485b225SElliott Hughes  // Toggles the visibility of the passed element ID.
375*7485b225SElliott Hughes  this.FindChildElement = function(id) {
376*7485b225SElliott Hughes    const parentElement = document.getElementById(id);
377*7485b225SElliott Hughes    let element = parentElement.firstChild;
378*7485b225SElliott Hughes
379*7485b225SElliott Hughes    while (element && element!=parentElement) {
380*7485b225SElliott Hughes      if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') {
381*7485b225SElliott Hughes        return element;
382*7485b225SElliott Hughes      }
383*7485b225SElliott Hughes
384*7485b225SElliott Hughes      if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) {
385*7485b225SElliott Hughes        element = element.firstChild;
386*7485b225SElliott Hughes      } else if (element.nextSibling) {
387*7485b225SElliott Hughes        element = element.nextSibling;
388*7485b225SElliott Hughes      } else {
389*7485b225SElliott Hughes        do {
390*7485b225SElliott Hughes          element = element.parentNode;
391*7485b225SElliott Hughes        }
392*7485b225SElliott Hughes        while (element && element!=parentElement && !element.nextSibling);
393*7485b225SElliott Hughes
394*7485b225SElliott Hughes        if (element && element!=parentElement) {
395*7485b225SElliott Hughes          element = element.nextSibling;
396*7485b225SElliott Hughes        }
397*7485b225SElliott Hughes      }
398*7485b225SElliott Hughes    }
399*7485b225SElliott Hughes  }
400*7485b225SElliott Hughes
401*7485b225SElliott Hughes  this.Toggle = function(id) {
402*7485b225SElliott Hughes    const element = this.FindChildElement(id);
403*7485b225SElliott Hughes    if (element) {
404*7485b225SElliott Hughes      if (element.style.display == 'block') {
405*7485b225SElliott Hughes        element.style.display = 'none';
406*7485b225SElliott Hughes      } else {
407*7485b225SElliott Hughes        element.style.display = 'block';
408*7485b225SElliott Hughes      }
409*7485b225SElliott Hughes    }
410*7485b225SElliott Hughes  }
411*7485b225SElliott Hughes
412*7485b225SElliott Hughes  // Searches for the passed string.  If there is no parameter,
413*7485b225SElliott Hughes  // it takes it from the URL query.
414*7485b225SElliott Hughes  //
415*7485b225SElliott Hughes  // Always returns true, since other documents may try to call it
416*7485b225SElliott Hughes  // and that may or may not be possible.
417*7485b225SElliott Hughes  this.Search = function(search) {
418*7485b225SElliott Hughes    if (!search) { // get search word from URL
419*7485b225SElliott Hughes      search = window.location.search;
420*7485b225SElliott Hughes      search = search.substring(1);  // Remove the leading '?'
421*7485b225SElliott Hughes      search = unescape(search);
422*7485b225SElliott Hughes    }
423*7485b225SElliott Hughes
424*7485b225SElliott Hughes    search = search.replace(/^ +/, ""); // strip leading spaces
425*7485b225SElliott Hughes    search = search.replace(/ +$/, ""); // strip trailing spaces
426*7485b225SElliott Hughes    search = search.toLowerCase();
427*7485b225SElliott Hughes    search = convertToId(search);
428*7485b225SElliott Hughes
429*7485b225SElliott Hughes    const resultRows = document.getElementsByTagName("div");
430*7485b225SElliott Hughes    let matches = 0;
431*7485b225SElliott Hughes
432*7485b225SElliott Hughes    let i = 0;
433*7485b225SElliott Hughes    while (i < resultRows.length) {
434*7485b225SElliott Hughes      const row = resultRows.item(i);
435*7485b225SElliott Hughes      if (row.className == "SRResult") {
436*7485b225SElliott Hughes        let rowMatchName = row.id.toLowerCase();
437*7485b225SElliott Hughes        rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
438*7485b225SElliott Hughes
439*7485b225SElliott Hughes        if (search.length<=rowMatchName.length &&
440*7485b225SElliott Hughes          rowMatchName.substr(0, search.length)==search) {
441*7485b225SElliott Hughes          row.style.display = 'block';
442*7485b225SElliott Hughes          matches++;
443*7485b225SElliott Hughes        } else {
444*7485b225SElliott Hughes          row.style.display = 'none';
445*7485b225SElliott Hughes        }
446*7485b225SElliott Hughes      }
447*7485b225SElliott Hughes      i++;
448*7485b225SElliott Hughes    }
449*7485b225SElliott Hughes    document.getElementById("Searching").style.display='none';
450*7485b225SElliott Hughes    if (matches == 0) { // no results
451*7485b225SElliott Hughes      document.getElementById("NoMatches").style.display='block';
452*7485b225SElliott Hughes    } else { // at least one result
453*7485b225SElliott Hughes      document.getElementById("NoMatches").style.display='none';
454*7485b225SElliott Hughes    }
455*7485b225SElliott Hughes    this.lastMatchCount = matches;
456*7485b225SElliott Hughes    return true;
457*7485b225SElliott Hughes  }
458*7485b225SElliott Hughes
459*7485b225SElliott Hughes  // return the first item with index index or higher that is visible
460*7485b225SElliott Hughes  this.NavNext = function(index) {
461*7485b225SElliott Hughes    let focusItem;
462*7485b225SElliott Hughes    for (;;) {
463*7485b225SElliott Hughes      const focusName = 'Item'+index;
464*7485b225SElliott Hughes      focusItem = document.getElementById(focusName);
465*7485b225SElliott Hughes      if (focusItem && focusItem.parentNode.parentNode.style.display=='block') {
466*7485b225SElliott Hughes        break;
467*7485b225SElliott Hughes      } else if (!focusItem) { // last element
468*7485b225SElliott Hughes        break;
469*7485b225SElliott Hughes      }
470*7485b225SElliott Hughes      focusItem=null;
471*7485b225SElliott Hughes      index++;
472*7485b225SElliott Hughes    }
473*7485b225SElliott Hughes    return focusItem;
474*7485b225SElliott Hughes  }
475*7485b225SElliott Hughes
476*7485b225SElliott Hughes  this.NavPrev = function(index) {
477*7485b225SElliott Hughes    let focusItem;
478*7485b225SElliott Hughes    for (;;) {
479*7485b225SElliott Hughes      const focusName = 'Item'+index;
480*7485b225SElliott Hughes      focusItem = document.getElementById(focusName);
481*7485b225SElliott Hughes      if (focusItem && focusItem.parentNode.parentNode.style.display=='block') {
482*7485b225SElliott Hughes        break;
483*7485b225SElliott Hughes      } else if (!focusItem) { // last element
484*7485b225SElliott Hughes        break;
485*7485b225SElliott Hughes      }
486*7485b225SElliott Hughes      focusItem=null;
487*7485b225SElliott Hughes      index--;
488*7485b225SElliott Hughes    }
489*7485b225SElliott Hughes    return focusItem;
490*7485b225SElliott Hughes  }
491*7485b225SElliott Hughes
492*7485b225SElliott Hughes  this.ProcessKeys = function(e) {
493*7485b225SElliott Hughes    if (e.type == "keydown") {
494*7485b225SElliott Hughes      this.repeatOn = false;
495*7485b225SElliott Hughes      this.lastKey = e.keyCode;
496*7485b225SElliott Hughes    } else if (e.type == "keypress") {
497*7485b225SElliott Hughes      if (!this.repeatOn) {
498*7485b225SElliott Hughes        if (this.lastKey) this.repeatOn = true;
499*7485b225SElliott Hughes        return false; // ignore first keypress after keydown
500*7485b225SElliott Hughes      }
501*7485b225SElliott Hughes    } else if (e.type == "keyup") {
502*7485b225SElliott Hughes      this.lastKey = 0;
503*7485b225SElliott Hughes      this.repeatOn = false;
504*7485b225SElliott Hughes    }
505*7485b225SElliott Hughes    return this.lastKey!=0;
506*7485b225SElliott Hughes  }
507*7485b225SElliott Hughes
508*7485b225SElliott Hughes  this.Nav = function(evt,itemIndex) {
509*7485b225SElliott Hughes    const e  = (evt) ? evt : window.event; // for IE
510*7485b225SElliott Hughes    if (e.keyCode==13) return true;
511*7485b225SElliott Hughes    if (!this.ProcessKeys(e)) return false;
512*7485b225SElliott Hughes
513*7485b225SElliott Hughes    if (this.lastKey==38) { // Up
514*7485b225SElliott Hughes      const newIndex = itemIndex-1;
515*7485b225SElliott Hughes      let focusItem = this.NavPrev(newIndex);
516*7485b225SElliott Hughes      if (focusItem) {
517*7485b225SElliott Hughes        let child = this.FindChildElement(focusItem.parentNode.parentNode.id);
518*7485b225SElliott Hughes        if (child && child.style.display == 'block') { // children visible
519*7485b225SElliott Hughes          let n=0;
520*7485b225SElliott Hughes          let tmpElem;
521*7485b225SElliott Hughes          for (;;) { // search for last child
522*7485b225SElliott Hughes            tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
523*7485b225SElliott Hughes            if (tmpElem) {
524*7485b225SElliott Hughes              focusItem = tmpElem;
525*7485b225SElliott Hughes            } else { // found it!
526*7485b225SElliott Hughes              break;
527*7485b225SElliott Hughes            }
528*7485b225SElliott Hughes            n++;
529*7485b225SElliott Hughes          }
530*7485b225SElliott Hughes        }
531*7485b225SElliott Hughes      }
532*7485b225SElliott Hughes      if (focusItem) {
533*7485b225SElliott Hughes        focusItem.focus();
534*7485b225SElliott Hughes      } else { // return focus to search field
535*7485b225SElliott Hughes        document.getElementById("MSearchField").focus();
536*7485b225SElliott Hughes      }
537*7485b225SElliott Hughes    } else if (this.lastKey==40) { // Down
538*7485b225SElliott Hughes      const newIndex = itemIndex+1;
539*7485b225SElliott Hughes      let focusItem;
540*7485b225SElliott Hughes      const item = document.getElementById('Item'+itemIndex);
541*7485b225SElliott Hughes      const elem = this.FindChildElement(item.parentNode.parentNode.id);
542*7485b225SElliott Hughes      if (elem && elem.style.display == 'block') { // children visible
543*7485b225SElliott Hughes        focusItem = document.getElementById('Item'+itemIndex+'_c0');
544*7485b225SElliott Hughes      }
545*7485b225SElliott Hughes      if (!focusItem) focusItem = this.NavNext(newIndex);
546*7485b225SElliott Hughes      if (focusItem)  focusItem.focus();
547*7485b225SElliott Hughes    } else if (this.lastKey==39) { // Right
548*7485b225SElliott Hughes      const item = document.getElementById('Item'+itemIndex);
549*7485b225SElliott Hughes      const elem = this.FindChildElement(item.parentNode.parentNode.id);
550*7485b225SElliott Hughes      if (elem) elem.style.display = 'block';
551*7485b225SElliott Hughes    } else if (this.lastKey==37) { // Left
552*7485b225SElliott Hughes      const item = document.getElementById('Item'+itemIndex);
553*7485b225SElliott Hughes      const elem = this.FindChildElement(item.parentNode.parentNode.id);
554*7485b225SElliott Hughes      if (elem) elem.style.display = 'none';
555*7485b225SElliott Hughes    } else if (this.lastKey==27) { // Escape
556*7485b225SElliott Hughes      e.stopPropagation();
557*7485b225SElliott Hughes      searchBox.CloseResultsWindow();
558*7485b225SElliott Hughes      document.getElementById("MSearchField").focus();
559*7485b225SElliott Hughes    } else if (this.lastKey==13) { // Enter
560*7485b225SElliott Hughes      return true;
561*7485b225SElliott Hughes    }
562*7485b225SElliott Hughes    return false;
563*7485b225SElliott Hughes  }
564*7485b225SElliott Hughes
565*7485b225SElliott Hughes  this.NavChild = function(evt,itemIndex,childIndex) {
566*7485b225SElliott Hughes    const e  = (evt) ? evt : window.event; // for IE
567*7485b225SElliott Hughes    if (e.keyCode==13) return true;
568*7485b225SElliott Hughes    if (!this.ProcessKeys(e)) return false;
569*7485b225SElliott Hughes
570*7485b225SElliott Hughes    if (this.lastKey==38) { // Up
571*7485b225SElliott Hughes      if (childIndex>0) {
572*7485b225SElliott Hughes        const newIndex = childIndex-1;
573*7485b225SElliott Hughes        document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
574*7485b225SElliott Hughes      } else { // already at first child, jump to parent
575*7485b225SElliott Hughes        document.getElementById('Item'+itemIndex).focus();
576*7485b225SElliott Hughes      }
577*7485b225SElliott Hughes    } else if (this.lastKey==40) { // Down
578*7485b225SElliott Hughes      const newIndex = childIndex+1;
579*7485b225SElliott Hughes      let elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
580*7485b225SElliott Hughes      if (!elem) { // last child, jump to parent next parent
581*7485b225SElliott Hughes        elem = this.NavNext(itemIndex+1);
582*7485b225SElliott Hughes      }
583*7485b225SElliott Hughes      if (elem) {
584*7485b225SElliott Hughes        elem.focus();
585*7485b225SElliott Hughes      }
586*7485b225SElliott Hughes    } else if (this.lastKey==27) { // Escape
587*7485b225SElliott Hughes      e.stopPropagation();
588*7485b225SElliott Hughes      searchBox.CloseResultsWindow();
589*7485b225SElliott Hughes      document.getElementById("MSearchField").focus();
590*7485b225SElliott Hughes    } else if (this.lastKey==13) { // Enter
591*7485b225SElliott Hughes      return true;
592*7485b225SElliott Hughes    }
593*7485b225SElliott Hughes    return false;
594*7485b225SElliott Hughes  }
595*7485b225SElliott Hughes}
596*7485b225SElliott Hughes
597*7485b225SElliott Hughesfunction createResults(resultsPath) {
598*7485b225SElliott Hughes
599*7485b225SElliott Hughes  function setKeyActions(elem,action) {
600*7485b225SElliott Hughes    elem.setAttribute('onkeydown',action);
601*7485b225SElliott Hughes    elem.setAttribute('onkeypress',action);
602*7485b225SElliott Hughes    elem.setAttribute('onkeyup',action);
603*7485b225SElliott Hughes  }
604*7485b225SElliott Hughes
605*7485b225SElliott Hughes  function setClassAttr(elem,attr) {
606*7485b225SElliott Hughes    elem.setAttribute('class',attr);
607*7485b225SElliott Hughes    elem.setAttribute('className',attr);
608*7485b225SElliott Hughes  }
609*7485b225SElliott Hughes
610*7485b225SElliott Hughes  const results = document.getElementById("SRResults");
611*7485b225SElliott Hughes  results.innerHTML = '';
612*7485b225SElliott Hughes  searchData.forEach((elem,index) => {
613*7485b225SElliott Hughes    const id = elem[0];
614*7485b225SElliott Hughes    const srResult = document.createElement('div');
615*7485b225SElliott Hughes    srResult.setAttribute('id','SR_'+id);
616*7485b225SElliott Hughes    setClassAttr(srResult,'SRResult');
617*7485b225SElliott Hughes    const srEntry = document.createElement('div');
618*7485b225SElliott Hughes    setClassAttr(srEntry,'SREntry');
619*7485b225SElliott Hughes    const srLink = document.createElement('a');
620*7485b225SElliott Hughes    srLink.setAttribute('id','Item'+index);
621*7485b225SElliott Hughes    setKeyActions(srLink,'return searchResults.Nav(event,'+index+')');
622*7485b225SElliott Hughes    setClassAttr(srLink,'SRSymbol');
623*7485b225SElliott Hughes    srLink.innerHTML = elem[1][0];
624*7485b225SElliott Hughes    srEntry.appendChild(srLink);
625*7485b225SElliott Hughes    if (elem[1].length==2) { // single result
626*7485b225SElliott Hughes      srLink.setAttribute('href',resultsPath+elem[1][1][0]);
627*7485b225SElliott Hughes      srLink.setAttribute('onclick','searchBox.CloseResultsWindow()');
628*7485b225SElliott Hughes      if (elem[1][1][1]) {
629*7485b225SElliott Hughes       srLink.setAttribute('target','_parent');
630*7485b225SElliott Hughes      } else {
631*7485b225SElliott Hughes       srLink.setAttribute('target','_blank');
632*7485b225SElliott Hughes      }
633*7485b225SElliott Hughes      const srScope = document.createElement('span');
634*7485b225SElliott Hughes      setClassAttr(srScope,'SRScope');
635*7485b225SElliott Hughes      srScope.innerHTML = elem[1][1][2];
636*7485b225SElliott Hughes      srEntry.appendChild(srScope);
637*7485b225SElliott Hughes    } else { // multiple results
638*7485b225SElliott Hughes      srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
639*7485b225SElliott Hughes      const srChildren = document.createElement('div');
640*7485b225SElliott Hughes      setClassAttr(srChildren,'SRChildren');
641*7485b225SElliott Hughes      for (let c=0; c<elem[1].length-1; c++) {
642*7485b225SElliott Hughes        const srChild = document.createElement('a');
643*7485b225SElliott Hughes        srChild.setAttribute('id','Item'+index+'_c'+c);
644*7485b225SElliott Hughes        setKeyActions(srChild,'return searchResults.NavChild(event,'+index+','+c+')');
645*7485b225SElliott Hughes        setClassAttr(srChild,'SRScope');
646*7485b225SElliott Hughes        srChild.setAttribute('href',resultsPath+elem[1][c+1][0]);
647*7485b225SElliott Hughes        srChild.setAttribute('onclick','searchBox.CloseResultsWindow()');
648*7485b225SElliott Hughes        if (elem[1][c+1][1]) {
649*7485b225SElliott Hughes         srChild.setAttribute('target','_parent');
650*7485b225SElliott Hughes        } else {
651*7485b225SElliott Hughes         srChild.setAttribute('target','_blank');
652*7485b225SElliott Hughes        }
653*7485b225SElliott Hughes        srChild.innerHTML = elem[1][c+1][2];
654*7485b225SElliott Hughes        srChildren.appendChild(srChild);
655*7485b225SElliott Hughes      }
656*7485b225SElliott Hughes      srEntry.appendChild(srChildren);
657*7485b225SElliott Hughes    }
658*7485b225SElliott Hughes    srResult.appendChild(srEntry);
659*7485b225SElliott Hughes    results.appendChild(srResult);
660*7485b225SElliott Hughes  });
661*7485b225SElliott Hughes}
662*7485b225SElliott Hughes
663*7485b225SElliott Hughesfunction init_search() {
664*7485b225SElliott Hughes  const results = document.getElementById("MSearchSelectWindow");
665*7485b225SElliott Hughes
666*7485b225SElliott Hughes  results.tabIndex=0;
667*7485b225SElliott Hughes  for (let key in indexSectionLabels) {
668*7485b225SElliott Hughes    const link = document.createElement('a');
669*7485b225SElliott Hughes    link.setAttribute('class','SelectItem');
670*7485b225SElliott Hughes    link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
671*7485b225SElliott Hughes    link.href='javascript:void(0)';
672*7485b225SElliott Hughes    link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
673*7485b225SElliott Hughes    results.appendChild(link);
674*7485b225SElliott Hughes  }
675*7485b225SElliott Hughes
676*7485b225SElliott Hughes  const input = document.getElementById("MSearchSelect");
677*7485b225SElliott Hughes  const searchSelectWindow = document.getElementById("MSearchSelectWindow");
678*7485b225SElliott Hughes  input.tabIndex=0;
679*7485b225SElliott Hughes  input.addEventListener("keydown", function(event) {
680*7485b225SElliott Hughes    if (event.keyCode==13 || event.keyCode==40) {
681*7485b225SElliott Hughes      event.preventDefault();
682*7485b225SElliott Hughes      if (searchSelectWindow.style.display == 'block') {
683*7485b225SElliott Hughes        searchBox.CloseSelectionWindow();
684*7485b225SElliott Hughes      } else {
685*7485b225SElliott Hughes        searchBox.OnSearchSelectShow();
686*7485b225SElliott Hughes        searchBox.DOMSearchSelectWindow().focus();
687*7485b225SElliott Hughes      }
688*7485b225SElliott Hughes    }
689*7485b225SElliott Hughes  });
690*7485b225SElliott Hughes  const name = Cookie.readSetting(SEARCH_COOKIE_NAME,0);
691*7485b225SElliott Hughes  const id = searchBox.GetSelectionIdByName(name);
692*7485b225SElliott Hughes  searchBox.OnSelectItem(id);
693*7485b225SElliott Hughes}
694*7485b225SElliott Hughes/* @license-end */
695