@angular/flex-layout
Version:
Angular 2 Flexbox Layout
123 lines • 4.58 kB
JavaScript
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