More efficent method of styling alternating blocks of table rows with jQuery?

665 Views Asked by At

Doing odd/even styling with jQuery is pretty easy:

$(function() {
  $(".oddeven tbody tr:odd").addClass("odd");
  $(".oddeven tbody tr:even").addClass("even");
});

Now I came across an interesitng problem today. What if you want to style alternating groups of elements? For example, alternating blocks of 3. Longhand this can be done this way:

$(function() {
  $(".oddeven3 tbody tr:nth-child(3n+1)").addClass("odd");
  $(".oddeven3 tbody tr:nth-child(3n+2)").addClass("odd");
  $(".oddeven3 tbody tr:nth-child(3n+3)").addClass("odd");
  $(".oddeven3 tbody tr:nth-child(3n+4)").addClass("even");
  $(".oddeven3 tbody tr:nth-child(3n+5)").addClass("even");
  $(".oddeven3 tbody tr:nth-child(3n+6)").addClass("even");
});

Seems a bit longwinded though. Now it can be somewhat simplified and made generic like this:

function oddEvenGroupStyle(groupSize) {
  for (var i=1; i<=groupSize; i++) {
    $(".oddeven" + groupSize + " tbody tr:nth-child(" + groupSize + "n+" + i + ")").addClass("odd");
    $(".oddeven" + groupSize + " tbody tr:nth-child(" + groupSize + "n+" + (groupSize+i) " + ")").addClass("even");
  }
}

and:

$(function() {
  oddEvenGroupStyle(3);
});

Seems like a bit of a hack to me though. Is there some more jQuery-ish way of selecting the right rows?

4

There are 4 best solutions below

3
On BEST ANSWER
function oddEvenGroupStyle(groupSize) {
    var even = false;
    $('tr').each( 
        function(i){ 
            if(!(i % groupSize)) even = !even;
            $(this).attr('class', (even ? 'groupEven':'groupOdd') ); 
    })
}
1
On

cletus, if you'd like to get the job done 101% jQuery-ish consider:

  1. using each instead of classic for loop
  2. extending jQuery selector behaviour? (just a hint)
1
On

I would add a class to the first TR in a group:

<tr class="group"><td>Group 1</td></tr>
<tr class="grouppart"><td>Part of group 1</td></tr>
<tr class="grouppart"><td>Part of group 1</td></tr>
<tr class="group"><td>Group 2</td></tr>
...

This way you can change the size of groups as you go without any modification to your javascript.

// Format the groups:
$("tr.group:even").addClass("even");
$("tr.group:odd").addClass("odd");

// Then apply to groupparts:
$("tr.grouppart").each(function(){
    var oGroup = $(this).prevAll("tr.group:first");
    if(oGroup.hasClass("even")){$(this).addClass("even");}
    if(oGroup.hasClass("odd")){$(this).addClass("odd");}
});

Note: I wrote this from memory, so there might be some small glitches in there. Please comment if that's the case and I'll fix it.

1
On

1) why have a odd AND and a even class, if you have a default style and then have a overriding odd it will probably be quicker

2) can't you render out the html with the styling already applied? say if your doing this in PHP or ASP.net. doing it after the fact is slower, especially if you have a lot of rows.