diff --git a/src/lib/core/ripple/index.ts b/src/lib/core/ripple/index.ts index 45dea58ec64f..aab611db0302 100644 --- a/src/lib/core/ripple/index.ts +++ b/src/lib/core/ripple/index.ts @@ -4,7 +4,7 @@ import {CompatibilityModule} from '../compatibility/compatibility'; import {VIEWPORT_RULER_PROVIDER} from '../overlay/position/viewport-ruler'; import {SCROLL_DISPATCHER_PROVIDER} from '../overlay/scroll/scroll-dispatcher'; -export {MdRipple} from './ripple'; +export {MdRipple, MD_DISABLE_RIPPLES} from './ripple'; export {RippleRef, RippleState} from './ripple-ref'; export {RippleConfig} from './ripple-renderer'; diff --git a/src/lib/core/ripple/ripple.spec.ts b/src/lib/core/ripple/ripple.spec.ts index 6db9435fdd0a..330da08fea53 100644 --- a/src/lib/core/ripple/ripple.spec.ts +++ b/src/lib/core/ripple/ripple.spec.ts @@ -1,6 +1,6 @@ import {TestBed, ComponentFixture, fakeAsync, tick, inject} from '@angular/core/testing'; import {Component, ViewChild} from '@angular/core'; -import {MdRipple, MdRippleModule, RippleState} from './index'; +import {MdRipple, MdRippleModule, MD_DISABLE_RIPPLES, RippleState} from './index'; import {ViewportRuler} from '../overlay/position/viewport-ruler'; import {RIPPLE_FADE_OUT_DURATION, RIPPLE_FADE_IN_DURATION} from './ripple-renderer'; import {dispatchMouseEvent} from '../testing/dispatch-events'; @@ -18,7 +18,7 @@ describe('MdRipple', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [MdRippleModule.forRoot()], + imports: [MdRippleModule], declarations: [ BasicRippleContainer, RippleContainerWithInputBindings, @@ -346,6 +346,50 @@ describe('MdRipple', () => { }); + describe('with ripples disabled', () => { + let rippleDirective: MdRipple; + + beforeEach(() => { + // Reset the previously configured testing module to be able to disable ripples globally. + // The testing module has been initialized in the root describe group for the ripples. + TestBed.resetTestingModule(); + TestBed.configureTestingModule({ + imports: [MdRippleModule], + declarations: [BasicRippleContainer], + providers: [{ provide: MD_DISABLE_RIPPLES, useValue: true }] + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BasicRippleContainer); + fixture.detectChanges(); + + rippleTarget = fixture.nativeElement.querySelector('[mat-ripple]'); + rippleDirective = fixture.componentInstance.ripple; + }); + + it('should not show any ripples on mousedown', () => { + dispatchMouseEvent(rippleTarget, 'mousedown'); + dispatchMouseEvent(rippleTarget, 'mouseup'); + + expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0); + + dispatchMouseEvent(rippleTarget, 'mousedown'); + dispatchMouseEvent(rippleTarget, 'mouseup'); + + expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0); + }); + + it('should still allow manual ripples', () => { + expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0); + + rippleDirective.launch(0, 0); + + expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(1); + }); + + }); + describe('configuring behavior', () => { let controller: RippleContainerWithInputBindings; let rippleComponent: MdRipple; diff --git a/src/lib/core/ripple/ripple.ts b/src/lib/core/ripple/ripple.ts index 5218e7e75e94..844cf20144b7 100644 --- a/src/lib/core/ripple/ripple.ts +++ b/src/lib/core/ripple/ripple.ts @@ -2,15 +2,20 @@ import { Directive, ElementRef, Input, + Inject, NgZone, OnChanges, SimpleChanges, OnDestroy, + OpaqueToken, + Optional, } from '@angular/core'; import {RippleConfig, RippleRenderer} from './ripple-renderer'; import {ViewportRuler} from '../overlay/position/viewport-ruler'; import {RippleRef} from './ripple-ref'; +/** OpaqueToken that can be used to globally disable all ripples. Except programmatic ones. */ +export const MD_DISABLE_RIPPLES = new OpaqueToken('md-disable-ripples'); @Directive({ selector: '[md-ripple], [mat-ripple]', @@ -65,7 +70,9 @@ export class MdRipple implements OnChanges, OnDestroy { /** Renderer for the ripple DOM manipulations. */ private _rippleRenderer: RippleRenderer; - constructor(elementRef: ElementRef, ngZone: NgZone, ruler: ViewportRuler) { + constructor(elementRef: ElementRef, ngZone: NgZone, ruler: ViewportRuler, + @Optional() @Inject(MD_DISABLE_RIPPLES) private _forceDisableRipples: boolean) { + this._rippleRenderer = new RippleRenderer(elementRef, ngZone, ruler); } @@ -74,7 +81,7 @@ export class MdRipple implements OnChanges, OnDestroy { this._rippleRenderer.setTriggerElement(this.trigger); } - this._rippleRenderer.rippleDisabled = this.disabled; + this._rippleRenderer.rippleDisabled = this._forceDisableRipples || this.disabled; this._rippleRenderer.rippleConfig = this.rippleConfig; } diff --git a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts index 930f8a9a2f1e..5a0968b36f7f 100644 --- a/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts +++ b/src/lib/tabs/tab-nav-bar/tab-nav-bar.ts @@ -5,11 +5,9 @@ import { ElementRef, ViewEncapsulation, Directive, - NgZone, } from '@angular/core'; import {MdInkBar} from '../ink-bar'; import {MdRipple} from '../../core/ripple/index'; -import {ViewportRuler} from '../../core/overlay/position/viewport-ruler'; /** * Navigation component matching the styles of the tab group header. @@ -81,9 +79,4 @@ export class MdTabLink { '[class.mat-tab-link]': 'true', }, }) -export class MdTabLinkRipple extends MdRipple { - constructor(elementRef: ElementRef, ngZone: NgZone, ruler: ViewportRuler) { - super(elementRef, ngZone, ruler); - } - -} +export class MdTabLinkRipple extends MdRipple {}