一、预览
二、代码
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}}" οnclick="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']}}" οnclick="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']}}" οnclick="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']}}" οnclick="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"]+"' οnclick='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' οnclick='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状态。
四、github地址
https://github.com/Nangxif/ChooseItem