import InView from '../utils/classes/InView';
import customEvent from '../utils/customEvent';
/**
* Load script defined as attribute `[data-load-script]` as element becomes in view
*
* @example
* <div data-load-script="url" data-placeholder=".c-module__placeholder">
* <div class="c-module__placeholder"></div>
* </div>
*
* @module LoadScript
* @prop {string} selector - targets elements on to set up dynamic loading
* @prop {string} hiddenCss - CSS class that hides an element
* @prop {string} loadingCss - CSS class that displays a loading state
*/
const LoadScript = {
selector: '[data-load-script]:not([data-load-manually])',
hiddenCss: 'is-hidden',
loadingCss: 'c-shimmer',
/**
* Set's up `InView` listener on any `[data-load-content]` elements.
* Callback is fired when element comes into view.
*
* @method init
*/
init() {
// set up in view watcher for lazy load ads
const inViewWatcher = new InView({
selector: this.selector,
threshold: 0.1,
rootMargin: '-100px 0px 0px 0px',
}, 'scriptWatcher' );
inViewWatcher.init();
const $targets = document.querySelectorAll( this.selector );
[].forEach.call( $targets, ( $target ) => {
$target.addEventListener( customEvent.IN_VIEW, ( event ) => {
if ( event && event.detail && event.detail.isInView ) {
this.load( $target );
}
});
});
},
/**
* Load script specified by `[data-load-script]`.
* Inserts script before first script tag on the page
*
* @method load
*/
load( $target ) {
const url = $target.dataset.loadScript;
if ( url ) {
const tag = document.createElement( 'script' );
tag.src = url;
tag.async = true;
// handle script load
tag.onload = () => {
const placeholderSelector = $target.dataset.placeholder;
if ( placeholderSelector ) {
const $placeholder = $target.querySelector( placeholderSelector );
$placeholder.classList.add( this.loadingCss );
$placeholder.classList.add( this.hiddenCss );
}
$target.dataset.scriptLoaded = true; // eslint-disable-line no-param-reassign
this.broadcastLoad( $target );
};
// insert script tag
const $node = document.getElementsByTagName( 'script' )[0];
if ( $node && $node.parentNode ) {
$node.parentNode.insertBefore( tag, $node );
}
}
},
/**
* Fire a custom event signifying script being loaded
*
* @method broadcastLoad
*/
broadcastLoad( $target ) {
customEvent.fire( window, customEvent.LOADED, {
target: $target,
});
},
};
export default LoadScript;