用js实现输入提示(自动完成)
以前也写过一个jQuery的这种插件 ,但是很多地方根本不用jQuery,这个功能也有很多其它库支持,但是为了用这个功能而加载很多js插件,这样效率明显下降了很多,而且这个东西平时也很常用,所以一决心自己写了个相对比较独立的。
完成有以下功能:
输入字符会把以输入字符开头的提示出来。
支持上下方向键选择提示选项,支持循环
支持绑定一个数组提示,支持ajax传递输入框值请求数据。
支持多个选择的dom元素一块绑定数据实现输入提示。各dom元素也可以单独绑定自己的数据实现输入提示,互不影响。
支持中文。
首先是js的核心部分,其各部分都有较详细的说明,代码如下:
view source print ?
;( function (window){
/* 插件开始 */
varautoComplete=function(o){
varhandler=( function (){
varhandler=function(e,o){ return new handler.prototype.init(e,o); }; /* 为每个选择的dom都创建一个相对应的对象,这样选择多个dom时可以很方便地使用 */
handler.prototype={
e: null , o: null , timer: null , show:0, input: null , popup: null ,
init: function (e,o){ /* 设置初始对象 */
this.e=e, this.o=o,
this.input=this.e.getElementsByTagName( this .o.input)[0],
this.popup=this.e.getElementsByTagName( this .o.popup)[0],
this .initEvent(); /* 初始化各种事件 */
},
match: function (quickExpr,value,source){ /* 生成提示 */
varli=null;
for ( var i in source){
if ( value.length>0 && quickExpr.exec(source[i])!= null ){
li=document.createElement( 'li' );
li.innerHTML=''+source[i]+ '< span>a>' ;
this .popup.appendChild(li);
}
}
if ( this .popup.getElementsByTagName( 'a' ).length)
this.popup.style.display='block';
else
this.popup.style.display='none';
},
ajax: function (type,url,quickExpr,search){ /* ajax请求远程数据 */
varxhr=window.ActiveXObject ? new ActiveXObject( "Microsoft.XMLHTTP" ) : new XMLHttpRequest();
xhr.open(type,url, true ); /* 同异步在此修改 */
xhr.setRequestHeader( "Content-Type" , "application/x-www-form-urlencoded" );
varthat=this;
xhr.onreadystatechange=function(){
if (xhr.readyState==4) {
if (xhr.status==200) {
vardata=eval(xhr.responseText);
that.match(quickExpr,search,data); /* 相同于成功的回调函数 */
} else {
alert( "请求页面异常!" ); /* 请求失败 */
}
}
};
xhr.send( null );
},
fetch: function (ajax,search,quickExpr){
varthat=this;
this .ajax(ajax.type,ajax.url+search,quickExpr,search);
},
initEvent: function (){ /* 各事件的集合 */
varthat=this;
this.input.οnfοcus=function(){
if ( this .inputValue) this.value=this.inputValue;
varvalue=this.value,quickExpr=RegExp( '^' +value, 'i' ),self=this;
varels=that.popup.getElementsByTagName( 'a' );
if (els.length>0)that.popup.style.display='block';
that.timer=setInterval( function (){
if (value!=self.value){ /* 判断输入内容是否改变,兼容中文 */
value=self.value;
that.popup.innerHTML='';
if (value!= '' ){
quickExpr=RegExp( '^' +value);
if (that.o.source) that.match(quickExpr,value,that.o.source);
else if (that.o.ajax) that.fetch(that.o.ajax,value,quickExpr);
}
}
},200);
};
this.input.οnblur=function(){ /* 输入框添加事件 */
if ( this .value!= this .defaultValue) this.inputValue=this.value;
clearInterval(that.timer);
varcurrent=-1; /* 记住当前有焦点的选项 */
varels=that.popup.getElementsByTagName( 'a' );
varlen=els.length-1;
varaClick=function(){
that.input.inputValue=this.firstChild.nodeValue;
that.popup.innerHTML='';
that.popup.style.display='none';
that.input.focus();
};
varaFocus=function(){
for ( vari=len; i>=0; i--){
if ( this.parentNode===that.popup.children[i]){
current=i;
break ;
}
}
//that.input.value=this.firstChild.nodeValue;
for ( var k in that.o.elemCSS.focus){
this .style[k] = that.o.elemCSS.focus[k];
}
};
varaBlur=function(){
for ( var k in that.o.elemCSS.blur)
this .style[k] = that.o.elemCSS.blur[k];
};
varaKeydown=function(event){
eventevent= event || window.event; /* 兼容IE */
if (current=== len &&event.keyCode===9){ /* tab键时popup隐藏 */
that.popup.style.display='none';
} else if (event.keyCode==40){ /* 处理上下方向键事件方便选择提示的选项 */
current++;
if (current
if (current>len){
current=-1;
that.input.focus();
} else {
that.popup.getElementsByTagName( 'a' )[current].focus();
}
} else if (event.keyCode==38){
current--;
if (current==-1){
that.input.focus();
} else if (current
current=len;
that.popup.getElementsByTagName( 'a' )[current].focus();
} else {
that.popup.getElementsByTagName( 'a' )[current].focus();
}
}
};
for ( vari=0; i
els[i].οnclick=aClick;
els[i].οnfοcus=aFocus;
els[i].οnblur=aBlur;
els[i].οnkeydοwn=aKeydown;
}
};
this.input.οnkeydοwn=function(event){
eventevent= event || window.event; /* 兼容IE */
varels=that.popup.getElementsByTagName( 'a' );
if (event.keyCode==40){
if (els[0]) els[0].focus();
} else if (event.keyCode==38){
if (els[els.length-1]) els[els.length-1].focus();
} else if (event.keyCode==9){
if (event.shiftKey== true )that.popup.style.display='none';
}
};
this.e.οnmοuseοver=function(){that.show=1; };
this.e.οnmοuseοut=function(){that.show=0; };
addEvent.call(document, 'click' , function (){
if (that.show==0){
that.popup.style.display='none';
}
}); /* 处理提示框dom元素不支持onblur的情况 */
}
};
handlerhandler.prototype.init.prototype=handler.prototype; /* JQuery style,这样我们在处的时候就不用每个dom元素都用new来创建对象了 */
return handler; /* 把内部的处理函数传到外部 */
})();
if ( this .length){ /* 处理选择多个dom元素 */
for ( vara=this.length-1; a>=0; a--){ /* 调用方法为每个选择的dom生成一个处理对象,使它们不互相影响 */
handler( this [a],o);
}
} else { /* 处理选择一个dom元素 */
handler( this ,o);
}
return this ;
};
returnwindow.autoComplete= autoComplete; /* 暴露方法给全局对象 */
/* 插件结束 */
})(window);
其中了一些全局的自定义函数,如addEvent和在例子中将要用到的getElementsByClassName函数如下:
view source print ?
vargetElementsByClassName=function(searchClass, node, tag) { /* 兼容各浏览器的选择class的方法;(写法参考了博客园:http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1529640.html
,想了解更多请看这个地址) */
nodenode= node || document,tagtag= tag ? tag.toUpperCase() : "*" ;
if (document.getElementsByClassName){ /* 支持getElementsByClassName的浏览器 */
vartemp=node.getElementsByClassName(searchClass);
if (tag== "*" ){
return temp;
} else {
varret=newArray();
for ( vari=0; i
JavaScript跨域总结与解决办法
使用Javascript开发移动应用程序
10个令人惊奇的HTML5和JavaScript效果
JavaScript初学者应注意的七个细节