1. 程式人生 > >layui自定義外掛citySelect 省市區三級聯動選擇

layui自定義外掛citySelect 省市區三級聯動選擇


citySelect.js


/**
 * @ name : citySelect 省市區三級選擇模組
 * @ Author: aggerChen
 * @ version: 1.0
 */

layui.define(['layer','form','element','laytpl'], function(exports){
	var $ = layui.$;
	var form = layui.form;
	var laytpl = layui.laytpl;
	var element = layui.emelemt;
	
	//外部介面
	var citySelect = {
		    config: {} //全域性配置項
		    ,cache: {} //資料快取
		    ,index: layui.laypage ? (layui.laypage.index + 10000) : 0
	};
	
	//操作當前例項
	var thisSelect = function(){
	    var that = this,
	    options = that.config,
	    id = options.id;
	    id && (thisSelect.config[id] = options);
	    
	    return {
	      reload: function(options){
	    	  that.reload.call(that, options);
	      },
	      config: options
	    }
	};
	
	//字元常量
	var MOD_NAME = 'citySelect';
	
	//主模板
	var TPL_MAIN = ['<div class="layui-form-item" >',
						'<label class="layui-form-label">{{ d.data.lableName }}</label>',
						'<div class="layui-input-inline" style="width:160px">',
							'<select name="{{ d.data.filed.provinceName }}" class="{{ d.data.id }}_selectCity" id="citySelect_{{ d.data.filed.provinceName }}{{ d.index }}" lay-filter="province{{ d.index }}" {{#if(d.data.search){ }}  lay-search {{# } }} {{#if(d.data.required){ }} lay-verify="required" {{# } }} {{#if(d.data.disabled){ }} disabled {{# } }} >',
								'<option value="000000">-- 全部 --</option>',
							'</select>',
						'</div>',
						'<div class="layui-input-inline" style="width:161px">',
							'<select name="{{ d.data.filed.cityName }}" class="{{ d.data.id }}_selectCity" id="citySelect_{{ d.data.filed.cityName }}{{ d.index }}" lay-filter="city{{ d.index }}" {{#if(d.data.search){ }}  lay-search {{# } }} {{#if(d.data.required){ }} lay-verify="required" {{# } }} {{#if(d.data.disabled){ }} disabled {{# } }} >',
								'<option value="">-- 全部 --</option>',
							'</select>',
						'</div>',
						'{{# if(d.data.filed.area){ }}',
						'<div class="layui-input-inline" style="width:161px">',
							'<select name="{{ d.data.filed.areaName }}" class="{{ d.data.id }}_selectCity" id="citySelect_{{ d.data.filed.areaName }}{{ d.index }}" lay-filter="area{{ d.index }}" {{#if(d.data.search){ }}  lay-search {{# } }} {{#if(d.data.required){ }} lay-verify="required" {{# } }} {{#if(d.data.disabled){ }} disabled {{# } }} >',
								'<option value="">-- 全部 --</option>',
							'</select>',
						'</div>',
						'{{# } }}',
						
						'{{# if(d.data.msg){ }}',
						 '<div class="layui-form-mid layui-word-aux">{{ d.data.msg }}</div>',
						 '{{# } }}',
					'</div>'
				].join("");
	//選項模板
	var TPL_OPTION = [
	                '<option value="">-- 全部 --</option>',
	                '{{# layui.each(d.data,function(index,item){ }}',
	                	'<option class="ajaxOption" value="{{ item[d.options.filed.regionId] }}" {{#if(d.options.selectedArr.length>0 && ($.inArray(item[d.options.filed.regionId], d.options.selectedArr)!=-1)){ }} selected {{# } }} >{{ item[d.options.filed.regionName] }}</option>',
	                '{{# }) }}'
	                ].join("");
	
	
	//構造器
	var Class = function(options){
		var that = this;
	    that.index = ++citySelect.index;
	    that.config = $.extend(true,{}, that.config, citySelect.config, options);
	    that.render();
	};
	
	//核心入口
	citySelect.render = function(options){
	    var inst = new Class(options);
	    return thisSelect.call(inst);
	};
    //獲取選中值
	citySelect.values = function(id){
		return citySelect.cache[id]["values"];		//返回快取中的選中值
    };
    //設定禁用/啟用
    citySelect.disabled = function(id,flag){
    	$("."+id+"_selectCity").attr("disabled",flag);
    };
    //過載
    thisSelect.config = {};
    citySelect.reload = function(id,options){
    	var config = thisSelect.config[id];
        if(!config) return hint.error('The ID option was not found in the citySelect instance');
        return citySelect.render($.extend(true, {}, config, options));
    };
	
	//預設配置
	Class.prototype.config = {
		lableName : "行政區域",
		required : false,		//是否必選
		search : true,			//是否搜尋
		msg:null,				//預設附加資訊
		selectedArr : [],		//預設選中陣列
		disabled:false,			//禁用 預設不禁用
		filed:{
	    	area:true,				//預設啟用區
	    	regionId:'regionId',	//預設欄位id名
	    	regionName:'regionName',//預設欄位name名
	    	provinceName: "province",	//預設省份名稱
			cityName : "city",			//預設城市名稱
			areaName : "area",			//預設區縣名稱
	    },
		
	};
	
	//載入容器
	Class.prototype.render = function(){
		 var that = this;
		 var options = that.config;	
		 options.elem = $(options.elem);
		 var othis = options.elem; 
		 if(!options.elem[0]) return that;		//如果元素不存在
	     
		 //請求引數的自定義格式
	     options.request = $.extend({
	    	 //pageName: 'page',
	    	 //limitName: 'limit'
	     }, options.request);
	    
	    //響應資料的自定義格式
	    options.response = $.extend({
	    	statusName: 'code',
	    	statusCode: 0,
	    	msgName: 'msg',
	    	dataName: 'data',
	    }, options.response);
		 
		 //主容器
		 var reElem = that.elem = $(laytpl(TPL_MAIN).render({
		      //VIEW_CLASS: ELEM_VIEW,
		      data: options,
		      index: that.index //索引
		 }));
		 othis.html(reElem);			//生成主元素
		 that.pullData();				//渲染初始
		 that.formFilter();				//監聽選擇
		 
	};
	
	//監聽表單
	Class.prototype.formFilter = function(){
		var that = this;
		var options = that.config;
		that.key = options.id || options.index;
		
		//監聽省
		form.on('select(province'+that.index+')', function(data){
			var cityDom = $("#citySelect_"+ options.filed.cityName + that.index);	//市
			var areaDom = $("#citySelect_"+ options.filed.areaName + that.index);	//區
			that.chearDom(cityDom);								//清理市
			that.chearDom(areaDom);								//清理區
			citySelect.cache[that.key]["values"][0] = data.value;	//存入快取
			citySelect.cache[that.key]["values"][1] = "";			//清理市級快取
			citySelect.cache[that.key]["values"][2] = "";			//清理區級快取
			if(data.value!=""){
				if(options.data){
					that.localData(cityDom, data.value);				//本地渲染市級			
				}else{
					that.ajaxData(cityDom,data.value);					//ajax渲染市
				}
			}
		}); 
		//監聽市
		form.on('select(city'+that.index+')', function(data){
			var areaDom = $("#citySelect_"+ options.filed.areaName + that.index);	//區
			that.chearDom(areaDom);									//清理區
			citySelect.cache[that.key]["values"][1] = data.value;
			citySelect.cache[that.key]["values"][2] = "";
			if(data.value!=""){
				if(options.data){
					that.localData(areaDom, data.value);				//本地渲染市級			
				}else{
					that.ajaxData(areaDom,data.value);					//載入區
				}
			}
		}); 
		//監聽區
		form.on('select(area'+that.index+')', function(data){
			citySelect.cache[that.key]["values"][2] = data.value;
			console.log("選擇區"); //得到select原始DOM物件
		}); 
		
	};
	
	//渲染資料
	Class.prototype.pullData = function(){
		var that = this;
		var options = that.config;
		var dom = $("#citySelect_"+ options.filed.provinceName + that.index);	//預設先渲染省
		that.key = options.id || options.index;
		citySelect.cache[that.key] = {values:["","",""]}; 	//記錄values快取標記
		
		if(options.data){ 		//data存在
			that.localData(dom,"000000");
		}else if(options.url){	//url存在
			that.ajaxData(dom);
		}
		
	};
	
	//data渲染資料
	Class.prototype.localData = function(dom,regionId){ 
		var that = this;
		var options = that.config;
		var regs = /^\d{2}0000$/;	//驗證省id 
		var regc = /^\d{4}00$/; 	//驗證市ID
		if(regionId=="000000"){
			//渲染省級
			that.renderData(options.data,dom);
		}else if(regs.test(regionId)){
			//渲染市級
			$.each(options.data,function(index,item){
				if(regionId==item[options.filed.regionId]){
					that.renderData(item.children,dom);
				}
			});
		}else if(regc.test(regionId)){
			//渲染區級
			var sId = regionId.substr(0, 2)+"0000";		//獲取省級Id
			$.each(options.data,function(index,item){
				if(sId==item[options.filed.regionId]){
					$.each(item.children,function(i,it){
						if(regionId==it[options.filed.regionId]){
							that.renderData(it.children,dom);
						}
					});
				}
			});
		}
	}
	
	
	//ajax獲取資料
	Class.prototype.ajaxData = function(dom,regionId){
		var that = this;
		var options = that.config;
	    var response = options.response;
	    var params = {};
	    params[options.filed.regionId] = regionId==undefined?"000000":regionId;
	    
	    //先檢視快取有沒有
	    if(citySelect.cache[that.key][regionId]!=undefined ){
	    	 that.renderData(citySelect.cache[that.key][regionId],dom);
	    }else{
	    	$.ajax({
	    		type: options.method || 'get',
	    		url: options.url,
	    		data: $.extend(params, options.where),
	    		dataType: 'json',
	    		success: function(res){
	    			if(res[response.statusName] != response.statusCode){
	    				that.renderForm();
	    				typeof options.error === 'function' && options.error(res);
	    				return ;
	    			}
	    			var data = res[options.response.dataName] || [];
	    			that.renderData(data,dom);
	    			if(data.length>0){
	    				citySelect.cache[that.key][regionId] = data;			//將已經獲取的資料儲存快取
	    			}
	    			options.time = (new Date().getTime() - that.startTime) + ' ms'; //耗時(介面請求+檢視渲染)
	    			typeof options.done === 'function' && options.done(res);
	    		}
	    	,error: function(e, m){
	    		that.renderData('<option value="">資料介面請求異常</option>',dom);
	    		typeof options.error === 'function' && options.error(res, e,m);
	    	}
	    	});
	    }
	    
	};
	
	//資料渲染
	Class.prototype.renderData = function(data,dom){
		var that = this,
		options = that.config;
		var selectedArr = options.selectedArr;		//獲取預設選中陣列
		
		if(typeof data === 'string'){
			$(dom).html(data);
		}else{
			//渲染選擇項
			$(dom).html( $(laytpl(TPL_OPTION).render({
				data: data,
				options:options,
				index: that.index //索引
			})));
			that.renderForm('select');
		}
		//設定預設選中
		var v = $(dom).val();
		if(v!=""&&selectedArr.length>0){
			for (var i = 0; i < selectedArr.length; i++) {
				if(v == selectedArr[i] && i<3){
					citySelect.cache[that.key]["values"][i] = v;		//儲存到選中快取
					that.config.selectedArr[i] = "";					//清除預設選擇陣列
					if(i==0){
						var dom = $("#citySelect_"+ options.filed.cityName + that.index);
						if(options.data){
							that.localData(dom, v);		//本地渲染市級			
						}else{
							that.ajaxData(dom, v);		//ajax渲染市級
						}
					}else if(i==1&&options.filed.area){
						var dom = $("#citySelect_"+ options.filed.areaName + that.index);
						if(options.data){
							that.localData(dom, v);		//本地渲染區級			
						}else{
							that.ajaxData(dom, v);		//ajax渲染區級
						}
					}
				}
			}
		}
	};

	
	//渲染表單
	Class.prototype.renderForm = function(type){
		form.render(type);
	};
	
	//清空select
	Class.prototype.chearDom = function(dom){
		var that = this;
		$(dom).html('');
		$(dom).append('<option value="">-- 全部 --</option>');
		that.renderForm('select');
	};
	
	//暴露模組
	exports(MOD_NAME, citySelect);
});