iframe.io 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +9 -9
- package/package.json +4 -10
- package/src/index.ts +208 -0
- package/src/types/index.d.ts +52 -0
package/dist/index.js
CHANGED
|
@@ -62,11 +62,11 @@ var IFrameIO = /** @class */ (function () {
|
|
|
62
62
|
// Handshake or availability check events
|
|
63
63
|
if (_event == 'pong') {
|
|
64
64
|
// Content Window is connected to iframe
|
|
65
|
-
_this.
|
|
65
|
+
_this.fire('connect');
|
|
66
66
|
return _this.debug("[".concat(_this.peer.type, "] connected"));
|
|
67
67
|
}
|
|
68
|
-
//
|
|
69
|
-
_this.
|
|
68
|
+
// Fire available event listeners
|
|
69
|
+
_this.fire(_event, payload, callback);
|
|
70
70
|
}, false);
|
|
71
71
|
this.debug("[".concat(this.peer.type, "] Initiate connection: IFrame origin <").concat(iframeOrigin, ">"));
|
|
72
72
|
this.emit('ping');
|
|
@@ -101,15 +101,15 @@ var IFrameIO = /** @class */ (function () {
|
|
|
101
101
|
if (_event == 'ping') {
|
|
102
102
|
_this.emit('pong');
|
|
103
103
|
// Iframe is connected to content window
|
|
104
|
-
_this.
|
|
104
|
+
_this.fire('connect');
|
|
105
105
|
return _this.debug("[".concat(_this.peer.type, "] connected"));
|
|
106
106
|
}
|
|
107
|
-
//
|
|
108
|
-
_this.
|
|
107
|
+
// Fire available event listeners
|
|
108
|
+
_this.fire(_event, payload, callback);
|
|
109
109
|
}, false);
|
|
110
110
|
return this;
|
|
111
111
|
};
|
|
112
|
-
IFrameIO.prototype.
|
|
112
|
+
IFrameIO.prototype.fire = function (_event, payload, callback) {
|
|
113
113
|
var _this = this;
|
|
114
114
|
// Volatile event
|
|
115
115
|
if (!this.Events[_event]
|
|
@@ -129,12 +129,12 @@ var IFrameIO = /** @class */ (function () {
|
|
|
129
129
|
// Once triggable event
|
|
130
130
|
_event += '--@once';
|
|
131
131
|
listeners = this.Events[_event];
|
|
132
|
-
// Delete once event listeners after
|
|
132
|
+
// Delete once event listeners after fired
|
|
133
133
|
delete this.Events[_event];
|
|
134
134
|
}
|
|
135
135
|
else
|
|
136
136
|
listeners = this.Events[_event];
|
|
137
|
-
//
|
|
137
|
+
// Fire listeners
|
|
138
138
|
listeners.map(function (fn) { return payload ? fn(payload, callbackFn) : fn(callbackFn); });
|
|
139
139
|
};
|
|
140
140
|
IFrameIO.prototype.emit = function (_event, payload, fn) {
|
package/package.json
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iframe.io",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Easy and friendly API to connect and interact between content window and its containing iframe",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
|
-
"types": "./src/
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"require": "./dist/index.js",
|
|
11
|
-
"types": "./src/index.d.ts"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
6
|
+
"types": "./src/types/*.d.ts",
|
|
14
7
|
"private": false,
|
|
15
8
|
"scripts": {
|
|
16
9
|
"compile": "rimraf ./dist && tsc",
|
|
@@ -27,7 +20,8 @@
|
|
|
27
20
|
"typescript": "^4.5.5"
|
|
28
21
|
},
|
|
29
22
|
"files": [
|
|
30
|
-
"dist/"
|
|
23
|
+
"dist/",
|
|
24
|
+
"src/"
|
|
31
25
|
],
|
|
32
26
|
"directories": {
|
|
33
27
|
"example": "example/",
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
|
|
2
|
+
import type {
|
|
3
|
+
Options,
|
|
4
|
+
RegisteredEvents,
|
|
5
|
+
Peer,
|
|
6
|
+
PeerType,
|
|
7
|
+
Message,
|
|
8
|
+
MessageData,
|
|
9
|
+
Listener,
|
|
10
|
+
CallbackFunction
|
|
11
|
+
} from './types'
|
|
12
|
+
|
|
13
|
+
function newObject( data: object ){
|
|
14
|
+
return JSON.parse( JSON.stringify( data ) )
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default class IFrameIO {
|
|
18
|
+
|
|
19
|
+
Events: RegisteredEvents
|
|
20
|
+
peer: Peer
|
|
21
|
+
options: Options
|
|
22
|
+
|
|
23
|
+
constructor( options: Options ){
|
|
24
|
+
|
|
25
|
+
if( options && typeof options !== 'object' )
|
|
26
|
+
throw new Error('Invalid Options')
|
|
27
|
+
|
|
28
|
+
this.options = options
|
|
29
|
+
this.Events = {}
|
|
30
|
+
this.peer = { type: 'IFRAME' }
|
|
31
|
+
|
|
32
|
+
if( options.type )
|
|
33
|
+
this.peer.type = options.type.toUpperCase() as PeerType
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
debug( ...args: any[] ){ this.options && this.options.debug && console.log( ...args ) }
|
|
37
|
+
|
|
38
|
+
initiate( contentWindow: MessageEventSource, iframeOrigin: string ){
|
|
39
|
+
// Establish a connection with an iframe containing in the current window
|
|
40
|
+
if( !contentWindow || !iframeOrigin )
|
|
41
|
+
throw new Error('Invalid Connection initiation arguments')
|
|
42
|
+
|
|
43
|
+
if( this.peer.type === 'IFRAME' )
|
|
44
|
+
throw new Error('Expect IFRAME to <listen> and WINDOW to <initiate> a connection')
|
|
45
|
+
|
|
46
|
+
this.peer.source = contentWindow as Window
|
|
47
|
+
this.peer.origin = iframeOrigin
|
|
48
|
+
|
|
49
|
+
window.addEventListener( 'message', ({ origin, data, source }) => {
|
|
50
|
+
// Check valid message
|
|
51
|
+
if( origin !== this.peer.origin
|
|
52
|
+
|| !source
|
|
53
|
+
|| typeof data !== 'object'
|
|
54
|
+
|| !data.hasOwnProperty('_event') ) return
|
|
55
|
+
|
|
56
|
+
const { _event, payload, callback } = data as Message['data']
|
|
57
|
+
this.debug( `[${this.peer.type}] Message: ${_event}`, payload || '' )
|
|
58
|
+
|
|
59
|
+
// Handshake or availability check events
|
|
60
|
+
if( _event == 'pong' ){
|
|
61
|
+
// Content Window is connected to iframe
|
|
62
|
+
this.fire('connect')
|
|
63
|
+
return this.debug(`[${this.peer.type}] connected`)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Fire available event listeners
|
|
67
|
+
this.fire( _event, payload, callback )
|
|
68
|
+
}, false )
|
|
69
|
+
|
|
70
|
+
this.debug(`[${this.peer.type}] Initiate connection: IFrame origin <${iframeOrigin}>`)
|
|
71
|
+
this.emit('ping')
|
|
72
|
+
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
listen( hostOrigin?: string ){
|
|
77
|
+
// Listening to connection from the content window
|
|
78
|
+
|
|
79
|
+
this.peer.type = 'IFRAME' // iframe.io connection listener is automatically set as IFRAME
|
|
80
|
+
this.debug(`[${this.peer.type}] Listening to connect${hostOrigin ? `: Host <${hostOrigin}>` : ''}`)
|
|
81
|
+
|
|
82
|
+
window.addEventListener( 'message', ({ origin, data, source }) => {
|
|
83
|
+
// Check host origin where event must only come from.
|
|
84
|
+
if( hostOrigin && hostOrigin !== origin )
|
|
85
|
+
throw new Error('Invalid Event Origin')
|
|
86
|
+
|
|
87
|
+
// Check valid message
|
|
88
|
+
if( !source
|
|
89
|
+
|| typeof data !== 'object'
|
|
90
|
+
|| !data.hasOwnProperty('_event') ) return
|
|
91
|
+
|
|
92
|
+
// Define peer source window and origin
|
|
93
|
+
if( !this.peer.source ){
|
|
94
|
+
this.peer = { ...this.peer, source: source as Window, origin }
|
|
95
|
+
this.debug(`[${this.peer.type}] Connect to ${origin}`)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Origin different from handshaked source origin
|
|
99
|
+
else if( origin !== this.peer.origin )
|
|
100
|
+
throw new Error('Invalid Origin')
|
|
101
|
+
|
|
102
|
+
const { _event, payload, callback } = data
|
|
103
|
+
this.debug( `[${this.peer.type}] Message: ${_event}`, payload || '' )
|
|
104
|
+
|
|
105
|
+
// Handshake or availability check events
|
|
106
|
+
if( _event == 'ping' ){
|
|
107
|
+
this.emit('pong')
|
|
108
|
+
|
|
109
|
+
// Iframe is connected to content window
|
|
110
|
+
this.fire('connect')
|
|
111
|
+
return this.debug(`[${this.peer.type}] connected`)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Fire available event listeners
|
|
115
|
+
this.fire( _event, payload, callback )
|
|
116
|
+
}, false )
|
|
117
|
+
|
|
118
|
+
return this
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fire( _event: string, payload?: MessageData['payload'], callback?: boolean ){
|
|
122
|
+
// Volatile event
|
|
123
|
+
if( !this.Events[ _event ]
|
|
124
|
+
&& !this.Events[ _event +'--@once'] )
|
|
125
|
+
return this.debug(`[${this.peer.type}] No <${_event}> listener defined`)
|
|
126
|
+
|
|
127
|
+
const callbackFn = callback ?
|
|
128
|
+
( error: boolean | string, ...args: any[] ): void => {
|
|
129
|
+
this.emit( _event +'--@callback', { error: error || false, args } )
|
|
130
|
+
return
|
|
131
|
+
} : undefined
|
|
132
|
+
let listeners: Listener[] = []
|
|
133
|
+
|
|
134
|
+
if( this.Events[ _event +'--@once'] ){
|
|
135
|
+
// Once triggable event
|
|
136
|
+
_event += '--@once'
|
|
137
|
+
listeners = this.Events[ _event ]
|
|
138
|
+
// Delete once event listeners after fired
|
|
139
|
+
delete this.Events[ _event ]
|
|
140
|
+
}
|
|
141
|
+
else listeners = this.Events[ _event ]
|
|
142
|
+
|
|
143
|
+
// Fire listeners
|
|
144
|
+
listeners.map( fn => payload ? fn( payload, callbackFn ) : fn( callbackFn ) )
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
emit( _event: string, payload?: MessageData['payload'], fn?: Listener ){
|
|
148
|
+
|
|
149
|
+
if( !this.peer.source )
|
|
150
|
+
throw new Error('No Connection initiated')
|
|
151
|
+
|
|
152
|
+
if( typeof payload == 'function' ){
|
|
153
|
+
fn = payload
|
|
154
|
+
payload = null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Acknowledge/callback event listener
|
|
158
|
+
let hasCallback = false
|
|
159
|
+
if( typeof fn === 'function' ){
|
|
160
|
+
const callbackFunction = fn as CallbackFunction
|
|
161
|
+
|
|
162
|
+
this.once( _event +'--@callback', ({ error, args }) => callbackFunction( error, ...args ) )
|
|
163
|
+
hasCallback = true
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
this.peer.source.postMessage( newObject({ _event, payload, callback: hasCallback }), this.peer.origin as string )
|
|
167
|
+
|
|
168
|
+
return this
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
on( _event: string, fn: Listener ){
|
|
172
|
+
// Add Event listener
|
|
173
|
+
if( !this.Events[ _event ] ) this.Events[ _event ] = []
|
|
174
|
+
this.Events[ _event ].push( fn )
|
|
175
|
+
|
|
176
|
+
this.debug(`[${this.peer.type}] New <${_event}> listener on`)
|
|
177
|
+
return this
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
once( _event: string, fn: Listener ){
|
|
181
|
+
// Add Once Event listener
|
|
182
|
+
_event += '--@once'
|
|
183
|
+
|
|
184
|
+
if( !this.Events[ _event ] ) this.Events[ _event ] = []
|
|
185
|
+
this.Events[ _event ].push( fn )
|
|
186
|
+
|
|
187
|
+
this.debug(`[${this.peer.type}] New <${_event} once> listener on`)
|
|
188
|
+
return this
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
off( _event: string, fn: Listener ){
|
|
192
|
+
// Remove Event listener
|
|
193
|
+
delete this.Events[ _event ]
|
|
194
|
+
typeof fn == 'function' && fn()
|
|
195
|
+
|
|
196
|
+
this.debug(`[${this.peer.type}] <${_event}> listener off`)
|
|
197
|
+
return this
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
removeListeners( fn: Listener ){
|
|
201
|
+
// Clear all event listeners
|
|
202
|
+
this.Events = {}
|
|
203
|
+
typeof fn == 'function' && fn()
|
|
204
|
+
|
|
205
|
+
this.debug(`[${this.peer.type}] All listeners removed`)
|
|
206
|
+
return this
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
export type * as IFrameIOTop from '..'
|
|
3
|
+
|
|
4
|
+
export type PeerType = 'WINDOW' | 'IFRAME'
|
|
5
|
+
|
|
6
|
+
export type CallbackFunction = ( error: boolean | string, ...args: any[] ) => void
|
|
7
|
+
export type Listener = ( payload?: any, callback?: CallbackFunction ) => void
|
|
8
|
+
|
|
9
|
+
export type Options = {
|
|
10
|
+
type?: PeerType
|
|
11
|
+
debug?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface RegisteredEvents {
|
|
15
|
+
[index: string]: Listener[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type Peer = {
|
|
19
|
+
type: PeerType
|
|
20
|
+
source?: Window
|
|
21
|
+
origin?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type MessageData = {
|
|
25
|
+
_event: string
|
|
26
|
+
payload: any
|
|
27
|
+
callback: boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type Message = {
|
|
31
|
+
origin: string
|
|
32
|
+
data: MessageData,
|
|
33
|
+
source: Window
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export interface IFrameIOClass {
|
|
38
|
+
Events: RegisteredEvents
|
|
39
|
+
peer: Peer
|
|
40
|
+
options: Options
|
|
41
|
+
|
|
42
|
+
// constructor: ( options: Options ) => void
|
|
43
|
+
debug: ( ...args: any[] ) => void
|
|
44
|
+
initiate: ( contentWindow: MessageEventSource, iframeOrigin: string ) => this
|
|
45
|
+
listen: ( hostOrigin?: string ) => this
|
|
46
|
+
fire: ( _event: string, payload?: MessageData['payload'], callback?: boolean ) => void
|
|
47
|
+
emit: ( _event: string, payload?: MessageData['payload'], fn?: Listener ) => void
|
|
48
|
+
on: ( _event: string, fn: Listener ) => void
|
|
49
|
+
once: ( _event: string, fn: Listener ) => void
|
|
50
|
+
off: ( _event: string, fn: Listener ) => void
|
|
51
|
+
removeListeners: ( fn: Listener ) => void
|
|
52
|
+
}
|