2

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?

Different55
  • 577
  • 2
  • 17

2 Answers2

1

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>
Community
  • 1
  • 1
Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
  • Fantastic, that was it! Excellent work! Side questions, what happens when there are multiple top level elements (My full page does have a sibling or two for .container), and is there any way to avoid this stripdown? – Different55 May 10 '18 at 03:28
  • `$(data)` will correspond to the first top-level element, ignoring siblings after it. Regarding you second point, take a look [at this question](https://stackoverflow.com/questions/2488839/does-jquery-strip-some-html-elements-from-a-string-when-using-html) - it may be helpful. Given the information included within, I believe your `$(
    ")` workaround may actually be safer. Though, it could be shortened to just `$("
    ")`.
    – Tyler Roper May 10 '18 at 03:35
  • @Different55 Upon investigation I've edited my answer. I think that my previous answer will not work across all browsers. Not only will the suggested work around be cross-browser compatible, but I think it will solve your sibling issue as well. – Tyler Roper May 10 '18 at 03:43
0

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');

Chanckjh
  • 2,587
  • 2
  • 22
  • 28
  • I'm not quite sure that makes sense in this context. `data` is a string containing a full HTML document. I have it set as a second parameter so that it's interpreted as a document all its own, and so that the selector is executed in that context. See this bit of the [documentation](https://api.jquery.com/jQuery/). Appending the HTML string to the selector ends in `".container ..."` and spits out a syntax error. – Different55 May 10 '18 at 02:10