近来工作需要大量的下拉框来实现一些功能,网上介绍实现的也不少,总觉得没有称心如意的,于是自己动手丰衣足食,干脆写一个基于jquery的可支持多选回车的批量使用的下拉框组件:
$(function($) {
function _getGUID(){//随机定义下拉框身份
var guid = "";
for (var i = 1; i <= 32; i++){
var n = Math.floor(Math.random()*16.0).toString(16);
guid += n;
if((i==8)||(i==12)||(i==16)||(i==20)){
guid += "-";
}
}
return guid;
};
zip_addSelect=function(){
$('input[zip_select="selector"]').each(function(){
var that=$(this);
var isCheckBox=$(this).attr('zip_isCheckBox')||false;//是否多选
var isDefalut=$(this).attr('zip_isDefalut')||false;//是否定义默认值
var xxx=false;
if(!isCheckBox&&isDefalut){//不是多选并且有默认值取默认值
for(var i=0;i<$(that).next().children().size();i++){
if($($(that).next().children()[i]).html()==isDefalut){
that.val(isDefalut);
that.attr('val',$(that).next().children()[i].getAttribute('value'));
xxx=true;
}
}
if(!xxx){//数据中不存在默认值取第一个值
if($(that).next().children().size()>0){
that.val($(that).next().children()[0].innerHTML);
that.attr('val',$(that).next().children()[0].getAttribute('value'));
xxx=true;
}
}
}
})
$(document).on('focus','input[zip_select="selector"]',function(){//下拉框获得焦点
var that=$(this);
var isOpen=$(this).attr('zip_openKey')||true;//是否开启键盘选择
var isCheckBox=$(this).attr('zip_isCheckBox')||false;//是否多选
var KEY = {"up":38,"down":40,"enter":13};//定义键盘
var isShow=false;//是否显示下拉列表
var idx='';
var arrContent=[];//多选数组用
var maxLength=$(this).attr('zip_maxLength')||12;//输入框最大长度限制(多余用...代替)
var isDefalut=$(this).attr('zip_isDefalut')||false;//默认显示某一条数据
var xxx=false;
var callback=$(this).attr('zip_callback')||null;//选择后回执函数
closeSelect(that);
$(that).attr('randomId',new Date().getTime()+_getGUID());
$("input[zip_select='selector']").each(function(){//同一页面多个组件只能打开一个
if($(this).hasClass('zip_open')){
var drl=$(this);
$(this).next().slideUp("fast",function(){//其他组件关闭下拉列表
drl.removeClass('zip_open');
if(isOpen&&!isCheckBox){
drl.unbind('keydown',keyOperate);//移除键盘事件
}
});
}
});
if($(that).hasClass('zip_open')){
closeSelect(that);//关闭下拉列表
}
else{
$(that).addClass('zip_open');
$(that).next().show();
isShow=true;
if(isOpen&&!isCheckBox){
that.bind('keydown',keyOperate);//绑定键盘事件
}
}
$(that).next().children().each(function(i){//自定义设置默认值
$(this).css({background:''})
if($(this).html()==$(that).val()&&$.trim($(this).html())!=''){
idx=i;//记录当前选中位数便于上下键选择
$(this).css({background:'#496a00'});
$(that).val(this.innerHTML);//初始默认值
}
});
function closeSelect(obj){//关闭下拉列表事件
$(obj).next().hide();
if(isOpen&&!isCheckBox){
that.unbind('keydown',keyOperate);
}
$(obj).removeClass('zip_open');
isShow=false;
}
$(document).bind("click", function(e) {//点击页面其他部分关闭下拉列表
if((!$(e.target).hasClass('zip_open')&&!isCheckBox)|| ((!$(e.target).hasClass('zip_open'))&&$(that).next().children().index($(e.target))==-1)){
if(isShow){
closeSelect(that);
}
}
});
$(that).next().unbind('click').bind('click',function(e){//下拉列表点击选择后事件
var src=e.target;var b='',vv='';
if(src.tagName.toLowerCase()=='li'){
var vl=src.getAttribute('value');
if(!isCheckBox){//单选
idx=parseInt($(src).parent('ul').children().index($(src)));
$(that).next().children().each(function(){
$(this).css({background:''})
});
$(src).css({background:'#496a00'});
$(that).val(src.innerHTML);
$(that).attr('val',src.getAttribute('value'));
if(callback!=null){//选择后执行回调函数
var thisCallback= window.eval(callback);
thisCallback(that,$(that).val(),$(that).attr('val'),e);
}
}
else{//多选
if($(src).attr('isSelect')=='selected'){
var a={};
a[vl]=src.innerHTML;
for(var i=0;i<arrContent.length;i++){
for(var t in arrContent[i]){
if(t==vl){
arrContent.splice(i,1);
}
}
}
$(src).css({background:''});
$(src).attr('isSelect','');
}
else{
var ttt={};
ttt[vl]=src.innerHTML;
arrContent.push(ttt);
$(src).css({background:'#496a00'});
$(src).attr('isSelect','selected');
}
for(var i=0;i<arrContent.length;i++){
for (var t in arrContent[i]){
b=b==''?b+arrContent[i][t]:b+","+arrContent[i][t];
vv=vv==''?vv+t:vv+','+t;
}
}
if(b.length>maxLength){
$(that).val(b.slice(0,maxLength)+'..');
}
else{
$(that).val(b);
}
$(that).attr('val',vv);
$(that).attr('title',b);
}
}
});
function keyOperate(e) {//键盘事件
var childLi=$(that).next().children(), len=childLi.size();
if(len > 0){
if(e.keyCode == KEY.up || e.keyCode == KEY.down) {//上下键
if(e.keyCode == KEY.up) {
if(idx === ''){
idx = len - 1;
}
else {
$(childLi).each(function(){
$(this).css({background:""})
});
idx--;
idx = idx < 0? len - 1 : idx;
}
$(childLi[idx]).css({background:"#496a00"});
$(that).val($(childLi[idx]).text());
}
else if(e.keyCode == KEY.down){
if(idx === ''){
idx = 0;
}
else {
$(childLi).each(function(){
$(this).css({background:""})
});
idx++;
idx = idx > len - 1? 0:idx;
}
$(childLi[idx]).css({background:"#496a00"});
$(that).val($(childLi[idx]).text());
}
e.preventDefault();
}
else if(e.keyCode==KEY.enter){//回车
closeSelect(that);
$(that).attr('val',childLi[idx].getAttribute('value'));
if(callback!=null){
var thisCallback= window.eval(callback);
thisCallback(that,$(that).val(),$(that).attr('val'),e);
}
$(that).blur();
}
}
}
});
}
zip_addSelect();
})
特别说明:现实应用中很多都是ajax返回成功后才有下拉列表中的数据,此时由于该方法是在页面加载完成后即调用,下拉列表为空就不会触发任何事件,所以要在ajax成功后再调用zip_addSelect();
html代码格式及结构:
<input type="text" id="brand" autocomplete="off" readonly="true" zip_select="selector" zip_openkey="true" zip_isDefalut="31001" />
<ul >
<li value="31001" >中广华夏</li>
<li value="31002" >CDCPC</li>
<li value="31003" >NORM</li>
</ul>
截图如下:
单选:
多选(不支持键盘):