一、预览
二、代码
1.HTML部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script type="text/javascript" src="./template-web.js"></script> <link rel="stylesheet" type="text/css" href="./chooseItem.css"> </head> <body> <!-- 按钮触发模态框 --> <input type="text" class="form-control" data-toggle="modal" data-target="#myModal" id="showModal"/> <p>已选中的标签</p> <ol class="showItem"></ol> <!-- 模态框(Modal) --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h4 class="modal-title" id="myModalLabel"> 选择成员 </h4> </div> <div class="modal-body"> <div class="choose"></div> <ul id="myTab" class="nav nav-tabs"> <li class="active"> <a href="#apartment" data-toggle="tab"> 按部门选择 </a> </li> <li><a href="#self" data-toggle="tab">按人员选择</a></li> </ul> <div id="content-area"></div> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" id="sure"> 确定 </button> </div> </div><!-- /.modal-content --> </div><!-- /.modal --> </div> </body> <script id="tem" type="text/html"> <div id="myTabContent" class="tab-content"> <div class="tab-pane fade in active" id="apartment"> <ul> <li><p class="dropdow">{{level}}<input type="checkbox" class="A" id="{{id}}" /><label class="checkbox_label" for="{{id}}" onclick="addItem($(this),$(this).parent().text())"></label></p> <ul> {{each childlevel as A}} <li><p class="dropdow">{{A["level"]}}<input type="checkbox" class="A" id="{{A['id']}}"/><label class="checkbox_label" for="{{A['id']}}" onclick="addItem($(this),$(this).parent().text())"></label></p> {{if A["childlevel"].length>0}} <ul> {{each A["childlevel"] as B}} <li><p class="dropdow">{{B["level"]}}<input type="checkbox" class="A" id="{{B['id']}}"/><label class="checkbox_label" for="{{B['id']}}" onclick="addItem($(this),$(this).parent().text())"></label></p> {{if B["childlevel"].length>0}} <ul> {{each B["childlevel"] as C}} <li><p>{{C["level"]}}<input type="checkbox" class="A" id="{{C['id']}}"/><label class="checkbox_label" for="{{C['id']}}" onclick="addItem($(this),$(this).parent().text())"></label></p></li> {{/each}} </ul> {{/if}} </li> {{/each}} </ul> {{/if}} </li> {{/each}} </ul> </li> </ul> </div> <div class="tab-pane fade" id="self"> <div class="side"> <ul> <li><p class="dropdow">{{level}}<span style="display: none;">[]</span></p> <ul> {{each childlevel as A}} <li><p class="dropdow">{{A["level"]}}<span style="display: none;">{{A["staf"]}}</span></p> {{if A["childlevel"].length>0}} <ul> {{each A["childlevel"] as B}} <li><p class="dropdow">{{B["level"]}}<span style="display: none;">{{B["staf"]}}</span></p> {{if B["childlevel"].length>0}} <ul> {{each B["childlevel"] as C}} <li><p class="dropdow">{{C["level"]}}<span style="display: none;">{{C["staf"]}}</span></p></li> {{/each}} </ul> {{/if}} </li> {{/each}} </ul> {{/if}} </li> {{/each}} </ul> </li> </ul> </div> <div class="detail"> </div> </div> </div> </script> <script type="text/javascript" src="http://www.w3school.com.cn/jquery/jquery-1.11.1.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script type="text/javascript" src="chooseItem.js"></script> <script type="text/javascript"> $(function(){ var data={ level:"读书郎", id:"readboy", childlevel:[{ level:"总经办", id:"all", childlevel:[], staf:[ { id:"Z1", level:"总经办阿七" }, { id:"Z2", level:"总经办阿哥" }, { id:"Z3", level:"总经办阿龙" }, { id:"Z4", level:"总经办阿东" }, { id:"Z5", level:"总经办阿强" }] },{ level:"市场营销", id:"market", childlevel:[{ level:"客户服务", id:"service", childlevel:[{ level:"400客服", id:"service1", childlevel:[], staf:[ { id:"K1", level:"客服阿七" }, { id:"K2", level:"客服阿哥" }, { id:"K3", level:"客服阿龙" }, { id:"K4", level:"客服阿东" }, { id:"Z5", level:"客服阿强" }] }] },{ level:"推培部", id:"teach", childlevel:[{ level:"推培一部", id:"teach1", childlevel:[], staf:[ { id:"T1", level:"推培一部阿七" }, { id:"T2", level:"推培一部阿哥" }, { id:"T3", level:"推培一部阿龙" }, { id:"T4", level:"推培一部阿东" }, { id:"T5", level:"推培一部阿强" }] },{ level:"推培二部", id:"teach2", childlevel:[], staf:[ { id:"TS1", level:"推培二部阿七" }, { id:"TS2", level:"推培二部阿哥" }, { id:"TS3", level:"推培二部阿龙" }, { id:"TS4", level:"推培二部阿东" }, { id:"TS5", level:"推培二部阿强" }] }] },{ level:"渠道部", id:"way", childlevel:[{ level:"渠道一部", id:"way1", childlevel:[], staf:[ { id:"Q1", level:"渠道一部阿七" }, { id:"Q2", level:"渠道一部阿哥" }, { id:"Q3", level:"渠道一部阿龙" }, { id:"Q4", level:"渠道一部阿东" }, { id:"Q5", level:"渠道一部阿强" }] },{ level:"渠道二部", id:"way2", childlevel:[], staf:[ { id:"QS1", level:"渠道二部阿七" }, { id:"QS2", level:"渠道二部阿哥" }, { id:"QS3", level:"渠道二部阿龙" }, { id:"QS4", level:"渠道二部阿东" }, { id:"QS5", level:"渠道二部阿强" }] }] }] }] }; var html=template('tem', data); $('#content-area').html(html); var CI=new ChooseItem(); CI.usefor(); }) </script> </html>
2.CSS部分
.form-control{ width: 20%; } .modal-body{ padding: 0px; } .modal-content{ border-radius: 0px; } .choose{ margin: 0 auto; margin-top: 15px; margin-bottom: 15px; width: 95%; min-height: 50px; border: 1px solid #c9d0d9; border-radius: 4px; } .nav-tabs{ border-top: 1px solid #c9d0d9; border-bottom: 1px solid #c9d0d9; padding-left: 15px; } .nav-tabs>li{ margin-bottom: 0px; } /*点击后的样式*/ .nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover{ color: #269bec; font-weight: 600; border: 0px; border-bottom:3px solid #269bec; } a{ color: black; } .btn-primary{ background-color: #269bec; border: 0px; } .btn{ border-radius: 0px; } .tab-content{ height: 250px; overflow-y: scroll; } .tab-content::-webkit-scrollbar {/*滚动条整体样式*/ width: 4px; /*高宽分别对应横竖滚动条的尺寸*/ height: 4px; } .tab-content::-webkit-scrollbar-thumb {/*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } .tab-content::-webkit-scrollbar-track {/*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); } .tab-pane{ width: 100%; height: 100%; } ul{ padding-left: 30px; } li{ list-style: none; cursor: pointer; } #apartment input[type="checkbox"]{ float: right; display: none; } .checkbox_label{ float: right; } .checkbox_label:before { content: ""; display: inline-block; vertical-align: middle; width: 13px; height: 13px; border:1px solid #269bec; } input[type="checkbox"]:checked+.checkbox_label:before { background-color:#269bec; } p{ margin-right: 15px; } /*下拉菜单*/ #apartment .dropdown-menu{ left: 3%; width:97%; border: 0px; box-shadow: 0 0 0 transparent; } #apartment ul li ul{ display: none; } #self ul li ul{ display: none; } #self{ display: flex; } #self .side{ flex: 0 0 35%; width: 35%; height: 100%; overflow-y: scroll; } #self .side::-webkit-scrollbar {/*滚动条整体样式*/ width: 7px; /*高宽分别对应横竖滚动条的尺寸*/ height: 7px; } #self .side::-webkit-scrollbar-thumb {/*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } #self .side::-webkit-scrollbar-track {/*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); } #self .detail{ flex: 1; height: 100%; } #self .line{ padding-top: 15px; padding-left: 15px; padding-right: 15px; margin: 0px; } #self .A{ float: right; display: none; } .choosebox{ position: relative; margin: 2px; padding:2px; display: inline-block; border: 1px solid rgba(0,0,0,0.2); border-radius: 2px; } .choosebox .delete{ display: block; position: absolute; top: -7px; right: -7px; width:15px; height: 15px; background-color: white; border:1px solid rgba(0,0,0,0.2); border-radius: 50%; text-align: center; line-height: 15px; font-size: 12px; cursor: pointer; z-index: 1; } .isExit{ display: none; }
3.JS部分
;(function($, window, document) { function ChooseItem(){ this.Arr=[];//左边标签页的左边栏每个下拉菜单隐藏的右边框需要显示的数据 this.showModal=$("#showModal"); this.apDropDow=$("#apartment .dropdow"); this.seDropDow=$("#self .dropdow"); this.sure=$("#sure"); }; ChooseItem.prototype.usefor=function(){ this.showModal.click(function(){//点击输入框清除所有checkbox选择状态 $("input[type='checkbox']").attr("checked",false); }); //左边标签页的下拉菜单功能 this.apDropDow.click(function(){ if($(this).parent().children("ul").is(':hidden')==true){ $(this).parent().children("ul").css({"display":"block"}); }else{ $(this).parent().children("ul").css({"display":"none"}); } }) //右边标签页的下拉菜单功能 this.seDropDow.click(function(){ if($(this).parent().children("ul").is(':hidden')==true){ $(this).parent().children("ul").css({"display":"block"}); }else{ $(this).parent().children("ul").css({"display":"none"}); } if($(this).find("span").text()=="[]"||$(this).find("span").text()==""){ }else{ this.Arr=JSON.parse($(this).find("span").text()); $("#self .detail").children().remove();//在右边栏生成列表之前,必须清除掉原来右边栏的checkbox //获取已选择的checkbox的长度 var ChooseBoxLen=$(".isExit").length||0; for(var i=0;i<this.Arr.length;i++){//在循环生成checkbox的同时,也要判断一下checkbox的选择状态 var h=$("<p class='line'>"+this.Arr[i]["level"]+"<input type='checkbox' class='A' id='"+this.Arr[i]["id"]+"'/><label class='checkbox_label' for='"+this.Arr[i]["id"]+"' onclick='addItem($(this),$(this).parent().text())'></label></p>"); var isChecked=false;//点击左边栏生成右边栏时判断checkbox的状态 for(var j=0;j<ChooseBoxLen;j++){ if($(".choosebox").eq(j).find("span").eq(0).text()==this.Arr[i]["id"]){ isChecked=true; } } h.find("input").attr("checked",isChecked); $("#self .detail").append(h); } } }) //确定按钮,点击确定按钮之后获取已选择的checkbox信息,将信息添加到弹框外面,然后清除弹框里面的操作数据 this.sure.on("click",function(){ for(var n=0;n<$(".choosebox").length;n++){ $(".showItem").append("<li>"+$(".choosebox").eq(n).find("span").eq(1).text()+"</li>"); } $(".choose").empty(); $(this).attr({"data-dismiss":"modal","aria-hidden":"true"}) }) }; //在choose框添加项目 window.addItem=function(obj,text){ var chooseLen=$(".isExit").length;//判断选中框元素的个数 var isExit=false;//判断选中的checkbox是否已经在选中框中 for(var i=0;i<chooseLen;i++){ if($(".isExit").eq(i).text()==obj.parent().find("input").attr("id")){//只要有存在,那么就是true isExit=true; } } if(isExit){ obj.parent().find("input").on("click",function(e){//如果已经存在的话,那么CheckBox就处于选中的状态 e.preventDefault(); }) }else{ var T=$("<p class='choosebox'><span class='isExit'>"+obj.parent().find("input").attr("id")+"</span><span>"+text+"</span><span class='delete' onclick='removeItem($(this))'>x</span></p>");//<span>标签是一个占位符,里面存放的是选中的checkbox的id $(".choose").append(T); } } //移除choose框的项目 window.removeItem=function(obj){ var ALen=$(".A").length;//判断checkbox的总数 var chooseId=obj.parent().find("span").eq(0).text();//要删除的选项的id for(var m=0;m<ALen;m++){ if($(".A").eq(m).attr("id")==chooseId){ obj.parent().remove(); $(".A").eq(m).attr("checked",false); } } } ChooseItem.case = function() { return new ChooseItem(); }; if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) { define(function() { return ChooseItem; }); } else if (typeof module !== 'undefined' && module.exports) { module.exports = ChooseItem.case; module.exports.ChooseItem = ChooseItem; } else { window.ChooseItem = ChooseItem; } })(jQuery,window,document);
三、分析
这个弹框的数据渲染采用的是ArtTemplate来渲染的,具体用法参照如下地址:
https://www.awesomes.cn/repo/aui/arttemplate#%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97
这个小demo在编写过程中遇到了几个小问题:
1.如何让checkbox一直处于被点击状态
解决:最后还是想到用e.preventDefault()来解决
2.如何修改checkbox的样式
解决:思路是这样的,建立<input type="checkbox" id="test"/>和<label for="test"></label>,然后隐藏掉<input/>,我们修改的其实是label的样式,checkbox的样式是没办法直接修改的。
#apartment input[type="checkbox"]{ float: right; display: none; } .checkbox_label{ float: right; } .checkbox_label:before { content: ""; display: inline-block; vertical-align: middle; width: 13px; height: 13px; border:1px solid #269bec; } input[type="checkbox"]:checked+.checkbox_label:before { background-color:#269bec; }
这段代码里面可以看出,点击后的checkbox样式是采用:checked伪类选择器和+选择器来获取到当前被点击的checkbox的。
3.如何修改滚动条的样式
.tab-content{ height: 250px; overflow-y: scroll; } .tab-content::-webkit-scrollbar {/*滚动条整体样式*/ width: 4px; /*高宽分别对应横竖滚动条的尺寸*/ height: 4px; } .tab-content::-webkit-scrollbar-thumb {/*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } .tab-content::-webkit-scrollbar-track {/*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); }
4.代码编写思路
①首先,数据最多只能有四个级别,每个级别/个人必须要有自己特定的id,这样在后面进行移除标签的时候才方便移除。每个可以选中的选项都有相同的css样式类A,这样方便对所有可以选中的checkbox进行遍历;
②在“按人员选择标签页”中,要实现点击左边栏的菜单,在右边栏就出现相应的信息,这就需要在渲染的时候绑定各自的详细数据,我们来通过一张图看一下是怎么实现的
在具有信息的菜单项里面,藏入一个display为none的<span>标签,里面存放相应的数据,然后在点击的时候,通过$(this)和其他选择器获取到这个span的数据,然后放到右边栏中。记住,在每次获取span里面的数据放到右边栏之前,必须遍历这些数据,看看最上面已经被选择的标签当中是否出现这些数据,然后设置其对应的点击状态;
③在选择checkbox之后,最上面的已选择框中会出现这些数据,这时也需要对选中框中每个标签进行绑定
K1是客服阿七对应的id,我们把它藏到这个标签里面,获取的时候同样通过$(this)获取;
④删除标签的时候通过第三点绑定的id,遍历所有具有类A的checkbox,然后设置各自的checkbox状态。