1
1
import { Component } from "./component" ;
2
- import $ from "cash-dom" ;
3
2
import anim from "animejs" ;
4
3
import { M } from "./global" ;
5
4
6
- let _defaults = {
5
+ const _defaults = {
7
6
opacity : 0.5 ,
8
7
inDuration : 250 ,
9
8
outDuration : 250 ,
@@ -18,12 +17,13 @@ let _defaults = {
18
17
} ;
19
18
20
19
export class Modal extends Component {
20
+ el : HTMLElement ;
21
21
static _modalsOpen : number ;
22
22
static _count : number ;
23
23
isOpen : boolean ;
24
- id : any ;
24
+ id : string ;
25
25
private _openingTrigger : any ;
26
- $overlay : any ;
26
+ private _overlay : HTMLElement ;
27
27
private _nthModalOpened : number ;
28
28
private _handleOverlayClickBound : any ;
29
29
private _handleModalCloseClickBound : any ;
@@ -35,10 +35,11 @@ let _defaults = {
35
35
( this . el as any ) . M_Modal = this ;
36
36
this . options = { ...Modal . defaults , ...options } ;
37
37
this . isOpen = false ;
38
- this . id = this . $ el. attr ( 'id' ) ;
38
+ this . id = this . el . id ;
39
39
this . _openingTrigger = undefined ;
40
- this . $overlay = $ ( '<div class="modal-overlay"></div>' ) ;
41
- ( this . el as HTMLElement ) . tabIndex = 0 ;
40
+ this . _overlay = document . createElement ( 'div' ) ;
41
+ this . _overlay . classList . add ( 'modal-overlay' ) ;
42
+ this . el . tabIndex = 0 ;
42
43
this . _nthModalOpened = 0 ;
43
44
Modal . _count ++ ;
44
45
this . _setupEventHandlers ( ) ;
@@ -53,15 +54,15 @@ let _defaults = {
53
54
}
54
55
55
56
static getInstance ( el ) {
56
- let domElem = ! ! el . jquery ? el [ 0 ] : el ;
57
+ const domElem = ! ! el . jquery ? el [ 0 ] : el ;
57
58
return domElem . M_Modal ;
58
59
}
59
60
60
61
destroy ( ) {
61
62
Modal . _count -- ;
62
63
this . _removeEventHandlers ( ) ;
63
64
this . el . removeAttribute ( 'style' ) ;
64
- this . $overlay . remove ( ) ;
65
+ this . _overlay . remove ( ) ;
65
66
( this . el as any ) . M_Modal = undefined ;
66
67
}
67
68
@@ -71,76 +72,63 @@ let _defaults = {
71
72
if ( Modal . _count === 1 ) {
72
73
document . body . addEventListener ( 'click' , this . _handleTriggerClick ) ;
73
74
}
74
- this . $overlay [ 0 ] . addEventListener ( 'click' , this . _handleOverlayClickBound ) ;
75
+ this . _overlay . addEventListener ( 'click' , this . _handleOverlayClickBound ) ;
75
76
this . el . addEventListener ( 'click' , this . _handleModalCloseClickBound ) ;
76
77
}
77
78
78
79
_removeEventHandlers ( ) {
79
80
if ( Modal . _count === 0 ) {
80
81
document . body . removeEventListener ( 'click' , this . _handleTriggerClick ) ;
81
82
}
82
- this . $overlay [ 0 ] . removeEventListener ( 'click' , this . _handleOverlayClickBound ) ;
83
+ this . _overlay . removeEventListener ( 'click' , this . _handleOverlayClickBound ) ;
83
84
this . el . removeEventListener ( 'click' , this . _handleModalCloseClickBound ) ;
84
85
}
85
86
86
87
_handleTriggerClick ( e ) {
87
- let $trigger = $ ( e . target ) . closest ( '.modal-trigger' ) ;
88
- if ( $trigger . length ) {
89
- let modalId = M . getIdFromTrigger ( $trigger [ 0 ] ) ;
90
- let modalInstance = ( document . getElementById ( modalId ) as any ) . M_Modal ;
91
- if ( modalInstance ) {
92
- modalInstance . open ( $trigger ) ;
93
- }
94
- e . preventDefault ( ) ;
95
- }
88
+ const trigger = e . target . closest ( '.modal-trigger' ) ;
89
+ if ( ! trigger ) return ;
90
+ const modalId = M . getIdFromTrigger ( trigger ) ;
91
+ const modalInstance = ( document . getElementById ( modalId ) as any ) . M_Modal ;
92
+ if ( modalInstance ) modalInstance . open ( trigger ) ;
93
+ e . preventDefault ( ) ;
96
94
}
97
95
98
96
_handleOverlayClick ( ) {
99
- if ( this . options . dismissible ) {
100
- this . close ( ) ;
101
- }
97
+ if ( this . options . dismissible ) this . close ( ) ;
102
98
}
103
99
104
100
_handleModalCloseClick ( e ) {
105
- let $closeTrigger = $ ( e . target ) . closest ( '.modal-close' ) ;
106
- if ( $closeTrigger . length ) {
107
- this . close ( ) ;
108
- }
101
+ const closeTrigger = e . target . closest ( '.modal-close' ) ;
102
+ if ( closeTrigger ) this . close ( ) ;
109
103
}
110
104
111
105
_handleKeydown ( e ) {
112
106
// ESC key
113
- if ( e . keyCode === 27 && this . options . dismissible ) {
114
- this . close ( ) ;
115
- }
107
+ if ( e . keyCode === 27 && this . options . dismissible ) this . close ( ) ;
116
108
}
117
109
118
110
_handleFocus ( e ) {
119
111
// Only trap focus if this modal is the last model opened (prevents loops in nested modals).
120
112
if ( ! this . el . contains ( e . target ) && this . _nthModalOpened === Modal . _modalsOpen ) {
121
- ( this . el as HTMLElement ) . focus ( ) ;
113
+ this . el . focus ( ) ;
122
114
}
123
115
}
124
116
125
117
_animateIn ( ) {
126
- // Set initial styles
127
- $ . extend ( ( this . el as HTMLElement ) . style , {
128
- display : 'block' ,
129
- opacity : 0
130
- } ) ;
131
- $ . extend ( this . $overlay [ 0 ] . style , {
132
- display : 'block' ,
133
- opacity : 0
134
- } ) ;
118
+ // Set initial styles
119
+ this . el . style . display = 'block' ;
120
+ this . el . style . opacity = '0' ;
121
+ this . _overlay . style . display = 'block' ;
122
+ this . _overlay . style . opacity = '0' ;
135
123
// Animate overlay
136
124
anim ( {
137
- targets : this . $overlay [ 0 ] ,
125
+ targets : this . _overlay ,
138
126
opacity : this . options . opacity ,
139
127
duration : this . options . inDuration ,
140
128
easing : 'easeOutQuad'
141
129
} ) ;
142
130
// Define modal animation options
143
- let enterAnimOptions = {
131
+ const enterAnimOptions = {
144
132
targets : this . el ,
145
133
duration : this . options . inDuration ,
146
134
easing : 'easeOutCubic' ,
@@ -151,45 +139,38 @@ let _defaults = {
151
139
}
152
140
}
153
141
} ;
154
-
155
142
// Bottom sheet animation
156
143
if ( this . el . classList . contains ( 'bottom-sheet' ) ) {
157
- $ . extend ( enterAnimOptions , {
158
- bottom : 0 ,
159
- opacity : 1
160
- } ) ;
161
- anim ( enterAnimOptions ) ;
162
-
163
- // Normal modal animation
164
- } else {
165
- $ . extend ( enterAnimOptions , {
166
- top : [ this . options . startingTop , this . options . endingTop ] ,
167
- opacity : 1 ,
168
- scaleX : [ 0.8 , 1 ] ,
169
- scaleY : [ 0.8 , 1 ]
170
- } ) ;
171
- anim ( enterAnimOptions ) ;
144
+ enterAnimOptions [ 'bottom' ] = 0 ;
145
+ enterAnimOptions [ 'opacity' ] = 1 ;
146
+ }
147
+ // Normal modal animation
148
+ else {
149
+ enterAnimOptions [ 'top' ] = [ this . options . startingTop , this . options . endingTop ] ;
150
+ enterAnimOptions [ 'opacity' ] = 1 ;
151
+ enterAnimOptions [ 'scaleX' ] = [ 0.8 , 1 ] ;
152
+ enterAnimOptions [ 'scaleY' ] = [ 0.8 , 1 ] ;
172
153
}
154
+ anim ( enterAnimOptions ) ;
173
155
}
174
156
175
157
_animateOut ( ) {
176
158
// Animate overlay
177
159
anim ( {
178
- targets : this . $overlay [ 0 ] ,
160
+ targets : this . _overlay ,
179
161
opacity : 0 ,
180
162
duration : this . options . outDuration ,
181
163
easing : 'easeOutQuart'
182
164
} ) ;
183
-
184
165
// Define modal animation options
185
- let exitAnimOptions = {
166
+ const exitAnimOptions = {
186
167
targets : this . el ,
187
168
duration : this . options . outDuration ,
188
169
easing : 'easeOutCubic' ,
189
170
// Handle modal ready callback
190
171
complete : ( ) => {
191
- ( this . el as HTMLElement ) . style . display = 'none' ;
192
- this . $overlay . remove ( ) ;
172
+ this . el . style . display = 'none' ;
173
+ this . _overlay . remove ( ) ;
193
174
// Call onCloseEnd callback
194
175
if ( typeof this . options . onCloseEnd === 'function' ) {
195
176
this . options . onCloseEnd . call ( this , this . el ) ;
@@ -198,104 +179,78 @@ let _defaults = {
198
179
} ;
199
180
// Bottom sheet animation
200
181
if ( this . el . classList . contains ( 'bottom-sheet' ) ) {
201
- $ . extend ( exitAnimOptions , {
202
- bottom : '-100%' ,
203
- opacity : 0
204
- } ) ;
205
- anim ( exitAnimOptions ) ;
206
- // Normal modal animation
182
+ exitAnimOptions [ 'bottom' ] = '-100%' ;
183
+ exitAnimOptions [ 'opacity' ] = 0 ;
207
184
}
185
+ // Normal modal animation
208
186
else {
209
- $ . extend ( exitAnimOptions , {
210
- top : [ this . options . endingTop , this . options . startingTop ] ,
211
- opacity : 0 ,
212
- scaleX : 0.8 ,
213
- scaleY : 0.8
214
- } ) ;
215
- anim ( exitAnimOptions ) ;
187
+ exitAnimOptions [ 'top' ] = [ this . options . endingTop , this . options . startingTop ] ;
188
+ exitAnimOptions [ 'opacity' ] = 0 ;
189
+ exitAnimOptions [ 'scaleX' ] = 0.8 ;
190
+ exitAnimOptions [ 'scaleY' ] = 0.8 ;
216
191
}
192
+ anim ( exitAnimOptions ) ;
217
193
}
218
194
219
- open ( $trigger ) {
220
- if ( this . isOpen ) {
221
- return ;
222
- }
195
+ open ( trigger : HTMLElement | undefined ) : Modal {
196
+ if ( this . isOpen ) return ;
223
197
this . isOpen = true ;
224
198
Modal . _modalsOpen ++ ;
225
199
this . _nthModalOpened = Modal . _modalsOpen ;
226
-
227
200
// Set Z-Index based on number of currently open modals
228
- this . $overlay [ 0 ] . style . zIndex = 1000 + Modal . _modalsOpen * 2 ;
229
- ( this . el as HTMLElement ) . style . zIndex = ( 1000 + Modal . _modalsOpen * 2 + 1 ) . toString ( ) ;
230
-
201
+ this . _overlay . style . zIndex = ( 1000 + Modal . _modalsOpen * 2 ) . toString ( ) ;
202
+ this . el . style . zIndex = ( 1000 + Modal . _modalsOpen * 2 + 1 ) . toString ( ) ;
231
203
// Set opening trigger, undefined indicates modal was opened by javascript
232
- this . _openingTrigger = ! ! $trigger ? $trigger [ 0 ] : undefined ;
233
-
204
+ this . _openingTrigger = ! ! trigger ? trigger : undefined ;
234
205
// onOpenStart callback
235
206
if ( typeof this . options . onOpenStart === 'function' ) {
236
207
this . options . onOpenStart . call ( this , this . el , this . _openingTrigger ) ;
237
208
}
238
-
239
209
if ( this . options . preventScrolling ) {
240
210
document . body . style . overflow = 'hidden' ;
241
211
}
242
-
243
212
this . el . classList . add ( 'open' ) ;
244
- this . el . insertAdjacentElement ( 'afterend' , this . $overlay [ 0 ] ) ;
245
-
213
+ this . el . insertAdjacentElement ( 'afterend' , this . _overlay ) ;
246
214
if ( this . options . dismissible ) {
247
215
this . _handleKeydownBound = this . _handleKeydown . bind ( this ) ;
248
216
this . _handleFocusBound = this . _handleFocus . bind ( this ) ;
249
217
document . addEventListener ( 'keydown' , this . _handleKeydownBound ) ;
250
218
document . addEventListener ( 'focus' , this . _handleFocusBound , true ) ;
251
219
}
252
-
253
220
anim . remove ( this . el ) ;
254
- anim . remove ( this . $overlay [ 0 ] ) ;
221
+ anim . remove ( this . _overlay ) ;
255
222
this . _animateIn ( ) ;
256
-
257
223
// Focus modal
258
- ( this . el as HTMLElement ) . focus ( ) ;
224
+ this . el . focus ( ) ;
259
225
return this ;
260
226
}
261
227
262
228
close ( ) {
263
- if ( ! this . isOpen ) {
264
- return ;
265
- }
229
+ if ( ! this . isOpen ) return ;
266
230
this . isOpen = false ;
267
231
Modal . _modalsOpen -- ;
268
232
this . _nthModalOpened = 0 ;
269
-
270
233
// Call onCloseStart callback
271
234
if ( typeof this . options . onCloseStart === 'function' ) {
272
235
this . options . onCloseStart . call ( this , this . el ) ;
273
236
}
274
-
275
237
this . el . classList . remove ( 'open' ) ;
276
-
277
238
// Enable body scrolling only if there are no more modals open.
278
239
if ( Modal . _modalsOpen === 0 ) {
279
240
document . body . style . overflow = '' ;
280
241
}
281
-
282
242
if ( this . options . dismissible ) {
283
243
document . removeEventListener ( 'keydown' , this . _handleKeydownBound ) ;
284
244
document . removeEventListener ( 'focus' , this . _handleFocusBound , true ) ;
285
245
}
286
-
287
246
anim . remove ( this . el ) ;
288
- anim . remove ( this . $overlay [ 0 ] ) ;
247
+ anim . remove ( this . _overlay ) ;
289
248
this . _animateOut ( ) ;
290
249
return this ;
291
250
}
292
-
251
+
293
252
static {
294
253
Modal . _modalsOpen = 0 ;
295
254
Modal . _count = 0 ;
296
255
}
297
-
298
256
}
299
-
300
-
301
-
0 commit comments