UNPKG

@angular/flex-layout

Version:
123 lines 4.58 kB
import { Injectable, NgZone } from '@angular/core'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; import { MediaChange } from './media-change'; /** * MediaMonitor configures listeners to mediaQuery changes and publishes an Observable facade to * convert mediaQuery change callbacks to subscriber notifications. These notifications will be * performed within the ng Zone to trigger change detections and component updates. * * NOTE: both mediaQuery activations and de-activations are announced in notifications */ export var MatchMedia = (function () { function MatchMedia(_zone) { this._zone = _zone; this._registry = new Map(); this._source = new BehaviorSubject(new MediaChange(true)); this._observable$ = this._source.asObservable(); } /** * For the specified mediaQuery? */ MatchMedia.prototype.isActive = function (mediaQuery) { if (this._registry.has(mediaQuery)) { var mql = this._registry.get(mediaQuery); return mql.matches; } return false; }; /** * External observers can watch for all (or a specific) mql changes. * Typically used by the MediaQueryAdaptor; optionally available to components * who wish to use the MediaMonitor as mediaMonitor$ observable service. * * NOTE: if a mediaQuery is not specified, then ALL mediaQuery activations will * be announced. */ MatchMedia.prototype.observe = function (mediaQuery) { this.registerQuery(mediaQuery); return this._observable$.filter(function (change) { return mediaQuery ? (change.mediaQuery === mediaQuery) : true; }); }; /** * Based on the BreakPointRegistry provider, register internal listeners for each unique * mediaQuery. Each listener emits specific MediaChange data to observers */ MatchMedia.prototype.registerQuery = function (mediaQuery) { var _this = this; if (mediaQuery) { var mql = this._registry.get(mediaQuery); var onMQLEvent = function (e) { _this._zone.run(function () { var change = new MediaChange(e.matches, mediaQuery); _this._source.next(change); }); }; if (!mql) { mql = this._buildMQL(mediaQuery); mql.addListener(onMQLEvent); this._registry.set(mediaQuery, mql); } if (mql.matches) { onMQLEvent(mql); // Announce activate range for initial subscribers } } }; /** * Call window.matchMedia() to build a MediaQueryList; which * supports 0..n listeners for activation/deactivation */ MatchMedia.prototype._buildMQL = function (query) { prepareQueryCSS(query); var canListen = !!window.matchMedia('all').addListener; return canListen ? window.matchMedia(query) : { matches: query === 'all' || query === '', media: query, addListener: function () { }, removeListener: function () { } }; }; MatchMedia.decorators = [ { type: Injectable }, ]; /** @nocollapse */ MatchMedia.ctorParameters = function () { return [ { type: NgZone, }, ]; }; return MatchMedia; }()); /** * Private global registry for all dynamically-created, injected style tags * @see prepare(query) */ var ALL_STYLES = {}; /** * For Webkit engines that only trigger the MediaQueryListListener * when there is at least one CSS selector for the respective media query. * * @param query string The mediaQuery used to create a faux CSS selector * */ function prepareQueryCSS(query) { if (!ALL_STYLES[query]) { try { var style = document.createElement('style'); style.setAttribute('type', 'text/css'); if (!style['styleSheet']) { var cssText = "@media " + query + " {.fx-query-test{ }}"; style.appendChild(document.createTextNode(cssText)); } document.getElementsByTagName('head')[0].appendChild(style); // Store in private global registry ALL_STYLES[query] = style; } catch (e) { console.error(e); } } } //# sourceMappingURL=/usr/local/google/home/tinagao/WebstormProjects/caretaker/flex-layout/src/lib/media-query/match-media.js.map