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.

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>
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);.
Da notare che la comunicazione può avvenire sia dall'iframe verso la pagina sia dalla pagina verso l'iframe.

IFrame

L'HTML dell'iframe è questo

HTML: 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>
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.
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 eseguirlo

DOS / 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

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.
Tags:
HTML 554 JavaScript184 JSON31 NodeJs21
Potrebbe interessarti anche: