import customEvent from '../utils/customEvent';
import InView from '../utils/classes/InView';
/**
* Image Container that loads a background element to pad white space if image does not match
* container aspect ratio
*
* @module ImageContainer
* @prop {string} selector - selector for HTML elements for loading background image to pad
* @prop {string} imageCss - image css class
* @prop {string} backgroundCss - background css class
*/
const ImageContainer = {
selector: '.c-imageContainer',
backgroundCss: 'c-imageContainer__bg',
imageCss: 'c-imageContainer__image',
fitByWidthCss: 'c-imageContainer--fitWidth',
fitByHeightCss: 'c-imageContainer--fitHeight',
watcher: false,
/**
* Initialize InView watcher for handling lazy load image / iframes
*
* @method init
*/
init( $elems = false ) {
const $targets = $elems || document.querySelectorAll( this.selector );
// Set up in view for loading a background image
if ( ! this.watcher ) {
this.watcher = new InView({
threshold: 0.1,
rootMargin: `${window.innerHeight * 0.4}px`,
});
this.watcher.init();
}
[].forEach.call( $targets, ( $elem ) => {
const $image = $elem.querySelector( 'img' );
if ( $image ) {
$image.classList.add( this.imageCss );
const fitted = $elem.classList.contains( this.fitByWidthCss )
|| $elem.classList.contains( this.fitByHeightCss );
if ( ! fitted && $image.dataset.height < $image.dataset.width ) {
// Landscape image with a ratio not matching container,
// render image width top and bottom cropped
const imageRatio = parseFloat( $image.dataset.height / $image.dataset.width );
if ( imageRatio > parseFloat( $image.dataset.ratio ) ) {
$elem.classList.add( this.fitByWidthCss );
}
} else {
// Pad with a blurred background image to fill empty space in container
const src = $image.getAttribute( 'data-src' ) || $image.getAttribute( 'src' );
if ( src ) {
const $background = document.createElement( 'div' );
$background.classList.add( this.backgroundCss );
$background.dataset.background = 'true';
$elem.appendChild( $background );
$background.addEventListener( customEvent.IN_VIEW, ( event ) => {
if ( event && event.detail && event.detail.isInView ) {
this.setBackground( event.currentTarget, src );
this.watcher.stopWatching( event.currentTarget );
}
});
this.watcher.startWatching( $background );
}
}
}
});
},
/**
* Set background image of an html element
*
* @method setBackground
* @param {element} $target
* @param {string} src
*/
setBackground( $target, src ) {
$target.setAttribute( 'style', `background-image: url(${src});` );
},
};
export default ImageContainer;