main/Messenger.js

/**
 * Module to receive and send post window messages
 *
 */

const Messenger = {
	receiverSelector: '[data-iframe-receiver]',

	registry: {},

	isListening: false,

	/**
	 * Bind window event listener for post messages
	 * if receiver iframes exists
	 *
	 * @method init
	 */
	init() {
		const $receivers = document.querySelectorAll( this.receiverSelector );

		if ( $receivers.length > 0 ) {
			this.startListening();
		}
	},

	/**
	 * Start listening to window messages when not already done so.
	 */
	startListening() {
		if ( ! this.isListening ) {
			window.addEventListener( 'message', evt => this.receiveMessage( evt ) );
			this.isListening = true;
		}
	},

	/**
	 * Register receiver for receiving iframe messages
	 *
	 * @method registerReceiver
	 * @param {string} eventType - event type, e.g. gnca_video, gnca-iframe
	 * @param {object} receiver - an object with a receiveMessage() function for
	 * receiving messages from the iframe
	 */
	registerReceiver( eventType, receiver ) {
		// Ensure messenger listens to window message events
		// There might be the case where listening has not started when ther's no
		// data-iframe-receiver elements on page load
		this.startListening();

		if ( ! this.registry[eventType]) {
			this.registry[eventType] = [];
		}
		this.registry[eventType].push( receiver );
	},

	/**
	 * Post message to an iframe with the specified iframe id
	 *
	 * @method sendMessage
	 * @param {string} iframeId - iframe ID
	 * @param {string} eventType - event type, e.g. gnca_video, gnca-iframe
	 * @param {string} eventAction - action sent to the iframe
	 */
	sendMessage( iframeId, eventType, eventAction ) {
		if ( iframeId ) {
			const $iframe = document.querySelector( `#${iframeId}` );
			if ( $iframe ) {
				$iframe.contentWindow.postMessage(
					{ type: eventType, action: eventAction },
					`${window.location.protocol}//${window.location.hostname}`,
				);
			}
		}
	},

	/**
	 * Receive messages posted from an iframe,
	 * pass on the message to registered receivers
	 *
	 * @method receiveMessage
	 * @param {Object} event - Event object received from child iframe post message
	 */
	receiveMessage( event ) {
		if ( event && event.data ) {
			if ( this.registry[event.data.type]) {
				[].forEach.call( this.registry[event.data.type], ( receiver ) => {
					if ( receiver.receiveMessage ) {
						receiver.receiveMessage( event.data );
					}
				});
			}
		}
	},
};

export default Messenger;