Gmail-Like Incremental Search //JavaScript Class
Implements a GMail-like auto-complete.
[UPDATED CODE AND HELP CAN BE FOUND HERE]
@REQUIRES Event-Listener
1 2 //Requires http://www.jsfromhell.com/geral/event-listener 3 4 //+ Jonas Raoni Soares Silva 5 //@ http://jsfromhell.com/dhtml/incremental-search [v1.0] 6 7 IncrementalSearch = function( input, callback, className ){ 8 var i, o = ( o = this, o.l = [], o.i = input, o.c = null, o.s = { e: null, i: -1 }, o.f = callback || function(){}, o.n = className || "", o ); 9 for( i in { keydown: 0, focus: 0, blur: 0, keyup: 0, keypress: 0 } ) 10 addEventListener( o.i, i, function( e ){ o.handler.call( o, e ); } ); 11 }; 12 with( { p: IncrementalSearch.prototype } ){ 13 (p.constructor.fadeAway = function( o ){ 14 o instanceof Object ? ( this.trash = this.trash || [] ).push( o ) && setTimeout( this.fadeAway, 200 ) : arguments.callee.c.trash.pop().hide(); 15 }).c = p.constructor; 16 p.callEvent = function( e ){ this[e] && this[e].apply( this, [].slice.call( arguments, 1 ) ); }; 17 p.highlite = function( e ){ ( this.s.e && ( this.s.e.className = "normal" ), ( this.s = { e: e, i: e.listindex } ).e.className += " highlited", this.callEvent( "onhighlite", this.l[ this.s.i ], this.s.e.d ) ); }; 18 p.select = function(){ this.s.i + 1 && ( this.i.value = this.l[ this.s.i ], this.callEvent( "onselect", this.i.value, this.s.e.d ), this.hide() ); }; 19 p.hide = function(){ ( this.c && this.c.parentNode.removeChild( this.c ), this.c = null, this.l = [], this.s = { e: null, i: -1 }, this.callEvent( "onhide" ) ); }; 20 p.next = function(){ var e = ( e = this.s.e ) ? e.nextSibling || e.parentNode.firstChild : null; e && this.highlite( e ); }; 21 p.previous = function(){ var e = ( e = this.s.e ) ? e.previousSibling || e.parentNode.lastChild : null; e && this.highlite( e ); }; 22 p.handler = function( evt ){ 23 var o = this, t = evt.type, k = evt.key, e = /span/i.test( ( e = evt.target ).tagName ) ? e.parentNode : e; 24 t == "keyup" ? k != 40 && k != 38 && k != 13 && o.show() 25 : t == "keydown" ? ( k == 40 && o.next() ) || ( k == 38 && o.previous() ) 26 : t == "keypress" ? k == 13 && !evt.preventDefault() && o.select() 27 : t == "blur" ? o.constructor.fadeAway( o ) 28 : t == "click" ? o.select() 29 : t == "focus" ? o.show() 30 : o.highlite( e ); 31 }; 32 p.show = function(){ 33 var cS, found = 0, o = this, i = o.i, iV = i.value, d = document, c = ( o.hide(), o.c = d.body.appendChild( d.createElement( "div" ) ) ); 34 ( c.className = o.n, cS = c.style, cS.display = "none", cS.position = "absolute", o.callEvent( "onshow" ) ); 35 o.f.call( function( s, x, data ){ 36 if( !( x.length == undefined ? ( x = [x] ) : x ).length ) 37 return; 38 var j, l = 0, i = o.l.length, e = c.appendChild( d.createElement( "div" ) ); 39 for( j in ( o.l[i] = s, e.className = "normal", e.d = data, e.listindex = i, !found && i == o.s.i && ++found && o.highlite( e ), x ) ) 40 e.appendChild( d.createTextNode( s.substring( l, x[j] ) ) ).parentNode.appendChild( d.createElement( "span" ) ).appendChild( d.createTextNode( s.substring( x[j], l = x[j] + iV.length ) ) ).parentNode.className = "selectedText"; 41 for( x in ( e.appendChild( d.createTextNode( s.substr( l ) ) ), { click: 0, mouseover: 0 } ) ) 42 addEventListener( e, x, function( e ){ o.handler.call( o, e ); } ); 43 }, iV ); 44 if( !c.childNodes.length ) 45 return o.hide(); 46 for( var x = i.offsetLeft, y = i.offsetTop + i.offsetHeight; i = i.offsetParent; x += i.offsetLeft, y += i.offsetTop ); 47 ( cS.display = "block", cS.left = x + "px", cS.top = y + "px", !found && o.highlite( c.firstChild ) ); 48 }; 49 }
Example
1 2 <style type="text/css"> 3 /*container da lista*/ 4 .autocomplete{ 5 cursor: pointer; 6 border: 1px solid #999; 7 border-top: none; 8 background: #eee; 9 } 10 /*caracteres que combinaram*/ 11 .autocomplete .selectedText{ font-weight: bold; color: #008; } 12 /*items não selecionados*/ 13 .autocomplete .normal{ border-top: 1px solid #999; overflow: hidden; white-space: pre; } 14 /*item selecionado*/ 15 .autocomplete .highlited{ background: #ddf; } 16 </style> 17 18 <form action=""> 19 <fieldset> 20 <legend>Preenchimento dinâmico</legend> 21 <label for="list" >Emails</label> 22 <input autocomplete="0" type="text" name="list" id="list" /> 23 <br /> 24 <label for="ip" >Lista de IPs</label> 25 <textarea name="ip" rows="3" cols="20" id="ip"></textarea> 26 <br /> 27 </fieldset> 28 </form> 29 30 <script type="text/javascript"> 31 //<![CDATA[ 32 33 var list = [ "192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.1.1", "192.168.1.2", "192.168.1.3", "200.168.0.1", "200.168.0.2", "200.168.0.3", "200.168.1.1", "200.168.1.2", "200.168.1.3" ]; 34 new IncrementalSearch( document.forms[0].ip, function( search ){ 35 for( var i in list ) 36 if( !list[i].indexOf( search ) ) 37 this( list[i], 0 ); 38 }, "autocomplete" ); 39 40 41 var names = [ "João Alves <joao@123.com>", "Jonas Raoni Soares Silva <jonas@abc.com>", "Roberto <rob@net.net>", "Maria Fernanda <mariaf@i.tu>" ]; 42 43 function retrieveNames( search ){ 44 search = search.toLowerCase(); 45 for( var i in names ){ 46 if( search ){ 47 for( var j = 0, indices = []; j = names[i].toLowerCase().indexOf( search, j ) + 1; indices[indices.length] = j - 1 ); 48 this( names[i], indices, i ); 49 } 50 else 51 this( names[i], 0, i ); 52 53 } 54 } 55 56 x = new IncrementalSearch( document.forms[0].list, retrieveNames, "autocomplete" ); 57 58 59 //]]> 60 </script>