javascript - 如何使用 treeview 复选框制作表格

标签 javascript html

我有 treeview - https://jsfiddle.net/allengosta/9pg13kth/11/ 我想让 treetable(第一列 - treeview,第二列 - 颜色)像:

example

如何做到这一点?

//json example

var treeObject = [
{
    text:"Parent 1",
    checked:true,
    id:15,
color: 'blue',
    children:[ // Required
        { text:"Child 1", checked:true, color: 'white'},
        { text:"Child 2", color: 'green'    }
    ]
},
{
    text:"Parent 2",
color: 'yellow',
    children:[
        {
            text:"Parent 3",
    color: 'purple',
            children:[
                {text:"Child 3",checked:true, color: 'green'},
                {text:"Child 4", color: 'orange'}
            ]
        }
    ]
}

]

最佳答案

已编辑
这个新解决方案按照您的要求使用 HTML Table 元素。当我在 Chrome 中测试它时,UI 看起来不错,但这不是一个理想的解决方案,因为它将表行直接嵌套在其他表行中。(如果没有这种困惑,正确设置 CSS 将更具挑战性。)SPACER_WIDTH破解 createSingleItem函数是我在这种情况下处理水平对齐的方式。

(如果您真的不需要表格本身,您可以考虑将 TR 改回 UL 并使用一些具有适当宽度的内联 block LI 等以保持一切都对齐。)

大部分重大变化都在最后两个函数中。我希望它对你有用。

// Constructs a TableTreeView from `testArray` and adds it to `container` 
  var testArray = [
    {
      text: "Parent 1",
      checked: true,
      id: 15,
      color: 'blue',
      children: [{ text: "Child 1", checked: true, color: 'white' }, { text: "Child 2", color: 'green' }]
    },
    {
      text: "Parent 2",
      color: 'yellow',
      children: [{
        text: "Parent 3",
        color: 'purple',
        children: [{ text: "Child 3", checked: true, color: 'green' }, { text: "Child 4", color: 'orange' }]
      }]
    }  
  ]
  var tw = new TableTreeView( testArray, { showAlwaysCheckBox: true, fold: false });
  document.getElementById("container").appendChild(tw.root);


  // ---------- TableTreeView constructor ----------
  function TableTreeView(datas, options) {

    // --- Makes `root` table (with class `.tabletreeview`) ---
    this.root = document.createElement("table");
    this.root.className = "tabletreeview";
    let t = this;

    // ---- Defines instance methods ----
    this.update = function() {
      $(t.root).find(".group").each(function(index, el) {
        if ($(el).find(".group").length > 0) { $(el).find(">[fold-button]").css("visibility", "visible"); }
        else { $(el).find(">[fold-button]").css("visibility", "hidden"); }
        checkControlParents.bind($(el).find(">.item"))();
      })
    }
    this.load = function(datas){
      $(this.root).empty();
      createTreeViewReq(this.root, datas, options, 0);
      this.update();
    }
    this.save = function(type, node){
      if(type == null){ type = "tree"; }
      if(type == "tree"){
        if(node == null){
          var data = [], $children = $(this.root).find(">.group");
          for (var i = 0; i < $children.length; i++) { var child = this.save("tree", $children[i]); data.push(child); }
          return data;
        }
        else {
          var data = saveSingle($(node).find(">.item")[0]);
          data.children = [];
          var $children = $(node).find(">.group");
          for (var i = 0; i < $children.length; i++){ var child = this.save("tree", $children[i]); data.children.push(child); }
          return data;
        }
      }
      if (type == "list") {
        var data = [], $items = $(this.root).find(".item");
        for (var i = 0; i < $items.length; i++) { data.push(saveSingle($items[i])); }
        return data;
      }
    }
    this.openAllFold = function(item) {
      item = item ||this.root;
      $(item).find("[fold-button]").each(function(index, el) {  groupOpen.bind(this)(); });
    }
    this.closeAllFold = function(item) {
      item = item || this.root;
      $(item).find("[fold-button]").each(function(index, el) { groupClose.bind(this)(); })
    }
    function saveSingle(el) {
      el = el || this;
      return Object.assign({ children: [] },  el.data, { checked: el.checked });
    }

    // ---- Sets options and calls `this.load` ----
    var defaultOptions = { showAlwaysCheckBox: true, fold: true, openAllFold: true }
    options = Object.assign(defaultOptions, options);
    if(options.openAllFold){ this.openAllFold(); } else { this.closeAllFold(); }
    this.load(datas);


    // ---- GROUP EVENTS ----
    function groupOpen(){ $(this).parent().find(">.group").slideDown("fast"); }
    function groupClose() { $(this).parent().find(">.group").slideUp("fast"); }
    function groupToggle(){ $(this).parent().find(">.group").slideToggle("fast"); }

    // ---- ITEM EVENTS ----
    function changeCheckState(value, allChildCheck) {
      var c = this.checked;
      if (value != null && !(value instanceof MouseEvent)){c = value; }
      else{ if(c == 0){ c = 1; } else if(c == 1 || c == 2){ c-- } }       
      this.checked = c;
      setCheckState.bind(this)(c);
      if (c != 2){ checkAllChilds.bind(this)(c); checkControlParents.bind(this)(); }
    }
    function checkAllChilds(value) {
      var $group = $(this).parent(".group");
      $group.find(".item").each(function(index, el) { setCheckState.bind(el)(value); })
    }
    function checkControlParents() {
      var $parents = $(this).parents(".tabletreeview .group");
      for (var index = 1; index < $parents.length; index++) {
        var el = $parents[index]; item = $(el).find(">.item").get(0); $children = $(el).find(".group .item"); var all1 = true; var all0 = true;
        for (var i = 0; i < $children.length; i++) { if ($children[i].checked != 1) all1 = false; if ($children[i].checked != 0) all0 = false; }
        if(all1){ setCheckState.bind(item)(1); } else if(all0){ setCheckState.bind(item)(0); } else setCheckState.bind(item)(2);
      }
    }
    function setCheckState(value) {
      this.checked = value; this.setAttribute("check-value", value)
      if(value == 0){ $(this).find(">[check-icon]")[0].className = "fa fa-circle-thin"; }
      if(value == 1){ $(this).find(">[check-icon]")[0].className = "fa fa-check-circle-o"; }
      if(value == 2){ $(this).find(">[check-icon]")[0].className = "fa fa-dot-circle-o"; }
    }
    
    function createTreeViewReq(parentNode, datas, options, depth){
      // Takes `parentNode` (a row or table), `datas` (array of objects),
      //   `options` (object), and `depth` (integer)
      // Appends rows to parentNode -- kludgy b/c `tr` elements are nested
      for(var i = 0; i < datas.length; i++){
        if(datas[i] != null){
          var
            data = datas[i],
            item = createSingleItem(data, depth);
          parentNode.appendChild(item);
          if("children" in data && data.children.length > 0){
            createTreeViewReq(item, data.children, options, depth + 1);
          }
        }
      }
    }

    function createSingleItem(data, depth) {
      // Takes a `data` object (w/ .text, .checked, .color & .children)
      // Returns a `tr` (w/ spacer, foldButton, item, and color)

      // Defines width values
      const TOP_ITEM_WIDTH = 300, SPACER_WIDTH = 20;

      // Makes a row (aka `group`) 
      var group = document.createElement("tr");
      group.className = "group"
      if("className" in options){ group.className += options.className; }

      // Adds a `spacer` cell to the row
      var spacer = document.createElement("td");
      spacer.style.width = `${SPACER_WIDTH}px`;
      group.appendChild(spacer);

      // Conditionally adds a `foldButton` 
      if("fold" in options){
        var foldButton = document.createElement("i");
        foldButton.className = "fa fa-caret-right";
        foldButton.setAttribute("fold-button", 1);
        foldButton.onclick = groupToggle.bind(foldButton);
        foldButton.isOpened = options.fold;
        group.appendChild(foldButton);
      }

      // Makes `item` (`showing data.text`, w/ all data attributes from `data`)
      var item = document.createElement("td");
      // Hack to align color cells
      item.style.width = `${ TOP_ITEM_WIDTH - (depth * (SPACER_WIDTH + 4)) }px`;
      item.className = "item";
      item.innerHTML = data.text;
      item.data = data;
      for(var keys = Object.keys(data), i = 0; i < keys.length; i++){
        item.setAttribute("data-" + keys[i], data[keys[i]]);
      }
      // Handles check-related events
      if ("checked" in data || options.showAlwaysCheckBox == true) {
        var checked = document.createElement("i");
        checked.setAttribute("check-icon", "1");
        checked.className = "fa ";
        item.prepend(checked);
        if ("checked" in data && data.checked) { setCheckState.bind(item)(data.checked ? 1 : 0); }
        else { setCheckState.bind(item)(0); }
      }
      item.onclick = changeCheckState.bind(item);

      // Adds item cell to the row
      group.appendChild(item);

      // Adds color cell to the row
      var colorLi = document.createElement("td");
      colorLi.classList.add("color");
      colorLi.appendChild(document.createTextNode(data.color));
      group.appendChild(colorLi);

      return group;
    }
  }
/* Note: some of your original styles may not be appropriate for HTML tables */

body {
  background-color: #fafafa;
  font-family: 'Roboto';
}

.tabletreeview,
.tabletreeview * {
  user-select: none;
  margin: 0px;
  padding: 0px;
}

.tabletreeview .item {
  cursor: pointer;
  display: inline-block;
  padding: 4px;
}

.tabletreeview .color {
  display: inline-block;
  padding: 4px;
}

.tabletreeview .item:hover {
  background: #DDD;
}

.tabletreeview .group [fold-button] {
  display: inline-block;
  padding: 10px;
  width: 30px;
  text-align: center;
  border-radius: 3px;
  cursor: pointer;
}

.tabletreeview .group [fold-button]:hover {
  background: #AAA;
}

.tabletreeview .item i {
  margin-right: 10px;
}

.tabletreeview .item[check-value="2"] {
  color: #595;
}

.tabletreeview .item[check-value="1"] {
  color: #5A5;
}

.tabletreeview .item[check-value="0"] {
  color: #333;
}
<head>
  <link href="https://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <!-- <script type="text/javascript" src="treeview.js"></script> -->
  <!-- <link href="css/jquery.tabletreeview.css" rel="stylesheet"> -->
</head>

<body>
  <div id="container"></div>
</body>

关于javascript - 如何使用 treeview 复选框制作表格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57968392/

相关文章:

javascript - 显示模式对话框 jquery

javascript - 平滑滚动都是小故障! (这是方形空间上的代码块)

html - AngularJS - 将 HTML 呈现为工具提示

javascript - 输入类型 ="file"设置base64图像数据

jquery - 能用jquery给代码动态添加注释吗?

JavaScript 只工作一次

c# - 如何将返回的 ajax 数据作为 C# 对象列表传递给 Controller ​​?

javascript - 如何将类似数组的字符串转换为 Node.js 中的数组?

javascript - 一键禁用窗口 beforeunload 属性

javascript - 改变jquery下一个元素的值