Cómo acceder al iframe padre desde JavaScript

170

Bueno, tengo un IFrame, que llama a una misma página de dominio. Mi problema es que quiero acceder a cierta información de este Iframe principal desde esta página llamada (desde JavaScript). ¿Cómo puedo acceder a este Iframe?

Detalles: Hay varios Iframes como este, que pueden tener la misma página cargada, porque estoy programando un entorno de Windows. Tengo la intención de cerrar este Iframe, por eso necesito saber cuál debo cerrar desde su interior. Tengo una matriz que mantiene referencias a estos Iframes.

EDITAR: los iframes se generan dinámicamente

José Leal
fuente
incluso si los iframes se generan dinámicamente, puede asignar una nueva identificación única utilizando algún tipo de contador, finalmente no necesita conocer la identificación, pero puede buscar fácilmente, vea mi respuesta.
Akash Kava

Respuestas:

138

También puede establecer el nombre y la ID en valores iguales

<iframe id="frame1" name="frame1" src="any.html"></iframe>

así podrá usar el siguiente código dentro de la página secundaria

parent.document.getElementById(window.name);
Acuático
fuente
16
Tal vez no sea obvio para todos, pero con este método puede acceder a un objeto de biblioteca del padre (solo si el padre ya ha cargado la biblioteca). Ejemplo: acceda a jQuery con el padre. $ ('#
Something
1
Esta solución es compatible con el modo de peculiaridades de compatibilidad de IE5 +.
Slayner
Incluso en 2016, esto funciona muy bien como parte de una solución para el problema de que IE imprima el contenido de una iframeunidad demasiado pequeña. ¿Pero por qué funciona? window.namedevuelve una cadena ¿Qué tiene de diferente el uso window.nameque simplemente pasar el nombre de identificación como una cadena que no funciona)?
Karl
3
Hola, no se ejecuta con Chrome 59 ..: VM111: 1 DOMException no capturada: bloqueó un marco con origen " xxx " para que no acceda a un marco de origen cruzado.
Didier68
Chrome ve los archivos en la misma carpeta que el origen cruzado si no está configurado CORS. Dicen que es por seguridad. La configuración de CORS necesita un servidor. Envía a los usuarios un mensaje para configurar un servidor o cambiar el navegador si se detecta Chrome.
90

Simplemente llame window.frameElementdesde su página enmarcada. Si la página no está enmarcada, frameElementlo estará null.

La otra forma (obtener el elemento de ventana dentro de un marco es menos trivial) pero por razones de integridad:

/**
 * @param f, iframe or frame element
 * @return Window object inside the given frame
 * @effect will append f to document.body if f not yet part of the DOM
 * @see Window.frameElement
 * @usage myFrame.document = getFramedWindow(myFrame).document;
 */
function getFramedWindow(f)
{
    if(f.parentNode == null)
        f = document.body.appendChild(f);
    var w = (f.contentWindow || f.contentDocument);
    if(w && w.nodeType && w.nodeType==9)
        w = (w.defaultView || w.parentWindow);
    return w;
}
Ian Carter
fuente
2
¡Gracias! Funciona en IE 6+, FF y Chrome!
rustyx
11
window.frameElementregresa nullcuando window e iframe tienen dominios diferentes, es decir, mensajes de origen cruzado.
Qwerty
@Qwerty, ¿has encontrado alguna solución?
Ajay Patidar
@AjayPatidar Creo que me di por vencido. :(
Qwerty
78

Recomendaría usar la API postMessage .

En su iframe, llame a:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

En la página que incluye el iframe, puede escuchar eventos como este:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

Por cierto, también es posible hacer llamadas a otras ventanas, y no solo iframes.

Lea más sobre la API postMessage en el blog de John Resigs aquí

Kenneth Lynne
fuente
77
Creo que esta es claramente la mejor respuesta, el <iframe>contenido no tiene que saber nada sobre los padres y viceversa. Solo tienen que obedecer el simple mensaje del contrato. ¡Increíble!
mfeineis
1
El <iframe> todavía tiene que conocer el dominio de los padres, ¿verdad?
Homr Zodyssey
1
@HomrZodyssey El dominio principal solo está disponible como mecanismo de seguridad; si no lo conoce, puede configurarlo '*'.
Amir Ali Akbari
Uso '*'en clientes. Todas las demás soluciones dan un error en un navegador Chrome que trata los archivos en la carpeta de clientes como no del mismo origen porque un servidor no está configurado. Esta es la mejor y única solución: dyn-web.com/tutorials/iframes/postmessage
30

Antigua pregunta, pero acabo de tener este mismo problema y encontré una manera de obtener el iframe. Es simplemente una cuestión de iterar a través de la matriz frames [] de la ventana principal y probar la ventana contentWindow de cada marco contra la ventana en la que se está ejecutando su código. Ejemplo:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

O, usando jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

Este método guarda la asignación de una ID a cada iframe, lo cual es bueno en su caso, ya que se crean dinámicamente. No pude encontrar una forma más directa, ya que no puede obtener el elemento iframe usando window.parent: va directamente al elemento de la ventana principal (omitiendo el iframe). Por lo tanto, recorrerlos parece ser la única forma, a menos que desee usar ID.

ingrediente_15939
fuente
1
Actualización: esto no funcionó exactamente como se anuncia, y tuve que usar contentWindow.document === document. No tengo idea de por qué. También en algunos navegadores utilicé contentDocument. Bueno, eso me gusta!
Christophe
1
Disculpas, es cierto que solo lo probé en Firefox. :) Sin embargo, he tenido éxito al usar el método jQuery y contentWindow en varios navegadores.
ingrediente_15939
1
Actualización: descubrí que también puedes usar window.frameElement, pero no estoy seguro de qué navegadores lo admiten.
Christophe
2
No creo que este tipo de cosas funcione más; obtienes un error de origen cruzado.
Andrew Mao
@AndrewMao la pregunta es sobre los mismos documentos de origen, por lo que no hay razón para tener problemas de origen cruzado.
Christophe
21

puede usar parentpara acceder a la página principal. Entonces para acceder a una función sería:

var obj = parent.getElementById('foo');
kemiller2002
fuente
1
Kevin, el problema es CONOCER la identificación. Tengo varios Iframes, y quiero acceder a ellos desde el código interno
José Leal
Todavía obtengo "Bloqueado un marco con origen" other-localhost: 8000 "del acceso a un marco de origen cruzado".
user2568374
13

Una vez que se establece el id del iframe, puede acceder al iframe desde el documento interno como se muestra a continuación.

var iframe = parent.document.getElementById(frameElement.id);

Funciona bien en IE, Chrome y FF.

Akash Kava
fuente
Esto parece una forma complicada de hacerlovar iframe = frameElement
Oriol
frameElement devuelve el objeto en el contexto de la ventana actual, pero parent.document.getElementById (frameElement.id) devuelve el objeto en el contexto de la ventana principal, no puede ejecutar las funciones de JavaScript de la ventana principal con frameElement, pruébelo en jsfiddle y déme un ejemplo si puede .
Akash Kava
6

Tal vez solo use

window.parent

en su iframe para obtener el marco de llamada / ventanas. Si tenía un marco de llamada múltiple, puede usar

window.top
Clawfire
fuente
3

Pruebe esto, en su marco principal configure IFRAME como este:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

Tenga en cuenta que la identificación de cada fotograma se pasa como un ancla en el src.

luego, en su html interno, puede acceder a la identificación del marco en el que se carga a través de location.hash:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

entonces puede acceder a parent.document.getElementById () para acceder a la etiqueta iframe desde dentro del iframe

Mark Porter
fuente
Sí, esta sería la solución más lógica, pero a veces necesito cambiar el src del iframe ... y pasar este hash o el parámetro GET cada solicitud no es buena ...
José Leal
¿Por qué es malo pasar el hash cada vez? Solo es visible para el navegador, no para el servidor, y no afecta el almacenamiento en caché como lo haría un parámetro get.
Mark Porter
-1
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
    win = (win || window);
    var parentJQuery = window.parent.jQuery;
    var ifrms = parentJQuery("iframe.upload_iframe");
    for (var i = 0; i < ifrms.length; i++)
    {
        if (ifrms[i].contentDocument === win.document)
            return ifrms[i];
    }
    return null;
}
Alex
fuente