展开/折叠带有嵌套行的表格行

3
我想创建一个具有以下结构的表格:
行1 数据列1 数据列2 数据列3
子行1 数据列1 数据列2 数据列3
子行2 数据列1 数据列2 数据列3
子行3 数据列1 数据列2 数据列3
我希望子行能够在单击时展开/折叠。但是,我无法通过表格实现这一点。我知道列表可能是更好的选择,但表格更容易维护。
<tbody>
    <tr class="row1 head1">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row1 head2 closed">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row1 head3">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row1 head4">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row1 head5">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row2 head1">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>

    <tr class="row2 head4">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr class="row2 head5">
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr>
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>
    <tr>
        <td>Cash and Equivalents</td>
        <td>000,000</td>
        <td>000,000</td>

    </tr>

</tbody>

在行点击时,我调用以下函数:
holdingsTree: function(that){
    var stack = '',
        classes = ba.splitClasses(that.attr('class')),
        nextRow = ba.getClassNumber(classes[1], "head");

    if (that.next().hasClass('head'+nextRow)){
        if (that.next().hasClass(classes[0]) && that.next().hasClass('open')){
            that.nextUntil('.head1').hide().addClass('closed').removeClass('open');
        } else if (that.next().hasClass(classes[0])){
            stack = that.nextUntil('.head1');
            $.each(stack, function(i, item){ if ($(item).hasClass('head' + (nextRow))){ $(this).show().addClass('open').removeClass('closed'); } });
        }
    } else if (that.next().hasClass('head'+ (nextRow+1))){
        if (that.next().hasClass(classes[0]) && that.next().hasClass('open')){
            that.nextUntil('.head1').hide().addClass('closed').removeClass('open');
        } else if (that.next().hasClass(classes[0])){
            stack = that.nextUntil('.head1');
            $.each(stack, function(i, item){ if ($(item).hasClass('head' + (nextRow+1))){ $(this).show().addClass('open').removeClass('closed'); } });
        }
    } else if (that.next().hasClass('head'+ (nextRow+2))){
        if (that.next().hasClass(classes[0]) && that.next().hasClass('open')){
            that.nextUntil('.head1').hide().addClass('closed').removeClass('open');
            return;
        } else if (that.next().hasClass(classes[0])){
            stack = that.nextUntil('.head'+ (nextRow+3));
            $.each(stack, function(i, item){ if ($(item).hasClass('head' + (nextRow+2))){ $(this).show().addClass('open').removeClass('closed'); } });
            //stack.find('.head'+(nextRow+2)).show().addClass('open').removeClass('closed');
        }
    } else if (that.next().hasClass('head'+ (nextRow+3))){
        if (that.next().hasClass(classes[0]) && that.next().hasClass('open')){
            that.nextUntil('.head1').hide().addClass('closed').removeClass('open');
        } else if (that.next().hasClass(classes[0])){
            stack = that.nextUntil('.head1');
            $.each(stack, function(i, item){ if ($(item).hasClass('head' + (nextRow+3))){ $(this).show().addClass('open').removeClass('closed'); } });
        }
    } else if (that.next().hasClass('head'+ (nextRow+4))){
        if (that.next().hasClass(classes[0]) && that.next().hasClass('open')){
            that.nextUntil('.head1').hide().addClass('closed').removeClass('open');
        } else if (that.next().hasClass(classes[0])){
            that.nextUntil('.head1').show().addClass('open').removeClass('closed');
        }
    } 

},

splitClasses: function(names){
    var names = names.split(' ');
    return names;
},

getClassNumber: function(name, pretext){
    var result = name.split(pretext);
    console.log(parseInt(result[1]) + 1);
    return parseInt(result[1]) + 1;
}

这很糟糕,我知道。:)

4个回答

10
你可以为你称之为“父级”的行创建一个类,为你称之为“子级”的行创建另一个类,并切换它们的显示。
以下是具体步骤:
$(document).ready(function() {

    function getChildren($row) {
        var children = [];
        while($row.next().hasClass('child')) {
             children.push($row.next());
             $row = $row.next();
        }            
        return children;
    }        

    $('.parent').on('click', function() {

        var children = getChildren($(this));
        $.each(children, function() {
            $(this).toggle();
        })
    });

})

请查看此fiddle以获取完整运行代码:http://jsfiddle.net/T8t2r/3/。如果此解决了您的问题,请接受答案!祝好运!编辑:为了在更多层次上工作,一种方法是拥有一个级别属性。因此,这是更新版本,应该可以在任意数量的级别上工作。http://jsfiddle.net/T8t2r/9/
$(document).ready(function() {

    function getChildren($row) {
        var children = [], level = $row.attr('data-level');
        while($row.next().attr('data-level') > level) {
             children.push($row.next());
             $row = $row.next();
        }            
        return children;
    }        

    $('.parent').on('click', function() {

        var children = getChildren($(this));
        $.each(children, function() {
            $(this).toggle();
        })
    });

})

1
你可以使用fadeToggle()或slideToggle()来实现不同的效果,而不是使用toggle。 - Angel
只处理一个嵌套级别。我有多个嵌套级别要处理。 - amit
谢谢你的帮助。但是它仍然有漏洞。一旦你折叠了所有子行,然后尝试折叠最顶层的父行,它只会折叠next()的子行。 - amit
检查这个:http://jsfiddle.net/T8t2r/13/ 这些都是草稿,请指出正确的方向,您应该尝试并改进解决方案。 - Angel
@Angel将http://jsfiddle.net/T8t2r/9/的第16行更改为`$(this).slideToggle(500);`,似乎不起作用? - Tina Chen

0
你可以这样做:
$('.mySelectorOfNOTSubRow').toggle(
    function(){
        $(this).nextUntil('.mySelectorOfNOTSubRow').show();
    }, function(){
        $(this).nextUntil('.mySelectorOfNOTSubRow').hide();
});

HTML:

<table>
<tbody>
<tr class="head"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
<tr class="head"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
<tr class="head"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
     <tr class="sub"><td></td></tr>
...
</tbody>
</table>

CSS:

.sub{display: none;}

小提琴


这只处理单层嵌套。我必须处理多达5层的嵌套。 - amit

0

从那个例子中很难理解你想做什么。

你想做的事情应该相当简单 - 我会从头开始重写,使用以下概念:

  1. 给每个可点击的项目(行)分配一个自己的ID,但将它们全部放在一个“可点击”的类中
  2. 根据可点击父级的ID为每个子行分配一个类,例如“[id]-sub”
  3. 在“可点击”类上设置一个点击事件,在其中确定所点击的项目ID,并使用它来切换(隐藏/显示)所有具有类“[clicked ID]-sub”的行

这样做,你应该会有更少的代码,而且代码可读性更高。

希望这可以帮助到你...


啊,DKSan建议使用DataTables - 我也曾经用过DataTables的详细行来处理这种情况,但除非您需要DataTables的其他功能,否则我个人建议避免使用它 - 要让详细行正好按照您的要求工作可能会很麻烦。 - John - Not A Number

-1

既然您已经在使用jQuery,那么您可以选择插件datatales

正如页面示例部分所示,您可以完全实现您的代码所需达到的效果。


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