使用 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

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

expand/collapse table rows with JQuery

jqueryhtmlcss

提问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 headerto 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 == '-' ? '+' : '-'
        });
    });
});

.promise()

。承诺()

.slideToggle()

.slideToggle()

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 trelements 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';
    });
});

JS Fiddle demo.

JS小提琴演示

In the linked demo I've used CSS to hide the trelements that don'thave the headerclass-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';
    });
});

JS Fiddle demo.

JS小提琴演示

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');

DEMO

演示

回答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, etcor even a div > spansetup.

编辑:但是,它涉及一些 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();
});