| Current Path : /var/www/homesaver/www/bitrix/templates/landing24/assets/js/components/ |
| Current File : /var/www/homesaver/www/bitrix/templates/landing24/assets/js/components/hs.scroll-nav.js |
/**
* HSScrollNav Component.
*
* @author Htmlstream
* @version 1.0
* @requires jQuery
*
*/
;(function ($) {
'use strict';
$.HSCore.components.HSScrollNav = {
/**
* Base configuraion of the component.
*
* @private
*/
_baseConfig: {
duration: 400,
easing: 'linear',
over: $(),
activeItemClass: 'active',
afterShow: function(){},
beforeShow: function(){}
},
/**
* All initialized item on the page.
*
* @private
*/
_pageCollection: $(),
/**
* Initialization of the component.
*
* @param {jQuery} collection
* @param {Object} config
*
* @public
* @return {jQuery}
*/
init: function(collection, config) {
var self = this;
if( !collection || !collection.length ) return $();
collection.each(function(i, el) {
var $this = $(el),
itemConfig = config && $.isPlainObject(config) ?
$.extend(true, {}, self._baseConfig, config, $this.data()) :
$.extend(true, {}, self._baseConfig, $this.data());
if( !$this.data('HSScrollNav') ) {
$this.data('HSScrollNav', new HSScrollNav($this, itemConfig));
self._pageCollection = self._pageCollection.add( $this );
}
});
$(window).on('scroll.HSScrollNav', function(){
self._pageCollection.each(function(i, el) {
if($.contains(document, el))
{
$(el).data('HSScrollNav').highlight();
}
});
}).trigger('scroll.HSScrollNav');
return collection;
}
}
/**
* HSScrollNav.
*
* @param {jQuery} element
* @param {Object} config
*
* @constructor
*/
function HSScrollNav(element, config) {
/**
* Current element.
*
* @public
*/
this.element = element;
/**
* Configuraion.
*
* @public
*/
this.config = config;
/**
* Sections.
*
* @public
*/
this._items = $();
this._makeItems();
this._bindEvents();
}
/**
* Return collection of sections.
*
* @private
* @return {jQuery}
*/
HSScrollNav.prototype._makeItems = function() {
var self = this;
this.element
.find('a[href*="#"]').filter(function(key, item) {
var hash = item.getAttribute("href").split("#")[1];
return !!document.getElementById(hash);
})
.each(function(i, el) {
var $this = $(el);
if( !$this.data('HSScrollNavSection') ) {
$this.data('HSScrollNavSection', new HSScrollNavSection($this, self.config));
self._items = self._items.add( $this );
}
});
};
/**
* Binds necessary events.
*
* @private
* @return {undefined}
*/
HSScrollNav.prototype._bindEvents = function() {
var self = this;
this.element.on('click.HSScrollNav', 'a[href*="#"]', function(e) {
var link = this;
self._lockHightlight = true;
if(self.current) self.current.unhighlight();
link.blur();
self.current = $(link).data('HSScrollNavSection');
if (self.current)
{
self.current.highlight();
$(this).data('HSScrollNavSection').show(function () {
self._lockHightlight = false;
});
e.preventDefault();
}
});
};
/**
* Activates necessary menu item.
*
* @public
*/
HSScrollNav.prototype.highlight = function() {
var self = this, items, currentItem, current, scrollTop;
if(!this._items.length || this._lockHightlight) return;
scrollTop = $(window).scrollTop();
if(scrollTop + $(window).height() === $(document).height()) {
this.current = this._items.last().data('HSScrollNavSection');
this.unhighlight();
this.current.highlight();
this.current.changeHash();
return;
}
this._items.each(function(i, el){
var Section = $(el).data('HSScrollNavSection'),
$section = Section.section;
if(scrollTop >= Section.offset) {
current = Section;
}
});
if(current && this.current != current) {
this.unhighlight();
current.highlight();
if(this.current) current.changeHash();
this.current = current;
}
};
/**
* Deactivates all menu items.
*
* @public
*/
HSScrollNav.prototype.unhighlight = function() {
this._items.each(function(i, el){
$(el).data('HSScrollNavSection').unhighlight();
});
};
/**
* HSScrollNavSection.
*
* @param {jQuery} element
*
* @constructor
*/
function HSScrollNavSection(element, config) {
var self = this;
/**
* Current section.
*
* @public
*/
this.element = element;
/**
* Configuration.
*
* @public
*/
this.config = config;
/**
* Getter for acces to the section element.
*
* @public
*/
Object.defineProperty(this, 'section', {
value: $("#"+self.element.attr('href').split("#")[1])
});
/**
* Getter for determinate position of the section relative to document.
*
* @public
*/
Object.defineProperty(this, 'offset', {
get: function() {
// todo: need relative selector (only current header)
var header = $('.u-header, header');
if(header.length > 0)
{
var headerHeight = header.outerHeight(),
headerStyles = getComputedStyle(header.get(0)),
headerPosition = headerStyles.position,
offset = self.section.offset().top,
headerTop = parseInt(headerStyles.top),
headerMarginTop = parseInt(headerStyles.marginTop);
}
else
{
var headerHeight = 0,
headerPosition = 'fixed',
offset = self.section.offset().top,
headerTop = 0,
headerMarginTop = 0;
}
if(headerPosition == 'fixed' && headerTop == 0) {
offset = offset - headerHeight - headerMarginTop;
}
if(self.config.over.length) {
offset = offset - self.config.over.outerHeight();
}
return offset;
}
});
}
/**
* Moves to the section.
*
* @public
*/
HSScrollNavSection.prototype.show = function(callback) {
var self = this;
if( !this.section.length ) return;
self.config.beforeShow.call(self.section);
this.changeHash();
$('html, body').stop().animate({
scrollTop: self.offset + 3
}, {
duration: self.config.duration,
easing: self.config.easing,
complete: function() {
$('html, body').stop().animate({
scrollTop: self.offset + 3
}, {
duration: self.config.duration,
easing: self.config.easing,
complete: function() {
self.config.afterShow.call(self.section);
if($.isFunction(callback)) callback();
}
});
}
});
};
/**
* Changes location's hash.
*
* @public
*/
HSScrollNavSection.prototype.changeHash = function() {
this.section.attr('id', '');
// window.location.hash = "#"+this.element.attr('href').split("#")[1];
this.section.attr('id', this.element.attr('href').split("#")[1]);
};
/**
* Activates the menu item.
*
* @public
*/
HSScrollNavSection.prototype.highlight = function() {
var parent = this.element.parent('li');
if(parent.length) parent.addClass(this.config.activeItemClass);
};
/**
* Deactivates the menu item.
*
* @public
*/
HSScrollNavSection.prototype.unhighlight = function() {
var parent = this.element.parent('li');
if(parent.length) parent.removeClass(this.config.activeItemClass);
};
})(jQuery);