feat(ripple): support for global ripple options (#3463)

* feat(ripple): add option to change global speedFactor

* Refactors the `MD_DISABLE_RIPPLES` token to a configuration object, that can also include options like a global `baseSpeedFactor`.

* Fix Angular issue
This commit is contained in:
Paul Gschwendtner
2017-03-10 19:37:17 +01:00
committed by tinayuangao
parent 17bf5e5759
commit fb75a136e7
3 changed files with 69 additions and 17 deletions
+1 -1
View File
@@ -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, MD_DISABLE_RIPPLES} from './ripple';
export {MdRipple, RippleGlobalOptions, MD_RIPPLE_GLOBAL_OPTIONS} from './ripple';
export {RippleRef, RippleState} from './ripple-ref';
export {RippleConfig} from './ripple-renderer';
+49 -10
View File
@@ -1,9 +1,11 @@
import {TestBed, ComponentFixture, fakeAsync, tick, inject} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
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';
import {
MdRipple, MdRippleModule, MD_RIPPLE_GLOBAL_OPTIONS, RippleState, RippleGlobalOptions
} from './index';
/** Extracts the numeric value of a pixel size string like '123px'. */
const pxStringToFloat = (s: string) => {
@@ -346,29 +348,29 @@ describe('MdRipple', () => {
});
describe('with ripples disabled', () => {
describe('global ripple options', () => {
let rippleDirective: MdRipple;
beforeEach(() => {
// Reset the previously configured testing module to be able to disable ripples globally.
function createTestComponent(rippleConfig: RippleGlobalOptions) {
// Reset the previously configured testing module to be able set new providers.
// 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 }]
providers: [{ provide: MD_RIPPLE_GLOBAL_OPTIONS, useValue: rippleConfig }]
});
});
beforeEach(() => {
fixture = TestBed.createComponent(BasicRippleContainer);
fixture.detectChanges();
rippleTarget = fixture.nativeElement.querySelector('[mat-ripple]');
rippleDirective = fixture.componentInstance.ripple;
});
}
it('when disabled should not show any ripples on mousedown', () => {
createTestComponent({ disabled: true });
it('should not show any ripples on mousedown', () => {
dispatchMouseEvent(rippleTarget, 'mousedown');
dispatchMouseEvent(rippleTarget, 'mouseup');
@@ -380,7 +382,9 @@ describe('MdRipple', () => {
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
});
it('should still allow manual ripples', () => {
it('when disabled should still allow manual ripples', () => {
createTestComponent({ disabled: true });
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
rippleDirective.launch(0, 0);
@@ -388,6 +392,41 @@ describe('MdRipple', () => {
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(1);
});
it('should support changing the baseSpeedFactor', fakeAsync(() => {
createTestComponent({ baseSpeedFactor: 0.5 });
dispatchMouseEvent(rippleTarget, 'mousedown');
dispatchMouseEvent(rippleTarget, 'mouseup');
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(1);
// Calculates the speedFactor for the duration. Those factors needs to be inverted, because
// a lower speed factor, will make the duration longer. For example: 0.5 => 2x duration.
let fadeInFactor = 1 / 0.5;
// Calculates the duration for fading-in and fading-out the ripple.
tick(RIPPLE_FADE_IN_DURATION * fadeInFactor + RIPPLE_FADE_OUT_DURATION);
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
}));
it('should combine individual speed factor with baseSpeedFactor', fakeAsync(() => {
createTestComponent({ baseSpeedFactor: 0.5 });
rippleDirective.launch(0, 0, { speedFactor: 1.5 });
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(1);
// Calculates the speedFactor for the duration. Those factors needs to be inverted, because
// a lower speed factor, will make the duration longer. For example: 0.5 => 2x duration.
let fadeInFactor = 1 / (0.5 * 1.5);
// Calculates the duration for fading-in and fading-out the ripple.
tick(RIPPLE_FADE_IN_DURATION * fadeInFactor + RIPPLE_FADE_OUT_DURATION);
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
}));
});
describe('configuring behavior', () => {
+19 -6
View File
@@ -14,8 +14,13 @@ 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');
/** OpaqueToken that can be used to specify the global ripple options. */
export const MD_RIPPLE_GLOBAL_OPTIONS = new OpaqueToken('md-ripple-global-options');
export type RippleGlobalOptions = {
disabled?: boolean;
baseSpeedFactor?: number;
};
@Directive({
selector: '[md-ripple], [mat-ripple], [mdRipple], [matRipple]',
@@ -70,10 +75,18 @@ export class MdRipple implements OnChanges, OnDestroy {
/** Renderer for the ripple DOM manipulations. */
private _rippleRenderer: RippleRenderer;
constructor(elementRef: ElementRef, ngZone: NgZone, ruler: ViewportRuler,
@Optional() @Inject(MD_DISABLE_RIPPLES) private _forceDisableRipples: boolean) {
/** Options that are set globally for all ripples. */
private _globalOptions: RippleGlobalOptions;
constructor(
elementRef: ElementRef,
ngZone: NgZone,
ruler: ViewportRuler,
// Type needs to be `any` because of https://github.com/angular/angular/issues/12631
@Optional() @Inject(MD_RIPPLE_GLOBAL_OPTIONS) globalOptions: any
) {
this._rippleRenderer = new RippleRenderer(elementRef, ngZone, ruler);
this._globalOptions = globalOptions ? globalOptions : {};
}
ngOnChanges(changes: SimpleChanges) {
@@ -81,7 +94,7 @@ export class MdRipple implements OnChanges, OnDestroy {
this._rippleRenderer.setTriggerElement(this.trigger);
}
this._rippleRenderer.rippleDisabled = this._forceDisableRipples || this.disabled;
this._rippleRenderer.rippleDisabled = this._globalOptions.disabled || this.disabled;
this._rippleRenderer.rippleConfig = this.rippleConfig;
}
@@ -104,7 +117,7 @@ export class MdRipple implements OnChanges, OnDestroy {
get rippleConfig(): RippleConfig {
return {
centered: this.centered,
speedFactor: this.speedFactor,
speedFactor: this.speedFactor * (this._globalOptions.baseSpeedFactor || 1),
radius: this.radius,
color: this.color
};