Skip to content

Commit 04b1461

Browse files
committed
fix(universal): gate several browser-specific bits on being on the
browser Related to #308
1 parent bfdef8e commit 04b1461

File tree

7 files changed

+60
-27
lines changed

7 files changed

+60
-27
lines changed

src/lib/button/button.ts

+13-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from '@angular/core';
1212
import {coerceBooleanProperty, FocusOriginMonitor} from '../core';
1313
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
14+
import {isBrowser} from '../core/platform/browser';
1415

1516

1617
// TODO(kara): Convert attribute selectors to classes when attr maps become available
@@ -22,9 +23,7 @@ import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
2223
*/
2324
@Directive({
2425
selector: 'button[md-button], button[mat-button], a[md-button], a[mat-button]',
25-
host: {
26-
'[class.mat-button]': 'true'
27-
}
26+
host: {'class': 'mat-button'}
2827
})
2928
export class MdButtonCssMatStyler {}
3029

@@ -36,9 +35,7 @@ export class MdButtonCssMatStyler {}
3635
selector:
3736
'button[md-raised-button], button[mat-raised-button], ' +
3837
'a[md-raised-button], a[mat-raised-button]',
39-
host: {
40-
'[class.mat-raised-button]': 'true'
41-
}
38+
host: {'class': 'mat-raised-button'}
4239
})
4340
export class MdRaisedButtonCssMatStyler {}
4441

@@ -49,9 +46,7 @@ export class MdRaisedButtonCssMatStyler {}
4946
@Directive({
5047
selector:
5148
'button[md-icon-button], button[mat-icon-button], a[md-icon-button], a[mat-icon-button]',
52-
host: {
53-
'[class.mat-icon-button]': 'true',
54-
}
49+
host: {'class': 'mat-icon-button'}
5550
})
5651
export class MdIconButtonCssMatStyler {}
5752

@@ -61,9 +56,7 @@ export class MdIconButtonCssMatStyler {}
6156
*/
6257
@Directive({
6358
selector: 'button[md-fab], button[mat-fab], a[md-fab], a[mat-fab]',
64-
host: {
65-
'[class.mat-fab]': 'true'
66-
}
59+
host: {'class': 'mat-fab'}
6760
})
6861
export class MdFabCssMatStyler {}
6962

@@ -73,9 +66,7 @@ export class MdFabCssMatStyler {}
7366
*/
7467
@Directive({
7568
selector: 'button[md-mini-fab], button[mat-mini-fab], a[md-mini-fab], a[mat-mini-fab]',
76-
host: {
77-
'[class.mat-mini-fab]': 'true'
78-
}
69+
host: {'class': 'mat-mini-fab'}
7970
})
8071
export class MdMiniFabCssMatStyler {}
8172

@@ -165,6 +156,13 @@ export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisabl
165156
* with either an 'md-' or 'mat-' prefix.
166157
*/
167158
_hasAttributeWithPrefix(...unprefixedAttributeNames: string[]) {
159+
// If not on the browser, say that there are none of the attributes present.
160+
// Since these only affect how the ripple displays (and ripples only happen on the client),
161+
// detecting these attributes isn't necessary when not on the browser.
162+
if (!isBrowser()) {
163+
return false;
164+
}
165+
168166
return unprefixedAttributeNames.some(suffix => {
169167
const el = this._getHostElement();
170168

src/lib/core/overlay/position/viewport-ruler.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,18 @@ export class ViewportRuler {
1313
private _documentRect?: ClientRect;
1414

1515
constructor(scrollDispatcher: ScrollDispatcher) {
16-
// Initially cache the document rectangle.
17-
this._cacheViewportGeometry();
18-
1916
// Subscribe to scroll and resize events and update the document rectangle on changes.
2017
scrollDispatcher.scrolled(null, () => this._cacheViewportGeometry());
2118
}
2219

2320
/** Gets a ClientRect for the viewport's bounds. */
2421
getViewportRect(documentRect = this._documentRect): ClientRect {
22+
// Cache the document bounding rect so that we don't recompute it for multiple calls.
23+
if (!documentRect) {
24+
this._cacheViewportGeometry();
25+
documentRect = this._documentRect;
26+
}
27+
2528
// Use the document element's bounding rect rather than the window scroll properties
2629
// (e.g. pageYOffset, scrollY) due to in issue in Chrome and IE where window scroll
2730
// properties and client coordinates (boundingClientRect, clientX/Y, etc.) are in different
@@ -51,6 +54,12 @@ export class ViewportRuler {
5154
* @param documentRect
5255
*/
5356
getViewportScrollPosition(documentRect = this._documentRect) {
57+
// Cache the document bounding rect so that we don't recompute it for multiple calls.
58+
if (!documentRect) {
59+
this._cacheViewportGeometry();
60+
documentRect = this._documentRect;
61+
}
62+
5463
// The top-left-corner of the viewport is determined by the scroll position of the document
5564
// body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about
5665
// whether `document.body` or `document.documentElement` is the scrolled element, so reading

src/lib/core/overlay/scroll/scroll-dispatcher.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {Injectable, ElementRef, Optional, SkipSelf, NgZone} from '@angular/core';
1+
import {ElementRef, Injectable, NgZone, Optional, SkipSelf} from '@angular/core';
2+
import {isBrowser} from '../../platform/browser';
23
import {Scrollable} from './scrollable';
34
import {Subject} from 'rxjs/Subject';
45
import {Observable} from 'rxjs/Observable';
@@ -62,6 +63,10 @@ export class ScrollDispatcher {
6263
* to override the default "throttle" time.
6364
*/
6465
scrolled(auditTimeInMs: number = DEFAULT_SCROLL_TIME, callback: () => any): Subscription {
66+
if (!isBrowser()) {
67+
return Subscription.EMPTY;
68+
}
69+
6570
// In the case of a 0ms delay, use an observable without auditTime
6671
// since it does add a perceptible delay in processing overhead.
6772
let observable = auditTimeInMs > 0 ?

src/lib/core/platform/browser.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/** Gets whether the current platform is a web browser (versus node). */
2+
export function isBrowser() {
3+
return typeof document === 'object';
4+
}

src/lib/core/ripple/ripple-renderer.ts

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {ElementRef, NgZone} from '@angular/core';
2+
import {isBrowser} from '../platform/browser';
23
import {ViewportRuler} from '../overlay/position/viewport-ruler';
34
import {RippleRef, RippleState} from './ripple-ref';
45

6+
57
/** Fade-in duration for the ripples. Can be modified with the speedFactor option. */
68
export const RIPPLE_FADE_IN_DURATION = 450;
79

@@ -47,15 +49,18 @@ export class RippleRenderer {
4749
rippleDisabled: boolean = false;
4850

4951
constructor(_elementRef: ElementRef, private _ngZone: NgZone, private _ruler: ViewportRuler) {
50-
this._containerElement = _elementRef.nativeElement;
52+
// Only do anything if we're on the browser.
53+
if (isBrowser()) {
54+
this._containerElement = _elementRef.nativeElement;
5155

52-
// Specify events which need to be registered on the trigger.
53-
this._triggerEvents.set('mousedown', this.onMousedown.bind(this));
54-
this._triggerEvents.set('mouseup', this.onMouseup.bind(this));
55-
this._triggerEvents.set('mouseleave', this.onMouseLeave.bind(this));
56+
// Specify events which need to be registered on the trigger.
57+
this._triggerEvents.set('mousedown', this.onMousedown.bind(this));
58+
this._triggerEvents.set('mouseup', this.onMouseup.bind(this));
59+
this._triggerEvents.set('mouseleave', this.onMouseLeave.bind(this));
5660

57-
// By default use the host element as trigger element.
58-
this.setTriggerElement(this._containerElement);
61+
// By default use the host element as trigger element.
62+
this.setTriggerElement(this._containerElement);
63+
}
5964
}
6065

6166
/** Fades in a ripple at the given coordinates. */

src/lib/core/style/focus-origin-monitor.ts

+11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@angular/core';
1313
import {Observable} from 'rxjs/Observable';
1414
import {Subject} from 'rxjs/Subject';
15+
import {isBrowser} from '../platform/browser';
1516

1617

1718
// This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
@@ -64,6 +65,11 @@ export class FocusOriginMonitor {
6465
* When the element is blurred, null will be emitted.
6566
*/
6667
monitor(element: Element, renderer: Renderer, checkChildren: boolean): Observable<FocusOrigin> {
68+
// Do nothing if we're not on the browser platform.
69+
if (!isBrowser()) {
70+
return Observable.of();
71+
}
72+
6773
// Check if we're already monitoring this element.
6874
if (this._elementInfo.has(element)) {
6975
let info = this._elementInfo.get(element);
@@ -126,6 +132,11 @@ export class FocusOriginMonitor {
126132

127133
/** Register necessary event listeners on the document and window. */
128134
private _registerDocumentEvents() {
135+
// Do nothing if we're not on the browser platform.
136+
if (!isBrowser()) {
137+
return;
138+
}
139+
129140
// Note: we listen to events in the capture phase so we can detect them even if the user stops
130141
// propagation.
131142

tools/gulp/util/rollup-helper.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ const ROLLUP_GLOBALS = {
3636
'rxjs/add/operator/first': 'Rx.Observable.prototype',
3737
'rxjs/add/operator/startWith': 'Rx.Observable.prototype',
3838
'rxjs/add/operator/switchMap': 'Rx.Observable.prototype',
39-
'rxjs/Observable': 'Rx'
39+
'rxjs/Observable': 'Rx',
40+
'rxjs/Subscription': 'Rx',
4041
};
4142

4243
export type BundleConfig = {

0 commit comments

Comments
 (0)