otro - llamar javascript desde html
Invocar código JavaScript en un iframe desde la página principal (17)
Algunas de estas respuestas no tratan el problema de CORS, o no lo hacen obvio donde coloca los fragmentos de código para hacer posible la comunicación.
Aquí hay un ejemplo concreto. Diga que quiero hacer clic en un botón en la página principal y que haga algo dentro del iframe. Así es como lo haría.
parent_frame.html
<button id=''parent_page_button'' onclick=''call_button_inside_frame()''></button>
function call_button_inside_frame() {
document.getElementById(''my_iframe'').contentWindow.postMessage(''foo'',''*'');
}
iframe_page.html
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if(event) {
click_button_inside_frame();
}
}
function click_button_inside_frame() {
document.getElementById(''frame_button'').click();
}
Para ir a la otra dirección (haga clic en el botón dentro de iframe para llamar al método fuera de iframe) simplemente cambie la ubicación del fragmento de código en vivo, y cambie esto:
document.getElementById(''my_iframe'').contentWindow.postMessage(''foo'',''*'');
a esto:
window.parent.postMessage(''foo'',''*'')
Básicamente, tengo un iframe
incrustado en una página y el iframe
tiene algunas rutinas de JavaScript que necesito invocar desde la página principal.
Ahora lo contrario es bastante simple, ya que solo necesitas llamar a parent.functionName()
, pero desafortunadamente, necesito exactamente lo contrario a eso.
Tenga en cuenta que mi problema no es cambiar la URL de origen del iframe
, sino invocar una función definida en el iframe
.
Continuando con respuesta :
Para mayor robustez, usar de la siguiente manera:
var el = document.getElementById(''targetFrame'');
if(el.contentWindow)
{
el.contentWindow.targetFunction();
}
else if(el.contentDocument)
{
el.contentDocument.targetFunction();
}
Workd como encanto :)
El IFRAME debería estar en la colección frames[]
. Usa algo como
frames[''iframeid''].method();
En el IFRAME, haga pública su función al objeto de la ventana:
window.myFunction = function(args) {
doStuff();
}
Para acceder desde la página principal, use esto:
var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);
Es posible llamar a una función JS principal desde iframe
, pero solo cuando tanto la principal como la página cargada en el iframe
son del mismo dominio, es decir, abc.com, y ambas usan el mismo protocolo, es decir, ambas están en http://
o https://
.
La llamada fallará en los casos mencionados a continuación:
- La página principal y la página de iframe son de dominio diferente.
- Están utilizando diferentes protocolos, uno está en http: // y el otro está en https: //.
Cualquier solución a esta restricción sería extremadamente insegura.
Por ejemplo, imagine que registré el dominio superwinningcontest.com y envié enlaces a los correos electrónicos de las personas. Cuando cargaron la página principal, podría ocultar algunos iframe
s allí y leer su feed de Facebook, revisar las transacciones recientes de Amazon o PayPal, o, si utilizaban un servicio que no implementara suficiente seguridad, transferir dinero de sus cuentas. Es por eso que JavaScript está limitado al mismo dominio y al mismo protocolo.
Hay algunas peculiaridades a tener en cuenta aquí.
HTMLIFrameElement.contentWindow
es probablemente la forma más fácil, pero no es una propiedad estándar y algunos navegadores no lo admiten, en su mayoría los más antiguos. Esto se debe a que el estándar HTML de nivel 1 de DOM no tiene nada que decir sobre el objeto dewindow
.También puede probar
HTMLIFrameElement.contentDocument.defaultView
, que permiten un par de navegadores más antiguos pero IE no. Aun así, el estándar no dice explícitamente que recuperas el objeto de lawindow
, por la misma razón que en (1), pero puedes tomar algunas versiones adicionales del navegador aquí si te importa.window.frames[''name'']
devolver la ventana es la interfaz más antigua y, por lo tanto, más confiable. Pero luego tienes que usar un atributoname="..."
para poder obtener una trama por nombre, que es ligeramente feo /obsoleto/ de transición. (id="..."
sería mejor pero a IE no le gusta eso).window.frames[number]
también es muy confiable, pero conocer el índice correcto es el truco. Usted puede salirse con la suya, por ejemplo. Si sabes que solo tienes un iframe en la página.Es completamente posible que el iframe secundario no se haya cargado todavía, o que algo haya fallado para que sea inaccesible. Es posible que le resulte más fácil revertir el flujo de comunicaciones: es decir,
window.parent
iframe secundario notifique a su scriptwindow.parent
cuando haya terminado de cargarse y esté listo para volver awindow.parent
. Al pasar uno de sus propios objetos (por ejemplo, una función de devolución de llamada) al script principal, ese padre puede entonces comunicarse directamente con el script en el iframe sin tener que preocuparse de a qué HTMLIFrameElement está asociado.
He encontrado una solución bastante elegante.
Como dijo, es bastante fácil ejecutar el código ubicado en el documento principal. Y esa es la base de mi código, hacer justo lo contrario.
Cuando se carga mi iframe, llamo a una función ubicada en el documento principal, pasando como argumento una referencia a una función local, ubicada en el documento del iframe. El documento principal ahora tiene un acceso directo a la función del iframe a través de esta referencia.
Ejemplo:
En el padre:
function tunnel(fn) {
fn();
}
En el iframe:
var myFunction = function() {
alert("This work!");
}
parent.tunnel(myFunction);
Cuando se cargue el iframe, llamará a parent.tunnel (YourFunctionReference), que ejecutará la función recibida en el parámetro.
Así de simple, sin tener que lidiar con todos los métodos no estándares de los distintos navegadores.
Intenta solo parent.myfunction()
Lo mismo, pero de una forma un poco más fácil, será cómo actualizar la página principal desde la página dentro de iframe . Simplemente llame a la función de la página principal para invocar la función javascript para volver a cargar la página:
window.location.reload();
O haz esto directamente desde la página en iframe:
window.parent.location.reload();
Ambas obras
Quirksmode tenía un post en esto .
Como la página ahora está rota y solo se puede acceder a través de archive.org, la reproduje aquí:
IFrames
En esta página le ofrezco una breve descripción general del acceso a los iframes desde la página en la que están. No es de extrañar, hay algunas consideraciones de navegador.
Un iframe es un marco en línea, un marco que, aunque contiene una página completamente separada con su propia URL, se coloca dentro de otra página HTML. Esto da muy buenas posibilidades en diseño web. El problema es acceder al iframe, por ejemplo para cargar una nueva página en él. Esta página explica cómo hacerlo.
¿Marco u objeto?
La pregunta fundamental es si el iframe se ve como un marco o como un objeto.
- Como se explica en la Introducción a las páginas de marcos , si utiliza marcos, el navegador creará una jerarquía de marcos (
top.frames[1].frames[2]
y similares). ¿Encaja el iframe en esta jerarquía de cuadros? - ¿O el navegador ve un iframe como solo otro objeto, un objeto que tiene una propiedad src? En ese caso, tenemos que usar una llamada estándar de DOM (como
document.getElementById(''theiframe''))
para acceder a ella. En general, los navegadores permiten ambas vistas en iframes "reales" (codificados), pero no se puede acceder a los iframes generados como marcos.
Atributo NAME
La regla más importante es dar a cualquier iframe que cree un atributo de name
, incluso si también usa un id
.
<iframe src="iframe_page1.html"
id="testiframe"
name="testiframe"></iframe>
La mayoría de los navegadores necesitan el atributo de name
para hacer que el iframe sea parte de la jerarquía de cuadros. Algunos navegadores (especialmente Mozilla) necesitan la id
para hacer que el iframe sea accesible como un objeto. Al asignar ambos atributos al iframe, mantiene abiertas sus opciones. Pero el name
es mucho más importante que la id
.
Acceso
Puede acceder al iframe como un objeto y cambiar su src
o acceder al iframe como un marco y cambiar su location.href
.
document.getElementById (''iframe_id''). src = ''newpage.html''; frames [''iframe_name'']. location.href = ''newpage.html''; La sintaxis del cuadro es ligeramente preferible porque Opera 6 la admite pero no la sintaxis del objeto.
Accediendo al iframe
Por lo tanto, para una experiencia completa en varios navegadores, debe asignar un nombre al iframe y utilizar el
frames[''testiframe''].location.href
sintaxis. Por lo que sé, esto siempre funciona.
Accediendo al documento
Acceder al documento dentro del iframe es bastante simple, siempre que use el atributo name
. Para contar el número de enlaces en el documento en el iframe, haga los frames[''testiframe''].document.links.length
.
Iframes generados
Sin embargo, cuando genera un iframe a través del DOM W3C, el iframe no se ingresa inmediatamente en la matriz de frames
, y la sintaxis de frames[''testiframe''].location.href
no funciona de inmediato. El navegador necesita un poco de tiempo antes de que aparezca el iframe en la matriz, tiempo durante el cual no se puede ejecutar ningún script.
La sintaxis document.getElementById(''testiframe'').src
funciona bien en todas las circunstancias.
El atributo de target
de un enlace tampoco funciona con los iframes generados, excepto en Opera, a pesar de que le di a mi iframe generado un name
y una id
.
La falta de soporte de target
significa que debe usar JavaScript para cambiar el contenido de un iframe generado, pero como necesita JavaScript de todas formas para generarlo, no veo que esto sea un problema.
Tamaño del texto en iframes
Un curioso solo error del Explorer 6:
Cuando cambia el tamaño del texto a través del menú Ver, los tamaños de texto en iframes se cambian correctamente. Sin embargo, este navegador no cambia los saltos de línea en el texto original, por lo que parte del texto puede volverse invisible, o pueden ocurrir saltos de línea mientras que la línea aún puede contener otra palabra.
Si el iFrame y el documento que contiene están en un dominio diferente, los métodos publicados anteriormente podrían no funcionar, pero existe una solución:
Por ejemplo, si el documento A contiene un elemento iframe que contiene el documento B, y el script en el documento A llama a postMessage () en el objeto de la ventana del documento B, entonces se activará un evento de mensaje en ese objeto, marcado como originario de la ventana de El documento A. El guión en el documento A podría verse así:
var o = document.getElementsByTagName(''iframe'')[0];
o.contentWindow.postMessage(''Hello world'', ''http://b.example.org/'');
Para registrar un controlador de eventos para eventos entrantes, la secuencia de comandos usaría addEventListener () (o mecanismos similares). Por ejemplo, el script en el documento B podría verse así:
window.addEventListener(''message'', receiver, false);
function receiver(e) {
if (e.origin == ''http://example.com'') {
if (e.data == ''Hello world'') {
e.source.postMessage(''Hello'', e.origin);
} else {
alert(e.data);
}
}
}
Esta secuencia de comandos primero comprueba que el dominio es el dominio esperado y, a continuación, mira el mensaje, que muestra al usuario o responde enviando un mensaje al documento que lo envió en primer lugar.
a través de http://dev.w3.org/html5/postmsg/#web-messaging
Si queremos llamar a la página principal javascript desde el iframe que se generó a partir de la codificación. ex shadowbox o lightbox
window.parent.targetFunction ();
Siguiendo la respuesta de Nitin Bansal
y para aún más robustez:
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
y
...
var el = document.getElementById(''targetFrame'');
var frame_win = getIframeWindow(el);
if (frame_win) {
frame_win.targetFunction();
...
}
...
Solo para el registro, me he encontrado con el mismo problema hoy, pero esta vez la página estaba incrustada en un objeto, no en un iframe (ya que era un documento XHTML 1.1). Así es como funciona con los objetos:
document
.getElementById(''targetFrame'')
.contentDocument
.defaultView
.targetFunction();
(perdón por los feos saltos de línea, no cabía en una sola línea)
Suponga que el ID de su iFrame es "targetFrame" y la función que desea llamar es targetFunction()
:
document.getElementById(''targetFrame'').contentWindow.targetFunction();
También puede acceder al marco utilizando window.frames
lugar de document.getElementById
.
// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction();
Utilice lo siguiente para llamar a la función de un marco en la página principal
parent.document.getElementById(''frameid'').contentWindow.somefunction()
$("#myframe").load(function() {
alert("loaded");
});