树结构

子节点的勾选状态和父节点状态的动态关联,通过子节点的点击事件进行上下递归;数据回显时,调用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>

效果图:

原文地址:https://www.cnblogs.com/xtreme/p/8027124.html