1/** 2 * NextGEN Gallery - Custom Lightbox TikTok & Video Support 3 * 4 * This script provides TikTok and video playback support for custom lightboxes. 5 * It intercepts clicks on TikTok/video images and displays content in a simple overlay 6 * that works alongside any custom lightbox library. 7 */ 8(function($) { 9 "use strict"; 10 11 var DEBUG = false; 12 var initialized = false; 13 14 var log = function() { 15 if (DEBUG && window.console) { 16 console.log.apply(console, ['[NGG Custom Lightbox TikTok]'].concat(Array.prototype.slice.call(arguments))); 17 } 18 }; 19 20 /** 21 * Get TikTok data from anchor element 22 */ 23 var getTikTokData = function($anchor) { 24 var playUrl = $anchor.attr('data-tiktok-play-url'); 25 var shareUrl = $anchor.attr('data-tiktok-share-url'); 26 var embedUrl = $anchor.attr('data-tiktok-embed-url'); 27 28 if (playUrl || shareUrl || embedUrl) { 29 return { 30 playUrl: playUrl || '', 31 shareUrl: shareUrl || '', 32 embedUrl: embedUrl || '' 33 }; 34 } 35 36 // Check window.ngg_tiktok_images 37 var imageId = $anchor.attr('data-image-id'); 38 if (imageId && window.ngg_tiktok_images && window.ngg_tiktok_images[imageId]) { 39 return window.ngg_tiktok_images[imageId]; 40 } 41 42 return null; 43 }; 44 45 /** 46 * Get video URL from anchor element 47 */ 48 var getVideoUrl = function($anchor) { 49 return $anchor.attr('data-video-url') || null; 50 }; 51 52 /** 53 * Get gallery ID from element 54 */ 55 var getGalleryId = function($element) { 56 var $galleryContainer = $element.closest('[data-gallery-id]'); 57 if ($galleryContainer.length) { 58 return $galleryContainer.attr('data-gallery-id') || $galleryContainer.data('gallery-id'); 59 } 60 61 $galleryContainer = $element.closest('.ngg-galleryoverview, .ngg-imagebrowser, .ngg-slideshow'); 62 if ($galleryContainer.length) { 63 return $galleryContainer.attr('data-gallery-id') || 64 $galleryContainer.data('gallery-id') || 65 $galleryContainer.attr('data-nextgen-gallery-id') || 66 $galleryContainer.data('nextgen-gallery-id'); 67 } 68 return null; 69 }; 70 71 /** 72 * Get TikTok settings for gallery 73 */ 74 var getTikTokSettings = function(galleryId) { 75 if (window.NggTikTokVideo && typeof window.NggTikTokVideo.getTikTokSettings === 'function') { 76 return window.NggTikTokVideo.getTikTokSettings(galleryId); 77 } 78 79 if (window.ngg_tiktok_gallery_settings) { 80 if (galleryId && window.ngg_tiktok_gallery_settings['gallery_' + galleryId]) { 81 return window.ngg_tiktok_gallery_settings['gallery_' + galleryId]; 82 } 83 if (window.ngg_tiktok_gallery_settings.global) { 84 return window.ngg_tiktok_gallery_settings.global; 85 } 86 } 87 88 return { link: '0', link_target: '0' }; 89 }; 90 91 /** 92 * Get video settings for gallery 93 */ 94 var getVideoSettings = function(galleryId) { 95 if (!window.ngg_video_gallery_settings) { 96 return { 97 show_video_controls: true, 98 show_play_pause_controls: true, 99 autoplay_videos: false 100 }; 101 } 102 103 var settings = window.ngg_video_gallery_settings; 104 var galleryIdStr = galleryId ? String(galleryId) : null; 105 106 if (galleryIdStr && settings['gallery_' + galleryIdStr]) { 107 return settings['gallery_' + galleryIdStr]; 108 } 109 110 return settings.global || { 111 show_video_controls: true, 112 show_play_pause_controls: true, 113 autoplay_videos: false 114 }; 115 }; 116 117 /** 118 * Create and show the TikTok/Video overlay 119 */ 120 var showOverlay = function(contentElement) { 121 // Remove existing overlay 122 $('#ngg-custom-lightbox-overlay').remove(); 123
124 var $overlay = $('<div id="ngg-custom-lightbox-overlay"></div>').css({ 125 position: 'fixed', 126 top: 0, 127 left: 0, 128 width: '100%', 129 height: '100%', 130 backgroundColor: 'transparent', 131 zIndex: 999999, 132 display: 'flex', 133 alignItems: 'center', 134 justifyContent: 'center', 135 cursor: 'pointer' 136 }); 137 138 var $closeBtn = $('<button type="button" class="ngg-custom-lightbox-close">×</button>').css({ 139 position: 'absolute', 140 top: '20px', 141 right: '20px', 142 background: 'transparent', 143 border: 'none', 144 color: '#fff', 145 fontSize: '40px', 146 cursor: 'pointer', 147 zIndex: 1000000, 148 padding: '10px', 149 lineHeight: 1 150 }); 151 152 var $content = $('<div class="ngg-custom-lightbox-content"></div>').css({ 153 position: 'relative', 154 maxWidth: '90vw', 155 maxHeight: '90vh', 156 display: 'flex', 157 alignItems: 'center', 158 justifyContent: 'center' 159 }); 160 161 $content.append(contentElement); 162 $overlay.append($closeBtn).append($content); 163 164 // Close handlers 165 var closeOverlay = function() { 166 // Stop video/cleanup before removing 167 var $video = $overlay.find('video'); 168 if ($video.length) { 169 $video[0].pause(); 170 $video.attr('src', ''); 171 } 172 var $iframe = $overlay.find('iframe'); 173 if ($iframe.length) { 174 $iframe.attr('src', ''); 175 } 176 $overlay.remove(); 177 }; 178 179 $closeBtn.on('click', function(e) { 180 e.stopPropagation(); 181 closeOverlay(); 182 }); 183 184 $overlay.on('click', function(e) { 185 if (e.target === this) { 186 closeOverlay(); 187 } 188 }); 189 190 $(document).on('keydown.nggCustomLightbox', function(e) { 191 if (e.keyCode === 27) { // ESC 192 closeOverlay(); 193 $(document).off('keydown.nggCustomLightbox'); 194 } 195 }); 196 197 $('body').append($overlay); 198 199 return $overlay; 200 }; 201 202 /** 203 * Handle TikTok content display 204 */ 205 var handleTikTokClick = function($anchor, tiktokData) { 206 log('Handling TikTok click', tiktokData); 207 208 if (!tiktokData.playUrl && !tiktokData.shareUrl) { 209 return false; 210 } 211 212 // Create container for TikTok content
213 var $container = $('<div class="ngg-tiktok-container"></div>').css({ 214 position: 'relative', 215 display: 'flex', 216 alignItems: 'center', 217 justifyContent: 'center' 218 }); 219 220 // Use NextGEN_TikTok helper if available 221 if (window.NextGEN_TikTok && window.NextGEN_TikTok.handle_content) { 222 window.NextGEN_TikTok.handle_content({ 223 playUrl: tiktokData.playUrl, 224 shareUrl: tiktokData.shareUrl, 225 container: $container 226 }); 227 showOverlay($container); 228 return true; 229 } 230 231 // Fallback: create video element directly 232 if (tiktokData.playUrl) { 233 var $video = $('<video></video>').attr({ 234 src: tiktokData.playUrl, 235 controls: true, 236 autoplay: true, 237 playsinline: true, 238 muted: true, 239 loop: true 240 }).css({ 241 maxWidth: '90vw', 242 maxHeight: '90vh', 243 width: 'auto', 244 height: 'auto' 245 }); 246 247 $container.append($video); 248 showOverlay($container); 249 250 // Try to unmute after user interaction 251 $video.on('click', function() { 252 this.muted = false; 253 }); 254 255 return true; 256 } 257 258 return false; 259 }; 260 261 /** 262 * Handle video content display 263 */ 264 var handleVideoClick = function($anchor, videoUrl, galleryId) { 265 log('Handling video click', videoUrl); 266 267 if (!videoUrl) { 268 return false; 269 } 270 271 // Check if NextGEN_Video can handle this platform 272 if (!window.NextGEN_Video || !window.NextGEN_Video.detect_platform(videoUrl)) { 273 return false; 274 } 275 276 var videoSettings = getVideoSettings(galleryId); 277
278 var $container = $('<div class="ngg-video-container"></div>').css({ 279 position: 'relative', 280 display: 'flex', 281 alignItems: 'center', 282 justifyContent: 'center' 283 }); 284 285 if (window.NextGEN_Video.handle_content) { 286 window.NextGEN_Video.handle_content({ 287 videoUrl: videoUrl, 288 container: $container[0], 289 settings: videoSettings, 290 containerClass: 'ngg-video-container', 291 videoClass: 'ngg-video-player', 292 errorClass: 'ngg-video-error' 293 }); 294 showOverlay($container); 295 return true; 296 } 297 298 return false; 299 }; 300 301 /** 302 * Main click handler 303 */ 304 var handleClick = function(e) { 305 var $target = $(e.target); 306 var $anchor = $target.is('a') ? $target : $target.closest('a'); 307 308 if (!$anchor.length) { 309 return; 310 } 311 312 // Check if this is a NextGEN gallery image 313 if (!$anchor.attr('data-image-id')) { 314 return; 315 } 316 317 var tiktokData = getTikTokData($anchor); 318 var videoUrl = getVideoUrl($anchor); 319 var galleryId = getGalleryId($anchor); 320 321 // Handle TikTok 322 if (tiktokData && (tiktokData.playUrl || tiktokData.shareUrl)) { 323 var tiktokSettings = getTikTokSettings(galleryId); 324 var linkSetting = String(tiktokSettings.link || '0'); 325 326 // If link setting is to redirect, don't intercept 327 if (linkSetting === '1' || linkSetting === '2') { 328 return; 329 } 330 331 e.preventDefault(); 332 e.stopPropagation(); 333 e.stopImmediatePropagation(); 334 335 handleTikTokClick($anchor, tiktokData); 336 return; 337 } 338 339 // Handle Video 340 if (videoUrl && window.NextGEN_Video && window.NextGEN_Video.detect_platform(videoUrl)) { 341 e.preventDefault(); 342 e.stopPropagation(); 343 e.stopImmediatePropagation(); 344 345 handleVideoClick($anchor, videoUrl, galleryId); 346 return; 347 } 348 }; 349 350 /** 351 * Initialize the handler 352 */ 353 var init = function() { 354 if (initialized) { 355 return; 356 } 357 initialized = true; 358 359 log('Initializing custom lightbox TikTok/video handler'); 360 361 // Use capture phase to intercept clicks before other lightbox handlers 362 document.addEventListener('click', handleClick, true); 363 }; 364 365 // Initialize on DOM ready 366 $(function() { 367 init(); 368 }); 369 370 // Reinitialize on refreshed event (AJAX navigation) 371 $(window).on('refreshed', function() { 372 log('Refreshed event - reinitializing'); 373 }); 374 375 // Expose API 376 window.NggCustomLightboxTikTok = { 377 showOverlay: showOverlay, 378 handleTikTokClick: handleTikTokClick, 379 handleVideoClick: handleVideoClick 380 }; 381 382})(jQuery); 383
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.