How do you share events accross windows on same domain?

1.3k views Asked by At

Suppose I have an iframe on my page and I have an event that can be triggered from either the parent or inside the frame but I need listeners on both pages to execute when either one is triggered. What is the best way to accomplish this?

Both pages are on the same domain so don't think I need to worry about same origin security policy issues.

I'm using jQuery but happy to go with naked JavaScript if required.

What I've tried so far, distilled to a simple example:

On parent:

HTML:

<input type="button" value="Click me"/>
<iframe src='child.html'/></iframe>

JS:

$(function() {
  var $iframe = $('iframe');
  $(document).on('custom_event', function() {
    alert('hello from parent!');
    $($iframe[0].contentWindow.document).trigger('custom_event');
  });
  $('input').on('click', function() {
    $(document).trigger('custom_event');
  });
});

On child:

HTML:

<input type="button" value="Click me too"/>

JS:

$(function() {
  $('input').on('click', function() {
    $(document).trigger('custom_event');
  });
  $(document).on('custom_event', function() {
    alert('hello from child!');
    $(window.parent.document).trigger('custom_event');
  });
});

I expect clicking either button to also trigger 'custom_event' in the other window. I.e in the parent to be able to trigger events in the frame via $iframe.contentWindow.document, and likewise in the frame to be able to trigger events via window.parent.document, but alas no! No errors, warnings or any other clues.

Am I doing something wrong, missing something obvious or is this just not possible?

1

There are 1 answers

1
Mark Simon On BEST ANSWER

I had the same scenario recently. The key is to find a high level DOM element that can be referenced by either the child or parent to dispatch the event on such as an app container div.

I had multiple iframes and so passed a "targetFrame" id so that only the correct one would execute given that all frames caught the event (best practice MVC loose coupling). You can also dynamically add any parameters you like.

Sample code for child iFrame to fire event to container:

var evt = document.createEvent('Event');
evt.initEvent('myEvent', true, true);
evt.targetFrame = "Frame1";
element = parent.document.getElementById('containerDiv'); // $('#containerDiv') for parent
element.dispatchEvent(evt);

Code for child iframe to listen for events:

parent.document.addEventListener('myEvent', function( evt) {
    if(evt.targetFrame == "Frame1") {
        // won't execute your code here in other frames.
    }
});

You just have to work out what "parent.document" reference works for your app.

Hope that helps.