级联菜单:linkSelect 维护版本

/**
级联下拉菜单
Last Edit:	2011-11-4
Version:	0.1
默认数据格式,没有自定义数据解析器时,都是以这种格式处理:
[
	{text:'2',value:'2',child:[
				{text:'2.1',value:'2.1',child:[]}
				]
	},
	{text:'1.1.1',value:'1.1.1'}

]
**/
(function($) {
//全局设定
var globalSetting = {
	dataType : null,//地区area、证书类型licence
	language : "cn",//显示语言
	maxLevel: 5,//级联层数
	onChange : function(){},//onchange事件
	format : function(text){	//格式化下拉菜单显示的内容,可以在全局参数统一设置,也可以在每一级单独设置
		return text;
	},
	css : ""
};
//某一级设定
var levelSetting = {
	container : null,//容器
	blankItem : null, //{text:'-----',value:-1}
	title : "",
	titlePos : "left",
	id : "select",
	css : "",
	defaultValue : null,
	format : function(text){}
};
//数据解析
var DataParser = {
	language : "cn",
	//每种类型不同的处理
	"area": {
		ordinalData : window.citys||[],
		idIndex : 5,
		textIndex : 2,
		setLanguage : function(language){
			if(language == "en"){
				this.idIndex = 5;
				this.textIndex = 3;
			}
		},
		getOrdinalData : function(i){
			return {value:this.ordinalData[i][this.idIndex],
					text:this.ordinalData[i][this.textIndex],
					isParent:this.ordinalData[i][4] == 1 ? true : false};
		}
	},
	"licence":{
		ordinalData : window.licence||[],
		idIndex : 1,
		textIndex : 0,
		setLanguage : function(language){
			if(language == "en"){
				this.idIndex = 1;
				this.textIndex = 0;
			}
		},
		getOrdinalData : function(i){
			return {value:this.ordinalData[i][this.idIndex],
				text:this.ordinalData[i][this.textIndex],
				isParent:this.ordinalData[i][2] == 1 ? true : false};
		}
	},
	getData : function(dataType){
		var data = [];
		var st = this[dataType];
		if(!st) return null;
		st.setLanguage(DataParser.language);
		var item,parentItem;
		for(var i=0;i<st.ordinalData.length;i++){
			item = st.getOrdinalData(i);
			if(item.isParent == true){
				item.child = [];
				parentItem = item;
				data.push(item);
			} else {
				parentItem.child.push(item);
			}
		}
		return data;
	},
	changeObjToMap : function(orgData){
		var stack = [].concat(orgData);
		var item, result = {};
		//将树形的结构转换为简单的key,value结构,key为菜单项的值,value为该项的子菜单数组
		while(stack.length != 0){
		    item = stack.shift();
		    result[item.value] = item.child || [];
		    if(item.child){
		        for(var j=0;j<item.child.length;j++){
		            stack.push(item.child[j]);
		        }
		    }
		}
		return result;
	},
	getDataParser : function(arg){
		var orgData = DataParser.getData(arg);
		if(!orgData){
			orgData = arg;
		}
		var result = this.changeObjToMap(orgData);
		//返回默认的数据解析器,自定义的解析器也要实现这里的方法
		return {
			//返回第一个菜单数组
			getRoot : function(){
				return orgData;
			},
			//根据级别参数和选中的值,返回下一级的
			getNext : function(value, level){
				return !!result[value] ? result[value] : [];
			}
		}
	}
};
/**
* 生成多级下拉菜单,并且控制菜单的关系
**/
cv.linkSelect = function(container, setting){
	this.container = jQuery(container);
	this.setting = [];
	this.setting[0]  = $.extend({}, globalSetting, setting);
	for(var i=1;i<=this.setting[0].maxLevel;i++){
		this.setting[i]  = $.extend({}, levelSetting, this.setting[0]);
	}
	this.parser = null;
	if(this.setting[0].dataType){
		DataParser.language = this.setting[0].language;
		this.parser = DataParser.getDataParser(this.setting[0].dataType);
	}
	this.selectors = [];
};

cv.linkSelect.prototype = {

	setOption : function(level, setting){
		if(level < 0){
			throw "level must start from 0";
		}
		this.setting[level + 1]  = $.extend({}, this.setting[level + 1], setting);
	},
	render : function(){
		var selector,defaultValue,currentData = this.parser.getRoot();
		for(var i=0;i<this.setting[0].maxLevel;i++){

			if(this.setting[i+1].blankItem){
				currentData.unshift(this.setting[i+1].blankItem)
			}
			defaultValue = this.setting[i+1].defaultValue;
			if(!defaultValue){
				defaultValue = currentData[0].value;
			}
			selector = new Selector(this, this.setting[i+1], i);
			selector.setData(currentData);
			selector.render();
			selector.setSelect(defaultValue);
			this.selectors[i] = selector;
			if(this.parser.getNext(defaultValue, i).length > 0){
				currentData =  this.parser.getNext(defaultValue, i);
			}else {
				break;//20121025修改
//				currentData = [];
			}
		}
	},
	//设置符合默认格式的数据
	setData : function(data){
		this.parser = DataParser.getDataParser(data);
	},
	setDataParser : function(parser){
		this.parser = parser;
	},
	setSelect : function(level, value){
		if(this.selectors[level]){
			this.selectors[level].setSelect(value);
			this.change(level);
		}
	},
	setText : function(level, text){
		if(this.selectors[level]){
			var value = this.selectors[level].setText(text);
			this.change(level);
		}
	},
	change : function(level){
		var childData, selector;
		for(var i=level;i<this.setting[0].maxLevel;i++){
			childData = this.parser.getNext(this.selectors[i].getSelectValue(), i);
			//当前选项没有子菜单,将已经生成的子菜单都删除
			if(!childData || childData.length == 0){
				for(var j=i+1;j<this.selectors.length;j++){
					if(this.selectors[j]){
						this.selectors[j].remove();
						this.selectors[j] = null;
					}
				}
				//break;//20121025修改
				break;
			}
			//因为level表示当前的级别,现在要取下一个级别的空白元素(level + 1),又因为setting跟level错开了一位,所以要level+2
			if(this.setting[level + 2].blankItem){
				childData.unshift(this.setting[level + 2].blankItem)
			}
			//判断下一级的子菜单是否存在,存在则刷新数据,不存在则创建新的子菜单
			if(this.selectors[i+1]){
				this.selectors[i+1].setData(childData);
				this.selectors[i+1].refreshItem();
			} else {
				selector = new Selector(this, this.setting[i+2], i+1);
				selector.setData(childData);
				selector.render();
				this.selectors[i+1] = selector;
			}
		}
		this.setting[0].onChange(level, this.selectors[level].getSelectValue());
	},
	getValue : function(){
		var result = [];
		for(var i=0;i<this.selectors.length;i++){
			if(!this.selectors[i]) break;
			result.push(this.selectors[i].getSelectValue());
		}
		return result;
	},
	getText : function(){
		var result = [];
		for(var i=0;i<this.selectors.length;i++){
			if(!this.selectors[i]) break;
			result.push(this.selectors[i].getSelectText());
		}
		return result;
	}
};
/**
* 代表每一级的菜单对象
**/
var Selector = function(linkSelectObj, setting, level){
	this.data = null;
	this.linkSelectObj = linkSelectObj;
	this.setting = setting;
	this.level = level;
	this.selectObj = null;
	this.container;
};
Selector.prototype = {
	addItem : function(item){
		this.selectObj.append("<option value='"+item.value+"'>"+this.setting.format(item.text)+"</option>");
	},
	addAllItem : function(){
		for(var i=0;i<this.data.length;i++){
			this.addItem(this.data[i]);
		}
	},
	setSelect : function(value){
		var item;
		this.selectObj.find("option").each(function(){
			if(this.value == value){
				this.selected=true;
				this.defaultSelected=true;
			} else {
				this.defaultSelected=false;
			}
		});
	},
	setText : function(text){
		var item , value;
		this.selectObj.find("option").each(function(){
			value = this.value;
			if($(this).html() == text){
				this.selected=true;
				this.defaultSelected=true;
			} else {
				this.defaultSelected=false;
			}
		});
		return value;
	},
	setData : function(data){
		this.data = data;
	},
	getSelectValue : function(){
		return this.selectObj.val();
	},
	getSelectText : function(){
		return this.selectObj.find("option").eq(this.selectObj.attr("selectedIndex")).html();
	},
	render : function(){
		var self = this;
		this.selectObj = $("<select></select>").attr("id", this.setting.id).addClass(this.setting.css)
							.change(function(){
								self.linkSelectObj.change(self.level);
							});
		if(this.setting.name)this.selectObj.attr("name", this.setting.name);
		this.addAllItem();
		if(this.setting.titlePos == "left"){
			this.container = $("<span></span>").append(this.setting.title).append(this.selectObj)
				.appendTo(this.setting.container ? this.setting.container : this.linkSelectObj.container);
		} else {
			this.container = $("<span></span>").append(this.selectObj).append(this.setting.title)
				.appendTo(this.setting.container ? this.setting.container : this.linkSelectObj.container);
		}
	},
	refreshItem : function(){
		this.selectObj.empty();
		this.addAllItem();
	},
	remove : function(){
		this.container.remove();
		this.container = null;
	},
	empty : function(){
		this.container.find("select").empty();
	}
};

})(jQuery);


各种使用:

转载于:https://my.oschina.net/wrean/blog/183031

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值