55 * Use of this source code is governed by an MIT-style license that can be
66 * found in the LICENSE file at https://angular.io/license
77 */
8- import { Injectable , NgZone } from '@angular/core' ;
9-
8+ import { Inject , Injectable , NgZone } from '@angular/core' ;
9+ import { ɵgetDOM as getDom , DOCUMENT } from '@angular/platform-browser' ;
1010import { BehaviorSubject } from 'rxjs/BehaviorSubject' ;
1111import { Observable } from 'rxjs/Observable' ;
1212import { filter } from 'rxjs/operator/filter' ;
@@ -27,7 +27,9 @@ export interface MediaQueryListListener {
2727export interface MediaQueryList {
2828 readonly matches : boolean ;
2929 readonly media : string ;
30+
3031 addListener ( listener : MediaQueryListListener ) : void ;
32+
3133 removeListener ( listener : MediaQueryListListener ) : void ;
3234}
3335
@@ -45,7 +47,7 @@ export class MatchMedia {
4547 protected _source : BehaviorSubject < MediaChange > ;
4648 protected _observable$ : Observable < MediaChange > ;
4749
48- constructor ( protected _zone : NgZone ) {
50+ constructor ( protected _zone : NgZone , @ Inject ( DOCUMENT ) protected _document : any ) {
4951 this . _registry = new Map < string , MediaQueryList > ( ) ;
5052 this . _source = new BehaviorSubject < MediaChange > ( new MediaChange ( true ) ) ;
5153 this . _observable$ = this . _source . asObservable ( ) ;
@@ -86,7 +88,7 @@ export class MatchMedia {
8688 let list = normalizeQuery ( mediaQuery ) ;
8789
8890 if ( list . length > 0 ) {
89- prepareQueryCSS ( list ) ;
91+ prepareQueryCSS ( list , this . _document ) ;
9092
9193 list . forEach ( query => {
9294 let mql = this . _registry . get ( query ) ;
@@ -114,8 +116,9 @@ export class MatchMedia {
114116 * Call window.matchMedia() to build a MediaQueryList; which
115117 * supports 0..n listeners for activation/deactivation
116118 */
117- protected _buildMQL ( query : string ) : MediaQueryList {
118- let canListen = ! ! ( < any > window ) . matchMedia ( 'all' ) . addListener ;
119+ protected _buildMQL ( query : string ) : MediaQueryList {
120+ let canListen = isBrowser ( ) && ! ! ( < any > window ) . matchMedia ( 'all' ) . addListener ;
121+
119122 return canListen ? ( < any > window ) . matchMedia ( query ) : < MediaQueryList > {
120123 matches : query === 'all' || query === '' ,
121124 media : query ,
@@ -127,6 +130,13 @@ export class MatchMedia {
127130 }
128131}
129132
133+ /**
134+ * Determine if SSR or Browser rendering.
135+ */
136+ export function isBrowser ( ) {
137+ return getDom ( ) . supportsDOMEvents ( ) ;
138+ }
139+
130140/**
131141 * Private global registry for all dynamically-created, injected style tags
132142 * @see prepare(query)
@@ -140,27 +150,28 @@ const ALL_STYLES = {};
140150 * @param query string The mediaQuery used to create a faux CSS selector
141151 *
142152 */
143- function prepareQueryCSS ( mediaQueries : string [ ] ) {
153+ function prepareQueryCSS ( mediaQueries : string [ ] , _document : any ) {
144154 let list = mediaQueries . filter ( it => ! ALL_STYLES [ it ] ) ;
145155 if ( list . length > 0 ) {
146156 let query = list . join ( ', ' ) ;
157+
147158 try {
148- let style = document . createElement ( 'style' ) ;
159+ let styleEl = getDom ( ) . createElement ( 'style' ) ;
149160
150- style . setAttribute ( 'type' , 'text/css' ) ;
151- if ( ! style [ 'styleSheet' ] ) {
161+ getDom ( ) . setAttribute ( styleEl , 'type' , 'text/css' ) ;
162+ if ( ! styleEl [ 'styleSheet' ] ) {
152163 let cssText = `/*
153164 @angular/flex-layout - workaround for possible browser quirk with mediaQuery listeners
154165 see http://bit.ly/2sd4HMP
155166*/
156167@media ${ query } {.fx-query-test{ }}` ;
157- style . appendChild ( document . createTextNode ( cssText ) ) ;
168+ getDom ( ) . appendChild ( styleEl , getDom ( ) . createTextNode ( cssText ) ) ;
158169 }
159170
160- document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( style ) ;
171+ getDom ( ) . appendChild ( _document . head , styleEl ) ;
161172
162173 // Store in private global registry
163- list . forEach ( mq => ALL_STYLES [ mq ] = style ) ;
174+ list . forEach ( mq => ALL_STYLES [ mq ] = styleEl ) ;
164175
165176 } catch ( e ) {
166177 console . error ( e ) ;
0 commit comments