From 992bcfb1799c3342de33153e5de7e404821a1e2e Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 19 Oct 2018 23:04:29 +0200 Subject: [PATCH] refactor(platform): add utility to normalize passive event listener options (#13533) --- src/cdk/a11y/focus-monitor/focus-monitor.ts | 8 +++++--- src/cdk/drag-drop/drag-drop-registry.ts | 4 ++-- src/cdk/platform/features/passive-listeners.ts | 11 +++++++++++ src/cdk/text-field/autofill.spec.ts | 4 ++-- src/cdk/text-field/autofill.ts | 4 ++-- src/lib/core/ripple/ripple-renderer.ts | 15 ++++++++------- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/cdk/a11y/focus-monitor/focus-monitor.ts b/src/cdk/a11y/focus-monitor/focus-monitor.ts index 612ec9d144e..d8d1d72a95d 100644 --- a/src/cdk/a11y/focus-monitor/focus-monitor.ts +++ b/src/cdk/a11y/focus-monitor/focus-monitor.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Platform, supportsPassiveEventListeners} from '@angular/cdk/platform'; +import {Platform, normalizePassiveListenerOptions} from '@angular/cdk/platform'; import { Directive, ElementRef, @@ -243,8 +243,10 @@ export class FocusMonitor implements OnDestroy { // Event listener options that enable capturing and also mark the the listener as passive // if the browser supports it. - const captureEventListenerOptions = supportsPassiveEventListeners() ? - {passive: true, capture: true} : true; + const captureEventListenerOptions = normalizePassiveListenerOptions({ + passive: true, + capture: true + }); // Note: we listen to events in the capture phase so we can detect them even if the user stops // propagation. diff --git a/src/cdk/drag-drop/drag-drop-registry.ts b/src/cdk/drag-drop/drag-drop-registry.ts index 8ce26bc18dd..156128b6eab 100644 --- a/src/cdk/drag-drop/drag-drop-registry.ts +++ b/src/cdk/drag-drop/drag-drop-registry.ts @@ -8,12 +8,12 @@ import {Injectable, NgZone, OnDestroy, Inject} from '@angular/core'; import {DOCUMENT} from '@angular/common'; -import {supportsPassiveEventListeners} from '@angular/cdk/platform'; +import {normalizePassiveListenerOptions} from '@angular/cdk/platform'; import {Subject} from 'rxjs'; import {toggleNativeDragInteractions} from './drag-styling'; /** Event options that can be used to bind an active event. */ -const activeEventOptions = supportsPassiveEventListeners() ? {passive: false} : false; +const activeEventOptions = normalizePassiveListenerOptions({passive: false}); /** Handler for a pointer event callback. */ type PointerEventHandler = (event: TouchEvent | MouseEvent) => void; diff --git a/src/cdk/platform/features/passive-listeners.ts b/src/cdk/platform/features/passive-listeners.ts index c2e1e149ae0..4b460116e68 100644 --- a/src/cdk/platform/features/passive-listeners.ts +++ b/src/cdk/platform/features/passive-listeners.ts @@ -26,3 +26,14 @@ export function supportsPassiveEventListeners(): boolean { return supportsPassiveEvents; } + +/** + * Normalizes an `AddEventListener` object to something that can be passed + * to `addEventListener` on any browser, no matter whether it supports the + * `options` parameter. + * @param options Object to be normalized. + */ +export function normalizePassiveListenerOptions(options: AddEventListenerOptions): + AddEventListenerOptions | boolean { + return supportsPassiveEventListeners() ? options : !!options.capture; +} diff --git a/src/cdk/text-field/autofill.spec.ts b/src/cdk/text-field/autofill.spec.ts index 788b3282bde..8b24ae5f524 100644 --- a/src/cdk/text-field/autofill.spec.ts +++ b/src/cdk/text-field/autofill.spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {supportsPassiveEventListeners} from '@angular/cdk/platform'; +import {normalizePassiveListenerOptions} from '@angular/cdk/platform'; import {Component, ElementRef, NgZone, ViewChild} from '@angular/core'; import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; import {EMPTY} from 'rxjs'; @@ -14,7 +14,7 @@ import {AutofillEvent, AutofillMonitor} from './autofill'; import {TextFieldModule} from './text-field-module'; -const listenerOptions: any = supportsPassiveEventListeners() ? {passive: true} : false; +const listenerOptions = normalizePassiveListenerOptions({passive: true}); describe('AutofillMonitor', () => { diff --git a/src/cdk/text-field/autofill.ts b/src/cdk/text-field/autofill.ts index bf85958c86e..609f17d584a 100644 --- a/src/cdk/text-field/autofill.ts +++ b/src/cdk/text-field/autofill.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Platform, supportsPassiveEventListeners} from '@angular/cdk/platform'; +import {Platform, normalizePassiveListenerOptions} from '@angular/cdk/platform'; import { Directive, ElementRef, @@ -37,7 +37,7 @@ type MonitoredElementInfo = { /** Options to pass to the animationstart listener. */ -const listenerOptions: any = supportsPassiveEventListeners() ? {passive: true} : false; +const listenerOptions = normalizePassiveListenerOptions({passive: true}); /** diff --git a/src/lib/core/ripple/ripple-renderer.ts b/src/lib/core/ripple/ripple-renderer.ts index a5f82245cf6..de4056448c1 100644 --- a/src/lib/core/ripple/ripple-renderer.ts +++ b/src/lib/core/ripple/ripple-renderer.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ import {ElementRef, NgZone} from '@angular/core'; -import {Platform, supportsPassiveEventListeners} from '@angular/cdk/platform'; +import {Platform, normalizePassiveListenerOptions} from '@angular/cdk/platform'; import {isFakeMousedownFromScreenReader} from '@angular/cdk/a11y'; import {RippleRef, RippleState} from './ripple-ref'; @@ -57,6 +57,9 @@ export const defaultRippleAnimationConfig = { */ const ignoreMouseEventsTimeout = 800; +/** Options that apply to all the event listeners that are bound by the ripple renderer. */ +const passiveEventOptions = normalizePassiveListenerOptions({passive: true}); + /** * Helper service that performs DOM manipulations. Not intended to be used outside this module. * The constructor takes a reference to the ripple directive's host element and a map of DOM @@ -86,9 +89,6 @@ export class RippleRenderer { /** Time in milliseconds when the last touchstart event happened. */ private _lastTouchStartEvent: number; - /** Options that apply to all the event listeners that are bound by the renderer. */ - private _eventOptions = supportsPassiveEventListeners() ? ({passive: true} as any) : false; - /** * Cached dimensions of the ripple container. Set when the first * ripple is shown and cleared once no more ripples are visible. @@ -235,8 +235,9 @@ export class RippleRenderer { this._removeTriggerEvents(); this._ngZone.runOutsideAngular(() => { - this._triggerEvents.forEach((fn, type) => - element.addEventListener(type, fn, this._eventOptions)); + this._triggerEvents.forEach((fn, type) => { + element.addEventListener(type, fn, passiveEventOptions); + }); }); this._triggerElement = element; @@ -305,7 +306,7 @@ export class RippleRenderer { _removeTriggerEvents() { if (this._triggerElement) { this._triggerEvents.forEach((fn, type) => { - this._triggerElement!.removeEventListener(type, fn, this._eventOptions); + this._triggerElement!.removeEventListener(type, fn, passiveEventOptions); }); } }