`

淘宝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[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

 

实际项目中需要和数据库结合起来,通过标签输出,下面附件内容供大家参考:

附件3

 

  • 大小: 19.4 KB
3
2
分享到:
评论
1 楼 qustmao 2009-01-03  
谢谢分享,,,,,正好项目中要用到这个东西,去淘宝研究了很长时间,没有分离出js文件,,,,我在js方面就是个小白,,,,,,

相关推荐

Global site tag (gtag.js) - Google Analytics