Skip to content
This repository has been archived by the owner on Feb 2, 2019. It is now read-only.

Commit

Permalink
feat(util): add Media injectable for media query checks and events
Browse files Browse the repository at this point in the history
  • Loading branch information
justindujardin committed Dec 28, 2015
1 parent 6916e46 commit edc437e
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 7 deletions.
9 changes: 2 additions & 7 deletions examples/components/dialog/basic_usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ import {ElementRef} from "angular2/core";
import {Input} from "angular2/core";
import {DOM} from "angular2/src/platform/dom/dom_adapter";
import {MdDialogConfig, MdDialogBasic, MdDialogRef} from "ng2-material/components/dialog/dialog";


function hasMedia(size: string) {
// TODO: Implement as $mdMedia
return true;
}
import {Media} from "../../../ng2-material/core/util/media";

@Component({selector: 'dialog-basic-usage'})
@View({
Expand All @@ -20,7 +15,7 @@ function hasMedia(size: string) {
export default class DialogBasicUsage {

status = ' ';
customFullscreen = hasMedia('xs') || hasMedia('sm');
customFullscreen = Media.hasMedia('xs') || Media.hasMedia('sm');

constructor(public dialog: MdDialog, public element: ElementRef) {

Expand Down
2 changes: 2 additions & 0 deletions ng2-material/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export * from './components/toolbar/toolbar';

import {MdTabs, MdTab} from './components/tabs/tabs';
import {UrlResolver} from "angular2/compiler";
import {Media} from "./core/util/media";
export * from './components/toolbar/toolbar';

/**
Expand Down Expand Up @@ -115,6 +116,7 @@ export class MaterialTemplateResolver extends UrlResolver {
*/
export const MATERIAL_PROVIDERS: any[] = [
MdDialog,
Media,
MdRadioDispatcher,
provide(UrlResolver, {useValue: new MaterialTemplateResolver()})
];
126 changes: 126 additions & 0 deletions ng2-material/core/util/media.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import {CONST} from "angular2/src/facade/lang";
import {Injectable} from "angular2/core";
import {Output} from "angular2/core";
import {EventEmitter} from "angular2/core";


/**
* As defined in core/style/variables.scss
*
* $layout-breakpoint-xs: 600px !default;
* $layout-breakpoint-sm: 960px !default;
* $layout-breakpoint-md: 1280px !default;
* $layout-breakpoint-lg: 1920px !default;
*
*/
export const MEDIA: any = {
'xs': '(max-width: 599px)',
'gt-xs': '(min-width: 600px)',
'sm': '(min-width: 600px) and (max-width: 959px)',
'gt-sm': '(min-width: 960px)',
'md': '(min-width: 960px) and (max-width: 1279px)',
'gt-md': '(min-width: 1280px)',
'lg': '(min-width: 1280px) and (max-width: 1919px)',
'gt-lg': '(min-width: 1920px)',
'xl': '(min-width: 1920px)'
};

export const MEDIA_PRIORITY: any = [
'xl',
'gt-lg',
'lg',
'gt-md',
'md',
'gt-sm',
'sm',
'gt-xs',
'xs'
];

/**
* Reference to a Media query listener. When you are done with it, call the `destroy` method
* to release its reference.
*/
export class MediaListener {

/**
* Emits when the query that this is listening for changes.
*/
@Output() onMatched: EventEmitter<string> = new EventEmitter<string>();

/**
* Determine if this query is currently matched by the viewport.
* @returns {boolean} True if the query is matched.
*/
get matches(): boolean {
return !this._destroyed && this._mql.matches;
}

private _destroyed: boolean = false;

private _listener: MediaQueryListListener;

constructor(public query: string,
private _mql: MediaQueryList,
private _media: Media) {
this._listener = (mql: MediaQueryList) => this.onMatched.emit(query);
this._mql.addListener(this._listener);
}

/**
* Destroy and unhook this listener.
*/
destroy() {
if (!this._destroyed) {
this._mql.removeListener(this._listener);
this._media.unregisterListener(this);
this._destroyed = true;
this._listener = null;
this._mql = null;
}
}

}

interface IMediaQueryCache {
references:number;
mql:MediaQueryList;
}

/**
* Injectable class for being notified of changes to viewport media queries.
*/
@Injectable()
export class Media {
private _cache: {[query:string]:IMediaQueryCache} = {};

listen(query: string): MediaListener {
let listener = this._cache[query];
if (!listener) {
listener = this._cache[query] = {
mql: window.matchMedia(query),
references: 0
};
}
listener.references++;
return new MediaListener(query, listener.mql, this);
}

unregisterListener(listener: MediaListener): void {
let cached = this._cache[listener.query];
if (cached) {
cached.references--;
delete this._cache[listener.query];
}
}

static hasMedia(size: string): boolean {
let query = MEDIA[size];
if (!query) {
console.warn(`unknown media query size ${size}. Expected one of [${MEDIA_PRIORITY.join(',')}]`);
return false;
}
return window.matchMedia(query).matches;
}

}

0 comments on commit edc437e

Please sign in to comment.