symphony/assets/js/src/symphony.affix.js
/**
* @package assets
*/
(function($, Symphony) {
'use strict';
// holds up all instances
var instances = $();
// last scroll position
var scrollTop = 0;
/**
* Create affix elements.
* Affix elements follow the scroll and are constrain by their container.
*
* @since Symphony 2.5
*
* @name $.symphonyAffix
* @class
*
* @param {Object} options An object specifying containing the attributes specified below
* @param {String} [options.container=$(this).parent()] Selector to find affix container
*
* @example
var affix = $('#affix').symphonyAffix({
container: '.parent',
});
*/
$.fn.symphonyAffix = function(options) {
var objects = $(this),
settings = {
// public
container: null,
// private
top: 0,
freespace: 0,
bottom: 0,
height: 0,
maxtop: 0
};
$.extend(settings, options);
/*---------------------------------------------------------------------
Initialisation
---------------------------------------------------------------------*/
objects.each(function createOneAffix() {
var itemSettings = $.extend({}, settings);
var item = $(this);
var updateItemSettings = function () {
itemSettings.top = itemSettings.container.offset().top;
itemSettings.freespace = itemSettings.container.height();
itemSettings.bottom = itemSettings.top + itemSettings.freespace;
itemSettings.height = item.height();
itemSettings.maxtop = (itemSettings.freespace - itemSettings.height) + 'px';
};
// use parent as default container
if (!itemSettings.container) {
itemSettings.container = item.parent();
}
// resolve jQuery object
else {
itemSettings.container = $(itemSettings.container);
}
// cache cssom values
updateItemSettings();
item.on('updatesettings.affix', updateItemSettings);
item.addClass('js-affix');
// save instance settings
item.data('affix-settings', itemSettings);
// register instance
instances = instances.add(item);
});
// Init
$(window).triggerHandler('scroll');
return objects;
};
/*-----------------------------------------------------------------------*/
// One listener for all instances
$(window).on('scroll', function affixScroll() {
scrollTop = $(this).scrollTop();
Symphony.Utilities.requestAnimationFrame(function affixScrollRaf() {
instances.each(function affixScrollOne() {
var item = $(this);
var settings = item.data('affix-settings');
var cssClass = 'js-affix-scroll';
var top = '';
if (scrollTop < settings.top) {
cssClass = 'js-affix-top';
} else if (scrollTop > settings.bottom) {
cssClass = 'js-affix-bottom';
top = settings.maxtop;
}
// Do changes only if state changes
if (!item.hasClass(cssClass)) {
item
.removeClass('js-affix-scroll js-affix-top js-affix-bottom')
.addClass(cssClass)
.css({top: top});
}
});
});
});
})(window.jQuery, window.Symphony);