Search code examples
javascriptjqueryjquery-selectorschildrencss-selectors

Getting the n-th child which also matches a compound selector in each row


Say I have the following markup

<div><p></p><blockquote></blockquote><ul>...</ul></div>
<div><p></p><blockquote></blockquote><ul>...</ul></div>
 ...
<div><p></p><blockquote></blockquote><ul>...</ul><ul></ul></div>

Is there a jQuery selector/traversal technique I can use to get the nth child matching a complex selector in each div which is robust (in the sense that I can change elements not matched by the selector without messing things up)

Here are some approaches that don't work to help illustrate the problem

 $("div").children("p, ul").filter(":eq(1)") // returns just the first <ul> in the first div
 $("div").children("p, ul:eq(1)") // returns all the p's and the first ul in the first div
 $("div").find(":not(blockquote):eq(1)") //returns the correct elements, but at the expense of having to reference the elements we're *not* after. Also not restricted to just children
 $("div").find(">:not(blockquote):eq(1)") ) // tackles the children problem, but ">" without a parent is not officially supported and jQuery want to deprecate (Can't find the reference but I raised it once in discussion on the jQuery bug boards and John Resig himself said this)

Finally for some context, I'm asking this in order to always find the ith column of a table regardless of whether or not the first column contains th or td cells


Solution

  • After thinking about it I realised what's needed is some sort of :is() selector to wrap the compound selector. jQuery won't implement it (for good reasons), but then I realised a double negative is the same as a positive so the following works for the general case

    $("div").find(">:not(:not(p, ul)):eq(1)")