使用 JQuery 展开/折叠表行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16926752/
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
expand/collapse table rows with JQuery
提问by Saqib
I want to expand and collapse table rows when header columns is clicked. I only want to expand/collapse rows which are under the specific header (clicked).
我想在单击标题列时展开和折叠表格行。我只想展开/折叠特定标题下的行(单击)。
Here is my table structure:
这是我的表结构:
<table border="0">
<tr>
<td colspan="2">Header</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td colspan="2">Header</td>
</tr>
<tr>
<td>date</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
</table>
Any thoughts on how can I accomplish this task. Using div this task seems quite simple, but I have tabular data which I want to manipulate.
关于我如何完成这项任务的任何想法。使用 div 这个任务看起来很简单,但我有我想要操作的表格数据。
One idea I can think of is to use css class in every row which distinguish rows in under each header and use JQuery to expand/collapse those rows only when header is clicked. But if my table has 10-15 headers then it seems difficult to keep track of css classes.
我能想到的一个想法是在每一行中使用 css 类来区分每个标题下的行,并仅在单击标题时使用 JQuery 来展开/折叠这些行。但是如果我的表有 10-15 个标题,那么跟踪 css 类似乎很困难。
Please suggest a suitable way to achieve this.
请提出一种合适的方法来实现这一目标。
回答by PSL
You can try this way:-
你可以试试这种方式:-
Give a class say header
to the header rows, use nextUntil to get all rows beneath the clicked header until the next header.
给一个类说header
标题行,使用 nextUntil 获取单击的标题下方的所有行,直到下一个标题。
JS
JS
$('.header').click(function(){
$(this).nextUntil('tr.header').slideToggle(1000);
});
Html
html
<table border="0">
<tr class="header">
<td colspan="2">Header</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
Demo
演示
Another Example:
另一个例子:
$('.header').click(function(){
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100); // or just use "toggle()"
});
Demo
演示
You can also use promise to toggle the span icon/text after the toggle is complete in-case of animated toggle.
在动画切换的情况下,您还可以在切换完成后使用 promise 切换跨度图标/文本。
$('.header').click(function () {
var $this = $(this);
$(this).nextUntil('tr.header').slideToggle(100).promise().done(function () {
$this.find('span').text(function (_, value) {
return value == '-' ? '+' : '-'
});
});
});
Or just with a css pseudo element to represent the sign of expansion/collapse, and just toggle a class on the header.
或者只是用一个 css 伪元素来表示扩展/折叠的标志,只需在标题上切换一个类。
CSS:-
CSS:-
.header .sign:after{
content:"+";
display:inline-block;
}
.header.expand .sign:after{
content:"-";
}
JS:-
JS:-
$(this).toggleClass('expand').nextUntil('tr.header').slideToggle(100);
Demo
演示
回答by David says reinstate Monica
The easiest way to achieve this, without changing the HTML table
-based structure, is to use a class-name on the tr
elements containing a header, such as .header
, to give:
在不更改table
基于HTML的结构的情况下,最简单的方法是在tr
包含标题的元素上使用类名,例如.header
,给出:
<table border="0">
<tr class="header">
<td colspan="2">Header</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr class="header">
<td colspan="2">Header</td>
</tr>
<tr>
<td>date</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
</table>
And the jQuery:
和 jQuery:
// bind a click-handler to the 'tr' elements with the 'header' class-name:
$('tr.header').click(function(){
/* get all the subsequent 'tr' elements until the next 'tr.header',
set the 'display' property to 'none' (if they're visible), to 'table-row'
if they're not: */
$(this).nextUntil('tr.header').css('display', function(i,v){
return this.style.display === 'table-row' ? 'none' : 'table-row';
});
});
In the linked demo I've used CSS to hide the tr
elements that don'thave the header
class-name; in practice though (despite the relative rarity of users with JavaScript disabled) I'd suggest using JavaScript to add the relevant class-names, hiding and showing as appropriate:
在链接的演示我使用CSS来隐藏tr
的元素不具备的header
类名; 但在实践中(尽管禁用 JavaScript 的用户相对较少)我建议使用 JavaScript 添加相关的类名,并根据需要隐藏和显示:
// hide all 'tr' elements, then filter them to find...
$('tr').hide().filter(function () {
// only those 'tr' elements that have 'td' elements with a 'colspan' attribute:
return $(this).find('td[colspan]').length;
// add the 'header' class to those found 'tr' elements
}).addClass('header')
// set the display of those elements to 'table-row':
.css('display', 'table-row')
// bind the click-handler (as above)
.click(function () {
$(this).nextUntil('tr.header').css('display', function (i, v) {
return this.style.display === 'table-row' ? 'none' : 'table-row';
});
});
References:
参考:
回答by LynchburgExplorer
I liked the simplest answer provided. However, I didn't like the choppiness of the collapsing. So I combined a solution from this question: How to Use slideDown (or show) function on a table row?to make it a smoother animation when the rows slide up or down. It involves having to wrap the content of each td in a div. This allows it to smoothly animate the collapsing. When the rows are expanded, it will replace the div, with just the content.
我喜欢提供的最简单的答案。然而,我不喜欢倒塌的波涛汹涌。所以我结合了这个问题的解决方案:How to Use slideDown (or show) function on a table row? 当行向上或向下滑动时,使其动画更流畅。它涉及必须将每个 td 的内容包装在一个 div 中。这允许它平滑地为折叠设置动画。当行被展开时,它将用内容替换 div。
So here's the html:
所以这是html:
<table>
<tr class="header">
<td>CARS</td>
</tr>
<tr class="thing">
<td>car</td>
</tr>
<tr class="thing">
<td>truck</td>
</tr>
<tr class="header">
<td>HOUSES</td>
</tr>
<tr class="thing">
<td>split level</td>
</tr>
<tr class="thing">
<td>trailer</td>
</tr>
And here's the js
这是js
$('.header').click(function(){
if($(this).hasClass("collapsed")){
$(this).nextUntil('tr.header')
.find('td')
.parent()
.find('td > div')
.slideDown("fast", function(){
var $set = $(this);
$set.replaceWith($set.contents());
});
$(this).removeClass("collapsed");
} else {
$(this).nextUntil('tr.header')
.find('td')
.wrapInner('<div style="display: block;" />')
.parent()
.find('td > div')
.slideUp("fast");
$(this).addClass("collapsed");
}
});
Checkout this fiddle for an example https://jsfiddle.net/p9mtqhm7/52/
以这个小提琴为例 https://jsfiddle.net/p9mtqhm7/52/
回答by Barmaley
I expanded one of the answers, however my functionality is a bit different. In my version, different rows form different groups. And "header" row triggers collapsing/expanding of that particular group. Also, each individual subgroup memorizes state that its in. It might sound a bit confusing, you can test drive my version using jsfiddle. Hope this code snippets will be helpful to someone out there!
我扩展了其中一个答案,但是我的功能有点不同。在我的版本中,不同的行形成不同的组。“标题”行会触发该特定组的折叠/展开。此外,每个单独的子组都会记住其所在的状态。这听起来可能有点令人困惑,您可以使用 jsfiddle 测试驱动我的版本。希望这些代码片段对那里的人有所帮助!
HTML
HTML
<table border="0">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td class='group1'>Group 1</td>
<td>data 2</td>
</tr>
<tr class='group1'>
<td>data 3</td>
<td>data 4</td>
</tr>
<tr>
<td class='group2'>Group 2</td>
<td>data 2</td>
</tr>
<tr class='group2'>
<td>data 3</td>
<td>data 4</td>
</tr>
<tr class='group2'>
<td class='sub_group1'>Sub Group 1</td>
<td>data 6</td>
</tr>
<tr class='group2 sub_group1'>
<td>data 7</td>
<td>data 8</td>
</tr>
<tr class='group2 sub_group1'>
<td>data 9</td>
<td>data 10</td>
</tr>
<tr class='group2 sub_group1'>
<td class='sub_sub_group1'>Sub Sub Group 1</td>
<td>data 11</td>
</tr>
<tr class='group2 sub_group1 sub_sub_group1'>
<td>data 12</td>
<td>data 13</td>
</tr>
<tr class='group2 sub_group1 sub_sub_group1'>
<td>data 14</td>
<td>data 15</td>
</tr>
<tr class='group2'>
<td class='sub_group2'>Sub Group 2</td>
<td>data 11</td>
</tr>
<tr class='group2 sub_group2'>
<td>data 12</td>
<td>data 13</td>
</tr>
<tr class='group2 sub_group2'>
<td>data 14</td>
<td>data 15</td>
</tr>
</table>
CSS
CSS
table, tr, td, th
{
border: 1px solid black;
border-collapse:collapse;
}
img.button_open{
content:url('http://code.stephenmorley.org/javascript/collapsible-lists/button-open.png');
cursor:pointer;
}
img.button_closed{
content: url('http://code.stephenmorley.org/javascript/collapsible-lists/button-closed.png');
cursor:pointer;
}
JS
JS
function CreateGroup(group_name)
{
// Create Button(Image)
$('td.' + group_name).prepend("<img class='" + group_name + " button_closed'> ");
// Add Padding to Data
$('tr.' + group_name).each(function () {
var first_td = $(this).children('td').first();
var padding_left = parseInt($(first_td).css('padding-left'));
$(first_td).css('padding-left', String(padding_left + 25) + 'px');
});
RestoreGroup(group_name);
// Tie toggle function to the button
$('img.' + group_name).click(function(){
ToggleGroup(group_name);
});
}
function ToggleGroup(group_name)
{
ToggleButton($('img.' + group_name));
RestoreGroup(group_name);
}
function RestoreGroup(group_name)
{
if ($('img.' + group_name).hasClass('button_open'))
{
// Open everything
$('tr.' + group_name).show();
// Close subgroups that been closed
$('tr.' + group_name).find('img.button_closed').each(function () {
sub_group_name = $(this).attr('class').split(/\s+/)[0];
//console.log(sub_group_name);
RestoreGroup(sub_group_name);
});
}
if ($('img.' + group_name).hasClass('button_closed'))
{
// Close everything
$('tr.' + group_name).hide();
}
}
function ToggleButton(button)
{
$(button).toggleClass('button_open');
$(button).toggleClass('button_closed');
}
CreateGroup('group1');
CreateGroup('group2');
CreateGroup('sub_group1');
CreateGroup('sub_group2');
CreateGroup('sub_sub_group1');
回答by krishgopinath
I would say using the data-
attribute to match the headers with the elements inside it. Fiddle : http://jsfiddle.net/GbRAZ/1/
我会说使用该data-
属性将标题与其中的元素进行匹配。小提琴:http: //jsfiddle.net/GbRAZ/1/
A preview of the HTML alteration :
HTML 更改的预览:
<tr class="header" id="header1">
<td colspan="2">Header</td>
</tr>
<tr data-for="header1" style="display:none">
<td>data</td>
<td>data</td>
</tr>
<tr data-for="header1" style="display:none">
<td>data</td>
<td>data</td>
</tr>
JS code :
JS代码:
$(".header").click(function () {
$("[data-for="+this.id+"]").slideToggle("slow");
});
EDIT:
But, it involves some HTML changes. so I dunno if thats what you wanted. A better way to structure this would be using <th>
or by changing the entire html to use ul, ol, etc
or even a div > span
setup.
编辑:但是,它涉及一些 HTML 更改。所以我不知道这是否是你想要的。更好的构建方法是使用<th>
或更改整个 html 以使用ul, ol, etc
甚至div > span
设置。
回答by tony gil
A JavaScript accordiondoes the trick.
JavaScript 手风琴可以解决问题。
This fiddle by W3Schoolsmakes a simple task even more simple using nothing but javascript, which i partially reproduce below.
W3Schools 的这个小提琴使一个简单的任务变得更加简单,只使用 javascript,我在下面部分复制了它。
<head>
<style>
button.accordion {
background-color: #eee;
color: #444;
font-size: 15px;
cursor: pointer;
}
button.accordion.active, button.accordion:hover {
background-color: #ddd;
}
div.panel {
padding: 0 18px;
display: none;
background-color: white;
}
div.panel.show {
display: block;
}
</style>
</head><body>
<script>
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function(){
this.classList.toggle("active");
this.nextElementSibling.classList.toggle("show");
}
}
</script>
...
<button class="accordion">Section 1</button>
<div class="panel">
<p>Lorem ipsum dolor sit amet</p>
</div>
...
<button class="accordion">Table</button>
<div class="panel">
<p><table name="detail_table">...</table></p>
</div>
...
<button class="accordion"><table name="button_table">...</table></button>
<div class="panel">
<p>Lorem ipsum dolor sit amet</p>
<table name="detail_table">...</table>
<img src=...></img>
</div>
...
</body></html>
if using php, don't forget to convert "
to '
. You can also use tables of data inside the button and it will still work.
如果使用 php,不要忘记转换"
为'
. 您还可以在按钮内使用数据表,它仍然可以工作。
回答by rjg132234
using jQuery it's easy...
使用jQuery很容易...
$('YOUR CLASS SELECTOR').click(function(){
$(this).toggle();
});