906 lines
18 KiB
JavaScript
906 lines
18 KiB
JavaScript
/*
|
|
* HS Mega Menu - jQuery Plugin
|
|
* @version: 1.0.0 (Sun, 26 Feb 2017)
|
|
* @requires: jQuery v1.6 or later
|
|
* @author: HtmlStream
|
|
* @event-namespace: .HSMegaMenu
|
|
* @browser-support: IE9+
|
|
* @license:
|
|
*
|
|
* Copyright 2017 HtmlStream
|
|
*
|
|
*/
|
|
;(function($){
|
|
'use strict';
|
|
|
|
|
|
/**
|
|
* Creates a mega menu.
|
|
*
|
|
* @constructor
|
|
* @param {HTMLElement|jQuery} element - The element to create the mega menu for.
|
|
* @param {Object} options - The options
|
|
*/
|
|
function MegaMenu(element, options) {
|
|
|
|
var self = this;
|
|
|
|
/**
|
|
* Current element.
|
|
*
|
|
* @public
|
|
*/
|
|
this.$element = $(element);
|
|
|
|
/**
|
|
* Current options set by the caller including defaults.
|
|
*
|
|
* @public
|
|
*/
|
|
this.options = $.extend(true, {}, MegaMenu.defaults, options);
|
|
|
|
|
|
/**
|
|
* Collection of menu elements.
|
|
*
|
|
* @private
|
|
*/
|
|
this._items = $();
|
|
|
|
|
|
Object.defineProperties( this, {
|
|
|
|
/**
|
|
* Contains composed selector of menu items.
|
|
*
|
|
* @public
|
|
*/
|
|
itemsSelector: {
|
|
get: function() {
|
|
return self.options.classMap.hasSubMenu + ',' +
|
|
self.options.classMap.hasMegaMenu;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Contains chain of active items.
|
|
*
|
|
* @private
|
|
*/
|
|
_tempChain: {
|
|
value: null,
|
|
writable: true
|
|
},
|
|
|
|
/**
|
|
* Contains current behavior state.
|
|
*
|
|
* @public
|
|
*/
|
|
state: {
|
|
value: null,
|
|
writable: true
|
|
}
|
|
|
|
});
|
|
|
|
this.initialize();
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Default options of the mega menu.
|
|
*
|
|
* @public
|
|
*/
|
|
MegaMenu.defaults = {
|
|
event: 'hover',
|
|
direction: 'horizontal',
|
|
breakpoint: 991,
|
|
animationIn: false,
|
|
animationOut: false,
|
|
|
|
rtl: false,
|
|
hideTimeOut: 300,
|
|
|
|
// For 'vertical' direction only
|
|
sideBarRatio: 1/4,
|
|
pageContainer: $('body'),
|
|
|
|
classMap: {
|
|
initialized: '.hs-menu-initialized',
|
|
mobileState: '.hs-mobile-state',
|
|
|
|
subMenu: '.hs-sub-menu',
|
|
hasSubMenu: '.hs-has-sub-menu',
|
|
hasSubMenuActive: '.hs-sub-menu-opened',
|
|
|
|
megaMenu: '.hs-mega-menu',
|
|
hasMegaMenu: '.hs-has-mega-menu',
|
|
hasMegaMenuActive: '.hs-mega-menu-opened'
|
|
},
|
|
|
|
mobileSpeed: 400,
|
|
mobileEasing: 'linear',
|
|
|
|
beforeOpen: function(){},
|
|
beforeClose: function(){},
|
|
afterOpen: function(){},
|
|
afterClose: function(){}
|
|
};
|
|
|
|
|
|
/**
|
|
* Initialization of the plugin.
|
|
*
|
|
* @protected
|
|
*/
|
|
MegaMenu.prototype.initialize = function() {
|
|
|
|
var self = this,
|
|
$w = $(window);
|
|
|
|
if( this.options.rtl ) this.$element.addClass('hs-rtl');
|
|
|
|
this.$element
|
|
.addClass(this.options.classMap.initialized.slice(1))
|
|
.addClass('hs-menu-' + this.options.direction);
|
|
|
|
|
|
|
|
// Independent events
|
|
$w.on('resize.HSMegaMenu', function(e){
|
|
|
|
if( self.resizeTimeOutId ) clearTimeout( self.resizeTimeOutId );
|
|
|
|
self.resizeTimeOutId = setTimeout( function(){
|
|
|
|
if($w.width() <= self.options.breakpoint && self.state == 'desktop') self.initMobileBehavior();
|
|
else if( $w.width() > self.options.breakpoint && self.state == 'mobile' ) self.initDesktopBehavior();
|
|
|
|
self.refresh();
|
|
|
|
}, 50 );
|
|
|
|
});
|
|
|
|
$(document)
|
|
.on('click.HSMegaMenu', function(e){
|
|
|
|
var $parents = $(e.target).parents(self.itemsSelector);
|
|
self.closeAll( $parents.add($(e.target)) );
|
|
|
|
})
|
|
.on('keyup.HSMegaMenu', function(e){
|
|
if( e.keyCode && e.keyCode == 27 ) self.closeAll();
|
|
});
|
|
|
|
if($w.width() <= this.options.breakpoint) this.initMobileBehavior();
|
|
else if( $w.width() > this.options.breakpoint) this.initDesktopBehavior();
|
|
|
|
this.smartPositions();
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
MegaMenu.prototype.smartPositions = function() {
|
|
|
|
var self = this,
|
|
$submenus = this.$element.find( this.options.classMap.subMenu );
|
|
|
|
$submenus.each(function(i, el) {
|
|
|
|
MenuItem.smartPosition( $(el), self.options );
|
|
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* Binding events to menu elements.
|
|
*
|
|
* @protected
|
|
*/
|
|
MegaMenu.prototype.bindEvents = function() {
|
|
|
|
var self = this,
|
|
selector;
|
|
|
|
// Hover case
|
|
if(this.options.event === 'hover' && !_isTouch()) {
|
|
this.$element
|
|
.on(
|
|
'mouseenter.HSMegaMenu',
|
|
this.options.classMap.hasMegaMenu + ':not([data-event="click"]),' +
|
|
this.options.classMap.hasSubMenu + ':not([data-event="click"])',
|
|
function(e) {
|
|
|
|
var $this = $(this),
|
|
$chain = $this.parents( self.itemsSelector);
|
|
|
|
// Lazy initialization
|
|
if( !$this.data('HSMenuItem') ) {
|
|
self.initMenuItem( $this, self.getType( $this ) );
|
|
}
|
|
|
|
$chain = $chain.add($this);
|
|
|
|
self.closeAll( $chain );
|
|
|
|
$chain.each(function(i, el){
|
|
|
|
var HSMenuItem = $(el).data('HSMenuItem');
|
|
|
|
if(HSMenuItem.hideTimeOutId) clearTimeout(HSMenuItem.hideTimeOutId);
|
|
HSMenuItem.show();
|
|
|
|
});
|
|
|
|
self._items = self._items.not( $chain );
|
|
self._tempChain = $chain;
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
)
|
|
.on(
|
|
'mouseleave.HSMegaMenu',
|
|
this.options.classMap.hasMegaMenu + ':not([data-event="click"]),' +
|
|
this.options.classMap.hasSubMenu + ':not([data-event="click"])',
|
|
function(e) {
|
|
|
|
var $this = $(this),
|
|
HSMenuItem = $this.data('HSMenuItem'),
|
|
$chain = $(e.relatedTarget).parents( self.itemsSelector );
|
|
|
|
HSMenuItem.hideTimeOutId = setTimeout( function(){
|
|
self.closeAll( $chain );
|
|
}, self.options.hideTimeOut );
|
|
|
|
self._items = self._items.add( self._tempChain );
|
|
self._tempChain = null;
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
)
|
|
.on(
|
|
'click.HSMegaMenu',
|
|
this.options.classMap.hasMegaMenu + '[data-event="click"] > a, ' +
|
|
this.options.classMap.hasSubMenu + '[data-event="click"] > a',
|
|
function(e) {
|
|
|
|
var $this = $(this).parent('[data-event="click"]'),
|
|
HSMenuItem;
|
|
|
|
// Lazy initialization
|
|
if(!$this.data('HSMenuItem')) {
|
|
self.initMenuItem( $this, self.getType( $this ) );
|
|
}
|
|
|
|
|
|
self.closeAll( $this.add(
|
|
$this.parents(self.itemsSelector)
|
|
) );
|
|
|
|
HSMenuItem = $this
|
|
.data('HSMenuItem');
|
|
|
|
if(HSMenuItem.isOpened) {
|
|
HSMenuItem.hide();
|
|
}
|
|
else{
|
|
HSMenuItem.show();
|
|
}
|
|
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
}
|
|
);
|
|
}
|
|
// Click case
|
|
else {
|
|
|
|
this.$element
|
|
.on(
|
|
'click.HSMegaMenu',
|
|
(_isTouch() ?
|
|
this.options.classMap.hasMegaMenu + ' > a, ' +
|
|
this.options.classMap.hasSubMenu + ' > a' :
|
|
this.options.classMap.hasMegaMenu + ':not([data-event="hover"]) > a,' +
|
|
this.options.classMap.hasSubMenu + ':not([data-event="hover"]) > a'),
|
|
function(e) {
|
|
|
|
var $this = $(this).parent(),
|
|
HSMenuItem,
|
|
$parents = $this.parents(self.itemsSelector);
|
|
|
|
// Lazy initialization
|
|
if(!$this.data('HSMenuItem')) {
|
|
self.initMenuItem( $this, self.getType( $this ) );
|
|
}
|
|
|
|
self.closeAll( $this.add(
|
|
$this.parents( self.itemsSelector )
|
|
) );
|
|
|
|
HSMenuItem = $this
|
|
.addClass('hs-event-prevented')
|
|
.data('HSMenuItem');
|
|
|
|
if(HSMenuItem.isOpened) {
|
|
HSMenuItem.hide();
|
|
}
|
|
else{
|
|
HSMenuItem.show();
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
);
|
|
|
|
if(!_isTouch()) {
|
|
this.$element
|
|
.on(
|
|
'mouseenter.HSMegaMenu',
|
|
this.options.classMap.hasMegaMenu + '[data-event="hover"],' +
|
|
this.options.classMap.hasSubMenu + '[data-event="hover"]',
|
|
function(e) {
|
|
|
|
var $this = $(this),
|
|
$parents = $this.parents( self.itemsSelector);
|
|
|
|
// Lazy initialization
|
|
if( !$this.data('HSMenuItem') ) {
|
|
self.initMenuItem( $this, self.getType( $this ) );
|
|
}
|
|
|
|
self.closeAll( $this.add($parents) );
|
|
|
|
$parents.add($this).each(function(i, el){
|
|
|
|
var HSMenuItem = $(el).data('HSMenuItem');
|
|
|
|
if(HSMenuItem.hideTimeOutId) clearTimeout(HSMenuItem.hideTimeOutId);
|
|
HSMenuItem.show();
|
|
|
|
});
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
)
|
|
.on(
|
|
'mouseleave.HSMegaMenu',
|
|
this.options.classMap.hasMegaMenu + '[data-event="hover"],' +
|
|
this.options.classMap.hasSubMenu + '[data-event="hover"]',
|
|
function(e) {
|
|
|
|
var $this = $(this),
|
|
HSMenuItem = $this.data('HSMenuItem');
|
|
|
|
HSMenuItem.hideTimeOutId = setTimeout( function(){
|
|
|
|
self.closeAll(
|
|
$(e.relatedTarget).parents(self.itemsSelector)
|
|
);
|
|
|
|
}, self.options.hideTimeOut );
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* Initialization of certain menu item.
|
|
*
|
|
* @protected
|
|
*/
|
|
MegaMenu.prototype.initMenuItem = function(element, type) {
|
|
|
|
var self = this,
|
|
Item = new MenuItem(
|
|
element,
|
|
element.children(
|
|
self.options.classMap[type === 'mega-menu' ? 'megaMenu' : 'subMenu']
|
|
),
|
|
$.extend(true, {type: type}, self.options, element.data()),
|
|
self.$element
|
|
);
|
|
|
|
element.data( 'HSMenuItem', Item );
|
|
this._items = this._items.add( element );
|
|
|
|
};
|
|
|
|
/**
|
|
* Destroys of desktop behavior, then makes initialization of mobile behavior.
|
|
*
|
|
* @protected
|
|
*/
|
|
MegaMenu.prototype.initMobileBehavior = function() {
|
|
|
|
var self = this;
|
|
|
|
this.state = 'mobile';
|
|
|
|
this.$element
|
|
.off('.HSMegaMenu')
|
|
.addClass( this.options.classMap.mobileState.slice(1) )
|
|
.on('click.HSMegaMenu', self.options.classMap.hasSubMenu + ' > a, ' + self.options.classMap.hasMegaMenu + ' > a', function(e){
|
|
|
|
var $this = $(this).parent(),
|
|
MenuItemInstance;
|
|
|
|
// Lazy initialization
|
|
if( !$this.data('HSMenuItem') ) {
|
|
self.initMenuItem( $this, self.getType( $this ) );
|
|
}
|
|
|
|
self.closeAll( $this.parents( self.itemsSelector ).add($this) );
|
|
|
|
MenuItemInstance = $this
|
|
.data('HSMenuItem');
|
|
|
|
console.log(MenuItemInstance.isOpened);
|
|
|
|
if(MenuItemInstance.isOpened) {
|
|
MenuItemInstance.mobileHide();
|
|
}
|
|
else {
|
|
MenuItemInstance.mobileShow();
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
})
|
|
.find( this.itemsSelector )
|
|
.not(
|
|
this.options.classMap.hasSubMenuActive + ',' +
|
|
this.options.classMap.hasMegaMenuActive
|
|
)
|
|
.children(
|
|
this.options.classMap.subMenu + ',' +
|
|
this.options.classMap.megaMenu
|
|
)
|
|
.hide();
|
|
|
|
};
|
|
|
|
/**
|
|
* Destroys of mobile behavior, then makes initialization of desktop behavior.
|
|
*
|
|
* @protected
|
|
*/
|
|
MegaMenu.prototype.initDesktopBehavior = function() {
|
|
|
|
this.state = 'desktop';
|
|
|
|
this.$element
|
|
.removeClass(this.options.classMap.mobileState.slice(1))
|
|
.off('.HSMegaMenu')
|
|
.find( this.itemsSelector )
|
|
.not(
|
|
this.options.classMap.hasSubMenuActive + ',' +
|
|
this.options.classMap.hasMegaMenuActive
|
|
)
|
|
.children(
|
|
this.options.classMap.subMenu + ',' +
|
|
this.options.classMap.megaMenu
|
|
)
|
|
.hide();
|
|
|
|
this.bindEvents();
|
|
|
|
};
|
|
|
|
/**
|
|
* Hides all of opened submenus/megamenus.
|
|
*
|
|
* @param {jQuery} except - collection of elements, which shouldn't be closed.
|
|
* @return {jQuery}
|
|
* @public
|
|
*/
|
|
MegaMenu.prototype.closeAll = function(except) {
|
|
|
|
var self = this;
|
|
|
|
return this._items.not(except && except.length ? except : $()).each(function(i, el){
|
|
|
|
$(el)
|
|
.removeClass('hs-event-prevented')
|
|
.data('HSMenuItem')[self.state == 'mobile' ? 'mobileHide' : 'hide']();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* Returns type of sub menu based on specified menu item.
|
|
*
|
|
* @param {jQuery} item
|
|
* @return {String|null}
|
|
* @public
|
|
*/
|
|
MegaMenu.prototype.getType = function( item ) {
|
|
|
|
if(!item || !item.length) return null;
|
|
|
|
return item.hasClass(this.options.classMap.hasSubMenu.slice(1)) ? 'sub-menu' :
|
|
(item.hasClass(this.options.classMap.hasMegaMenu.slice(1)) ? 'mega-menu' : null);
|
|
|
|
};
|
|
|
|
/**
|
|
* Returns current menu state.
|
|
*
|
|
* @return {String}
|
|
* @public
|
|
*/
|
|
MegaMenu.prototype.getState = function() {
|
|
return this.state;
|
|
};
|
|
|
|
/**
|
|
* Updates bounds of all menu items.
|
|
*
|
|
* @return {jQuery}
|
|
* @public
|
|
*/
|
|
MegaMenu.prototype.refresh = function() {
|
|
|
|
return this._items.add( this._tempChain ).each(function(i, el){
|
|
$(el).data('HSMenuItem')._updateMenuBounds();
|
|
});
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates a mega-menu element.
|
|
*
|
|
* @param {jQuery} element
|
|
* @param {jQuery} menu
|
|
* @param {Object} options
|
|
* @param {jQuery} container
|
|
* @constructor
|
|
*/
|
|
function MenuItem(element, menu, options, container) {
|
|
|
|
var self = this;
|
|
|
|
/**
|
|
* Current menu item element.
|
|
*
|
|
* @public
|
|
*/
|
|
this.$element = element;
|
|
|
|
/**
|
|
* Current mega menu element.
|
|
*
|
|
* @public
|
|
*/
|
|
this.menu = menu;
|
|
|
|
/**
|
|
* Item options.
|
|
*
|
|
* @public
|
|
*/
|
|
this.options = options;
|
|
|
|
|
|
/**
|
|
* MegaMenu container.
|
|
*
|
|
* @public
|
|
*/
|
|
this.$container = container;
|
|
|
|
Object.defineProperties(this, {
|
|
|
|
/**
|
|
* Contains css class of menu item element.
|
|
*
|
|
* @public
|
|
*/
|
|
itemClass: {
|
|
get: function() {
|
|
return self.options.type === 'mega-menu' ?
|
|
self.options.classMap.hasMegaMenu :
|
|
self.options.classMap.hasSubMenu;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Contains css active-class of menu item element.
|
|
*
|
|
* @public
|
|
*/
|
|
activeItemClass: {
|
|
get: function() {
|
|
return self.options.type === 'mega-menu' ?
|
|
self.options.classMap.hasMegaMenuActive :
|
|
self.options.classMap.hasSubMenuActive;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Contains css class of menu element.
|
|
*
|
|
* @public
|
|
*/
|
|
menuClass: {
|
|
get: function() {
|
|
return self.options.type === 'mega-menu' ?
|
|
self.options.classMap.megaMenu :
|
|
self.options.classMap.subMenu;
|
|
}
|
|
},
|
|
|
|
isOpened: {
|
|
get: function() {
|
|
return this.$element.hasClass(this.activeItemClass.slice(1));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
|
|
this.menu.addClass('animated').on('click.HSMegaMenu', function(e){
|
|
self._updateMenuBounds();
|
|
});
|
|
|
|
if( this.$element.data('max-width') ) this.menu.css('max-width', this.$element.data('max-width') );
|
|
if( this.$element.data('position') ) this.menu.addClass( 'hs-position-' + this.$element.data('position') );
|
|
|
|
|
|
if( this.options.animationOut ) {
|
|
|
|
this.menu.on('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(e) {
|
|
|
|
if(self.menu.hasClass(self.options.animationOut)) {
|
|
self.$element.removeClass(self.activeItemClass.slice(1));
|
|
self.options.afterClose.call(self, self.$element, self.menu);
|
|
}
|
|
|
|
if(self.menu.hasClass(self.options.animationIn)) {
|
|
self.options.afterOpen.call(self, self.$element, self.menu);
|
|
}
|
|
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Shows the mega-menu item.
|
|
*
|
|
* @public
|
|
* @return {MenuItem}
|
|
*/
|
|
MenuItem.prototype.show = function() {
|
|
if( !this.menu.length ) return this;
|
|
|
|
this.$element.addClass(this.activeItemClass.slice(1));
|
|
|
|
if(this.options.direction == 'horizontal') this.smartPosition( this.menu, this.options );
|
|
|
|
this._updateMenuBounds();
|
|
|
|
if(this.options.animationOut) {
|
|
this.menu.removeClass(this.options.animationOut);
|
|
}
|
|
else {
|
|
this.options.afterOpen.call(this, this.$element, this.menu);
|
|
}
|
|
|
|
if(this.options.animationIn) this.menu.addClass(this.options.animationIn);
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Hides the mega-menu item.
|
|
*
|
|
* @public
|
|
* @return {MenuItem}
|
|
*/
|
|
MenuItem.prototype.hide = function() {
|
|
|
|
var self = this;
|
|
|
|
if( !this.menu.length ) return this;
|
|
|
|
if(!this.options.animationOut) {
|
|
this.$element.removeClass(this.activeItemClass.slice(1));
|
|
}
|
|
|
|
if(this.options.animationIn) this.menu.removeClass(this.options.animationIn);
|
|
if(this.options.animationOut) {
|
|
this.menu
|
|
.addClass(this.options.animationOut);
|
|
}
|
|
else{
|
|
this.options.afterClose.call(this, this.$element, this.menu);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Shows the mega-menu item.
|
|
*
|
|
* @public
|
|
* @return {MenuItem}
|
|
*/
|
|
MenuItem.prototype.mobileShow = function() {
|
|
var self = this;
|
|
|
|
if( !this.menu.length ) return this;
|
|
|
|
|
|
|
|
this.menu
|
|
.removeClass( this.options.animationIn )
|
|
.removeClass( this.options.animationOut )
|
|
.stop()
|
|
.slideDown({
|
|
duration: self.options.mobileSpeed,
|
|
easing: self.options.mobileEasing,
|
|
complete: function() {
|
|
self.options.afterOpen.call(self, self.$element, self.menu);
|
|
}
|
|
});
|
|
|
|
this.$element.addClass(this.activeItemClass.slice(1));
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Hides the mega-menu item.
|
|
*
|
|
* @public
|
|
* @return {MenuItem}
|
|
*/
|
|
MenuItem.prototype.mobileHide = function() {
|
|
var self = this;
|
|
|
|
if( !this.menu.length ) return this;
|
|
|
|
this.menu.stop().slideUp({
|
|
duration: self.options.mobileSpeed,
|
|
easing: self.options.mobileEasing,
|
|
complete: function() {
|
|
self.options.afterClose.call(self, self.$element, self.menu);
|
|
}
|
|
});
|
|
|
|
this.$element.removeClass(this.activeItemClass.slice(1));
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Check, if element is in viewport.
|
|
*
|
|
* @param {jQuery} element
|
|
* @param {Object} options
|
|
* @public
|
|
*/
|
|
MenuItem.prototype.smartPosition = function( element, options ) {
|
|
|
|
MenuItem.smartPosition(element, options);
|
|
|
|
};
|
|
|
|
/**
|
|
* Check, if element is in viewport.
|
|
*
|
|
* @param {jQuery} element
|
|
* @param {Object} options
|
|
* @static
|
|
* @public
|
|
*/
|
|
MenuItem.smartPosition = function( element, options ) {
|
|
if(!element && !element.length) return;
|
|
|
|
var $w = $(window);
|
|
|
|
element.removeClass('hs-reversed');
|
|
|
|
if(!options.rtl) {
|
|
|
|
if( element.offset().left + element.outerWidth() > $w.width() ) {
|
|
element.addClass('hs-reversed');
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
if(element.offset().left < 0) {
|
|
element.addClass('hs-reversed');
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Updates bounds of current opened menu.
|
|
*
|
|
* @private
|
|
*/
|
|
MenuItem.prototype._updateMenuBounds = function() {
|
|
|
|
var width = 'auto';
|
|
|
|
if( this.options.direction == 'vertical' && this.options.type == 'mega-menu' ) {
|
|
|
|
if( this.$container && this.$container.data('HSMegaMenu').getState() == 'desktop' ) {
|
|
if( !this.options.pageContainer.length ) this.options.pageContainer = $('body');
|
|
width = this.options.pageContainer.outerWidth() * (1 - this.options.sideBarRatio);
|
|
}
|
|
else {
|
|
width = 'auto';
|
|
}
|
|
|
|
|
|
this.menu.css({
|
|
'width': width,
|
|
'height': 'auto'
|
|
});
|
|
|
|
if( this.menu.outerHeight() > this.$container.outerHeight() ) {
|
|
return;
|
|
}
|
|
|
|
this.menu.css('height', '100%');
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* The jQuery plugin for the MegaMenu.
|
|
*
|
|
* @public
|
|
*/
|
|
$.fn.HSMegaMenu = function(options) {
|
|
|
|
return this.each(function(i, el) {
|
|
|
|
var $this = $(this);
|
|
|
|
if(!$this.data('HSMegaMenu')) {
|
|
$this.data('HSMegaMenu', new MegaMenu($this, options));
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* Helper function for detect touch events in the environment.
|
|
*
|
|
* @return {Boolean}
|
|
* @private
|
|
*/
|
|
function _isTouch() {
|
|
return ('ontouchstart' in window);
|
|
}
|
|
|
|
})(jQuery); |