aboutsummaryrefslogtreecommitdiffstats
path: root/src/base-pubsub.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/base-pubsub.ts')
-rw-r--r--src/base-pubsub.ts126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/base-pubsub.ts b/src/base-pubsub.ts
new file mode 100644
index 0000000..36b959a
--- /dev/null
+++ b/src/base-pubsub.ts
@@ -0,0 +1,126 @@
+declare const window: Window;
+
+export class BasePubSub {
+
+ subscribers: Map<string, ISubscriber>;
+ eventsCallbacks: Function[];
+ clientId: string;
+ eventsToWait: Map<string, string[]>;
+ lastEventNotified: string;
+
+ constructor(pluginId: string) {
+ this.subscribers = new Map<string, ISubscriber>();
+ this.eventsCallbacks = [];
+ this.eventsToWait = new Map<string, string[]>();
+ this.clientId = pluginId;
+ this.lastEventNotified = '';
+ this.onMessage = this.onMessage.bind(this);
+
+ window.addEventListener('message', this.onMessage);
+ }
+
+ public register(subscriberId: string, subscriberWindow: Window, subscriberUrl: string) {
+ const subscriber = {
+ window: subscriberWindow,
+ locationUrl: subscriberUrl || subscriberWindow.location.href
+ } as ISubscriber;
+
+ this.subscribers.set(subscriberId, subscriber);
+ }
+
+ public unregister(subscriberId: string) {
+ this.subscribers.delete(subscriberId);
+ }
+
+ public on(callback: Function) {
+ const functionExists = this.eventsCallbacks.find((func: Function) => {
+ return callback.toString() === func.toString();
+ });
+
+ if (!functionExists) {
+ this.eventsCallbacks.push(callback);
+ }
+ }
+
+ public off(callback: Function) {
+ const index = this.eventsCallbacks.indexOf(callback);
+ this.eventsCallbacks.splice(index, 1);
+ }
+
+ public notify(eventType: string, eventData?: any) {
+ const eventObj = {
+ type: eventType,
+ data: eventData,
+ originId: this.clientId
+ } as IPubSubEvent;
+
+ this.subscribers.forEach( (subscriber: ISubscriber, subscriberId: string) => {
+ subscriber.window.postMessage(eventObj, subscriber.locationUrl);
+ });
+
+ this.lastEventNotified = eventType;
+
+ return {
+ subscribe: function(callbackFn) {
+
+ if (this.subscribers.size !== 0) {
+ const subscribersToNotify = Array.from(this.subscribers.keys());
+
+ const checkNotifyComplete = (subscriberId: string) => {
+
+ const index = subscribersToNotify.indexOf(subscriberId);
+ subscribersToNotify.splice(index, 1);
+
+ if (subscribersToNotify.length === 0) {
+ callbackFn();
+ }
+ };
+
+ this.subscribers.forEach((subscriber: ISubscriber, subscriberId: string) => {
+ if (this.eventsToWait.has(subscriberId) &&
+ this.eventsToWait.get(subscriberId).indexOf(eventType) !== -1) {
+
+ const actionCompletedFunction = (actionCompletedEventData, subId = subscriberId) => {
+ if (actionCompletedEventData.type === 'ACTION_COMPLETED') {
+ checkNotifyComplete(subId);
+ }
+ this.off(actionCompletedFunction);
+
+ };
+ this.on(actionCompletedFunction);
+ } else {
+ checkNotifyComplete(subscriberId);
+ }
+ });
+ } else {
+ callbackFn();
+ }
+ }.bind(this)
+ };
+ }
+
+ public isWaitingForEvent(eventName: string): boolean {
+ return Array.from(this.eventsToWait.values()).some((eventsList: string[]) =>
+ eventsList.indexOf(eventName) !== -1
+ );
+ }
+
+ protected onMessage(event: any) {
+ if (this.subscribers.has(event.data.originId)) {
+ this.eventsCallbacks.forEach((callback: Function) => {
+ callback(event.data, event);
+ });
+ }
+ }
+}
+
+export interface IPubSubEvent {
+ type: string;
+ originId: string;
+ data: any;
+}
+
+export interface ISubscriber {
+ window: Window;
+ locationUrl: string;
+}