/** * JQ多级联动通用插件 * 初始化 $.linkAgeInit(options); * @param options * @version 1.0 * @email 641453620@qq.com * * id,插件内部唯一Id * zIndex,层级,默认899 * shade,遮罩,默认0.2。支持true,false,0~1 * fadeTime,淡入淡出时间(毫秒) * dataModel,插件数据来源模式:http 通过url插件自动请求获取数据源,data 通过 “dataSource” 注入数据源 * dataHttpUri,当 dataModel = http时,代表请求数据源的URL地址(使用GET请求方式) * dataHttpPidKeyName,当 dataModel = http时,请求 dataHttpUri 时携带当前选项Id的键值名称,默认 pid * dataHttpParams,当 dataModel = http时,需另外携带的请求参数 * dataHttpResultHandle,当 dataModel = http时,请求数据成功后,将调用该方法进行数据二次处理,然后返回给插件使用 * dataIndex, 联动数据层级,范围2~5,默认2 * dataName,联动显示名称,默认:['一级' , '二级' , '三级'] * dataSource,当 dataModel = data时,为数据源 * dataOnePid,当 dataModel = data时,一级数据源Id,默认0 * dataIdKey,数据源Id键值名,默认id * selectedValues,默认选中项,形式:[{id:442001001,name:'测试项1',route:id路径}],route可选 * maxChecked,最大支持选中项数量,默认5 * boxClickShow,选择后显示下一级列表,默认true。支持true,false * showHtml,Box主体模板 * showListHtml,下拉框主体Box html * showSelectHtml,下拉选择行 html,模板可自定义。内置变量:{id},{name},{route} * showCheckHtml,单项选择 html,模板可自定义。内置变量:{id},{name},{route},{_on_}(高亮class) * showCheckedHtml,已选择项 html,模板可自定义。内置变量:{id},{name},{route} * showShadeHtml,遮罩 html * closeCallBack,关闭按钮回调方法,传入已选中的项 * confirmCallBack,确认按钮回调方法,传入已选中的项 * msgCallBack,提示信息处理方法,传入提示消息 * @type {{id: number, zIndex: number, shade: boolean, fadeTime: number, dataModel: string, dataHttpUri: Array, dataHttpPidKeyName: string, dataHttpParams: {}, dataHttpResultHandle: (function(*): *), dataIndex: number, dataName: string[], dataSource: Array, dataOnePid: number, dataIdKey: string, selectedValues: Array, maxChecked: number, showHtml: string, showListHtml: string, showSelectHtml: string, showCheckHtml: string, showCheckedHtml: string, showShadeHtml: string, closeCallBack: string, confirmCallBack: string, msgCallBack: msgCallBack}} * @returns {*} */ ;(function ($) { var instanceNums = 0; $.extend({ linkAgeInit:function (options) { var defaults = { id:12138, zIndex:899, shade:0.2, fadeTime:600, boxTitle:'请选择地区', dataModel:'http', dataHttpUri:[], dataHttpPidKeyName:'pid', dataHttpParams:{}, dataHttpResultHandle:function (res) { return res.data; }, dataIndex:2, dataName:['一级' , '二级' , '三级'], dataSource:[], dataOnePid:0, dataIdKey:'id', //已选择Id项 selectedValues:[], maxChecked:5, boxClickShow:true, showHtml:' ', showListHtml:'
\n' + ' \n' + '
', showSelectHtml:'
  • {name}
  • ', showCheckHtml:'
    {name}
    ', showCheckedHtml:'
    {name}
    ', showShadeHtml:'
    ', closeCallBack:'', confirmCallBack:'', msgCallBack:function (msg) { alert(msg); } }; if (!options) options = {}; //初始化配置 options = $.extend(defaults, options); //唯一Id instanceNums++; options.id = options.id + instanceNums; if (options.dataIndex < 2) { console.log('Error : dataIndex 不能小于2!'); return false; } try { //实例化 return init(options); } catch (e) { console.log('Error : ' , e); return false; } }, }); //私有业务方法 //实例化插件 function init(options) { return { options:options, /** * 打开窗口 * @param areaItem */ open:function (areaItem) { var $this = this; var $thisSys = $this.options; //选择元素 if (!areaItem) areaItem = 'body'; //BoxId var thisBoxId = '.thr-box-'+$thisSys.id + ' '; //遮罩 if ($thisSys.shade !== false) { var thisShadeTpl = $thisSys.showShadeHtml; var shadeNums = $thisSys.shade === true ? 0.2 : $thisSys.shade; thisShadeTpl = thisShadeTpl.replace(/{shadeNums}/g , shadeNums); thisShadeTpl = thisShadeTpl.replace(/{z_index}/g , $thisSys.zIndex-1); $(areaItem).append(thisShadeTpl); } //判断Box是否存在 var thisStatus = $(".thr-box-" + $thisSys.id).css('display'); if (thisStatus == 'none') { $(".thr-box-" + $thisSys.id).fadeIn($thisSys.fadeTime); //局部渲染 if ($thisSys.selectedValues.constructor == Array && $thisSys.selectedValues.length > 0) { var thisSelectedIds = []; for (var i in $thisSys.selectedValues) { thisSelectedIds.push($thisSys.selectedValues[i].id); } $(thisBoxId + '.thr-select-area dd').each(function () { var $this = $(this); var $thisId = $(this).data('id'); if (!in_array($thisId , thisSelectedIds)) { //丢弃选项 $this.remove(); //丢球选中 $(thisBoxId + ".thr-check-box dd[data-id='"+$thisId+"']").removeClass('on'); } }) } return; } var thisHtml = $thisSys.showHtml; //替换 thisHtml = thisHtml.replace(/{id}/g , $thisSys.id); thisHtml = thisHtml.replace(/{z_index}/g , $thisSys.zIndex); thisHtml = thisHtml.replace(/{boxTitle}/g , $thisSys.boxTitle); thisHtml = thisHtml.replace(/{maxChecked}/g , $thisSys.maxChecked); //遍历结构体 thisHtml = thisHtml.replace(/{selectList}/g , loopSelectBoxInit($thisSys)); //遍历已选择项 if ($thisSys.selectedValues.constructor == Array) { var selectedHtml = ''; for (var s in $thisSys.selectedValues) { var selectedTpl = $thisSys.showCheckedHtml; selectedTpl = selectedTpl.replace(/{id}/g , $thisSys.selectedValues[s].id); selectedTpl = selectedTpl.replace(/{name}/g , $thisSys.selectedValues[s].name); selectedTpl = selectedTpl.replace(/{route}/g , ''); selectedHtml += selectedTpl; } thisHtml = thisHtml.replace(/{selectedList}/g , selectedHtml); } else { thisHtml = thisHtml.replace(/{selectedList}/g , ''); } //输出 $(areaItem).append(thisHtml); //显示 $(thisBoxId).fadeIn($thisSys.fadeTime); //移除事件 $('body').off('click' , thisBoxId + '.thr-list-area ul li'); $('body').off('click' , thisBoxId + '.thr-check-box dl dd'); $('body').off('click' , thisBoxId + '.thr-select-area dd'); $('body').off('click' , thisBoxId + '.thr-confirm'); $('body').off('click' , thisBoxId + '.thr-close-'+$thisSys.id); //绑定事件 //下拉选择区点击 $('body').on('click', thisBoxId + '.thr-list-area ul li:not(:first-child)' , function () { var $thisLi = $(this); var $index = $thisLi.parent().parent().data('index'); var nextIndex = parseInt($index)+1; var $thisId = $thisLi.data('id'); var $thisRoute = $thisLi.data('route'); $thisLi.siblings().removeClass('on'); $thisLi.addClass('on'); if (nextIndex < $thisSys.dataIndex) { if ($thisSys.boxClickShow) { //显示 $('.thr-box-'+$thisSys.id+' .thr-list-'+nextIndex).show(); } var nextHtml = loopSelectBoxItem($thisId , $thisSys.showSelectHtml , nextIndex , $thisRoute , $thisSys); $('.thr-box-'+$thisSys.id+' .thr-list-'+nextIndex+' ul li.thr-name').nextUntil().remove(); $('.thr-box-'+$thisSys.id+' .thr-list-'+nextIndex+' ul').append(nextHtml); return; } //最后一级 var nextHtml = loopSelectBoxItem($thisId , $thisSys.showCheckHtml , nextIndex , $thisRoute , $thisSys); $('.thr-box-'+$thisSys.id+' .thr-check-box dl').html('').append(nextHtml); }); //选择项事件 $('body').on('click' , thisBoxId + '.thr-check-box dl dd' , function () { var $thisDd = $(this); var $thisId = $thisDd.data('id'); var $thisRoute = $thisDd.data('route'); var $thisName = $.trim($thisDd.text()); if ($thisSys.selectedValues.constructor != Array) { $thisSys.selectedValues = []; } //验证已选择 for (var s in $thisSys.selectedValues) { if ($thisId == $thisSys.selectedValues[s].id) { //删除操作 $thisSys.selectedValues.splice(s , 1); $thisDd.removeClass('on'); $(thisBoxId + ".thr-select-area dd[data-id='"+$thisId+"']").remove(); return false; } } //验证最大选择数量 if ($thisSys.selectedValues.length >= $thisSys.maxChecked) { if (typeof $thisSys.msgCallBack == 'function') { $thisSys.msgCallBack('您最多只可选择 '+$thisSys.maxChecked+' 个哦!'); } return false; } //添加 var thisTpl = $thisSys.showCheckedHtml; thisTpl = thisTpl.replace(/{id}/g , $thisId); thisTpl = thisTpl.replace(/{name}/g , $thisName); thisTpl = thisTpl.replace(/{route}/g , $thisRoute); $(thisBoxId + '.thr-select-area').append(thisTpl); $thisSys.selectedValues.push({id:$thisId,name:$thisName,route:$thisRoute}); $thisDd.addClass('on'); }); //点击删除项 $('body').on('click' , thisBoxId + '.thr-select-area dd' , function () { var $thisDd = $(this); var $thisId = $thisDd.data('id'); if ($thisSys.selectedValues.constructor != Array) { $thisSys.selectedValues = []; return false; } //删除数据 for (var s in $thisSys.selectedValues) { if ($thisId == $thisSys.selectedValues[s].id) { //删除 $thisSys.selectedValues.splice(s , 1); } } $thisDd.remove(); $(thisBoxId + ".thr-check-box dl dd[data-id='"+$thisId+"']").removeClass('on'); }); //确定事件 $('body').on('click' , thisBoxId + '.thr-confirm' , function () { $(".thr-linkage-shade").remove(); $(".thr-box-" + $thisSys.id).fadeOut($thisSys.fadeTime); //回调 if (typeof $thisSys.confirmCallBack == 'function') { $thisSys.confirmCallBack($thisSys.selectedValues); } }); //关闭 $('body').on('click' , thisBoxId + '.thr-close-'+$thisSys.id , function () { $(".thr-linkage-shade").remove(); $(".thr-box-" + $thisSys.id).fadeOut($thisSys.fadeTime , function () { $(this).remove(); }); //回调 if (typeof $thisSys.closeCallBack == 'function') { $thisSys.closeCallBack($thisSys.selectedValues); } //清空已选数据 $thisSys.selectedValues = []; }); }, /** * 注入已选数据,格式:[{id:1,name:名称,route:id路径}] * @param selected */ set:function (selected) { var $this = this; if (selected && selected.constructor == Array) { $this.options.selectedValues = selected; return; } $this.options.selectedValues = []; } }; } /** * 根据配置遍历单项下拉选择数据(初始化) * @param thisSys */ function loopSelectBoxInit(thisSys) { var thisList = ''; for (var i=0;i<(thisSys.dataIndex-1);i++) { var volistItem = ''; var thisListHtml = thisSys.showListHtml; thisListHtml = thisListHtml.replace(/{index}/g , (i+1)); thisListHtml = thisListHtml.replace(/{name}/g , thisSys.dataName[i]); //初始化 if (i == 0) { thisListHtml = thisListHtml.replace(/{display}/g , ''); volistItem = loopSelectBoxItem(thisSys.dataOnePid , thisSys.showSelectHtml , (i+1) , '' , thisSys); } else { thisListHtml = thisListHtml.replace(/{display}/g , thisSys.boxClickShow ? 'style="display:none;"' : ''); volistItem = ''; } thisListHtml = thisListHtml.replace(/{volistItem}/ , volistItem) thisList += thisListHtml; } return thisList; } function loopSelectBoxItem(thisPid , thisHtml , thisIndex , thisRoute , thisSys){ var thisData = []; var thisSelectIdValue = []; if (thisSys.selectedValues.constructor == Array) { for (var s in thisSys.selectedValues) { thisSelectIdValue.push(thisSys.selectedValues[s].id); } } switch (thisSys.dataModel) { case 'http': if (thisSys.dataHttpUri.constructor == Array) { var thisUrl = thisSys.dataHttpUri[thisIndex-1]; } else { var thisUrl = thisSys.dataHttpUri; } if (isNull(thisUrl)) { throw new Error('dataHttpUri Error : data error !'); } //构造请求参数 var requestData = {}; requestData[thisSys.dataHttpPidKeyName] = thisPid; requestData = $.extend(requestData , thisSys.dataHttpParams); //请求 $.ajax({ async:false, type:'GET', url:thisUrl, data:requestData, error:function () {}, success:function (res) { if (typeof thisSys.dataHttpResultHandle == 'function') { thisData = thisSys.dataHttpResultHandle(res); } } }); break; case 'data': if (!(thisSys.dataSource).hasOwnProperty(thisPid)) { throw new Error('dataSource Error : '+thisPid+' Property does not exist !'); } thisData = thisSys.dataSource[thisPid]; break; default: throw new Error('dataModel Error !'); } if (isNull(thisData)) return ''; //遍历html var returnHtml = ''; for (var i in thisData) { var thisForHtml = thisHtml; if (thisData[i].constructor == Object) { for (var j in thisData[i]) { var thisExp = new RegExp('{'+j+'}' , 'g'); thisForHtml = thisForHtml.replace(thisExp , thisData[i][j]); //选项高亮 if (!isNull(thisSelectIdValue) && thisIndex == thisSys.dataIndex && in_array(thisData[i][thisSys.dataIdKey] , thisSelectIdValue)) { thisForHtml = thisForHtml.replace(/{_on_}/ , 'on'); } else { thisForHtml = thisForHtml.replace(/{_on_}/ , ''); } //路由Id var thisRouteTxt = ''; if (isNull(thisRoute)) { thisRouteTxt = thisData[i][thisSys.dataIdKey]; } else { thisRouteTxt = thisRoute + '-' + thisData[i][thisSys.dataIdKey]; } thisForHtml = thisForHtml.replace(/{route}/ , thisRouteTxt); } } else { throw new Error('dataSource Error : ' , thisData[i]); } returnHtml += thisForHtml; } //返回 return returnHtml; } //公共方法 /** * 检验数据是否为 null,undefined,"" * @param string * @returns {boolean} */ function isNull(string) { string = $.trim(string); if (string === 0) { return false; } if(string == "" || string == undefined || string == null || string == "undefined") { return true; } return false; } /** * 搜索某个值是否存在数组之内 * @param needle 搜索的值 * @param haystack 被搜索的数组 * */ function in_array(needle, haystack) { if (haystack.constructor != Array) { haystack = String(haystack).split(','); } var length = haystack.length; for(var i = 0; i < length; i++) { if(haystack[i] == needle) return true; } return false; } })(jQuery);