Files
talk/client/coral-framework/services/postMessage.js
T
Chi Vinh Le 918ce04e83 fix jsdoc 2
2018-02-26 22:51:46 +01:00

88 lines
2.3 KiB
JavaScript

import set from 'lodash/set';
import has from 'lodash/has';
import get from 'lodash/get';
import remove from 'lodash/remove';
/**
* createPostMessage returns a service that deals with cross
* window communication using the postMessage API.
* @param {string} origin
* @param {string} scope
* @return {Object} postMessage service
*/
export function createPostMessage(origin, scope = 'client') {
// Store a reference to each listener added.
const listeners = {};
// withOriginCheck wraps a given handler for a messages event with a check to
// see if the origin matches.
const withOriginCheck = handler => {
return event => {
if (get(event, 'origin') !== origin) {
return;
}
if (get(event, 'data.scope') !== scope) {
return;
}
// Pass the handler the event details.
handler(event);
};
};
// withParseData will parse the data.
const withParseData = handler => {
return event => {
const data = get(event, 'data.data');
const name = get(event, 'data.name');
if (!data || !name) {
return;
}
handler({ data, name, event });
};
};
return {
post(name, data, target = window.opener) {
if (!target) {
return;
}
// Serialize the message to be sent via postMessage.
const msg = { name, data, scope };
// Send the message.
target.postMessage(msg, origin);
},
subscribe: (handler, target = window) => {
// If this handler is already attached to the target, detach it.
if (has(listeners, [target, handler])) {
this.unsubscribeFromMessages(handler, target);
}
// Wrap the listener with a origin check.
const listener = withOriginCheck(withParseData(handler));
// Save a reference to the compiled listener.
set(listeners, [target, handler], listener);
// Attach the listener to the target.
target.addEventListener('message', listener);
},
unsubscribe: (handler, target = window) => {
if (!has(listeners, [target, handler])) {
return;
}
const listener = get(listeners, [target, handler]);
// Remove the listener from the target.
target.removeEventListener('message', listener);
remove(listeners, [target, handler]);
},
};
}