Reputation: 38143
I'm writing tests with QUnit and using $.ajax()
to pull in HTML for some of the tests from the the dev site running on my local:
add_elements = function(location, selector) {
$.ajax(location, {async: false}).done(function(data) {
stor.$els = $(selector, $.parseHTML(data));
stor.$els.appendTo($('body'));
})
}
Using this function at a certain location, I get the following data
passed to my .done()
callback:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/static/css/bootstrap.min.css" rel="stylesheet" media="screen">
</head>
<body>
<div id="app-container" class="container-fluid">
<div class="page-header">
<h1>
<a href="/">Home</a>
<small>Text</small>
</h1>
</div>
<div id="hero-units" class="carousel-inner slide">
<div class="hero-unit home item active">
<h1>
Text text text
</h1>
<p>
More text!
</p>
<div id="app-nav">
<a id="lets-go" class="btn btn-primary btn-large nav-forward" href="/what-up/">
Let's go
</a>
</div>
</div>
</div>
</div>
<script src="/static/js/jquery.js"></script>
<script src="/static/js/underscore.js"></script>
<script src="/static/js/backbone.js"></script>
<script src="/static/js/bootstrap.js"></script>
<script src="/static/js/site-fiddle.js"></script>
<script src="/static/js/site.js"></script>
</body>
</html>
Everything works if selector
is #hero-units
or .hero-unit
, but $(selector, $.parseHTML(data))
returns nothing if selector
is #app-container
! And I want a jQuery
object for the div#app-container
element.
And here is what kills me:
$.parseHTML(data)
does contain the div#app-container
element. It's just $.parseHTML(data)[7]
. $('#app-container', $.parseHTML(data))
is an empty array.$('div', $.parseHTML(data))
includes all the div
s inside of div#app-container
, but not div#app-container
itself.What's going on here? It appears that what's happening is that $
is not looking at any of the top-level elements returned by $.parseHTML(data)
or $($.parseHTML(data)))
, and just their children.
How can I get a jQuery
object for div#app-container
from this $.parseHTML(data)
?
ANSWER
The $(selector, $.parseHTML(data))
-style lookup uses $.find
. Since I'm looking for an element that's top-level in this jQuery object, I should use $.filter
instead. Voila.
Upvotes: 38
Views: 49444
Reputation: 51
Above answers didn't work for me, this did:
use jQuery.parseHTML to parse the HTML into an array of elements; then you’ll be able to convert it to a jQuery collection and use filter to restrict the collection to elements matching a selector.
var html =
'<td class="test">asd</td>' +
'<td class="last">jkl</td>';
var obj = $($.parseHTML(html)).filter('.test');
Upvotes: 2
Reputation: 22553
It doesn't have anything to do with the html not being part of the DOM. It's just that for whatever reason the top level tag(s) in the parsed HTML cannot be found. If the element you are looking for is wrapped in another tag, then the find works as you expect. BTW, wrapping the element in the body tag won't work, but all the others I have tried work fine.
var bad = $.parseHTML('<ul><<li><one/li>/<li>two</li></ul>');
console.log($(bad).find('li').length); //will be 2
console.log($(bad).find('ul').length); //will be 0
var good = $.parseHTML('<div><ul><<li><one/li>/<li>two</li></ul></div>');
console.log($(good).find('li').length); //will be 2
console.log($(good).find('ul').length); //will be 1
This is definitely the case in jQuery 1.11, not sure what happens in later versions. Here is a fiddle that demonstrates: http://jsfiddle.net/ndnnhf94/
Upvotes: 4
Reputation: 66490
You can try this:
$($.parseHTML('<div><span id="foo">hello</span></div>')).find('#foo');
for strings that start with <
you can shorter that code to just:
$('<div><span id="foo">hello</span></div>').find('#foo');
Upvotes: 14
Reputation: 71
I believe this will work, especially if you specifically need to find the element by id;
function findInParsed(html, selector){
return $(selector, html).get(0) || $(html).filter(selector).get(0);
}
If you need the jquery version of the object then you can get it with this
function findInParsed(html, selector){
var check = $(selector, html).get(0);
if(check)
return $(check);
check = $(html).filter(selector).get(0)
return (check)? $(check) : false;
}
Upvotes: 0
Reputation: 987
Just ran into this.
Turns out $.parseHTML
returns a vanilla Array
of DOM elements, and that doesn't support the jQuery find that you want.
I think this is the cleanest solution for converting an HTML string to a jQuery object:
var html = '<div><span id="foo">hello</span></div>';
var $foo = $(html).find('#foo');
Note: You may want to use $.trim
around your html strings so jQuery doesn't get confused by whitespaces.
Upvotes: 4
Reputation: 7466
You need to create a DOM element to append the results of .parseHTML()
first so that it creates a DOM tree before jQuery can traverse it and find div#app-container
.
var tempDom = $('<output>').append($.parseHTML(str));
var appContainer = $('#app-container', tempDom);
I used your example and got it working: http://jsfiddle.net/gEYgZ/
The .parseHTML()
function seems to choke on the <script>
tags, so I had to remove them.
PS. Obviously <output>
is not a real HTML tag, just using it for the example
Upvotes: 42