本代码纯属个人js练手,写着写着,顺便整理。(望哥们姐们手下留砖)
/**
* N级联动v2.0
*
* @说明: 使用json数据格式,生成N级下拉框联运,
* 在初始化联动前,可灵活设置json数据中相对应的id\text\value\parent以及topParent
*
* @author: tips
* @date: 2009-09-07
* @lastupdate: 2010-04-14
* @调用: SelectN(数组, '下拉框id1', '下拉框id2', ...'第N个..ID');
* @注意: 级数N<=254
* setProperties只能在其它初始化级联效果之前运行,否则将有可能出现异常
*
* 数据格式为: [{id:'cn', text:'中国', parent:'-'}, ...]
*
* 若需要设定其它键为id\text\parent,则使用SelectN.setProperties(json);
* 例:SelectN.setProperties({idKey: 'ucode', textKey:'uname', textKey:'uname', parentKey:'fatherCode'});
* 此时解析的数据格式将发生变化:[{ucode: 'aaa', uname: 'bbb', fatherCode:'xxx'}]
*
*/
;(function() {
var myData;
var topParent='-';
var idKey='id', textKey='text', valueKey=idKey, parentKey='parent';
var SelectN = window.SelectN = function(data) {
myData = data;
var ids = [].slice.call(arguments, 1);//下拉框级数的ID,按级数顺序存入数组selectN
//length-1 => 最后一个下拉框不添加onchange
for(var i=0, len=ids.length-1; i<len; i++){
var o = $(ids[i]);
addEventHandler(o, 'change', (function() {
var self=o, index=i+1;
return function() {
showChild(self, ids, index);
}
})());
}
showChild(null, ids, 0);
return SelectN;
}
/**
* 指定data中的哪一项代表相应的id、text、value、parent等
*
* 设置属性,该方法必须在SelectN所有其它初始化方法之前调用!
* @param Object opt 配置参数
* topParent - 代表顶级节点的值,默认为"-"
* idKey - 代表id的键名,默认为"id"
* textKey - 代表下拉框text的键名,默认为"text"
* valueKey - 代表下拉框value的键名,默认使用idKey
* parentKey - 代表parent的键名,默认为"parent"
*/
SelectN.setProperties = function(opt) {
topParent = opt.topParent || topParent;
idKey = opt.idKey || idKey;
textKey = opt.textKey || textKey;
valueKey = opt.valueKey || idKey;
parentKey = opt.parentKey || parentKey;
return SelectN;
}
/**
* 显示子级下拉框
* @param Object(Select) oSelect 当前change的下拉框DOM
* @param Array ids 联动的下拉框ID数组
* @param int index 当前下拉框的下一级索引
*/
function showChild(oSelect, ids, index) {
var p = null == oSelect ? topParent : oSelect.options[oSelect.selectedIndex].xid;
var ds = getChilds(p);
clearSelect(ids, index);
var child = $(ids[index]);
for(var i=0,len=ds.length; i<len; i++){
var currentObj = ds[i];
//child.options[child.length] = new Option(ds[i].text, ds[i].text);
var currentOpt = child.options[child.length] = new Option(currentObj[textKey], currentObj[valueKey]);
//child.options[child.length-1].xid=ds[i].id;
currentOpt.xid=currentObj[idKey];
currentOpt.ownerObj = currentObj;
}
}
/**
* 获得子级数据
* @param String p 父级代号
* @return Array childs
*/
function getChilds(p) {
var childs = [];
for(var i=0, len=myData.length; i<len; i++){
//if(p == myData[i].parent)
if(p == myData[i][parentKey]){
childs.push(myData[i]);
}
}
return childs;
}
/**
* 清除所有子级下拉框
* @param Array ids 联动的下拉框ID数组
* @param int index 当前下拉框的下一级索引
*/
function clearSelect(ids, index) {
for(var i=index, len=ids.length; i<len; i++){
$(ids[i]).length=1;
}
}
function $(sid) {
return document.getElementById(sid);
}
//为对象obj追加事件 -- 兼容IE与FF
function addEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" + sEventType, fnHandler);
} else {
oTarget["on" + sEventType] = fnHandler;
}
};
})();
下面是demo(附带几行测试用的数据):
var data = [];
data.push({id:'cn', text:'中国', parent:'-'});
data.push({id:'fj', text:'福建', parent:'cn'});
data.push({id:'gd', text:'广东', parent:'cn'});
data.push({id:'fz', text:'福州', parent:'fj'});
data.push({id:'xm', text:'厦门', parent:'fj'});
data.push({id:'ly', text:'龙岩', parent:'fj'});
data.push({id:'fz-fq', text:'福州1', parent:'fz'});
data.push({id:'fz-mh', text:'福州2', parent:'fz'});
data.push({id:'fz-cl', text:'福州3', parent:'fz'});
data.push({id:'xm-dn', text:'厦门1', parent:'xm'});
data.push({id:'xm-jm', text:'厦门2', parent:'xm'});
data.push({id:'xm-xl', text:'厦门3', parent:'xm'});
data.push({id:'yl-xl', text:'龙岩1', parent:'ly'});
data.push({id:'yl-lc', text:'龙岩2', parent:'ly'});
data.push({id:'yl-sh', text:'龙岩3', parent:'ly'});
data.push({id:'yl-wp', text:'龙岩4', parent:'ly'});
data.push({id:'gz', text:'广州', parent:'gd'});
data.push({id:'sz', text:'深圳', parent:'gd'});
data.push({id:'mx', text:'梅县', parent:'gd'});
data.push({id:'gz-fq', text:'广州1', parent:'gz'});
data.push({id:'gz-mh', text:'广州2', parent:'gz'});
data.push({id:'gz-cl', text:'广州3', parent:'gz'});
data.push({id:'sz-dn', text:'深圳1', parent:'sz'});
data.push({id:'sz-jm', text:'深圳2', parent:'sz'});
data.push({id:'sz-xl', text:'深圳3', parent:'sz'});
data.push({id:'mx-xl', text:'梅县1', parent:'mx'});
data.push({id:'mx-lc', text:'梅县2', parent:'mx'});
data.push({id:'mx-sh', text:'梅县3', parent:'mx'});
data.push({id:'mx-wp', text:'梅县4', parent:'mx'});
data.push({id:'am', text:'美国', parent:'-'});
data.push({id:'ny', text:'纽约', parent:'am'});
data.push({id:'hsd', text:'华盛顿', parent:'am'});
//在onload后执行
window.onload = function() {
/*
SelectN.setProperties({
topParent:'gd', //设置顶级节点的parent值
idKey:'ucode', //指定data中的哪一项代表id
textKey:'text', //指定data中的哪一项代表下拉框中的text
valueKey:'text', //指定data中的哪一项代表下拉框中的value
parentKey:'parent' //指定data中的哪一项代表parent
})(data, 'p1', 'p2', 'p3', 'p4');
*/
SelectN.setProperties({valueKey:'text'}); //重新设定各属性的键值
SelectN(data, 'p1', 'p2', 'p3', 'p4'); //初始化级联关系
}
下面是html相关的代码:
<body>
<select id="p1"><option>-选择-</option></select><br/>
<select id="p2"><option>-选择-</option></select><br/>
<select id="p3"><option>-选择-</option></select><br/>
<select id="p4"><option>-选择-</option></select>
</body>
把上面三段代码放到一起,就能看见效果了。
等哪天突然心血来潮了,再重构一下,加上Ajax动态级联功能