Updated Layout to new JS Design pattern
Updated Layout component to use new JS design pattern as defined at: https://github.com/jasonmayes/wsk-component-design-patternmaster
parent
3d6939769f
commit
5a84e7eba8
|
@ -303,7 +303,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="../third_party/wskComponentHandler.js"></script>
|
||||||
<!-- build:js(app/styleguide/layout/) ../../scripts/main.min.js -->
|
<!-- build:js(app/styleguide/layout/) ../../scripts/main.min.js -->
|
||||||
<script src="layout.js"></script>
|
<script src="layout.js"></script>
|
||||||
<script src="../textfield/textfield.js"></script>
|
<script src="../textfield/textfield.js"></script>
|
||||||
|
|
|
@ -1,85 +1,190 @@
|
||||||
window.addEventListener('load', function() {
|
/**
|
||||||
|
* Class constructor for Layout WSK component.
|
||||||
|
* Implements WSK component design pattern defined at:
|
||||||
|
* https://github.com/jasonmayes/wsk-component-design-pattern
|
||||||
|
* @param {HTMLElement} element The element that will be upgraded.
|
||||||
|
*/
|
||||||
|
function MaterialLayout(element) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var layouts = document.querySelectorAll('.wsk-js-layout');
|
this.element_ = element;
|
||||||
var MODE = {
|
|
||||||
|
// Initialize instance.
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store constants in one place so they can be updated easily.
|
||||||
|
* @enum {string | number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.Constant_ = {
|
||||||
|
MAX_WIDTH: '(max-width: 850px)'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modes.
|
||||||
|
* @enum {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.Mode_ = {
|
||||||
STANDARD: 0,
|
STANDARD: 0,
|
||||||
SEAMED: 1,
|
SEAMED: 1,
|
||||||
WATERFALL: 2,
|
WATERFALL: 2,
|
||||||
SCROLL: 3
|
SCROLL: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
var SHADOW_CLASS = 'is-casting-shadow';
|
|
||||||
var COMPACT_CLASS = 'is-compact';
|
|
||||||
var SMALL_SCREEN_CLASS = 'is-small-screen';
|
|
||||||
var DRAWER_OPEN_CLASS = 'is-visible';
|
|
||||||
|
|
||||||
var scrollHandlerGenerator = function(header, content) {
|
/**
|
||||||
|
* Store strings for class names defined by this component that are used in
|
||||||
|
* JavaScript. This allows us to simply change it in one place should we
|
||||||
|
* decide to modify at a later date.
|
||||||
|
* @enum {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.CssClasses_ = {
|
||||||
|
/**
|
||||||
|
* Class names should use camelCase and be prefixed with the word "material"
|
||||||
|
* to minimize conflict with 3rd party systems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Upgrade classnames in HTML / CSS / JS to use material prefix to
|
||||||
|
// reduce conflict and convert to camelCase for consistency.
|
||||||
|
WSK_LAYOUT_HEADER: 'wsk-layout__header',
|
||||||
|
|
||||||
|
WSK_LAYOUT_DRAWER: 'wsk-layout__drawer',
|
||||||
|
|
||||||
|
WSK_LAYOUT_CONTENT: 'wsk-layout__content',
|
||||||
|
|
||||||
|
WSK_LAYOUT_HEADER_SEAMED: 'wsk-layout__header--seamed',
|
||||||
|
|
||||||
|
WSK_LAYOUT_HEADER_WATERFALL: 'wsk-layout__header--waterfall',
|
||||||
|
|
||||||
|
WSK_LAYOUT_HEADER_SCROLL: 'wsk-layout__header--scroll',
|
||||||
|
|
||||||
|
WSK_LAYOUT_DRAWER_BTN: 'wsk-layout__drawer-button',
|
||||||
|
|
||||||
|
WSK_LAYOUT_FIXED_HEADER: 'wsk-layout--fixed-header',
|
||||||
|
|
||||||
|
WSK_LAYOUT_OBFUSCATOR: 'wsk-layout__obfuscator',
|
||||||
|
|
||||||
|
SHADOW_CLASS: 'is-casting-shadow',
|
||||||
|
|
||||||
|
COMPACT_CLASS: 'is-compact',
|
||||||
|
|
||||||
|
SMALL_SCREEN_CLASS: 'is-small-screen',
|
||||||
|
|
||||||
|
DRAWER_OPEN_CLASS: 'is-visible'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a scroll handler function.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.scrollHandlerGenerator_ = function(header, content) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
if (content.scrollTop > 0) {
|
if (content.scrollTop > 0) {
|
||||||
header.classList.add(SHADOW_CLASS);
|
header.classList.add(this.CssClasses_.SHADOW_CLASS);
|
||||||
header.classList.add(COMPACT_CLASS);
|
header.classList.add(this.CssClasses_.COMPACT_CLASS);
|
||||||
} else {
|
} else {
|
||||||
header.classList.remove(SHADOW_CLASS);
|
header.classList.remove(this.CssClasses_.SHADOW_CLASS);
|
||||||
header.classList.remove(COMPACT_CLASS);
|
header.classList.remove(this.CssClasses_.COMPACT_CLASS);
|
||||||
}
|
}
|
||||||
};
|
}.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
var screenSizeHandlerGenerator = function(mediaQuery, layout, drawer) {
|
|
||||||
|
/**
|
||||||
|
* Generate a screenSize handler function.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.screenSizeHandlerGenerator_ =
|
||||||
|
function(mediaQuery, layout, drawer) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
if (mediaQuery.matches) {
|
if (mediaQuery.matches) {
|
||||||
layout.classList.add(SMALL_SCREEN_CLASS);
|
layout.classList.add(this.CssClasses_.SMALL_SCREEN_CLASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
layout.classList.remove(SMALL_SCREEN_CLASS);
|
layout.classList.remove(this.CssClasses_.SMALL_SCREEN_CLASS);
|
||||||
// Collapse drawer (if any) when moving to a large screen size.
|
// Collapse drawer (if any) when moving to a large screen size.
|
||||||
if (drawer) {
|
if (drawer) {
|
||||||
drawer.classList.remove(DRAWER_OPEN_CLASS);
|
drawer.classList.remove(this.CssClasses_.DRAWER_OPEN_CLASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
var drawerToggleHandlerGenerator = function(drawer) {
|
|
||||||
|
/**
|
||||||
|
* Generate a drawerToggle handler function.
|
||||||
|
* @param {Event} event The event that fired.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
MaterialLayout.prototype.drawerToggleHandlerGenerator_ =
|
||||||
|
function(drawer) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
drawer.classList.toggle(DRAWER_OPEN_CLASS);
|
drawer.classList.toggle(this.CssClasses_.DRAWER_OPEN_CLASS);
|
||||||
};
|
}.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var i = 0; i < layouts.length; i++) {
|
|
||||||
var layout = layouts[i];
|
/**
|
||||||
var header = layout.querySelector('.wsk-layout__header');
|
* Initialize element.
|
||||||
var drawer = layout.querySelector('.wsk-layout__drawer');
|
*/
|
||||||
var content = layout.querySelector('.wsk-layout__content');
|
MaterialLayout.prototype.init = function() {
|
||||||
var mode = MODE.STANDARD;
|
'use strict';
|
||||||
|
|
||||||
|
if (this.element_) {
|
||||||
|
var header = this.element_.querySelector('.' +
|
||||||
|
this.CssClasses_.WSK_LAYOUT_HEADER);
|
||||||
|
var drawer = this.element_.querySelector('.' +
|
||||||
|
this.CssClasses_.WSK_LAYOUT_DRAWER);
|
||||||
|
var content = this.element_.querySelector('.' +
|
||||||
|
this.CssClasses_.WSK_LAYOUT_CONTENT);
|
||||||
|
|
||||||
|
var mode = this.Mode_.STANDARD;
|
||||||
|
|
||||||
// Keep an eye on screen size, and add/remove auxiliary class for styling
|
// Keep an eye on screen size, and add/remove auxiliary class for styling
|
||||||
// of small screens.
|
// of small screens.
|
||||||
var mediaQuery = window.matchMedia('(max-width: 850px)');
|
var mediaQuery = window.matchMedia(this.Constant_.MAX_WIDTH);
|
||||||
var screenSizeHandler =
|
var screenSizeHandler =
|
||||||
screenSizeHandlerGenerator(mediaQuery, layout, drawer);
|
this.screenSizeHandlerGenerator_(mediaQuery, this.element_,
|
||||||
|
drawer).bind(this);
|
||||||
mediaQuery.addListener(screenSizeHandler);
|
mediaQuery.addListener(screenSizeHandler);
|
||||||
screenSizeHandler();
|
screenSizeHandler();
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
if (header.classList.contains('wsk-layout__header--seamed')) {
|
if (header.classList.contains(
|
||||||
mode = MODE.SEAMED;
|
this.CssClasses_.WSK_LAYOUT_HEADER_SEAMED)) {
|
||||||
} else if (header.classList.contains('wsk-layout__header--waterfall')) {
|
mode = this.Mode_.SEAMED;
|
||||||
mode = MODE.WATERFALL;
|
} else if (header.classList.contains(
|
||||||
} else if (layout.classList.contains('wsk-layout__header--scroll')) {
|
this.CssClasses_.WSK_LAYOUT_HEADER_WATERFALL)) {
|
||||||
mode = MODE.SCROLL;
|
mode = this.Mode_.WATERFALL;
|
||||||
|
} else if (this.element_.classList.contains(
|
||||||
|
this.CssClasses_.WSK_LAYOUT_HEADER_SCROLL)) {
|
||||||
|
mode = this.Mode_.SCROLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === MODE.STANDARD) {
|
if (mode === this.Mode_.STANDARD) {
|
||||||
header.classList.add(SHADOW_CLASS);
|
header.classList.add(this.CssClasses_.SHADOW_CLASS);
|
||||||
} else if (mode === MODE.SEAMED || mode === MODE.SCROLL) {
|
} else if (mode === this.Mode_.SEAMED || mode === this.Mode_.SCROLL) {
|
||||||
header.classList.remove(SHADOW_CLASS);
|
header.classList.remove(this.CssClasses_.SHADOW_CLASS);
|
||||||
} else if (mode === MODE.WATERFALL) {
|
} else if (mode === this.Mode_.WATERFALL) {
|
||||||
// Add and remove shadows depending on scroll position.
|
// Add and remove shadows depending on scroll position.
|
||||||
// Also add/remove auxiliary class for styling of the compact version of
|
// Also add/remove auxiliary class for styling of the compact version of
|
||||||
// the header.
|
// the header.
|
||||||
var scrollHandler = scrollHandlerGenerator(header, content);
|
var scrollHandler = this.scrollHandlerGenerator_(header,
|
||||||
|
content).bind(this);
|
||||||
content.addEventListener('scroll', scrollHandler);
|
content.addEventListener('scroll', scrollHandler);
|
||||||
scrollHandler();
|
scrollHandler();
|
||||||
}
|
}
|
||||||
|
@ -88,23 +193,36 @@ window.addEventListener('load', function() {
|
||||||
// Add drawer toggling button to our layout, if we have an openable drawer.
|
// Add drawer toggling button to our layout, if we have an openable drawer.
|
||||||
if (drawer) {
|
if (drawer) {
|
||||||
var drawerButton = document.createElement('div');
|
var drawerButton = document.createElement('div');
|
||||||
drawerButton.classList.add('wsk-layout__drawer-button');
|
drawerButton.classList.add(this.CssClasses_.WSK_LAYOUT_DRAWER_BTN);
|
||||||
var clickHandler = drawerToggleHandlerGenerator(drawer);
|
var clickHandler = this.drawerToggleHandlerGenerator_(drawer).bind(this);
|
||||||
drawerButton.addEventListener('click', clickHandler);
|
drawerButton.addEventListener('click', clickHandler);
|
||||||
|
|
||||||
// If we have a fixed header, add the button to the header rather than
|
// If we have a fixed header, add the button to the header rather than
|
||||||
// the layout.
|
// the layout.
|
||||||
if (layout.classList.contains('wsk-layout--fixed-header')) {
|
if (this.element_.classList.contains(
|
||||||
|
this.CssClasses_.WSK_LAYOUT_FIXED_HEADER)) {
|
||||||
header.insertBefore(drawerButton, header.firstChild);
|
header.insertBefore(drawerButton, header.firstChild);
|
||||||
} else {
|
} else {
|
||||||
layout.insertBefore(drawerButton, content);
|
this.element_.insertBefore(drawerButton, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
var obfuscator = document.createElement('div');
|
var obfuscator = document.createElement('div');
|
||||||
obfuscator.classList.add('wsk-layout__obfuscator');
|
obfuscator.classList.add(this.CssClasses_.WSK_LAYOUT_OBFUSCATOR);
|
||||||
layout.appendChild(obfuscator);
|
this.element_.appendChild(obfuscator);
|
||||||
obfuscator.addEventListener('click', clickHandler);
|
obfuscator.addEventListener('click', clickHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// On document ready, the component registers itself. It can assume
|
||||||
|
// componentHandler is available in the global scope.
|
||||||
|
componentHandler.register({
|
||||||
|
constructor: MaterialLayout,
|
||||||
|
classAsString: 'MaterialLayout',
|
||||||
|
cssClass: 'wsk-js-layout'
|
||||||
|
});
|
||||||
});
|
});
|
Loading…
Reference in New Issue