简体   繁体   English

jQuery展开/折叠分层表行

[英]jQuery expand/collapse hierarchical table row

I am looking for an efficient way to expand/collapse hierarchical table rows using jQuery. 我正在寻找一种使用jQuery扩展/折叠分层表行的有效方法。 The problem is, that the expand and collapse functionality differs. 问题是,扩展和折叠功能不同。

  • Initially, only rows with class level_0 are show, all other rows are hidden. 最初,仅显示具有类level_0的行,所有其他行都被隐藏。
  • expand should only show the next level, so clicking on row id=10 should only make rows with id=11 and id=14 visible. expand应该只显示下一个级别,因此单击row id=10应该只显示id=11id=14
  • collapse on the other hand, should collapse all consecutive rows with a deeper level than the current one. 另一方面,崩溃应该折叠比当前行更深的所有连续行。 For example, clicking collapse on row id=10 should hide rows with ids 11, 12, 13, 14 , if they are visible. 例如,单击行id=10上的折叠应隐藏具有ID 11, 12, 13, 14行(如果它们可见)。

The table data looks as follows: 表数据如下所示:

<table id="mytable">
    <tr class="level_0" id="10">...</td>
    <tr class="level_1 parent_10" id="11">...</td>
    <tr class="level_2 parent_11" id="12">...</td>
    <tr class="level_2 parent_11" id="13">...</td>
    <tr class="level_1 parent_10" id="14">...</td>
    <tr class="level_0" id="15">...</td>
</table>

My non-working solution: 我的非工作解决方案:

$('#mytable tr').live('click', function() {
  var toggleClass = 'parent_' + $(this).attr('id');
  $(this).nextAll('tr').each(function() {
    if ($(this).is('.'+toggleClass)) {
      $(this).toggleClass("showme");
    }
  });
});

The problem is, that it only collapses the next level rows. 问题是,它只会折叠下一级行。 Visible and deeper level rows beneath the clicked row are still shown. 仍显示点击行下方的可见和更深级别的行。


Can anyone give me some hints on how I could do this in an efficient way? 任何人都可以给我一些提示,告诉我如何以有效的方式做到这一点? The HTML code can be adjusted if needed. 如果需要,可以调整HTML代码。

Thanks for any hints. 谢谢你的任何提示。

The table html in your post is not valid (tr enclosed by td). 帖子中的表格html无效(由td括起来)。 On the properly structured table, this code works. 在结构合理的表上,此代码有效。

$("tr.level_0").live("click", function () {
  $(this).nextUntil(".level_0").toggle();
});

I've created a version for multiple levels of hierarchy as an answer to another question . 我已经为多个层次结构创建了一个版本作为另一个问题的答案

The jQuery for your table would be: 你的表的jQuery将是:

var treeTable = {
    parentClassPrefix : '',
    collapsedClass : 'collapsed',
    init : function(parentClassPrefix) {
        this.parentClassPrefix = parentClassPrefix;
        $('table').on('click', 'tr', function () { 
            treeTable.toggleRowChildren($(this));
        });
    },
    toggleRowChildren : function(parentRow) {
        var childClass = this.parentClassPrefix+parentRow.attr('id');
        var childrenRows = $('tr', parentRow.parent()).filter('.'+childClass);
        childrenRows.toggle();
        childrenRows.each(function(){
            if (!$(this).hasClass(treeTable.collapsedClass)) {
                treeTable.toggleRowChildren($(this));
            }
        });
        parentRow.toggleClass(this.collapsedClass);
    }
};

treeTable.init('parent_');

See this JSFiddle for it working. 看到这个JSFiddle工作。

Optimisations 最佳化

I have a slightly different table structure, which involves specifying parents as well as children so that the searching can be more efficient. 我有一个稍微不同的表结构,它涉及指定父项和子项,以便搜索更有效。

I've then also made a jQuery hierarchical table row toggling Gist from it and converted it into objectified javascript with optimisations. 然后我还制作了一个jQuery层次表行,从中切换Gist并将其转换为带优化的客观化javascript。 The optimisations come from http://24ways.org/2011/your-jquery-now-with-less-suck/ . 优化来自http://24ways.org/2011/your-jquery-now-with-less-suck/

Specifically: 特别:

Event delegation on the table rather than on the rows. 表上的事件委托而不是行。

$('table').on('click', 'tr.'+treeTable.parentClass, function () {
    treeTable.toggleRowChildren($(this));
});

Cache the children selection. 缓存子选择。

Use the faster element selector followed by a slower filter on the .childClass 使用更快的元素选择器,然后在.childClass上使用更慢的过滤器

var childrenRows = $('tr', parentRow.parent()).filter('.'+childClass);

I think you're gonna need a little some more code so you can handle clicks on all the rows in both closed and open states. 我想你需要更多一些代码,这样你就可以处理关闭打开状态下所有行的点击。

I added a class switch to indicate when a row is open, and treat clicks differently based on it's state. 我添加了一个类开关来指示行何时打开,并根据其状态以不同方式处理点击。 Both collapse and expand have while loops that walk through rows, starting with the one immediately after the clicked row, and they stop when they get to rows of the same level. collapseexpand都有while循环遍历行,从紧跟在单击行之后的循环开始,并且当它们到达相同级别的行时它们停止。 This logic should work for any level, not just 0. Also, the while loop could probably be cleaner using nextUntil logic with a fancy selector - I wasn't familiar with that jQuery method until seeing Jules answer - very slick! 这个逻辑应该适用于任何级别,而不仅仅是0.此外,使用具有花式选择器的nextUntil逻辑, while循环可能更清晰 - 我不熟悉jQuery方法,直到看到Jules的答案 - 非常光滑!

ALso, for keeping this example code simpler, I treated your level class naming system as HTML data attributes, so a given row looks like this: <tr data-level="0" id="10"> . 另外,为了使这个示例代码更简单,我将您的级别类命名系统视为HTML数据属性,因此给定的行如下所示: <tr data-level="0" id="10"> You could replace calls to .data with code to parse your class names. 您可以使用代码替换对.data调用来解析您的类名。

var $rows = $('#mytable tr');

$rows.live('click', function() {
$(this).toggleClass('open');

if ($this.hasClass('open')){
    collapse($(this));
} else {
    expand($this);
}
}

function collapse ($row) {
    $row.removeClass('open');
var rowIndex = $rows.index($row);
var siblingOrAncestorRowFound = false;

while (!siblingOrAncestorRowFound){
    var $nextRow = $rows.eq(rowIndex + 1);
    if ($nextRow.level  > $row.level){
        $nextRow.hide().removeClass('open');
        rowIndex++;
    } else {
        siblingOrAncestorRowFound = true;
    }
}
}

function expand ($row) {
    $row.addClass('open')
var rowIndex = $rows.index($row);
var siblingOrAncestorRowFound = false;

while (!siblingOrAncestorRowFound){
    var $nextRow = $rows.eq(rowIndex + 1);
    if ($nextRow.level  > $row.level){

        // only show rows exactly one level below
        if ($nextRow.level == $row.level + 1){
            $nextRow.show();
        }

        rowIndex++;
    } else {
        siblingOrAncestorRowFound = true;
    }
}
}

(This isn't tested - sorry gotta hit the sack!) (这没有经过测试 - 抱歉打算掏腰包!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM