PageSourceSearch

https://www.centsys.co.za/wp-content/plugins/video-popup/assets/js/videoPopup.js?ver=2.0.4

js centsys.co.za collected 2026-09-24 10:56:13 UTC 20,204 bytes, 577 lines download raw bytes

1/**
2 * Pure JavaScript Video Popup Library - Developed by Alobaidi.
3 * Core library that manages the popup display, video embedding, and all related functionality
4 * 
5 * @author   Alobaidi
6 * @version  2.0.4
7 */
8
9
10/**
11 * Main VideoPopup class
12 * Manages popup creation, video embedding and all popup behaviors
13 */
14class VideoPopup {
15    /**
16     * Initializes plugin with customizable options
17     * @param {Object} options Configuration options
18     */
19    constructor(options = {}) {
20        this.defaults = {
21            autoplay: this.validateBoolean(options.autoplay, true),
22            wrapClose: this.validateBoolean(options.wrapClose, false),
23            noCookie: this.validateBoolean(options.noCookie, false),
24            handleVars: this.validateBoolean(options.handleVars, false),
25            onPageLoad: this.validateBoolean(options.onPageLoad, false),
26            oplCookie: options.oplCookie || false,
27            debug: this.validateBoolean(options.debug, false)
28        };
29        
30        this.init();
31    }
32
33    /**
34     * Initializes event listeners
35     */
36    init() {
37        this.addClickListener();
38    }
39
40    /**
41     * Adds click event listeners to video links
42     */
43    addClickListener() {
44        document.querySelectorAll('a.vp-a, a.vp-s').forEach(link => {
45            link.addEventListener('click', async (e) => {
46
47                if ( link.classList.contains('vp-a') ) {
48                    e.preventDefault();
49                    link.blur();
50                    await this.openPopup(link, true);
51                }
52
53                else if ( link.classList.contains('vp-s') ) {
54                    e.preventDefault();
55                    link.blur();
56                    await this.openPopup(link, false);
57                }
58        
59            });
60        });
61    }
62
63    /**
64     * Validates boolean values with various formats
65     * @param {*} value Value to validate as boolean
66     * @param {boolean} defaultValue Default if invalid
67     * @return {boolean} Normalized boolean value
68     */
69    validateBoolean(value, defaultValue) {
70        if (value === undefined || value === null) return defaultValue;
71        
72        if (value === true || value === false) return value;
73        
74        if (value && typeof value === 'string') {
75            const cleanValue = value.trim().toLowerCase();
76            if (cleanValue === 'true' || cleanValue === '1') return true;
77            if (cleanValue === 'false' || cleanValue === '0') return false;
78        }
79        
80        if (typeof value === 'number') {
81            if (value === 1) return true;
82            if (value === 0) return false;
83        }
84        
85        return defaultValue;
86    }
87
88    /**
89     * Trims string values if they exist
90     * @param {*} value Value to trim if string
91     * @return {*} Trimmed value or original value
92     */
93    trimIfExists(value) {
94        if ( value && (typeof value === 'string' || typeof value === 'number') ) {
95            const trimmed = typeof value === 'string' ? value.trim() : value;
96            return trimmed === '' ? null : trimmed;
97        }
98        return value;
99    }
100
101    /**
102     * Opens popup with video content
103     * @param {HTMLElement} element Link element that was clicked
104     * @param {boolean} autoplay Whether video should autoplay
105     */
106    async openPopup(element, autoplay) {
107        const data = this.extractData(element);
108        const embedHTML = this.generateEmbed(data, autoplay);
109        await this.createPopup(embedHTML, data);
110    }
111
112    /**
113     * Sets cookie with expiration time
114     * @param {string} name Cookie name
115     * @param {number} days Days until expiration
116     */
117    setCookie(name, days) {
118        if ( !name || !days ) return;
119        const expirySec = Math.floor(Date.now() / 1000) + (days * 24 * 60 * 60);
120        const expiryDate = new Date(expirySec * 1000);
121        document.cookie = `${name}=${expirySec};expires=${expiryDate.toUTCString()};path=/`;
122    }
123
124    /**
125     * Checks if cookie exists
126     * @param {string} name Cookie name
127     * @return {boolean} True if cookie exists
128     */
129    getCookie(name) {
130        if ( !name ) return;
131        const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
132        return match ? true : false;
133    }
134
135    /**
136     * Removes cookie if it exists
137     * @param {string} name Cookie name
138     */
139    unsetCookie(name){
140        if ( !name ) return;
141        if ( this.getCookie(name) ) {
142            document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`;
143        }
144    }
145
146    /**
147     * Extracts data attributes and settings from link element
148     * @param {HTMLElement} element Link element
149     * @return {Object} Extracted and validated data
150     */
151    extractData(element) {
152        const url = element.href;
153
154        let autoplay_status;
155        if ( element.classList.contains('vp-a') ) {
156            autoplay_status = 'true (vp-a class)';
157        } else if ( element.classList.contains('vp-s') ) {
158            autoplay_status = 'false (vp-s class)';
159        } else {
160            autoplay_status = 'the link are not contains vp-s or vp-a class!';
161        }
162
163        const noCookie = this.trimIfExists(element.getAttribute('data-cookie'));
164        const wrapClose = this.trimIfExists(element.getAttribute('data-wrap-c'));
165
166        return {
167            url: url,
168            noCookie: this.validateBoolean(noCookie, this.defaults.noCookie),
169            wrapClose: this.validateBoolean(wrapClose, this.defaults.wrapClose),
170
171            videoType: this.detectVideoType(url),
172            videoMimeType: this.getDirectVideoMimeType(url),
173
174            isAutoplay: autoplay_status,
175            mute: this.trimIfExists(element.getAttribute('data-mute')),
176
177            linkClasses: element.classList,
178            handleVars: this.defaults.handleVars,
179            onPageLoad: this.defaults.onPageLoad,
180            oplCookie: this.defaults.oplCookie
181        };
182    }
183
184    /**
185     * Generates appropriate embed code based on URL type
186     * @param {Object} data Video data object
187     * @param {boolean} autoplay Whether video should autoplay
188     * @return {string|number|null} HTML embed code or error indicator
189     */
190    generateEmbed(data, autoplay) {
191        const url = data.url ? data.url.trim() : null;
192        if ( !url ) return null;
193        
194        if (this.isYouTube(url)) {
195            return this.createYouTubeEmbed(url, data, autoplay);
196        } else if (this.isVimeo(url)) {
197            return this.createVimeoEmbed(url, data, autoplay);
198        } else if (this.isDirectVideo(url)) {
199            return this.createDirectVideoEmbed(url, data, autoplay);
200        }
201        
202        return 0;
203    }
204
205    /**
206     * Checks if URL is from YouTube
207     * @param {string} url URL to check
208     * @return {boolean} True if YouTube URL
209     */
210    isYouTube(url) {
211        return /youtube\.com|youtu\.be|youtube-nocookie\.com/i.test(url);
212    }
213
214    /**
215     * Checks if URL is from Vimeo
216     * @param {string} url URL to check
217     * @return {boolean} True if Vimeo URL
218     */
219    isVimeo(url) {
220        return /vimeo\.com/i.test(url);
221    }
222
223    /**
224     * Checks if URL is direct video file
225     * @param {string} url URL to check
226     * @return {boolean} True if direct video file
227     */
228    isDirectVideo(url) {
229        return /\.(mp4|webm)(\?.*)?$/i.test(url);
230    }
231
232    /**
233     * Determines MIME type for direct video files
234     * @param {string} url Video URL
235     * @return {string|null} MIME type or null
236     */
237    getDirectVideoMimeType(url) {
238        if (/\.mp4(\?.*)?$/i.test(url)) {
239            return 'video/mp4';
240        }
241        else if (/\.webm(\?.*)?$/i.test(url)) {
242            return 'video/webm';
243        }
244        else {
245            return null;
246        }
247    }
248
249    /**
250     * Detects video provider type from URL
251     * @param {string} url Video URL
252     * @return {string|boolean} CSS class name for video type or false
253     */
254    detectVideoType(url) {
255        if (this.isYouTube(url)) {
256            return 'vp-video-type-youtube';
257        } 
258
259        else if (this.isVimeo(url)) {
260            return 'vp-video-type-vimeo';
261        } 
262
263        else if (this.isDirectVideo(url)) {
264            const getVideoMimeType = this.getDirectVideoMimeType(url);
265
266            if ( getVideoMimeType == 'video/mp4') {
267                return 'vp-video-type-mp4';
268            }
269            else if ( getVideoMimeType == 'video/webm' ) {
270                return 'vp-video-type-webm';
271            }
272            return null;
273        }
274
275        return false;
276    }
277
278    /**
279     * Extracts YouTube video ID from URL
280     * @param {string} url YouTube URL
281     * @return {string|null} Video ID or null
282     */
283    extractYouTubeId(url) {
284        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?#]+)/);
285        return match ? match[1] : null;
286    }
287
288    /**
289     * Extracts Vimeo video ID from URL
290     * @param {string} url Vimeo URL
291     * @return {string|null} Video ID or null
292     */
293    extractVimeoId(url) {
294        const match = url.match(/vimeo\.com\/(?:channels\/[^\/]+\/|video\/)?(\d+)(?:\/|\?|$)/);
295        return match ? match[1] : null;
296    }
297
298    /**
299     * Creates YouTube embed HTML
300     * @param {string} url YouTube URL
301     * @param {Object} data Video settings
302     * @param {boolean} autoplay Whether video should autoplay
303     * @return {string|boolean|null} Embed HTML or false/null on error
304     */
305    createYouTubeEmbed(url, data, autoplay) {
306        if ( !url ) return null;
307
308        url = url.trim();
309        const videoId = this.extractYouTubeId(url);
310        if ( !videoId ) return false;
311
312        const youtubeDomain = data.noCookie === true || data.noCookie == 1 ? 'youtube-nocookie.com' : 'youtube.com';
313
314        let embedUrl = `https://www.${youtubeDomain}/embed/${videoId}?`;
315
316        embedUrl += `autoplay=${autoplay ? 1 : 0}`;
317
318        if (data.mute == 1) embedUrl += `&mute=1`;
319
320        return `<iframe src="${embedUrl}" frameborder="0" allow="autoplay; fullscreen"></iframe>`;
321    }
322
323    /**
324     * Creates Vimeo embed HTML
325     * @param {string} url Vimeo URL
326     * @param {Object} data Video settings
327     * @param {boolean} autoplay Whether video should autoplay
328     * @return {string|boolean|null} Embed HTML or false/null on error
329     */
330    createVimeoEmbed(url, data, autoplay) {
331        if ( !url ) return null;
332
333        url = url.trim();
334        const videoId = this.extractVimeoId(url);
335        if ( !videoId ) return false;
336
337        let embedUrl = `https://player.vimeo.com/video/${videoId}?`;
338
339        embedUrl += `autoplay=${autoplay ? 1 : 0}`;
340
341        if (data.mute == 1) embedUrl += `&muted=1`;
342        if (data.noCookie === true || data.noCookie == 1) embedUrl += `&dnt=1`;
343
344        return `<iframe src="${embedUrl}" frameborder="0" allow="autoplay; fullscreen"></iframe>`;
345    }
346
347    /**
348     * Creates direct video embed HTML
349     * @param {string} url Direct video URL
350     * @param {Object} data Video settings
351     * @param {boolean} autoplay Whether video should autoplay
352     * @return {string|boolean|null} Embed HTML or false/null on error
353     */
354    createDirectVideoEmbed(url, data, autoplay) {
355        if ( !url ) return null;
356
357        url = url.trim();
358
359        if ( !this.isDirectVideo(url) ) return false;
360
361        const autoplayAttr = autoplay ? ' autoplay' : '';
362        const mutedAttr = data.mute ? ' muted' : '';
363        
364        const getVideoMimeType = this.getDirectVideoMimeType(url) || 'video/mp4';
365        
366        return `<video${mutedAttr}${autoplayAttr}
366 controls playsInline controlslist="nodownload" disablePictureInPicture="true">
367                    <source src="${url}" type="${getVideoMimeType}">
368                    Your browser does not support the video tag.
369                 </video>`;
370    }
371
372    /**
373     * Removes any existing popup from the page
374     */
375    deleteCurrentPopup() {
376        const currentOldPopup = document.querySelector('.YouTubePopUp-Wrap');
377        if ( currentOldPopup ) {
378            currentOldPopup.remove();
379        }
380        
381        const currentPopup = document.querySelector('.vp-show');
382        if ( currentPopup ) {
383            currentPopup.classList.remove('vp-show');
384            currentPopup.remove();
385        }
386    }
387
388    /**
389     * Creates and displays the popup with video content
390     * @param {string} embedHTML HTML for video embed
391     * @param {Object} data Video settings
392     */
393    async createPopup(embedHTML, data) {
394        this.deleteCurrentPopup();
395
396        const popup = document.createElement('div');
397        const modalType = this.defaults.onPageLoad ? 'vp-modal vp-modal_type_onpageload' : 'vp-modal vp-modal_type_click';
398        popup.className = modalType;
399
400        const videoTypeClass = data.videoType ? ' ' + data.videoType : '';
401        const iframe = embedHTML ? embedHTML : '';
402        
403        popup.innerHTML = `
404            <div class="vp-container${videoTypeClass}">
405                <div class="vp-video" style="width: 800px; height: 450px;">
406                    <span class="vp-close"></span>
407                    ${iframe}
408                </div>
409            </div>
410        `;
411
412        const popupContainer = popup.querySelector('.vp-container');
413        document.body.appendChild(popup);
414
415        await new Promise(resolve => setTimeout(resolve, 30));
416        this.deleteCurrentPopup();
417        popup.classList.add('vp-show');
418        popup.focus();
419        data['iframe'] = iframe ? 'appear' : 'no iframe';
420
421        if ( this.defaults.onPageLoad && data.oplCookie ) {
422            const cookieName = data.oplCookie["name"];
423            const cookieDays = data.oplCookie["days"];
424            if ( cookieName && cookieDays ) {
425                this.setCookie(cookieName, parseInt(cookieDays));
426            }
427        }
428        
429        popup.addEventListener('click', async (e) => {
430            if ( data.wrapClose != 1 && data.wrapClose !== true ) {
431                if ( popup && e.target === popup ) {
432                    await this.closePopup();
433                }
434
435                if ( popupContainer && e.target === popupContainer ) {
436                    await this.closePopup();
437                }
438            }
439        });
440        
441        popup.querySelector('.vp-close').addEventListener('click', async () => {
442            await this.closePopup();
443        });
444
445        // Allows closing popup by ESC key
446        document.addEventListener('keydown', async (e) => {
447            const isShowPopup = document.querySelector('.vp-show'); // Current Popup
448            if ( e.key === 'Escape' && isShowPopup ) {
449                await this.closePopup();
450            }
451        });
452
453        this.debug(data);
454    }
455
456    /**
457     * Closes and removes the popup
458     */
459    async closePopup() {
460        const popup = document.querySelector('.vp-show');
461        if (popup) {
462            popup.classList.remove('vp-show');
463            await new Promise(resolve => setTimeout(resolve, 500));
464            popup.remove();
465        }
466    }
467
468    /**
469     * Outputs debug information to console
470     * @param {Object} data Debug data to display
471     */
472    debug(data) {
473        if ( !this.defaults.handleVars ) {
474            console.log("videoPopup.js: General options object not found. Will use default options.");
475        }
476
477        const debugLogTitle = this.defaults.onPageLoad ? 'Video Popup - On Page Load Modal Debug' : 'Video Popup Modal Debug';
478
479        if ( this.defaults.debug ) {
480            const videoURL =  data.url ? data.url.trim() : null;
481            if ( !videoURL ) {
482                console.log(`=== ${debugLogTitle} - Start ===`);
483                console.log('   No video URL! Please enter a video URL to display the debug result.');
484                console.log(`=== ${debugLogTitle} - End ===`);
485                console.log(''); // an empty line
486                return;
487            } 
488
489            console.log(`=== ${debugLogTitle} - Start ===`);
490            
491            console.log('Link Properties:');
492            for (const [key, value] of Object.entries(data)) {
493                if (key === 'oplCookie' && typeof value === 'object' && value !== null) {
494                    console.log(`   ${key}: {`);
495                    for (const [cookieKey, cookieValue] of Object.entries(value)) {
496                        console.log(`           ${cookieKey}: "${cookieValue}"`);
497                    }
498                    console.log(`       }`);
499                } else {
500                    console.log(`   ${key}: ${value}`);
501                }
502            }
503
504            console.log('Functions Status:');
505
506            console.log('   If YouTube Video:');
507                const isYouTubeResult = this.isYouTube(videoURL);
508                console.log(`      isYouTube: ${isYouTubeResult ? 'true' : isYouTubeResult}`);
509                const youtubeVideoId = this.extractYouTubeId(videoURL);
510                console.log(`      extractYouTubeId: ${youtubeVideoId ? `Works Good - ${youtubeVideoId}` : youtubeVideoId}`);
511                const youtubeEmbedResult = this.createYouTubeEmbed(videoURL, data, true);
512                console.log(`      createYouTubeEmbed: ${youtubeEmbedResult ? 'Works Good' : youtubeEmbedResult}`);    
513
514            console.log('   If Vimeo Video:');
515                const isVimeoResult = this.isVimeo(videoURL);
516                console.log(`      isVimeo: ${isVimeoResult ? 'true' : isVimeoResult}`);
517                const vimeoVideoId = this.extractVimeoId(videoURL);
518                console.log(`      extractVimeoId: ${vimeoVideoId ? `Works Good - ${vimeoVideoId}` : vimeoVideoId}`);
519                const vimeoEmbedResult = this.createVimeoEmbed(videoURL, data, true);
520                console.log(`      createVimeoEmbed: ${vimeoEmbedResult ? 'Works Good' : vimeoEmbedResult}`);
521
522            console.log('   If Direct Video:');
523                const isDirectVideoResult = this.isDirectVideo(videoURL);
524                console.log(`      isDirectVideo: ${isDirectVideoResult ? 'true' : isDirectVideoResult}`);
525                const directEmbedResult = this.createDirectVideoEmbed(videoURL, data, true);
526                console.log(`      createDirectVideoEmbed: ${directEmbedResult ? 'Works Good' : directEmbedResult}`);
527
528            const generateEmbedResult = this.generateEmbed(data, true);
529            console.log(`   generateEmbed: ${generateEmbedResult ? 'Works Good' : generateEmbedResult}`);
530
531            console.log(`=== ${debugLogTitle} - End ===`);
532            console.log(''); // an empty line
533        }
534    }
535}
536
537
538/**
539 * VideoPopupOnPageLoad class extends core popup functionality
540 * with specialized behavior for automatic page load display
541 * 
542 * @extends VideoPopup
543 */
544class VideoPopupOnPageLoad extends VideoPopup {
545    constructor(options = {}) {
546        super(options);
547    }
548
549    init(){}
550    
551    async closePopup() {
552        await super.closePopup();
553        delete this;
554    }
555}
556
557
558/**
559 * Auto-initialization when DOM is ready
560 * Creates VideoPopup instance with default or custom settings
561 */
562document.addEventListener('DOMContentLoaded', () => {
563    if ( typeof theVideoPopupGeneralOptions === 'undefined' ) {
564        new VideoPopup( { handleVars: false } );
565        return;
566    }
567
568    new VideoPopup({
569        autoplay: true,
570        onPageLoad: false,
571        oplCookie: false,
572        wrapClose: theVideoPopupGeneralOptions.wrap_close,
573        noCookie: theVideoPopupGeneralOptions.no_cookie,
574        handleVars: true,
575        debug: theVideoPopupGeneralOptions.debug
576    });
vendor: 3 bytes, line 577
577});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.