(function() {
'use strict';
const AIOVGTemplate = document.createElement( 'template' );
AIOVGTemplate.innerHTML = `
`;
class AIOVGBaseElement extends HTMLElement {
/**
* Element created.
*/
constructor() {
super();
// Attach Shadow DOM to the component
const shadowDom = this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild( AIOVGTemplate.content.cloneNode( true ) );
// Set references to the DOM elements from the component's template
this.$root = shadowDom.querySelector( '#root' );
this.$posterImage = shadowDom.querySelector( '#posterimage' );
this.$playButton = shadowDom.querySelector( '#playbutton' );
this.$cookieConsentButton = shadowDom.querySelector( '#cookieconsent-button' );
this.$emailCaptureModal = shadowDom.querySelector( '#email-capture-modal' );
// Set references to the private properties used by the component
this._isRendered = false;
this._ajaxUrl = aiovg_embed.ajax_url;
this._ajaxNonce = aiovg_embed.ajax_nonce;
this._isCookieConsentLoaded = false;
this._isEmailCaptureLoaded = false;
this._isPosterImageLoaded = false;
this._isIframeLoaded = false;
this._forceIframeElement = navigator.vendor.includes( 'Apple' ) || navigator.userAgent.includes( 'Mobi' );
this._intersectionObserver = null;
this._isInViewport = false;
}
/**
* Browser calls this method when the element is added to the document.
* (can be called many times if an element is repeatedly added/removed)
*/
connectedCallback() {
if ( ! this.src ) return false;
if ( ! this.lazyLoading ) {
this._forceIframeElement = true;
}
if ( ! this.poster ) {
this._forceIframeElement = true;
}
if ( ! this._forceIframeElement ) {
const url = new URL( this.src );
const query = new URLSearchParams( url.search );
const autoplayRequested = query.has( 'autoplay' ) && ( query.get( 'autoplay' ) == 1 || query.get( 'autoplay' ) == true );
if ( autoplayRequested ) this._forceIframeElement = true;
}
this._render();
this.addEventListener( 'pointerover', () => this._warmConnections(), { once: true, } );
this.addEventListener( 'click', () => this._addIframe( true ) );
}
/**
* Browser calls this method when the element is removed from the document.
* (can be called many times if an element is repeatedly added/removed)
*/
disconnectedCallback() {
// TODO
}
/**
* Array of attribute names to monitor for changes.
*/
static get observedAttributes() {
return [ 'title', 'ratio' ];
}
/**
* Called when one of the observed attributes listed above is modified.
*/
attributeChangedCallback( name, oldValue, newValue ) {
if ( oldValue == newValue ) return false;
switch ( name ) {
case 'title':
// Set attributes for accessibility
if ( newValue ) {
this.$posterImage.setAttribute( 'alt', newValue );
} else {
this.$posterImage.setAttribute( 'alt', '' );
}
break;
case 'ratio':
if ( newValue ) {
this.$root.style.paddingBottom = `${parseFloat(newValue)}%`;
}
break;
}
}
/**
* Define getters and setters for attributes.
*/
get title() {
return this.getAttribute( 'title' ) || '';
}
get src() {
const value = this.getAttribute( 'src' ) || '';
return AIOVGBaseElement.isValidUrl( value ) ? value : '';
}
get poster() {
const value = this.getAttribute( 'poster' ) || '';
return AIOVGBaseElement.isValidUrl( value ) ? value : '';
}
get postId() {
return parseInt( this.getAttribute( 'post_id' ) || 0 );
}
get postType() {
return this.getAttribute( 'post_type' ) || '';
}
get lazyLoading() {
return this.hasAttribute( 'lazyloading' );
}
get statistics() {
return this.hasAttribute( 'statistics' );
}
get cookieConsent() {
return this.hasAttribute( 'cookieconsent' );
}
set cookieConsent( value ) {
const isEnabled = Boolean( value );
if ( isEnabled ) {
this.setAttribute( 'cookieconsent', '' );
} else {
this.removeAttribute( 'cookieconsent' );
}
}
get emailCapture() {
return this.hasAttribute( 'email-capture' );
}
set emailCapture( value ) {
const isEnabled = Boolean( value );
if ( isEnabled ) {
this.setAttribute( 'email-capture', '' );
} else {
this.removeAttribute( 'email-capture' );
}
}
/**
* Define private methods.
*/
_render() {
if ( this._isRendered ) return false;
if ( this.lazyLoading && ! this._isInViewport ) {
this._initIntersectionObserver();
return false;
}
if ( this.emailCapture ) {
this._addEmailCapture();
return false;
}
if ( this.cookieConsent ) {
this._addCookieConsent();
return false;
}
this._isRendered = true;
if ( this._forceIframeElement ) {
this._warmConnections();
this._addIframe();
} else {
this._addPosterImage();
}
}
_addCookieConsent() {
if ( this._isCookieConsentLoaded ) return false;
this._isCookieConsentLoaded = true;
this._addPosterImage();
this._addClass( 'cookieconsent' );
this.$cookieConsentButton.addEventListener( 'click', () => this._onCookieConsent() );
}
_onCookieConsent() {
this._isRendered = true;
this._removeClass( 'cookieconsent' );
this.cookieConsent = false;
this._warmConnections();
this._addIframe( true );
this._setCookie();
// Remove cookieconsent from other players
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
videos[ i ].removeCookieConsent();
}
window.postMessage({
message: 'aiovg-cookie-consent'
}, window.location.origin );
}
_addEmailCapture() {
if ( this._isEmailCaptureLoaded ) return false;
this._isEmailCaptureLoaded = true;
// Read template from light DOM child placed by PHP
const templateEl = this.querySelector( 'template.aiovg-player-template' );
if ( ! templateEl ) return false;
// Clone HTML from template into shadow DOM
const emailCaptureEl = templateEl.content.querySelector( '.email-capture' );
if ( ! emailCaptureEl ) return false;
// Move all children of email capture block into the email capture modal container in the shadow DOM
this.$emailCaptureModal.appendChild( emailCaptureEl.cloneNode( true ) );
// Add poster image if available and enable the email capture modal by adding the corresponding class to the root element
this._addPosterImage();
this._addClass( 'email-capture' );
// Focus the first input for better accessibility
const firstInput = this.$emailCaptureModal.querySelector( 'input' );
if ( firstInput ) {
firstInput.focus();
}
// Submit handler
const submitBtn = this.$emailCaptureModal.querySelector( '.email-capture-submit' );
if ( submitBtn ) {
submitBtn.addEventListener( 'click', () => {
const emailField = this.$emailCaptureModal.querySelector( '.email-capture-email' );
const errorSpan = this.$emailCaptureModal.querySelector( '.email-capture-error' );
const email = emailField ? emailField.value.trim() : '';
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if ( ! email || ! regex.test( email ) ) {
if ( errorSpan ) {
const errorMessage = errorSpan.getAttribute( 'data-invalid_email' ) || 'Please enter a valid email address.';
errorSpan.textContent = errorMessage;
errorSpan.style.display = 'block';
}
if ( emailField ) {
emailField.classList.add( 'is-invalid' );
emailField.setAttribute( 'aria-invalid', 'true' );
}
return false;
}
if ( errorSpan ) {
errorSpan.style.display = 'none';
}
if ( emailField ) {
emailField.classList.remove( 'is-invalid' );
emailField.removeAttribute( 'aria-invalid' );
}
let params = 'email=' + encodeURIComponent( email );
const nameField = this.$emailCaptureModal.querySelector( '.email-capture-name' );
if ( nameField && nameField.value.trim() ) {
params += '&name=' + encodeURIComponent( nameField.value.trim() );
}
const phoneField = this.$emailCaptureModal.querySelector( '.email-capture-phone' );
if ( phoneField && phoneField.value.trim() ) {
params += '&phone=' + encodeURIComponent( phoneField.value.trim() );
}
if ( 'aiovg_videos' === this.postType && this.postId ) {
params += '&video_id=' + encodeURIComponent( this.postId );
} else {
params += '&video_id=0';
if ( this.src ) {
params += '&video_url=' + encodeURIComponent( this.src );
}
}
params += '&page_url=' + encodeURIComponent( window.location.href );
this._onEmailCapture( params );
} );
}
// Skip handler
const skipLink = this.$emailCaptureModal.querySelector( '.email-capture-skip' );
if ( skipLink ) {
const doSkip = () => {
this._onEmailCapture( 'skipped=1' );
};
skipLink.addEventListener( 'click', doSkip );
skipLink.addEventListener( 'keydown', ( event ) => {
if ( 13 === event.keyCode || 32 === event.keyCode ) {
event.preventDefault();
doSkip();
}
} );
}
}
_onEmailCapture( data ) {
if ( this.$emailCaptureModal.classList.contains( 'is-loading' ) ) return false; // Prevent multiple submissions
this.$emailCaptureModal.classList.add( 'is-loading' );
const xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = () => {
if ( 4 == xmlhttp.readyState ) {
let response = null;
if ( 200 == xmlhttp.status && xmlhttp.responseText ) {
try {
response = JSON.parse( xmlhttp.responseText );
} catch ( e ) {}
}
if ( response && response.success ) {
// Email captured successfully, proceed to load the video and remove the email capture gate
this._isRendered = true;
this._removeClass( 'email-capture' );
this.emailCapture = false;
this._warmConnections();
this._addIframe( true );
// Email submission implies consent — remove both gates from other players
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
videos[ i ].removeCookieConsent();
videos[ i ].removeEmailCapture();
}
window.postMessage({
message: 'aiovg-email-captured'
}, window.location.origin );
} else {
// Show error message
const errorSpan = this.$emailCaptureModal.querySelector( '.email-capture-error' );
if ( errorSpan ) {
errorSpan.textContent = ( response && response.data && typeof response.data === 'string' ) ? response.data : errorSpan.getAttribute( 'data-error_generic' );
errorSpan.style.display = 'block';
}
// Restore the form so the user can retry.
this.$emailCaptureModal.classList.remove( 'is-loading' );
}
}
};
xmlhttp.open( 'POST', this._ajaxUrl + '?action=aiovg_save_email_lead&security=' + this._ajaxNonce, true );
xmlhttp.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );
xmlhttp.send( data );
}
_addPosterImage() {
if ( this._isPosterImageLoaded ) return false;
this._isPosterImageLoaded = true;
if ( this.poster ) {
this.$posterImage.src = this.poster;
}
}
_addIframe( autoplayRequested = false ) {
if ( this._isIframeLoaded || this.emailCapture || this.cookieConsent ) return false;
this._isIframeLoaded = true;
const iframeEl = document.createElement( 'iframe' );
iframeEl.width = 560;
iframeEl.height = 315;
iframeEl.title = this.title;
iframeEl.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share';
iframeEl.allowFullscreen = true;
if ( /youtube\.com|youtu\.be/.test( this.src ) ) {
iframeEl.referrerPolicy = 'strict-origin-when-cross-origin';
}
if ( autoplayRequested ) {
const url = new URL( this.src );
let searchParams = url.searchParams;
searchParams.set( 'autoplay', 1 );
url.search = searchParams.toString();
iframeEl.src = url.toString();
} else {
iframeEl.src = this.src;
}
this.$root.append( iframeEl );
this._onIframeAdded( iframeEl );
this._addClass( 'initialized' );
this._updateViewsCount();
}
_initIntersectionObserver() {
if ( this._intersectionObserver ) return false;
const options = {
root: null,
rootMargin: '0px',
threshold: 0,
};
this._intersectionObserver = new IntersectionObserver(( entries, observer ) => {
entries.forEach(entry => {
if ( entry.isIntersecting ) {
this._isInViewport = true;
this._render();
if ( this._isRendered ) observer.unobserve( this );
} else {
this._isInViewport = false;
}
});
}, options);
this._intersectionObserver.observe( this );
}
_hasClass( className ) {
return this.$root.classList.contains( className );
}
_addClass( className ) {
this.$root.classList.add( className );
}
_removeClass( className ) {
this.$root.classList.remove( className );
}
/**
* Define private async methods.
*/
async _updateViewsCount() {
if ( this.statistics && this.postType == 'aiovg_videos' ) {
let formData = new FormData();
formData.append( 'action', 'aiovg_update_views_count' );
formData.append( 'post_id', this.postId );
formData.append( 'security', this._ajaxNonce );
fetch( this._ajaxUrl, { method: 'POST', body: formData } );
}
}
async _setCookie() {
let formData = new FormData();
formData.append( 'action', 'aiovg_set_cookie' );
formData.append( 'security', this._ajaxNonce );
fetch( this._ajaxUrl, { method: 'POST', body: formData } );
}
/**
* Define public methods.
*/
_warmConnections() {
// Always overridden by the child classes
}
_onIframeAdded() {
// Always overridden by the child classes
}
/**
* Define public static methods.
*/
static isValidUrl( url ) {
if ( url == '' ) return false;
try {
new URL( url );
return true;
} catch ( error ) {
return false;
}
}
static addPrefetch( kind, url ) {
const linkElem = document.createElement( 'link' );
linkElem.rel = kind;
linkElem.href = url;
linkElem.crossOrigin = 'true';
document.head.append( linkElem );
}
/**
* Define API methods.
*/
removeCookieConsent() {
if ( this._isRendered ) return false;
this._removeClass( 'cookieconsent' );
this.cookieConsent = false;
this._render();
}
removeEmailCapture() {
if ( this._isRendered ) return false;
this._removeClass( 'email-capture' );
this.emailCapture = false;
this._render();
}
play() {
// Always overridden by the child classes
}
pause() {
// Always overridden by the child classes
}
seekTo( seconds ) {
// Always overridden by the child classes
}
}
class AIOVGYouTubeElement extends AIOVGBaseElement {
constructor() {
super();
this._addClass( 'youtube' );
// Set references to the private properties used by the component
this._player = null;
}
/**
* Browser calls this method when the element is removed from the document.
* (can be called many times if an element is repeatedly added/removed)
*/
disconnectedCallback() {
if ( this._player && this._player.destroy ) {
this._player.destroy();
}
this._player = null;
if ( super.disconnectedCallback ) {
super.disconnectedCallback();
}
}
/**
* Define public methods.
*/
_warmConnections() {
if ( window.AIOVGYouTubeIsPreconnected ) return false;
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://i.ytimg.com' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://s.ytimg.com' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://yt3.ggpht.com' );
if ( this.src.indexOf( 'www.youtube-nocookie.com' ) > -1 ) {
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://www.youtube-nocookie.com' );
} else {
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://www.youtube.com' );
}
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://www.google.com' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://googleads.g.doubleclick.net' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://static.doubleclick.net' );
window.AIOVGYouTubeIsPreconnected = true;
}
_onIframeAdded( iframeEl ) {
this._loadApi().then(() => {
const player = new YT.Player( iframeEl, {
events: {
'onReady': () => {
this._player = player;
},
'onStateChange': ( event ) => {
if ( 1 == event.data ) { // Playing
// Pause other players
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
if ( videos[ i ] != this ) {
videos[ i ].pause();
}
}
window.postMessage({
message: 'aiovg-video-playing'
}, window.location.origin );
}
}
}
});
});
}
/**
* Define private methods.
*/
_loadApi() {
return new Promise(( resolve ) => {
if ( typeof window.YT === 'undefined' && typeof AIOVGYouTubeElement.isApiLoaded === 'undefined' ) {
AIOVGYouTubeElement.isApiLoaded = true;
const tag = document.createElement( 'script' );
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName( 'script' )[0];
firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );
}
if ( typeof window.YT !== 'undefined' && window.YT.Player ) {
resolve();
} else {
let intervalHandler = setInterval(function() {
if ( typeof window.YT !== 'undefined' && window.YT.Player ) {
clearInterval( intervalHandler );
resolve();
}
}, 100 );
}
});
}
/**
* Define API methods.
*/
play() {
if ( this._player && this._player.playVideo ) {
this._player.playVideo();
}
}
pause() {
if ( this._player && this._player.pauseVideo ) {
this._player.pauseVideo();
}
}
seekTo( seconds ) {
if ( this._player && this._player.seekTo ) {
this._player.seekTo( seconds, true );
}
}
}
class AIOVGVimeoElement extends AIOVGBaseElement {
constructor() {
super();
this._addClass( 'vimeo' );
// Set references to the private properties used by the component
this._player = null;
}
/**
* Browser calls this method when the element is removed from the document.
* (can be called many times if an element is repeatedly added/removed)
*/
disconnectedCallback() {
if ( this._player && this._player.destroy ) {
this._player.destroy();
}
this._player = null;
if ( super.disconnectedCallback ) {
super.disconnectedCallback();
}
}
/**
* Define public methods.
*/
_warmConnections() {
if ( window.AIOVGVimeoIsPreconnected ) return false;
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://i.vimeocdn.com' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://player.vimeo.com' );
window.AIOVGVimeoIsPreconnected = true;
}
_onIframeAdded( iframeEl ) {
this._loadApi().then(() => {
const player = new Vimeo.Player( iframeEl );
player.ready().then(() => {
this._player = player;
});
player.on( 'play', ( data ) => {
// Pause other players
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
if ( videos[ i ] != this ) {
videos[ i ].pause();
}
}
window.postMessage({
message: 'aiovg-video-playing'
}, window.location.origin );
});
});
}
/**
* Define private methods.
*/
_loadApi() {
return new Promise(( resolve ) => {
if ( typeof window.Vimeo === 'undefined' && typeof AIOVGVimeoElement.isApiLoaded === 'undefined' ) {
AIOVGVimeoElement.isApiLoaded = true;
const tag = document.createElement( 'script' );
tag.src = 'https://player.vimeo.com/api/player.js';
const firstScriptTag = document.getElementsByTagName( 'script' )[0];
firstScriptTag.parentNode.insertBefore( tag, firstScriptTag );
}
if ( typeof window.Vimeo !== 'undefined' && window.Vimeo.Player ) {
resolve();
} else {
let intervalHandler = setInterval(function() {
if ( typeof window.Vimeo !== 'undefined' && window.Vimeo.Player ) {
clearInterval( intervalHandler );
resolve();
}
}, 100 );
}
});
}
/**
* Define API methods.
*/
play() {
if ( this._player && this._player.play ) {
this._player.play();
}
}
pause() {
if ( this._player && this._player.pause ) {
this._player.pause();
}
}
seekTo( seconds ) {
if ( this._player && this._player.setCurrentTime ) {
this._player.setCurrentTime( seconds );
}
}
}
class AIOVGDailymotionElement extends AIOVGBaseElement {
constructor() {
super();
this._addClass( 'dailymotion' );
}
_warmConnections() {
if ( window.AIOVGDailymotionIsPreconnected ) return false;
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://s1.dmcdn.net' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://s2.dmcdn.net' );
AIOVGBaseElement.addPrefetch( 'preconnect', 'https://www.dailymotion.com' );
window.AIOVGDailymotionIsPreconnected = true;
}
}
class AIOVGIframeElement extends AIOVGBaseElement {
constructor() {
super();
this._forceIframeElement = true;
}
}
window.AIOVGYouTubeIsPreconnected = false;
window.AIOVGVimeoIsPreconnected = false;
window.AIOVGDailymotionIsPreconnected = false;
/**
* Called when the page has loaded.
*/
document.addEventListener( 'DOMContentLoaded', function() {
// Register custom elements
if ( ! customElements.get( 'aiovg-youtube' ) ) {
customElements.define( 'aiovg-youtube', AIOVGYouTubeElement );
}
if ( ! customElements.get( 'aiovg-vimeo' ) ) {
customElements.define( 'aiovg-vimeo', AIOVGVimeoElement );
}
if ( ! customElements.get( 'aiovg-dailymotion' ) ) {
customElements.define( 'aiovg-dailymotion', AIOVGDailymotionElement );
}
if ( ! customElements.get( 'aiovg-embed' ) ) {
customElements.define( 'aiovg-embed', AIOVGIframeElement );
}
// Update views count for the non-iframe embeds
const videos = document.querySelectorAll( '.aiovg-player-raw' );
for ( let i = 0; i < videos.length; i++ ) {
const elem = videos[ i ];
const post_id = parseInt( elem.dataset.post_id );
const statistics = parseInt( elem.dataset.statistics );
if ( statistics ) {
let formData = new FormData();
formData.append( 'action', 'aiovg_update_views_count' );
formData.append( 'post_id', post_id );
formData.append( 'security', aiovg_embed.ajax_nonce );
fetch( aiovg_embed.ajax_url, { method: 'POST', body: formData } );
}
}
// Listen to the iframe player events
window.addEventListener( 'message', function( event ) {
if ( event.origin != window.location.origin ) {
return false;
}
if ( ! event.data.hasOwnProperty( 'context' ) || event.data.context != 'iframe' ) {
return false;
}
if ( ! event.data.hasOwnProperty( 'message' ) ) {
return false;
}
if ( event.data.message == 'aiovg-cookie-consent' ) {
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
videos[ i ].removeCookieConsent();
}
}
if ( event.data.message == 'aiovg-email-captured' ) {
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
videos[ i ].removeEmailCapture();
}
}
if ( event.data.message == 'aiovg-video-playing' ) {
const videos = document.querySelectorAll( '.aiovg-player-element' );
for ( let i = 0; i < videos.length; i++ ) {
videos[ i ].pause();
}
}
});
});
})();