chunks
1 week ago
vendor
8 months ago
admin.build.js
1 week ago
admin.js
3 months ago
analytics-tracker.js
4 weeks ago
analytics.build.js
1 week ago
blocks.build.js
1 week ago
carousel.js
1 year ago
custom-player.build.js
1 week ago
documents-viewer-script.js
3 months ago
ep-pdf-lightbox.js
3 months ago
ep-view-count.js
1 week ago
ep-yt-queue.js
4 weeks ago
feature-notices.js
7 months ago
front.js
4 weeks ago
frontend.build.js
3 months ago
gallery-justify.js
1 week ago
gutneberg-script.js
1 month ago
index.html
7 years ago
initCarousel.js
2 years ago
initplyr.js
1 month ago
instafeed.js
4 weeks ago
instagram-shortcode-generator.js
1 month ago
lazy-load.js
6 months ago
license.js
3 months ago
meetup-timezone.js
3 months ago
onboarding.build.js
1 week ago
pdf-gallery-elementor-editor.js
3 months ago
pdf-gallery.js
3 months ago
preview.js
8 months ago
settings.js
3 months ago
sponsored.js
9 months ago
pdf-gallery.js
747 lines
| 1 | /** |
| 2 | * EmbedPress PDF Gallery - Frontend Script |
| 3 | * |
| 4 | * Handles: |
| 5 | * - PDF.js thumbnail generation (first page render) |
| 6 | * - Carousel layout initialization |
| 7 | * - Popup/lightbox with prev/next navigation |
| 8 | */ |
| 9 | (function () { |
| 10 | 'use strict'; |
| 11 | |
| 12 | // ========================================= |
| 13 | // Module 1: PDF Thumbnail Generator |
| 14 | // ========================================= |
| 15 | var ThumbnailGenerator = { |
| 16 | pdfjsLoaded: false, |
| 17 | pdfjsLoading: false, |
| 18 | loadCallbacks: [], |
| 19 | |
| 20 | /** |
| 21 | * Load PDF.js library dynamically |
| 22 | */ |
| 23 | loadPdfJs: function (callback) { |
| 24 | if (this.pdfjsLoaded && window.pdfjsLib) { |
| 25 | callback(); |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | this.loadCallbacks.push(callback); |
| 30 | |
| 31 | if (this.pdfjsLoading) return; |
| 32 | this.pdfjsLoading = true; |
| 33 | |
| 34 | var self = this; |
| 35 | var scriptUrl = (typeof embedpressObj !== 'undefined' && embedpressObj.pluginUrl) |
| 36 | ? embedpressObj.pluginUrl + 'assets/pdf/build/script.js' |
| 37 | : null; |
| 38 | |
| 39 | if (!scriptUrl) { |
| 40 | // Try to find from existing script tags |
| 41 | var scripts = document.querySelectorAll('script[src*="embedpress"]'); |
| 42 | for (var i = 0; i < scripts.length; i++) { |
| 43 | var match = scripts[i].src.match(/(.*embedpress[^/]*\/(?:assets|static)\/)/); |
| 44 | if (match) { |
| 45 | scriptUrl = match[1] + 'pdf/build/script.js'; |
| 46 | break; |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | if (!scriptUrl) { |
| 52 | self.pdfjsLoading = false; |
| 53 | return; |
| 54 | } |
| 55 | |
| 56 | var script = document.createElement('script'); |
| 57 | script.src = scriptUrl; |
| 58 | script.type = 'module'; |
| 59 | script.onload = function () { |
| 60 | // Module scripts set pdfjsLib on globalThis; wait a tick for execution |
| 61 | setTimeout(function () { |
| 62 | if (window.pdfjsLib || globalThis.pdfjsLib) { |
| 63 | if (!window.pdfjsLib) window.pdfjsLib = globalThis.pdfjsLib; |
| 64 | var workerUrl = scriptUrl.replace('script.js', 'pdf.worker.js'); |
| 65 | window.pdfjsLib.GlobalWorkerOptions.workerSrc = workerUrl; |
| 66 | self.pdfjsLoaded = true; |
| 67 | } |
| 68 | self.pdfjsLoading = false; |
| 69 | self.loadCallbacks.forEach(function (cb) { cb(); }); |
| 70 | self.loadCallbacks = []; |
| 71 | }, 50); |
| 72 | }; |
| 73 | script.onerror = function () { |
| 74 | self.pdfjsLoading = false; |
| 75 | self.loadCallbacks = []; |
| 76 | }; |
| 77 | document.head.appendChild(script); |
| 78 | }, |
| 79 | |
| 80 | /** |
| 81 | * Render first page of a PDF to a canvas |
| 82 | */ |
| 83 | renderThumbnail: function (canvas, pdfUrl) { |
| 84 | if (!window.pdfjsLib) return; |
| 85 | |
| 86 | canvas.setAttribute('data-loading', 'true'); |
| 87 | |
| 88 | var loadingTask = window.pdfjsLib.getDocument(pdfUrl); |
| 89 | loadingTask.promise.then(function (pdf) { |
| 90 | pdf.getPage(1).then(function (page) { |
| 91 | var containerWidth = canvas.parentElement ? canvas.parentElement.offsetWidth : 400; |
| 92 | var dpr = Math.min(window.devicePixelRatio || 1, 2); |
| 93 | var targetWidth = Math.max(containerWidth * dpr, 400); |
| 94 | targetWidth = Math.min(targetWidth, 1200); |
| 95 | var scale = targetWidth / page.getViewport({ scale: 1 }).width; |
| 96 | scale = Math.max(scale, 0.8); |
| 97 | scale = Math.min(scale, 3); |
| 98 | var viewport = page.getViewport({ scale: scale }); |
| 99 | |
| 100 | canvas.width = viewport.width; |
| 101 | canvas.height = viewport.height; |
| 102 | |
| 103 | var ctx = canvas.getContext('2d'); |
| 104 | page.render({ |
| 105 | canvasContext: ctx, |
| 106 | viewport: viewport |
| 107 | }).promise.then(function () { |
| 108 | canvas.removeAttribute('data-loading'); |
| 109 | }); |
| 110 | }); |
| 111 | }).catch(function () { |
| 112 | // Show fallback placeholder |
| 113 | canvas.removeAttribute('data-loading'); |
| 114 | canvas.style.display = 'none'; |
| 115 | var wrap = canvas.parentElement; |
| 116 | if (wrap && !wrap.querySelector('.ep-pdf-gallery__placeholder')) { |
| 117 | var placeholder = document.createElement('div'); |
| 118 | placeholder.className = 'ep-pdf-gallery__placeholder'; |
| 119 | placeholder.innerHTML = '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm-1 2l5 5h-5V4zM6 20V4h5v7h7v9H6z"/></svg>'; |
| 120 | wrap.appendChild(placeholder); |
| 121 | } |
| 122 | }); |
| 123 | }, |
| 124 | |
| 125 | /** |
| 126 | * Initialize all thumbnails with IntersectionObserver |
| 127 | */ |
| 128 | initAll: function () { |
| 129 | var canvases = document.querySelectorAll('.ep-pdf-gallery__canvas[data-pdf-src]'); |
| 130 | if (!canvases.length) return; |
| 131 | |
| 132 | var self = this; |
| 133 | this.loadPdfJs(function () { |
| 134 | if (!window.pdfjsLib) return; |
| 135 | |
| 136 | if ('IntersectionObserver' in window) { |
| 137 | var observer = new IntersectionObserver(function (entries) { |
| 138 | entries.forEach(function (entry) { |
| 139 | if (entry.isIntersecting) { |
| 140 | var c = entry.target; |
| 141 | observer.unobserve(c); |
| 142 | self.renderThumbnail(c, c.dataset.pdfSrc); |
| 143 | } |
| 144 | }); |
| 145 | }, { rootMargin: '200px' }); |
| 146 | |
| 147 | canvases.forEach(function (c) { observer.observe(c); }); |
| 148 | } else { |
| 149 | canvases.forEach(function (c) { |
| 150 | self.renderThumbnail(c, c.dataset.pdfSrc); |
| 151 | }); |
| 152 | } |
| 153 | }); |
| 154 | } |
| 155 | }; |
| 156 | |
| 157 | // ========================================= |
| 158 | // Module 2: Carousel |
| 159 | // ========================================= |
| 160 | var Carousel = { |
| 161 | init: function (gallery) { |
| 162 | var carouselEl = gallery.querySelector('.ep-pdf-gallery__carousel'); |
| 163 | if (!carouselEl) return; |
| 164 | |
| 165 | var track = carouselEl.querySelector('.ep-pdf-gallery__carousel-track'); |
| 166 | var items = carouselEl.querySelectorAll('.ep-pdf-gallery__item'); |
| 167 | var prevBtn = carouselEl.querySelector('.ep-pdf-gallery__carousel-prev'); |
| 168 | var nextBtn = carouselEl.querySelector('.ep-pdf-gallery__carousel-next'); |
| 169 | var dotsContainer = carouselEl.querySelector('.ep-pdf-gallery__carousel-dots'); |
| 170 | |
| 171 | if (!track || !items.length) return; |
| 172 | |
| 173 | var options; |
| 174 | try { |
| 175 | options = JSON.parse(gallery.dataset.carouselOptions || '{}'); |
| 176 | } catch (e) { |
| 177 | options = {}; |
| 178 | } |
| 179 | |
| 180 | var slidesPerView = options.slidesPerView || 3; |
| 181 | var gap = parseInt(gallery.dataset.gap) || 20; |
| 182 | var loop = options.loop !== false; |
| 183 | var autoplay = options.autoplay || false; |
| 184 | var autoplaySpeed = options.autoplaySpeed || 3000; |
| 185 | var showDots = options.dots || false; |
| 186 | var currentIndex = 0; |
| 187 | var totalSlides = items.length; |
| 188 | var autoplayTimer = null; |
| 189 | |
| 190 | // Responsive slides per view |
| 191 | function getSlidesPerView() { |
| 192 | var w = window.innerWidth; |
| 193 | if (w <= 767) return 1; |
| 194 | if (w <= 1024) return Math.min(slidesPerView, 2); |
| 195 | return slidesPerView; |
| 196 | } |
| 197 | |
| 198 | function updateLayout() { |
| 199 | var spv = getSlidesPerView(); |
| 200 | var containerWidth = carouselEl.offsetWidth; |
| 201 | var slideWidth = (containerWidth - gap * (spv - 1)) / spv; |
| 202 | |
| 203 | items.forEach(function (item) { |
| 204 | item.style.width = slideWidth + 'px'; |
| 205 | item.style.marginRight = gap + 'px'; |
| 206 | }); |
| 207 | |
| 208 | // Last item no margin |
| 209 | if (items.length) { |
| 210 | items[items.length - 1].style.marginRight = '0'; |
| 211 | } |
| 212 | |
| 213 | goTo(currentIndex, false); |
| 214 | } |
| 215 | |
| 216 | function goTo(index, animate) { |
| 217 | var spv = getSlidesPerView(); |
| 218 | var maxIndex = Math.max(0, totalSlides - spv); |
| 219 | |
| 220 | if (loop) { |
| 221 | if (index > maxIndex) index = 0; |
| 222 | if (index < 0) index = maxIndex; |
| 223 | } else { |
| 224 | index = Math.max(0, Math.min(index, maxIndex)); |
| 225 | } |
| 226 | |
| 227 | currentIndex = index; |
| 228 | |
| 229 | var containerWidth = carouselEl.offsetWidth; |
| 230 | var slideWidth = (containerWidth - gap * (spv - 1)) / spv; |
| 231 | var offset = index * (slideWidth + gap); |
| 232 | |
| 233 | track.style.transition = animate !== false ? 'transform 0.4s ease' : 'none'; |
| 234 | track.style.transform = 'translateX(-' + offset + 'px)'; |
| 235 | |
| 236 | updateDots(); |
| 237 | updateArrows(); |
| 238 | } |
| 239 | |
| 240 | function updateArrows() { |
| 241 | if (!prevBtn || !nextBtn) return; |
| 242 | if (loop) return; |
| 243 | var spv = getSlidesPerView(); |
| 244 | var maxIndex = Math.max(0, totalSlides - spv); |
| 245 | prevBtn.classList.toggle('ep-hidden', currentIndex <= 0); |
| 246 | nextBtn.classList.toggle('ep-hidden', currentIndex >= maxIndex); |
| 247 | } |
| 248 | |
| 249 | function updateDots() { |
| 250 | if (!dotsContainer || !showDots) return; |
| 251 | var spv = getSlidesPerView(); |
| 252 | var totalDots = Math.max(1, totalSlides - spv + 1); |
| 253 | |
| 254 | dotsContainer.innerHTML = ''; |
| 255 | for (var i = 0; i < totalDots; i++) { |
| 256 | var dot = document.createElement('button'); |
| 257 | dot.className = 'ep-pdf-gallery__carousel-dot' + (i === currentIndex ? ' active' : ''); |
| 258 | dot.setAttribute('aria-label', 'Go to slide ' + (i + 1)); |
| 259 | (function (idx) { |
| 260 | dot.addEventListener('click', function () { goTo(idx, true); }); |
| 261 | })(i); |
| 262 | dotsContainer.appendChild(dot); |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | function startAutoplay() { |
| 267 | if (!autoplay) return; |
| 268 | stopAutoplay(); |
| 269 | autoplayTimer = setInterval(function () { |
| 270 | goTo(currentIndex + 1, true); |
| 271 | }, autoplaySpeed); |
| 272 | } |
| 273 | |
| 274 | function stopAutoplay() { |
| 275 | if (autoplayTimer) { |
| 276 | clearInterval(autoplayTimer); |
| 277 | autoplayTimer = null; |
| 278 | } |
| 279 | } |
| 280 | |
| 281 | // Event listeners |
| 282 | if (prevBtn) { |
| 283 | prevBtn.addEventListener('click', function (e) { |
| 284 | e.stopPropagation(); |
| 285 | goTo(currentIndex - 1, true); |
| 286 | stopAutoplay(); |
| 287 | startAutoplay(); |
| 288 | }); |
| 289 | } |
| 290 | if (nextBtn) { |
| 291 | nextBtn.addEventListener('click', function (e) { |
| 292 | e.stopPropagation(); |
| 293 | goTo(currentIndex + 1, true); |
| 294 | stopAutoplay(); |
| 295 | startAutoplay(); |
| 296 | }); |
| 297 | } |
| 298 | |
| 299 | // Touch/swipe support |
| 300 | var touchStartX = 0; |
| 301 | var touchDiff = 0; |
| 302 | track.addEventListener('touchstart', function (e) { |
| 303 | touchStartX = e.touches[0].clientX; |
| 304 | stopAutoplay(); |
| 305 | }, { passive: true }); |
| 306 | track.addEventListener('touchmove', function (e) { |
| 307 | touchDiff = e.touches[0].clientX - touchStartX; |
| 308 | }, { passive: true }); |
| 309 | track.addEventListener('touchend', function () { |
| 310 | if (Math.abs(touchDiff) > 50) { |
| 311 | if (touchDiff < 0) goTo(currentIndex + 1, true); |
| 312 | else goTo(currentIndex - 1, true); |
| 313 | } |
| 314 | touchDiff = 0; |
| 315 | startAutoplay(); |
| 316 | }); |
| 317 | |
| 318 | // Mouse drag support (desktop swipe) |
| 319 | var mouseDown = false; |
| 320 | var mouseStartX = 0; |
| 321 | var mouseDiff = 0; |
| 322 | track.addEventListener('mousedown', function (e) { |
| 323 | mouseDown = true; |
| 324 | mouseStartX = e.clientX; |
| 325 | mouseDiff = 0; |
| 326 | track.style.cursor = 'grabbing'; |
| 327 | stopAutoplay(); |
| 328 | e.preventDefault(); |
| 329 | }); |
| 330 | track.addEventListener('mousemove', function (e) { |
| 331 | if (!mouseDown) return; |
| 332 | mouseDiff = e.clientX - mouseStartX; |
| 333 | }); |
| 334 | track.addEventListener('mouseup', function () { |
| 335 | if (!mouseDown) return; |
| 336 | mouseDown = false; |
| 337 | track.style.cursor = ''; |
| 338 | if (Math.abs(mouseDiff) > 50) { |
| 339 | if (mouseDiff < 0) goTo(currentIndex + 1, true); |
| 340 | else goTo(currentIndex - 1, true); |
| 341 | } |
| 342 | mouseDiff = 0; |
| 343 | startAutoplay(); |
| 344 | }); |
| 345 | track.addEventListener('mouseleave', function () { |
| 346 | if (!mouseDown) return; |
| 347 | mouseDown = false; |
| 348 | track.style.cursor = ''; |
| 349 | if (Math.abs(mouseDiff) > 50) { |
| 350 | if (mouseDiff < 0) goTo(currentIndex + 1, true); |
| 351 | else goTo(currentIndex - 1, true); |
| 352 | } |
| 353 | mouseDiff = 0; |
| 354 | }); |
| 355 | |
| 356 | window.addEventListener('resize', function () { updateLayout(); }); |
| 357 | |
| 358 | // Init |
| 359 | updateLayout(); |
| 360 | if (showDots) updateDots(); |
| 361 | startAutoplay(); |
| 362 | } |
| 363 | }; |
| 364 | |
| 365 | // ========================================= |
| 366 | // Module 3: Popup Controller |
| 367 | // ========================================= |
| 368 | var Popup = { |
| 369 | popupEl: null, |
| 370 | iframe: null, |
| 371 | counterEl: null, |
| 372 | prevBtn: null, |
| 373 | nextBtn: null, |
| 374 | currentGallery: null, |
| 375 | currentIndex: 0, |
| 376 | isOpen: false, |
| 377 | |
| 378 | init: function () { |
| 379 | this.createPopupElement(); |
| 380 | this.bindEvents(); |
| 381 | }, |
| 382 | |
| 383 | createPopupElement: function () { |
| 384 | if (document.querySelector('.ep-pdf-gallery__popup')) return; |
| 385 | |
| 386 | var popup = document.createElement('div'); |
| 387 | popup.className = 'ep-pdf-gallery__popup'; |
| 388 | popup.innerHTML = |
| 389 | '<div class="ep-pdf-gallery__popup-overlay">' + |
| 390 | '<button class="ep-pdf-gallery__popup-close" aria-label="Close">×</button>' + |
| 391 | '<button class="ep-pdf-gallery__popup-prev" aria-label="Previous PDF">' + |
| 392 | '<svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>' + |
| 393 | '</button>' + |
| 394 | '<button class="ep-pdf-gallery__popup-next" aria-label="Next PDF">' + |
| 395 | '<svg viewBox="0 0 24 24"><path d="M8.59 16.59L10 18l6-6-6-6-1.41 1.41L13.17 12z"/></svg>' + |
| 396 | '</button>' + |
| 397 | '<div class="ep-pdf-gallery__popup-counter"></div>' + |
| 398 | '<div class="ep-pdf-gallery__popup-viewer">' + |
| 399 | '<iframe class="ep-pdf-gallery__popup-iframe" src="" allowfullscreen></iframe>' + |
| 400 | '</div>' + |
| 401 | '</div>'; |
| 402 | |
| 403 | document.body.appendChild(popup); |
| 404 | |
| 405 | this.popupEl = popup; |
| 406 | this.iframe = popup.querySelector('.ep-pdf-gallery__popup-iframe'); |
| 407 | this.counterEl = popup.querySelector('.ep-pdf-gallery__popup-counter'); |
| 408 | this.prevBtn = popup.querySelector('.ep-pdf-gallery__popup-prev'); |
| 409 | this.nextBtn = popup.querySelector('.ep-pdf-gallery__popup-next'); |
| 410 | }, |
| 411 | |
| 412 | bindEvents: function () { |
| 413 | var self = this; |
| 414 | |
| 415 | // Delegate click on gallery items |
| 416 | document.addEventListener('click', function (e) { |
| 417 | var item = e.target.closest('.ep-pdf-gallery__item'); |
| 418 | if (!item) return; |
| 419 | |
| 420 | var gallery = item.closest('.ep-pdf-gallery'); |
| 421 | if (!gallery) return; |
| 422 | |
| 423 | e.preventDefault(); |
| 424 | self.currentGallery = gallery; |
| 425 | self.currentIndex = parseInt(item.dataset.pdfIndex) || 0; |
| 426 | self.open(); |
| 427 | }); |
| 428 | |
| 429 | // Close button |
| 430 | if (this.popupEl) { |
| 431 | this.popupEl.querySelector('.ep-pdf-gallery__popup-close').addEventListener('click', function () { |
| 432 | self.close(); |
| 433 | }); |
| 434 | |
| 435 | // Close on overlay click (not on viewer) |
| 436 | this.popupEl.querySelector('.ep-pdf-gallery__popup-overlay').addEventListener('click', function (e) { |
| 437 | if (e.target === e.currentTarget) { |
| 438 | self.close(); |
| 439 | } |
| 440 | }); |
| 441 | |
| 442 | // Prev/Next |
| 443 | this.prevBtn.addEventListener('click', function (e) { |
| 444 | e.stopPropagation(); |
| 445 | self.prev(); |
| 446 | }); |
| 447 | this.nextBtn.addEventListener('click', function (e) { |
| 448 | e.stopPropagation(); |
| 449 | self.next(); |
| 450 | }); |
| 451 | } |
| 452 | |
| 453 | // Keyboard |
| 454 | document.addEventListener('keydown', function (e) { |
| 455 | if (!self.isOpen) return; |
| 456 | if (e.key === 'Escape') self.close(); |
| 457 | if (e.key === 'ArrowLeft') self.prev(); |
| 458 | if (e.key === 'ArrowRight') self.next(); |
| 459 | }); |
| 460 | }, |
| 461 | |
| 462 | open: function () { |
| 463 | if (!this.currentGallery || !this.popupEl) return; |
| 464 | |
| 465 | var items = this.currentGallery.querySelectorAll('.ep-pdf-gallery__item'); |
| 466 | if (this.currentIndex >= items.length) return; |
| 467 | |
| 468 | var item = items[this.currentIndex]; |
| 469 | var pdfUrl = item.dataset.pdfUrl; |
| 470 | if (!pdfUrl) return; |
| 471 | |
| 472 | var viewerSrc = this.buildViewerUrl(pdfUrl); |
| 473 | this.iframe.src = viewerSrc; |
| 474 | |
| 475 | this.popupEl.classList.add('ep-pdf-gallery__popup--open'); |
| 476 | document.body.style.overflow = 'hidden'; |
| 477 | this.isOpen = true; |
| 478 | |
| 479 | this.updateCounter(items.length); |
| 480 | this.updateNavButtons(items.length); |
| 481 | }, |
| 482 | |
| 483 | close: function () { |
| 484 | if (!this.popupEl) return; |
| 485 | this.popupEl.classList.remove('ep-pdf-gallery__popup--open'); |
| 486 | this.iframe.src = ''; |
| 487 | document.body.style.overflow = ''; |
| 488 | this.isOpen = false; |
| 489 | }, |
| 490 | |
| 491 | prev: function () { |
| 492 | if (this.currentIndex > 0) { |
| 493 | this.currentIndex--; |
| 494 | this.iframe.src = ''; |
| 495 | this.open(); |
| 496 | } |
| 497 | }, |
| 498 | |
| 499 | next: function () { |
| 500 | var items = this.currentGallery ? this.currentGallery.querySelectorAll('.ep-pdf-gallery__item') : []; |
| 501 | if (this.currentIndex < items.length - 1) { |
| 502 | this.currentIndex++; |
| 503 | this.iframe.src = ''; |
| 504 | this.open(); |
| 505 | } |
| 506 | }, |
| 507 | |
| 508 | updateCounter: function (total) { |
| 509 | if (this.counterEl) { |
| 510 | this.counterEl.textContent = (this.currentIndex + 1) + ' / ' + total; |
| 511 | } |
| 512 | }, |
| 513 | |
| 514 | updateNavButtons: function (total) { |
| 515 | if (this.prevBtn) { |
| 516 | this.prevBtn.classList.toggle('ep-hidden', this.currentIndex <= 0); |
| 517 | } |
| 518 | if (this.nextBtn) { |
| 519 | this.nextBtn.classList.toggle('ep-hidden', this.currentIndex >= total - 1); |
| 520 | } |
| 521 | }, |
| 522 | |
| 523 | buildViewerUrl: function (pdfUrl) { |
| 524 | if (!this.currentGallery) return pdfUrl; |
| 525 | |
| 526 | var viewerStyle = this.currentGallery.dataset.viewerStyle || 'modern'; |
| 527 | var viewerParams = this.currentGallery.dataset.viewerParams || ''; |
| 528 | var encodedFile = encodeURIComponent(pdfUrl); |
| 529 | |
| 530 | // Get viewer base URLs from localized data |
| 531 | var pdfRenderer = ''; |
| 532 | var flipbookRenderer = ''; |
| 533 | |
| 534 | if (typeof embedpressObj !== 'undefined') { |
| 535 | pdfRenderer = embedpressObj.pdfRenderer || ''; |
| 536 | flipbookRenderer = embedpressObj.flipbookRenderer || ''; |
| 537 | } |
| 538 | |
| 539 | if (viewerStyle === 'flip-book' && flipbookRenderer) { |
| 540 | return flipbookRenderer + '&file=' + encodedFile + '&key=' + viewerParams; |
| 541 | } else if (pdfRenderer) { |
| 542 | return pdfRenderer + '&file=' + encodedFile + '#key=' + viewerParams; |
| 543 | } |
| 544 | |
| 545 | // Fallback: just open the PDF directly |
| 546 | return pdfUrl; |
| 547 | } |
| 548 | }; |
| 549 | |
| 550 | // ========================================= |
| 551 | // Module 4: Bookshelf — multi-row layout |
| 552 | // ========================================= |
| 553 | var Bookshelf = { |
| 554 | DEFAULT_BOOKS_PER_SHELF: 5, |
| 555 | |
| 556 | _getPerShelf: function (gallery) { |
| 557 | var w = window.innerWidth; |
| 558 | if (w <= 767) { |
| 559 | return parseInt(gallery.dataset.columnsMobile, 10) || 1; |
| 560 | } else if (w <= 1024) { |
| 561 | return parseInt(gallery.dataset.columnsTablet, 10) || 2; |
| 562 | } |
| 563 | return parseInt(gallery.dataset.columns, 10) || this.DEFAULT_BOOKS_PER_SHELF; |
| 564 | }, |
| 565 | |
| 566 | _buildRows: function (gallery, container, items) { |
| 567 | var perShelf = this._getPerShelf(gallery); |
| 568 | |
| 569 | // Store current perShelf to avoid unnecessary rebuilds |
| 570 | if (container._lastPerShelf === perShelf) return; |
| 571 | container._lastPerShelf = perShelf; |
| 572 | |
| 573 | // Clear existing rows |
| 574 | container.innerHTML = ''; |
| 575 | |
| 576 | // Chunk items into rows |
| 577 | for (var i = 0; i < items.length; i += perShelf) { |
| 578 | var row = document.createElement('div'); |
| 579 | row.className = 'ep-pdf-gallery__shelf-row'; |
| 580 | |
| 581 | var chunk = items.slice(i, i + perShelf); |
| 582 | for (var j = 0; j < chunk.length; j++) { |
| 583 | row.appendChild(chunk[j]); |
| 584 | } |
| 585 | |
| 586 | container.appendChild(row); |
| 587 | } |
| 588 | }, |
| 589 | |
| 590 | init: function (gallery) { |
| 591 | var carousel = gallery.querySelector('.ep-pdf-gallery__carousel'); |
| 592 | var container = gallery.querySelector('.ep-pdf-gallery__bookshelf-container'); |
| 593 | var items; |
| 594 | |
| 595 | if (carousel) { |
| 596 | var track = carousel.querySelector('.ep-pdf-gallery__carousel-track'); |
| 597 | if (!track) return; |
| 598 | |
| 599 | items = Array.prototype.slice.call(track.querySelectorAll('.ep-pdf-gallery__item')); |
| 600 | if (!items.length) return; |
| 601 | |
| 602 | // Create bookshelf container replacing carousel |
| 603 | container = document.createElement('div'); |
| 604 | container.className = 'ep-pdf-gallery__bookshelf-container'; |
| 605 | carousel.parentNode.replaceChild(container, carousel); |
| 606 | } else if (container) { |
| 607 | items = Array.prototype.slice.call(container.querySelectorAll('.ep-pdf-gallery__item')); |
| 608 | if (!items.length) return; |
| 609 | } else { |
| 610 | return; |
| 611 | } |
| 612 | |
| 613 | // Store items reference for resize rebuilds |
| 614 | gallery._bookshelfItems = items; |
| 615 | gallery._bookshelfContainer = container; |
| 616 | |
| 617 | var self = this; |
| 618 | self._buildRows(gallery, container, items); |
| 619 | |
| 620 | // Rebuild rows on resize for responsive columns |
| 621 | if (!gallery._bookshelfResizeListener) { |
| 622 | var resizeTimer; |
| 623 | gallery._bookshelfResizeListener = function () { |
| 624 | clearTimeout(resizeTimer); |
| 625 | resizeTimer = setTimeout(function () { |
| 626 | self._buildRows(gallery, gallery._bookshelfContainer, gallery._bookshelfItems); |
| 627 | }, 150); |
| 628 | }; |
| 629 | window.addEventListener('resize', gallery._bookshelfResizeListener); |
| 630 | } |
| 631 | } |
| 632 | }; |
| 633 | |
| 634 | // ========================================= |
| 635 | // Module 5: Initialization |
| 636 | // ========================================= |
| 637 | function initGalleries() { |
| 638 | var galleries = document.querySelectorAll('.ep-pdf-gallery'); |
| 639 | if (!galleries.length) return; |
| 640 | |
| 641 | // Init thumbnails |
| 642 | ThumbnailGenerator.initAll(); |
| 643 | |
| 644 | // Init layouts |
| 645 | galleries.forEach(function (gallery) { |
| 646 | var layout = gallery.dataset.layout; |
| 647 | |
| 648 | // Set CSS custom properties from data attributes |
| 649 | var columns = gallery.dataset.columns || 3; |
| 650 | var columnsTablet = gallery.dataset.columnsTablet || 2; |
| 651 | var columnsMobile = gallery.dataset.columnsMobile || 1; |
| 652 | var gap = gallery.dataset.gap || 20; |
| 653 | var radius = gallery.dataset.borderRadius; |
| 654 | |
| 655 | gallery.style.setProperty('--ep-gallery-columns-desktop', columns); |
| 656 | gallery.style.setProperty('--ep-gallery-columns-tablet', columnsTablet); |
| 657 | gallery.style.setProperty('--ep-gallery-columns-mobile', columnsMobile); |
| 658 | gallery.style.setProperty('--ep-gallery-gap', gap + 'px'); |
| 659 | if (radius !== undefined) { |
| 660 | gallery.style.setProperty('--ep-gallery-radius', radius + 'px'); |
| 661 | } |
| 662 | |
| 663 | if (layout === 'carousel') { |
| 664 | Carousel.init(gallery); |
| 665 | } |
| 666 | if (layout === 'bookshelf') { |
| 667 | Bookshelf.init(gallery); |
| 668 | } |
| 669 | }); |
| 670 | |
| 671 | // Init popup |
| 672 | Popup.init(); |
| 673 | } |
| 674 | |
| 675 | // Run on DOMContentLoaded |
| 676 | if (document.readyState === 'loading') { |
| 677 | document.addEventListener('DOMContentLoaded', initGalleries); |
| 678 | } else { |
| 679 | initGalleries(); |
| 680 | } |
| 681 | |
| 682 | // Elementor editor: re-initialize when widget is rendered/re-rendered |
| 683 | if (typeof jQuery !== 'undefined') { |
| 684 | jQuery(window).on('elementor/frontend/init', function () { |
| 685 | if (typeof elementorFrontend !== 'undefined') { |
| 686 | elementorFrontend.hooks.addAction( |
| 687 | 'frontend/element_ready/embedpress_pdf_gallery.default', |
| 688 | function ($scope) { |
| 689 | var gallery = $scope.find('.ep-pdf-gallery')[0]; |
| 690 | if (!gallery) return; |
| 691 | |
| 692 | // Set CSS custom properties from data attributes |
| 693 | var columns = gallery.dataset.columns || 3; |
| 694 | var columnsTablet = gallery.dataset.columnsTablet || 2; |
| 695 | var columnsMobile = gallery.dataset.columnsMobile || 1; |
| 696 | var gap = gallery.dataset.gap || 20; |
| 697 | var radius = gallery.dataset.borderRadius; |
| 698 | |
| 699 | gallery.style.setProperty('--ep-gallery-columns-desktop', columns); |
| 700 | gallery.style.setProperty('--ep-gallery-columns-tablet', columnsTablet); |
| 701 | gallery.style.setProperty('--ep-gallery-columns-mobile', columnsMobile); |
| 702 | gallery.style.setProperty('--ep-gallery-gap', gap + 'px'); |
| 703 | if (radius !== undefined) { |
| 704 | gallery.style.setProperty('--ep-gallery-radius', radius + 'px'); |
| 705 | } |
| 706 | |
| 707 | // Re-init thumbnails within this widget |
| 708 | var canvases = gallery.querySelectorAll('.ep-pdf-gallery__canvas[data-pdf-src]'); |
| 709 | if (canvases.length) { |
| 710 | ThumbnailGenerator.loadPdfJs(function () { |
| 711 | if (!window.pdfjsLib) return; |
| 712 | canvases.forEach(function (c) { |
| 713 | ThumbnailGenerator.renderThumbnail(c, c.dataset.pdfSrc); |
| 714 | }); |
| 715 | }); |
| 716 | } |
| 717 | |
| 718 | // Re-init carousel or bookshelf |
| 719 | var layout = gallery.dataset.layout; |
| 720 | if (layout === 'carousel') { |
| 721 | Carousel.init(gallery); |
| 722 | } else if (layout === 'bookshelf') { |
| 723 | Bookshelf.init(gallery); |
| 724 | } |
| 725 | |
| 726 | // Ensure popup is initialized |
| 727 | if (!Popup.popupEl) { |
| 728 | Popup.init(); |
| 729 | } |
| 730 | |
| 731 | // If popup is open, update gallery reference and refresh iframe |
| 732 | // so changed viewer controls take effect immediately |
| 733 | if (Popup.isOpen && Popup.currentGallery) { |
| 734 | var oldGalleryId = Popup.currentGallery.dataset.galleryId; |
| 735 | var newGalleryId = gallery.dataset.galleryId; |
| 736 | if (oldGalleryId === newGalleryId) { |
| 737 | Popup.currentGallery = gallery; |
| 738 | Popup.open(); |
| 739 | } |
| 740 | } |
| 741 | } |
| 742 | ); |
| 743 | } |
| 744 | }); |
| 745 | } |
| 746 | })(); |
| 747 |