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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5636375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:11:01  来源:igfitidea点击:

How to create a collapsing tree table in html/css/js?

javascripthtmlcsstreecss-selectors

提问by justkevin

I have some data to display that is both tabular and hierarchical. I'd like to let the user be able to expand and collapse the nodes.

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

Sort of like this, except functional:

有点像这样,除了功能:

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

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

What would be the best way to approach this? I'm not adverse to using an off-the-shelf plugin.

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

回答by bcoughlan

SlickGridhas this functionality, see the tree demo.

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

If you want to build your own, here is an example (jsFiddle demo): Build your table with a data-depthattribute to indicate the depth of the item in the tree (the levelXCSS classes are just for styling indentation): 

如果您想构建自己的,这里有一个示例(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>

Then when a toggle link is clicked, use Javascript to hide all <tr>elements until a <tr>of equal or less depth is found (excluding those already collapsed):

然后,当点击切换链接时,使用 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;
    });
});

回答by John Slegers

In modern browsers, you need only very little to code to create a collapsible tree :

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

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>

(see also this Fiddle)

(另见这个小提琴

回答by joe_coolish

jquery is your friend here.

jquery 是你的朋友。

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

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

If you want to make your own, here is some high level guidance:

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

Display all of your data as <ul />elements with the inner data as nested <ul />, and then use the jquery:

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

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

I believe that is correct. Something like that.

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

EDIT:

编辑:

Here is a complete example.

这是一个完整的例子。

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
</head>
                                                                                                                                                                                <body>
<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>
<script type="text/javascript">
    $(".Collapsable").click(function () {

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

    });

</script>

回答by peteorpeter

I'll throw jsTreeinto the ring, too. I've found it fairly adaptable to your particular situation. It's packed as a jQuery plugin.

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

It can run from a variety of data sources, but my favorite is a simple nested list, as described by @joe_coolish or here:

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

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

This structure fails gracefully into a static tree when JS is not available in the client, and is easy enough to read and understand from a coding perspective.

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

回答by rational

HTML 5 allows summary tag, details element. That can be used to view or hide (collapse/expand) a section. Link

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

回答by Tutompita

You can try jQuery treegrid(http://maxazan.github.io/jquery-treegrid/) or jQuery treetable(http://ludo.cubicphuse.nl/jquery-treetable/)

您可以尝试jQuery treegrid( http://maxazan.github.io/jquery-treegrid/) 或jQuery treetable( http://ludo.cubicphuse.nl/jquery-treetable/)

Both are using HTML <table>tag format and styled the as tree.

两者都使用 HTML<table>标记格式并将样式设置为树。

The jQuery treetableis using data-tt-idand data-tt-parent-idfor determining the parent and child of the tree. Usage example:

jQuery的treetable中使用data-tt-iddata-tt-parent-id确定树的父母和孩子。用法示例:

<table id="tree">
  <tr data-tt-id="1">
    <td>Parent</td>
  </tr>
  <tr data-tt-id="2" data-tt-parent-id="1">
    <td>Child</td>
  </tr>
</table>
$("#tree").treetable({ expandable: true });

Meanwhile, jQuery treegridis using only class for styling the tree. Usage example:

同时,jQuery treegrid只使用类来设置树的样式。用法示例:

<table class="tree">
    <tr class="treegrid-1">
        <td>Root node</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-2 treegrid-parent-1">
        <td>Node 1-1</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-3 treegrid-parent-1">
        <td>Node 1-2</td><td>Additional info</td>
    </tr>
    <tr class="treegrid-4 treegrid-parent-3">
        <td>Node 1-2-1</td><td>Additional info</td>
    </tr>
</table>
<script type="text/javascript">
  $('.tree').treegrid();
</script>