Skip to content

Commit

Permalink
feat: make hammerjs optional
Browse files Browse the repository at this point in the history
Makes HammerJS and logs a warning if it's missing, instead of crashing the app.
  • Loading branch information
crisbeto committed Dec 20, 2016
1 parent 3cf25a0 commit 0c7b8fb
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 17 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
"@angular/platform-browser-dynamic": "^2.2.0",
"@angular/router": "^3.2.0",
"core-js": "^2.4.1",
"hammerjs": "^2.0.8",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.38",
"zone.js": "^0.6.23"
},
"optionalDependencies": {
"hammerjs": "^2.0.8"
},
"devDependencies": {
"@angular/compiler-cli": "^2.2.0",
"@angular/platform-server": "^2.2.0",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export * from './overlay/position/connected-position-strategy';
export * from './overlay/position/connected-position';

// Gestures
export {GestureConfig} from './gestures/gesture-config';
export {GestureConfig, MdHammerEvent} from './gestures/gesture-config';

// Ripple
export {MdRipple, MdRippleModule} from './ripple/ripple';
Expand Down
42 changes: 33 additions & 9 deletions src/lib/core/gestures/gesture-config.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import {Injectable} from '@angular/core';
import {Injectable, isDevMode} from '@angular/core';
import {HammerGestureConfig} from '@angular/platform-browser';

/* Adjusts configuration of our gesture library, Hammer. */
@Injectable()
export class GestureConfig extends HammerGestureConfig {
private _hammer = typeof window !== 'undefined' ? (window as any).Hammer : null;

/* List of new event names to add to the gesture support list */
events: string[] = [
events: string[] = this._hammer ? [
'longpress',
'slide',
'slidestart',
'slideend',
'slideright',
'slideleft'
];
] : [];

constructor() {
super();

if (!this._hammer && isDevMode()) {
console.warn('Could not find HammerJS. Certain Angular Material may not work correctly.');
}
}

/*
* Builds Hammer instance manually to add custom recognizers that match the Material Design spec.
Expand All @@ -28,12 +37,12 @@ export class GestureConfig extends HammerGestureConfig {
* TODO: Confirm threshold numbers with Material Design UX Team
* */
buildHammer(element: HTMLElement) {
const mc = new Hammer(element);
const mc: any = super.buildHammer(element);

// Default Hammer Recognizers.
let pan = new Hammer.Pan();
let swipe = new Hammer.Swipe();
let press = new Hammer.Press();
let pan = new this._hammer.Pan();
let swipe = new this._hammer.Swipe();
let press = new this._hammer.Press();

// Notice that a HammerJS recognizer can only depend on one other recognizer once.
// Otherwise the previous `recognizeWith` will be dropped.
Expand All @@ -50,8 +59,8 @@ export class GestureConfig extends HammerGestureConfig {
}

/** Creates a new recognizer, without affecting the default recognizers of HammerJS */
private _createRecognizer(base: Recognizer, options: any, ...inheritances: Recognizer[]) {
let recognizer = new (<RecognizerStatic> base.constructor)(options);
private _createRecognizer(base: any, options: any, ...inheritances: any[]) {
let recognizer = new base.constructor(options);

inheritances.push(base);
inheritances.forEach(item => recognizer.recognizeWith(item));
Expand All @@ -60,3 +69,18 @@ export class GestureConfig extends HammerGestureConfig {
}

}

/**
* Stripped-down annotation to be used as alternative
* to the one from HammerJS.
* @docs-private
*/
export interface MdHammerEvent {
preventDefault: () => {};
deltaX: number;
deltaY: number;
center: {
x: number;
y: number;
};
}
3 changes: 2 additions & 1 deletion src/lib/slide-toggle/slide-toggle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
applyCssTransform,
coerceBooleanProperty,
GestureConfig,
MdHammerEvent,
DefaultStyleCompatibilityModeModule,
} from '../core';
import {Observable} from 'rxjs/Observable';
Expand Down Expand Up @@ -234,7 +235,7 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
}
}

_onDrag(event: HammerInput) {
_onDrag(event: MdHammerEvent) {
if (this._slideRenderer.isDragging()) {
this._slideRenderer.updateThumbPosition(event.deltaX);
}
Expand Down
7 changes: 3 additions & 4 deletions src/lib/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import {NG_VALUE_ACCESSOR, ControlValueAccessor, FormsModule} from '@angular/for
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {
GestureConfig,
MdHammerEvent,
coerceBooleanProperty,
coerceNumberProperty,
DefaultStyleCompatibilityModeModule,
} from '../core';
import {Input as HammerInput} from 'hammerjs';
import {Dir} from '../core/rtl/dir';
import {CommonModule} from '@angular/common';
import {
Expand All @@ -32,7 +32,6 @@ import {
DOWN_ARROW,
} from '../core/keyboard/keycodes';


/**
* Visually, a 30px separation between tick marks looks best. This is very subjective but it is
* the default separation we chose.
Expand Down Expand Up @@ -324,7 +323,7 @@ export class MdSlider implements ControlValueAccessor {
this._emitValueIfChanged();
}

_onSlide(event: HammerInput) {
_onSlide(event: MdHammerEvent) {
if (this.disabled) {
return;
}
Expand All @@ -334,7 +333,7 @@ export class MdSlider implements ControlValueAccessor {
this._updateValueFromPosition({x: event.center.x, y: event.center.y});
}

_onSlideStart(event: HammerInput) {
_onSlideStart(event: MdHammerEvent) {
if (this.disabled) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/slider/test-gesture-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class TestGestureConfig extends GestureConfig {
* A map of Hammer instances to element.
* Used to emit events over instances for an element.
*/
hammerInstances: Map<HTMLElement, HammerManager[]> = new Map<HTMLElement, HammerManager[]>();
hammerInstances: Map<HTMLElement, any[]> = new Map<HTMLElement, any[]>();

/**
* Create a mapping of Hammer instances to element so that events can be emitted during testing.
Expand Down

0 comments on commit 0c7b8fb

Please sign in to comment.