使用jQuery折叠和展开多个嵌套行

3

我需要一点帮助来折叠和展开嵌套行。目前我的代码可以在第一层级上按照预期进行展开和折叠,但是后续的层级也会显示出来。

$(document).ready(function(e) {
  $('.collapseTitle').click(function() {
    $(this).parent()
      .parent()
      .next('tbody')
      .toggleClass('collapsed');
  });
});
.collapsed {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <thead>
    <tr>
      <td class="collapseTitle">Title</td>
    </tr>
  </thead>

  <tbody class="collapsed">
    <tr>
      <td>Level 1</td>
    </tr>

    <tr>
      <td>Level 2</td>
    </tr>
  </tbody>
</table>

我正在尝试实现以下效果:当点击“collapseTitle”时,展开1级内容,只有当点击“collapseAccount”时才展开2级内容。我知道代码应该类似下面这样,但我还是遇到了困难...
<table>
  <thead>
    <tr>
      <td class="collapseTitle">Title</td>
    </tr>
  </thead>

  <tbody>
    <tr class="collapsed account">
      <td class="collapseAccount">Level 1</td>
    </tr>

    <tr class="collapsed level">
      <td>Level 2</td>
    </tr>
  </tbody>
</table>

<script>
$(document).ready(function(e) {
    $('.collapseTitle').click(function() {
        $(this).parent().parent().next('tbody tr').toggleClass('account');
    });
});

$(document).ready(function(e) {
    $('.collapseAccount').click(function() {
        $(this).next('tr').toggleClass('level');
    });
});
</script>

非常感谢您的帮助。


你的行并不是嵌套的,而是同级的。 - Matt D
$('.collapseAccount').click(function() { $(this).next('tr').toggleClass('level'); --> 将其更改为$(this).parent().next().toggleClass('level'); }); - Vishwas S L
3个回答

2
以下代码应该可以实现您想要实现的功能。希望对您有所帮助:
  1. 点击列标题/头时,可折叠/展开列;
  2. 点击 account 行后面的所有行(直到下一个 account 行)时,可折叠/展开这些行。
您唯一需要做的就是将类 account 添加到更高级别的行中。当您使用循环显示这些行时,可以很容易地完成此操作。

.collapsed {
  /* using visibility, since display causes layout issues */
  /* due to empty rows rows/columns collapsing */
  visibility: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <thead>
    <tr>
      <td>Title1</td>
      <td>Title2</td>
    </tr>
  </thead>
  <tbody>
    <tr class="account">
      <td class="collapsed">Account Summary - Account A</td>
      <td class="collapsed">Account Summary - Account A</td>
    </tr>
    <tr class="collapsed">
      <td class="collapsed">Account Details Part I - Account A</td>
      <td class="collapsed">Account Details Part I - Account A</td>
    </tr>
    <tr class="collapsed">
      <td class="collapsed">Account Details Part II - Account A</td>
      <td class="collapsed">Account Details Part II - Account A</td>
    </tr>
    <tr class="account">
      <td class="collapsed">Account Summary - Account B</td>
      <td class="collapsed">Account Summary - Account B</td>
    </tr>
    <tr class="collapsed">
      <td class="collapsed">Account Details Part I - Account B</td>
      <td class="collapsed">Account Details Part I - Account B</td>
    </tr>
  </tbody>
</table>
<script>
  $(document).ready(() => {
  
    /* the following handlers expand/collapse the columns */
    $('thead > tr > td').each((i, el) => {
      $(el).click(() => {
        const colIndex = $(el).index() + 1;
        const nRows = $('tbody > tr').length;
        for (let j = 0; j < nRows; j += 1) {
          let cellSelector = `tbody > tr:nth-child(${j+1})`
          cellSelector += `> td:nth-child(${colIndex})`;
          $(cellSelector).toggleClass('collapsed');
        }
      })
    })

    /* the following handlers expand/collapse the account-details rows */
    $('tbody > tr.account').each((i, el) => {
      $(el).click(() => {
        $(el).nextUntil('.account').each((j, ele) => {
          $(ele).toggleClass('collapsed');
        })
      })
    })
  });
  
  
</script>


如果我每个账户有多个“账户详情”,我该如何调整你的代码来适应这种情况? - 5abre
不要使用jQuery的.next(),而是可以使用.nextUntil(),它返回一个数组,然后您可以循环遍历该数组。这也进一步简化了类的使用:使用.nextUntil('.account')。然后,您可以完全省略account-details类,因为它只是查找具有account类的下一行。我已经调整了上面的答案。 - chrikrah
非常感谢!它的运行效果非常好。我现在唯一遇到的问题是,因为折叠类被应用在body上,“详细信息”在我展开“账户”时也被显示出来了。有什么办法可以解决这个问题吗? - 5abre
“collapse class being on the body” 是什么意思?当你展开账户时应该发生什么? - chrikrah
当您点击“标题”时,应该展开账户。只有在点击账户时,详细信息才会展开。目前,当单击标题时,账户和详细信息都会展开。 - 5abre
你只需要适当地设置默认值并从一开始就隐藏所有内容。我已经对我的答案进行了更改 - 请参见上文。顺便说一句,如果您的原始问题得到了回答,请将其标记为接受的答案。 - chrikrah

1
你的jQuery选择器在toggleClass中有点问题。你可以使用行的类名进行切换。此外,你应该创建一个要切换的类,以显示/隐藏该行。例如:
编辑:
我现在动态地创建了标题和行,以便更好地演示如何使用data-属性完成此操作。
你将拥有一个与data-属性匹配的标题td和行td,因此当你单击标题时,相应的tr将被显示。例如,如果你单击标题1(具有data-index = 1),则将显示具有属性data-rowindex = 1的tr。

$(document).ready(function(e) {
  createTable();
  
  $('.collapseTitle').click(function() {
  
    // grab the data-index value from the clicked title
    let index = $(this).attr("data-index");
    
    // find a tr that has the attribute data-rowindex and it matches index 
    $("tr[data-rowindex='" + index + "']").toggleClass("collapsed");
  });
});

function createTable(){
  // create the titles and the level rows
  for(let i = 0; i < 3; i++){
  
    // create the title row
    let $trTitle = $('<tr>');
    let $tdTitle = $('<td>', {class: "collapseTitle", text: "Title " + i});
    $tdTitle.attr("data-index", i);
    let $finalTitleRow = $trTitle.append( $tdTitle );
    
    // create the level row
    let $trLevel = $('<tr>', {class: "collapsed account"} );
    $trLevel.attr("data-rowindex", i);
    let $tdLevel = $('<td>', {text: "Level " + i});
    let $finalLevelRow = $trLevel.append( $tdLevel );
    
    // add the title and level row pairs to the head and body
    $("#myTableHead").append($finalTitleRow[0]);
    $("#myTableBody").append($finalLevelRow[0]);
  }
}
.collapsed {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <thead id="myTableHead">
  </thead>

  <tbody id="myTableBody">

  </tbody>
</table>


@ Andrew,谢谢您的建议。我在使用您的建议时遇到的问题是,在循环中使用它来拥有多个标题时,当一个被点击时,所有标题都会展开,而不仅仅是被点击的那个。 - 5abre
@5abre,我更新了我的示例,希望能更好地让你理解如何使用动态创建的元素来实现这一点。 - Andrew Lohr

-2

我成功找到了我正在寻找的答案... 感谢 "stackoverfloweth", 我的问题的答案

迄今为止帮助我最多的代码片段如下所示,

$('.parent-row').click(function(){
var $element = $(this).next();
while(!$element.hasClass('parent-row')){
    $element.toggle();
    if($element.next().length >0){
        $element = $element.next();   
    }
    else{
        return;
    }
} });

$('.child-row.has-children').click(function(){
var $element = $(this).next();
while($element.hasClass('child-child-row')){
    $element.toggle();
    if($element.next().length >0){
        $element = $element.next();   
    }
    else{
        return;
    }
} });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接