最近在一个项目里面做了一个控件:该控件作为一个带输入的 select ,且支持根据动态输入的内容去后台查询,将结果放在 select 的下拉框里面。效果图如下:
该控件支持绑定回调函数,支持动态事件等等。另一个比较实用的功能是,可以任意指定该控件的上一级联动控件:比如上面产品名称的上一级联动是系统名称,一旦系统名称选择值了,则产品名称必然是该系统属下的。如下图,联动状态下的自动完成搜索。
代码参考 js 库的写法,使用完全的面向对象。
库的使用方法很简单,在 html 里面写一个 div,如 <div id="sys_area"></div>,然后在该页面加载后调用这句 js 代码即可:
var config={...} //具体配置后续加上
$('#sys_area').simulation(config);
库的代码如下:
(function($w){
'use strict';
var __name__ = 'divInputSimulation';
var __version__ = '1.0';
var __author__ = 'edgarlli';
var logger = (typeof console === 'undefined')?{
log:_noop, debug:_noop, error:_noop, warn:_noop, info:_noop
}:console;
var divInputSimulation = function(config)
{
this.divId = config.divId;
this.inputId = (config.divId+"_input");
this.expandDivId = (config.divId+"_expand_div");
this.textKey = config.textKey;
this.ajaxUrl = config.ajaxUrl;
this.dataType = config.dataType;
this.searchName = config.searchName;
this.dataHandle = config.dataHandle;
this.optionClickFunc = config.optionClickFunc;
this.dependencyValuableNodeMap = config.dependencyValuableNodeMap;
//等待用户不输入 1 秒后再去执行 search
this. loseInputMillsecs = 1000;
this.clocker = null;
this.init();
};
divInputSimulation.prototype=
{
init : function() {
this.initDivInputSimulationSelect();
},
getInputNode : function()
{
return $('#'+this.inputId);
},
getexpandDivId : function()
{
return $('#'+this.expandDivId);
},
initDivInputSimulationSelect:function()
{
//add node
var inputId = (this.divId+"_input");
var expandDivId = (this.divId+"_expand_div");
var addHtml = '';
addHtml += '';
addHtml += '
';
$('#'+this.divId).html(addHtml);
var expandNode = $('#' + expandDivId);
var inputNode = $('#' + inputId);
$(document).click(function(e)
{
expandNode.hide();
if(inputNode.val() == "")
inputNode.val('全选');
})
$('#'+this.divId).click(function(event){
event=event||window.event;
event.stopPropagation();
})
var thisPointer = this;
inputNode.focus(function()
{
if(inputNode.val() == "全选")
inputNode.val('');
if(0 != expandNode.find('ul>li').length)
expandNode.show();
else
{
thisPointer.search(thisPointer);
}
})
var v = this;
inputNode.keydown(function(){
v.innerKeydown();
})
},
innerKeydown:function()
{
var search = this.search;
if(null == this.clocker)
{
this.clocker = setTimeout(this.search,this.loseInputMillsecs,this);
}
else //再次击键,重新计时
{
clearTimeout(this.clocker);
this.clocker = setTimeout(this.search,this.loseInputMillsecs,this);
}
},
//因为 search 不在当前类的执行环境下,所以 search 中的 this 不是指的当前类。故需要将当前类的指针传入其中
search:function(thisPointer)
{
if(typeof thisPointer === 'undefined' || !thisPointer)
thisPointer = this;
var searchKey = $('#' + thisPointer.inputId).val();
if(searchKey == '全选')
searchKey = '';
var param = {};
var nodeMap = thisPointer.dependencyValuableNodeMap;
if(typeof nodeMap != 'undefined')
{
$.each(nodeMap,function(k,v)
{
param[k] = (v.val() == '全选' ? '' : v.val());
})
}
param[thisPointer.searchName] = searchKey;
$.post(thisPointer.ajaxUrl, param, function(result) {
}, thisPointer.dataType)
.success(
function(result)
{
if(thisPointer.dataHandle)
{
result = thisPointer.dataHandle(result);
}
thisPointer.resetInputAttrs(thisPointer);
thisPointer.resetExpand(thisPointer);
thisPointer.buildDivInputtSimulationSelect(result,thisPointer);
if(!!result && 0 != result.length)
$('#' + thisPointer.expandDivId).show();
else
$('#' + thisPointer.expandDivId).hide();
}).error(function() {
console.info("load data error");
});
this.clocker = null;
},
resetInputAttrs:function(thisPointer)
{
if(typeof thisPointer === 'undefined' || !thisPointer)
thisPointer = this;
var inputNode = $('#' + thisPointer.inputId);
var attrs = inputNode[0].attributes;
if(typeof attrs != 'undefined' && !!attrs)
for(var i =0;i < attrs.length;++ i)
{
if(attrs[i].name == "style" || attrs[i].name=='id' || attrs[i].name=='class'
|| attrs[i].name == 'type') //跳过 style,id ,class
continue;
$(inputNode).attr(attrs[i].name,'');
}
},
resetExpand:function(thisPointer)
{
if(typeof thisPointer === 'undefined' || !thisPointer)
thisPointer = this;
var expandNode = $('#' + thisPointer.expandDivId);
expandNode.html('');
},
hideExpand:function(thisPointer)
{
if(typeof thisPointer === 'undefined' || !thisPointer)
thisPointer = this;
var expandNode = $('#' + thisPointer.expandDivId);
expandNode.hide();
},
/**
* 由 div + input 模拟一个可输入的 select
keyValues : 键值对数组
thisPointer : 当前类对象的指针
*/
buildDivInputtSimulationSelect: function(keyValues,thisPointer)
{
if(typeof thisPointer === 'undefined' || !thisPointer)
thisPointer = this;
var addHtml = '';
var length = keyValues.length;
addHtml += '
-
';
for(var i = 0;i < length;++ i)
{
addHtml += '
- ';
}
addHtml += '
';
$('#'+thisPointer.expandDivId + '>ul').remove();
$('#'+thisPointer.expandDivId).html(addHtml);
$('#'+thisPointer.expandDivId).children('ul').children('li').hover(function(){
$(this).css("background-color","#428bca");
},function(){
$(this).css("background-color","#FFFFFF");
})
var optionClickFunc_ = thisPointer.optionClickFunc;
$('#'+thisPointer.expandDivId).children('ul').children('li').on('click',function()
{
var attrs = this.attributes;
console.info(attrs);
var inputNode = $('#'+thisPointer.inputId);
for(var i =0;i < attrs.length;++ i)
{
if(attrs[i].name == "style" || attrs[i].name=='id' || attrs[i].name=='class'
|| attrs[i].name == 'type') //跳过 style,id ,class
continue;
inputNode.attr(attrs[i].name,attrs[i].value);
if(attrs[i].name == thisPointer.textKey)
inputNode.val(attrs[i].value);
}
$('#'+thisPointer.expandDivId).hide();
if(optionClickFunc_)
{
optionClickFunc_($(this));
}
});
},
}
$w[__name__] = divInputSimulation;
$.fn.simulation = function(config)
{
console.info(this);
var divId = $(this).attr('id');
config.divId = divId;
return new divInputSimulation(config)
};
})(window);