如何在 html/css/js 中创建折叠树表?
Posted
技术标签:
【中文标题】如何在 html/css/js 中创建折叠树表?【英文标题】:How to create a collapsing tree table in html/css/js? 【发布时间】:2011-08-03 22:18:40 【问题描述】:我有一些表格和分层的数据要显示。我想让用户能够展开和折叠节点。
有点像这样,除了功能性:
http://www.maxdesign.com.au/articles/tree-table/
解决此问题的最佳方法是什么?我不反对使用现成的插件。
【问题讨论】:
【参考方案1】:SlickGrid 有这个功能,见tree demo。
如果您想自己构建,这里有一个示例 (jsFiddle demo):使用 data-depth
属性构建您的表格以指示树中项目的深度(levelX
CSS 类仅用于样式缩进):
<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;
);
);
【讨论】:
非常好:-) 只是一个小的修正:注释应该是: // 获取所有深度更大的在现代浏览器中,您只需编写很少的代码即可创建可折叠树:
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>
(另见this Fiddle)
【讨论】:
感谢您的精彩回答。我正在尝试实施您的解决方案,但它似乎在我的设置中不起作用。我已经发布了一个关于这个的问题。请让我知道我做错了什么? ***.com/questions/43016555/… @AnandTyagi :您可以将您的代码发布在JSFiddle 或其他在线地方吗?我需要能够调试您的代码以找出问题所在! 感谢您的回复。 stackoverlow 的好心人已经解决了这个问题。 我知道这是旧的,但我发现这是最简单和最好的答案。在我的项目中完美运行 我认为您可能需要e.preventDefault()
才能使用它【参考方案3】:
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>
【讨论】:
这工作得很好,但对我来说,它从扩展所有路径开始 - 需要修改什么以便它从所有折叠到第一级开始? *编辑:我删除了我的消息进行编辑 - 感谢@joe_coolish 的快速回复。 .each() 是我需要的 没有问题 :) jQuery 太棒了!你可以这么快做这么多! p.s.,我更新了 jsfiddle 使其更可重用。这是新链接:jsfiddle.net/5Q8rJ/1 这正是我想要的,我只是想知道如何将背景设置为交替和全宽,即项目 1 中的项目 2 中的项目 4,具有与项目 1 相同的宽度背景?使其看起来像一个“树表”。 @user986697 - 我不确定你的意思?你说的是 CSS 吗? @user986697 - 如果这就是您所指的,请告诉我:jsfiddle.net/5Q8rJ/67【参考方案4】:我也会把jsTree 扔进擂台。我发现它相当适合您的特定情况。它被打包为一个 jQuery 插件。
它可以从多种数据源运行,但我最喜欢的是一个简单的嵌套列表,如 @joe_coolish 或此处所述:
<ul>
<li>
Item 1
<ul>
<li>Item 1.1</li>
...
</ul>
</li>
...
</ul>
当 JS 在客户端不可用时,这种结构优雅地失败为静态树,并且从编码的角度来看很容易阅读和理解。
【讨论】:
【参考方案5】:html 5 允许摘要标签、详细信息元素。这可用于查看或隐藏(折叠/展开)部分。 Link
【讨论】:
男人让我的希望在那里一秒钟。【参考方案6】:你可以试试 jQuery treegrid (http://maxazan.github.io/jquery-treegrid/) 或 jQuery treetable (http://ludo.cubicphuse.nl/jquery-treetable/)
两者都使用 HTML <table>
标记格式并将样式设置为树。
jQuery 树表 使用data-tt-id
和data-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 );
同时,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>
【讨论】:
这对大数据有性能问题。仅 1500 个节点大约需要 1 分钟。以上是关于如何在 html/css/js 中创建折叠树表?的主要内容,如果未能解决你的问题,请参考以下文章