views:

722

answers:

6

I'm writing an html page with some jQuery for style. So I have the following:

$("table tr:odd td").css({"background-color":"rgb(233,247,255)"});

This makes every other row bluish. But just now, I put a table inside one of the cells. What happened? Well, it treated the row of the inner table as if it was a row in the outer table, and the coloring got messed up (two consecutive blue rows, while the row in the inner table was left white).

So, how do I exclude sub-tables in a selector like this? Anyone?

EDIT:

Thanks for your ideas and answers. I came up with this bit of code, because what I really want is to have all tables have even/odd coloring (not just top-level tables):

$("table").each(function()
{   $(this).children().children(":odd").css({"background-color":"rgb(240,255,250)"});
     $(this).children().children(":even").css({"background-color":"rgb(233,247,255)"});
});

The problem is that this seems to only color the first row - I have no idea why. Does anyone see why?

SOLUTION: I figured it out. The problem is that browsers do in fact insert a tbody tag, and you have to figure it in. Heres the final result i'm using:

$("table").each(function()
{   $(this).children().children(":odd").children().css({"background-color":"green"});
     $(this).children().children(":even").children().css({"background-color":"blue"});
});
+7  A: 

You can use the child selector >. They browser should insert a tbody element though:

$("#myTable > tbody > tr:odd > td").css({"background-color":"rgb(233,247,255)"});
Greg
@Greg- that doesn't appear to work - http://jsbin.com/oxafi
Russ Cam
This still selects cell in the child table because it has its own tr elements.
Lance Fisher
You need to select a specific table
Greg
+4  A: 

The easiest way is to give the outer table an identifier, such as a CSS class or id. Then it is trivial. By the way, I think the selector :odd should be :nth-child(odd)

$("table.highlight > tr:nth-child(odd) > td")
    .css({"background-color":"rgb(233,247,255)"});

Here we use the CSS class highlight on the outer table and therefore the inner table cells in odd rows do not get the style applied.

EDIT:

Without some kind of identifier, things are a little trickier, but this works (although I'm sure there's a more succinct way of doing this)

$("table")
    .filter(function() { return this.parentNode.nodeName.toLowerCase() !== "td" })
    .children('tbody').children('tr:nth-child(odd)').children('td')
    .css({"background-color":"rgb(233,247,255)"});

find() cannot be used instead of children() because the odd rows of the inner table would also match and be returned in the wrapped set.

Here's a Working Demo

EDIT:

In response to your edited question, striping odd or even rows for each table is straightforward

$('table tbody').children('tr:nth-child(odd)').css({"background-color":"green"})

I would recommend to use :nth-child(odd|even) over :odd|even since the former is one-based index and therefore the odd rows (1,3,5,etc) are selected; The latter is zero-based, meaning that the even rows (2,4,6,etc) will be the "odd rows". In my opinion, not completely aligned with the selectors semantic name. Also, I would recommend using a CSS style for this over inline styling, and apply the CSS class to the <tr> using addClass(). Using CSS classes will allow you to easily modify the styles to apply and reuse them on different pages. Something like the following,

tr.odd > td  { background-color: green; }
tr.even > td { background-color: red;   }

To apply zebra striping to a table, you have, in my opinion, two real choices

  1. Apply one background color to all <tr> elements in a table and then simply add a CSS class to odd/even rows to add the other background colour you want to stripe with.

  2. Apply both CSS classes using jQuery.

Here's some code for the second option

$('table tbody')                 // find <tbody> that are descendents of <table>
  .children('tr:nth-child(odd)') // find odd <tr>
  .addClass('odd')               // add odd class
  .end()                         // jump back to previous wrapped set
  .children('tr:nth-child(even)')// find even <tr>
  .addClass('even');             // add even class

And a Working Demo. add /edit to the URL to see the code.

Russ Cam
+1 for illustration , and multiple answers
Madi D.
A: 

What is the parent element for your parent table? Try using a descendant selector with it. e.g. If your parent table is directly under the body:

$("body > table >  tr:odd > td").css({"background-color":"rgb(233,247,255)"});

or if you've specified tbody in the markup:

$("body > table > tbody > tr:odd > td").css({"background-color":"rgb(233,247,255)"});
Lance Fisher
`tbody` is not necessary if you haven't specified on in the markup - http://jsbin.com/itebi - a demo using a CSS class identifier
Russ Cam
Thanks, I've incorporated your comment into my answer.
Lance Fisher
A: 

Greg's example:

$("table > tbody > tr:odd > td").css({"background-color":"rgb(233,247,255)"});

Will not work because it will select all tables on the page. The best solution is to add an ID to the table and change the code to:

$("#the-table > tbody > tr:odd > td").css({"background-color":"rgb(233,247,255)"});
kaba
+4  A: 

Russ Cam inspired me to answer the question again without using an identifier on the table and this is what I came up with:

$("table:not(td > table) > tbody > tr:odd > td").css({"background-color":"rgb(233,247,255)"});

Here I select all td's, in every odd row, in tables that are not children of a <td>. Working demo here.

kaba
+1- it works, is a better selector and less winded than using `filter()` as I suggested. I thought there would be a selector way :)
Russ Cam
This works great for exactly what I asked for. The problem is, I wasn't entirely clear. I don't want to *exclude* all subtables - I just want each table to be treated individually (even subtables). But this is a good solution and I could use it for each level of tables separately. Thanks!
B T
A: 

Hi, everyone, just discovered this website, which is amazing! I have a similar problem, but instead of a table is a div.

Since: $('ul#postlist li:even').css('background','red'); is not working, maybe you guys can help me. Is about selecting of even/odd child of a ul, so is about li. Is there any other way to select li (even/odd) elements and add to them a different style? Thanks a lot!

ken
$('#postlist').children(':even').css('background','red'); // should work .
B T