mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 00:50:07 +08:00
88 lines
2.3 KiB
JavaScript
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]);
|
|
},
|
|
};
|
|
}
|