1/** 2 * author: Timothy Groves - http://www.brandspankingnew.net 3 * version: 1.2 - 2006-11-17 4 * 1.3 - 2006-12-04 5 * 2.0 - 2007-02-07 6 * 2.1.1 - 2007-04-13 7 * 2.1.2 - 2007-07-07 8 * 2.1.3 - 2007-07-19 9 * 10 */ 11 12 var global_iHigh = 0; 13 14 15if (typeof(bsn) == "undefined") 16 _b = bsn = {}; 17 18if (typeof(_b.Autosuggest) == "undefined") 19 _b.Autosuggest = {}; 20else 21 alert("Autosuggest is already set!"); 22 23_b.AutoSuggest = function (id, param) 24{ 25 // no DOM - give up! 26 // 27 if (!document.getElementById) 28 return 0; 29 30 // get field via DOM 31 // 32 this.fld = _b.DOM.gE(id); 33 34 if (!this.fld) 35 return 0; 36 37 // init variables 38 // 39 this.sInp = ""; 40 this.nInpC = 0; 41 this.aSug = []; 42 this.iHigh = 0; 43 44 45 46 47 // parameters object 48 // 49 this.oP = param ? param : {}; 50 51 // defaults 52 // 53 var k, def = {minchars:1, meth:"get", varname:"input", className:"autosuggest", timeout:2500, delay:500, offsety:-5, shownoresults: true, noresults: "No results!", maxheight: 250, cache: true, maxentries: 25}; 54 for (k in def) 55 { 56 if (typeof(this.oP[k]) != typeof(def[k])) 57 this.oP[k] = def[k]; 58 } 59 60 // set keyup handler for field 61 // and prevent autocomplete from client 62 // 63 var p = this; 64 65 // NOTE: not using addEventListener because UpArrow fired twice in Safari 66 //_b.DOM.addEvent( this.fld, 'keyup', function(ev){ return pointer.onKeyPress(ev); } ); 67 68 this.fld.onkeypress = function(ev){ return p.onKeyPress(ev); }; 69 this.fld.onkeyup = function(ev){ return p.onKeyUp(ev); }; 70 71 this.fld.setAttribute("autocomplete","off"); 72}; 73 74_b.AutoSuggest.prototype.onKeyPress = function(ev) 75{ 76 var key = (window.event) ? window.event.keyCode : ev.keyCode; 77 78 // set responses to keydown events in the field 79 // this allows the user to use the arrow keys to scroll through the results 80 // ESCAPE clears the list 81 // TAB sets the current highlighted value 82 // 83 var RETURN = 13; 84 var TAB = 9; 85 var ESC = 27; 86 87 var bubble = 1; 88 89 switch(key) 90 { 91 case RETURN: 92 this.setHighlightedValue(); 93 bubble = 0; 94 break; 95 96 case ESC: 97 this.clearSuggestions(); 98 break; 99 } 100 101 return bubble; 102}; 103 104_b.AutoSuggest.prototype.onKeyUp = function(ev) 105{ 106 var key = (window.event) ? window.event.keyCode : ev.keyCode; 107 108 // set responses to keydown events in the field 109 // this allows the user to use the arrow keys to scroll through the results 110 // ESCAPE clears the list 111 // TAB sets the current highlighted value 112 // 113 114 var ARRUP = 38; 115 var ARRDN = 40; 116 117 var bubble = 1; 118 119 switch(key) 120 { 121 case ARRUP: 122 this.changeHighlight(key); 123 bubble = 0; 124 break; 125 126 case ARRDN: 127 this.changeHighlight(key); 128 bubble = 0; 129 break; 130 131 default: 132 this.getSuggestions(this.fld.value); 133 } 134 135 return bubble; 136 137 138}; 139 140_b.AutoSuggest.prototype.getSuggestions = function (val) 141{ 142 // if input stays the same, do nothing 143 // 144 if (val == this.sInp) 145 return 0; 146 147 // kill list 148 // 149 _b.DOM.remE(this.idAs); 150 151 this.sInp = val; 152 153 // input length is less than the min required to trigger a request 154 // do nothing 155 // 156 if (val.length < this.oP.minchars) 157 { 158 this.aSug = []; 159 this.nInpC = val.length; 160 return 0; 161 } 162 163 var ol = this.nInpC; // old length 164 this.nInpC = val.length ? val.length : 0; 165 166 // if caching enabled, and user is typing (ie. length of input is increasing) 167 // filter results out of aSuggestions from last request 168 // 169 var l = this.aSug.length; 170 if (this.nInpC > ol && l && l<this.oP.maxentries && this.oP.cache) 171 { 172 var arr = []; 173 for (var i=0;i<l;i++) 174 { 175 if(this.aSug[i].value.toLowerCase().indexOf(val.toLowerCase()) != -1) 176 arr.push( this.aSug[i] ); 177 } 178 this.aSug = arr; 179 180 this.createList(this.aSug); 181 182 return false; 183 } 184 else 185 // do new request 186 // 187 { 188 var pointer = this; 189 var input = this.sInp; 190 clearTimeout(this.ajID); 191 this.ajID = setTimeout( function() { pointer.doAjaxRequest(input) }, this.oP.delay ); 192 } 193 194 return false; 195}; 196 197 198 199 200 201_b.AutoSuggest.prototype.doAjaxRequest = function (input) 202{ 203 // check that saved input is still the value of the field 204 // 205 if (input != this.fld.value) 206 return false; 207 208 209 var pointer = this; 210 211 212 // create ajax request 213 // 214 if (typeof(this.oP.script) == "function") 215 var url = this.oP.script(encodeURIComponent(this.sInp)); 216 else 217 var url = this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp); 218 219 if (!url) 220 return false;
221 222 var meth = this.oP.meth; 223 var input = this.sInp; 224 225 var onSuccessFunc = function (req) { pointer.setSuggestions(req, input) }; 226 var onErrorFunc = function (status) { alert("AJAX error: "+status); }; 227 228 var myAjax = new _b.Ajax(); 229 myAjax.makeRequest( url, meth, onSuccessFunc, onErrorFunc ); 230}; 231 232 233 234 235 236_b.AutoSuggest.prototype.setSuggestions = function (req, input) 237{ 238 // if field input no longer matches what was passed to the request 239 // don't show the suggestions 240 // 241 if (input != this.fld.value) 242 return false; 243 244 245 this.aSug = []; 246 247 248 if (this.oP.json) 249 { 250 var jsondata = eval('(' + req.responseText + ')'); 251 252 for (var i=0;i<jsondata.results.length;i++) 253 { 254 this.aSug.push( { 'id':jsondata.results[i].id, 'value':jsondata.results[i].value, 'info':jsondata.results[i].info } ); 255 } 256 } 257 else 258 { 259 260 var xml = req.responseXML; 261 262 // traverse xml 263 // 264 var results = xml.getElementsByTagName('results')[0].childNodes; 265 266 for (var i=0;i<results.length;i++) 267 { 268 if (results[i].hasChildNodes()) 269 this.aSug.push( { 'id':results[i].getAttribute('id'), 'value':results[i].childNodes[0].nodeValue, 'info':results[i].getAttribute('info') } ); 270 } 271 272 } 273 274 this.idAs = "as_"+this.fld.id; 275 276 277 this.createList(this.aSug); 278 279}; 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294_b.AutoSuggest.prototype.createList = function(arr) 295{ 296 var pointer = this; 297 298 299 300 301 // get rid of old list 302 // and clear the list removal timeout 303 // 304 _b.DOM.remE(this.idAs); 305 this.killTimeout(); 306 307 308 // if no results, and shownoresults is false, do nothing 309 // 310 if (arr.length == 0 && !this.oP.shownoresults) 311 return false; 312 313 314 // create holding div 315 // 316 var div = _b.DOM.cE("div", {id:this.idAs, className:this.oP.className}); 317 318 var hcorner = _b.DOM.cE("div", {className:"as_corner"}); 319 var hbar = _b.DOM.cE("div", {className:"as_bar"}); 320 var header = _b.DOM.cE("div", {className:"as_header"}); 321 header.appendChild(hcorner); 322 header.appendChild(hbar); 323 div.appendChild(header); 324 325 326 327 328 // create and populate ul 329 // 330 var ul = _b.DOM.cE("ul", {id:"as_ul"}); 331 332 333 334 335 // loop throught arr of suggestions 336 // creating an LI element for each suggestion 337 // 338 for (var i=0;i<arr.length;i++) 339 { 340 // format output with the input enclosed in a EM element 341 // (as HTML, not DOM) 342 // 343 var val = arr[i].value; 344 var st = val.toLowerCase().indexOf( this.sInp.toLowerCase() ); 345 var output = val.substring(0,st) + "<em>" + val.substring(st, st+this.sInp.length) + "</em>" + val.substring(st+this.sInp.length); 346 347 348 var span = _b.DOM.cE("span", {}, output, true); 349 if (arr[i].info != "") 350 { 351 var br = _b.DOM.cE("br", {}); 352 span.appendChild(br); 353 var small = _b.DOM.cE("small", {}, arr[i].info); 354 span.appendChild(small); 355 } 356 357 var a = _b.DOM.cE("a", { href:"#" }); 358 359 var tl = _b.DOM.cE("span", {className:"tl"}, " "); 360 var tr = _b.DOM.cE("span", {className:"tr"}, " "); 361 a.appendChild(tl); 362 a.appendChild(tr); 363 364 a.appendChild(span); 365 366 a.name = i+1; 367 a.onclick = function () { pointer.setHighlightedValue(); return false; }; 368 a.onmouseover = function () { pointer.setHighlight(this.name); }; 369 370 var li = _b.DOM.cE( "li", {}, a ); 371 372 ul.appendChild( li ); 373 } 374 375 376 // no results 377 // 378 if (arr.length == 0 && this.oP.shownoresults) 379 { 380 var li = _b.DOM.cE( "li", {className:"as_warning"}, this.oP.noresults ); 381 ul.appendChild( li ); 382 } 383 384 385 div.appendChild( ul ); 386 387 388 var fcorner = _b.DOM.cE("div", {className:"as_corner"}); 389 var fbar = _b.DOM.cE("div", {className:"as_bar"}); 390 var footer = _b.DOM.cE("div", {className:"as_footer"}); 391 footer.appendChild(fcorner); 392 footer.appendChild(fbar); 393 div.appendChild(footer); 394 395 396 397 // get position of target textfield 398 // position holding div below it 399 // set width of holding div to width of field 400 // 401 var pos = _b.DOM.getPos(this.fld); 402 403 div.style.left = pos.x + "px"; 404 div.style.top = ( pos.y + this.fld.offsetHeight + this.oP.offsety ) + "px"; 405 div.style.left=(this.oP.offsetx)+"px"; 406 div.style.width=this.oP.boxwidth+"px"; 407 408 // set mouseover functions for div 409 // when mouse pointer leaves div, set a timeout to remove the list after an interval 410 // when mouse enters div, kill the timeout so the list won't be removed 411 // 412 div.onmouseover = function(){ pointer.killTimeout() }; 413 div.onmouseout = function(){ pointer.resetTimeout() }; 414 415 416 // add DIV to document 417 // 418 document.getElementsByTagName("body")[0].appendChild(div); 419 420 421 422 // currently no item is highlighted 423 // 424 this.iHigh = 0; 425 426 427 428 429 430 431 // remove list after an interval 432 // 433 var pointer = this; 434 this.toID = setTimeout(function () { pointer.clearSuggestions() }
434, this.oP.timeout); 435}; 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451_b.AutoSuggest.prototype.changeHighlight = function(key) 452{ 453 var list = _b.DOM.gE("as_ul"); 454 455 if (!list) 456 return false; 457 458 var n; 459 460 if (key == 40) 461 n = this.iHigh + 1; 462 else if (key == 38) 463 n = this.iHigh - 1; 464 465 if (n > list.childNodes.length) 466 n = list.childNodes.length; 467 if (n < 1) 468 n = 0; 469 470 this.setHighlight(n); 471}; 472 473 474 475_b.AutoSuggest.prototype.setHighlight = function(n) 476{ 477 var list = _b.DOM.gE("as_ul"); 478 if (!list) 479 return false; 480 481 if (this.iHigh > 0) 482 this.clearHighlight(); 483 484 this.iHigh = Number(n); 485 486 // MOD: variabile globale per far funzionare 'onEnter' sul form di ricerca 487 global_iHigh = this.iHigh; 488 489 list.childNodes[this.iHigh-1].className = "as_highlight"; 490 491 this.killTimeout(); 492}; 493 494 495_b.AutoSuggest.prototype.clearHighlight = function() 496{ 497 var list = _b.DOM.gE("as_ul"); 498 if (!list) 499 return false; 500 501 if (this.iHigh > 0) 502 { 503 list.childNodes[this.iHigh-1].className = ""; 504 this.iHigh = 0; 505 } 506}; 507 508 509_b.AutoSuggest.prototype.setHighlightedValue = function () 510{ 511 if (this.iHigh) 512 { 513 //this.sInp = this.fld.value = this.aSug[ this.iHigh-1 ].value; 514 515 // move cursor to end of input (safari) 516 // 517 this.fld.focus(); 518 if (this.fld.selectionStart) 519 this.fld.setSelectionRange(this.sInp.length, this.sInp.length); 520 521 this.clearSuggestions(); 522 523 // pass selected object to callback function, if exists 524 // 525 if (typeof(this.oP.callback) == "function") 526 this.oP.callback( this.aSug[this.iHigh-1] ); 527 } 528}; 529 530 531 532 533 534 535 536 537 538 539 540 541 542_b.AutoSuggest.prototype.killTimeout = function() 543{ 544 clearTimeout(this.toID); 545}; 546 547_b.AutoSuggest.prototype.resetTimeout = function() 548{ 549 clearTimeout(this.toID); 550 var pointer = this; 551 this.toID = setTimeout(function () { pointer.clearSuggestions() }, 1000); 552}; 553 554 555 556 557 558 559 560_b.AutoSuggest.prototype.clearSuggestions = function () 561{ 562 563 this.killTimeout(); 564 565 var ele = _b.DOM.gE(this.idAs); 566 var pointer = this; 567 if (ele) 568 { 569 var fade = new _b.Fader(ele,1,0,250,function () { _b.DOM.remE(pointer.idAs) }); 570 } 571}; 572 573 574 575 576 577 578 579 580 581 582// AJAX PROTOTYPE _____________________________________________ 583 584 585if (typeof(_b.Ajax) == "undefined") 586 _b.Ajax = {}; 587 588 589 590_b.Ajax = function () 591{ 592 this.req = {}; 593 this.isIE = false; 594}; 595 596 597 598_b.Ajax.prototype.makeRequest = function (url, meth, onComp, onErr) 599{ 600 601 if (meth != "POST") 602 meth = "GET"; 603 604 this.onComplete = onComp; 605 this.onError = onErr; 606 607 var pointer = this; 608 609 // branch for native XMLHttpRequest object 610 if (window.XMLHttpRequest) 611 { 612 this.req = new XMLHttpRequest(); 613 this.req.onreadystatechange = function () { pointer.processReqChange() }; 614 this.req.open("GET", url, true); // 615 this.req.send(null); 616 // branch for IE/Windows ActiveX version 617 } 618 else if (window.ActiveXObject) 619 { 620 this.req = new ActiveXObject("Microsoft.XMLHTTP"); 621 if (this.req) 622 { 623 this.req.onreadystatechange = function () { pointer.processReqChange() }; 624 this.req.open(meth, url, true); 625 this.req.send(); 626 } 627 } 628}; 629 630 631_b.Ajax.prototype.processReqChange = function() 632{ 633 634 // only if req shows "loaded" 635 if (this.req.readyState == 4) { 636 // only if "OK" 637 if (this.req.status == 200) 638 { 639 this.onComplete( this.req ); 640 } else { 641 this.onError( this.req.status ); 642 } 643 } 644}; 645 646 647 648 649 650 651 652 653 654 655// DOM PROTOTYPE _____________________________________________ 656 657 658if (typeof(_b.DOM) == "undefined") 659 _b.DOM = {}; 660 661 662 663/* create element */ 664_b.DOM.cE = function ( type, attr, cont, html ) 665{ 666 var ne = document.createElement( type ); 667 if (!ne) 668 return 0; 669 670 for (var a in attr) 671 ne[a] = attr[a]; 672 673 var t = typeof(cont); 674 675 if (t == "string" && !html) 676 ne.appendChild( document.createTextNode(cont) ); 677 else if (t == "string" && html) 678 ne.innerHTML = cont; 679 else if (t == "object") 680 ne.appendChild( cont ); 681 682 return ne; 683}; 684 685 686 687/* get element */ 688_b.DOM.gE = function ( e ) 689{ 690 var t=typeof(e); 691 if (t == "undefined") 692 return 0; 693 else if (t == "string") 694 { 695 var re = document.getElementById( e ); 696 if (!re) 697 return 0; 698 else if (typeof(re.appendChild) != "undefined" ) 699 return re; 700 else 701 return 0; 702 } 703 else if (typeof(e.appendChild) != "undefined") 704 return e; 705 else 706 return 0; 707}; 708 709 710 711/* remove element */ 712_b.DOM.remE = function ( ele ) 713{ 714 var e = this.gE(ele); 715 716 if (!e) 717 return 0; 718 else if (e.parentNode.removeChild(e)) 719 return true; 720 else 721 return 0; 722}; 723 724 725 726/* get position */ 727_b.DOM.getPos = function ( e ) 728{ 729 var e = this.gE(e); 730 731 var obj = e; 732 733 var curleft = 0; 734 if (obj.offsetParent) 735 { 736 while (obj.offsetParent) 737 { 738 curleft += obj.offsetLeft; 739 obj = obj.offsetParent; 740 } 741 } 742 else if (obj.x) 743 curleft += obj.x; 744 745 var obj = e; 746 747 var curtop = 0; 748 if (obj.offsetParent) 749 { 750 while (obj.offsetParent) 751 { 752 curtop += obj.offsetTop; 753 obj = obj.offsetParent; 754 } 755 } 756 else if (obj.y) 757 curtop += obj.y; 758 759 return {x:curleft, y:curtop}; 760}; 761 762 763 764 765 766 767 768 769 770 771// FADER PROTOTYPE _____________________________________________ 772 773 774 775if (typeof(_b.Fader) == "undefined") 776 _b.Fader = {}; 777 778 779 780 781 782_b.Fader = function (ele, from, to, fadetime, callback) 783{ 784 if (!ele) 785 return 0; 786 787 this.e = ele; 788 789 this.from = from; 790 this.to = to; 791 792 this.cb = callback; 793 794 this.nDur = fadetime; 795 796 this.nInt = 50; 797 this.nTime = 0; 798 799 var p = this; 800 this.nID = setInterval(function() { p._fade() }, this.nInt); 801}; 802 803 804 805 806_b.Fader.prototype._fade = function() 807{ 808 this.nTime += this.nInt; 809 810 var ieop = Math.round( this._tween(this.nTime, this.from, this.to, this.nDur) * 100 ); 811 var op = ieop / 100; 812 813 if (this.e.filters) // internet explorer 814 { 815 try 816 { 817 this.e.filters.item("DXImageTransform.Microsoft.Alpha").opacity = ieop; 818 } catch (e) { 819 // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. 820 this.e.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+ieop+')'; 821 } 822 } 823 else // other browsers 824 { 825 this.e.style.opacity = op; 826 } 827 828 829 if (this.nTime == this.nDur) 830 { 831 clearInterval( this.nID ); 832 if (this.cb != undefined) 833 this.cb(); 834 } 835}; 836 837 838 839_b.Fader.prototype._tween = function(t,b,c,d) 840{ 841 return b + ( (c-b) * (t/d) ); 842};
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.