2022-09-08 08:04:32 -07:00

1096 lines
24 KiB
JavaScript

/**
* HSHeaderSide Component.
*
* @author Htmlstream
* @version 1.0
* @requires HSScrollBar component (hs.scrollbar.js v1.0.0), jQuery(v2.0.0)
*
*/
;(function ($) {
'use strict';
$.HSCore.components.HSHeaderSide = {
/**
* Base configuration.
*
* @private
*/
_baseConfig: {
headerBreakpoint: null,
breakpointsMap: {
'md': 768,
'sm': 576,
'lg': 992,
'xl': 1200
},
afterOpen: function(){},
afterClose: function(){}
},
/**
* Contains collection of all initialized items on the page.
*
* @private
*/
_pageCollection: $(),
/**
* Initializtion of the component.
*
* @param {jQuery} collection
* @param {Object} config
*
* @public
* @returns {jQuery}
*/
init: function(collection, config) {
var _self = this;
if(!collection || !collection.length) return $();
this.$w = $(window);
config = config && $.isPlainObject(config) ? config : {};
this._bindGlobalEvents();
return collection.each(function(i, el){
var $this = $(el),
itemConfig = $.extend(true, {}, _self._baseConfig, config, $this.data());
if( $this.data('HSHeaderSide') ) return;
$this.data('HSHeaderSide', _self._factoryMethod( $this, itemConfig ) );
_self._pageCollection = _self._pageCollection.add($this);
});
},
/**
* Binds necessary global events.
*
* @private
*/
_bindGlobalEvents: function() {
var _self = this;
this.$w.on('resize.HSHeaderSide', function(e){
if(_self.resizeTimeoutId) clearTimeout(_self.resizeTimeoutId);
_self.resizeTimeoutId = setTimeout(function(){
_self._pageCollection.each(function(i, el){
var HSHeaderSide = $(el).data('HSHeaderSide');
if(!HSHeaderSide.config.headerBreakpoint) return;
if(_self.$w.width() < HSHeaderSide.config.breakpointsMap[HSHeaderSide.config.headerBreakpoint] && HSHeaderSide.isInit()) {
HSHeaderSide.destroy();
}
else if(_self.$w.width() >= HSHeaderSide.config.breakpointsMap[HSHeaderSide.config.headerBreakpoint] && !HSHeaderSide.isInit()) {
HSHeaderSide.init();
}
});
}, 10);
});
$(document).on('keyup.HSHeaderSide', function(e){
if(e.keyCode && e.keyCode === 27) {
_self._pageCollection.each(function(i,el){
var HSHeaderSide = $(el).data('HSHeaderSide'),
hamburgers = HSHeaderSide.invoker;
if(!HSHeaderSide) return;
if(hamburgers.length && hamburgers.find('.is-active').length) hamburgers.find('.is-active').removeClass('is-active');
HSHeaderSide.hide();
});
}
});
},
/**
* Returns an object which would be describe the Header behavior.
*
* @private
* @returns {HSHeaderSide*}
*/
_factoryMethod: function(element, config) {
// static
if( !config.headerBehavior ) {
return new (config['headerPosition'] == "left" ? HSHeaderSideStaticLeft : HSHeaderSideStaticRight)(element, config);
}
// overlay
if( config.headerBehavior && config.headerBehavior == 'overlay' ) {
return new (config['headerPosition'] == "left" ? HSHeaderSideOverlayLeft : HSHeaderSideOverlayRight)(element, config);
}
// push
if( config.headerBehavior && config.headerBehavior == 'push' ) {
return new (config['headerPosition'] == "left" ? HSHeaderSidePushLeft : HSHeaderSidePushRight)(element, config);
}
}
}
/**
* Provides an abstract interface for the side header.
*
* @param {jQuery} element
* @param {Object} config
*
*/
function _HSHeaderSideAbstract(element, config) {
/**
* Contains link to the current element.
*
* @public
*/
this.element = element;
/**
* Contains configuration object.
*
* @public
*/
this.config = config;
/**
* Contains link to the window object.
*
* @public
*/
this.$w = $(window);
/**
* Contains name of methods which should be implemented in derived class.
* Each of these methods except 'isInit' must return link to the current object.
*
* @private
*/
this._abstractMethods = ['init', 'destroy', 'show', 'hide', 'isInit'];
/**
* Runs initialization of the object.
*
* @private
*/
this._build = function() {
if( !this.config.headerBreakpoint ) return this.init();
if( this.config.breakpointsMap[ this.config.headerBreakpoint ] <= this.$w.width() ) {
return this.init();
}
else {
return this.destroy();
}
};
/**
* Checks whether derived class implements necessary abstract events.
*
* @private
*/
this._isCorrectDerrivedClass = function() {
var _self = this;
this._abstractMethods.forEach(function(method){
if(!(method in _self) || !$.isFunction(_self[method])) {
throw new Error("HSHeaderSide: Derived class must implement " + method + " method.");
}
});
this._build();
};
setTimeout(this._isCorrectDerrivedClass.bind(this), 10);
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSideStaticLeft( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
this.body = $('body');
};
/**
* Initialization of the HSHeaderSideStaticLeft instance.
*
* @public
* @returns {HSHeaderSideStaticLeft}
*/
HSHeaderSideStaticLeft.prototype.init = function() {
this.body.addClass('u-body--header-side-static-left');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
return this;
};
/**
* Destroys the HSHeaderSideStaticLeft instance.
*
* @public
* @returns {HSHeaderSideStaticLeft}
*/
HSHeaderSideStaticLeft.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-static-left');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSideStaticLeft.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-static-left');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSideStaticLeft}
*/
HSHeaderSideStaticLeft.prototype.show = function() {
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSideStaticLeft}
*/
HSHeaderSideStaticLeft.prototype.hide = function() {
return this;
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSideStaticRight( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
this.body = $('body');
};
/**
* Initialization of the HSHeaderSideStaticRight instance.
*
* @public
* @returns {HSHeaderSideStaticRight}
*/
HSHeaderSideStaticRight.prototype.init = function() {
this.body.addClass('u-body--header-side-static-right');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
return this;
};
/**
* Destroys the HSHeaderSideStaticRight instance.
*
* @public
* @returns {HSHeaderSideStaticRight}
*/
HSHeaderSideStaticRight.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-static-right');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSideStaticRight.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-static-right');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSideStaticRight}
*/
HSHeaderSideStaticRight.prototype.show = function() {
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSideStaticRight}
*/
HSHeaderSideStaticRight.prototype.hide = function() {
return this;
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSideOverlayLeft( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
Object.defineProperty(this, 'isShown', {
get: function() {
return this.body.hasClass('u-body--header-side-opened');
}
});
Object.defineProperty(this, 'overlayClasses', {
get: function() {
return this.element.data('header-overlay-classes') ? this.element.data('header-overlay-classes') : '';
}
});
Object.defineProperty(this, 'headerClasses', {
get: function() {
return this.element.data('header-classes') ? this.element.data('header-classes') : '';
}
});
this.body = $('body');
this.invoker = $('[data-target="#'+this.element.attr('id')+'"]');
};
/**
* Initialization of the HSHeaderSideOverlayLeft instance.
*
* @public
* @returns {HSHeaderSideOverlayLeft}
*/
HSHeaderSideOverlayLeft.prototype.init = function() {
var _self = this;
this.body.addClass('u-body--header-side-overlay-left');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
if(this.invoker.length) {
this.invoker.on('click.HSHeaderSide', function(e){
if(_self.isShown) {
_self.hide();
}
else {
_self.show();
}
e.preventDefault();
}).css('display', 'block');
}
if(!this.overlay) {
this.overlay = $('<div></div>', {
class: 'u-header__overlay ' + _self.overlayClasses
});
}
this.overlay.on('click.HSHeaderSide', function(e){
var hamburgers = _self.invoker.length ? _self.invoker.find('.is-active') : $();
if(hamburgers.length) hamburgers.removeClass('is-active');
_self.hide();
});
this.element.addClass(this.headerClasses).append(this.overlay);
return this;
};
/**
* Destroys the HSHeaderSideOverlayLeft instance.
*
* @public
* @returns {HSHeaderSideOverlayLeft}
*/
HSHeaderSideOverlayLeft.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-overlay-left');
this.hide();
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
this.element.removeClass(this.headerClasses);
if(this.invoker.length) {
this.invoker.off('click.HSHeaderSide').css('display', 'none');
}
if(this.overlay) {
this.overlay.off('click.HSHeaderSide');
this.overlay.remove();
this.overlay = null;
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSideOverlayLeft.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-overlay-left');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSideOverlayLeft}
*/
HSHeaderSideOverlayLeft.prototype.show = function() {
this.body.addClass('u-body--header-side-opened');
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSideOverlayLeft}
*/
HSHeaderSideOverlayLeft.prototype.hide = function() {
// var hamburgers = this.invoker.length ? this.invoker.find('.is-active') : $();
// if(hamburgers.length) hamburgers.removeClass('is-active');
this.body.removeClass('u-body--header-side-opened');
return this;
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSidePushLeft( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
Object.defineProperty(this, 'isShown', {
get: function() {
return this.body.hasClass('u-body--header-side-opened');
}
});
Object.defineProperty(this, 'overlayClasses', {
get: function() {
return this.element.data('header-overlay-classes') ? this.element.data('header-overlay-classes') : '';
}
});
Object.defineProperty(this, 'headerClasses', {
get: function() {
return this.element.data('header-classes') ? this.element.data('header-classes') : '';
}
});
Object.defineProperty(this, 'bodyClasses', {
get: function() {
return this.element.data('header-body-classes') ? this.element.data('header-body-classes') : '';
}
});
this.body = $('body');
this.invoker = $('[data-target="#'+this.element.attr('id')+'"]');
};
/**
* Initialization of the HSHeaderSidePushLeft instance.
*
* @public
* @returns {HSHeaderSidePushLeft}
*/
HSHeaderSidePushLeft.prototype.init = function() {
var _self = this;
this.body.addClass('u-body--header-side-push-left');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
if(this.invoker.length) {
this.invoker.on('click.HSHeaderSide', function(e){
if(_self.isShown) {
_self.hide();
}
else {
_self.show();
}
e.preventDefault();
}).css('display', 'block');
}
if(!this.overlay) {
this.overlay = $('<div></div>', {
class: 'u-header__overlay ' + _self.overlayClasses
});
}
this.overlay.on('click.HSHeaderSide', function(e){
var hamburgers = _self.invoker.length ? _self.invoker.find('.is-active') : $();
if(hamburgers.length) hamburgers.removeClass('is-active');
_self.hide();
});
this.element.addClass(this.headerClasses).append(this.overlay);
this.body.addClass(this.bodyClasses);
return this;
};
/**
* Destroys the HSHeaderSidePushLeft instance.
*
* @public
* @returns {HSHeaderSidePushLeft}
*/
HSHeaderSidePushLeft.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-push-left');
this.hide();
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
this.element.removeClass(this.headerClasses);
this.body.removeClass(this.bodyClasses);
if(this.invoker.length){
this.invoker.off('click.HSHeaderSide').css('display', 'none');
}
if(this.overlay) {
this.overlay.off('click.HSHeaderSide');
this.overlay.remove();
this.overlay = null;
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSidePushLeft.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-push-left');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSidePushLeft}
*/
HSHeaderSidePushLeft.prototype.show = function() {
this.body.addClass('u-body--header-side-opened');
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSidePushLeft}
*/
HSHeaderSidePushLeft.prototype.hide = function() {
this.body.removeClass('u-body--header-side-opened');
return this;
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSideOverlayRight( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
Object.defineProperty(this, 'isShown', {
get: function() {
return this.body.hasClass('u-body--header-side-opened');
}
});
Object.defineProperty(this, 'overlayClasses', {
get: function() {
return this.element.data('header-overlay-classes') ? this.element.data('header-overlay-classes') : '';
}
});
Object.defineProperty(this, 'headerClasses', {
get: function() {
return this.element.data('header-classes') ? this.element.data('header-classes') : '';
}
});
this.body = $('body');
this.invoker = $('[data-target="#'+this.element.attr('id')+'"]');
};
/**
* Initialization of the HSHeaderSideOverlayRight instance.
*
* @public
* @returns {HSHeaderSideOverlayRight}
*/
HSHeaderSideOverlayRight.prototype.init = function() {
var _self = this;
this.body.addClass('u-body--header-side-overlay-right');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
if(this.invoker.length) {
this.invoker.on('click.HSHeaderSide', function(e){
if(_self.isShown) {
_self.hide();
}
else {
_self.show();
}
e.preventDefault();
}).css('display', 'block');
}
if(!this.overlay) {
this.overlay = $('<div></div>', {
class: 'u-header__overlay ' + _self.overlayClasses
});
}
this.overlay.on('click.HSHeaderSide', function(e){
var hamburgers = _self.invoker.length ? _self.invoker.find('.is-active') : $();
if(hamburgers.length) hamburgers.removeClass('is-active');
_self.hide();
});
this.element.addClass(this.headerClasses).append(this.overlay);
return this;
};
/**
* Destroys the HSHeaderSideOverlayRight instance.
*
* @public
* @returns {HSHeaderSideOverlayRight}
*/
HSHeaderSideOverlayRight.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-overlay-right');
this.hide();
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
this.element.removeClass(this.headerClasses);
if(this.invoker.length) {
this.invoker.off('click.HSHeaderSide').css('display', 'none');
}
if(this.overlay) {
this.overlay.off('click.HSHeaderSide');
this.overlay.remove();
this.overlay = null;
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSideOverlayRight.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-overlay-right');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSideOverlayRight}
*/
HSHeaderSideOverlayRight.prototype.show = function() {
this.body.addClass('u-body--header-side-opened');
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSideOverlayRight}
*/
HSHeaderSideOverlayRight.prototype.hide = function() {
// var hamburgers = this.invoker.length ? this.invoker.find('.is-active') : $();
// if(hamburgers.length) hamburgers.removeClass('is-active');
this.body.removeClass('u-body--header-side-opened');
return this;
};
/**
* HSHeaderSide constructor function.
*
* @extends _HSHeaderSideAbstract
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSHeaderSidePushRight( element, config ) {
_HSHeaderSideAbstract.call(this, element, config);
Object.defineProperty(this, 'scrollContainer', {
get: function() {
return this.element.find('.u-header__sections-container');
}
});
Object.defineProperty(this, 'isShown', {
get: function() {
return this.body.hasClass('u-body--header-side-opened');
}
});
Object.defineProperty(this, 'overlayClasses', {
get: function() {
return this.element.data('header-overlay-classes') ? this.element.data('header-overlay-classes') : '';
}
});
Object.defineProperty(this, 'headerClasses', {
get: function() {
return this.element.data('header-classes') ? this.element.data('header-classes') : '';
}
});
Object.defineProperty(this, 'bodyClasses', {
get: function() {
return this.element.data('header-body-classes') ? this.element.data('header-body-classes') : '';
}
});
this.body = $('body');
this.invoker = $('[data-target="#'+this.element.attr('id')+'"]');
};
/**
* Initialization of the HSHeaderSidePushRight instance.
*
* @public
* @returns {HSHeaderSidePushRight}
*/
HSHeaderSidePushRight.prototype.init = function() {
var _self = this;
this.body.addClass('u-body--header-side-push-right');
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.init( this.scrollContainer );
}
if(this.invoker.length) {
this.invoker.on('click.HSHeaderSide', function(e){
if(_self.isShown) {
_self.hide();
}
else {
_self.show();
}
e.preventDefault();
}).css('display', 'block');
}
if(!this.overlay) {
this.overlay = $('<div></div>', {
class: 'u-header__overlay ' + _self.overlayClasses
});
}
this.overlay.on('click.HSHeaderSide', function(e){
var hamburgers = _self.invoker.length ? _self.invoker.find('.is-active') : $();
if(hamburgers.length) hamburgers.removeClass('is-active');
_self.hide();
});
this.element.addClass(this.headerClasses).append(this.overlay);
this.body.addClass(this.bodyClasses);
return this;
};
/**
* Destroys the HSHeaderSidePushRight instance.
*
* @public
* @returns {HSHeaderSidePushRight}
*/
HSHeaderSidePushRight.prototype.destroy = function() {
this.body.removeClass('u-body--header-side-push-right');
this.hide();
if( $.HSCore.components.HSScrollBar && this.scrollContainer.length ) {
$.HSCore.components.HSScrollBar.destroy( this.scrollContainer );
}
this.element.removeClass(this.headerClasses);
this.body.removeClass(this.bodyClasses);
if(this.invoker.length){
this.invoker.off('click.HSHeaderSide').css('display', 'none');
}
if(this.overlay) {
this.overlay.off('click.HSHeaderSide');
this.overlay.remove();
this.overlay = null;
}
return this;
};
/**
* Checks whether instance has been initialized.
*
* @public
* @returns {Boolean}
*/
HSHeaderSidePushRight.prototype.isInit = function() {
return this.body.hasClass('u-body--header-side-push-right');
};
/**
* Shows the Header.
*
* @public
* @returns {HSHeaderSidePushRight}
*/
HSHeaderSidePushRight.prototype.show = function() {
this.body.addClass('u-body--header-side-opened');
return this;
};
/**
* Hides the Header.
*
* @public
* @returns {HSHeaderSidePushRight}
*/
HSHeaderSidePushRight.prototype.hide = function() {
// var hamburgers = this.invoker.length ? this.invoker.find('.is-active') : $();
// if(hamburgers.length) hamburgers.removeClass('is-active');
this.body.removeClass('u-body--header-side-opened');
return this;
};
})(jQuery);