123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /**
- * @Name: 基于layui的无限级联选择器
- * @Author: 李祥
- * @License:MIT
- * 最近修改时间: 2019/03/20
- */
- layui.define(["jquery","laytpl","layer"], function (exports) {
- var $ = layui.jquery;
- var laytpl = layui.laytpl;
- var layer = layui.layer;
- var zIndex=3000; // 共用一个层级
-
- function Cascader(option) {
- this.option=option; // 获取传入的数据
- this.domContent=""; // content节点
- this.textArr=[]; // 最终的text数组
- this.textStr=""; // 最终的text
- this.valueArr=[]; // 最终的value数组
- this.onOff=false; // 是否显示
- this.positionArr=[]; // 当前点击的面板在数据中的下标位置
- this.blockData={}; // 当前点击的当前面板的数据
- // this.count=0; // 进入finishInitData的次数
- this.initOption();
- }
- Cascader.prototype={
- constructor: Cascader,
- // 初始化参数数据
- initOption: function () {
- var self=this;
- self.option.elem?(function(){
- self.elem=self.option.elem;
- })():(function() {
- throw "缺少elem节点选择器";
- })();
- self.triggerType=self.option.triggerType==="change"?"mouseenter":"click";
- self.changeOnSelect=self.option.changeOnSelect || false;
- // 判断data参数
- if(self.option.data){
- self.d=self.option.data;
- self.callback();
- return;
- }
- // 判断url参数
- if(self.option.url){
- $.ajax({
- url: self.option.url,
- type: self.option.type?self.option.type:"get",
- data: self.option.where?self.option.where:{},
- success: function(data){
- if(data.Code===0){
- self.d=data.Data;
- self.callback();
- return;
- }
- layer.alert(data.Msg, { title: "选择器"+self.elem+"获取数据失败", icon: 2 });
- }
- });
- return;
- }
- throw "选择器"+self.elem+"缺少data或url参数";
- },
- // 初始化容器和标签
- init: function () {
- $(this.elem).after('<i class="layui-icon layui-icon-down"></i>');
- $(this.elem).after('<div class="urp-cascader-content"></div>');
- },
- // 初始化第一层
- initFirst: function () {
- var string = laytpl(
- '<ul class="urp-cascader-child">'+
- '{{# for(var i=0;i<d.length;i++){ }}'+
- '<li>{{ d[i].label }}<i class="layui-icon layui-icon-right" ></i></li>'+
- '{{# } }}'+
- '</ul>'
- ).render(this.d);
- $(this.elem).siblings(".urp-cascader-content").append(string);
- this.domContent=$(this.elem).siblings(".urp-cascader-content");
- this.domContent.find(".urp-cascader-child").hide();
- // 显示隐藏第一层的标签
- for(var i=0;i<this.d.length;i++){
- ("children" in this.d[i] && this.d[i]["children"].length>0)?(
- this.domContent.find("ul.urp-cascader-child li").eq(i).find("i").show()
- ):(
- this.domContent.find("ul.urp-cascader-child li").eq(i).find("i").hide()
- );
- }
- },
- // 获取当前点击的当前面板的数据
- getBlockData: function (event,el) {
- event.stopPropagation();
- this.floor=$(el).parent().index(); // 当前点击的是第几层
- var index=$(el).index(); // 当前点击的是这一层的第几个
- this.positionArr.length=this.floor;
- this.positionArr.push(index);
-
- // 等同下方注释
- this.blockData = this.d[this.positionArr[0]];
- for(var i = 1; i<=this.floor; i++){
- this.blockData = this.blockData["children"][this.positionArr[i]];
- }
- // switch (floor) {
- // case 0:
- // blockData=d[arr[0]];
- // break;
- // case 1:
- // blockData=d[arr[0]]["children"][arr[1]];
- // break;
- // case 2:
- // blockData=d[arr[0]]["children"][arr[1]]["children"][arr[2]];
- // break;
- // case 3:
- // blockData=d[arr[0]]["children"][arr[1]]["children"][arr[2]]["children"][arr[3]];
- // break;
-
- // default:
- // break;
- // }
-
- },
- // 若有第二层则初始化第二层
- initChild: function (triggerData) {
- // 删除后面的面板
- this.domContent.find(".urp-cascader-child:gt("+(this.floor)+")").remove();
- // 获取text值
- this.textArr.length=this.floor;
- this.textArr.push(this.blockData.label);
- this.valueArr.length=this.floor;
- this.valueArr.push(this.blockData.value);
- var string = laytpl(
- '<ul class="urp-cascader-child">'+
- '{{# for(var i=0;i< d.length;i++){ }}'+
- '<li>{{ d[i].label }}<i class="layui-icon layui-icon-right"></i></li>'+
- '{{# } }}'+
- '</ul>'
- ).render(this.blockData["children"]);
- this.domContent.append(string);
- // 显示隐藏第二层的标签
- for(var i=0;i<this.blockData["children"].length;i++){
- ("children" in this.blockData["children"][i] && this.blockData["children"][i]["children"].length>0)?(
- this.domContent.find("ul.urp-cascader-child:gt("+(this.floor)+")").find("li").eq(i).find("i").show()
- ):(
- this.domContent.find("ul.urp-cascader-child:gt("+(this.floor)+")").find("li").eq(i).find("i").hide()
- );
- }
- if(this.changeOnSelect){
- // 文本拼接
- this.textStr=this.textArr.join("/");
- $(this.elem).val(this.textStr);
-
- if(triggerData!=="initValue" && this.option.success) this.option.success(this.valueArr,this.textArr);
- }
- },
- // 结束之后拿取数据
- finishInitData: function (triggerData) {
- this.domContent.find(".urp-cascader-child:gt("+(this.floor)+")").remove();
-
- this.textArr.length=this.floor;
- this.textArr.push(this.blockData.label);
- this.valueArr.length=this.floor;
- this.valueArr.push(this.blockData.value);
- // 文本拼接
- this.textStr=this.textArr.join("/");
- (this.option.showLastLevels)?(
- $(this.elem).val(this.textArr[this.textArr.length-1])
- ):(
- $(this.elem).val(this.textStr)
- );
-
- this.onOff = false;
- $(this.elem).siblings(".urp-cascader-content").find("ul").slideUp(100);
- $(this.elem).siblings("i").replaceWith('<i class="layui-icon layui-icon-down"></i>');
- // 如果有初始值,则第一次不回调
- if(triggerData!=="initValue" && this.option.success) this.option.success(this.valueArr,this.textArr);
- // this.count++;
- // if($.isArray(this.option.value) && this.option.value.length>0 && this.count===1 && this.option.success){
- // return;
- // }
- // if(this.option.success) this.option.success(this.valueArr,this.textArr);
- },
- // 赋初值
- initValue: function() {
- var self=this;
- ($.isArray(this.option.value) && this.option.value.length>0)?(function(){
- var value=self.option.value;
- $(self.elem).trigger("click");
- var arrr=[]; // 保存当前在data中的位置
- var data=self.d; // 需要遍历的子数组
- // 等同于下面的注释
-
- value.forEach(function(val,index){
- // console.log(data);
- if(!data) throw "选择器"+self.elem+"初始化数据不匹配";
- for(var i=0;i<data.length;i++){
- if(data[i].value==val){
- arrr.push(i);
- self.domContent.find(".urp-cascader-child").eq(index).find("li").eq(i).trigger(self.triggerType,"initValue");
- $(self.elem).siblings(".urp-cascader-content").find("ul").finish(); // 停止当前正在运行的动画
- }
- }
- // 先判断数据是否存在,即是否有相匹配的数据
- data[arrr[index]]?(function(){
- data=data[arrr[index]].children;
- })():(function(){
- throw "选择器"+self.elem+"初始化数据不匹配";
- })()
- })
- // for(var i=0;i<d.length;i++){
- // if(d[i].value==value[0]){
- // arrr.push(i);
- // obj.domContent.find(".urp-cascader-child").eq(0).find("li").eq(i).trigger(triggerType);
- // }
- // }
- // for(var i=0;i<d[arrr[0]].children.length;i++){
- // if(d[arrr[0]].children[i].value==value[1]){
- // arrr.push(i)
- // obj.domContent.find(".urp-cascader-child").eq(1).find("li").eq(i).trigger(triggerType);
- // }
- // }
- // for(var i=0;i<d[arrr[0]].children[arrr[1]].children.length;i++){
- // if(d[arrr[0]].children[arrr[1]].children[i].value==value[2]){
- // obj.domContent.find(".urp-cascader-child").eq(2).find("li").eq(i).trigger(triggerType);
- // }
- // }
- })():"";
- },
- callback: function () {
- // 初始化第一层
- this.init();
- this.initFirst();
- var self=this; // Cascader对象
- // 每层点击时绑定事件
- self.domContent.on(self.triggerType,".urp-cascader-child li",function(event,triggerData){
- var _self=this; // 点击的对象
- self.getBlockData(event,this);
- $(this).addClass("active").siblings("li").removeClass("active");
- // 判断当前是否存在子层
- ("children" in self.blockData && self.blockData["children"].length>0)?(
- // 初始化子层
- self.initChild(triggerData)
- ):(
- // 判断触发方式
- self.triggerType==="mouseenter"?(function() {
- self.domContent.find(".urp-cascader-child:gt("+(self.floor)+")").remove();
- // click事件先解除再定义,防止多次定义
- $(_self).off("click").on("click",function() {
- self.finishInitData();
- })
- // 赋初值时若为change则需要触发上方函数(判断是否是通过赋初值方式触发)
- if(triggerData==="initValue"){
- $(_self).trigger("click");
- }
- })():(
- self.finishInitData(triggerData)
- )
- );
- })
-
- // input点击显示隐藏
- $(self.elem).on("click", function () {
- self.onOff = !self.onOff;
- zIndex++;
- if (self.onOff) {
- $(self.elem).siblings(".urp-cascader-content").find("ul").slideDown(100);
- $(self.elem).siblings("i").replaceWith('<i class="layui-icon layui-icon-up"></i>');
- self.domContent.css("zIndex",zIndex);
- } else {
- $(self.elem).siblings(".urp-cascader-content").find("ul").slideUp(100);
- $(self.elem).siblings("i").replaceWith('<i class="layui-icon layui-icon-down"></i>');
- }
- })
- // 点击外层文档隐藏
- $(document).on("click",function(event) {
- if(event.target.isEqualNode($(self.elem).get(0))) return;
- self.onOff = false;
- if(!self.onOff){
- $(self.elem).siblings(".urp-cascader-content").find("ul").slideUp(100);
- $(self.elem).siblings("i").replaceWith('<i class="layui-icon layui-icon-down"></i>');
- }
- })
- self.initValue();
- },
- reload: function(option) {
- var self=this;
- this.domContent.off();
- $(this.elem).off().siblings(".urp-cascader-content,.layui-icon").remove();
- this.option = $.extend({}, this.option, option);
- $(this.elem).val("");
- this.domContent="";
- this.textArr=[];
- this.textStr="";
- this.valueArr=[];
- this.onOff=false;
- this.positionArr=[];
- this.blockData={};
- return this.initOption()
- }
- }
- var thisCas=function() {
- var self=this;
- return {
- reload: function(option) {
- self.reload.call(self,option);
- }
- }
- }
-
- exports('cascader', function(option) {
- var ins=new Cascader(option);
- return thisCas.call(ins);
- });
- })
|