Skip to content

Commit

Permalink
fix(tooltip): opening after click on android (#12250)
Browse files Browse the repository at this point in the history
Fixes the tooltip opening on clicks on Android devices. Also does some minor cleanup.

Fixes #12223.
  • Loading branch information
crisbeto authored and jelbourn committed Aug 23, 2018
1 parent 5fb338b commit 2a49532
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
35 changes: 32 additions & 3 deletions src/lib/tooltip/tooltip.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {Direction, Directionality} from '@angular/cdk/bidi';
import {OverlayContainer, OverlayModule, CdkScrollable} from '@angular/cdk/overlay';
import {Platform} from '@angular/cdk/platform';
import {dispatchFakeEvent, dispatchKeyboardEvent, patchElementFocus} from '@angular/cdk/testing';
import {
dispatchFakeEvent,
dispatchKeyboardEvent,
patchElementFocus,
dispatchMouseEvent,
} from '@angular/cdk/testing';
import {ESCAPE} from '@angular/cdk/keycodes';
import {FocusMonitor} from '@angular/cdk/a11y';
import {
Expand All @@ -40,12 +45,12 @@ describe('MatTooltip', () => {
let overlayContainer: OverlayContainer;
let overlayContainerElement: HTMLElement;
let dir: {value: Direction};
let platform: {IOS: boolean, isBrowser: boolean};
let platform: {IOS: boolean, isBrowser: boolean, ANDROID: boolean};
let focusMonitor: FocusMonitor;

beforeEach(async(() => {
// Set the default Platform override that can be updated before component creation.
platform = {IOS: false, isBrowser: true};
platform = {IOS: false, isBrowser: true, ANDROID: false};

TestBed.configureTestingModule({
imports: [MatTooltipModule, OverlayModule, NoopAnimationsModule],
Expand Down Expand Up @@ -808,6 +813,30 @@ describe('MatTooltip', () => {
expect(fixture.componentInstance.button.nativeElement.style.webkitUserDrag).toBeFalsy();
});

it('should not open on `mouseenter` on iOS', () => {
platform.IOS = true;

const fixture = TestBed.createComponent(BasicTooltipDemo);

fixture.detectChanges();
dispatchMouseEvent(fixture.componentInstance.button.nativeElement, 'mouseenter');
fixture.detectChanges();

assertTooltipInstance(fixture.componentInstance.tooltip, false);
});

it('should not open on `mouseenter` on Android', () => {
platform.ANDROID = true;

const fixture = TestBed.createComponent(BasicTooltipDemo);

fixture.detectChanges();
dispatchMouseEvent(fixture.componentInstance.button.nativeElement, 'mouseenter');
fixture.detectChanges();

assertTooltipInstance(fixture.componentInstance.tooltip, false);
});

});

});
Expand Down
17 changes: 8 additions & 9 deletions src/lib/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class MatTooltip implements OnDestroy {
}
}

private _manualListeners = new Map<string, Function>();
private _manualListeners = new Map<string, EventListenerOrEventListenerObject>();

/** Emits when the component is destroyed. */
private readonly _destroyed = new Subject<void>();
Expand All @@ -210,15 +210,14 @@ export class MatTooltip implements OnDestroy {

const element: HTMLElement = _elementRef.nativeElement;

// The mouse events shouldn't be bound on iOS devices, because
// they can prevent the first tap from firing its click event.
if (!_platform.IOS) {
this._manualListeners.set('mouseenter', () => this.show());
this._manualListeners.set('mouseleave', () => this.hide());

// 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) {
this._manualListeners
.forEach((listener, event) => _elementRef.nativeElement.addEventListener(event, listener));
} else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
.set('mouseenter', () => this.show())
.set('mouseleave', () => this.hide())
.forEach((listener, event) => element.addEventListener(event, listener));
} else if (_platform.IOS && (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
// problematic on iOS, because it will prevent users from typing in inputs. If
Expand Down

0 comments on commit 2a49532

Please sign in to comment.