PostMessage in JavaScript (iframe)
Come si sa, le attuali impostazioni del browser, per motivi di sicurezza, limitano le possibilità di comunicazione tra una pagina HTML e un iframe contenuto nella stessa.
Per superare questo problema si può ricorrere alla API JavaScript window.postMessage.
Questo metodo permette di inviare dei messaggi tra le pagine, che possono essere catturati (window.addEventListener) tramite l'evento message.
Nell'esempio seguente si considera di avere la pagina principale che risponde all'indirizzo http://localhost:8080 e la pagina contenuta nell'iframe risponde a http://localhost:3000, quindi su un dominio differente.
la pagina riceve i messaggi inviati dall'iframe tramite window.addEventListener("message", fn) e a sua volta reinvia il messaggio all'iframe tramite event.source.postMessage(msg);.
dove tramite un timer JavaScript, ogni secondo, viene inviato un messaggio al parent tramite window.parent.postMessage(msg) ovvero la pagina principale.
Il messaggio è un oggetto serializzato in JSON.
In questo specifico caso il messaggio scambiato sono le dimensioni della finestra che il ricevente userà per adeguare l'altezza.
Per un esempio di utilizzo vedi iframe-resizer.
Per superare questo problema si può ricorrere alla API JavaScript window.postMessage.
Questo metodo permette di inviare dei messaggi tra le pagine, che possono essere catturati (window.addEventListener) tramite l'evento message.
Nell'esempio seguente si considera di avere la pagina principale che risponde all'indirizzo http://localhost:8080 e la pagina contenuta nell'iframe risponde a http://localhost:3000, quindi su un dominio differente.
Pagina principale
La pagina principale è questa:HTML: index.html - Pagina principale
<html>
<body>
<h1>Pagina principale</h1>
<div id="messaggio">...</div>
<iframe src="http://localhost:3000/iframe-page.html" style="width: 80%; height: 250px;"></iframe>
<script>
window.addEventListener("message", function (event) {
if (event.origin != 'http://127.0.0.1:3000' && event.origin != 'http://localhost:3000') {
// se arriva da un domino che non conosco ignoro il messaggio
console.error("messaggio ignorato");
return;
}
// event.data contiene il messaggio, una "stringa"
console.log("received from iframe: " + event.data);
// converto il messaggio in un oggetto
const msg = JSON.parse(event.data);
// lo visualizzo su questa pagina (principale)
document.getElementById("messaggio").innerHTML = msg.title + ": " + msg.actualTime;
// rimando un altro messaggio
const newMsg = { value: "Msg di ritorno: " + msg.actualTime };
event.source.postMessage(JSON.stringify(newMsg));
});
</script>
<p>
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage">Window.postMessage()</a>
</p>
</body>
</html>
Da notare che la comunicazione può avvenire sia dall'iframe verso la pagina sia dalla pagina verso l'iframe.
IFrame
L'HTML dell'iframe è questoHTML: iframe-page.html - Iframe
<html>
<body>
<h2>Pagina Iframe</h2>
<div id="messaggio-locale">...</div>
<hr>
<div id="messaggio-ritorno">...</div>
<script>
setInterval(() => {
const dt = Date();
// il messaggio deve essere stringa, se è un oggetto va poi serializzato
var msg = { title: "test invio messaggi", actualTime: dt };
// visualizzo la data e ora sulla pagina locale
document.getElementById("messaggio-locale").innerHTML = dt;
// serializzo il messaggio e lo invio
window.parent.postMessage(JSON.stringify(msg), "*");
}, 1000);
// gestione messaggio che arriva dalla pagina principale
window.addEventListener("message", function (event) {
console.log('origin', event.origin)
if (event.origin != 'http://127.0.0.1:8080' && event.origin != 'http://localhost:8080'
// se rimando il messaggio l'origin è se stesso
&& event.origin != 'http://127.0.0.1:3000' && event.origin != 'http://localhost:3000'
) {
// se arriva da un domino che non conosco ignoro il messaggio
//console.error("messaggio ignorato");
return;
}
// event.data contiene il messaggio, una "stringa"
console.log("received from main page: " + event.data);
// converto il messaggio in un oggetto
const msg = JSON.parse(event.data);
// lo visualizzo su questa pagina (iframe)
document.getElementById("messaggio-ritorno").innerHTML = msg.value;
});
</script>
</body>
</html>
Il messaggio è un oggetto serializzato in JSON.
Da notare che in entrambi i casi viene verificata la sorgente (URL) del messaggio prima di accettarlo.
Esecuzione
Per eseguire la demo creare i due file HTML e il seguente file start.bat nella stessa cartella ed eseguirloDOS / Batch file: start.bat
start http-server.cmd -p 3000 -o iframe-page.html
http-server.cmd -p 8080 -o index.html
Per funzionare richiede l'installazione di Node JS e del comando http-server tramite
npm install --global http-server
npm install --global http-server
Note
Questa tecnica di comunicazione tra pagina e iframe, è spesso usata nelle pagine responsive per permettere all'iframe, di ridimensionarsi in altezza in funzione della larghezza della pagina e/o del dispositivo, in modo da non avere scrollbar doppie.In questo specifico caso il messaggio scambiato sono le dimensioni della finestra che il ricevente userà per adeguare l'altezza.
Per un esempio di utilizzo vedi iframe-resizer.