1112 lines
32 KiB
JavaScript
1112 lines
32 KiB
JavaScript
(function( $ ) {
|
|
'use strict';
|
|
|
|
class AIOVGVideoElement extends HTMLElement {
|
|
|
|
/**
|
|
* Element created.
|
|
*/
|
|
constructor() {
|
|
super();
|
|
|
|
// Set references to the DOM elements used by the component
|
|
this.player = null;
|
|
this.playButtonEl = null;
|
|
this.cookieConsentEl = null;
|
|
this.emailCaptureEl = null;
|
|
|
|
// Set references to the public properties used by the component
|
|
this.settings = {};
|
|
|
|
// Set references to the private properties used by the component
|
|
this._playerId = '';
|
|
this._hasVideoStarted = false;
|
|
this._ajaxUrl = aiovg_player.ajax_url;
|
|
this._ajaxNonce = aiovg_player.ajax_nonce;
|
|
}
|
|
|
|
/**
|
|
* 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() {
|
|
this._playerId = this.dataset.id || '';
|
|
|
|
this.settings = this.dataset.params ? JSON.parse( this.dataset.params ) : {};
|
|
|
|
if ( ! this.settings.hasOwnProperty( 'player' ) ) {
|
|
this.settings.player = {};
|
|
}
|
|
|
|
this.settings.player.html5 = {
|
|
vhs: {
|
|
overrideNative: ! videojs.browser.IS_ANY_SAFARI,
|
|
}
|
|
};
|
|
|
|
if ( this.settings.hasOwnProperty( 'email_capture' ) ) {
|
|
this.emailCaptureEl = this.querySelector( '.aiovg-email-capture' );
|
|
}
|
|
|
|
if ( this.emailCaptureEl && parseInt( this.emailCaptureEl.dataset.pre_roll ) ) {
|
|
this._initPreRollEmailCapture();
|
|
} else if ( this.settings.cookie_consent ) {
|
|
this.cookieConsentEl = this.querySelector( '.aiovg-privacy-wrapper' );
|
|
const cookieConsentButtonEl = this.querySelector( '.aiovg-privacy-consent-button' );
|
|
|
|
if ( this.cookieConsentEl && cookieConsentButtonEl !== null ) {
|
|
const poster = this.cookieConsentEl.getAttribute( 'data-poster' ) || '';
|
|
if ( AIOVGVideoElement.isValidUrl( poster ) ) {
|
|
this.cookieConsentEl.style.backgroundImage = `url("${poster}")`;
|
|
}
|
|
|
|
cookieConsentButtonEl.addEventListener( 'click', () => this._onCookieConsent() );
|
|
} else {
|
|
this._initPlayer();
|
|
}
|
|
} else {
|
|
this._initPlayer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
}
|
|
|
|
/**
|
|
* Define private methods.
|
|
*/
|
|
|
|
_onCookieConsent() {
|
|
this.settings.player.autoplay = 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 );
|
|
}
|
|
|
|
_initPreRollEmailCapture() {
|
|
this.classList.add( 'aiovg-show-email-capture' );
|
|
|
|
const poster = this.emailCaptureEl.getAttribute( 'data-poster' ) || '';
|
|
if ( AIOVGVideoElement.isValidUrl( poster ) ) {
|
|
this.emailCaptureEl.style.backgroundImage = `url("${poster}")`;
|
|
}
|
|
|
|
const firstInput = this.emailCaptureEl.querySelector( 'input' );
|
|
if ( firstInput ) {
|
|
firstInput.focus();
|
|
}
|
|
|
|
this._initEmailCaptureForm( ( data ) => {
|
|
if ( ! this.emailCaptureEl ) return false;
|
|
|
|
if ( this.emailCaptureEl.classList.contains( 'aiovg-is-loading' ) ) return false; // Prevent multiple submissions
|
|
this.emailCaptureEl.classList.add( 'aiovg-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 ) {
|
|
// Hide the form and remove it from the DOM to prevent it from being submitted again.
|
|
this.classList.remove( 'aiovg-show-email-capture' );
|
|
|
|
this.emailCaptureEl.remove();
|
|
this.emailCaptureEl = null;
|
|
|
|
// Render player
|
|
this.settings.player.autoplay = true;
|
|
this._initPlayer();
|
|
|
|
// 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.emailCaptureEl.querySelector( '.aiovg-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.emailCaptureEl.classList.remove( 'aiovg-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 );
|
|
} );
|
|
}
|
|
|
|
_initPlayer() {
|
|
if ( this.player ) {
|
|
return false;
|
|
}
|
|
|
|
this.player = videojs( this.querySelector( 'video-js' ), this.settings.player );
|
|
|
|
this.player.ready( () => this._onReady() );
|
|
this.player.one( 'loadedmetadata', () => this._onMetadataLoaded() );
|
|
this.player.on( 'play', () => this._onPlay() );
|
|
this.player.on( 'playing', () => this._onPlaying() );
|
|
this.player.on( 'ended', () => this._onEnded() );
|
|
|
|
this._initOffset();
|
|
this._initChapters();
|
|
this._initQualitySelector();
|
|
this._initOverlays();
|
|
this._initHotKeys();
|
|
this._initEmailCapture();
|
|
this._initContextMenu();
|
|
|
|
// Dispatch a player ready event
|
|
const options = {
|
|
id: this._playerId, // Backward compatibility to 3.3.0
|
|
player_id: this._playerId,
|
|
config: this.settings, // Backward compatibility to 3.3.0
|
|
settings: this.settings,
|
|
player: this.player
|
|
};
|
|
|
|
this._dispatchEvent( 'player.init', options );
|
|
}
|
|
|
|
_onReady() {
|
|
this.classList.remove( 'vjs-waiting' );
|
|
|
|
this.playButtonEl = this.querySelector( '.vjs-big-play-button' );
|
|
if ( this.playButtonEl !== null ) {
|
|
this.playButtonEl.addEventListener( 'click', () => this._onPlayClicked() );
|
|
}
|
|
}
|
|
|
|
_onMetadataLoaded() {
|
|
// Quality selector
|
|
const qualitySelectorEl = this.querySelector( '.vjs-quality-selector' );
|
|
|
|
if ( qualitySelectorEl !== null ) {
|
|
const items = qualitySelectorEl.querySelectorAll( '.vjs-menu-item' );
|
|
|
|
for ( let i = 0; i < items.length; i++ ) {
|
|
let item = items[ i ];
|
|
|
|
const textNode = item.querySelector( '.vjs-menu-item-text' );
|
|
const resolution = textNode.innerHTML.replace( /\D/g, '' );
|
|
|
|
if ( resolution >= 2160 ) {
|
|
item.innerHTML += '<span class="vjs-quality-menu-item-sub-label">4K</span>';
|
|
} else if ( resolution >= 720 ) {
|
|
item.innerHTML += '<span class="vjs-quality-menu-item-sub-label">HD</span>';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add support for SRT
|
|
if ( this.settings.hasOwnProperty( 'tracks' ) ) {
|
|
for ( let i = 0, max = this.settings.tracks.length; i < max; i++ ) {
|
|
const track = this.settings.tracks[ i ];
|
|
|
|
let mode = '';
|
|
if ( i == 0 && this.settings.cc_load_policy == 1 ) {
|
|
mode = 'showing';
|
|
}
|
|
|
|
if ( /srt/.test( track.src.toLowerCase() ) ) {
|
|
this._addSrtTextTrack( track, mode );
|
|
} else {
|
|
const obj = {
|
|
kind: 'captions',
|
|
src: track.src,
|
|
label: track.label,
|
|
srclang: track.srclang
|
|
};
|
|
|
|
if ( mode ) {
|
|
obj.mode = mode;
|
|
}
|
|
|
|
this.player.addRemoteTextTrack( obj, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Chapters
|
|
if ( this.settings.hasOwnProperty( 'chapters' ) ) {
|
|
this._addMarkers();
|
|
}
|
|
}
|
|
|
|
_onPlayClicked() {
|
|
if ( ! this._hasVideoStarted ) {
|
|
this.classList.add( 'vjs-waiting' );
|
|
}
|
|
|
|
this.playButtonEl.removeEventListener( 'click', () => this._onPlayClicked() );
|
|
}
|
|
|
|
_onPlay() {
|
|
if ( ! this._hasVideoStarted ) {
|
|
this._hasVideoStarted = true;
|
|
this.classList.remove( 'vjs-waiting' );
|
|
|
|
this._updateViewsCount();
|
|
}
|
|
|
|
// 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 );
|
|
}
|
|
|
|
_onPlaying() {
|
|
this.player.trigger( 'controlsshown' );
|
|
}
|
|
|
|
_onEnded() {
|
|
this.player.trigger( 'controlshidden' );
|
|
}
|
|
|
|
_initOffset() {
|
|
const offset = {};
|
|
|
|
if ( this.settings.hasOwnProperty( 'start' ) ) {
|
|
offset.start = this.settings.start;
|
|
}
|
|
|
|
if ( this.settings.hasOwnProperty( 'end' ) ) {
|
|
offset.end = this.settings.end;
|
|
}
|
|
|
|
if ( Object.keys( offset ).length > 1 ) {
|
|
offset.restart_beginning = false;
|
|
this.player.offset( offset );
|
|
}
|
|
}
|
|
|
|
_initChapters() {
|
|
if ( ! this.settings.hasOwnProperty( 'chapters' ) ) {
|
|
return false;
|
|
}
|
|
|
|
const root = this;
|
|
|
|
try {
|
|
this.player.getDescendant([
|
|
'ControlBar',
|
|
'ProgressControl',
|
|
'SeekBar',
|
|
'MouseTimeDisplay',
|
|
'TimeTooltip',
|
|
]).update = function( seekBarRect, seekBarPoint, time ) {
|
|
const markers = root.settings.chapters;
|
|
const markerIndex = markers.findIndex( ( { time: markerTime } ) => markerTime == root._formattedTimeToSeconds( time ) );
|
|
|
|
if ( markerIndex > -1 ) {
|
|
const label = markers[ markerIndex ].label;
|
|
|
|
videojs.dom.emptyEl( this.el() );
|
|
videojs.dom.appendContent( this.el(), [ root._labelEl( label ), root._timeEl( time ) ] );
|
|
|
|
return false;
|
|
}
|
|
|
|
this.write( time );
|
|
};
|
|
} catch ( error ) {
|
|
// console.log( error );
|
|
}
|
|
}
|
|
|
|
_initQualitySelector() {
|
|
// Standard quality selector
|
|
this.player.on( 'qualitySelected', ( event, source ) => {
|
|
const resolution = source.label.replace( /\D/g, '' );
|
|
|
|
this.player.removeClass( 'vjs-4k' );
|
|
this.player.removeClass( 'vjs-hd' );
|
|
|
|
if ( resolution >= 2160 ) {
|
|
this.player.addClass( 'vjs-4k' );
|
|
} else if ( resolution >= 720 ) {
|
|
this.player.addClass( 'vjs-hd' );
|
|
}
|
|
});
|
|
|
|
// HLS quality selector
|
|
const src = this.player.src();
|
|
|
|
if ( /.m3u8/.test( src ) || /.mpd/.test( src ) ) {
|
|
if ( this.settings.player.controlBar.children.indexOf( 'QualitySelector' ) != -1 ) {
|
|
this.player.qualityMenu();
|
|
}
|
|
}
|
|
}
|
|
|
|
_initOverlays() {
|
|
const overlays = [];
|
|
|
|
// Share / Embed
|
|
if ( this.settings.hasOwnProperty( 'share' ) || this.settings.hasOwnProperty( 'embed' ) ) {
|
|
overlays.push({
|
|
content: '<button type="button" class="vjs-share-embed-button" title="Share"><span class="vjs-icon-share" aria-hidden="true"></span><span class="vjs-control-text" aria-live="polite">Share</span></button>',
|
|
class: 'vjs-share',
|
|
align: 'top-right',
|
|
start: 'controlsshown',
|
|
end: 'controlshidden',
|
|
showBackground: false
|
|
});
|
|
}
|
|
|
|
// Download
|
|
if ( this.settings.hasOwnProperty( 'download' ) ) {
|
|
let className = 'vjs-download';
|
|
|
|
if ( this.settings.hasOwnProperty( 'share' ) || this.settings.hasOwnProperty( 'embed' ) ) {
|
|
className += ' vjs-has-share';
|
|
}
|
|
|
|
overlays.push({
|
|
content: '<a href="' + this.settings.download.url + '" class="vjs-download-button" title="Download" target="_blank"><span class="vjs-icon-file-download" aria-hidden="true"></span><span class="vjs-control-text" aria-live="polite">Download</span></a>',
|
|
class: className,
|
|
align: 'top-right',
|
|
start: 'controlsshown',
|
|
end: 'controlshidden',
|
|
showBackground: false
|
|
});
|
|
}
|
|
|
|
// Logo / Trailer Badge
|
|
let hasLogo = this.settings.hasOwnProperty( 'logo' );
|
|
let hasTrailer = this.settings.hasOwnProperty( 'trailer' );
|
|
|
|
if ( hasLogo || hasTrailer ) {
|
|
let align = 'bottom-left';
|
|
let style = 'margin: 5px;';
|
|
|
|
if ( hasLogo ) {
|
|
if ( this.settings.logo.margin ) {
|
|
this.settings.logo.margin = this.settings.logo.margin - 5;
|
|
}
|
|
|
|
style = 'margin: ' + this.settings.logo.margin + 'px;';
|
|
|
|
switch ( this.settings.logo.position ) {
|
|
case 'topleft':
|
|
align = 'top-left';
|
|
break;
|
|
|
|
case 'topright':
|
|
align = 'top-right';
|
|
break;
|
|
|
|
case 'bottomright':
|
|
align = 'bottom-right';
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Determine the href: trailer URL takes precedence when active.
|
|
let logoHref = hasLogo ? this.settings.logo.link : 'javascript:void(0)';
|
|
|
|
if ( hasTrailer && this.settings.trailer.url ) {
|
|
logoHref = this.settings.trailer.url;
|
|
}
|
|
|
|
// Icon: logo image > external-link SVG (only when URL set) > nothing.
|
|
let iconHtml = '';
|
|
|
|
if ( hasLogo ) {
|
|
iconHtml = '<img src="' + this.settings.logo.image + '" alt="" />';
|
|
} else if ( hasTrailer && this.settings.trailer.url ) {
|
|
iconHtml = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="#fff" aria-hidden="true"><path d="M19 19H5V5h7V3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></svg>';
|
|
}
|
|
|
|
// Label: visible trailer label or sr-only text for logo-only mode.
|
|
let labelHtml = hasTrailer ? '<span class="vjs-logo-label">' + this.settings.trailer.label + '</span>' : '<span class="vjs-control-text" aria-live="polite">Logo</span>';
|
|
let logoContent = '<a href="' + logoHref + '" target="_top" style="' + style + '">' + iconHtml + labelHtml + '</a>';
|
|
|
|
overlays.push({
|
|
content: logoContent,
|
|
class: 'vjs-logo',
|
|
align: align,
|
|
start: 'controlsshown',
|
|
end: 'controlshidden',
|
|
showBackground: false
|
|
});
|
|
}
|
|
|
|
// Overlay
|
|
if ( overlays.length > 0 ) {
|
|
this.player.overlay({
|
|
content: '',
|
|
overlays: overlays
|
|
});
|
|
|
|
if ( this.settings.hasOwnProperty( 'share' ) || this.settings.hasOwnProperty( 'embed' ) ) {
|
|
const options = {};
|
|
options.content = this.querySelector( '.vjs-share-embed' );
|
|
options.temporary = false;
|
|
|
|
const ModalDialog = videojs.getComponent( 'ModalDialog' );
|
|
const modal = new ModalDialog( this.player, options );
|
|
modal.addClass( 'vjs-modal-dialog-share-embed' );
|
|
|
|
this.player.addChild( modal );
|
|
|
|
let wasPlaying = true;
|
|
this.querySelector( '.vjs-share-embed-button' ).addEventListener( 'click', () => {
|
|
wasPlaying = ! this.player.paused();
|
|
modal.open();
|
|
});
|
|
|
|
modal.on( 'modalclose', () => {
|
|
if ( wasPlaying ) {
|
|
this.player.play();
|
|
}
|
|
});
|
|
}
|
|
|
|
if ( this.settings.hasOwnProperty( 'embed' ) ) {
|
|
this.querySelector( '.vjs-input-embed-code' ).addEventListener( 'focus', function() {
|
|
this.select();
|
|
|
|
if ( navigator.clipboard && navigator.clipboard.writeText ) {
|
|
navigator.clipboard.writeText( this.value ).catch( () => {} );
|
|
} else {
|
|
document.execCommand( 'copy' );
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
_initHotKeys() {
|
|
if ( this.settings.hotkeys ) {
|
|
this.player.hotkeys();
|
|
}
|
|
}
|
|
|
|
_initEmailCapture() {
|
|
if ( ! this.emailCaptureEl ) return false;
|
|
|
|
this.emailCaptureEl.style.backgroundImage = 'none';
|
|
this.player.el().appendChild( this.emailCaptureEl );
|
|
|
|
let isModalOpen = false;
|
|
let wasPlaying = false;
|
|
|
|
const showEmailCapture = () => {
|
|
if ( ! this.emailCaptureEl || isModalOpen ) return false;
|
|
isModalOpen = true;
|
|
|
|
if ( this.player && ! this.player.ended() ) {
|
|
wasPlaying = ! this.player.paused();
|
|
this.player.pause();
|
|
}
|
|
|
|
this.classList.add( 'aiovg-show-email-capture' );
|
|
|
|
const firstInput = this.emailCaptureEl.querySelector( 'input' );
|
|
if ( firstInput ) {
|
|
firstInput.focus();
|
|
}
|
|
};
|
|
|
|
const hideEmailCapture = () => {
|
|
if ( ! this.emailCaptureEl || ! isModalOpen ) return false;
|
|
isModalOpen = false; // Clear before player.play() so the guard above does not block it.
|
|
|
|
this.classList.remove( 'aiovg-show-email-capture' );
|
|
|
|
this.emailCaptureEl.remove();
|
|
this.emailCaptureEl = null;
|
|
|
|
if ( wasPlaying ) {
|
|
this.player.play();
|
|
}
|
|
}
|
|
|
|
const ajaxEmailCapture = ( data ) => {
|
|
if ( ! this.emailCaptureEl ) return false;
|
|
|
|
if ( this.emailCaptureEl.classList.contains( 'aiovg-is-loading' ) ) return false; // Prevent multiple submissions
|
|
this.emailCaptureEl.classList.add( 'aiovg-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 ) {
|
|
// Hide the form and remove it from the DOM to prevent it from being submitted again.
|
|
hideEmailCapture();
|
|
|
|
// 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.emailCaptureEl.querySelector( '.aiovg-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.emailCaptureEl.classList.remove( 'aiovg-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 );
|
|
};
|
|
|
|
// Mid-roll — show when currentTime reaches the configured percentage.
|
|
const midRoll = parseInt( this.emailCaptureEl.dataset.mid_roll );
|
|
|
|
if ( midRoll ) {
|
|
let midRollFired = false;
|
|
|
|
const onMidRollTimeUpdate = () => {
|
|
if ( ! this.emailCaptureEl ) {
|
|
this.player.off( 'timeupdate', onMidRollTimeUpdate );
|
|
return false;
|
|
}
|
|
|
|
if ( midRollFired ) return false;
|
|
|
|
// Skip during ad playback — currentTime/duration reflect the ad, not the content.
|
|
if ( this.settings.hasOwnProperty( 'ads' ) && this.player.ads && this.player.ads.isInAdMode() ) {
|
|
return false;
|
|
}
|
|
|
|
const duration = this.player.duration();
|
|
const current = this.player.currentTime();
|
|
|
|
if ( duration && current >= ( midRoll / 100 ) * duration ) {
|
|
midRollFired = true;
|
|
this.player.off( 'timeupdate', onMidRollTimeUpdate );
|
|
showEmailCapture();
|
|
}
|
|
};
|
|
|
|
this.player.on( 'timeupdate', onMidRollTimeUpdate );
|
|
}
|
|
|
|
// Post-roll — show after the video ends.
|
|
const postRoll = parseInt( this.emailCaptureEl.dataset.post_roll );
|
|
|
|
if ( postRoll ) {
|
|
this.player.on( 'ended', () => {
|
|
showEmailCapture();
|
|
} );
|
|
}
|
|
|
|
// Re-pause on any play event while the overlay is open.
|
|
this.player.on( 'play', () => {
|
|
if ( ! this.emailCaptureEl || ! isModalOpen ) return false;
|
|
|
|
wasPlaying = true;
|
|
this.player.pause();
|
|
} );
|
|
|
|
this.player.on( 'playing', () => {
|
|
if ( ! this.emailCaptureEl || ! isModalOpen ) return false;
|
|
|
|
wasPlaying = true;
|
|
this.player.pause();
|
|
} );
|
|
|
|
this._initEmailCaptureForm( ( data ) => ajaxEmailCapture( data ) );
|
|
}
|
|
|
|
_initEmailCaptureForm( onSubmit ) {
|
|
const submitBtn = this.querySelector( '.aiovg-email-capture-submit' );
|
|
const skipLink = this.querySelector( '.aiovg-email-capture-skip' );
|
|
|
|
if ( submitBtn ) {
|
|
submitBtn.addEventListener( 'click', () => {
|
|
const emailField = this.emailCaptureEl.querySelector( '.aiovg-email-capture-email' );
|
|
const errorSpan = this.emailCaptureEl.querySelector( '.aiovg-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( 'aiovg-is-invalid' );
|
|
emailField.setAttribute( 'aria-invalid', 'true' );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if ( errorSpan ) {
|
|
errorSpan.style.display = 'none';
|
|
}
|
|
|
|
if ( emailField ) {
|
|
emailField.classList.remove( 'aiovg-is-invalid' );
|
|
emailField.removeAttribute( 'aria-invalid' );
|
|
}
|
|
|
|
let params = 'email=' + encodeURIComponent( email );
|
|
|
|
const nameField = this.emailCaptureEl.querySelector( '.aiovg-email-capture-name' );
|
|
if ( nameField && nameField.value.trim() ) {
|
|
params += '&name=' + encodeURIComponent( nameField.value.trim() );
|
|
}
|
|
|
|
const phoneField = this.emailCaptureEl.querySelector( '.aiovg-email-capture-phone' );
|
|
if ( phoneField && phoneField.value.trim() ) {
|
|
params += '&phone=' + encodeURIComponent( phoneField.value.trim() );
|
|
}
|
|
|
|
if ( 'aiovg_videos' == this.settings.post_type && this.settings.post_id ) {
|
|
params += '&video_id=' + encodeURIComponent( this.settings.post_id );
|
|
} else {
|
|
params += '&video_id=0';
|
|
|
|
if ( this.emailCaptureEl.dataset.video_url ) {
|
|
params += '&video_url=' + encodeURIComponent( this.emailCaptureEl.dataset.video_url );
|
|
}
|
|
}
|
|
|
|
params += '&page_url=' + encodeURIComponent( window.location.href );
|
|
|
|
onSubmit( params );
|
|
} );
|
|
}
|
|
|
|
if ( skipLink ) {
|
|
const doSkip = () => onSubmit( 'skipped=1' );
|
|
|
|
skipLink.addEventListener( 'click', doSkip );
|
|
|
|
skipLink.addEventListener( 'keydown', ( event ) => {
|
|
if ( 13 === event.keyCode || 32 === event.keyCode ) {
|
|
event.preventDefault();
|
|
doSkip();
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
|
|
_initContextMenu() {
|
|
if ( ! this.settings.hasOwnProperty( 'contextmenu' ) ) {
|
|
return false;
|
|
}
|
|
|
|
let contextmenuEl = document.querySelector( '#aiovg-contextmenu' );
|
|
if ( contextmenuEl === null ) {
|
|
contextmenuEl = document.createElement( 'div' );
|
|
contextmenuEl.id = 'aiovg-contextmenu';
|
|
contextmenuEl.style.display = 'none';
|
|
contextmenuEl.innerHTML = '<div class="aiovg-contextmenu-content">' + this.settings.contextmenu.content + '</div>';
|
|
|
|
document.body.appendChild( contextmenuEl );
|
|
|
|
document.addEventListener( 'click', () => {
|
|
contextmenuEl.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
let timeoutHandler = '';
|
|
|
|
this.addEventListener( 'contextmenu', function( event ) {
|
|
if ( event.keyCode == 3 || event.which == 3 ) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
let width = contextmenuEl.offsetWidth,
|
|
height = contextmenuEl.offsetHeight,
|
|
x = event.pageX,
|
|
y = event.pageY,
|
|
documentElement = document.documentElement,
|
|
scrollLeft = ( window.pageXOffset || documentElement.scrollLeft ) - ( documentElement.clientLeft || 0 ),
|
|
scrollTop = ( window.pageYOffset || documentElement.scrollTop ) - ( documentElement.clientTop || 0 ),
|
|
left = x + width > window.innerWidth + scrollLeft ? x - width : x,
|
|
top = y + height > window.innerHeight + scrollTop ? y - height : y;
|
|
|
|
contextmenuEl.style.display = '';
|
|
contextmenuEl.style.left = left + 'px';
|
|
contextmenuEl.style.top = top + 'px';
|
|
|
|
clearTimeout( timeoutHandler );
|
|
|
|
timeoutHandler = setTimeout( () => {
|
|
contextmenuEl.style.display = 'none';
|
|
}, 1500 );
|
|
}
|
|
});
|
|
}
|
|
|
|
_addSrtTextTrack( track, mode ) {
|
|
let xmlhttp;
|
|
|
|
if ( window.XMLHttpRequest ) {
|
|
xmlhttp = new XMLHttpRequest();
|
|
} else {
|
|
xmlhttp = new ActiveXObject( 'Microsoft.XMLHTTP' );
|
|
}
|
|
|
|
xmlhttp.onreadystatechange = () => {
|
|
if ( xmlhttp.readyState == 4 && xmlhttp.status == 200 && xmlhttp.responseText ) {
|
|
const text = this._srtToWebVTT( xmlhttp.responseText );
|
|
|
|
if ( text ) {
|
|
const blob = new Blob( [ text ], { type : 'text/vtt' } );
|
|
const src = URL.createObjectURL( blob );
|
|
|
|
const obj = {
|
|
kind: 'captions',
|
|
src: src,
|
|
label: track.label,
|
|
srclang: track.srclang
|
|
};
|
|
|
|
if ( mode ) {
|
|
obj.mode = mode;
|
|
}
|
|
|
|
this.player.addRemoteTextTrack( obj, true );
|
|
}
|
|
}
|
|
};
|
|
|
|
xmlhttp.open( 'GET', track.src, true );
|
|
xmlhttp.send();
|
|
}
|
|
|
|
_srtToWebVTT( data ) {
|
|
// Remove dos newlines
|
|
let srt = data.replace( /\r+/g, '' );
|
|
|
|
// Trim white space start and end
|
|
srt = srt.replace( /^\s+|\s+$/g, '' );
|
|
|
|
// Get cues
|
|
let cuelist = srt.split( '\n\n' );
|
|
let result = '';
|
|
|
|
if ( cuelist.length > 0 ) {
|
|
result += "WEBVTT\n\n";
|
|
|
|
for ( let i = 0; i < cuelist.length; i++ ) {
|
|
result += this._convertSrtCue( cuelist[ i ] );
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
_convertSrtCue( caption ) {
|
|
// Remove all html tags for security reasons
|
|
// srt = srt.replace( /<[a-zA-Z\/][^>]*>/g, '' );
|
|
|
|
let cue = '';
|
|
let s = caption.split( /\n/ );
|
|
|
|
// Concatenate muilt-line string separated in array into one
|
|
while ( s.length > 3 ) {
|
|
for ( let i = 3; i < s.length; i++ ) {
|
|
s[2] += "\n" + s[ i ];
|
|
}
|
|
|
|
s.splice( 3, s.length - 3 );
|
|
}
|
|
|
|
let line = 0;
|
|
|
|
// Detect identifier
|
|
if ( ! s[0].match( /\d+:\d+:\d+/ ) && s[1].match( /\d+:\d+:\d+/ ) ) {
|
|
cue += s[0].match( /\w+/ ) + "\n";
|
|
line += 1;
|
|
}
|
|
|
|
// Get time strings
|
|
if ( s[ line ].match( /\d+:\d+:\d+/ ) ) {
|
|
// Convert time string
|
|
let m = s[1].match( /(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/ );
|
|
|
|
if ( m ) {
|
|
cue += m[1] + ":" + m[2] + ":" + m[3] + "." + m[4] + " --> " + m[5] + ":" + m[6] + ":" + m[7] + "." + m[8] + "\n";
|
|
line += 1;
|
|
} else {
|
|
// Unrecognized timestring
|
|
return '';
|
|
}
|
|
} else {
|
|
// File format error or comment lines
|
|
return '';
|
|
}
|
|
|
|
// Get cue text
|
|
if ( s[ line ] ) {
|
|
cue += s[ line ] + "\n\n";
|
|
}
|
|
|
|
return cue;
|
|
}
|
|
|
|
_addMarkers() {
|
|
const total = this.player.duration();
|
|
const seekBarEl = this.player.el_.querySelector( '.vjs-progress-control .vjs-progress-holder' );
|
|
|
|
if ( seekBarEl !== null ) {
|
|
for ( let i = 0; i < this.settings.chapters.length; i++ ) {
|
|
const elem = document.createElement( 'div' );
|
|
elem.className = 'vjs-marker';
|
|
elem.style.left = ( this.settings.chapters[ i ].time / total ) * 100 + '%';
|
|
|
|
seekBarEl.appendChild( elem );
|
|
}
|
|
}
|
|
}
|
|
|
|
_formattedTimeToSeconds( time ) {
|
|
let timeSplit = time.split( ':' );
|
|
let seconds = +timeSplit.pop();
|
|
|
|
return timeSplit.reduce( ( acc, curr, i, arr ) => {
|
|
if ( arr.length === 2 && i === 1 ) return acc + +curr * 60 ** 2;
|
|
else return acc + +curr * 60;
|
|
}, seconds );
|
|
}
|
|
|
|
_timeEl( time ) {
|
|
return videojs.dom.createEl( 'span', undefined, undefined, '(' + time + ')' );
|
|
}
|
|
|
|
_labelEl( label ) {
|
|
return videojs.dom.createEl( 'strong', undefined, undefined, label );
|
|
}
|
|
|
|
_dispatchEvent( event, data ) {
|
|
$( this ).trigger( event, data );
|
|
}
|
|
|
|
_fetch( data ) {
|
|
$.post( this._ajaxUrl, data );
|
|
}
|
|
|
|
/**
|
|
* Define private async methods.
|
|
*/
|
|
|
|
async _setCookie() {
|
|
const data = {
|
|
'action': 'aiovg_set_cookie',
|
|
'security': this._ajaxNonce
|
|
};
|
|
|
|
this._fetch( data );
|
|
}
|
|
|
|
async _updateViewsCount() {
|
|
if ( this.settings.statistics && this.settings.post_type == 'aiovg_videos' ) {
|
|
const data = {
|
|
'action': 'aiovg_update_views_count',
|
|
'post_id': this.settings.post_id,
|
|
'duration': this.player.duration() || 0,
|
|
'security': this._ajaxNonce
|
|
};
|
|
|
|
this._fetch( data );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Define public static methods.
|
|
*/
|
|
|
|
static isValidUrl( url ) {
|
|
if ( url === '' ) return false;
|
|
|
|
try {
|
|
new URL( url );
|
|
return true;
|
|
} catch ( error ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Define API methods.
|
|
*/
|
|
|
|
removeCookieConsent() {
|
|
if ( ! this.cookieConsentEl ) return false;
|
|
|
|
this.cookieConsentEl.remove();
|
|
this.cookieConsentEl = null;
|
|
|
|
this._initPlayer();
|
|
}
|
|
|
|
removeEmailCapture() {
|
|
if ( ! this.emailCaptureEl ) return false;
|
|
|
|
this.classList.remove( 'aiovg-show-email-capture' );
|
|
|
|
this.emailCaptureEl.remove();
|
|
this.emailCaptureEl = null;
|
|
|
|
if ( ! this.player ) {
|
|
this._initPlayer();
|
|
}
|
|
}
|
|
|
|
pause() {
|
|
if ( this.player ) {
|
|
this.player.pause();
|
|
}
|
|
}
|
|
|
|
seekTo( seconds ) {
|
|
if ( this.player ) {
|
|
this.player.currentTime( seconds );
|
|
if ( ! this._hasVideoStarted ) {
|
|
this.player.play();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Called when the page has loaded.
|
|
*/
|
|
$(function() {
|
|
|
|
// Register custom element
|
|
if ( ! customElements.get( 'aiovg-video' ) ) {
|
|
customElements.define( 'aiovg-video', AIOVGVideoElement );
|
|
}
|
|
|
|
// Custom error message
|
|
if ( typeof videojs !== 'undefined' ) {
|
|
videojs.hook( 'beforeerror', function( player, error ) {
|
|
// Prevent current error from being cleared out
|
|
if ( error == null ) {
|
|
return player.error();
|
|
}
|
|
|
|
// But allow changing to a new error
|
|
if ( error.code == 2 || error.code == 4 ) {
|
|
const src = player.src();
|
|
|
|
if ( /.m3u8/.test( src ) || /.mpd/.test( src ) ) {
|
|
return {
|
|
code: error.code,
|
|
message: aiovg_player.i18n.stream_not_found
|
|
}
|
|
}
|
|
}
|
|
|
|
return error;
|
|
});
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
})( jQuery );
|