Найти тег тела в ответе HTML ajax
Я делаю ajax-вызов для извлечения содержимого и добавления этого содержимого следующим образом:
$(function(){
var site = $('input').val();
$.get('file.php', { site:site }, function(data){
mas = $(data).find('a');
mas.map(function(elem, index) {
divs = $(this).html();
$('#result').append('' + divs + '');
})
}, 'html');
});
Проблема в том, что когда я изменяю a
в body
, я ничего не получаю (нет ошибки, просто нет html). Я предполагаю, что тело - это тег, как "а"? Что я делаю неправильно?
Итак, это работает для меня:
mas = $(data).find('a');
Но это не так:
mas = $(data).find('body');
Ответы
Ответ 1
Анализ допустимого HTML через объект jQuery (т.е. $(data)
), чтобы получить тег body
, обречен на провал, я боюсь.
Причина в том, что возвращенный data
является string
(try console.log(typeof(data))
). Теперь, согласно документации jQuery, при создании объекта jQuery из строки, содержащей сложную разметку HTML, теги, такие как body
, скорее всего, будут разделены. Это происходит, поскольку для создания объекта разметка HTML фактически вставлена в DOM, которая не может допускать такие дополнительные теги.
Соответствующая цитата из документации:
Если строка передается как параметр в $(), jQuery проверяет строку, чтобы увидеть, выглядит ли она как HTML.
[...] Если HTML более сложный, чем один тег без атрибутов, как в приведенном выше примере, фактическое создание элементов обрабатывается механизмом браузера innerHTML. В большинстве случаев jQuery создает новый элемент и устанавливает свойство innerHTML этого элемента в фрагмент HTML, который был передан. Когда параметр имеет один тег (с дополнительным закрывающим тегом или быстрым закрытием) - $( "< lt, img/" > ") или $(" <img> "), $(" <a> </a> ") или $(" <a> ") - jQuery создает элемент с использованием встроенного JavaScript createElement().
При передаче сложного HTML некоторые браузеры не могут генерировать DOM что точно реплицирует предоставленный HTML-источник. Как уже упоминалось, jQuery использует свойство .innerHTML браузера для анализа прошедших HTML и вставьте его в текущий документ. Во время этого процесса некоторые браузеры отфильтровывают определенные элементы, такие как <html> , <title> , или <head> элементов. В результате вставленные элементы могут не быть представитель исходной строки.
Ответ 2
Я закончил с этим простым решением:
var body = data.substring(data.indexOf("<body>")+6,data.indexOf("</body>"));
$('body').html(body);
Работает также с головой или любым другим тегом .
(Решение с синтаксическим анализом xml было бы лучше, но с неверным ответом XML вы должны выполнить "синтаксический анализ строк".)
Ответ 3
Я немного экспериментировал и определил причину к точке, поэтому, ожидая реального ответа, который мне будет интересен, вот взлом, чтобы помочь понять проблему.
$.get('/',function(d){
// replace the `HTML` tags with `NOTHTML` tags
// and the `BODY` tags with `NOTBODY` tags
d = d.replace(/(<\/?)html( .+?)?>/gi,'$1NOTHTML$2>',d)
d = d.replace(/(<\/?)body( .+?)?>/gi,'$1NOTBODY$2>',d)
// select the `notbody` tag and log for testing
console.log($(d).find('notbody').html())
})
Изменить: дальнейшее экспериментирование
Кажется, что если вы загружаете контент в iframe, вы можете получить доступ к содержимому кадра через некоторую иерархию объектов dom...
// get a page using AJAX
$.get('/',function(d){
// create a temporary `iframe`, make it hidden, and attach to the DOM
var frame = $('<iframe id="frame" src="/" style="display: none;"></iframe>').appendTo('body')
// check that the frame has loaded content
$(frame).load(function(){
// grab the HTML from the body, using the raw DOM node (frame[0])
// and more specifically, it `contentDocument` property
var html = $('body',frame[0].contentDocument).html()
// check the HTML
console.log(html)
// remove the temporary iframe
$("#frame").remove()
})
})
Изменить: больше исследований
Похоже, что contentDocument является стандартным способом удержания элемента window.document
iFrame, но, конечно, IE действительно не заботится о стандартах, так вот как получить ссылку на iFrame window.document.body
объект в кросс-платформенном способе...
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
var iframeBody = iframeDoc.body;
// or for extra caution, to support even more obsolete browsers
// var iframeBody = iframeDoc.getElementsByTagName("body")[0]
Смотрите: contentDocument для iframe
Ответ 4
Я ЧЕРЕЗ ЧЕРЕЗ ЧЕРЕЗ (я думаю!)
Получил ваш html как строку?
var results = //probably an ajax response
Здесь объект jquery, который будет работать точно так же, как элементы, которые в настоящее время подключены к DOM:
var superConvenient = $($.parseXML(response)).children('html');
Ничего не будет удалено из superConvenient
! Вы можете делать такие вещи, как superConvenient.find('body')
или даже
superConvenient.find('head > script');
superConvenient
работает точно так же, как элементы jquery, к которым все привыкли!!!!
Примечание
В этом случае строка results
должна быть корректной XML, потому что она передается методу JQuery parseXML
. Общей чертой HTML-ответа может быть тег <!DOCTYPE>
, который в этом смысле недействителен. Теги <!DOCTYPE>
могут быть удалены перед использованием этого подхода! Также обратите внимание на такие функции, как <!--[if IE 8]>...<![endif]-->
, теги без закрывающих тегов, например:
<ul>
<li>content...
<li>content...
<li>content...
</ul>
... и любые другие функции HTML, которые будут интерпретироваться с помощью браузеров мягко, но приведет к сбою анализатора XML.