Skip to content

Commit

Permalink
Fix screen resizer memory leak for mdl layout (#6)
Browse files Browse the repository at this point in the history
* Fix mem leak

* Make screenResizeHanlder local and use change event

* Make the media query global

* Loop over all layouts

* Update src/layout/layout.js

Co-authored-by: Ryan Brown <ryan@derivita.com>

* Only add one listener for all layouts

* Formatting adjustments

* Clean Linter

* Add nvmrc

* Clean linter

* Fix es5 error

* Fixing tests that rely on window.mediaQuery

* Clean linter

* No need for .nvmrc

* Register a mock media list if one exists on the static def of layout

* Make screenSizeMediaQuery static and add update docs

* Use static method for storing the matchMedia

* Make matchMedia static and update doc for closure

* Fix test typo

---------

Co-authored-by: Ryan Brown <ryan@derivita.com>
  • Loading branch information
jakelauritsen and ribrdb authored Jul 23, 2024
1 parent d88b3be commit 589db69
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 29 deletions.
63 changes: 38 additions & 25 deletions src/layout/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/
(function() {
'use strict';

/**
* Class constructor for Layout MDL component.
* Implements MDL component design pattern defined at:
Expand Down Expand Up @@ -136,10 +135,14 @@
*
* @private
*/
MaterialLayout.prototype.matchMedia_ = function(query) {
MaterialLayout.matchMedia_ = function(query) {
return window.matchMedia(query);
};

MaterialLayout.screenSizeMediaQuery_ = MaterialLayout.matchMedia_(
/** @type {string} */ (MaterialLayout.prototype.Constant_.MAX_WIDTH));
MaterialLayout.screenSizeMediaQuery_.onchange = screenSizeHandler;

/**
* Handles scrolling on the content.
*
Expand Down Expand Up @@ -186,31 +189,44 @@
};

/**
* Handles changes in screen size.
* Handles screen size changes by updating the layout and drawer elements
* based on the media query change event status.
*
* @param {!MediaQueryList|!MediaQueryListEvent} m - is any object that provides matches
*
* @private
*/
MaterialLayout.prototype.screenSizeHandler_ = function() {
if (this.screenSizeMediaQuery_.matches) {
this.element_.classList.add(this.CssClasses_.IS_SMALL_SCREEN);
function screenSizeHandler(m) {
// modified to query dependent elements rather than binding materialLayout to windows media query result
var materialLayouts = document.querySelectorAll('.mdl-layout');

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);
for (var i = 0; i < materialLayouts.length; i++) {
var layout = materialLayouts[i];

if (this.element_.classList.contains(this.CssClasses_.FIXED_DRAWER)) {
this.drawer_.setAttribute('aria-hidden', 'false');
if (layout) {
var drawerElement = layout.querySelector('.mdl-layout__drawer');

if (m.matches) {
layout.classList.add('is-small-screen');
if (drawerElement) {
drawerElement.setAttribute('aria-hidden', 'true');
}
} else {
layout.classList.remove('is-small-screen');
// Collapse drawer (if any) when moving to a large screen size.
if (drawerElement) {
drawerElement.classList.remove('is-visible');
var obfuscator = layout.querySelector('.mdl-layout__obfuscator'); // corrected selector
if (obfuscator) {
obfuscator.classList.remove('is-visible');
}
if (layout.classList.contains('mdl-layout--fixed-drawer')) {
drawerElement.setAttribute('aria-hidden', 'false');
}
}
}
}
}
};

}
/**
* Handles events of drawer button.
*
Expand All @@ -223,7 +239,6 @@
// prevent scrolling in drawer nav
evt.preventDefault();
} else {
// prevent other keys
return;
}
}
Expand Down Expand Up @@ -433,10 +448,8 @@

// Keep an eye on screen size, and add/remove auxiliary class for styling
// of small screens.
this.screenSizeMediaQuery_ = this.matchMedia_(
/** @type {string} */ (this.Constant_.MAX_WIDTH));
this.screenSizeMediaQuery_.addListener(this.screenSizeHandler_.bind(this));
this.screenSizeHandler_();

screenSizeHandler(MaterialLayout.screenSizeMediaQuery_);

// Initialize tabs, if any.
if (this.header_ && this.tabBar_) {
Expand Down
11 changes: 7 additions & 4 deletions test/unit/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ describe('MaterialLayout', function () {
}

MockMediaQueryList.registry = {};
if(MaterialLayout.screenSizeMediaQuery_){
var query = window.MaterialLayout.prototype.Constant_.MAX_WIDTH
MockMediaQueryList.registry[query] = new MockMediaQueryList(query)
}

MockMediaQueryList.mockMatchMedia = function(query) {
if (! MockMediaQueryList.registry.hasOwnProperty(query)) {
Expand Down Expand Up @@ -131,9 +135,8 @@ describe('MaterialLayout', function () {
var navLink;

beforeEach(function() {
this.originalMatchMedia = window.MaterialLayout.prototype.matchMedia_;
window.MaterialLayout.prototype.matchMedia_ = MockMediaQueryList.mockMatchMedia;
window.patched = 'yes patched';
this.originalMatchMedia = MaterialLayout.matchMedia_;
MaterialLayout.matchMedia_ = MockMediaQueryList.mockMatchMedia;

el = document.createElement('div');
el.innerHTML = '<div class="mdl-layout__header"></div>' +
Expand All @@ -157,7 +160,7 @@ describe('MaterialLayout', function () {
});

afterEach(function() {
window.MaterialLayout.prototype.matchMedia_ = this.originalMatchMedia;
MaterialLayout.matchMedia_ = this.originalMatchMedia;
});

it('should have attribute aria-hidden="true"', function () {
Expand Down

0 comments on commit 589db69

Please sign in to comment.