如何在 html/css/js 中创建一个折叠树表?

IT技术 javascript html css tree css-selectors
2021-03-06 13:36:54

我要显示一些表格和分层数据。我想让用户能够展开和折叠节点。

有点像这样,除了功能:

http://www.maxdesign.com.au/articles/tree-table/

解决这个问题的最佳方法是什么?我不反对使用现成的插件。

6个回答

SlickGrid具有此功能,请参阅树演示

如果你想构建自己的,这里有一个例子(jsFiddle 演示):用一个data-depth属性构建你的表来指示树中项目的深度(levelXCSS 类仅用于样式缩进): 

<table id="mytable">
    <tr data-depth="0" class="collapse level0">
        <td><span class="toggle collapse"></span>Item 1</td>
        <td>123</td>
    </tr>
    <tr data-depth="1" class="collapse level1">
        <td><span class="toggle"></span>Item 2</td>
        <td>123</td>
    </tr>
</table>

然后,当点击切换链接时,使用 Javascript 隐藏所有<tr>元素,直到<tr>找到相同或更少深度的元素(不包括已经折叠的元素):

$(function() {
    $('#mytable').on('click', '.toggle', function () {
        //Gets all <tr>'s  of greater depth below element in the table
        var findChildren = function (tr) {
            var depth = tr.data('depth');
            return tr.nextUntil($('tr').filter(function () {
                return $(this).data('depth') <= depth;
            }));
        };

        var el = $(this);
        var tr = el.closest('tr'); //Get <tr> parent of toggle button
        var children = findChildren(tr);

        //Remove already collapsed nodes from children so that we don't
        //make them visible. 
        //(Confused? Remove this code and close Item 2, close Item 1 
        //then open Item 1 again, then you will understand)
        var subnodes = children.filter('.expand');
        subnodes.each(function () {
            var subnode = $(this);
            var subnodeChildren = findChildren(subnode);
            children = children.not(subnodeChildren);
        });

        //Change icon and hide/show children
        if (tr.hasClass('collapse')) {
            tr.removeClass('collapse').addClass('expand');
            children.hide();
        } else {
            tr.removeClass('expand').addClass('collapse');
            children.show();
        }
        return children;
    });
});
非常好:-) 只是一个小的更正:注释应该是: // 获取所有 <tr> 的更大深度.. NOT // 获取所有 <tr> 的更大或相等深度.. 它只是 tr 的具有我们想要隐藏的更大深度。我们要显示的相同深度:) 逻辑仍然是正确的。
2021-04-22 13:36:54
此评论可能会被标记,但我不在乎,我要感谢您对可折叠树形网格的简单实现。你值得一千个赞!
2021-04-30 13:36:54
看起来挺好的!你能说出当一切都崩溃时它是如何开始的吗?
2021-05-12 13:36:54

在现代浏览器中,您只需要编写很少的代码即可创建可折叠树:

var tree = document.querySelectorAll('ul.tree a:not(:last-child)');
for(var i = 0; i < tree.length; i++){
    tree[i].addEventListener('click', function(e) {
        var parent = e.target.parentElement;
        var classList = parent.classList;
        if(classList.contains("open")) {
            classList.remove('open');
            var opensubs = parent.querySelectorAll(':scope .open');
            for(var i = 0; i < opensubs.length; i++){
                opensubs[i].classList.remove('open');
            }
        } else {
            classList.add('open');
        }
        e.preventDefault();
    });
}
body {
    font-family: Arial;
}

ul.tree li {
    list-style-type: none;
    position: relative;
}

ul.tree li ul {
    display: none;
}

ul.tree li.open > ul {
    display: block;
}

ul.tree li a {
    color: black;
    text-decoration: none;
}

ul.tree li a:before {
    height: 1em;
    padding:0 .1em;
    font-size: .8em;
    display: block;
    position: absolute;
    left: -1.3em;
    top: .2em;
}

ul.tree li > a:not(:last-child):before {
    content: '+';
}

ul.tree li.open > a:not(:last-child):before {
    content: '-';
}
<ul class="tree">
  <li><a href="#">Part 1</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>

  <li><a href="#">Part 2</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>

  <li><a href="#">Part 3</a>
    <ul>
      <li><a href="#">Item A</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item B</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item C</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item D</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
      <li><a href="#">Item E</a>
        <ul>
          <li><a href="#">Sub-item 1</a></li>
          <li><a href="#">Sub-item 2</a></li>
          <li><a href="#">Sub-item 3</a></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

(另见这个小提琴

@AnandTyagi :你能在JSFiddle或网上的其他地方发布你的代码吗?我需要能够调试您的代码以找出它的问题所在!
2021-04-28 13:36:54
我想你可能需要e.preventDefault()让它工作
2021-05-08 13:36:54
谢谢你的精彩回答。我正在尝试实施您的解决方案,但它似乎在我的设置中不起作用。我已经发布了一个关于此的问题。请让我知道我做错了什么?stackoverflow.com/questions/43016555/...
2021-05-09 13:36:54
我知道这是旧的,但我发现这是最简单和最好的答案。在我的项目中完美运行
2021-05-13 13:36:54
感谢您的回复。这个问题已经被stackoverlow的好心人解决了。
2021-05-18 13:36:54

jquery 是你的朋友。

http://docs.jquery.com/UI/Tree

如果您想自己制作,这里有一些高级指南:

将所有数据显示为<ul />元素,内部数据为嵌套<ul />,然后使用 jquery:

$('.ulClass').click(function(){ $(this).children().toggle(); });

我相信这是正确的。类似的东西。

编辑:

这是一个完整的例子。

 $(".Collapsable").click(function () {

    $(this).parent().children().toggle();
    $(this).toggle();

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
    <li><span class="Collapsable">item 1</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span><ul>
            <li><span class="Collapsable">item 1</span></li>
            <li><span class="Collapsable">item 2</span></li>
            <li><span class="Collapsable">item 3</span></li>
            <li><span class="Collapsable">item 4</span></li>
        </ul>
        </li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span><ul>
            <li><span class="Collapsable">item 1</span></li>
            <li><span class="Collapsable">item 2</span></li>
            <li><span class="Collapsable">item 3</span></li>
            <li><span class="Collapsable">item 4</span></li>
        </ul>
        </li>
    </ul>
    </li>
    <li><span class="Collapsable">item 2</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span></li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span></li>
    </ul>
    </li>
    <li><span class="Collapsable">item 3</span><ul>
        <li><span class="Collapsable">item 1</span></li>
        <li><span class="Collapsable">item 2</span></li>
        <li><span class="Collapsable">item 3</span></li>
        <li><span class="Collapsable">item 4</span></li>
    </ul>
    </li>
    <li><span class="Collapsable">item 4</span></li>
</ul>

这正是我想要的,我只是想知道如何将背景设置为交替和全宽,即项目 1 中项目 2 中的项目 4 与项目 1 的背景宽度相同?从而使它看起来像一个“树表”。
2021-05-01 13:36:54
@ user986697 - 我不确定你的意思?你在谈论 CSS 吗?
2021-05-01 13:36:54
@user986697 - 如果这就是您所指的,请告诉我:jsfiddle.net/5Q8rJ/67
2021-05-06 13:36:54
这工作得很好,但对我来说,它开始时扩展了所有路径 - 需要修改什么以便它从折叠到第一级的所有内容开始?*编辑:我删除了我的消息进行编辑 - 感谢@joe_coolish 的快速回复。.each() 是我需要的
2021-05-15 13:36:54
没问题 :) jQuery 很棒!你可以这么快做这么多!ps,我更新了 jsfiddle 以提高可重用性。这是新链接:jsfiddle.net/5Q8rJ/1
2021-05-17 13:36:54

我也会把jsTree扔进戒指。我发现它非常适合您的特定情况。它被打包为一个 jQuery 插件。

它可以从各种数据源运行,但我最喜欢的是一个简单的嵌套列表,如@joe_coolish 或此处所述:

<ul>
  <li>
    Item 1
    <ul>
      <li>Item 1.1</li>
      ...
    </ul>
  </li>
  ...
</ul>

当 JS 在客户端不可用时,这种结构会优雅地失败为静态树,并且从编码的角度来看很容易阅读和理解。

HTML 5 允许摘要标签、详细信息元素。可用于查看或隐藏(折叠/展开)部分。关联

男人让我的希望寄托在那里。
2021-04-30 13:36:54