jQuery expand/collapse hierarchical table row

前端 未结 3 731
不知归路
不知归路 2021-02-09 23:14

I am looking for an efficient way to expand/collapse hierarchical table rows using jQuery. The problem is, that the expand and collapse functionality differs.

  • Init
相关标签:
3条回答
  • 2021-02-09 23:36

    The table html in your post is not valid (tr enclosed by td). On the properly structured table, this code works.

    $("tr.level_0").live("click", function () {
      $(this).nextUntil(".level_0").toggle();
    });
    
    0 讨论(0)
  • 2021-02-09 23:39

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

    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">. You could replace calls to .data with code to parse your class names.

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

    0 讨论(0)
  • 2021-02-09 23:47

    I've created a version for multiple levels of hierarchy as an answer to another question.

    The jQuery for your table would be:

    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.

    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. The optimisations come from 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

    var childrenRows = $('tr', parentRow.parent()).filter('.'+childClass);
    
    0 讨论(0)
提交回复
热议问题