多选框 三级目录 菜单权限 的关联选择功能

实现目标:三级目录菜单分别称为:顶级目录、次级目录、底级目录,实现对各层级目录进行选择操作时,同步影响其他目录的选择状态

具体要求:
1、当顶级目录取消选中时,次级目录和底级目录全部取消选中;
2、当有一个次级目录选中时,其顶级目录也为选中状态;
   当有一个次级目录取消选中时,其底级目录全部取消选中;
   当所有的次级目录都取消选中时,其顶级目录也取消选中;
3、当底级目录选中时,其次级目录和顶级目录也全部选中;

界面效果

html代码部分

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
</head>
<style type="text/css">
 .list{ width:300px; border:1px solid #ccc; margin:10px; padding:10px;}
 .sec{ padding-left:20px; margin:10px;}
 .last{ padding-left:20px; margin:10px;}
 .submit{ text-align:center; margin:30px;}
 </style>
<body>
<form name="main" action="check-all-up-post.php" method=post >
  <div class="list">
    <div class="title">-- 顶级目录 <br>
      &nbsp;&nbsp;&nbsp;&nbsp; -- 次级目录 <br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  -- 底级目录</div>
    <br>
    <div class="top">
      <input type="checkbox" name="T1" value="1" onClick="checkTop('1')" >
      <b>系统使用</b>
      <div class="sec">
        <input type="checkbox" id="p3" name="S1[]" value="3" onClick="checkSec('1',this.id)" >
        系统使用规范
        <div class="last">
          <input type="checkbox" id="p4" name="L1[]" value="4" onClick="checkLast('1',this.id)" >
          添加
          <input type="checkbox" id="p5" name="L1[]" value="5" onClick="checkLast('1',this.id)" >
          删除
          <input type="checkbox" id="p6" name="L1[]" value="6" onClick="checkLast('1',this.id)" >
          编辑 </div>
      </div>
      <div class="sec">
        <input type="checkbox" id="p7" name="S1[]" value="7" onClick="checkSec('1',this.id)" >
        系统使用详情
        <div class="last">
          <input type="checkbox" id="p8" name="L1[]" value="8" onClick="checkLast('1',this.id)" >
          添加
          <input type="checkbox" id="p9" name="L1[]" value="9" onClick="checkLast('1',this.id)" >
          删除
          <input type="checkbox" id="p10" name="L1[]" value="10" onClick="checkLast('1',this.id)" >
          编辑 </div>
      </div>
    </div>
    <div class="top">
      <input type="checkbox" name="T2" value="2" onClick="checkTop('2')" >
      <b>会议资料</b>
      <div class="sec">
        <input type="checkbox" id="p11" name="S2[]" value="11" onClick="checkSec('2',this.id)" >
        会议报告
        <div class="last">
          <input type="checkbox" id="p12" name="L2[]" value="12" onClick="checkLast('2',this.id)" >
          添加
          <input type="checkbox" id="p13" name="L2[]" value="13" onClick="checkLast('2',this.id)" >
          删除
          <input type="checkbox" id="p14" name="L2[]" value="14" onClick="checkLast('2',this.id)" >
          编辑 </div>
      </div>
    </div>
	<div class="submit"><input type="submit" value="确认提交" /></div>
  </div>
</form>
</body>
</html>

 

js代码部分

<script type="text/javascript">

/*	顶级top目录选择事件
分析:
达成目标:
	顶级目录取消选中时,子级目录同步取消选中;顶级目录选中时,子级目录无操作
实现思路:
	1、保证sec和last目录表单的name值中的数值部分与top表单的name值数值保证一致,用以标记为同一组,可分别记做T1、S1、L1
	2、根据传入的id值,获取当前top目录的表单选中状态
	3、遍历所有元素,根据id值找到当前top下的所有sec和last目录表单并修改选择状态
*/
function checkTop(id){

	//获取当前页面所有元素节点数
	var len = document.main.elements.length;

	//根据当前id值,获取当前top目录选择框的选中状态
	var topchecked = document.all("T"+id).checked;
	//alert(topchecked);
	//遍历所有元素,根据id找出所有当前top目录下的sec和last目录
	for( var i=0;i<len;i++){
		if(document.main.elements[i].name == 'S'+id+'[]' || document.main.elements[i].name == 'L'+id+'[]'){
			if(topchecked == false){
				document.main.elements[i].checked = topchecked;
			}
		}
	}
}


/*	次级sec目录选择事件
分析:
达成目标:
	次级目录有一个选中时,顶级目录同步选中,底级目录无操作;
	当所有次级目录取消选中时,顶级目录同步取消选中,同时底级目录也取消选中
实现思路:
	1、对顶级目录操作。遍历所有元素,如果有1个次级目录是选择状态,则顶级目录也为选中状态,如果所有次级目录都未选中,则顶级目录也为未选中状态
	2、对底级目录操作。当前次级目录如果未选中,则设置其底级目录也为未选中;如当前次级目录为选择状态,其底级目录无操作
*/
function checkSec(id,sid){

	/**********  对底级目录的操作  **********/
	//获取当前节点
	var curNode = document.getElementById(sid);
	
	//通过sid获取当前节点的下一个兄弟节点
	var nextNode = curNode.nextElementSibling;

	//获取该兄弟节点的所有子节点
	var subNode = nextNode.childNodes;

	//遍历所有子节点
	for(var i=0;i<subNode.length;i++){
		//筛选出input节点,并且上级节点状态为未选中时,设置所有子节点状态为未选中
		if(subNode[i].name && curNode.checked==false){
			subNode[i].checked = false;
		}
	}
	
	/***********  对顶级目录的操作  **********/
	//获取当前节点
	var len = document.main.elements.length;

	//alert(len);
	for(var i=0;i<len;i++){
		//遍历元素,找出当前目录的次级目录,并进行下一步操作
		if(document.main.elements[i].name == 'S'+id+'[]'){
			//如果有1个次级目录是选择状态,则顶级目录也为选中状态
			if(document.main.elements[i].checked){
				//设置顶级目录为选中状态
				document.all("T"+id).checked = true;				
				return;
			}
		}
	}
	//如果所有次级目录都未选中,则顶级目录也设置未选中
	document.all("T"+id).checked = false;
}

/*	底级last目录选择事件
*/
function checkLast(id,sid){
	
	/**  对次级目录的处理  **/
	//获取当前节点
	var curNode = document.getElementById(sid);

	//通过当前节点找出上级节点的上一个兄弟节点
	var brotherNode = curNode.parentNode.previousElementSibling;
	//console.log(curNode.checked);

	//如果当前底级目录选择状态为已选中,则设置其上级即次级目录也为选中状态
	if(curNode.checked){
		brotherNode.checked = true;
	}


	/**  对顶级目录的处理  **/	
	//获取当前页面所有元素节点数
	var len = document.main.elements.length;

	for(var i=0;i<len;i++){
		//遍历元素,找出当前底级目录
		if(document.main.elements[i].name == 'L'+id+'[]'){
			//如果有1个底级目录是选择状态,则顶级目录也为选中状态
			if(document.main.elements[i].checked){
				//设置顶级目录为选中状态	
				document.all("T"+id).checked = true;				
				return;
			}
		}
	}
}

</script>

Ps:本次实例是楼主在网上搜寻了一些js代码样例,然后在其基础上结合自己的需求逻辑进行修改的。路过的朋友如果还有更好的实现逻辑及方法,欢迎留言讨论,以求共同进步,谢谢!

 

 

 

在此基础上 补充另一个多选框三级联动实现方法

htmld代码:

<div class="container">
<form method="POST" action="/Menus/create">
    <div class="form-group row">
        <label for="controller" class="col-md-4 col-form-label text-md-right">选择权限</label>
        
        <div class="col-md-6">
            <input name="menus" type="checkbox" id="1" value="" onclick="checkTop(0,this.id,0,array<!--这里的数组需要先转成json字符串 json_encode()方法实现-->)">系统管理<br/>
            <input name="menus" type="checkbox" id="2" value="" onclick="checkTop(0,this.id,1,array)">菜单添加<br/>
            <input name="menus" type="checkbox" id="3" value="" onclick="checkTop(0,this.id,1,array)">系统日志<br/>
            <input name="menus" type="checkbox" id="4" value="" onclick="checkTop(0,this.id,0,array)">用户管理<br/>
            <input name="menus" type="checkbox" id="5" value="" onclick="checkTop(0,this.id,4,array)">用户列表<br/>
            <input name="menus" type="checkbox" id="6" value="" onclick="checkTop(0,this.id,5,array)">添加
            <input name="menus" type="checkbox" id="8" value="" onclick="checkTop(0,this.id,5,array)">编辑<br/>
            <input name="menus" type="checkbox" id="7" value="" onclick="checkTop(0,this.id,4,array)">角色列表<br/>
            <input name="menus" type="checkbox" id="9" value="" onclick="checkTop(0,this.id,7,array)">添加
            <input name="menus" type="checkbox" id="10" value="" onclick="checkTop(0,this.id,7,array)">编辑<br/>
        </div>
    </div>

    <div class="form-group row mb-0">
        <div class="col-md-6 offset-md-4">
            <button type="submit" class="btn btn-primary">确认添加</button>
        </div>
    </div>
</form>
</div>

js代码

<script type="text/javascript">

    function checkTop(i,id,pid,str){
        var list1 = [];
        var list2 = [];
        list1 = getSubmenus(i,id,str,list1);
        //console.log(list);
        list2 = getSupmenus(i,pid,str,list2);
        //alert(typeof(list));
        //console.log(list);
        var list = list1.concat(list2);
        console.log(list);
        //根据当前id值,获取当前顶级选择框的选中状态
        var topchecked = document.getElementById(id).checked;
        //alert(topchecked);
        //根据获取的list子菜单数据,设置checkbox的选中状态与当前菜单选择框选择状态一致
        for(var i=0;i<list1.length;i++){
            //alert(list[i]);
            document.getElementById(list1[i]).checked = topchecked;
        }

        //根据获取的list父菜单数据,设置checkbox的选中状态与当前顶级选择框选中状态一致,取消选中则不处理
        for(var i=0;i<list2.length;i++){
            //alert(list[i]);
            if(topchecked){
                document.getElementById(list2[i]).checked = topchecked;
            }

        }
    }

    //遍历检索获取当前菜单下所有子菜单
    function getSubmenus(i,id,str,list1){
        //alert(id);return false;
        //将js对象转化为js数组
        var objs = eval(str);
        //console.log(objs);
        //遍历数组
        for(var j = 0;j<objs.length;j++){
            //遍历到的pid值如果等于当前id值,则说明当前菜单找到了其子类菜单,并写入到list数组中
            if(objs[j].pid == id){
                //获取当前id值,用于递归时使用
                var sid = objs[j].id;
                list1.push(sid);
                //alert(sid);
                //删除当前遍历元素,防止重复遍历
                //objs.splice(j,1);
                getSubmenus(i,sid,objs,list1);
            }
        }
        return list1;
    }
    
    //遍历检索获取当前菜单的所有父菜单
    function getSupmenus(i,pid,str,list2) {
        //alert(id);return false;
        //将js对象转化为js数组
        var objs = eval(str);
        //console.log(objs);
        //遍历数组
        for(var j = 0;j<objs.length;j++){
            //遍历到的pid值如果等于当前id值,则说明当前菜单找到了其子类菜单,并写入到list数组中
            if(objs[j].id == pid){
                //获取当前id值,用于递归时使用
                var sid = objs[j].id;
                list2.push(sid);
                //alert(sid);
                //删除当前遍历元素,防止重复遍历
                //objs.splice(j,1);
                getSupmenus(i,objs[j].pid,objs,list2);
            }
        }
        return list2;
    }

</script>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值