效果地址:
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[c][1];
if (!parent[ii]) {
parent[ii] = new Array();
}
parent[ii][parent[ii].length] = c;
}
这样,形成如下图的两个类别数组:

二、填充下拉框方法
利用cats 和parent两个数组填充,主要是得到了选中的某个类别的子类别集合:
/*
id:选中的类别id
obj:下拉列表框dom对象
defaultId: 如果要选中默认的某个子,则传递此参数
isFirst:为了可以连级初始化所用。
*/
function _addList(id, obj, defaultId, isFirst) {
if (!defaultId) {
defaultId = -1;
}
var s = 0;
if (haveBlank == 'true') {
obj.options[s++] = new Option('', '');
}
if (parent[id]) { //利用上面的数组关系直接得到了子数组
for (var i = 0; i < parent[id].length; ++i) {
var catId = parent[id][i];//某个子的id
if (!parent[catId]) {
obj.options[s++] = new Option(cats[catId][0], catId);
}else {
obj.options[s++] = new Option(cats[catId][0] + ' ->', catId); //如果还有子显示一个"->"
}
if (defaultId >= 0 && defaultId == catId) {
obj.options[s-1].selected = true;
changeSubCat(obj);
}else if (i == 0 && !isFirst && haveBlank == '') {
obj.options[i].selected = true;
changeSubCat(obj);
}
}
}
}
三、填充下拉框的子下拉框
其中做了一些判断是否有子,是否有子下拉框。
function changeSubCat(obj) {
if (!obj || !obj.name) {
error('obj not found!');
return;
}
var name = obj.name;
var form = document.forms[formName];
if (!form) {
error('form not found!');
return;
}
var selectNum = -1;
for (var i = 0; i < catSel.length; ++i) {
if (catSel[i] == name) {
selectNum = i;
break;
}
}
if (selectNum < 0) {
debug('can\'t found sub select');
_setValue();
return;
}
if (selectNum + 1 >= catSel.length || !form.elements[catSel[selectNum + 1]]) {
debug('can\'t found sub select 1');
_setValue();
return;
}
var subSel = form.elements[catSel[selectNum + 1]];
_clearList(subSel);
for (var i = selectNum + 1; i < catSel.length; ++i) {
if (form.elements[catSel[i]]) {
_clearList(form.elements[catSel[i]]);
}
}
if (obj.options[obj.selectedIndex].value == '') {
_setValue();
return;
}
var catId = obj.options[obj.selectedIndex].value;
if (!parent[catId]) {
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[i] = document.getElementById(this.catSel[i]);
this.sel_ar[i].attachEvent('onchange',fireChangeEvent,true);
}
};
/**
* 初始化树数据数组
*/
this.initParnet=function(cats){
this.parent = new Array();
for (c in cats) {
var ii = cats[c][1];
if (!this.parent[ii]) {
this.parent[ii] = new Array();
}
this.parent[ii][this.parent[ii].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[i] == name) {
selectNum = i;
break;
}
}
if (selectNum < 0) {
debug('can\'t found sub select');
return;
}
if (selectNum + 1 >= this.catSel.length || !document.getElementById( this.catSel[selectNum + 1] )) {
debug('can\'t found sub select 1');
return;
}
var subSel = document.getElementById(this.catSel[selectNum + 1]);
this._clearList(subSel);
for (var i = selectNum + 1; i < this.catSel.length; ++i) {
if (document.getElementById([this.catSel[i]])) {
this._clearList(document.getElementById(this.catSel[i]));
}
}
var catId = obj.options[obj.selectedIndex].value;
if (!this.parent[catId]) {
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[s++] = new Option('请选择', '');
}
if (this.parent[id]) {//当前选中的子数组
for (var i = 0; i < this.parent[id].length; ++i) {
var catId = this.parent[id][i];
if (!this.parent[catId]) {
obj.options[s++] = new Option(this.cats[catId][0], catId);
}else {
obj.options[s++] = new Option(this.cats[catId][0] + ' ->', catId);
}
if (defaultId >= 0 && defaultId == catId) {
obj.options[s-1].selected = true;
this.changeSubCat(obj);
}else if (i == 0 && !isFirst && this.haveBlank == '') {
obj.options[i].selected = true;
this.changeSubCat(obj);
}
}
}
};
}
function debug(info) {
//alert(info);
}
function error(info) {
alert(info);
}
详见: 附件2
实际项目中需要和数据库结合起来,通过标签输出,下面附件内容供大家参考:
本文介绍了一种实现多级下拉框联动的方法,并针对原有方案存在的问题进行了改进,使其能够支持多个独立的联动下拉框并允许自定义名称。

被折叠的 条评论
为什么被折叠?



