diff --git a/src/layout/layout.js b/src/layout/layout.js index 43a652a23..e9979acc9 100644 --- a/src/layout/layout.js +++ b/src/layout/layout.js @@ -101,6 +101,7 @@ HEADER_SCROLL: 'mdl-layout__header--scroll', FIXED_HEADER: 'mdl-layout--fixed-header', + FIXED_DRAWER: 'mdl-layout--fixed-drawer', OBFUSCATOR: 'mdl-layout__obfuscator', TAB_BAR: 'mdl-layout__tab-bar', @@ -128,6 +129,17 @@ }; + /** + * Provide local version of matchMedia. This is needed in order to support + * monkey-patching of matchMedia in the unit tests. Due to peculiarities in + * PhantomJS, it doesn't work to monkey patch window.matchMedia directly. + * + * @private + */ + MaterialLayout.prototype.matchMedia_ = function(query) { + return window.matchMedia(query); + }; + /** * Handles scrolling on the content. * @@ -181,12 +193,20 @@ MaterialLayout.prototype.screenSizeHandler_ = function() { if (this.screenSizeMediaQuery_.matches) { this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN); + + if (this.drawer_) { + this.drawer_.setAttribute('aria-hidden', 'true'); + } } else { this.element_.classList.remove(this.CssClasses_.IS_SMALL_SCREEN); // Collapse drawer (if any) when moving to a large screen size. if (this.drawer_) { this.drawer_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); this.obfuscator_.classList.remove(this.CssClasses_.IS_DRAWER_OPEN); + + if (this.element_.classList.contains(this.CssClasses_.FIXED_DRAWER)) { + this.drawer_.setAttribute('aria-hidden', 'false'); + } } } }; @@ -423,7 +443,7 @@ // Keep an eye on screen size, and add/remove auxiliary class for styling // of small screens. - this.screenSizeMediaQuery_ = window.matchMedia( + this.screenSizeMediaQuery_ = this.matchMedia_( /** @type {string} */ (this.Constant_.MAX_WIDTH)); this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this)); this.screenSizeHandler_(); diff --git a/test/unit/layout.js b/test/unit/layout.js index f5a8bdb05..688314f45 100644 --- a/test/unit/layout.js +++ b/test/unit/layout.js @@ -16,6 +16,33 @@ describe('MaterialLayout', function () { + MockMediaQueryList = function(media) { + this.media = media; + this.listeners = []; + } + + MockMediaQueryList.registry = {}; + + MockMediaQueryList.mockMatchMedia = function(query) { + if (! MockMediaQueryList.registry.hasOwnProperty(query)) { + MockMediaQueryList.registry[query] = new MockMediaQueryList(query); + } + return MockMediaQueryList.registry[query]; + } + + MockMediaQueryList.prototype.addListener = function(listener) { + this.listeners.push(listener); + } + + MockMediaQueryList.prototype.triggerMatch = function(matches) { + this.matches = matches; + this.listeners.forEach(function(listener) { + // PhantomJS doesn't support MediaQueryListEvent() so mock the event. + var event = {media: this.media, matches: this.matches}; + listener(event); + }.bind(this)); + } + it('should be globally available', function () { expect(MaterialLayout).to.be.a('function'); }); @@ -99,13 +126,18 @@ describe('MaterialLayout', function () { }); describe('Drawer', function () { + var el; var drawer, drawerBtn; var navLink; beforeEach(function() { - var el = document.createElement('div'); + this.originalMatchMedia = window.MaterialLayout.prototype.matchMedia_; + window.MaterialLayout.prototype.matchMedia_ = MockMediaQueryList.mockMatchMedia; + window.patched = 'yes patched'; + + el = document.createElement('div'); el.innerHTML = '
' + - '