树结构 - 半选状态控制及回显
子节点的勾选状态和父节点状态的动态关联,通过子节点的点击事件进行上下递归;数据回显时,调用review(rootId)修正父节点状态。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>javascript test</title> <link rel="stylesheet" type="text/css" href="css/metro/easyui.css"> <link rel="stylesheet" type="text/css" href="css/icon.css"> <link rel="stylesheet" type="text/css" href="css/demo.css"> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript" src="js/jquery.easyui.min.js"></script> <style media="screen"> span{ display: inline-block; padding: 5px 10px; border: 1px solid silver; } .leaf{ margin-left: 20px; } .tree-checkbox .tree-checkbox0{ /*未选中状态*/ background: #fff; } .tree-checkbox .tree-checkbox1{ /*全选中状态*/ background: yellow; } .tree-checkbox .tree-checkbox2{ /*半选中状态*/ background: green; } </style> </head> <body class="tree-checkbox"> <span class="tree-checkbox0" nodeId="1" onclick="accessTree(this)">root</span> <span class="tree-checkbox0" nodeId="2" pId="1" onclick="accessTree(this)">2</span> <span class="leaf tree-checkbox1" nodeId="5" pId="2" onclick="accessTree(this)">5</span> <span class="leaf tree-checkbox1" nodeId="6" pId="2" onclick="accessTree(this)">6</span> <span class="tree-checkbox1" nodeId="3" pId="1" onclick="accessTree(this)">3</span> <span class="leaf tree-checkbox0" nodeId="7" pId="3" onclick="accessTree(this)">7</span> <span class="tree-checkbox1" nodeId="4" pId="1" onclick="accessTree(this)">4</span> </body> <script type="text/javascript"> /** * 根据当前节点计算父级和子子集勾选状态 **/ function accessTree(node){ var checkedClass = 'tree-checkbox1', middleClass = 'tree-checkbox2', unCheckClass = 'tree-checkbox0'; var id = $(node).attr('nodeId'),pId = $(node).attr('pId'); var status = Array.from(node.classList).includes(checkedClass); if(status) accessClass(node,unCheckClass); else accessClass(node,checkedClass); upAccess(pId); downAccess(id,!status); // 向上递归 function upAccess(pId){ if(!pId) return; var isAll = true, has = false, pckbox = $('[nodeId='+pId+']').get(0); if(pckbox) { $('[pId='+pId+']').each(function(n,item){ var clist = Array.from(item.classList), status = clist.includes(checkedClass); if(!status) isAll = false; else has = true; if(clist.includes(middleClass)) has = true; }); if(isAll) accessClass(pckbox,checkedClass); else if(has) accessClass(pckbox,middleClass); else accessClass(pckbox,unCheckClass); upAccess($(pckbox).attr('pId')); } } // 向下递归 function downAccess(id,status){ $('[pId='+id+']').each(function(n,item){ if(status) accessClass(item,checkedClass); else accessClass(item,unCheckClass); downAccess($(item).attr('nodeId'),status); }); } function accessClass(node,cls){ var classes = [checkedClass,middleClass,unCheckClass]; classes.map(function(item){ if(item == cls) node.classList.add(item); else node.classList.remove(item); }); } } /** * 根据root节点回溯所有节点并修正状态 **/ function review(rootId){ var root = $('[nodeId='+rootId+']')[0]; if(!root) return; var checkedClass = 'tree-checkbox1', middleClass = 'tree-checkbox2', unCheckClass = 'tree-checkbox0'; var id = $(root).attr('nodeId'); var isAll = true, has = false, children = $('[pId='+id+']'); children.each(function(n,item){ review($(item).attr('nodeId')); var clist = Array.from(item.classList), status = clist.includes(checkedClass); if(!status) isAll = false; else has = true; if(clist.includes(middleClass)) has = true; }); if(children.length > 0) { if(isAll) accessClass(root,checkedClass); else if(has) accessClass(root,middleClass); else accessClass(root,unCheckClass); } function accessClass(node,cls){ var classes = [checkedClass,middleClass,unCheckClass]; classes.map(function(item){ if(item == cls) node.classList.add(item); else node.classList.remove(item); }); } }
// 回显状态修正
review(1); </script> </html>
效果图: