javascript - color - Buscar etiqueta de cuerpo en una respuesta HTML ajax
title html (4)
Estoy haciendo una llamada ajax para buscar contenido y agregar este contenido de esta manera:
$(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'');
});
El problema es que cuando cambio a
body
no obtengo nada (no hay error, simplemente no html). Im asumiendo que el cuerpo es una etiqueta al igual que ''a'' es? ¿Qué estoy haciendo mal?
Así que esto funciona para mí:
mas = $(data).find(''a'');
Pero esto no lo hace:
mas = $(data).find(''body'');
El análisis del HTML devuelto a través de un objeto jQuery (es decir, $(data)
) para obtener la etiqueta del body
está condenado al fracaso, me temo.
El motivo es que los data
devueltos son una string
(intente console.log(typeof(data))
). Ahora, de acuerdo con la documentación de jQuery , al crear un objeto jQuery a partir de una cadena que contiene un marcado HTML complejo, es probable que se eliminen etiquetas como body
. Esto sucede porque para crear el objeto, el marcado HTML se inserta realmente en el DOM que no puede permitir tales etiquetas adicionales.
Cita relevante de la documentación :
Si se pasa una cadena como parámetro a $ (), jQuery examina la cadena para ver si se parece a HTML.
[...] Si el HTML es más complejo que una sola etiqueta sin atributos, como se muestra en el ejemplo anterior, la creación real de los elementos se realiza mediante el mecanismo internoHTML del navegador. En la mayoría de los casos, jQuery crea un nuevo elemento y establece la propiedad innerHTML del elemento al fragmento HTML que se pasó. Cuando el parámetro tiene una etiqueta única (con etiqueta de cierre opcional o cierre rápido) - $ ("<img / > ") o $ (" <img> "), $ (" <a> </ a> ") o $ (" <a> ") - jQuery crea el elemento utilizando la función createElement () de JavaScript.
Al pasar en HTML complejo, algunos navegadores pueden no generar un DOM que replique exactamente el origen HTML proporcionado. Como se mencionó, jQuery usa la propiedad .innerHTML del navegador para analizar el HTML pasado e insertarlo en el documento actual. Durante este proceso, algunos navegadores filtran ciertos elementos como los elementos <html>, <title> o <head> Como resultado, los elementos insertados pueden no ser representativos de la cadena original pasada.
Experimenté un poco, y he identificado la causa hasta cierto punto, por lo que, en espera de una respuesta real que me interese, aquí hay un truco para ayudar a entender el problema.
$.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())
})
Edición: más experimentación
Parece que es posible si carga el contenido en un iframe, luego puede acceder al contenido del marco a través de alguna jerarquía de objetos 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''s `contentDocument` property
var html = $(''body'',frame[0].contentDocument).html()
// check the HTML
console.log(html)
// remove the temporary iframe
$("#frame").remove()
})
})
Edición: más investigación
Parece que contentDocument es la forma que cumple con los estándares para controlar el elemento window.document
de un iFrame, pero, por supuesto, a IE no le importan los estándares, así que esta es la forma de obtener una referencia a window.document.body
de iFrame window.document.body
Objeto de forma multiplataforma ...
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]
Ver: contentDocument para un iframe
Me di cuenta de algo maravilloso (¡Creo!)
¿Tienes tu html como una cadena?
var results = //probably an ajax response
Aquí hay un objeto jquery que funcionará exactamente igual que los elementos actualmente conectados al DOM:
var superConvenient = $($.parseXML(response)).children(''html'');
¡Nada será despojado de superConvenient
! Puedes hacer cosas como superConvenient.find(''body'')
o incluso
superConvenient.find(''head > script'');
superConvenient
funciona exactamente como los elementos de jquery a los que todos superConvenient
acostumbrados!
NOTA
En este caso, los results
la cadena deben ser XML válidos porque se alimentan al método parseXML
de JQuery. Una característica común de una respuesta HTML puede ser una etiqueta <!DOCTYPE>
, que invalidaría el documento en este sentido. <!DOCTYPE>
posible que las etiquetas <!DOCTYPE>
deban eliminarse antes de utilizar este enfoque! También tenga en cuenta las características como <!--[if IE 8]>...<![endif]-->
, etiquetas sin etiquetas de cierre, por ejemplo:
<ul>
<li>content...
<li>content...
<li>content...
</ul>
... y cualquier otra característica de HTML que será interpretada con indulgencia por los navegadores, pero bloqueará el analizador XML.
Terminé con esta solución simple:
var body = data.substring(data.indexOf("<body>")+6,data.indexOf("</body>"));
$(''body'').html(body);
Funciona también con cabeza o cualquier otra etiqueta .
(Una solución con análisis xml sería mejor, pero con una respuesta XML no válida, debe realizar un "análisis de cadena").