| @@ -8,8 +8,21 @@ | ||
| 8 | 8 | |
| 9 | 9 | (function() { |
| 10 | 10 | 'use strict'; |
| 11 | 11 | |
| 12 | + // Translation helper. Resolves through wp.i18n.__() when wp-i18n is | |
| 13 | + // enqueued (FrontendAssetsProvider registers it as a dependency for | |
| 14 | + // this script); falls back to identity so the page never breaks | |
| 15 | + // when the i18n runtime is unavailable on older builds. | |
| 16 | + // | |
| 17 | + // IMPORTANT — call sites MUST pass `'yatra'` as the second arg even | |
| 18 | + // though the shim ignores it. `wp i18n make-pot --domain=yatra` | |
| 19 | + // filters extraction to calls whose LITERAL second argument is the | |
| 20 | + // domain, so a bare `__('x')` is silently dropped from the .pot. | |
| 21 | + var __ = (window.wp && window.wp.i18n && window.wp.i18n.__) | |
| 22 | + ? function (text, domain) { return window.wp.i18n.__(text, domain || 'yatra'); } | |
| 23 | + : function (text) { return text; }; | |
| 24 | + | |
| 12 | 25 | class YatraTourViewer { |
| 13 | 26 | constructor() { |
| 14 | 27 | this.modal = null; |
| 15 | 28 | this.iframe = null; |
| @@ -17,8 +30,23 @@ | ||
| 17 | 30 | this.init(); |
| 18 | 31 | } |
| 19 | 32 | |
| 20 | 33 | init() { |
| 34 | + // Nothing is built here on purpose. The modal markup (and its | |
| 35 | + // empty <h3 class="yatra-tour-viewer-title">) used to be injected | |
| 36 | + // into <body> as soon as this script loaded — on every page, | |
| 37 | + // including ones with no 360° tour. It is now created on the | |
| 38 | + // first view() call, so pages that never open a tour never get | |
| 39 | + // the extra DOM. | |
| 40 | + } | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * Build the modal once, on first use. | |
| 44 | + */ | |
| 45 | + ensureModal() { | |
| 46 | + if (this.modal) { | |
| 47 | + return; | |
| 48 | + } | |
| 21 | 49 | this.createModal(); |
| 22 | 50 | this.attachEventListeners(); |
| 23 | 51 | } |
| 24 | 52 | |
| @@ -29,14 +57,21 @@ | ||
| 29 | 57 | this.iframe = document.getElementById('yatra-tour-viewer-iframe'); |
| 30 | 58 | return; |
| 31 | 59 | } |
| 32 | 60 | |
| 61 | + // Pre-compute translated labels OUT of the template literal so | |
| 62 | + // makepot extracts them reliably. `wp i18n make-pot` doesn't | |
| 63 | + // always traverse into `${ }` interpolations; calls at top- | |
| 64 | + // level statements are always picked up. | |
| 65 | + var closeTourLabel = __('Close Tour', 'yatra'); | |
| 66 | + var fullscreenLabel = __('Fullscreen', 'yatra'); | |
| 67 | + | |
| 33 | 68 | // Create modal HTML |
| 34 | 69 | const modalHTML = ` |
| 35 | 70 | <div id="yatra-tour-viewer-modal" class="yatra-tour-viewer-modal" style="display: none;"> |
| 36 | 71 | <div class="yatra-tour-viewer-overlay"></div> |
| 37 | 72 | <div class="yatra-tour-viewer-content"> |
| 38 | - <button type="button" class="yatra-tour-viewer-close" aria-label="Close Tour"> | |
| 73 | + <button type="button" class="yatra-tour-viewer-close" aria-label="${closeTourLabel}"> | |
| 39 | 74 | <svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 40 | 75 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> |
| 41 | 76 | </svg> |
| 42 | 77 | </button> |
| @@ -42,9 +77,9 @@ | ||
| 42 | 77 | </button> |
| 43 | 78 | <div class="yatra-tour-viewer-header"> |
| 44 | 79 | <h3 class="yatra-tour-viewer-title"></h3> |
| 45 | 80 | <div class="yatra-tour-viewer-controls"> |
| 46 | - <button type="button" class="yatra-tour-viewer-fullscreen" aria-label="Fullscreen"> | |
| 81 | + <button type="button" class="yatra-tour-viewer-fullscreen" aria-label="${fullscreenLabel}"> | |
| 47 | 82 | <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 48 | 83 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"/> |
| 49 | 84 | </svg> |
| 50 | 85 | </button> |
| @@ -107,13 +142,14 @@ | ||
| 107 | 142 | return; |
| 108 | 143 | } |
| 109 | 144 | |
| 110 | 145 | this.currentTour = tour; |
| 146 | + this.ensureModal(); | |
| 111 | 147 | |
| 112 | 148 | // Set title |
| 113 | 149 | const titleElement = this.modal.querySelector('.yatra-tour-viewer-title'); |
| 114 | 150 | if (titleElement) { |
| 115 | - titleElement.textContent = tour.title || '360° Virtual Tour'; | |
| 151 | + titleElement.textContent = tour.title || __('360° Virtual Tour', 'yatra'); | |
| 116 | 152 | } |
| 117 | 153 | |
| 118 | 154 | // Set iframe source |
| 119 | 155 | this.iframe.src = tour.url; |
| @@ -127,8 +163,11 @@ | ||
| 127 | 163 | document.body.style.overflow = 'hidden'; |
| 128 | 164 | } |
| 129 | 165 | |
| 130 | 166 | close() { |
| 167 | + if (!this.modal) { | |
| 168 | + return; // never opened on this page | |
| 169 | + } | |
| 131 | 170 | this.modal.style.display = 'none'; |
| 132 | 171 | document.body.style.overflow = ''; |
| 133 | 172 | |
| 134 | 173 | // Stop tour by clearing iframe src |
| @@ -141,8 +180,11 @@ | ||
| 141 | 180 | } |
| 142 | 181 | } |
| 143 | 182 | |
| 144 | 183 | toggleFullscreen() { |
| 184 | + if (!this.modal) { | |
| 185 | + return; | |
| 186 | + } | |
| 145 | 187 | const wrapper = this.modal.querySelector('.yatra-tour-viewer-wrapper'); |
| 146 | 188 | |
| 147 | 189 | if (!document.fullscreenElement) { |
| 148 | 190 | if (wrapper.requestFullscreen) { |