@@ -76,56 +76,59 @@ export class MatchMedia {
7676 observe ( mediaQuery ?: string ) : Observable < MediaChange > {
7777 this . registerQuery ( mediaQuery ) ;
7878
79- return this . _observable$ . filter ( ( change : MediaChange ) => {
80- return mediaQuery ? ( change . mediaQuery === mediaQuery ) : true ;
81- } ) ;
79+ return this . _observable$
80+ . filter ( ( change : MediaChange ) => {
81+ return mediaQuery ? ( change . mediaQuery === mediaQuery ) : true ;
82+ } ) ;
8283 }
8384
8485 /**
8586 * Based on the BreakPointRegistry provider, register internal listeners for each unique
8687 * mediaQuery. Each listener emits specific MediaChange data to observers
8788 */
88- registerQuery ( mediaQuery : string ) {
89- if ( mediaQuery ) {
90- let mql = this . _registry . get ( mediaQuery ) ;
91- let onMQLEvent = ( e : MediaQueryList ) => {
92- this . _zone . run ( ( ) => {
93- let change = new MediaChange ( e . matches , mediaQuery ) ;
94- this . _source . next ( change ) ;
95- } ) ;
96- } ;
89+ registerQuery ( mediaQuery : string | string [ ] ) {
90+ let list = normalizeQuery ( mediaQuery ) ;
91+
92+ if ( list . length > 0 ) {
93+ prepareQueryCSS ( list ) ;
94+
95+ list . forEach ( query => {
96+ let mql = this . _registry . get ( query ) ;
97+ let onMQLEvent = ( e : MediaQueryList ) => {
98+ this . _zone . run ( ( ) => {
99+ let change = new MediaChange ( e . matches , query ) ;
100+ this . _source . next ( change ) ;
101+ } ) ;
102+ } ;
97103
98- if ( ! mql ) {
99- mql = this . _buildMQL ( mediaQuery ) ;
100- mql . addListener ( onMQLEvent ) ;
101- this . _registry . set ( mediaQuery , mql ) ;
102- }
104+ if ( ! mql ) {
105+ mql = this . _buildMQL ( query ) ;
106+ mql . addListener ( onMQLEvent ) ;
107+ this . _registry . set ( query , mql ) ;
108+ }
103109
104- if ( mql . matches ) {
105- onMQLEvent ( mql ) ; // Announce activate range for initial subscribers
106- }
110+ if ( mql . matches ) {
111+ onMQLEvent ( mql ) ; // Announce activate range for initial subscribers
112+ }
113+ } ) ;
107114 }
108-
109115 }
110116
111117 /**
112118 * Call window.matchMedia() to build a MediaQueryList; which
113119 * supports 0..n listeners for activation/deactivation
114120 */
115121 protected _buildMQL ( query : string ) : MediaQueryList {
116- prepareQueryCSS ( query ) ;
117-
118122 let canListen = ! ! ( < any > window ) . matchMedia ( 'all' ) . addListener ;
119123 return canListen ? ( < any > window ) . matchMedia ( query ) : < MediaQueryList > {
120- matches : query === 'all' || query === '' ,
121- media : query ,
122- addListener : ( ) => {
123- } ,
124- removeListener : ( ) => {
125- }
126- } ;
124+ matches : query === 'all' || query === '' ,
125+ media : query ,
126+ addListener : ( ) => {
127+ } ,
128+ removeListener : ( ) => {
129+ }
130+ } ;
127131 }
128-
129132}
130133
131134/**
@@ -135,31 +138,55 @@ export class MatchMedia {
135138const ALL_STYLES = { } ;
136139
137140/**
138- * For Webkit engines that only trigger the MediaQueryListListener
141+ * For Webkit engines that only trigger the MediaQueryList Listener
139142 * when there is at least one CSS selector for the respective media query.
140143 *
141144 * @param query string The mediaQuery used to create a faux CSS selector
142145 *
143146 */
144- function prepareQueryCSS ( query ) {
145- if ( ! ALL_STYLES [ query ] ) {
147+ function prepareQueryCSS ( mediaQueries : string [ ] ) {
148+ let list = mediaQueries . filter ( it => ! ALL_STYLES [ it ] ) ;
149+ if ( list . length > 0 ) {
150+ let query = list . join ( ", " ) ;
146151 try {
147152 let style = document . createElement ( 'style' ) ;
148153
149154 style . setAttribute ( 'type' , 'text/css' ) ;
150155 if ( ! style [ 'styleSheet' ] ) {
151- let cssText = `@media ${ query } {.fx-query-test{ }}` ;
156+ let cssText = `/*
157+ @angular/flex-layout - workaround for possible browser quirk with mediaQuery listeners
158+ see http://bit.ly/2sd4HMP
159+ */
160+ @media ${ query } {.fx-query-test{ }}` ;
152161 style . appendChild ( document . createTextNode ( cssText ) ) ;
153162 }
154163
155164 document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( style ) ;
156165
157166 // Store in private global registry
158- ALL_STYLES [ query ] = style ;
167+ list . forEach ( mq => ALL_STYLES [ mq ] = style ) ;
159168
160169 } catch ( e ) {
161170 console . error ( e ) ;
162171 }
163172 }
164173}
165174
175+ /**
176+ * Always convert to unique list of queries; for iteration in ::registerQuery()
177+ */
178+ function normalizeQuery ( mediaQuery : string | string [ ] ) : string [ ] {
179+ return ( typeof mediaQuery === 'undefined' ) ? [ ] :
180+ ( typeof mediaQuery === 'string' ) ? [ mediaQuery ] : unique ( mediaQuery as string [ ] ) ;
181+ }
182+
183+ /**
184+ * Filter duplicate mediaQueries in the list
185+ */
186+ function unique ( list : string [ ] ) : string [ ] {
187+ let seen = { } ;
188+ return list . filter ( item => {
189+ return seen . hasOwnProperty ( item ) ? false : ( seen [ item ] = true ) ;
190+ } ) ;
191+ }
192+
0 commit comments