jQuery 展开/折叠分层表格行

6
我正在寻找一种使用jQuery展开/折叠分层表格行的高效方法。问题在于,展开和折叠功能是不同的。
  • 最初,只有带有类level_0的行会显示,所有其他行都被隐藏。
  • 展开应该只显示下一个级别,因此单击行id = 10应仅使具有id = 11id = 14的行可见。
  • 另一方面,折叠应该折叠比当前级别更深的所有连续行。例如,单击行id = 10上的折叠应隐藏具有id = 11,12,13,14的行(如果它们可见)。

表格数据如下:

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

我的无效解决方案:
$('#mytable tr').live('click', function() {
  var toggleClass = 'parent_' + $(this).attr('id');
  $(this).nextAll('tr').each(function() {
    if ($(this).is('.'+toggleClass)) {
      $(this).toggleClass("showme");
    }
  });
});

问题是,它只会折叠下一级行。被点击行下面可见的更深层次的行仍然显示。
有人可以给我一些提示吗?我应该如何以高效的方式做到这一点?如果需要,可以调整HTML代码。
感谢任何提示。
3个回答

2
您发布的帖子中的表格html不是有效的(tr由td包围)。在正确结构的表格上,此代码可正常工作。
$("tr.level_0").live("click", function () {
  $(this).nextUntil(".level_0").toggle();
});

0

我觉得你可能需要更多的代码来处理所有行在关闭打开状态下的点击。

我添加了一个类切换来指示行是否打开,并根据其状态以不同的方式处理点击。无论是collapse还是expand都有一个循环,从点击行后面的一行开始遍历,当它们到达相同级别的行时停止。这个逻辑对于任何级别都应该有效,不仅仅是0级。此外,使用带有精确选择器的nextUntil逻辑,while循环可能会更简洁 - 在看到Jules的回答之前,我对这个jQuery方法不熟悉 - 非常巧妙!

另外,为了使这个示例代码更简单,我将你的级别类命名系统视为HTML数据属性,所以给定的行看起来像这样:<tr data-level="0" id="10">。你可以用解析你的类名的代码替换对.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;
    }
}
}

(这个还没有测试 - 抱歉,我得去睡觉了!)


0

我已经为另一个问题的答案创建了一个多级层次结构版本

您表格的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_');

请查看此JSFiddle,以使其正常工作。

优化

我有一个稍微不同的表格结构,它涉及指定父项以及子项,这样搜索可以更有效。

接着我还从中制作了一个jQuery分层表格行切换Gist,并将其转换为对象化的JavaScript,进行了优化。 这些优化来自于http://24ways.org/2011/your-jquery-now-with-less-suck/

具体来说:

在表格上使用事件委托而不是在行上使用。

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

缓存子元素的选择。

使用更快的元素选择器,然后在.childClass上使用较慢的过滤器

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

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