views:

71

answers:

4

I need to retrieve data from the DOM, but the containers have no a specific class or id, and sometimes they are not all available.

So I could find this:

<h2>name</h2>
<p>john</p>
<h2>address</h2>
<p>street 1</p>
<h3>email</h3>
<p>[email protected]</p>

or this:

<h2>name</h2>
<p>john</p>
<h3>email</h3>
<p>[email protected]</p>

As you can see, to fetch the email I can't select by class or id, nor by n(th) element, because it could be the 2nd or 3th <p>

The only solution I see is to get the first <p> just after <h3>email</h3>, but I have no idea how to filter by text() data.

Thank you.

+2  A: 
var yourP = $('h3:contains("email")').next()
dev-null-dweller
+3  A: 

Use :contains()...or an exact match with .filter() then do .next() to get the <p> sibling that follows, like this:

$("h3:contains('email')").next().doSomething();

Or with .filter() for an exact match (where :contains() is a substring match), like this:

$("h3").filter(function() { return $.text([this]) == "email"; }).next()

You can test both here.

Nick Craver
+2  A: 

To get the email, for example, you could do this:

var emailAddress = $('h3:contains(email)').next('p').text();
Thomas
+3  A: 

You can always create your own selector that matches on exact text content.

This one does that, but trims any whitespace first.

$.extend($.expr[':'], {
    textIs: function(elem, i, attr) {
        return ( $.trim( $.text([elem]) ) === attr[3] );
    }
});

Then you would use it like this:

Example: http://jsfiddle.net/aXvm3/

$('h3:textIs(email)').next()
patrick dw
Why trim? :) Wouldn't it be more usable for `:textIs( email )` cases?
Nick Craver
@Nick - Could go either way. You have a line break inside the tag, and suddenly it doesn't work. I'd guess it would be less frequent that a user would want to match a leading and trailing white space in addition to the text.
patrick dw