JQuery() не находит элементы в результате jQuery.parseHTML()
Я пишу тесты с помощью QUnit и используя $.ajax()
, чтобы вытащить HTML для некоторых тестов из сайта dev, работающего на моем локальном:
add_elements = function(location, selector) {
$.ajax(location, {async: false}).done(function(data) {
stor.$els = $(selector, $.parseHTML(data));
stor.$els.appendTo($('body'));
})
}
Используя эту функцию в определенном месте, я получаю следующий data
, переданный моему обратному сообщению .done()
:
<!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 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>
Все работает, если selector
равно #hero-units
или .hero-unit
, но $(selector, $.parseHTML(data))
ничего не возвращает, если selector
is #app-container
! И я хочу объект jQuery
для элемента div#app-container
.
И вот что меня убило:
-
$.parseHTML(data)
содержит элемент div#app-container
. Это просто $.parseHTML(data)[7]
.
- Тем не менее,
$('#app-container', $.parseHTML(data))
- пустой массив.
-
$('div', $.parseHTML(data))
содержит все div
внутри div#app-container
, но не div#app-container
.
Что здесь происходит? Похоже, что происходит то, что $
не смотрит ни на один из элементов верхнего уровня, возвращаемых $.parseHTML(data)
или $($.parseHTML(data)))
, и просто их дочерние элементы.
Как я могу получить объект jQuery
для div#app-container
из этого $.parseHTML(data)
?
ANSWER
Поиск $(selector, $.parseHTML(data))
-style использует $.find
. Поскольку я ищу элемент верхнего уровня в этом объекте jQuery, вместо этого я должен использовать $.filter
. Вуаля.
Ответы
Ответ 1
Вам нужно создать элемент DOM, чтобы сначала добавить результаты .parseHTML()
, чтобы он создал дерево DOM, прежде чем jQuery сможет пересечь его и найти div#app-container
.
var tempDom = $('<output>').append($.parseHTML(str));
var appContainer = $('#app-container', tempDom);
Я использовал ваш пример и получил его работу: http://jsfiddle.net/gEYgZ/
Функция .parseHTML()
, кажется, задыхается от тегов <script>
, поэтому мне пришлось удалить их.
PS. Очевидно, что <output>
не является реальным тегом HTML, просто используя его для примера
Ответ 2
Вы можете попробовать следующее:
$($.parseHTML('<div><span id="foo">hello</span></div>')).find('#foo');
для строк, начинающихся с <
, вы можете сократить этот код:
$('<div><span id="foo">hello</span></div>').find('#foo');
Ответ 3
Просто наткнулся на это.
Выключает $.parseHTML
возвращает vanilla Array
из DOM-элементов и не поддерживает поиск jQuery, которое вы хотите.
Я думаю, что это самое чистое решение для преобразования строки HTML в объект jQuery:
var html = '<div><span id="foo">hello</span></div>';
var $foo = $(html).find('#foo');
Примечание. Вы можете использовать $.trim
вокруг своих строк html, чтобы jQuery не путался пробелами.
Ответ 4
Это не имеет ничего общего с HTML, не являющимся частью DOM. Просто по какой-то причине теги верхнего уровня в разобранном HTML не могут быть найдены. Если искомый элемент обернут в другой тег, то поиск работает так, как вы ожидаете. Кстати, обертывание элемента в теге body не сработает, но все остальные, которые я пробовал, работают нормально.
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
Это определенно имеет место в jQuery 1.11, не уверен, что произойдет в более поздних версиях. Вот скрипка, которая демонстрирует: http://jsfiddle.net/ndnnhf94/
Ответ 5
Я думаю, вам стоит попробовать:
$('body', $.parseHTML(data))
Ответ 6
Я считаю, что это сработает, особенно если вам нужно найти элемент по id;
function findInParsed(html, selector){
return $(selector, html).get(0) || $(html).filter(selector).get(0);
}
Если вам нужна версия jquery для объекта, вы можете получить ее с помощью этого
function findInParsed(html, selector){
var check = $(selector, html).get(0);
if(check)
return $(check);
check = $(html).filter(selector).get(0)
return (check)? $(check) : false;
}
Ответ 7
Приведенные выше ответы не спомогли мне, это сработало:
используйте jQuery.parseHTML, чтобы разобрать HTML в массив элементов; тогда вы сможете преобразовать его в коллекцию jQuery и использовать фильтр, чтобы ограничить коллекцию элементами, соответствующими селектору.
var html =
'<td class="test">asd</td>' +
'<td class="last">jkl</td>';
var obj = $($.parseHTML(html)).filter('.test');