Here is something armed with the Message API .
The idea is to have a reference to the parent window from the daughter window and a reference to the daughter window from the parent window.
In both cases we define a message handler: recibirMensajes(ev)
, and we hook the listening event to the corresponding document (parent / child) with
window.addEventListener("message", recibirMensajes, false);
The messages are sent as follows:
ventanaDestino.postMessage( elMensaje, elOrigen );
elMensaje
can be almost anything that can be serialized with the structured cloning algorithm .
elOrigen
is the domain from and to where messages can be sent / received, for tests use '*'
, then put the domain that goes.
I include sending text messages for both sides, I implement only the "message to modify attributes" of the father (from the child), because the inverse (from father to son) is the same mechanism.
The "message to modify attributes" is an object that carries an "action" and what things to "use for" or "modify with" the action.
In padre.html
there are 2 buttons with 2 messages, both of text (string)
- send a generic greeting (string)
- send the value of the input (string)
In hijo.html
there are 3 buttons with 3 more or less different messages:
- send a generic greeting (string)
- send an action (search) together with the value of the input (object)
- send an action (change) to modify the CSS of the father
In padre.html
the messages are printed if they are (string) and they are processed if they are (object) with a switch
for each action defined, and a pair of foreach
for each of the things in the action change.
In hijo.html
the messages are printed if they are (string) and the message is answered if the received text matches "I am your father".
Some ID's are repeated in father and son, it is only to show that they are two independent documents.
The code is quite commented, if there are any questions, please let me know and we will see it:
padre.html
<!-- https://es.stackoverflow.com/q/207601/81450 -->
<!-- Padre-->
<!DOCTYPE html>
<html>
<head>
<title>Emisor y Receptor Prueba</title>
</head>
<body>
<div style="width:45%; float:left;">
<h1>Claseee A</h1>
<h2 class="prueba">Ocultame iFreim!</h2>
<button id="elBotonSaludar">Saludar Iframe</button>
<p>
<input id="elTexto" name="elTexto" type="text" />
<!--Boton que genera la accion en el hijo -->
<button id="elBoton">Oprima porfavor (Desde parent)</button>
</p>
<br />
<div id="losMensajes"></div>
</div>
<iframe
id="elIframe" class="buscadoriframe"
src="hijo.html" width="45%"
height="320px;" style="float:left;"></iframe>
<script>
window.addEventListener("message", recibirMensajes, false);
function recibirMensajes(ev)
{
/*
// Para seguridad verificar el dominio de origen aqui
if (ev.origin !== "http://example.org:8080")
return;
//*/
// Mostramos por consola el origen, tipo y mensaje crudo
console.log(ev.origin, typeof ev.data, ev.data);
// Definimos como procesar los mensajes
// si es string lo añadimos como texto al div "losMensajes"
// intToRGB(hashCode(ev.data.accion)) es usado
// para colorear segun el texto
if('string'==typeof ev.data){
document.getElementById('losMensajes').innerHTML +=
'<span style="color:#'+intToRGB(hashCode(ev.data))+'">'+
'('+ev.origin+') dice:</span> ' +
ev.data + "<br/>";
}
// si es object buscamos que sea una accion y que hacer
if('object'==typeof ev.data){
// si accion esta definido y cosas no está vacío
// lo añadimos como texto al div "losMensajes"
// intToRGB(hashCode(ev.data.accion)) es usado
// para colorear segun la accion
if(ev.data.accion && ev.data.cosas){
document.getElementById('losMensajes').innerHTML +=
'<span style="color:#'+intToRGB(hashCode(ev.data.accion))+'">'+
'('+ev.origin+') dice:</span> ' +
ev.data.accion + " " +
JSON.stringify(ev.data.cosas) + "<br/>";
// aquí según el tipo de accion
// procesamos las cosas de manera diferente
switch (ev.data.accion){
// si es buscar, mentir
case 'buscar':
document.getElementById('losMensajes').innerHTML +=
"[*] Estoy buscando " + ev.data.cosas + "<br/>";
break;
// si es cambiar, buscar que cambiar y como
case 'cambiar':
document.getElementById('losMensajes').innerHTML +=
"[*] Estoy cambiando cosas<br/>";
// recorremos las cosas
for (var que in ev.data.cosas){
// hay una clase para agregar?
if (ev.data.cosas[que].clase){
// avisamos que hacemos
document.getElementById('losMensajes').innerHTML +=
'[**] agregandole la clase "' +
ev.data.cosas[que].clase + '" a "' + que + '"<br/>';
// lo hacemos :
// para cada elemento encontrado agregar la clase
document.querySelectorAll(que).forEach(function(el){
el.classList.add(ev.data.cosas[que].clase)
})
}
// hay estilos para cambiar?
if (ev.data.cosas[que].estilos){
// avisamos que hacemos
document.getElementById('losMensajes').innerHTML +=
'[**] agregandole estilos "' +
JSON.stringify(ev.data.cosas[que].estilos) + '" a "' + que + '"<br/>';
// lo hacemos :
// para cada elemento encontrado cambiar los estilos
document.querySelectorAll(que).forEach(function(el){
// cambiamos los estilos uno por uno
for(var e in ev.data.cosas[que].estilos) {
el.style[e] = ev.data.cosas[que].estilos[e];
}
})
}
}
break;
}
}
}
}
var soyTuHijo = document.getElementById('elIframe').contentWindow;
// Saludo Genérico
document.getElementById('elBotonSaludar').onclick = function(){
// Para seguridad definir el dominio de origen aqui en vez de '*'
soyTuHijo.postMessage(
"Hola Luke!",
'*'
);
}
// Mensaje personalizado :
// enviamos el valor del input como string
document.getElementById('elBoton').onclick = function(){
var mensajeParaEnviar = document.getElementById('elTexto').value;
// Para seguridad definir el dominio de origen aqui en vez de '*'
soyTuHijo.postMessage( mensajeParaEnviar, '*' );
}
//** extras **//
/* https://stackoverflow.com/a/3426956/1423096 */
function hashCode(str) { // java String#hashCode
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
}
function intToRGB(i){
var c = (i & 0x00FFFFFF)
.toString(16)
.toUpperCase();
return "00000".substring(0, 6 - c.length) + c;
}
</script>
</body>
</html>
hijo.html
<!-- https://es.stackoverflow.com/q/207601/81450 -->
<!--Hijo-->
<!DOCTYPE html>
<html>
<head>
<title>Emisor y Receptor Prueba</title>
</head>
<body>
<h1 class="prueba">Claseee L</h1>
<button id="elBotonSaludar">Saludar Parent</button>
<p>
<input id="laBusqueda" name="laBusqueda" type="text" />
<!--Boton que genera la accion en el padre -->
<button id="elBotonBuscar">1. Buscar (Desde iFrame)</button>
<button id="elOtroBoton">2. Oprima porfavor (Desde iFrame)</button>
</p>
<div id="losMensajes"></div>
<script>
window.addEventListener("message", recibirMensajes, false);
function recibirMensajes(ev)
{
/*
// Para seguridad verificar el dominio de origen aqui
if (ev.origin !== "http://example.org:8080")
return;
//*/
// Mostramos por consola el origen, tipo y mensaje crudo
console.log(ev.origin, typeof ev.data, ev.data);
// si es string lo añadimos como texto al div "losMensajes"
// intToRGB(hashCode(ev.data.accion)) es usado
// para colorear segun el texto
if('string'==typeof ev.data){
document.getElementById('losMensajes').innerHTML +=
'<span style="color:#'+intToRGB(hashCode(ev.data))+'">'+
'('+ev.origin+') dice:</span> ' +
ev.data + "<br/>";
}
// Definimos como procesar los mensajes
// si es string y es "soy tu padre", responder "Noooo"
// usamos el origen del evento como destinatario
if(
'string' == typeof ev.data &&
'soy tu padre' == ev.data.toLowerCase()
){
event.source.postMessage(
"Nooooo",
event.origin
);
}
}
// definimos destinatario
var soyTuPadre = window.parent;
// Saludo Genérico
document.getElementById('elBotonSaludar').onclick = function(){
soyTuPadre.postMessage("Hola Ancestro!", '*');
}
// Mensaje personalizado :
// enviamos un objeto con instruccion de "buscar" y el texto a buscar
document.getElementById('elBotonBuscar').onclick = function(){
var mensajeParaEnviar = {
accion : 'buscar',
cosas : document.getElementById('laBusqueda').value,
}
// Para seguridad definir el dominio de origen aqui en vez de '*'
soyTuPadre.postMessage( mensajeParaEnviar, '*' );
}
// Mensaje personalizado :
// enviamos un objeto con instruccion de "cambiar" y las cosas
document.getElementById('elOtroBoton').onclick = function(){
var mensajeParaEnviar = {
accion : 'cambiar',
cosas : {
'h1' : {
clase : 'cambiado',
estilos : {color : '#f00'},
},
'h2' : {
clase : 'cambiado',
estilos : {display : 'none'},
},
'div#losMensajes' : {
clase : 'otraclase',
estilos : {
border : '1px dashed red',
borderRadius : '10px',
padding : '5px',
margin : '5px'
},
}
},
}
// Para seguridad definir el dominio de origen aqui en vez de '*'
soyTuPadre.postMessage( mensajeParaEnviar, '*' );
}
//** extras **//
/* https://stackoverflow.com/a/3426956/1423096 */
function hashCode(str) { // java String#hashCode
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
}
function intToRGB(i){
var c = (i & 0x00FFFFFF)
.toString(16)
.toUpperCase();
return "00000".substring(0, 6 - c.length) + c;
}
</script>
</body>
</html>