Skip to content

Commit 3c03a92

Browse files
committed
fix(tooltip): avoid capturing the initial tap on mobile
Currently the tooltip always binds the `mouseenter` and `mouseleave` events, however this can cause the click handlers on the tooltip host not to be fired on the first tap. These changes switch to binding the events only on devices that have touch events. Fixes #2326.
1 parent 0420729 commit 3c03a92

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

src/lib/core/platform/features.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ export function getSupportedInputTypes(): Set<string> {
3434
}
3535
return supportedInputTypes;
3636
}
37+
38+
/** Whether the current browser supports touch events. */
39+
export const HAS_TOUCH_EVENTS = typeof window !== 'undefined' && !!(('ontouchstart' in window) ||
40+
((window as any).DocumentTouch && document instanceof (window as any).DocumentTouch));

src/lib/tooltip/tooltip.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
AnimationTransitionEvent,
1515
NgZone,
1616
Optional,
17-
OnDestroy
17+
OnDestroy,
18+
Renderer,
1819
} from '@angular/core';
1920
import {
2021
Overlay,
@@ -30,6 +31,7 @@ import {MdTooltipInvalidPositionError} from './tooltip-errors';
3031
import {Observable} from 'rxjs/Observable';
3132
import {Subject} from 'rxjs/Subject';
3233
import {Dir} from '../core/rtl/dir';
34+
import {HAS_TOUCH_EVENTS} from '../core/platform/features';
3335
import 'rxjs/add/operator/first';
3436

3537
export type TooltipPosition = 'left' | 'right' | 'above' | 'below' | 'before' | 'after';
@@ -48,8 +50,6 @@ export const TOUCHEND_HIDE_DELAY = 1500;
4850
host: {
4951
'(longpress)': 'show()',
5052
'(touchend)': 'hide(' + TOUCHEND_HIDE_DELAY + ')',
51-
'(mouseenter)': 'show()',
52-
'(mouseleave)': 'hide()',
5353
},
5454
exportAs: 'mdTooltip',
5555
})
@@ -121,11 +121,21 @@ export class MdTooltip implements OnDestroy {
121121
get _matShowDelay() { return this.showDelay; }
122122
set _matShowDelay(v) { this.showDelay = v; }
123123

124-
constructor(private _overlay: Overlay,
125-
private _elementRef: ElementRef,
126-
private _viewContainerRef: ViewContainerRef,
127-
private _ngZone: NgZone,
128-
@Optional() private _dir: Dir) { }
124+
constructor(
125+
private _overlay: Overlay,
126+
private _elementRef: ElementRef,
127+
private _viewContainerRef: ViewContainerRef,
128+
private _ngZone: NgZone,
129+
private _renderer: Renderer,
130+
@Optional() private _dir: Dir) {
131+
132+
// The mouse events shouldn't be bound on touch devices, because
133+
// they can prevent the first tap from firing it's click event.
134+
if (!HAS_TOUCH_EVENTS) {
135+
_renderer.listen(_elementRef.nativeElement, 'mouseenter', () => this.show());
136+
_renderer.listen(_elementRef.nativeElement, 'mouseleave', () => this.hide());
137+
}
138+
}
129139

130140
/**
131141
* Dispose the tooltip when destroyed.

0 commit comments

Comments
 (0)