| @@ -8,8 +8,16 @@ | ||
| 8 | 8 | |
| 9 | 9 | (function() { |
| 10 | 10 | 'use strict'; |
| 11 | 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 | + | |
| 12 | 20 | class YatraVideoPlayer { |
| 13 | 21 | constructor() { |
| 14 | 22 | this.modal = null; |
| 15 | 23 | this.iframe = null; |
| @@ -17,8 +25,22 @@ | ||
| 17 | 25 | this.init(); |
| 18 | 26 | } |
| 19 | 27 | |
| 20 | 28 | init() { |
| 29 | + // Nothing is built here on purpose. The modal markup used to be | |
| 30 | + // injected into <body> as soon as this script loaded — on every | |
| 31 | + // page, including ones with no video. It is now created on the | |
| 32 | + // first play() call, so pages that never play a video never get | |
| 33 | + // the extra DOM. | |
| 34 | + } | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * Build the modal once, on first use. | |
| 38 | + */ | |
| 39 | + ensureModal() { | |
| 40 | + if (this.modal) { | |
| 41 | + return; | |
| 42 | + } | |
| 21 | 43 | this.createModal(); |
| 22 | 44 | this.attachEventListeners(); |
| 23 | 45 | } |
| 24 | 46 | |
| @@ -29,14 +51,18 @@ | ||
| 29 | 51 | this.iframe = document.getElementById('yatra-video-player-iframe'); |
| 30 | 52 | return; |
| 31 | 53 | } |
| 32 | 54 | |
| 55 | + // Pre-compute the translated label OUT of the template literal | |
| 56 | + // so makepot extracts it reliably (see tour-viewer.js note). | |
| 57 | + var closeVideoLabel = __('Close Video', 'yatra'); | |
| 58 | + | |
| 33 | 59 | // Create modal HTML |
| 34 | 60 | const modalHTML = ` |
| 35 | 61 | <div id="yatra-video-player-modal" class="yatra-video-player-modal" style="display: none;"> |
| 36 | 62 | <div class="yatra-video-player-overlay"></div> |
| 37 | 63 | <div class="yatra-video-player-content"> |
| 38 | - <button type="button" class="yatra-video-player-close" aria-label="Close Video"> | |
| 64 | + <button type="button" class="yatra-video-player-close" aria-label="${closeVideoLabel}"> | |
| 39 | 65 | <svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 40 | 66 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> |
| 41 | 67 | </svg> |
| 42 | 68 | </button> |
| @@ -92,8 +118,9 @@ | ||
| 92 | 118 | } |
| 93 | 119 | |
| 94 | 120 | |
| 95 | 121 | this.currentVideo = video; |
| 122 | + this.ensureModal(); | |
| 96 | 123 | |
| 97 | 124 | // Determine the embed URL |
| 98 | 125 | let embedUrl = ''; |
| 99 | 126 | |
| @@ -154,9 +181,10 @@ | ||
| 154 | 181 | const patterns = [ |
| 155 | 182 | /youtube\.com\/watch\?v=([^&]+)/, |
| 156 | 183 | /youtube\.com\/embed\/([^?]+)/, |
| 157 | 184 | /youtu\.be\/([^?]+)/, |
| 158 | - /youtube\.com\/v\/([^?]+)/ | |
| 185 | + /youtube\.com\/v\/([^?]+)/, | |
| 186 | + /youtube\.com\/shorts\/([^?&]+)/ | |
| 159 | 187 | ]; |
| 160 | 188 | |
| 161 | 189 | for (const pattern of patterns) { |
| 162 | 190 | const match = url.match(pattern); |
| @@ -176,8 +204,11 @@ | ||
| 176 | 204 | |
| 177 | 205 | } |
| 178 | 206 | |
| 179 | 207 | close() { |
| 208 | + if (!this.modal) { | |
| 209 | + return; // never opened on this page | |
| 210 | + } | |
| 180 | 211 | this.modal.style.display = 'none'; |
| 181 | 212 | document.body.style.overflow = ''; |
| 182 | 213 | |
| 183 | 214 | // Stop video playback by clearing iframe src |