1
1
2
- import React , { Component } from 'react' ;
3
- import { string , arrayOf } from 'prop-types' ;
2
+ import React from 'react' ;
4
3
import WebApiBridge from '@precor/web-api-bridge' ;
5
4
6
- // to keep track of created iframes that use webApiBridges
7
- const bridgedIframes = [ ] ;
5
+ // createLibInstance factory, libs use apis to communicate through a bridge
6
+ const createLibInstance = ( { webApiBridge, apis } ) => ( {
7
+ webApiBridge,
8
+ apis,
9
+ findApiOfType ( apiName ) {
10
+ return this . webApiBridge . apis . find ( api => ( api instanceof apiMap [ apiName ] ) ) ;
11
+ } ,
12
+ } ) ;
13
+
14
+ // to keep track of created libs that use apis to communicate
15
+ class libInstances {
16
+ static instances = [ ] ;
17
+
18
+ static add = libInstance => libInstances . instances . push ( libInstance ) ;
19
+
20
+ static executeOnType = ( apiName , fn ) => {
21
+ libInstances . instances . forEach ( ( instance ) => {
22
+ const api = instance . findApiOfType ( apiName ) ;
23
+ if ( api ) fn ( api ) ;
24
+ } ) ;
25
+ }
26
+ }
8
27
9
28
class Common {
10
29
setSend = ( send ) => {
@@ -19,6 +38,7 @@ class Common {
19
38
this . send ( 'displayGrayscale' , [ grayScale ] , false ) ;
20
39
} ;
21
40
}
41
+
22
42
class Api1 {
23
43
setSend = ( send ) => {
24
44
this . send = send ;
@@ -35,15 +55,8 @@ class Api2 {
35
55
} ;
36
56
37
57
photoClicked = ( id ) => {
38
- const api1Iframe = bridgedIframes . find ( bridgedIframe => (
39
- bridgedIframe . props . type === 'LibType1'
40
- ) ) ;
41
- api1Iframe . getApiOfType ( 'Api1' ) . photoSelected ( id ) ;
42
- bridgedIframes . forEach ( ( bridgedIframe ) => {
43
- if ( bridgedIframe . send !== this . send && bridgedIframe . props . type === 'LibType2' ) {
44
- bridgedIframe . getApiOfType ( 'Api2' ) . displayNewPhoto ( ) ;
45
- }
46
- } ) ;
58
+ libInstances . executeOnType ( 'Api1' , api => api . photoSelected ( id ) ) ;
59
+ libInstances . executeOnType ( 'Api2' , ( api ) => { if ( api !== this ) api . displayNewPhoto ( ) ; } ) ;
47
60
} ;
48
61
49
62
displayNewPhoto = ( ) => {
@@ -57,81 +70,56 @@ class Api3 {
57
70
} ;
58
71
59
72
setGrayscale = ( grayscale ) => {
60
- bridgedIframes . forEach ( ( bridgedIframe ) => {
61
- bridgedIframe . getApiOfType ( 'Common' ) . displayGrayscale ( grayscale ) ;
62
- } ) ;
73
+ libInstances . executeOnType ( 'Common' , api => api . displayGrayscale ( grayscale ) ) ;
63
74
} ;
64
75
65
76
setBlur = ( blur ) => {
66
- bridgedIframes . forEach ( ( bridgedIframe ) => {
67
- bridgedIframe . getApiOfType ( 'Common' ) . displayBlur ( blur ) ;
68
- } ) ;
77
+ libInstances . executeOnType ( 'Common' , api => api . displayBlur ( blur ) ) ;
69
78
} ;
70
79
}
71
80
72
81
const apiMap = {
73
82
Common, Api1, Api2, Api3,
74
83
} ;
75
84
76
- class BridgedIframe extends Component {
77
- setIframe = ( iframe ) => {
78
- if ( ! iframe || this . iframe ) {
79
- return ;
80
- }
81
- this . iframe = iframe ;
82
- const { src, type, apis } = this . props ;
85
+ const BridgedIframe = ( {
86
+ src, type, apis, ...rest
87
+ } ) => {
88
+ console . log ( `render iframe: ${ src } ` ) ;
83
89
90
+ const setIframe = ( iframe ) => {
84
91
const url = new URL ( src ) ;
85
- this . webApiBridge = new WebApiBridge ( ) ;
86
- this . webApiBridge . origin = url . origin ;
87
- this . webApiBridge . targetOrigin = url . origin ;
88
- this . send = this . webApiBridge . send . bind ( this . webApiBridge ) ;
89
- bridgedIframes . push ( this ) ;
90
- this . webApiBridge . target = iframe . contentWindow ;
92
+ const webApiBridge = new WebApiBridge ( ) ;
93
+ webApiBridge . origin = url . origin ;
94
+ webApiBridge . targetOrigin = url . origin ;
95
+ const send = webApiBridge . send . bind ( webApiBridge ) ;
96
+ libInstances . add ( createLibInstance ( { webApiBridge , apis } ) ) ;
97
+ webApiBridge . target = iframe . contentWindow ;
91
98
window . addEventListener ( 'message' , ( event ) => {
92
- if ( event && event . source === this . webApiBridge . target ) {
93
- this . webApiBridge . onMessage ( event , event . data ) ;
99
+ if ( event && event . source === webApiBridge . target ) {
100
+ webApiBridge . onMessage ( event , event . data ) ;
94
101
}
95
102
} ) ;
96
- this . webApiBridge . apis = apis . map ( ( apiClassName ) => {
103
+ webApiBridge . apis = apis . map ( ( apiClassName ) => {
97
104
const api = new apiMap [ apiClassName ] ( ) ;
98
- api . setSend ( this . send ) ;
105
+ api . setSend ( send ) ;
99
106
return api ;
100
107
} ) ;
101
- this . iframe . onload = ( ) => {
108
+ iframe . onload = ( ) => {
102
109
console . log ( `${ iframe . src } loaded` ) ;
103
- this . send ( 'ready' , [ { type, apis } ] , false ) ;
110
+ send ( 'ready' , [ { type, apis } ] , false ) ;
104
111
} ;
105
112
} ;
106
113
107
- getApiOfType = apiName => (
108
- this . webApiBridge . apis . find ( api => (
109
- api instanceof apiMap [ apiName ]
110
- ) )
114
+ return (
115
+ < iframe
116
+ src = { src }
117
+ title = { src }
118
+ ref = { ( iframe ) => { setIframe ( iframe ) ; } }
119
+ scrolling = "no"
120
+ { ...rest }
121
+ />
111
122
) ;
112
-
113
- render ( ) {
114
- const {
115
- src, type, apis, ...rest
116
- } = this . props ;
117
- console . log ( `render iframe: ${ src } ` ) ;
118
-
119
- return (
120
- < iframe
121
- src = { src }
122
- title = { src }
123
- ref = { ( iframe ) => { this . setIframe ( iframe ) ; } }
124
- scrolling = "no"
125
- { ...rest }
126
- />
127
- ) ;
128
- }
129
- }
130
-
131
- BridgedIframe . propTypes = {
132
- src : string . isRequired ,
133
- type : string . isRequired ,
134
- apis : arrayOf ( string ) . isRequired ,
135
123
} ;
136
124
137
125
export default BridgedIframe ;
0 commit comments