kingapex 发表于 2013-1-27 05:05:10

淘宝javascript类别多级下拉连动解析和改进

效果地址:
http://search1.taobao.com/browse/ad_search.htm
具体代码见: 附件1
其中关键代码解析:
 
一、构造类别数组
声明一个类别数组cat
 
cats['11']=['电脑硬件/台式整机/网络设备','1'];cats['110502']=['品牌液晶显示器','11'];cats['110202']=['内存','11']; 
 

5000多个略…,规则为:
数组的下标是类别id,
第一个元素为类别名
第二个元素为类别父id
接下来构一个将cats数组存入一个parent数组,数组的下标为cats数组的父id,元素为类别数组本身:
 
for (c in cats) {var ii =cats;if (!parent) {parent = new Array();}parent.length] = c;} 
 
 
这样,形成如下图的两个类别数组:
 
http://www.iteye.com/upload/attachment/36958/de7c2c8d-1b64-39d5-84bc-a33227e6286b.jpg
 
二、填充下拉框方法
利用cats 和parent两个数组填充,主要是得到了选中的某个类别的子类别集合:
 
 
 
/*id:选中的类别idobj:下拉列表框dom对象defaultId: 如果要选中默认的某个子,则传递此参数isFirst:为了可以连级初始化所用。*/function _addList(id, obj, defaultId, isFirst) {if (!defaultId) {defaultId = -1;}var s = 0;if (haveBlank == 'true') {obj.options = new Option('', '');}if (parent) { //利用上面的数组关系直接得到了子数组for (var i = 0; i < parent.length; ++i) {var catId = parent;//某个子的idif (!parent) {  obj.options = new Option(cats, catId);}else {obj.options = new Option(cats + ' ->', catId); //如果还有子显示一个"->"}if (defaultId >= 0 && defaultId == catId) {obj.options.selected = true;changeSubCat(obj);}else if (i == 0 && !isFirst && haveBlank == '') {obj.options.selected = true;changeSubCat(obj);}}}} 

三、填充下拉框的子下拉框
<strong />
其中做了一些判断是否有子,是否有子下拉框。
 
 
function changeSubCat(obj) {if (!obj || !obj.name) {error('obj not found!');return;}var name = obj.name;var form = document.forms;if (!form) {error('form not found!');return;}var selectNum = -1;for (var i = 0; i < catSel.length; ++i) {if (catSel == name) {selectNum = i;break;}}if (selectNum < 0) {debug('can\'t found sub select');_setValue();return;}if (selectNum + 1 >= catSel.length || !form.elements]) {debug('can\'t found sub select 1');_setValue();return;}var subSel = form.elements];_clearList(subSel);for (var i = selectNum + 1; i < catSel.length; ++i) {if (form.elements]) {_clearList(form.elements]);}}if (obj.options.value == '') {_setValue();return;}var catId = obj.options.value;if (!parent) {debug('no sub select data');_setValue();return;}_addList(catId, subSel);_setValue();} 
 
 

如上方法可实现了多级下拉框连动,不过有以下问题:
1. 和form绑定死了
2. 在一个页面无法存在多个连动下拉框
3. 下拉框的name不能自定义,
在项目中同样有此需求,需要同时使用多个连动下拉框,同时name也需自定义,稍改进了一下,将各种方法和数组放入类中,同时根据下拉框的id来绑定下拉框,集成了下拉框的onchagne事件
 
function TreeSelect(){this.haveBlank=undefined;this.cats=undefined;this.parent=undefined;/** * 初始化数据 */this.init= function(_cats,_haveBlank,_selid){this.cats= _cats;this.initParnet(_cats);this.haveBlank=_haveBlank;this.initSelObj(_selid);};/** * 初始化select对象数组 */this.initSelObj=function(_selid){var p = this;function fireChangeEvent(){p.changeSubCat(event.srcElement);}this.catSel = _selid.split(',');this.sel_ar = new Array();for(var i=0;i<this.catSel.length;i++){this.sel_ar = document.getElementById(this.catSel);this.sel_ar.attachEvent('onchange',fireChangeEvent,true);}}; /** * 初始化树数据数组 */this.initParnet=function(cats){this.parent = new Array();for (c in cats) {var ii =cats;if (!this.parent) {this.parent = new Array();}this.parent.length] = c;}};/** * 清空select列表 */this._clearList=function(obj) {if (!obj) {return;}for (var i = obj.length - 1; i >= 0; --i) {obj.remove(i);}obj.value = '';};/** * 改变子的选择 */this.changeSubCat=function(obj) {if (!obj || !obj.id) {error('obj not found!');return;}var name = obj.id;var selectNum = -1;for (var i = 0; i < this.catSel.length; ++i) {if (this.catSel == name) {selectNum = i;break;}}if (selectNum < 0) {debug('can\'t found sub select');return;}if (selectNum + 1 >= this.catSel.length || !document.getElementById( this.catSel )) {debug('can\'t found sub select 1');return;}var subSel = document.getElementById(this.catSel);this._clearList(subSel);for (var i = selectNum + 1; i < this.catSel.length; ++i) {if (document.getElementById(])) {this._clearList(document.getElementById(this.catSel));}}var catId = obj.options.value;if (!this.parent) {debug('no sub select data'); return;}this._addList(catId, subSel); };/** * 填充一个select */this._addList=function(id, obj, defaultId, isFirst) {if (!defaultId) {defaultId = -1;}var s = 0;if (this.haveBlank == 'true') {obj.options = new Option('请选择', ''); }if (this.parent) {//当前选中的子数组for (var i = 0; i < this.parent.length; ++i) {var catId = this.parent;if (!this.parent) {obj.options = new Option(this.cats, catId);}else {obj.options = new Option(this.cats + ' ->', catId);}if (defaultId >= 0 && defaultId == catId) {obj.options.selected = true;this.changeSubCat(obj);}else if (i == 0 && !isFirst && this.haveBlank == '') {obj.options.selected = true;this.changeSubCat(obj);}}}};}function debug(info) {//alert(info);}function error(info) {alert(info);} 
 
 
详见: 附件2
 
实际项目中需要和数据库结合起来,通过标签输出,下面附件内容供大家参考:<span />
附件3
 
页: [1]
查看完整版本: 淘宝javascript类别多级下拉连动解析和改进