longform/Hero.js

import customEvent from '../utils/customEvent';
import cssPropertySupported from '../utils/cssPropertySupported';

/**
 * Handle video background for longform template hero area
 *
 * @module Hero
 * @prop {object} selectors - Hero area CSS selectors
 * @prop {NodeList} $elems - all hero area elements
 */
const Hero = {
	selectors: {
		elem: '.c-longform-hero',
		video: '.c-longform-hero__media--video',
		image: '.c-longform-hero__media--image',
		media: '.c-longform-hero__media',
	},
	states: {
		hidden: 'is-hidden',
		fitByWidth: 'c-longform-hero__media--fitByWidth',
		fitByHeight: 'c-longform-hero__media--fitByHeight',
	},
	$elems: false,
	listeners: [],

	/**
	 * Set up inview listener to handle play/pause of background video
	 *
	 * @method init
	 */
	init() {
		this.$elems = document.querySelectorAll( this.selectors.elem );
		if ( this.$elems.length > 0 ) {
			[].forEach.call( this.$elems, ( $elem ) => {
				const $video = $elem.querySelector( this.selectors.video );
				if ( $video ) {
					$video.addEventListener( customEvent.AUTO_PLAY_FAILED, () => {
						// Hide video, faallback to image
						const $image = $elem.querySelector( this.selectors.image );
						$image.classList.remove( this.states.hidden );
						$video.classList.add( this.states.hidden );
					});
				}

				// resize image / video manually if object-fit not supported
				if ( ! cssPropertySupported( 'object-fit' ) ) {
					this.setSize( $elem );
				}
			});
		}
	},

	/**
	 * Set media element sizes based on browser size
	 */
	setSize( $elem ) {
		const width = $elem.offsetWidth;
		const height = $elem.offsetHeight;
		const $mediaElems = $elem.querySelectorAll( this.selectors.media );
		[].forEach.call( $mediaElems, ( $media ) => {
			const mediaWidth = parseInt( $media.getAttribute( 'width' ), 10 );
			const mediaHeight = parseInt( $media.getAttribute( 'height' ), 10 );

			if ( mediaWidth / mediaHeight < width / height ) {
				// fit by width
				$media.classList.add( this.states.fitByWidth );
			} else {
				// fit by height
				$media.classList.add( this.states.fitByHeight );
			}
		});
	},
};

export default Hero;