5
5
* Use of this source code is governed by an MIT-style license that can be
6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
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' ;
10
10
import { BehaviorSubject } from 'rxjs/BehaviorSubject' ;
11
11
import { Observable } from 'rxjs/Observable' ;
12
12
import { filter } from 'rxjs/operator/filter' ;
@@ -27,7 +27,9 @@ export interface MediaQueryListListener {
27
27
export interface MediaQueryList {
28
28
readonly matches : boolean ;
29
29
readonly media : string ;
30
+
30
31
addListener ( listener : MediaQueryListListener ) : void ;
32
+
31
33
removeListener ( listener : MediaQueryListListener ) : void ;
32
34
}
33
35
@@ -45,7 +47,7 @@ export class MatchMedia {
45
47
protected _source : BehaviorSubject < MediaChange > ;
46
48
protected _observable$ : Observable < MediaChange > ;
47
49
48
- constructor ( protected _zone : NgZone ) {
50
+ constructor ( protected _zone : NgZone , @ Inject ( DOCUMENT ) protected _document : any ) {
49
51
this . _registry = new Map < string , MediaQueryList > ( ) ;
50
52
this . _source = new BehaviorSubject < MediaChange > ( new MediaChange ( true ) ) ;
51
53
this . _observable$ = this . _source . asObservable ( ) ;
@@ -86,7 +88,7 @@ export class MatchMedia {
86
88
let list = normalizeQuery ( mediaQuery ) ;
87
89
88
90
if ( list . length > 0 ) {
89
- prepareQueryCSS ( list ) ;
91
+ prepareQueryCSS ( list , this . _document ) ;
90
92
91
93
list . forEach ( query => {
92
94
let mql = this . _registry . get ( query ) ;
@@ -114,9 +116,12 @@ export class MatchMedia {
114
116
* Call window.matchMedia() to build a MediaQueryList; which
115
117
* supports 0..n listeners for activation/deactivation
116
118
*/
117
- protected _buildMQL ( query : string ) : MediaQueryList {
118
- let canListen = ! ! ( < any > window ) . matchMedia ( 'all' ) . addListener ;
119
- return canListen ? ( < any > window ) . matchMedia ( query ) : < MediaQueryList > {
119
+ protected _buildMQL ( query : string ) : MediaQueryList {
120
+ let canListen = ( typeof matchMedia != 'undefined' ) ;
121
+ if ( canListen ) {
122
+ canListen = ! ! matchMedia ( 'all' ) . addListener ;
123
+ }
124
+ return canListen ? matchMedia ( query ) : < MediaQueryList > {
120
125
matches : query === 'all' || query === '' ,
121
126
media : query ,
122
127
addListener : ( ) => {
@@ -140,27 +145,28 @@ const ALL_STYLES = {};
140
145
* @param query string The mediaQuery used to create a faux CSS selector
141
146
*
142
147
*/
143
- function prepareQueryCSS ( mediaQueries : string [ ] ) {
148
+ function prepareQueryCSS ( mediaQueries : string [ ] , _document : any ) {
144
149
let list = mediaQueries . filter ( it => ! ALL_STYLES [ it ] ) ;
145
150
if ( list . length > 0 ) {
146
151
let query = list . join ( ', ' ) ;
152
+
147
153
try {
148
- let style = document . createElement ( 'style' ) ;
154
+ let styleEl = getDom ( ) . createElement ( 'style' ) ;
149
155
150
- style . setAttribute ( 'type' , 'text/css' ) ;
151
- if ( ! style [ 'styleSheet' ] ) {
156
+ getDom ( ) . setAttribute ( styleEl , 'type' , 'text/css' ) ;
157
+ if ( ! styleEl [ 'styleSheet' ] ) {
152
158
let cssText = `/*
153
159
@angular/flex-layout - workaround for possible browser quirk with mediaQuery listeners
154
160
see http://bit.ly/2sd4HMP
155
161
*/
156
162
@media ${ query } {.fx-query-test{ }}` ;
157
- style . appendChild ( document . createTextNode ( cssText ) ) ;
163
+ getDom ( ) . appendChild ( styleEl , getDom ( ) . createTextNode ( cssText ) ) ;
158
164
}
159
165
160
- document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( style ) ;
166
+ getDom ( ) . appendChild ( _document . head , styleEl ) ;
161
167
162
168
// Store in private global registry
163
- list . forEach ( mq => ALL_STYLES [ mq ] = style ) ;
169
+ list . forEach ( mq => ALL_STYLES [ mq ] = styleEl ) ;
164
170
165
171
} catch ( e ) {
166
172
console . error ( e ) ;
0 commit comments