article/VideoLoop.js

import InView from '../utils/classes/InView';
import customEvent from '../utils/customEvent';

/**
 * Video loop that auto plays when in view.
 *
 * @module VideoLoop
 * @prop {string} selector - video loop DOM selector
 */
const VideoLoop = {
	selector: '.c-videoLoop',
	$videos: [],

	/**
	 * Check to see if there are any video loop elements on the page.
	 * If so, detect if auto play is supported.
	 *
	 * @method init
	 */
	init() {
		this.$videos = document.querySelectorAll( this.selector );
		if ( this.$videos.length > 0 ) {
			setTimeout( () => {
				this.detectAutoplay();
			}, 1000 );
		}
	},

	/**
	 * Detect if autoplay is allowed by attempting to play the first video.
	 *
	 * @method detectAutoplay
	 */
	detectAutoplay() {
		const $video = this.$videos[0];
		const promise = $video.play();
		if ( promise ) {
			promise.catch( () => {
				// auto play prohibited - enable click to play.
				this.autoplayDetected( false );
			}).then( () => {
				// Pause videos.
				$video.pause();

				// auto play successful.
				this.autoplayDetected( true );
			});
		}
	},

	/**
	 * Handler for when video autoplay detection has taken place.
	 * Add in view listener when video autoplay is supported.
	 *
	 * @method autoplayDetected
	 * @param {boolean} success - whether or not auto play is supported.
	 */
	autoplayDetected( success ) {
		if ( success ) {
			const watcher = new InView({
				threshold: 0.1,
			});
			watcher.init();

			[].forEach.call( this.$videos, ( $video ) => {
				$video.dataset.alwaysObserve = 'true'; // eslint-disable-line no-param-reassign
				$video.addEventListener( customEvent.IN_VIEW, ( inviewEvt ) => {
					this.handleInView( inviewEvt );
				});
				watcher.startWatching( $video );
			});
		} else {
			// Auto play not supported,
			// collapse the video element, and trigger the AUTO_PLAY_FAILED event.
			[].forEach.call( this.$videos, ( $video ) => {
				$video.setAttribute( 'style', 'display:none;' );
				customEvent.fire( $video, customEvent.AUTO_PLAY_FAILED );
			});
		}
	},

	/**
	 * Handler for in view event.
	 * Play video loop when it is in view, pause when out of view.
	 *
	 * @method handleInView
	 */
	handleInView( event ) {
		const $video = event.detail.target;
		if ( $video && event && event.detail ) {
			if ( event.detail.isInView ) {
				$video.play();
			} else {
				$video.pause();
			}
		}
	},
};

export default VideoLoop;