xmoex
xmoex

Reputation: 2702

How to apply further selectors after storing selected objects

I want to re-use jQuery selections to be able to do further sub-selections. This is my example:

if ($('#thisId > .thatClass').length > 0) {
    return $('#thisId > .thatClass > a.thatOtherClass').attr('id');
}

As I make extensive use of selections, I want (at least for readability reasons) to shorten the code to look similar to this:

var selection = $('#thisId > .thatClass');
if (selection.length > 0) {
    var furtherSelection = selection.filter('> a.thatOtherClass');
    return furtherSelection.attr('id');
}

Trying this I get an error:

TypeError: furtherSelection.attr(...) is undefined

Clearly I've got something wrong, maybe someone has an idea?

Upvotes: 4

Views: 106

Answers (2)

Justin Morgan
Justin Morgan

Reputation: 30760

You can use .children() instead as Archer suggests, and you should. But the root problem is that you're using .filter when you mean .find. Archer hints at this, but it's important to understand that there was no problem with your ("> a.thatOtherClass") construct other than best practice.

filter doesn't traverse the DOM tree; it removes elements from the current sequence, at the same DOM level. So, when you wrote this:

var furtherSelection = selection.filter('> a.thatOtherClass');

You were really saying "elements that satisfy '#thisId > .thatClass' AND ALSO '> a.thatOtherClass'." So you were testing your middle .thatClass elements when you should have been testing their children. If you had used find or children instead, it would have worked:

var furtherSelection = selection.find('> a.thatOtherClass');   //works
var furtherSelection = selection.children('a.thatOtherClass'); //also works

See these in action on jsFiddle: http://jsfiddle.net/jmorgan123/S726f/

I'm pointing this out because the difference between .filter and .find is very important, and your real problem was that you were confusing the two.

Upvotes: 1

Reinstate Monica Cellio
Reinstate Monica Cellio

Reputation: 26143

Us children() instead...

var selection = $('#thisId > .thatClass');
if (selection.length > 0)
{
    return selection.children('a.thatOtherClass').attr('id');
}

I've used children() due to the fact that the use of > in selectors is to be deprecated (as per comments below).

If you weren't looking specifically for child elements then you could use find() like this...

var selection = $('#thisId > .thatClass');
if (selection.length > 0)
{
    return selection.find('a.thatOtherClass').attr('id');
}

Upvotes: 6

Related Questions