annotate doc/html/search/search.js @ 117:ca2d83d29814 tip master

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