1jQuery.autocomplete = function(input, options) { 2 // Create a link to self 3 var me = this; 4 5 // Create jQuery object for input element 6 var $input = $(input).attr("autocomplete", "off"); 7 8 // Apply inputClass if necessary 9 if (options.inputClass) $input.addClass(options.inputClass); 10 11 // Create results 12 var results = document.createElement("div"); 13 // Create jQuery object for results 14 var $results = $(results); 15 $results.hide().addClass(options.resultsClass).css("position", "absolute"); 16 if( options.width > 0 ) $results.css("width", options.width); 17 18 // Add to body element 19 // $(".search-bar").append(results); 20 if (design == 17) { 21 $("body").append(results); 22 } else { 23 $(".search-bar").append(results); 24 } 25 26 input.autocompleter = me; 27 28 var timeout = null; 29 var prev = ""; 30 var active = -1; 31 var cache = {}; 32 var keyb = false; 33 var hasFocus = false; 34 var lastKeyPressCode = null; 35 36 // flush cache 37 function flushCache(){ 38 cache = {}; 39 cache.data = {}; 40 cache.length = 0; 41 }; 42 43 // flush cache 44 flushCache(); 45 46 // if there is a data array supplied 47 if( options.data != null ){ 48 var sFirstChar = "", stMatchSets = {}, row = []; 49 50 // no url was specified, we need to adjust the cache length to make sure it fits the local data store 51 if( typeof options.url != "string" ) options.cacheLength = 1; 52 53 // loop through the array and create a lookup structure 54 for( var i=0; i < options.data.length; i++ ){ 55 // if row is a string, make an array otherwise just reference the array 56 row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]); 57 58 // if the length is zero, don't add to list 59 if( row[0].length > 0 ){ 60 // get the first character 61 sFirstChar = row[0].substring(0, 1).toLowerCase(); 62 // if no lookup array for this character exists, look it up now 63 if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = []; 64 // if the match is a string 65 stMatchSets[sFirstChar].push(row); 66 } 67 } 68 69 // add the data items to the cache 70 for( var k in stMatchSets ){ 71 // increase the cache size 72 options.cacheLength++; 73 // add to the cache 74 addToCache(k, stMatchSets[k]); 75 } 76 } 77 78 $input 79 .keydown(function(e) { 80 // track last key pressed 81 lastKeyPressCode = e.keyCode; 82 switch(e.keyCode) { 83 case 38: // up 84 e.preventDefault(); 85 moveSelect(-1); 86 break; 87 case 40: // down 88 e.preventDefault(); 89 moveSelect(1); 90 break; 91 case 9: // tab 92 case 13: // return 93 if( selectCurrent() ){ 94 // make sure to blur off the current field 95 $input.get(0).blur(); 96 e.preventDefault(); 97 } 98 break; 99 default: 100 active = -1; 101 if (timeout) clearTimeout(timeout); 102 timeout = setTimeout(function(){onChange();}, options.delay); 103 break; 104 } 105 }) 106 .focus(function(){ 107 // track whether the field has focus, we shouldn't process any results if the field no longer has focus 108 hasFocus = true; 109 }) 110 .blur(function() { 111 // track whether the field has focus 112 hasFocus = false; 113 hideResults(); 114 }); 115 116 hideResultsNow(); 117 118 function onChange() { 119 // ignore if the following keys are pressed: [del] [shift] [capslock] 120 if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide(); 121 var v = $input.val(); 122 if (v == prev) return; 123 prev = v; 124 if (v.length >= options.minChars) { 125 $input.addClass(options.loadingClass); 126 requestData(v); 127 } else { 128 $input.removeClass(options.loadingClass); 129 $results.hide(); 130 } 131 }; 132 133 function scrollResultToActive(li) { 134 var container = $results.get(0); 135 136 if (!li || !container) { 137 return; 138 } 139 140 var liTop = li.offsetTop; 141 var liBottom = liTop + li.offsetHeight; 142 143 var visibleTop = container.scrollTop; 144 var visibleBottom = visibleTop + container.clientHeight; 145 146 if (liTop < visibleTop) { 147 container.scrollTop = liTop; 148 } else if (liBottom > visibleBottom) { 149 container.scrollTop = liBottom - container.clientHeight; 150 } 151 } 152 153 // function moveSelect(step) { 154 155 // var lis = $("li", results); 156 // if (!lis) return; 157 158 // active += step; 159 160 // if (active < 0) { 161 // active = 0; 162 // } else if (active >= lis.length) { 163 // active = lis.length- 1; 164 // } 165 166 // lis.removeClass("ac_over"); 167 168 // $(lis[active]).addClass("ac_over"); 169 170 // // Weird behaviour in IE 171 // // if (lis[active] && lis[active].scrollIntoView) { 172 // // lis[active].scrollIntoView(false); 173 // // } 174 175 // }; 176 177 function moveSelect(step) { 178 var lis = $("li", results); 179 180 if (!lis.length) { 181 return; 182 } 183 184 active += step; 185 186 if (active < 0) { 187 active = 0; 188 } else if (active >= lis.length) { 189 active = lis.length - 1; 190 } 191 192 lis.removeClass("ac_over"); 193 194 var activeLi = lis[active]; 195 196 $(activeLi).addClass("ac_over"); 197 198 scrollResultToActive(activeLi); 199 } 200 201 function selectCurrent() { 202 var li = $("li.ac_over", results)[0]; 203 if (!li) { 204 var $li = $("li", results); 205 if (options.selectOnly) { 206 if ($li.length == 1) li = $li[0]; 207 } else if (options.selectFirst) { 208 li = $li[0]; 209 } 210 } 211 if (li) { 212 selectItem(li); 213 return true; 214 } else { 215 return false;
216 } 217 }; 218 219 function selectItem(li) { 220 if (!li) { 221 li = document.createElement("li"); 222 li.extra = []; 223 li.selectValue = ""; 224 } 225 var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML); 226 input.lastSelected = v; 227 prev = v; 228 $results.html(""); 229 $input.val(v); 230 hideResultsNow(); 231 if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1); 232 }; 233 234 // selects a portion of the input string 235 function createSelection(start, end){ 236 // get a reference to the input element 237 var field = $input.get(0); 238 if( field.createTextRange ){ 239 var selRange = field.createTextRange(); 240 selRange.collapse(true); 241 selRange.moveStart("character", start); 242 selRange.moveEnd("character", end); 243 selRange.select(); 244 } else if( field.setSelectionRange ){ 245 field.setSelectionRange(start, end); 246 } else { 247 if( field.selectionStart ){ 248 field.selectionStart = start; 249 field.selectionEnd = end; 250 } 251 } 252 field.focus(); 253 }; 254 255 // fills in the input box w/the first match (assumed to be the best match) 256 function autoFill(sValue){ 257 // if the last user key pressed was backspace, don't autofill 258 if( lastKeyPressCode != 8 ){ 259 // fill in the value (keep the case the user has typed) 260 $input.val($input.val() + sValue.substring(prev.length)); 261 // select the portion of the value not typed by the user (so the next character will erase) 262 createSelection(prev.length, sValue.length); 263 } 264 }; 265 266 function showResults() { 267 // get the position of the input field right now (in case the DOM is shifted) 268 var pos = findPos(input); 269 // either use the specified width, or autocalculate based on form element 270 var iWidth = (options.width > 0) ? options.width : $input.width(); 271 272 // reposition 273 if (design == 3) { 274 if (window.innerWidth >= 946 && window.innerWidth <= 1025) { 275 $results.css({ 276 width: parseInt(iWidth) + "px", 277 // top: "-"+(input.offsetHeight) + "px", 278 top: "-" + (pos.y + pos.x) + "px", 279 height: "min-content", 280 // left: pos.x + "px" 281 }).show(); 282 } else { 283 if (window.innerWidth >= 790 && window.innerWidth <= 945) { 284 $results.css({ 285 width: parseInt(iWidth) + "px", 286 top: "-" + (pos.y - input.offsetHeight + pos.x) + "px", 287 // top: "-"+(pos.y - pos.x/3) + "px", 288 // top: "-"+(input.offsetHeight) + "px", 289 // top: "-" + (pos.y + pos.x - pos.x/3) + "px", 290 height: "min-content", 291 // left: pos.x + "px" 292 }).show(); 293 } else { 294 if (window.innerWidth >= 755 && window.innerWidth <= 789) { 295 $results.css({ 296 width: parseInt(iWidth) + "px", 297 // top: "-" + (pos.y - input.offsetHeight + pos.x) + "px", 298 top: "-"+(pos.y - pos.x) + "px", 299 // top: "-"+(input.offsetHeight) + "px", 300 // top: "-" + (pos.y + pos.x - pos.x/3) + "px", 301 height: "min-content", 302 // left: pos.x + "px" 303 }).show(); 304 } else { 305 if (window.innerWidth >= 630 && window.innerWidth <= 754) { 306 $results.css({ 307 width: parseInt(iWidth) + "px", 308 // top: "-" + (pos.y - input.offsetHeight + pos.x) + "px", 309 // top: "-"+(pos.y - pos.x) + "px", 310 top: "-"+(pos.y - input.offsetHeight) + "px", 311 // top: "-" + (pos.y + pos.x - pos.x/3) + "px", 312 height: "min-content", 313 // left: pos.x + "px" 314 }).show(); 315 } else { 316 if (window.innerWidth >= 530 && window.innerWidth <= 629) { 317 $results.css({ 318 width: parseInt(iWidth) + "px", 319 // top: "-" + (pos.y - input.offsetHeight + pos.x) + "px", 320 // top: "-"+(pos.y - pos.x) + "px", 321 top: "-" + (input.offsetHeight + pos.x) + "px", 322 // top: "-" + (pos.y + pos.x - pos.x/3) + "px", 323 height: "min-content", 324 // left: pos.x + "px" 325 }).show(); 326 } else { 327 $results.css({ 328 width: parseInt(iWidth) + "px", 329 top: "-" + (input.offsetHeight) + "px", 330 // top: (pos.y + input.offsetHeight) + "px", 331 height: "min-content", 332 // left: pos.x + "px" 333 }).show(); 334 } 335 } 336 } 337 } 338 } 339 } else if (design == 6) { 340 $results.css({ 341 width: parseInt(iWidth + 60) + "px", 342 height: "min-content", 343 }).show(); 344 } else { 345 if (window.innerWidth >= 600 && window.innerWidth <= 1025 && design == 2) { 346 $results.css({ 347 width: parseInt(iWidth) + "px", 348 // top: (input.offsetHeight) + "px", 349 top: "-2%", 350 height: "min-content", 351 left: "-2%", 352 }).show(); 353 } else { 354 $results.css({ 355 width: parseInt(iWidth) + "px", 356 top: (input.offsetHeight) + "px", 357 // top: (pos.y + input.offsetHeight) + "px", 358 height: "min-content", 359 // left: pos.x + "px" 360 }).show(); 361 } 362 } 363 }; 364 365 function showResultsNew() { 366 var inputEl = $input.get(0); 367 368 if (!inputEl) { 369 return; 370 } 371 372 var rect = inputEl.getBoundingClientRect(); 373 var searchBarRect = $(".search-bar").get(0).getBoundingClientRect(); 374 var gap = 8; 375 376 // var iWidth = (options.width > 0) ? options.width : $input.outerWidth(); 377 var iWidth = searchBarRect.width; 378 379 if (design == 6) { 380 iWidth += 60; 381 } 382 383 $results.css({ 384 position: "fixed", 385 width: parseInt(iWidth) + "px", 386 left: searchBarRect.left + "px", 387 boxSizing: "border-box", 388 top: "auto", 389 bottom: "auto", 390 // height: "auto", 391 // maxHeight: "none", 392 overflowY: "visible", 393 visibility: "hidden", 394 display: "block" 395 }); 396 397 var resultsHeight = $results.outerHeight(); 398 399 var spaceBelow = window.innerHeight - rect.bottom - gap;
400 var spaceAbove = rect.top - gap; 401 402 var showAbove = resultsHeight > spaceBelow && spaceAbove > spaceBelow; 403 404 var availableHeight = showAbove ? spaceAbove : spaceBelow; 405 var finalHeight = Math.min(resultsHeight, availableHeight); 406 407 if (showAbove) { 408 $results.css({ 409 top: Math.max(gap, rect.top - finalHeight - gap) - 5 + "px", 410 bottom: "auto", 411 // maxHeight: Math.max(80, availableHeight) + "px", 412 overflowY: "scroll", 413 visibility: "visible", 414 display: "block" 415 }); 416 } else { 417 $results.css({ 418 top: rect.bottom + gap + 5 + "px", 419 bottom: "auto", 420 // maxHeight: Math.max(80, availableHeight) + "px", 421 overflowY: "scroll", 422 visibility: "visible", 423 display: "block" 424 }); 425 } 426 }; 427 428 function repositionResults() { 429 if (design == 17 && $results.is(":visible") && hasFocus) { 430 showResultsNew(); 431 } 432 } 433 434 $(window).on("scroll resize", repositionResults); 435 436 // ÐÐ»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½ÑÑ scroll-конÑейнеÑов нÑжен native addEventListener 437 document.addEventListener("scroll", repositionResults, true); 438 439 function hideResults() { 440 if (timeout) clearTimeout(timeout); 441 timeout = setTimeout(hideResultsNow, 200); 442 }; 443 444 function hideResultsNow() { 445 if (timeout) clearTimeout(timeout); 446 $input.removeClass(options.loadingClass); 447 if ($results.is(":visible")) { 448 $results.hide(); 449 } 450 if (options.mustMatch) { 451 var v = $input.val(); 452 if (v != input.lastSelected) { 453 selectItem(null); 454 } 455 } 456 }; 457 458 function receiveData(q, data) { 459 if (data) { 460 $input.removeClass(options.loadingClass); 461 results.innerHTML = ""; 462 463 // if the field no longer has focus or if there are no matches, do not display the drop down 464 if( !hasFocus || data.length == 0 ) return hideResultsNow(); 465 466 if ($.browser.msie) { 467 // we put a styled iframe behind the calendar so HTML SELECT elements don't show through 468 $results.append(document.createElement('iframe')); 469 } 470 results.appendChild(dataToDom(data)); 471 // autofill in the complete box w/the first match as long as the user hasn't entered in more data 472 if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]); 473 474 if (design == 17) { 475 showResultsNew(); 476 477 // function repositionResults() { 478 // if ($results.is(":visible") && hasFocus) { 479 // showResultsNew(); 480 // } 481 // } 482 483 // $(window).on("scroll resize", repositionResults); 484 485 // $(document).on("scroll", repositionResults, true); 486 } else { 487 showResults(); 488 } 489 490 } else { 491 hideResultsNow(); 492 } 493 }; 494 495 function parseData(data) { 496 if (!data) return null; 497 var parsed = []; 498 var rows = data.split(options.lineSeparator); 499 for (var i=0; i < rows.length; i++) { 500 var row = $.trim(rows[i]); 501 if (row) { 502 parsed[parsed.length] = row.split(options.cellSeparator); 503 } 504 } 505 return parsed; 506 }; 507 508 function dataToDom(data) { 509 var ul = document.createElement("ul"); 510 var num = data.length; 511 512 // limited results to a max number 513 if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow; 514 515 for (var i=0; i < num; i++) { 516 var row = data[i]; 517 if (!row) continue; 518 var li = document.createElement("li"); 519 if (options.formatItem) { 520 li.innerHTML = options.formatItem(row, i, num); 521 li.selectValue = row[0]; 522 } else { 523 li.innerHTML = row[0]; 524 li.selectValue = row[0]; 525 } 526 var extra = null; 527 if (row.length > 1) { 528 extra = []; 529 for (var j=1; j < row.length; j++) { 530 extra[extra.length] = row[j]; 531 } 532 } 533 li.extra = extra; 534 ul.appendChild(li); 535 $(li).hover( 536 function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); }, 537 function() { $(this).removeClass("ac_over"); } 538 ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) }); 539 } 540 return ul; 541 }; 542 543 function requestData(q) { 544 if (!options.matchCase) q = q.toLowerCase(); 545 var data = options.cacheLength ? loadFromCache(q) : null; 546 // recieve the cached data 547 if (data) { 548 receiveData(q, data); 549 // if an AJAX url has been supplied, try loading the data now 550 } else if( (typeof options.url == "string") && (options.url.length > 0) ){ 551 $.get(makeUrl(q), function(data) { 552 data = parseData(data); 553 addToCache(q, data); 554 receiveData(q, data); 555 }); 556 // if there's been no data found, remove the loading class 557 } else { 558 $input.removeClass(options.loadingClass); 559 } 560 }; 561 562 function makeUrl(q) { 563 var url = options.url + "?q=" + encodeURI(q); 564 for (var i in options.extraParams) { 565 url += "&" + i + "=" + encodeURI(options.extraParams[i]); 566 } 567 return url; 568 }; 569 570 function loadFromCache(q) { 571 if (!q) return null; 572 if (cache.data[q]) return cache.data[q]; 573 if (options.matchSubset) { 574 for (var i = q.length - 1; i >= options.minChars; i--) { 575 var qs = q.substr(0, i); 576 var c = cache.data[qs]; 577 if (c) { 578 var csub = []; 579 for (var j = 0; j < c.length; j++) { 580 var x = c[j]; 581 var x0 = x[0]; 582 if (matchSubset(x0, q)) { 583 csub[csub.length] = x; 584 } 585 } 586 return csub; 587 } 588 } 589 } 590 return null; 591 }; 592 593 function matchSubset(s, sub) { 594 if (!options.matchCase) s = s.toLowerCase(); 595 var i = s.indexOf(sub); 596 if (i == -1) return false;
597 return i == 0 || options.matchContains; 598 }; 599 600 this.flushCache = function() { 601 flushCache(); 602 }; 603 604 this.setExtraParams = function(p) { 605 options.extraParams = p; 606 }; 607 608 this.findValue = function(){ 609 var q = $input.val(); 610 611 if (!options.matchCase) q = q.toLowerCase(); 612 var data = options.cacheLength ? loadFromCache(q) : null; 613 if (data) { 614 findValueCallback(q, data); 615 } else if( (typeof options.url == "string") && (options.url.length > 0) ){ 616 $.get(makeUrl(q), function(data) { 617 data = parseData(data) 618 addToCache(q, data); 619 findValueCallback(q, data); 620 }); 621 } else { 622 // no matches 623 findValueCallback(q, null); 624 } 625 } 626 627 function findValueCallback(q, data){ 628 if (data) $input.removeClass(options.loadingClass); 629 630 var num = (data) ? data.length : 0; 631 var li = null; 632 633 for (var i=0; i < num; i++) { 634 var row = data[i]; 635 636 if( row[0].toLowerCase() == q.toLowerCase() ){ 637 li = document.createElement("li"); 638 if (options.formatItem) { 639 li.innerHTML = options.formatItem(row, i, num); 640 li.selectValue = row[0]; 641 } else { 642 li.innerHTML = row[0]; 643 li.selectValue = row[0]; 644 } 645 var extra = null; 646 if( row.length > 1 ){ 647 extra = []; 648 for (var j=1; j < row.length; j++) { 649 extra[extra.length] = row[j]; 650 } 651 } 652 li.extra = extra; 653 } 654 } 655 656 if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1); 657 } 658 659 function addToCache(q, data) { 660 if (!data || !q || !options.cacheLength) return; 661 if (!cache.length || cache.length > options.cacheLength) { 662 flushCache(); 663 cache.length++; 664 } else if (!cache[q]) { 665 cache.length++; 666 } 667 cache.data[q] = data; 668 }; 669 670 function findPos(obj) { 671 var curleft = obj.offsetLeft || 0; 672 var curtop = obj.offsetTop || 0; 673 while (obj = obj.offsetParent) { 674 curleft += obj.offsetLeft 675 curtop += obj.offsetTop 676 } 677 return {x:curleft,y:curtop}; 678 } 679} 680 681jQuery.fn.autocomplete = function(url, options, data) { 682 // Make sure options exists 683 options = options || {}; 684 // Set url as option 685 options.url = url; 686 // set some bulk local data 687 options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null; 688 689 // Set default values for required options 690 options.inputClass = options.inputClass || "ac_input"; 691 options.resultsClass = options.resultsClass || "ac_results"; 692 options.lineSeparator = options.lineSeparator || "\n"; 693 options.cellSeparator = options.cellSeparator || "|"; 694 options.minChars = options.minChars || 1; 695 options.delay = options.delay || 400; 696 options.matchCase = options.matchCase || 0; 697 options.matchSubset = options.matchSubset || 1; 698 options.matchContains = options.matchContains || 0; 699 options.cacheLength = options.cacheLength || 1; 700 options.mustMatch = options.mustMatch || 0; 701 options.extraParams = options.extraParams || {}; 702 options.loadingClass = options.loadingClass || "ac_loading"; 703 options.selectFirst = options.selectFirst || false; 704 options.selectOnly = options.selectOnly || false; 705 options.maxItemsToShow = options.maxItemsToShow || -1; 706 options.autoFill = options.autoFill || false; 707 options.width = parseInt(options.width, 10) || 0; 708 709 this.each(function() { 710 var input = this; 711 new jQuery.autocomplete(input, options); 712 }); 713 714 // Don't break the chain 715 return this; 716} 717 718jQuery.fn.autocompleteArray = function(data, options) { 719 return this.autocomplete(null, options, data); 720} 721 722jQuery.fn.indexOf = function(e){ 723 for( var i=0; i<this.length; i++ ){ 724 if( this[i] == e ) return i; 725 } 726 return -1; 727};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.