mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(tooltip): add fallback for touch devices if Hammer isn't loaded (#13580)
Unlike other components that we use Hammer on, the tooltip won't show up at all on a touch device if Hammer isn't loaded. These changes add a fallback to using a `touchstart` event to trigger the tooltip. Also fixes the `_manualListeners` not being cleared on Android. Fixes #13536.
This commit is contained in:
committed by
mmalerba
parent
bbeb5ef46c
commit
5d54920e81
+17
-11
@@ -11,6 +11,7 @@ import {Directionality} from '@angular/cdk/bidi';
|
||||
import {coerceBooleanProperty} from '@angular/cdk/coercion';
|
||||
import {ESCAPE} from '@angular/cdk/keycodes';
|
||||
import {BreakpointObserver, Breakpoints, BreakpointState} from '@angular/cdk/layout';
|
||||
import {HammerLoader, HAMMER_LOADER} from '@angular/platform-browser';
|
||||
import {
|
||||
FlexibleConnectedPositionStrategy,
|
||||
HorizontalConnectionPos,
|
||||
@@ -201,27 +202,34 @@ export class MatTooltip implements OnDestroy {
|
||||
private _scrollDispatcher: ScrollDispatcher,
|
||||
private _viewContainerRef: ViewContainerRef,
|
||||
private _ngZone: NgZone,
|
||||
private _platform: Platform,
|
||||
platform: Platform,
|
||||
private _ariaDescriber: AriaDescriber,
|
||||
private _focusMonitor: FocusMonitor,
|
||||
@Inject(MAT_TOOLTIP_SCROLL_STRATEGY) scrollStrategy: any,
|
||||
@Optional() private _dir: Directionality,
|
||||
@Optional() @Inject(MAT_TOOLTIP_DEFAULT_OPTIONS)
|
||||
private _defaultOptions: MatTooltipDefaultOptions) {
|
||||
private _defaultOptions: MatTooltipDefaultOptions,
|
||||
@Optional() @Inject(HAMMER_LOADER) hammerLoader?: HammerLoader) {
|
||||
|
||||
this._scrollStrategy = scrollStrategy;
|
||||
const element: HTMLElement = _elementRef.nativeElement;
|
||||
const elementStyle = element.style as CSSStyleDeclaration & {webkitUserDrag: string};
|
||||
const hasGestures = typeof window === 'undefined' || (window as any).Hammer || hammerLoader;
|
||||
|
||||
// The mouse events shouldn't be bound on mobile devices, because they can prevent the
|
||||
// first tap from firing its click event or can cause the tooltip to open for clicks.
|
||||
if (!_platform.IOS && !_platform.ANDROID) {
|
||||
if (!platform.IOS && !platform.ANDROID) {
|
||||
this._manualListeners
|
||||
.set('mouseenter', () => this.show())
|
||||
.set('mouseleave', () => this.hide())
|
||||
.forEach((listener, event) => element.addEventListener(event, listener));
|
||||
.set('mouseleave', () => this.hide());
|
||||
} else if (!hasGestures) {
|
||||
// If Hammerjs isn't loaded, fall back to showing on `touchstart`, otherwise
|
||||
// there's no way for the user to trigger the tooltip on a touch device.
|
||||
this._manualListeners.set('touchstart', () => this.show());
|
||||
}
|
||||
|
||||
this._manualListeners.forEach((listener, event) => element.addEventListener(event, listener));
|
||||
|
||||
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
|
||||
// When we bind a gesture event on an element (in this case `longpress`), HammerJS
|
||||
// will add some inline styles by default, including `user-select: none`. This is
|
||||
@@ -258,12 +266,10 @@ export class MatTooltip implements OnDestroy {
|
||||
}
|
||||
|
||||
// Clean up the event listeners set in the constructor
|
||||
if (!this._platform.IOS) {
|
||||
this._manualListeners.forEach((listener, event) =>
|
||||
this._elementRef.nativeElement.removeEventListener(event, listener));
|
||||
|
||||
this._manualListeners.clear();
|
||||
}
|
||||
this._manualListeners.forEach((listener, event) => {
|
||||
this._elementRef.nativeElement.removeEventListener(event, listener);
|
||||
});
|
||||
this._manualListeners.clear();
|
||||
|
||||
this._destroyed.next();
|
||||
this._destroyed.complete();
|
||||
|
||||
Reference in New Issue
Block a user