class VideoPopup {
constructor(options={}){
this.defaults={
autoplay: this.validateBoolean(options.autoplay, true),
wrapClose: this.validateBoolean(options.wrapClose, false),
noCookie: this.validateBoolean(options.noCookie, false),
handleVars: this.validateBoolean(options.handleVars, false),
onPageLoad: this.validateBoolean(options.onPageLoad, false),
oplCookie: options.oplCookie||false,
debug: this.validateBoolean(options.debug, false)
};
this.init();
}
init(){
this.addClickListener();
}
addClickListener(){
document.querySelectorAll('a.vp-a, a.vp-s').forEach(link=> {
link.addEventListener('click', async (e)=> {
if(link.classList.contains('vp-a')){
e.preventDefault();
link.blur();
await this.openPopup(link, true);
}
else if(link.classList.contains('vp-s')){
e.preventDefault();
link.blur();
await this.openPopup(link, false);
}});
});
}
validateBoolean(value, defaultValue){
if(value===undefined||value===null) return defaultValue;
if(value===true||value===false) return value;
if(value&&typeof value==='string'){
const cleanValue=value.trim().toLowerCase();
if(cleanValue==='true'||cleanValue==='1') return true;
if(cleanValue==='false'||cleanValue==='0') return false;
}
if(typeof value==='number'){
if(value===1) return true;
if(value===0) return false;
}
return defaultValue;
}
trimIfExists(value){
if(value&&(typeof value==='string'||typeof value==='number')){
const trimmed=typeof value==='string' ? value.trim():value;
return trimmed==='' ? null:trimmed;
}
return value;
}
async openPopup(element, autoplay){
const data=this.extractData(element);
const embedHTML=this.generateEmbed(data, autoplay);
await this.createPopup(embedHTML, data);
}
setCookie(name, days){
if(!name||!days) return;
const expirySec=Math.floor(Date.now() / 1000) + (days * 24 * 60 * 60);
const expiryDate=new Date(expirySec * 1000);
document.cookie=`${name}=${expirySec};expires=${expiryDate.toUTCString()};path=/`;
}
getCookie(name){
if(!name) return;
const match=document.cookie.match(new RegExp('(^|)' + name + '=([^;]+)'));
return match ? true:false;
}
unsetCookie(name){
if(!name) return;
if(this.getCookie(name)){
document.cookie=`${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
}}
extractData(element){
const url=element.href;
let autoplay_status;
if(element.classList.contains('vp-a')){
autoplay_status='true (vp-a class)';
}else if(element.classList.contains('vp-s')){
autoplay_status='false (vp-s class)';
}else{
autoplay_status='the link are not contains vp-s or vp-a class!';
}
const noCookie=this.trimIfExists(element.getAttribute('data-cookie'));
const wrapClose=this.trimIfExists(element.getAttribute('data-wrap-c'));
return {
url: url,
noCookie: this.validateBoolean(noCookie, this.defaults.noCookie),
wrapClose: this.validateBoolean(wrapClose, this.defaults.wrapClose),
videoType: this.detectVideoType(url),
videoMimeType: this.getDirectVideoMimeType(url),
isAutoplay: autoplay_status,
mute: this.trimIfExists(element.getAttribute('data-mute')),
linkClasses: element.classList,
handleVars: this.defaults.handleVars,
onPageLoad: this.defaults.onPageLoad,
oplCookie: this.defaults.oplCookie
};}
generateEmbed(data, autoplay){
const url=data.url ? data.url.trim():null;
if(!url) return null;
if(this.isYouTube(url)){
return this.createYouTubeEmbed(url, data, autoplay);
}else if(this.isVimeo(url)){
return this.createVimeoEmbed(url, data, autoplay);
}else if(this.isDirectVideo(url)){
return this.createDirectVideoEmbed(url, data, autoplay);
}
return 0;
}
isYouTube(url){
return /youtube\.com|youtu\.be|youtube-nocookie\.com/i.test(url);
}
isVimeo(url){
return /vimeo\.com/i.test(url);
}
isDirectVideo(url){
return /\.(mp4|webm)$/i.test(url);
}
getDirectVideoMimeType(url){
if(/\.mp4$/i.test(url)){
return 'video/mp4';
}
else if(/\.webm$/i.test(url)){
return 'video/webm';
}else{
return null;
}}
detectVideoType(url){
if(this.isYouTube(url)){
return 'vp-video-type-youtube';
}
else if(this.isVimeo(url)){
return 'vp-video-type-vimeo';
}
else if(this.isDirectVideo(url)){
const getVideoMimeType=this.getDirectVideoMimeType(url);
if(getVideoMimeType=='video/mp4'){
return 'vp-video-type-mp4';
}
else if(getVideoMimeType=='video/webm'){
return 'vp-video-type-webm';
}
return null;
}
return false;
}
extractYouTubeId(url){
const match=url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/)|youtu\.be\/|youtube-nocookie\.com\/(?:watch\?v=|embed\/|v\/)|m\.youtube\.com\/watch\?v=)([^&\n?#]+)/);
return match ? match[1]:null;
}
extractVimeoId(url){
const match=url.match(/vimeo\.com\/(?:channels\/[^\/]+\/|video\/)?(\d+)(?:\/|\?|$)/);
return match ? match[1]:null;
}
createYouTubeEmbed(url, data, autoplay){
if(!url) return null;
url=url.trim();
const videoId=this.extractYouTubeId(url);
if(!videoId) return false;
const youtubeDomain=data.noCookie===true||data.noCookie==1 ? 'youtube-nocookie.com':'youtube.com';
let embedUrl=`https://www.${youtubeDomain}/embed/${videoId}?`;
embedUrl +=`autoplay=${autoplay ? 1:0}`;
if(data.mute==1) embedUrl +=`&mute=1`;
return `<iframe src="${embedUrl}" frameborder="0" allow="autoplay; fullscreen"></iframe>`;
}
createVimeoEmbed(url, data, autoplay){
if(!url) return null;
url=url.trim();
const videoId=this.extractVimeoId(url);
if(!videoId) return false;
let embedUrl=`https://player.vimeo.com/video/${videoId}?`;
embedUrl +=`autoplay=${autoplay ? 1:0}`;
if(data.mute==1) embedUrl +=`&muted=1`;
if(data.noCookie===true||data.noCookie==1) embedUrl +=`&dnt=1`;
return `<iframe src="${embedUrl}" frameborder="0" allow="autoplay; fullscreen"></iframe>`;
}
createDirectVideoEmbed(url, data, autoplay){
if(!url) return null;
url=url.trim();
if(!this.isDirectVideo(url)) return false;
const autoplayAttr=autoplay ? ' autoplay':'';
const mutedAttr=data.mute ? ' muted':'';
const getVideoMimeType=this.getDirectVideoMimeType(url)||'video/mp4';
return `<video${mutedAttr}${autoplayAttr} controls playsInline controlslist="nodownload" disablePictureInPicture="true">
<source src="${url}" type="${getVideoMimeType}">
Your browser does not support the video tag.
</video>`;
}
deleteCurrentPopup(){
const currentOldPopup=document.querySelector('.YouTubePopUp-Wrap');
if(currentOldPopup){
currentOldPopup.remove();
}
const currentPopup=document.querySelector('.vp-show');
if(currentPopup){
currentPopup.classList.remove('vp-show');
currentPopup.remove();
}}
async createPopup(embedHTML, data){
this.deleteCurrentPopup();
const popup=document.createElement('div');
const modalType=this.defaults.onPageLoad ? 'vp-modal vp-modal_type_onpageload':'vp-modal vp-modal_type_click';
popup.className=modalType;
const videoTypeClass=data.videoType ? ' ' + data.videoType:'';
const iframe=embedHTML ? embedHTML:'';
popup.innerHTML=`
<div class="vp-container${videoTypeClass}">
<div class="vp-video" style="width: 800px; height: 450px;">
<span class="vp-close"></span>
${iframe}
</div>
</div>
`;
const popupContainer=popup.querySelector('.vp-container');
document.body.appendChild(popup);
await new Promise(resolve=> setTimeout(resolve, 30));
this.deleteCurrentPopup();
popup.classList.add('vp-show');
popup.focus();
data['iframe']=iframe ? 'appear':'no iframe';
if(this.defaults.onPageLoad&&data.oplCookie){
const cookieName=data.oplCookie["name"];
const cookieDays=data.oplCookie["days"];
if(cookieName&&cookieDays){
this.setCookie(cookieName, parseInt(cookieDays));
}}
popup.addEventListener('click', async (e)=> {
if(data.wrapClose!=1&&data.wrapClose!==true){
if(popup&&e.target===popup){
await this.closePopup();
}
if(popupContainer&&e.target===popupContainer){
await this.closePopup();
}}
});
popup.querySelector('.vp-close').addEventListener('click', async ()=> {
await this.closePopup();
});
document.addEventListener('keydown', async (e)=> {
const isShowPopup=document.querySelector('.vp-show');
if(e.key==='Escape'&&isShowPopup){
await this.closePopup();
}});
this.debug(data);
}
async closePopup(){
const popup=document.querySelector('.vp-show');
if(popup){
popup.classList.remove('vp-show');
await new Promise(resolve=> setTimeout(resolve, 500));
popup.remove();
}}
debug(data){
if(!this.defaults.handleVars){
console.log("videoPopup.js: General options object not found. Will use default options.");
}
const debugLogTitle=this.defaults.onPageLoad ? 'Video Popup - On Page Load Modal Debug':'Video Popup Modal Debug';
if(this.defaults.debug){
const videoURL=data.url ? data.url.trim():null;
if(!videoURL){
console.log(`===${debugLogTitle} - Start===`);
console.log('   No video URL! Please enter a video URL to display the debug result.');
console.log(`===${debugLogTitle} - End===`);
console.log('');
return;
}
console.log(`===${debugLogTitle} - Start===`);
console.log('Link Properties:');
for (const [key, value] of Object.entries(data)){
if(key==='oplCookie'&&typeof value==='object'&&value!==null){
console.log(`   ${key}: {`);
for (const [cookieKey, cookieValue] of Object.entries(value)){
console.log(`           ${cookieKey}: "${cookieValue}"`);
}
console.log(`       }`);
}else{
console.log(`   ${key}: ${value}`);
}}
console.log('Functions Status:');
console.log('   If YouTube Video:');
const isYouTubeResult=this.isYouTube(videoURL);
console.log(`      isYouTube: ${isYouTubeResult ? 'true':isYouTubeResult}`);
const youtubeVideoId=this.extractYouTubeId(videoURL);
console.log(`      extractYouTubeId: ${youtubeVideoId ? `Works Good - ${youtubeVideoId}`:youtubeVideoId}`);
const youtubeEmbedResult=this.createYouTubeEmbed(videoURL, data, true);
console.log(`      createYouTubeEmbed: ${youtubeEmbedResult ? 'Works Good':youtubeEmbedResult}`);
console.log('   If Vimeo Video:');
const isVimeoResult=this.isVimeo(videoURL);
console.log(`      isVimeo: ${isVimeoResult ? 'true':isVimeoResult}`);
const vimeoVideoId=this.extractVimeoId(videoURL);
console.log(`      extractVimeoId: ${vimeoVideoId ? `Works Good - ${vimeoVideoId}`:vimeoVideoId}`);
const vimeoEmbedResult=this.createVimeoEmbed(videoURL, data, true);
console.log(`      createVimeoEmbed: ${vimeoEmbedResult ? 'Works Good':vimeoEmbedResult}`);
console.log('   If Direct Video:');
const isDirectVideoResult=this.isDirectVideo(videoURL);
console.log(`      isDirectVideo: ${isDirectVideoResult ? 'true':isDirectVideoResult}`);
const directEmbedResult=this.createDirectVideoEmbed(videoURL, data, true);
console.log(`      createDirectVideoEmbed: ${directEmbedResult ? 'Works Good':directEmbedResult}`);
const generateEmbedResult=this.generateEmbed(data, true);
console.log(`   generateEmbed: ${generateEmbedResult ? 'Works Good':generateEmbedResult}`);
console.log(`===${debugLogTitle} - End===`);
console.log('');
}}
}
class VideoPopupOnPageLoad extends VideoPopup {
constructor(options={}){
super(options);
}
init(){}
async closePopup(){
await super.closePopup();
delete this;
}}
document.addEventListener('DOMContentLoaded', ()=> {
if(typeof theVideoPopupGeneralOptions==='undefined'){
new VideoPopup( { handleVars: false });
return;
}
new VideoPopup({
autoplay: true,
onPageLoad: false,
oplCookie: false,
wrapClose: theVideoPopupGeneralOptions.wrap_close,
noCookie: theVideoPopupGeneralOptions.no_cookie,
handleVars: true,
debug: theVideoPopupGeneralOptions.debug
});
});