/* global jQuery */
/* global Stickyfill */
'use strict';
/**
* Initialises polyfill for sticky funtionality
* see https://github.com/wilddeer/stickyfill
* @namespace sticky
* @memberof UCASDesignFramework
* @param {object} global - UCASDesignFramework object.
* @param {object} $ - jQuery.
* @param {object} context - context to limit the selectors.
* @param {object} _u - UCASUtilities object.
*/
(function (global, $, context, _u) {
// Create namespaced object for module
global.sticky = {}
var stickies = {}
var conditionalStickies = {}
/**
* Initialise plugin.
* @function init
* @memberof! UCASDesignFramework.sticky
* @public
* @param {Node} [context=document] - DOM element we're limiting selection to
*/
function init (context) {
context = context || document
conditionalStickies = $('[data-sticky-conditional]', context)
stickies = $('.sticky', context)
// If the window is wide enough, enable stickiness.
if (context.body.clientWidth >= 720) {
stickies.each(function () {
$(this).Stickyfill()
})
conditionalSticky(context)
}
// Add an event listener on scroll to check if we need the
// content has resized and we need to remove the conditional sticky
// and a MutationObserver to see if the content has changed.
if (conditionalStickies.length > 0) {
$(window).on('scroll.sticky', _u.throttle(rebuildStickyConditional, 1000))
if (window.MutationObserver) {
addMutationObserver()
}
}
// Add an event listener on resize to check if we need to
// remove sticky.
$(window).on('resize.sticky', function () {
if (context.body.clientWidth >= 720) {
stickies.each(function () {
$(this).Stickyfill()
})
conditionalSticky(context)
}
// Make sure we remove the sticky functionality at small sizes.
if (document.body.clientWidth < 720) {
Stickyfill.kill()
}
Stickyfill.rebuild()
})
}
/**
* Add a mutation observer to see if the conditional stickies change content.
*/
function addMutationObserver () {
var onLoadImage = function (event) {
rebuildStickyConditional()
event.target.removeEventListener('load', onLoadImage)
}
var observer = new MutationObserver(function (mutations) {
rebuildStickyConditional()
// Loop through the mutations and check for images and iframes,
// which will need to rebuild the sticky when loaded.
mutations.forEach(function (mutation) {
_u.forEach(mutation.addedNodes, function (index, node) {
if ((node.nodeName === 'IMG' || node.nodeName === 'IFRAME') && !node.complete) {
node.addEventListener('load', onLoadImage)
}
})
})
})
var observerConfig = {
childList: true,
subtree: true
}
conditionalStickies.each(function () {
observer.observe(this, observerConfig)
})
}
/**
* Rebuild conditional sticky, checking its height.
*/
function rebuildStickyConditional () {
conditionalStickies.each(function () {
if ($(this).outerHeight(true) > $(window).height()) {
$(this).removeClass('sticky')
Stickyfill.remove(this)
}
})
Stickyfill.rebuild()
}
/**
* Remove all Stickyfill bindings and added classes
* @function destroy
* @memberof! UCASDesignFramework.sticky
* @public
* @param {Node} context - DOM element we're limiting selection to
*/
function destroy (context) {
Stickyfill.kill()
$(window).off('resize.sticky', context)
$(window).off('scroll.sticky', context)
conditionalStickies.removeClass('sticky')
}
/**
* Conditionally prevent Stickyfill from affecting elements taller than viewport
*/
function conditionalSticky () {
conditionalStickies.each(function () {
// If the element is taller than the viewport
if ($(this).outerHeight(true) < $(window).height()) {
// Add sticky class to element
$(this).addClass('sticky')
Stickyfill.add(this)
} else {
$(this).removeClass('sticky')
Stickyfill.remove(this)
}
})
}
/**
* Map local functions to global object
*/
function exports () {
global.sticky.init = init
global.sticky.destroy = destroy
}
/**
* Return public functions
*/
return exports()
})(UCASDesignFramework, jQuery, document, UCASUtilities)