HTML5 - Cross Browser iframe postMessage - child to parent?

JavascriptHtml

Javascript Problem Overview


I've been following this tutorial - http://www.youtube.com/watch?v=R2hOvZ7bwXU, which explains how to use postMessage to securely pass a message between iframe and parent - you basically end up with something like this - http://html5demos.com/postmessage2

My problem is that I need it to work the opposite way round (child to parent) and don't know how to target the parent window.

this is my receiver code (in the parent):

function handleMsg(e) {
	if(e.origin == "http://uc.dialogue.net") {
		let blah = e.data;
		alert(blah);	
	} else {
		alert("error");
	}
}
addEventListener("message", handleMsg, true);

and this is the sender function that is triggered by a simple form (in child):

   let text = document.querySelector('.srchInput').value;
   window.parent.postMessage(text, "http://uc.dialogue.net");   

Should I be targeting the parent in a different way?

Cheers Paul

Javascript Solutions


Solution 1 - Javascript

var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

// Listen to message from child window
eventer(messageEvent,function(e) {
    var key = e.message ? "message" : "data";
    var data = e[key];
    //run function//
},false);

Got it to work with the above in the parent page and the following in the child page -    

parent.postMessage("loadMyOrders","*");  //  `*` on any domain         

Code copied from here.

Solution 2 - Javascript

Unpacked the accepted answer using newer ecma262 spec, and dropping ie8 support:

window.addEventListener('message', e => {
    const key = e.message ? 'message' : 'data';
    const data = e[key];

    // ...
},false);

Relevant documentation:

Solution 3 - Javascript

This is a React version based on Avindra Goolcharan's answer:

const MessageHandler = ({ allowedUrl, handleMessage }) => {
  useEffect(() => {
    const handleEvent = event => {
      const { message, data, origin } = event;
      if (origin === allowedUrl) {
        handleMessage(message || data);
      }
    };

    window.addEventListener('message', handleEvent, false);
    return function cleanup() {
      window.removeEventListener('message', handleEvent);
    };
  });

  return <React.Fragment />;
};

Where allowedUrl is the URL loaded within the iframe and handleMessage is a redux-connected function (or other form of state management) letting the rest of the app know about the received message.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDancerView Question on Stackoverflow
Solution 1 - JavascriptDancerView Answer on Stackoverflow
Solution 2 - JavascriptAvindra GoolcharanView Answer on Stackoverflow
Solution 3 - JavascriptshebaView Answer on Stackoverflow