diff --git a/examples/app.html b/examples/app.html index 962fb532..59ddf641 100644 --- a/examples/app.html +++ b/examples/app.html @@ -1,4 +1,7 @@ - + Angular2 Material @@ -7,19 +10,28 @@ - Angular2 Material + Angular2 Material menu - Angular2 Material + Angular2 Material - v{{version}} + v{{version}} - + diff --git a/examples/app.scss b/examples/app.scss index e40be685..dea466db 100644 --- a/examples/app.scss +++ b/examples/app.scss @@ -6,10 +6,9 @@ $md-font-url: '../public/font/'; demos-app { - h1, h2, h3, h4, h5 { + > md-toolbar { font-family: $font-family; } - .fixed-toolbar, .shadow-toolbar { position: fixed; top: 0; diff --git a/ng2-material/components/peekaboo/peekaboo.scss b/ng2-material/components/peekaboo/peekaboo.scss index db2bf7e4..567e65ed 100644 --- a/ng2-material/components/peekaboo/peekaboo.scss +++ b/ng2-material/components/peekaboo/peekaboo.scss @@ -1,11 +1,11 @@ [md-peekaboo] { - &[action=show] { + &[breakAction=show] { display: none; &.md-peekaboo-active { display: inherit; } } - &[action=hide] { + &[breakAction=hide] { display: inherit; &.md-peekaboo-active { display: none; diff --git a/ng2-material/components/peekaboo/peekaboo.ts b/ng2-material/components/peekaboo/peekaboo.ts index b2e2767a..1811653d 100644 --- a/ng2-material/components/peekaboo/peekaboo.ts +++ b/ng2-material/components/peekaboo/peekaboo.ts @@ -1,5 +1,5 @@ import {Directive} from "angular2/core"; -import {Media, MediaListener} from '../../core/util/media'; +import {Media, MediaListener, MEDIA_PRIORITY} from '../../core/util/media'; import {DOM} from "angular2/src/platform/dom/dom_adapter"; import {OnDestroy} from "angular2/core"; import {debounce} from "../../core/util/util"; @@ -8,7 +8,6 @@ import {CONST} from "angular2/src/facade/lang"; import {isPresent} from "angular2/src/facade/lang"; import {Attribute} from "angular2/core"; - /** Different peekaboo actions to apply when active */ @CONST() export class PeekabooAction { @@ -26,17 +25,19 @@ export class PeekabooAction { */ @Directive({ selector: '[md-peekaboo]', - inputs: ['breaks'], + inputs: ['break', 'breakXs', 'breakSm', 'breakMd', 'breakLg', 'breakXl'], host: { '[class.md-peekaboo-active]': 'active', - '[attr.action]': 'action' + '[attr.breakAction]': 'breakAction' } }) export class MdPeekaboo implements OnDestroy { - //TODO(jdd): This is just testing hacks, use mapping size->scrollTop - @Input() breaks: number = 100; - @Input() action: string; + static SIZES: string[] = ['xs', 'sm', 'md', 'lg', 'xl']; + + @Input() break: number = 100; + + @Input() breakAction: string; private _active: boolean; get active(): boolean { @@ -47,21 +48,117 @@ export class MdPeekaboo implements OnDestroy { return window.pageYOffset || document.documentElement.scrollTop; } - constructor(@Attribute('action') action: string) { - this.action = isPresent(action) ? action : PeekabooAction.SHOW; - this._active = this._evaluate(this.scrollTop); + private _breakXs: number = -1; + @Input() set breakXs(value: number) { + this._breakXs = value; + } + + get breakXs(): number { + return this._breakXs; + } + + private _breakSm: number = -1; + @Input() set breakSm(value: number) { + this._breakSm = value; + } + + get breakSm(): number { + return this._breakSm; + } + + private _breakMd: number = -1; + @Input() set breakMd(value: number) { + this._breakMd = value; + } + + get breakMd(): number { + return this._breakMd; + } + + private _breakLg: number = -1; + @Input() set breakLg(value: number) { + this._breakLg = value; + } + + get breakLg(): number { + return this._breakLg; + } + + private _breakXl: number = -1; + @Input() set breakXl(value: number) { + this._breakXl = value; + } + + get breakXl(): number { + return this._breakXl; + } + + private _mediaListeners: MediaListener[] = []; + private _breakpoint: string = null; + + constructor(@Attribute('breakAction') action: string, public media: Media) { + this.breakAction = isPresent(action) ? action : PeekabooAction.SHOW; + this._evaluate(); window.addEventListener('scroll', this._windowScroll); + MdPeekaboo.SIZES.forEach((size: string) => { + this._watchMediaQuery(size); + if (Media.hasMedia(size)) { + this._breakpoint = size; + } + }); } ngOnDestroy(): any { + this._mediaListeners.forEach((l: MediaListener) => { + l.destroy(); + }); + this._mediaListeners = []; window.removeEventListener('scroll', this._windowScroll); } - private _evaluate(scrollTop: number): boolean { - return scrollTop >= this.breaks; + private _watchMediaQuery(size: string) { + let l = this.media.listen(Media.getQuery(size)); + l.onMatched.subscribe((q: string) => { + this._breakpoint = size; + this._evaluate(); + }); + this._mediaListeners.push(l); } private _windowScroll = (ev: Event) => { - this._active = this._evaluate(this.scrollTop); + this._evaluate(); }; + + private _evaluate(): void { + let bp: number = this.break; + switch (this._breakpoint) { + case 'xl': + if (this._breakXl !== -1) { + bp = this._breakXl; + break; + } + case 'lg': + if (this._breakLg !== -1) { + bp = this._breakLg; + break; + } + case 'md': + if (this._breakMd !== -1) { + bp = this._breakMd; + break; + } + case 'sm': + if (this._breakSm !== -1) { + bp = this._breakSm; + break; + } + case 'xs': + if (this._breakXs !== -1) { + bp = this._breakXs; + break; + } + } + this._active = this.scrollTop >= bp; + } + } diff --git a/ng2-material/core/util/media.ts b/ng2-material/core/util/media.ts index e958d26f..be419172 100644 --- a/ng2-material/core/util/media.ts +++ b/ng2-material/core/util/media.ts @@ -115,12 +115,20 @@ export class Media { } static hasMedia(size: string): boolean { - let query = MEDIA[size]; + let query = Media.getQuery(size); if (!query) { - console.warn(`unknown media query size ${size}. Expected one of [${MEDIA_PRIORITY.join(',')}]`); return false; } return window.matchMedia(query).matches; } + static getQuery(size: string): string { + let query = MEDIA[size]; + if (!query) { + console.warn(`unknown media query size ${size}. Expected one of [${MEDIA_PRIORITY.join(',')}]`); + return null; + } + return query; + } + }