PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.11
Yatra – Travel Booking & Tour Operator Software v3.0.11
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
yatra / assets / js / video-player.js

video-player.js in Yatra – Travel Booking & Tour Operator Software 3.0.11, at assets/js/video-player.js

208 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Yatra Video Player Module
3 * Reusable video player for YouTube and other video sources
4 *
5 * @package Yatra
6 * @version 1.0.0
7 */
8
9 (function() {
10 'use strict';
11
12 // Translation helper. Same shim as tour-viewer.js — resolves
13 // through wp.i18n when available, falls back to identity otherwise.
14 // Call sites must pass `'yatra'` so wp i18n make-pot --domain=yatra
15 // picks them up (see tour-viewer.js for the full rationale).
16 var __ = (window.wp && window.wp.i18n && window.wp.i18n.__)
17 ? function (text, domain) { return window.wp.i18n.__(text, domain || 'yatra'); }
18 : function (text) { return text; };
19
20 class YatraVideoPlayer {
21 constructor() {
22 this.modal = null;
23 this.iframe = null;
24 this.currentVideo = null;
25 this.init();
26 }
27
28 init() {
29 this.createModal();
30 this.attachEventListeners();
31 }
32
33 createModal() {
34 // Check if modal already exists
35 if (document.getElementById('yatra-video-player-modal')) {
36 this.modal = document.getElementById('yatra-video-player-modal');
37 this.iframe = document.getElementById('yatra-video-player-iframe');
38 return;
39 }
40
41 // Pre-compute the translated label OUT of the template literal
42 // so makepot extracts it reliably (see tour-viewer.js note).
43 var closeVideoLabel = __('Close Video', 'yatra');
44
45 // Create modal HTML
46 const modalHTML = `
47 <div id="yatra-video-player-modal" class="yatra-video-player-modal" style="display: none;">
48 <div class="yatra-video-player-overlay"></div>
49 <div class="yatra-video-player-content">
50 <button type="button" class="yatra-video-player-close" aria-label="${closeVideoLabel}">
51 <svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
52 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
53 </svg>
54 </button>
55 <div class="yatra-video-player-wrapper">
56 <iframe id="yatra-video-player-iframe"
57 width="100%"
58 height="100%"
59 frameborder="0"
60 allowfullscreen
61 allow="autoplay; encrypted-media; picture-in-picture">
62 </iframe>
63 </div>
64 </div>
65 </div>
66 `;
67
68 // Append to body
69 document.body.insertAdjacentHTML('beforeend', modalHTML);
70
71 this.modal = document.getElementById('yatra-video-player-modal');
72 this.iframe = document.getElementById('yatra-video-player-iframe');
73 }
74
75 attachEventListeners() {
76 // Close button
77 const closeBtn = this.modal.querySelector('.yatra-video-player-close');
78 if (closeBtn) {
79 closeBtn.addEventListener('click', () => this.close());
80 }
81
82 // Overlay click to close
83 const overlay = this.modal.querySelector('.yatra-video-player-overlay');
84 if (overlay) {
85 overlay.addEventListener('click', () => this.close());
86 }
87
88 // ESC key to close
89 document.addEventListener('keydown', (e) => {
90 if (e.key === 'Escape' && this.modal.style.display === 'flex') {
91 this.close();
92 }
93 });
94 }
95
96 /**
97 * Play a video
98 * @param {Object} video - Video object with url, embed_url, video_id, title
99 */
100 play(video) {
101 if (!video || !video.url) {
102 console.error('YatraVideoPlayer: Invalid video object');
103 return;
104 }
105
106
107 this.currentVideo = video;
108
109 // Determine the embed URL
110 let embedUrl = '';
111
112 if (video.embed_url) {
113 // Use provided embed URL
114 embedUrl = video.embed_url;
115 } else if (video.video_id) {
116 // YouTube video ID provided
117 embedUrl = `https://www.youtube.com/embed/${video.video_id}?autoplay=1&rel=0`;
118 } else if (video.url.includes('youtube.com') || video.url.includes('youtu.be')) {
119 // Extract YouTube video ID from URL
120 const videoId = this.extractYoutubeVideoId(video.url);
121 if (videoId) {
122 embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1&rel=0`;
123 }
124 } else if (video.url.includes('vimeo.com')) {
125 // Vimeo video
126 const vimeoId = video.url.split('/').pop();
127 embedUrl = `https://player.vimeo.com/video/${vimeoId}?autoplay=1`;
128 } else {
129 // Direct video URL
130 embedUrl = video.url;
131 }
132
133
134
135
136
137 // Add load event handlers for debugging
138 this.iframe.onload = () => {
139
140 };
141
142 this.iframe.onerror = (error) => {
143 console.error('YouTube iframe failed to load:', error);
144 };
145
146 // Set iframe source
147
148 this.iframe.src = embedUrl;
149
150 // Verify iframe src was set
151 setTimeout(() => {
152
153
154 }, 100);
155
156 // Show modal
157 this.open();
158 }
159
160 /**
161 * Extract YouTube video ID from various URL formats
162 * @param {string} url - YouTube URL
163 * @returns {string|null} Video ID or null
164 */
165 extractYoutubeVideoId(url) {
166 const patterns = [
167 /youtube\.com\/watch\?v=([^&]+)/,
168 /youtube\.com\/embed\/([^?]+)/,
169 /youtu\.be\/([^?]+)/,
170 /youtube\.com\/v\/([^?]+)/
171 ];
172
173 for (const pattern of patterns) {
174 const match = url.match(pattern);
175 if (match) {
176 return match[1];
177 }
178 }
179
180 return null;
181 }
182
183 open() {
184
185
186 this.modal.style.display = 'flex';
187 document.body.style.overflow = 'hidden';
188
189 }
190
191 close() {
192 this.modal.style.display = 'none';
193 document.body.style.overflow = '';
194
195 // Stop video playback by clearing iframe src
196 this.iframe.src = '';
197 this.currentVideo = null;
198 }
199 }
200
201 // Create global instance
202 window.YatraVideoPlayer = new YatraVideoPlayer();
203
204 // Log successful initialization
205
206
207 })();
208