Tengo un proyecto en el que necesito crear un elemento <iframe> usando JavaScript y agregarlo al DOM. Después de eso, necesito insertar algo de contenido en el <iframe>. Es un widget que se integrará en sitios web de terceros.
No configuro el atributo "src" del <iframe> porque no quiero cargar una página; más bien, se usa para aislar / aislar el contenido que inserto en él para que no me encuentre con conflictos de CSS o JavaScript con la página principal. Estoy usando JSONP para cargar contenido HTML desde un servidor e insertarlo en este <iframe>.
Esto funciona bien, con una excepción seria: si la propiedad document.domain está configurada en la página principal (que puede ser en ciertos entornos en los que se implementa este widget), Internet Explorer (probablemente todas las versiones, pero he confirmado en 6, 7 y 8) me da un error de "Acceso denegado" cuando intento acceder al objeto de documento de este <iframe> que he creado. No sucede en ningún otro navegador en el que haya probado (todos los principales modernos).
Esto tiene cierto sentido, ya que soy consciente de que Internet Explorer requiere que configure el dominio de documento de todas las ventanas / marcos que se comunicarán entre sí con el mismo valor. Sin embargo, no conozco ninguna forma de establecer este valor en un documento al que no puedo acceder.
¿Alguien conoce alguna forma de hacer esto, de alguna manera establecer la propiedad document.domain de este <iframe> creado dinámicamente? ¿O no lo estoy viendo desde el ángulo correcto? ¿Hay otra manera de lograr lo que busco sin encontrarme con este problema? Necesito usar un <iframe> en cualquier caso, ya que la ventana aislada / en espacio aislado es crucial para la funcionalidad de este widget.
Aquí está mi código de prueba:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Document.domain Test</title>
<script type="text/javascript">
document.domain = 'onespot.com'; // set the page's document.domain
</script>
</head>
<body>
<p>This is a paragraph above the <iframe>.</p>
<div id="placeholder"></div>
<p>This is a paragraph below the <iframe>.</p>
<script type="text/javascript">
var iframe = document.createElement('iframe'), doc; // create <iframe> element
document.getElementById('placeholder').appendChild(iframe); // append <iframe> element to the placeholder element
setTimeout(function() { // set a timeout to give browsers a chance to recognize the <iframe>
doc = iframe.contentWindow || iframe.contentDocument; // get a handle on the <iframe> document
alert(doc);
if (doc.document) { // HEREIN LIES THE PROBLEM
doc = doc.document;
}
doc.body.innerHTML = '<h1>Hello!</h1>'; // add an element
}, 10);
</script>
</body>
</html>
Lo he alojado en:
http://troy.onespot.com/static/access_denied.html
Como verá si carga esta página en IE, en el momento en que llamo a alert (), tengo un identificador en el objeto de ventana del <iframe>; Simplemente no puedo profundizar más en su objeto de documento.
¡Muchas gracias por cualquier ayuda o sugerencia! Estaré en deuda con quien pueda ayudarme a encontrar una solución a esto.
fuente
Respuestas:
Suspiro. Sí, es un problema de IE (¿error? Es difícil de decir ya que no existe un estándar documentado para este tipo de molestias). Cuando crea un iframe sin src, recibe un
document.domain
del documento principal enlocation.host
lugar de sudocument.domain
. En ese punto, casi has perdido, ya que no puedes cambiarlo.Una solución horrenda es establecer
src
un javascript: URL (¡urgh!):iframe.src= "javascript:'<html><body><p>Hello<\/p><script>do things;<\/script>'";
Pero por alguna razón, un documento de este tipo no puede establecer el suyo
document.domain
desde un script en IE (el viejo "error no especificado"), por lo que no puede usarlo para recuperar un puente entre el padre (*). Usted podría utilizarlo para escribir todo el documento HTML, suponiendo que el widget no necesita hablar con su documento de nivel superior una vez que se crea una instancia.Sin embargo, las URL de JavaScript de iframe no funcionan en Safari, por lo que aún necesitaría algún tipo de rastreo del navegador para elegir qué método usar.
*: Por alguna otra razón, puede , en IE, establecer
document.domain
desde un segundo documento, documento escrito por el primer documento. Entonces esto funciona:if (isIE) iframe.src= "javascript:'<script>window.onload=function(){document.write(\\'<script>document.domain=\\\""+document.domain+"\\\";<\\\\/script>\\');document.close();};<\/script>'";
En este punto, el nivel de horror es demasiado alto para mí, estoy fuera. Haría el HTML externo como dijo David.
fuente
void()
llamada, ya que la función ya regresaundefined
.Bueno, sí, la excepción de acceso se debe al hecho de que
document.domain
debe coincidir en su padre y en su iframe, y antes de que lo hagan, no podrá establecer mediante programación ladocument.domain
propiedad de su iframe.Creo que su mejor opción aquí es apuntar la página a una plantilla propia:
iframe.src = '/myiframe.htm#' + document.domain;
Y en myiframe.htm:
document.domain = location.hash.substring(1);
fuente
bueno, en realidad tengo un problema muy similar, pero con un giro ... digamos que el sitio de nivel superior es a.foo.com - ahora configuro el dominio del documento en a.foo.com
luego, en el iframe que creo / tengo, también lo configuro a.foo.com
tenga en cuenta que no puedo configurarlos también foo.com porque hay otro iframe en la página que apunta a bafoo.com (que nuevamente usa a.foo.com pero no puedo cambiar el código del script allí)
notará que esencialmente estoy configurando document.domain a lo que ya sería de todos modos ... pero tengo que hacer eso para acceder al otro iframe que mencioné de bafoo.com
dentro de mi marco, después de configurar el dominio, aunque todos los iframes tienen la misma configuración, sigo recibiendo un error al llegar al padre en IE 6/7
hay otras cosas que son realmente bizaree
en el nivel exterior / superior, si espero su evento de carga y configuro un temporizador, eventualmente puedo alcanzar el marco al que necesito acceder ... pero nunca puedo alcanzar de abajo hacia arriba ... y realmente Necesito poder
Además, si configuro todo para que sea foo.com (que, como dije, no puedo hacer) ¡FUNCIONA! pero por alguna razón, cuando se usa el mismo valor que location.host ... no lo hace y me está matando ...
fuente
Solo lo uso
<iframe src="about:blank" ...></iframe>
y funciona bien.fuente
para IE, el puerto importa. Entre dominios, debería ser el mismo puerto.
fuente
¿Has probado jQuery.contents () ?
fuente
Parece que el problema con IE surge cuando intenta acceder al iframe a través del objeto document.frames; si almacena una referencia al iframe creado en una variable, entonces puede acceder al iframe inyectado a través de la variable (my_iframe en el código siguiente ).
Conseguí que esto funcione en IE6 / 7/8
var my_iframe; var iframeId = "my_iframe_name" if (navigator.userAgent.indexOf('MSIE') !== -1) { // IE wants the name attribute of the iframe set my_iframe = document.createElement('<iframe name="' + iframeId + '">'); } else { my_iframe = document.createElement('iframe'); } iframe.setAttribute("src", "javascript:void(0);"); iframe.setAttribute("scrolling", "no"); iframe.setAttribute("frameBorder", "0"); iframe.setAttribute("name", iframeId); var is = iframe.style; is.border = is.width = is.height = "0px"; if (document.body) { document.body.appendChild(my_iframe); } else { document.appendChild(my_iframe); }
fuente
Tuve un problema similar y mi solución fue este fragmento de código (probado en IE8 / 9, Chrome y Firefox)
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.src = 'javascript:void((function(){var script = document.createElement(\'script\');' + 'script.innerHTML = "(function() {' + 'document.open();document.domain=\'' + document.domain + '\';document.close();})();";' + 'document.write("<head>" + script.outerHTML + "</head><body></body>");})())'; iframe.contentWindow.document.write('<div>foo</div>');
He probado varios métodos, pero este parece ser el mejor. Puedes encontrar algunas explicaciones en la publicación de mi blog aquí .
fuente
Siguiendo el método extremadamente simple de Andralor aquí solucionó el problema para mí: https://github.com/fancyapps/fancyBox/issues/766
Básicamente, vuelva a llamar al iframe onUpdate:
$('a.js-fancybox-iframe').fancybox({ type: 'iframe', scrolling : 'visible', autoHeight: true, onUpdate: function(){ $("iframe.fancybox-iframe"); } });
fuente
IE funciona con iframe como todos los demás navegadores (al menos para las funciones principales). Solo tienes que seguir un conjunto de reglas:
cuando se cargan todos los recursos de iframe, cambie document.domain para que sea el mismo que el definido en parent. (Debe hacer esto más tarde porque la configuración del dominio hará que falle la solicitud del recurso iframe)
ahora puede hacer una referencia para la ventana principal: var winn = window.parent
fuente
Para mí, encontré que la mejor respuesta era verificar los permisos de archivo a los que se les niega el acceso.
Acabo de actualizar a jQuery-1.8.0.js y recibí el error Acceso denegado en IE9.
Desde el Explorador de Windows
Probó el sitio. No más problema.
Tuve que hacer lo mismo con el script jQuery-UI que acababa de actualizar también
fuente