問題描述

當單擊頭列時,我想展開和摺疊錶行。我只想展開/摺疊位於特定標題下的行 (點擊) 。

這是我的表結構:

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

關於如何完成這項任務的任何想法。使用 div 這個任務看起來很簡單,但是我有我想要操作的表格數據。

我可以想到的一個想法是在每行中使用 css 類來區分每個標題下的行,並且只有在單擊標題時才使用 JQuery 來展開/摺疊這些行。但是如果我的表有 10-15 個標題,那麼很難跟蹤 css 類。

請建議一個合適的方式來實現這一點。

最佳解決方案

你可以這樣嘗試:

給一個類説 header 到標題行,使用 nextUntil 來獲取所點擊的標題下面的所有行,直到下一個標題。

JS

$('.header').click(function(){
    $(this).nextUntil('tr.header').slideToggle(1000);
});

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

另一個例子:

$('.header').click(function(){
   $(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
    $(this).nextUntil('tr.header').slideToggle(100); // or just use "toggle()"
});

Demo

您也可以使用 promise 在切換完成之後切換跨度圖標/文本 in-case 的動畫切換。

$('.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()

或者只是使用一個 css 偽元素來表示擴展/崩潰的符號,並且只是在標題上切換一個類。

CSS: –

.header .sign:after{
  content:"+";
  display:inline-block;
}
.header.expand .sign:after{
  content:"-";
}

JS: –

$(this).toggleClass('expand').nextUntil('tr.header').slideToggle(100);

Demo

次佳解決方案

實現此目的的最簡單的方法是在不改變基於 HTML table 的結構的基礎上,在包含標題的 tr 元素 (如.header) 上使用 class-name 來給出:

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

而 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

在鏈接的演示中,我使用 CSS 來隱藏沒有 header class-name 的 tr 元素; 在實踐中 (儘管用户的 JavaScript 相對稀少,禁用 JavaScript) 我建議使用 JavaScript 添加相關的 class-names,隱藏和顯示適當:

// 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

參考文獻:

  • addClass()

  • click()

  • css()

  • filter()

  • find()

  • hide()

  • nextUntil()

第三種解決方案

我會説使用 data-屬性將標題與其中的元素相匹配。小提琴:http://jsfiddle.net/GbRAZ/1/

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 代碼:

$(".header").click(function () {
   $("[data-for="+this.id+"]").slideToggle("slow");
});

編輯:但是,它涉及到一些 HTML 更改。所以我不知道如果這是你想要的。一個更好的方式來構建它將使用<th> 或通過更改整個 html 來使用 ul, ol, etc 甚至 div > span 設置。

第四種方案

我喜歡提供的最簡單的答案。但是,我並不喜歡坍塌的煩惱。所以我結合了一個這個問題的解決方案:How to Use slideDown (or show) function on a table row?,使它更順暢的動畫,當行向上或向下滑動。它需要將每個 td 的內容包裝在一個 div 中。這使它能夠平滑地動畫地摺疊。當行被展開時,它將只替換內容。

所以這裏是 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>

這就是 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");
}
});

結帳這個小提琴為例 https://jsfiddle.net/p9mtqhm7/52/

第五種方案

我擴展了一個答案,但是我的功能有點不同。在我的版本中,不同的行形成不同的組。並且”header” 行觸發該特定組的摺疊/展開。此外,每個單獨的子組記住它的狀態。它可能聽起來有點混亂,你可以使用 jsfiddle 測試驅動器我的版本。希望這段代碼段將有助於有人在那裏!

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

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

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

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇