'use strict';
/**
* Lazy images component.
* See lazy loading documentation under utilities on the index page
* @namespace lazyImages
* @memberof UCASDesignFramework
* @param {object} global - UCASDesignFramework object.
* @param {object} _u - UCASUtilities object.
*/
(function (global, _u) {
var lazyImages
/**
* @function init
* @memberof! UCASDesignFramework.lazyImages
* @param {Node} [context=document] - context to limit the selector
* @param {String} [selector=[data-lazy-image-background]:not([data-lazy-image-prepared])] - a valid CSS selector for the element to lazy load
* @param {String} [image=http://example.com/image.jpg] - an image to load when the selector is passed
* @returns {Boolean} - true for success
* @example
* UCASDesignFramework.lazyImages.init()
*/
function init (context, selector, image) {
context = context || document
selector = selector || '[data-lazy-image-background]:not([data-lazy-image-prepared])'
lazyImages = context.querySelectorAll(selector)
if (!lazyImages) {
_u.log.info('Failed to find any lazy images')
return false
}
lazyImages.forEach(function (lazyImage) {
if (image !== undefined) {
lazyImage.setAttribute('data-lazy-image-background', image)
}
if (window['IntersectionObserver']) {
createObserver(lazyImage)
} else {
loadImage(lazyImage)
}
})
}
/**
* @function createObserver
* @memberof! UCASDesignFramework.lazyImages
* @param {Array} entries - list of lazyImages objects
* @param {observer} observer - the calling observer
* @private
*/
function handleIntersect (entries, observer) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
loadImage(entry.target)
observer.unobserve(entry.target)
}
})
}
/**
* @function createObserver
* @memberof! UCASDesignFramework.lazyImages
* @param {Node} lazyImage - a lazyImages node
* @private
*/
function createObserver (lazyImage) {
const options = {
root: null,
threshold: '0'
}
const observer = new IntersectionObserver(handleIntersect, options)
observer.observe(lazyImage)
}
/**
* @function loadImage
* @memberof! UCASDesignFramework.lazyImages
* @param {Node} lazyImage - a lazyImages node
* @private
*/
function loadImage (lazyImage) {
var imageElement = new Image()
imageElement.src = lazyImage.getAttribute('data-lazy-image-background')
var lazyImageTarget = lazyImage
var transitionRemoved = false
if (lazyImage.hasAttribute('data-lazy-image-child')) {
var lazyBackground = document.createElement('div')
var lazyChildClasses = lazyImage.getAttribute('data-lazy-image-child')
var lazyChildData = lazyImage.getAttribute('data-lazy-image-data')
// Done this way for IE support.
lazyChildClasses.split(' ').forEach(
function (classname) {
lazyBackground.classList.add(classname)
}
)
// Done this way for IE support.
if (lazyChildData) {
lazyChildData.split(' ').forEach(
function (dataAttribute) {
lazyBackground.setAttribute(dataAttribute, '')
}
)
}
lazyBackground.classList.add('lazy-image-child')
// Done this way for IE support.
lazyImage.insertBefore(lazyBackground, lazyImage.childNodes[0])
lazyImageTarget = lazyBackground
}
lazyImageTarget.style.backgroundImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcIAAAGQCAQAAACXV6gyAAADO0lEQVR42u3TMQ0AAAzDsJU/6bFoHxtCpOSAqUgAJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEEwImBBMCJgQTAiYEE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggkBE4IJAROCCQETggnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEgAnBhIAJwYSACcGEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCwIRgQsCEYELAhGBCMKEEYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCFgQjAhYEIwIWBCMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQMCGYEDAhmBAwIZgQTAiYEEwImBBMCJgQTAiYEEwImBBMCLQ8WyQBkb6vglMAAAAASUVORK5CYII=)'
lazyImageTarget.style.transition = 'background .5s linear'
imageElement.addEventListener('load', function () {
setTimeout(function () {
renderLazyImage(lazyImage)
// IE and Firefox don't support transitions on background images, so this timeout is a fallback to remove the transition.
setTimeout(function () {
if (!transitionRemoved) {
lazyImageTarget.style.removeProperty('transition')
}
}, 700)
}, 100)
})
imageElement.addEventListener('error', function () {
_u.log.error('Unable to lazy load image.')
})
lazyImageTarget.addEventListener('transitionend', function (event) {
if ((event.propertyName === 'background') || (event.propertyName === 'background-image')) {
lazyImageTarget.style.removeProperty('transition')
transitionRemoved = true
}
})
}
/**
* @function renderLazyImage
* @memberof! UCASDesignFramework.lazyImages
* @param {Node} lazyImage - a lazyImages node
* @private
*/
function renderLazyImage (lazyImage) {
var lazyImageTarget = (lazyImage.hasAttribute('data-lazy-image-child')) ? lazyImage.querySelector('.lazy-image-child') : lazyImage
lazyImage.setAttribute('data-lazy-image-prepared', '')
lazyImageTarget.style.backgroundImage = 'url(' + lazyImage.getAttribute('data-lazy-image-background') + ')'
}
/**
* @function destroy
* @memberof! UCASDesignFramework.lazyImages
* @example
* UCASDesignFramework.lazyImages.destroy()
*/
function destroy () {
}
// Expose public methods and properties.
global.lazyImages = {
addSubscriptions: true,
init: init,
initOnLoad: true,
destroy: destroy
}
})(UCASDesignFramework, UCASUtilities)