@@ -61,14 +61,20 @@ const ignoreMouseEventsTimeout = 800;
61
61
/** Options that apply to all the event listeners that are bound by the ripple renderer. */
62
62
const passiveEventOptions = normalizePassiveListenerOptions ( { passive : true } ) ;
63
63
64
+ /** Events that signal that the pointer is down. */
65
+ const pointerDownEvents = [ 'mousedown' , 'touchstart' ] ;
66
+
67
+ /** Events that signal that the pointer is up. */
68
+ const pointerUpEvents = [ 'mouseup' , 'mouseleave' , 'touchend' , 'touchcancel' ] ;
69
+
64
70
/**
65
71
* Helper service that performs DOM manipulations. Not intended to be used outside this module.
66
72
* The constructor takes a reference to the ripple directive's host element and a map of DOM
67
73
* event handlers to be installed on the element that triggers ripple animations.
68
74
* This will eventually become a custom renderer once Angular support exists.
69
75
* @docs -private
70
76
*/
71
- export class RippleRenderer {
77
+ export class RippleRenderer implements EventListenerObject {
72
78
/** Element where the ripples are being added to. */
73
79
private _containerElement : HTMLElement ;
74
80
@@ -78,9 +84,6 @@ export class RippleRenderer {
78
84
/** Whether the pointer is currently down or not. */
79
85
private _isPointerDown = false ;
80
86
81
- /** Events to be registered on the trigger element. */
82
- private _triggerEvents = new Map < string , any > ( ) ;
83
-
84
87
/** Set of currently active ripple references. */
85
88
private _activeRipples = new Set < RippleRef > ( ) ;
86
89
@@ -90,6 +93,9 @@ export class RippleRenderer {
90
93
/** Time in milliseconds when the last touchstart event happened. */
91
94
private _lastTouchStartEvent : number ;
92
95
96
+ /** Whether pointer-up event listeners have been registered. */
97
+ private _pointerUpEventsRegistered = false ;
98
+
93
99
/**
94
100
* Cached dimensions of the ripple container. Set when the first
95
101
* ripple is shown and cleared once no more ripples are visible.
@@ -104,16 +110,6 @@ export class RippleRenderer {
104
110
// Only do anything if we're on the browser.
105
111
if ( platform . isBrowser ) {
106
112
this . _containerElement = coerceElement ( elementOrElementRef ) ;
107
-
108
- // Specify events which need to be registered on the trigger.
109
- this . _triggerEvents
110
- . set ( 'mousedown' , this . _onMousedown )
111
- . set ( 'mouseup' , this . _onPointerUp )
112
- . set ( 'mouseleave' , this . _onPointerUp )
113
-
114
- . set ( 'touchstart' , this . _onTouchStart )
115
- . set ( 'touchend' , this . _onPointerUp )
116
- . set ( 'touchcancel' , this . _onPointerUp ) ;
117
113
}
118
114
}
119
115
@@ -241,17 +237,34 @@ export class RippleRenderer {
241
237
// Remove all previously registered event listeners from the trigger element.
242
238
this . _removeTriggerEvents ( ) ;
243
239
244
- this . _ngZone . runOutsideAngular ( ( ) => {
245
- this . _triggerEvents . forEach ( ( fn , type ) => {
246
- element . addEventListener ( type , fn , passiveEventOptions ) ;
247
- } ) ;
248
- } ) ;
249
-
250
240
this . _triggerElement = element ;
241
+ this . _registerEvents ( pointerDownEvents ) ;
242
+ }
243
+
244
+ /**
245
+ * Handles all registered events.
246
+ * @docs -private
247
+ */
248
+ handleEvent ( event : Event ) {
249
+ if ( event . type === 'mousedown' ) {
250
+ this . _onMousedown ( event as MouseEvent ) ;
251
+ } else if ( event . type === 'touchstart' ) {
252
+ this . _onTouchStart ( event as TouchEvent ) ;
253
+ } else {
254
+ this . _onPointerUp ( ) ;
255
+ }
256
+
257
+ // If pointer-up events haven't been registered yet, do so now.
258
+ // We do this on-demand in order to reduce the total number of event listeners
259
+ // registered by the ripples, which speeds up the rendering time for large UIs.
260
+ if ( ! this . _pointerUpEventsRegistered ) {
261
+ this . _registerEvents ( pointerUpEvents ) ;
262
+ this . _pointerUpEventsRegistered = true ;
263
+ }
251
264
}
252
265
253
266
/** Function being called whenever the trigger is being pressed using mouse. */
254
- private _onMousedown = ( event : MouseEvent ) => {
267
+ private _onMousedown ( event : MouseEvent ) {
255
268
// Screen readers will fire fake mouse events for space/enter. Skip launching a
256
269
// ripple in this case for consistency with the non-screen-reader experience.
257
270
const isFakeMousedown = isFakeMousedownFromScreenReader ( event ) ;
@@ -265,7 +278,7 @@ export class RippleRenderer {
265
278
}
266
279
267
280
/** Function being called whenever the trigger is being pressed using touch. */
268
- private _onTouchStart = ( event : TouchEvent ) => {
281
+ private _onTouchStart ( event : TouchEvent ) {
269
282
if ( ! this . _target . rippleDisabled ) {
270
283
// Some browsers fire mouse events after a `touchstart` event. Those synthetic mouse
271
284
// events will launch a second ripple if we don't ignore mouse events for a specific
@@ -284,7 +297,7 @@ export class RippleRenderer {
284
297
}
285
298
286
299
/** Function being called whenever the trigger is being released. */
287
- private _onPointerUp = ( ) => {
300
+ private _onPointerUp ( ) {
288
301
if ( ! this . _isPointerDown ) {
289
302
return ;
290
303
}
@@ -309,12 +322,27 @@ export class RippleRenderer {
309
322
this . _ngZone . runOutsideAngular ( ( ) => setTimeout ( fn , delay ) ) ;
310
323
}
311
324
325
+ /** Registers event listeners for a given list of events. */
326
+ private _registerEvents ( eventTypes : string [ ] ) {
327
+ this . _ngZone . runOutsideAngular ( ( ) => {
328
+ eventTypes . forEach ( ( type ) => {
329
+ this . _triggerElement ! . addEventListener ( type , this , passiveEventOptions ) ;
330
+ } ) ;
331
+ } ) ;
332
+ }
333
+
312
334
/** Removes previously registered event listeners from the trigger element. */
313
335
_removeTriggerEvents ( ) {
314
336
if ( this . _triggerElement ) {
315
- this . _triggerEvents . forEach ( ( fn , type ) => {
316
- this . _triggerElement ! . removeEventListener ( type , fn , passiveEventOptions ) ;
337
+ pointerDownEvents . forEach ( ( type ) => {
338
+ this . _triggerElement ! . removeEventListener ( type , this , passiveEventOptions ) ;
317
339
} ) ;
340
+
341
+ if ( this . _pointerUpEventsRegistered ) {
342
+ pointerUpEvents . forEach ( ( type ) => {
343
+ this . _triggerElement ! . removeEventListener ( type , this , passiveEventOptions ) ;
344
+ } ) ;
345
+ }
318
346
}
319
347
}
320
348
}
0 commit comments