Demonstrating Cross-Domain Interaction with an Iframe

The example below demonstrates using postMessage to interact with a document in an iframe when that document is on another domain. Even though the Same Origin Policy prevents us from directly accessing objects and properties in the document, we can use postMessage to ask the document on the other domain to perform the tasks and provide the information we need.

Click the following buttons to interact with the iframe just below. The actions of the buttons are described in the iframe. The JavaScript for the example is displayed and described below the iframe.

This example demonstrates initiating action from the document containing the iframe: parent to iframe. A related example shows the iframed document initiating the action: iframe to parent.

JavaScript for the Example

Although this example performs the same tasks as that for same-domain cross-document communication, the JavaScript is much different.

The JavaScript displayed here is included in this document to perform the tasks demonstrated above. First we set up onclick handler functions for each of the buttons. With the exception of first button, each uses postMessage to instruct the document in the iframe which task to perform when it receives the message:

// check for browser support
if ( window.addEventListener ) {
    
    // when DOM is ready assign button onclick handlers
    window.addEventListener('DOMContentLoaded', function() {
        // where to send messages with postMessage
        var target_origin = 'http://www.example.com';
    
        // get reference to form to attach button onclick handlers
        var form = document.getElementById('demoForm');
        // get reference to iframe window
        var win = document.getElementById('ifrm').contentWindow;
        
        // set height of iframe and display value
        form.elements.button1.onclick = function() {
            var ifrm = document.getElementById('ifrm');
            var ht = ifrm.style.height = '160px';
            this.form.display.value = 'The iframe\'s height is: ' + ht;
        }
        
        // to increment and display counter variable in iframed document
        form.elements['button2'].onclick = function() {
            win.postMessage( {'task': 'ctr'}, target_origin );
        }
        
        // to get value of form element in iframed document
        form.elements.button3.onclick = function() {
            win.postMessage( {'task': 'val'}, target_origin );
        }
        
        // to invoke function in iframed document
        form.elements.button4.onclick = function() {
            win.postMessage( {'task': 'clear'}, target_origin );
        }
        
    }, false);
    
    // message handler
    window.addEventListener('message', function (e) {
        // check message origin
        if ( e.origin === 'http://www.example.com' ) {
            var task = e.data['task']; // task received in postMessage
            // get reference to demo form
            var form = document.getElementById('demoForm');
            
            switch ( task ) { // // postMessage tasks
                // display counter received in postMessage
                case 'ctr' :
                    form.display.value = 'counter in iframe is: ' + e.data['counter'];
                    break;
                
                // display text box value received in postMessage
                case 'val' :
                    form.display.value = 'The greeting is: ' + e.data['val'];
                    break;
                
                case 'clear' :
                    // nothing to do for this one
                    break;
                //default:
                    
            }
        }
    }, false);
    
    
} 

A function is assigned to the message event to display data returned from the iframed document related to the task it was asked to perform.

JavaScript in Iframed Document

The iframed document includes the following JavaScript to respond to messages sent from the containing document. A switch case is used to perform the task sent via postMessage.

// example variable and function for cross-document demo
counter = 0;

function clearGreeting() {
    document.forms['iframeDemoForm'].elements['greeting'].value = '';
}

// check for browser support
if ( window.addEventListener ) {
    // message handler
    window.addEventListener('message', function(e) {
        // check message origin
        if ( e.origin === 'http://www.dyn-web.com' ) {
            var task = e.data['task']; // task received in postMessage
            var msg; // for postMessage reply to e.source 
            
            switch ( task ) { // postMessage tasks
                // increment counter variable and send
                case 'ctr' :
                    msg = { 'task': 'ctr', 'counter': ++counter };
                    e.source.postMessage(msg , e.origin );
                    break;
                
                // send value of entry in text box (validate first)
                case 'val' :
                    var re = /[^-a-zA-Z!,'?\s]/g; // to filter out unwanted characters
                    var fld = document.forms['iframeDemoForm'].elements['greeting'];
                    var val = fld.value.replace(re, '');
                    var msg = {'task': 'val', 'val': val};
                    e.source.postMessage(msg , e.origin );
                    break;
                
                // clear text box by calling function
                case 'clear' :
                    clearGreeting();
                    break;
                
                //default:
            }
        }
    }, false);
}

See a related example that demonstrates the iframed document interacting with a containing document on another domain to request information about its objects and properties.