tags:

views:

80

answers:

6

I have this code

$(this).parent().children('.vote_count').children('span.number')

but I am wondering if there is a better way to go up one level, down two from a selector

+3  A: 

how about

$("> .vote_count > span.number", $(this).parent())

or

$("> span.number", $(this).siblings(".vote_count"))

or

$("~ .vote_count > span.number", this)

or

$(this).find("~ .vote_count > span.number")` 

using the sibling selector and the child selector

hunter
nice one. Will accept answer once it lets me. Not sure why I have to wait!!
Mild Fuzz
@Mild Fuzz: Note that these are *not* the same as your original. These use *descendant* selectors, not immediate child selectors.
T.J. Crowder
@TJ good point, thought it would be unlikely that there would be those children deeper in the hierarchy this is more concise.
hunter
@hunter: We have no idea whether it would be likely or not. Good edit to fix it.
T.J. Crowder
I'm not sure what OP meant by *"quicker"*, but it's worth noting that specifying a context is slower (execution).
patrick dw
@TJ I would be mad at my designer/developer if he/she were css class-ing elements like that. ;)
hunter
This should work fine, but I would suggest using the .find() method instead of .children; it has a bit better performance and does the same thing.
RussellUresti
if "quicker" means "faster", then those selectors are definetly slower.
jAndy
@RussellUresti: actually `.children()` should have a slightly better performance than `.find()` since it only grabs immediate child elements.
jAndy
check out the last one, I dig that greatly
hunter
@hunter: The last one (currently `$(this).find("~ .vote_count > span.number")` as I write this) is **again** using a descendant selector where the OP used an immediate-child function. It will find *any* `.vote-count` element at any level that's a descendant (not child) of a sibling. Also, note that the OP didn't say that `this` couldn't be a `.vote-count`, but it will be omitted if you use a sibling selector (the same problem patrick w pointed out about Matt Ball's answer).
T.J. Crowder
@T.J. Crowder: it also implies the use of the universal selector `*`, which should perform pretty poorly also.
jAndy
@T.J. Crowder : http://jsperf.com/parent-children-vs-sibling Ignore the title, I changed what it to test children vs find.
RussellUresti
could I ask for a bit of description with each one, would make this question better reference for others.
Mild Fuzz
@Mild Fuzz - The last two that use `~` don't seem to work at all. Not for me anyway. [Here's your code](http://jsbin.com/upopu4/) compared to [the last solution](http://jsbin.com/upopu4/2/). The first two examples take a context as the second argument, which is a slower equivalent of `$(this).parent().find("> .vote_count > span.number")` (for the first example). You'd be better off with your original code.
patrick dw
A: 
$(this).parent().find(".vote_count > span.number");

is one alternative.

Bobby Jack
That uses a descendant selector for the `.vote-count` part. The OP used an immediate-child selector.
T.J. Crowder
Yup, totally right. I hadn't realised find() would accept a leading combinator (e.g. ">") but I'm glad I learnt that today!
Bobby Jack
+2  A: 

How about using .siblings?

$(this).siblings('.vote_count').children('span.number');

After all, the children of my parents are my siblings.


Edit as per @patrick dw's comment, if you need to ensure that this is also included* then you can use .andSelf():

$(this).siblings('.vote_count').andSelf().children('span.number');

After a bit of discussion with patrick (see comments), it looks like the best answer is likely the one you already have: $(this).parent().children('.vote_count').children('span.number'), unless you can make assumptions about this based on how you selected it.


*The first answer (the one that doesn't use andSelf()) assumes that this is not a .vote_count.

Matt Ball
It could be a problem if `this` is also a `.vote_count` element. In that case it would be excluded. Not sure if that's the situation here, though.
patrick dw
@patrick: `this` will be excluded no matter what - but I get what you mean. Editing accordingly.
Matt Ball
Matt - In the question, `this` would not be excluded if `this` is a `.vote_count` element, because `.parent().children('.vote_count')` will include `this` in the elements being filtered, whereas `.siblings('.vote_count')` wouldn't.
patrick dw
@patrick - yes yes yes. When I said "`this` will be excluded no matter what" I meant in _my_ answer. Anyway, `andSelf()` to the rescue!
Matt Ball
...regarding your edit, the trouble with `.andSelf()` is that you're calling it *after* `.siblings('.vote_count')`, which means it will be added even if it isn't a `.vote_count`. You would need something like `$(this).siblings().andSelf().filter('.vote_count')...`.
patrick dw
@patrick: blarg. You're right. I have no idea how `this` is being selected... so the best answer may actually be the one in the question.
Matt Ball
+1  A: 

You can condense it some:

$(this).parent().find('> .vote_count > span.number')

Live example

This has the advantage of offloading as much as possible to the selector engine (rather than making individual function calls), where it can possibly be optimized. (It won't necessarily be, just that you're making it possible.) Unlike several of the other solutions here, it won't miss out the current element if it's a .vote-count, it respects your use of immediate-child functions rather than descendant functions, and moreover it's simple. Your original seemed just fine to me as well, though.

Your original only considers immediate children, which I assume was intentional, but just for completeness, I'll mention:

If you want to find .vote-count at any level under the parent, and look for immediate children of them that are span.number, do this instead:

// Slightly different from your original, see comment above
$(this).parent().find('.vote_count > span.number')

If you only want to find .vote-counts that are immediate children, but then find span.number underneath them wherever they are (even if not immediate children), do this:

// Slightly different from your original, see comment above
$(this).parent().find('> .vote_count span.number')

...and finally if you want find any .vote-count anywhere under the parent (not just as an immediate child) and find any span.number under it (not just as an immediate child):

// Fairly different from your original, see comment above
$(this).parent().find('.vote_count span.number')
T.J. Crowder
A: 

I'll not quite sure if this what you are looking for:

$(this).parent().find('.vote_count > span.number')
RoToRa
Note that that's not the same as the original. The original only deals with immediate children, yours is using descendant selectors instead.
T.J. Crowder
True. Changed that. Thanks.
RoToRa
+1  A: 

Personally, I think you're fine sticking with your original version, although I might change it to eliminate the .parent() call by using the native .parentNode property.

$(this.parentNode).children('.vote_count').children('span.number')
patrick dw