Different55
Different55

Reputation: 597

jQuery selector is overlooking elements from a separate context

I'm making an ajax request to a page on my site with this element as a direct child of the body tag:

<div class="container" id="wantme"><div class="content"></div></div>

There's only one .container, and I want to grab its ID which I don't know.

As far as I can tell, this code should do what I want:

$.get('/page', function(data) {
    id = $('.container', data).attr('id');
});

But the .container selector fails to find anything.

I did find these two workarounds. I can find .content, and I can climb up the tree like this:

id = $('.content', data).parent().attr('id');

But I can't leap directly there.

I found this workaround elsewhere on StackOverflow that works:

html = $('<div></div>').html(data);
id = html.find('.container').attr('id');

But why is it that the seemingly obvious answer doesn't work?

Upvotes: 2

Views: 70

Answers (2)

Tyler Roper
Tyler Roper

Reputation: 21672

UPDATED ANSWER: I'll leave my original answer at the bottom, however I'm concerned it may misbehave depending on browser. jQuery's .html() makes use of Javascript's innerHTML - some browsers choose to strip <head> and <body> tags when using innerHTML, whereas others do not.

The safest method to achieve what you're after may still be the workaround you mentioned, like so:

var data = '<!doctype html><html><body><div class="container" id="findme"><div class="content"></div></div></body></html>';

var $container = $("<div />").html(data).find(".container");
var id = $container.attr("id");

console.log(id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

More information as to the browser-related issues can be found here.


PREVIOUS ANSWER:

When you pass HTML to a jQuery element, it will ignore the <body> tags, as well as anything outside of them. Given the data string in your JSFiddle, $(data) will create something that looks like this:

<div class="container" id="findme">
    <div class="content"></div>
</div>

As you can see in the HTML above, your .container isn't inside of $(data) - it is $(data).

Because $(data) is representing your .container element, you should just be able to do $(data).attr("id") to retrieve what you're after.

var data = '<!doctype html><html><body><div class="container" id="findme"><div class="content"></div></div></body></html>';
var id = $(data).attr('id');
console.log(id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 1

Chanckjh
Chanckjh

Reputation: 2597

You are not getting the ID from $('.container', data).attr('id'); is because you are setting the value of the second parameter. What you want to do is this: $('.container ' + data).attr('id');.

Update: If data is a string then you should convert it into a DOM element: $('.container', $(data)).attr('id');

Upvotes: 0

Related Questions