iuap-design
Version:
UI Framework Used For Enterprise.
480 lines (421 loc) • 19.3 kB
JavaScript
u.NavLayout = u.BaseComponent.extend({
_Constant: {
MAX_WIDTH: '(max-width: 1024px)',
TAB_SCROLL_PIXELS: 100,
MENU_ICON: 'menu',
CHEVRON_LEFT: 'chevron_left',
CHEVRON_RIGHT: 'chevron_right'
},
/**
* Modes.
*
* @enum {number}
* @private
*/
_Mode: {
STANDARD: 0,
SEAMED: 1,
WATERFALL: 2,
SCROLL: 3
},
/**
* 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
*/
_CssClasses: {
CONTAINER: 'u-navlayout-container',
HEADER: 'u-navlayout-header',
DRAWER: 'u-navlayout-drawer',
CONTENT: 'u-navlayout-content',
DRAWER_BTN: 'u-navlayout-drawer-button',
ICON: 'fa',
//JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
//RIPPLE_CONTAINER: 'mdl-layout__tab-ripple-container',
//RIPPLE: 'mdl-ripple',
//RIPPLE_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events',
HEADER_SEAMED: 'seamed',
HEADER_WATERFALL: 'waterfall',
HEADER_SCROLL: 'scroll',
FIXED_HEADER: 'fixed',
OBFUSCATOR: 'u-navlayout-obfuscator',
TAB_BAR: 'u-navlayout-tab-bar',
TAB_CONTAINER: 'u-navlayout-tab-bar-container',
TAB: 'u-navlayout-tab',
TAB_BAR_BUTTON: 'u-navlayout-tab-bar-button',
TAB_BAR_LEFT_BUTTON: 'u-navlayout-tab-bar-left-button',
TAB_BAR_RIGHT_BUTTON: 'u-navlayout-tab-bar-right-button',
PANEL: 'u-navlayout-tab-panel',
HAS_DRAWER: 'has-drawer',
HAS_TABS: 'has-tabs',
HAS_SCROLLING_HEADER: 'has-scrolling-header',
CASTING_SHADOW: 'is-casting-shadow',
IS_COMPACT: 'is-compact',
IS_SMALL_SCREEN: 'is-small-screen',
IS_DRAWER_OPEN: 'is-visible',
IS_ACTIVE: 'is-active',
IS_UPGRADED: 'is-upgraded',
IS_ANIMATING: 'is-animating',
ON_LARGE_SCREEN: 'u-navlayout-large-screen-only',
ON_SMALL_SCREEN: 'u-navlayout-small-screen-only',
NAV: 'u-nav',
NAV_LINK: 'u-nav-link',
NAV_LINK_CURRENT: 'u-nav-link-current',
NAV_LINK_OPEN: 'u-nav-link-open',
NAV_SUB: 'u-nav-sub'
},
init: function(){
var container = document.createElement('div');
u.addClass(container, this._CssClasses.CONTAINER);
this.element.parentElement.insertBefore(container, this.element);
this.element.parentElement.removeChild(this.element);
container.appendChild(this.element);
var directChildren = this.element.childNodes;
var numChildren = directChildren.length;
for (var c = 0; c < numChildren; c++) {
var child = directChildren[c];
if (u.hasClass(child, this._CssClasses.HEADER)) {
this._header = child;
}
if (u.hasClass(child, this._CssClasses.DRAWER)) {
this._drawer = child;
}
if (u.hasClass(child, this._CssClasses.CONTENT)) {
this._content = child;
var layoutHeight = this.element.offsetHeight;
var headerHeight = typeof this._header === 'undefined' ? 0 : this._header.offsetHeight;
this._content.style.height = layoutHeight - headerHeight + 'px'
var self = this;
u.on(window,'resize', function () {
var layoutHeight = self.element.offsetHeight;
var headerHeight = typeof self._header === 'undefined' ? 0 : self._header.offsetHeight;
self._content.style.height = layoutHeight - headerHeight + 'px'
});
}
}
if (this._header) {
this._tabBar = this._header.querySelector('.' + this._CssClasses.TAB_BAR);
}
var mode = this._Mode.STANDARD;
if (this._header) {
if (u.hasClass(this._header, this._CssClasses.HEADER_SEAMED)) {
mode = this._Mode.SEAMED;
//} else if (u.hasClass(this._header,this._CssClasses.HEADER_SEAMED)) {
// mode = this._Mode.WATERFALL;
// u.on(this._header,'transitionend', this._headerTransitionEndHandler.bind(this));
// // this._header.addEventListener('transitionend', this._headerTransitionEndHandler.bind(this));
// u.on(this._header,'click', this._headerClickHandler.bind(this));
// // this._header.addEventListener('click', this._headerClickHandler.bind(this));
} else if (u.hasClass(this._header, this._CssClasses.HEADER_SCROLL)) {
mode = this._Mode.SCROLL;
u.addClass(container, this._CssClasses.HAS_SCROLLING_HEADER);
}
if (mode === this._Mode.STANDARD) {
u.addClass(this._header, this._CssClasses.CASTING_SHADOW);
if (this._tabBar) {
u.addClass(this._tabBar, this._CssClasses.CASTING_SHADOW);
}
} else if (mode === this._Mode.SEAMED || mode === this._Mode.SCROLL) {
u.removeClass(this._header, this._CssClasses.CASTING_SHADOW);
if (this._tabBar) {
u.removeClass(this._tabBar, this._CssClasses.CASTING_SHADOW);
}
} else if (mode === this._Mode.WATERFALL) {
// Add and remove shadows depending on scroll position.
// Also add/remove auxiliary class for styling of the compact version of
// the header.
u.on(this._content,'scroll',this._contentScrollHandler.bind(this));
this._contentScrollHandler();
}
}
// Add drawer toggling button to our layout, if we have an openable drawer.
if (this._drawer) {
var drawerButton = this.element.querySelector('.' + this._CssClasses.DRAWER_BTN);
if (!drawerButton) {
drawerButton = document.createElement('div');
u.addClass(drawerButton, this._CssClasses.DRAWER_BTN);
var drawerButtonIcon = document.createElement('i');
drawerButtonIcon.className = 'fa fa-bars';
//drawerButtonIcon.textContent = this._Constant.MENU_ICON;
drawerButton.appendChild(drawerButtonIcon);
}
if (u.hasClass(this._drawer, this._CssClasses.ON_LARGE_SCREEN)) {
//If drawer has ON_LARGE_SCREEN class then add it to the drawer toggle button as well.
u.addClass(drawerButton, this._CssClasses.ON_LARGE_SCREEN);
} else if (u.hasClass(this._drawer, this._CssClasses.ON_SMALL_SCREEN)) {
//If drawer has ON_SMALL_SCREEN class then add it to the drawer toggle button as well.
u.addClass(drawerButton, this._CssClasses.ON_SMALL_SCREEN);
}
u.on(drawerButton,'click', this._drawerToggleHandler.bind(this));
// Add a class if the layout has a drawer, for altering the left padding.
// Adds the HAS_DRAWER to the elements since this._header may or may
// not be present.
u.addClass(this.element, this._CssClasses.HAS_DRAWER);
// If we have a fixed header, add the button to the header rather than
// the layout.
if (u.hasClass(this.element, this._CssClasses.FIXED_HEADER) && this._header) {
this._header.insertBefore(drawerButton, this._header.firstChild);
} else {
this.element.insertBefore(drawerButton, this._content);
}
this.drawerButton = drawerButton;
var obfuscator = document.createElement('div');
u.addClass(obfuscator, this._CssClasses.OBFUSCATOR);
this.element.appendChild(obfuscator);
u.on(obfuscator,'click', this._drawerToggleHandler.bind(this));
this._obfuscator = obfuscator;
var leftnav = this.element.querySelector('.' + this._CssClasses.NAV);
u.on(leftnav,'click', this._navlinkClickHander.bind(this));
var items = leftnav.querySelectorAll('.' + this._CssClasses.NAV_LINK);
for(var i=0;i<items.length;i++) {
new u.Ripple(items[i])
}
}
// Keep an eye on screen size, and add/remove auxiliary class for styling
// of small screens.
if(u.isIE8 || u.isIE9){
u.on(window,'resize',this._screenSizeHandler.bind(this));
}else{
this._screenSizeMediaQuery = window.matchMedia(
/** @type {string} */ (this._Constant.MAX_WIDTH));
this._screenSizeMediaQuery.addListener(this._screenSizeHandler.bind(this));
}
this._screenSizeHandler();
// Initialize tabs, if any.
if (this._header && this._tabBar) {
u.addClass(this.element, this._CssClasses.HAS_TABS);
var tabContainer = document.createElement('div');
u.addClass(tabContainer, this._CssClasses.TAB_CONTAINER);
this._header.insertBefore(tabContainer, this._tabBar);
this._header.removeChild(this._tabBar);
var leftButton = document.createElement('div');
u.addClass(leftButton, this._CssClasses.TAB_BAR_BUTTON);
u.addClass(leftButton, this._CssClasses.TAB_BAR_LEFT_BUTTON);
var leftButtonIcon = document.createElement('i');
u.addClass(leftButtonIcon, this._CssClasses.ICON);
leftButtonIcon.textContent = this._Constant.CHEVRON_LEFT;
leftButton.appendChild(leftButtonIcon);
u.on(leftButton,'click', function () {
this._tabBar.scrollLeft -= this._Constant.TAB_SCROLL_PIXELS;
}.bind(this));
var rightButton = document.createElement('div');
u.addClass(rightButton, this._CssClasses.TAB_BAR_BUTTON);
u.addClass(rightButton, this._CssClasses.TAB_BAR_RIGHT_BUTTON);
var rightButtonIcon = document.createElement('i');
u.addClass(rightButtonIcon, this._CssClasses.ICON);
rightButtonIcon.textContent = this._Constant.CHEVRON_RIGHT;
rightButton.appendChild(rightButtonIcon);
u.on(rightButton,'click', function () {
this._tabBar.scrollLeft += this._Constant.TAB_SCROLL_PIXELS;
}.bind(this));
tabContainer.appendChild(leftButton);
tabContainer.appendChild(this._tabBar);
tabContainer.appendChild(rightButton);
// Add and remove buttons depending on scroll position.
var tabScrollHandler = function () {
if (this._tabBar.scrollLeft > 0) {
u.addClass(leftButton, this._CssClasses.IS_ACTIVE);
} else {
u.removeClass(leftButton, this._CssClasses.IS_ACTIVE);
}
if (this._tabBar.scrollLeft <
this._tabBar.scrollWidth - this._tabBar.offsetWidth) {
u.addClass(rightButton, this._CssClasses.IS_ACTIVE);
} else {
u.removeClass(rightButton, this._CssClasses.IS_ACTIVE);
}
}.bind(this);
u.on(this._tabBar,'scroll', tabScrollHandler);
tabScrollHandler();
if (u.hasClass(this._tabBar, this._CssClasses.JS_RIPPLE_EFFECT)) {
u.addClass(this._tabBar, this._CssClasses.RIPPLE_IGNORE_EVENTS);
}
// Select element tabs, document panels
var tabs = this._tabBar.querySelectorAll('.' + this._CssClasses.TAB);
var panels = this._content.querySelectorAll('.' + this._CssClasses.PANEL);
// Create new tabs for each tab element
for (var i = 0; i < tabs.length; i++) {
new UNavLayoutTab(tabs[i], tabs, panels, this);
}
}
u.addClass(this.element, this._CssClasses.IS_UPGRADED);
},
/**
* Handles scrolling on the content.
*
* @private
*/
_contentScrollHandler: function () {
if (u.hasClass(this._header, this._CssClasses.IS_ANIMATING)) {
return;
}
if (this._content.scrollTop > 0 && !u.hasClass(this._header, this._CssClasses.IS_COMPACT)) {
u.addClass(this._header, this._CssClasses.CASTING_SHADOW)
.addClass(this._header, this._CssClasses.IS_COMPACT)
.addClass(this._header, this._CssClasses.IS_ANIMATING);
} else if (this._content.scrollTop <= 0 && u.hasClass(this._header, this._CssClasses.IS_COMPACT)) {
u.removeClass(this._header, this._CssClasses.CASTING_SHADOW)
.removeClass(this._header, this._CssClasses.IS_COMPACT)
.addClass(this._header, this._CssClasses.IS_ANIMATING);
}
},
/**
* Handles changes in screen size.
*
* @private
*/
_screenSizeHandler: function () {
if(u.isIE8 || u.isIE9){
this._screenSizeMediaQuery = {};
var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
if(w > 1024)
this._screenSizeMediaQuery.matches = false;
else
this._screenSizeMediaQuery.matches = true;
}
if (this._screenSizeMediaQuery.matches) {
u.addClass(this.element, this._CssClasses.IS_SMALL_SCREEN);
} else {
u.removeClass(this.element, this._CssClasses.IS_SMALL_SCREEN);
// Collapse drawer (if any) when moving to a large screen size.
if (this._drawer) {
u.removeClass(this._drawer, this._CssClasses.IS_DRAWER_OPEN);
u.removeClass(this._obfuscator, this._CssClasses.IS_DRAWER_OPEN);
}
}
},
/**
* Handles toggling of the drawer.
*
* @private
*/
_drawerToggleHandler: function () {
u.toggleClass(this._drawer, this._CssClasses.IS_DRAWER_OPEN);
u.toggleClass(this._obfuscator, this._CssClasses.IS_DRAWER_OPEN);
},
/**
* Handles (un)setting the `is-animating` class
*
* @private
*/
_headerTransitionEndHandler: function () {
u.removeClass(this._header, this._CssClasses.IS_ANIMATING);
},
/**
* Handles expanding the header on click
*
* @private
*/
_headerClickHandler: function () {
if (u.hasClass(this._header, this._CssClasses.IS_COMPACT)) {
u.removeClass(this._header, this._CssClasses.IS_COMPACT);
u.addClass(this._header, this._CssClasses.IS_ANIMATING);
}
},
/**
* Reset tab state, dropping active classes
*
* @private
*/
_resetTabState: function (tabBar) {
for (var k = 0; k < tabBar.length; k++) {
u.removeClass(tabBar[k], this._CssClasses.IS_ACTIVE);
}
},
/**
* Reset panel state, droping active classes
*
* @private
*/
_resetPanelState: function (panels) {
for (var j = 0; j < panels.length; j++) {
u.removeClass(panels[j], this._CssClasses.IS_ACTIVE);
}
},
_navlinkClickHander: function (e) {
//var _target = e.currentTarget || e.target || e.srcElement;
var curlink = this.element.querySelector('.'+this._CssClasses.NAV_LINK_CURRENT);
curlink && u.removeClass(curlink, this._CssClasses.NAV_LINK_CURRENT);
// if (curlink && u.isIE8){
// var sub = curlink.parentNode.querySelector('.'+this._CssClasses.NAV_SUB);
// if (sub){
// sub.style.maxHeight = '0';
// }
// }
var item = u.closest(e.target, this._CssClasses.NAV_LINK);
if(item){
u.addClass(item, this._CssClasses.NAV_LINK_CURRENT);
var sub = item.parentNode.querySelector('.'+this._CssClasses.NAV_SUB),
open = u.hasClass(item, this._CssClasses.NAV_LINK_OPEN);
if (sub && open){
u.removeClass(item, this._CssClasses.NAV_LINK_OPEN);
if (u.isIE8)
sub.style.maxHeight = 0;
}
if (sub && !open){
u.addClass(item, this._CssClasses.NAV_LINK_OPEN);
if (u.isIE8)
sub.style.maxHeight = '999px';
}
// sub && open && u.removeClass(item, this._CssClasses.NAV_LINK_OPEN);
// sub && !open && u.addClass(item, this._CssClasses.NAV_LINK_OPEN);
}
}
});
/**
* Constructor for an individual tab.
*
* @constructor
* @param {HTMLElement} tab The HTML element for the tab.
* @param {!Array<HTMLElement>} tabs Array with HTML elements for all tabs.
* @param {!Array<HTMLElement>} panels Array with HTML elements for all panels.
* @param {UNavLayout} layout The UNavLayout object that owns the tab.
*/
function UNavLayoutTab(tab, tabs, panels, layout) {
/**
* Auxiliary method to programmatically select a tab in the UI.
*/
function selectTab() {
var href = tab.href.split('#')[1];
var panel = layout._content.querySelector('#' + href);
layout._resetTabState(tabs);
layout._resetPanelState(panels);
u.addClass(tab, layout._CssClasses.IS_ACTIVE);
u.addClass(panel, layout._CssClasses.IS_ACTIVE);
}
//if (layout.tabBar_.classList.contains(layout._CssClasses.JS_RIPPLE_EFFECT)) {
var rippleContainer = document.createElement('span');
u.addClass(rippleContainer, 'u-ripple');
//rippleContainer.classList.add(layout._CssClasses.JS_RIPPLE_EFFECT);
//var ripple = document.createElement('span');
//ripple.classList.add(layout._CssClasses.RIPPLE);
//rippleContainer.appendChild(ripple);
tab.appendChild(rippleContainer);
new URipple(tab)
//}
u.on(tab,'click', function (e) {
if (tab.getAttribute('href').charAt(0) === '#') {
e.preventDefault();
selectTab();
}
});
tab.show = selectTab;
u.on(tab,'click', function (e) {
e.preventDefault();
var href = tab.href.split('#')[1];
var panel = layout._content.querySelector('#' + href);
layout._resetTabState(tabs);
layout._resetPanelState(panels);
u.addClass(tab, layout._CssClasses.IS_ACTIVE);
u.addClass(panel, layout._CssClasses.IS_ACTIVE);
});
}
u.NavLayoutTab = UNavLayoutTab;
u.compMgr.regComp({
comp: u.NavLayout,
compAsString: 'u.NavLayout',
css: 'u-navlayout'
})