tags:

views:

2442

answers:

5

I have a table that has structure like this (td omitted)

<table>
<tr class="header">...</tr>
<tr class="row">...</tr>
<tr class="row">...</tr>
<tr class=="header">...</tr>
<tr class="row">...</tr>
<tr class="row">...</tr>
</table>

When user click on the row I need to hide all rows up to the next row that has class "header". What would be the easiest way to achieve this. Something along these lines, find all rows that have class header, find in the list row index of the clicked row, find the row index of the next row with the same class, and then select all rows within these two indicies?

+1  A: 

You could just do:

$('table tr.row').hide();

Or if you have more than one separations like that:

$('table tr.header').click(function(){
    var rowsToHide = [];
    var trs = $('table tr');
    //let's get the index of the tr clicked first.
    var idx = trs.index(this);
    //now loop untill next header
    for(var i = idx+1; i < trs.length; i++){
        if(trs[i].attr('class') == 'row'){
            rowsToHide.push(trs[i]);
        } else {
            break;
        }
    }

    // now hide the array of row elements
    $(rowsToHide).hide();
})
Dmitri Farkov
Will this not hide all rows with the class "row"?
epitka
yes, it will do that
eKek0
What if the second "header" has rows that are not meant to be hidden until that "header" row is clicked?
orandov
Added solution to make it just the rows between two headers. Code might seem a bit long but keep in mind that it is optimized to hide all rows at once rather than one by one forcing the browser to render each hide.
Dmitri Farkov
A: 

Assuming that you want to hide all rows between headers when a row in that range is clicked:

$('table tr.row').click( function() {
    $(this).hide();
    $(this).prevAll('tr').each( function() {
        if ($(this).hasClass('header')) {
           return false;
        }
        $(this).hide();
    });
    $(this).nextAll('tr').each( function() {
        if ($(this).hasClass('header')) {
           return false;
        }
        $(this).hide();
    });
});

This iterates over the previous/next siblings (that are rows), hiding each until it encounters another row with class header. The return false will terminate the each loop. Tested in Firefox 3.

Corresponding function to show rows when header is clicked:

$('table tr.header').click( function() {
    $(this).nextAll('tr').each( function() {
        if ($(this).hasClass('header')) {
            return false;
        }
        $(this).show();
    });
});
tvanfosson
+6  A: 

You could try something like:

$(document).ready($('table tr').click(
  function () {
    var tr = $(this).nextAll('tr');
    for (i = 0; i < tr.length; i++) {
      var class = $(tr[i]).attr('class');
      if (class == 'row')
        $(tr[i]).hide()
      else {
        if (class == 'header')
          return;
      }
    }
  }
));
eKek0
+1 less jquery elegance but more performant javascript...
Sander Versluys
this works fine, just two changes ("==" instead of "=" in last if) and tr[i] in for loop instead of tr. Also I used toggle instead of hide. Thanks bunch to everybody.
epitka
ups! yeah... = is == (je!) and tr is tr[i] (indexed...). Now is fine.
eKek0
A: 

I'd try using next() and prev() on the row that's clicked, and traverse both directions to find which rows you want to remove. just stop when you get to the header rows.

Matt S.
A: 

I do it like this (it supports 2 levels of headers)

function toggleCollapse(source, destinationClass) {
    var isHidden = source.hasClass('collapsed');
    var current = source;
    while (true) {
        current = current.next("tr:visible");

        if (current.length == 0 || current.hasClass(destinationClass))
            break;

        if (current.hasClass("level2grp"))
            toggleCollapse(current, "level2grp")

        if (isHidden)
            current.show();
        else
            current.hide();
    }

    source.toggleClass('collapsed');
}
Juan Manuel