1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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;
}
|