blob: 6635f0f7404cf17e088b941429c78d13bcafc5ed [file] [log] [blame]
import { Injectable, NgZone, SkipSelf, Optional, Directive, ElementRef, Input, Renderer2, NgModule } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { fromEvent } from 'rxjs/observable/fromEvent';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class TdMediaService {
/**
* @param {?} _ngZone
*/
constructor(_ngZone) {
this._ngZone = _ngZone;
this._resizing = false;
this._queryMap = new Map();
this._querySources = {};
this._queryObservables = {};
this._queryMap.set('xs', '(max-width: 599px)');
this._queryMap.set('gt-xs', '(min-width: 600px)');
this._queryMap.set('sm', '(min-width: 600px) and (max-width: 959px)');
this._queryMap.set('gt-sm', '(min-width: 960px)');
this._queryMap.set('md', '(min-width: 960px) and (max-width: 1279px)');
this._queryMap.set('gt-md', '(min-width: 1280px)');
this._queryMap.set('lg', '(min-width: 1280px) and (max-width: 1919px)');
this._queryMap.set('gt-lg', '(min-width: 1920px)');
this._queryMap.set('xl', '(min-width: 1920px)');
this._queryMap.set('landscape', '(orientation: landscape)');
this._queryMap.set('portrait', '(orientation: portrait)');
this._queryMap.set('print', 'print');
this._resizing = false;
// we make sure that the resize checking happend outside of angular since it happens often
this._globalSubscription = this._ngZone.runOutsideAngular(() => {
return fromEvent(window, 'resize').subscribe(() => {
// way to prevent the resize event from triggering the match media if there is already one event running already.
if (!this._resizing) {
this._resizing = true;
setTimeout(() => {
this._onResize();
this._resizing = false;
}, 100);
}
});
});
}
/**
* Deregisters a query so its stops being notified or used.
* @param {?} query
* @return {?}
*/
deregisterQuery(query) {
if (this._queryMap.get(query.toLowerCase())) {
query = this._queryMap.get(query.toLowerCase());
}
this._querySources[query].unsubscribe();
delete this._querySources[query];
delete this._queryObservables[query];
}
/**
* Used to evaluate whether a given media query is true or false given the current device's screen / window size.
* @param {?} query
* @return {?}
*/
query(query) {
if (this._queryMap.get(query.toLowerCase())) {
query = this._queryMap.get(query.toLowerCase());
}
return this._ngZone.run(() => {
return matchMedia(query).matches;
});
}
/**
* Registers a media query and returns an [Observable] that will re-evaluate and
* return if the given media query matches on window resize.
* Note: don't forget to unsubscribe from [Observable] when finished watching.
* @param {?} query
* @return {?}
*/
registerQuery(query) {
if (this._queryMap.get(query.toLowerCase())) {
query = this._queryMap.get(query.toLowerCase());
}
if (!this._querySources[query]) {
this._querySources[query] = new BehaviorSubject(matchMedia(query).matches);
this._queryObservables[query] = this._querySources[query].asObservable();
}
return this._queryObservables[query];
}
/**
* Trigger a match media event on all subscribed observables.
* @return {?}
*/
broadcast() {
this._onResize();
}
/**
* @return {?}
*/
_onResize() {
for (let /** @type {?} */ query in this._querySources) {
this._ngZone.run(() => {
this._matchMediaTrigger(query);
});
}
}
/**
* @param {?} query
* @return {?}
*/
_matchMediaTrigger(query) {
this._querySources[query].next(matchMedia(query).matches);
}
}
TdMediaService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
TdMediaService.ctorParameters = () => [
{ type: NgZone, },
];
/**
* @param {?} parent
* @param {?} ngZone
* @return {?}
*/
function MEDIA_PROVIDER_FACTORY(parent, ngZone) {
return parent || new TdMediaService(ngZone);
}
const MEDIA_PROVIDER = {
// If there is already a service available, use that. Otherwise, provide a new one.
provide: TdMediaService,
deps: [[new Optional(), new SkipSelf(), TdMediaService], NgZone],
useFactory: MEDIA_PROVIDER_FACTORY,
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class TdMediaToggleDirective {
/**
* @param {?} _renderer
* @param {?} _elementRef
* @param {?} _mediaService
*/
constructor(_renderer, _elementRef, _mediaService) {
this._renderer = _renderer;
this._elementRef = _elementRef;
this._mediaService = _mediaService;
this._matches = false;
this._attributes = {};
this._styles = {};
this._classes = [];
}
/**
* tdMediaToggle: string
* Media query used to evaluate screen/window size.
* Toggles attributes, classes and styles if media query is matched.
* @param {?} query
* @return {?}
*/
set query(query) {
if (!query) {
throw new Error('Query needed for [tdMediaToggle] directive.');
}
this._query = query;
}
/**
* mediaAttributes: {[key: string]: string}
* Attributes to be toggled when media query matches.
* @param {?} attributes
* @return {?}
*/
set attributes(attributes) {
this._attributes = attributes;
}
/**
* mediaClasses: string[]
* CSS Classes to be toggled when media query matches.
* @param {?} classes
* @return {?}
*/
set classes(classes) {
this._classes = classes;
}
/**
* mediaStyles: {[key: string]: string}
* CSS Styles to be toggled when media query matches.
* @param {?} styles
* @return {?}
*/
set styles(styles) {
this._styles = styles;
}
/**
* @return {?}
*/
ngOnInit() {
this._mediaChange(this._mediaService.query(this._query));
this._subscription = this._mediaService.registerQuery(this._query).subscribe((matches) => {
this._mediaChange(matches);
});
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this._subscription) {
this._subscription.unsubscribe();
}
}
/**
* @param {?} matches
* @return {?}
*/
_mediaChange(matches) {
this._matches = matches;
this._changeAttributes();
this._changeClasses();
this._changeStyles();
}
/**
* @return {?}
*/
_changeAttributes() {
for (let /** @type {?} */ attr in this._attributes) {
if (this._matches) {
this._renderer.setAttribute(this._elementRef.nativeElement, attr, this._attributes[attr]);
}
else {
this._renderer.removeAttribute(this._elementRef.nativeElement, attr);
}
}
}
/**
* @return {?}
*/
_changeClasses() {
this._classes.forEach((className) => {
if (this._matches) {
this._renderer.addClass(this._elementRef.nativeElement, className);
}
else {
this._renderer.removeClass(this._elementRef.nativeElement, className);
}
});
}
/**
* @return {?}
*/
_changeStyles() {
for (let /** @type {?} */ style in this._styles) {
if (this._matches) {
this._renderer.setStyle(this._elementRef.nativeElement, style, this._styles[style]);
}
else {
this._renderer.removeStyle(this._elementRef.nativeElement, style);
}
}
}
}
TdMediaToggleDirective.decorators = [
{ type: Directive, args: [{
selector: '[tdMediaToggle]',
},] },
];
/** @nocollapse */
TdMediaToggleDirective.ctorParameters = () => [
{ type: Renderer2, },
{ type: ElementRef, },
{ type: TdMediaService, },
];
TdMediaToggleDirective.propDecorators = {
"query": [{ type: Input, args: ['tdMediaToggle',] },],
"attributes": [{ type: Input, args: ['mediaAttributes',] },],
"classes": [{ type: Input, args: ['mediaClasses',] },],
"styles": [{ type: Input, args: ['mediaStyles',] },],
};
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const TD_MEDIA = [
TdMediaToggleDirective,
];
class CovalentMediaModule {
}
CovalentMediaModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule,
],
declarations: [
TD_MEDIA,
],
exports: [
TD_MEDIA,
],
providers: [
MEDIA_PROVIDER,
],
},] },
];
/** @nocollapse */
CovalentMediaModule.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
export { CovalentMediaModule, TdMediaToggleDirective, TdMediaService, MEDIA_PROVIDER_FACTORY, MEDIA_PROVIDER };
//# sourceMappingURL=covalent-core-media.js.map