ifcom

An Observable based wrapper around iframe postMessage

Usage no npm install needed!

<script type="module">
  import ifcom from 'https://cdn.skypack.dev/ifcom';
</script>

README

IFCom - "Inter iFrame Comms made easy"

IFCom

This is a observable+promise wrapper around the window.postMessage.

The main reason that we created this was to make the communication between the iframe and the parent easier. One of the issues that annoys you when dealing with the native window.addEventListener('message',callback) is that the callback function will be fired for every unrelated message that is being posted, which is definitely not what you want.

Features :

  • Your iframe only receives the messages that are related to it, ignoring all the other ones
  • If parent sends a message, while the iframe is not ready to receive yet, IFCom guaranties that those messages will be delivered.
  • A promise will be returned for every message, so you know when the iframe ( or parent) has received the message
  • Dynamically injects a loading indicator until the iframe's content is ready, and it can be customized.
  • The messages are rxjs streams, so you can apply all the rxjs operators and goodies.
  • The api for both parent and the child are identical, making it easier to maintain and manage.
  • Mixins are available to be applied on top of the IFCom to make it more restricted, if you don't have any typing available.

📖 Getting started

npm install --save ifcom / yarn add ifcom

💻 How to use :

In order to communicate between two windows, for now we're assuming that one is always the parent and one is the child.

This is how the parent would look like :

Inside your html

<iframe #id="iframe" sre="http://www.your-child-app.com"></iframe>

Inside your JS

import {IFCom} from 'ifcom';

const iframeElement = document.querySelector('#iframe');
const ifcom - new IFCom(iframeElement);

Note : The first parameter of the IFCom class is either the iframe element (for parent page) or the parent window ( for child) The second argument is the origin, which in our case is http://www.your-child-app.com. When instantiating the IFCom inside the parent, IFCom will extract the origin from the iframe element, if you don't want this, you could provide it yourself :

const ifcom - new IFCom(iframeElement , 'http://www.your-child-app.com');


This is how the child (the iframe's JS) would look like:

Inside your JS

import {IFCom} from 'ifcom';
const ifcom - new IFCom();

Note : Inside the child, there's no need to provide any arguments. This is because IFCom knows that we're inside an iframe and uses the parent by default, unless overriden Also the origin is being extraced from the document.referrer || document.location.href; You can override it otherwise , like bellow.

const ifcom - new IFCom(parent, 'http://www.your-parent-app-url.com');


🤔 How to send messages

Let's say the parent is sending this message :

ifcom.post({
        userInfo:{name:'Milad'}
    })
    .then((delivered)=>{
        // post will return a promise which is resolved when the parent/child has received the message:
    })
    .catch(()=>{
        // if message is not delivered after a timeout, you'll get an error
    })

IFCom uses rxjs Observables for streaming internally, the syntax is identical in both parent or child:

So the child can subscribe to the message :

ifcom.on(['userInfo']).subscribe(({userInfo})=>{
    console.log('name',userInfo.name)
})

NOTE on method accepts an array which is an object path ( like ['person','body','height']) to the message ( like lodash's get method), for example :

So if the parent is sending bellow object, :

ifcom.post({
   context:{
      user:{
        name:'Milad'
      }
   }
});

Child can subscribe to the user part only like this :

ifcom.on(['context','user']).subscribe(({user})=>{
    console.log('name',user.name);
})

Also, on can be used without providing any path, in this case, you'll receive all the messages

ifcom.on().subscribe((message)=>{
    console.log('Various messages sent by parent',message);
})

Mixins

We assume that there will be some messages that are frequently repeated and it would be nice to have a method for them. For these kinda messages, there's a folder called mixins which has multiple mixins that can be applied on top of the IFCom. To activate each of those, just import them, like below :

Let's say the child is going to pass the click events up to it's parent :

// first import the dom-event.mixins : 

import 'ifcom/dist/mixins/dom-event.mixins';

// now, The IFCom class has all the methods that are available inside the dom-event mixin.


childIcom.click($clickEvent, 'some extra parameters', 'and more parameters') 

And inside the parent, we should have :


import 'ifcom/dist/mixins/dom-event.mixins';
igIncom.onClick().subscribe(({event,args}) => {
    console.log('click event', event);
    console.log('click args', ...args);
})

// Or, we can even subscribe to all the domEvents
  
ifcom.onDomEvent($event).subscribe(({DOMEvent}})=>{
    // event will look like:
        DOMEvent === { name: 'click', event, args: ...   }
   })

License MIT.