zoomora 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"zoomora.es.js","sources":["../src/zoomora.js"],"sourcesContent":["/*!\n * Zoomora Lightbox Plugin v1.0.0\n * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features\n *\n * Copyright (c) 2025 Faruk Ahmed (FrontTheme)\n * Licensed under MIT License\n */\n\n// Import styles\nimport './styles/zoomora.scss';\n\n(function (global, factory) {\n 'use strict';\n\n if (typeof module === 'object' && typeof module.exports === 'object') {\n // CommonJS/Node.js\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(factory);\n } else {\n // Browser globals\n global.Zoomora = factory();\n }\n}(typeof window !== 'undefined' ? window : this, function () {\n 'use strict';\n\n /**\n * Zoomora Lightbox Plugin\n * @class\n */\n class Zoomora {\n /**\n * Default configuration options\n * @type {Object}\n */\n static get defaults() {\n return {\n selector: '[data-zoomora]',\n showCounter: true,\n showThumbnails: true,\n showFullscreen: true,\n showZoom: true,\n transition: 'fade', // 'fade' or 'slide'\n useHref: false, // Use href instead of data-src\n maxZoomScale: 3, // Maximum zoom scale\n zoomStep: 0.1, // Zoom step for scroll wheel\n animationDuration: 300, // Animation duration in ms\n onOpen: null, // Callback when lightbox opens\n onClose: null, // Callback when lightbox closes\n onNext: null, // Callback when navigating to next item\n onPrev: null, // Callback when navigating to previous item\n\n // Auto-hide controls\n showAutoHideToggle: true, // Show auto-hide toggle button\n autoHideDelay: 3000, // Delay in ms before hiding controls\n autoHideEnabled: false, // Default state of auto-hide\n };\n }\n\n /**\n * Constructor\n * @param {Object} options - Configuration options\n */\n constructor(options = {}) {\n this.options = {...Zoomora.defaults, ...options};\n this.currentIndex = 0;\n this.items = [];\n this.isZoomed = false;\n this.isFullscreen = false;\n this.isDragging = false;\n this.thumbnailsVisible = true;\n this.startX = 0;\n this.startY = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n this.isInitialized = false;\n this.eventListeners = new Map();\n\n // Auto-hide controls\n this.autoHideEnabled = false;\n this.autoHideTimeout = null;\n this.autoHideDelay = 3000;\n this.isControlsVisible = true;\n this.idleTimer = null;\n\n // Bound methods for event listeners\n this.boundMethods = {\n handleDocumentClick: this.handleDocumentClick.bind(this),\n handleKeydown: this.handleKeydown.bind(this),\n handleFullscreenChange: this.handleFullscreenChange.bind(this),\n handleZoomoraClick: this.handleZoomoraClick.bind(this),\n handleContentClick: this.handleContentClick.bind(this),\n handleMouseDown: this.handleMouseDown.bind(this),\n handleMouseMove: this.handleMouseMove.bind(this),\n handleMouseUp: this.handleMouseUp.bind(this),\n handleTouchStart: this.handleTouchStart.bind(this),\n handleTouchMove: this.handleTouchMove.bind(this),\n handleTouchEnd: this.handleTouchEnd.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Initialize the plugin\n */\n init() {\n if (this.isInitialized) {\n console.warn('Zoomora: Plugin already initialized');\n return;\n }\n\n try {\n this.createLightbox();\n this.bindEvents();\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Zoomora: Initialization failed', error);\n }\n }\n\n /**\n * Static method to bind to anchor tags with href\n * @param {string} selector - CSS selector\n * @param {Object} options - Configuration options\n * @returns {Zoomora} - New Zoomora instance\n */\n static bind(selector, options = {}) {\n const enhancedOptions = {\n ...options,\n selector: selector,\n useHref: true\n };\n return new Zoomora(enhancedOptions);\n }\n\n /**\n * Create lightbox HTML structure\n */\n createLightbox() {\n // Check if lightbox already exists\n if (document.getElementById('zoomoraLightbox')) {\n console.warn('Zoomora: Lightbox already exists in DOM');\n return;\n }\n\n const zoomoraHTML = `\n <div class=\"zoomora\" id=\"zoomoraLightbox\">\n <div class=\"zoomora-container\">\n <div class=\"zoomora-header\" id=\"zoomoraHeader\">\n <div class=\"zoomora-counter\" id=\"zoomoraCounter\">1 / 1</div>\n <div class=\"zoomora-controls\">\n <button class=\"zoomora-btn\" id=\"zoomoraThumbnailBtn\" title=\"Toggle Thumbnails\">\n <i class=\"zoomorai-thumbnails\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraAutoHideBtn\" title=\"Toggle Auto-Hide Controls\">\n <i class=\"zoomorai-controls-off\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraZoomBtn\" title=\"Zoom\">\n <i class=\"zoomorai-zoom\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraFullscreenBtn\" title=\"Fullscreen\">\n <i class=\"zoomorai-expand\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCollapseBtn\" title=\"Exit Fullscreen\" style=\"display: none;\">\n <i class=\"zoomorai-collapse\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCloseBtn\" title=\"Close\">\n <i class=\"zoomorai-close\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"zoomora-content\" id=\"zoomoraContent\">\n <div class=\"zoomora-loading\" id=\"zoomoraLoading\"></div>\n <div class=\"zoomora-slides-container\" id=\"zoomoraSlidesContainer\"></div>\n </div>\n \n <button class=\"zoomora-nav prev\" id=\"zoomoraPrevBtn\">\n <i class=\"zoomorai-arrow-left\"></i>\n </button>\n <button class=\"zoomora-nav next\" id=\"zoomoraNextBtn\">\n <i class=\"zoomorai-arrow-right\"></i>\n </button>\n \n <div class=\"zoomora-caption\" id=\"zoomoraCaption\"></div>\n <div class=\"zoomora-thumbnails\" id=\"zoomoraThumbs\"></div>\n </div>\n </div>\n `;\n\n document.body.insertAdjacentHTML('beforeend', zoomoraHTML);\n\n // Cache DOM elements\n this.zoomora = document.getElementById('zoomoraLightbox');\n this.header = document.getElementById('zoomoraHeader');\n this.content = document.getElementById('zoomoraContent');\n this.slidesContainer = document.getElementById('zoomoraSlidesContainer');\n this.counter = document.getElementById('zoomoraCounter');\n this.thumbs = document.getElementById('zoomoraThumbs');\n this.loading = document.getElementById('zoomoraLoading');\n this.caption = document.getElementById('zoomoraCaption');\n this.prevBtn = document.getElementById('zoomoraPrevBtn');\n this.nextBtn = document.getElementById('zoomoraNextBtn');\n\n // Verify all elements were created\n if (!this.zoomora || !this.content || !this.counter || !this.thumbs || !this.loading || !this.caption) {\n throw new Error('Failed to create required DOM elements');\n }\n }\n\n /**\n * Bind event listeners\n */\n bindEvents() {\n // Document click handler for opening lightbox\n this.addEventListener(document, 'click', this.boundMethods.handleDocumentClick);\n\n // Control button handlers\n this.addEventListener(document.getElementById('zoomoraCloseBtn'), 'click', () => this.close());\n this.addEventListener(document.getElementById('zoomoraPrevBtn'), 'click', () => this.prev());\n this.addEventListener(document.getElementById('zoomoraNextBtn'), 'click', () => this.next());\n this.addEventListener(document.getElementById('zoomoraZoomBtn'), 'click', () => this.toggleZoom());\n this.addEventListener(document.getElementById('zoomoraFullscreenBtn'), 'click', () => this.toggleFullscreen());\n this.addEventListener(document.getElementById('zoomoraCollapseBtn'), 'click', () => this.exitFullscreen());\n this.addEventListener(document.getElementById('zoomoraThumbnailBtn'), 'click', () => this.toggleThumbnails());\n\n // Fullscreen change events\n this.addEventListener(document, 'fullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'webkitfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'mozfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'MSFullscreenChange', this.boundMethods.handleFullscreenChange);\n\n // Keyboard navigation\n this.addEventListener(document, 'keydown', this.boundMethods.handleKeydown);\n\n // Lightbox click to close\n this.addEventListener(this.zoomora, 'click', this.boundMethods.handleZoomoraClick);\n\n // Content click for zoom toggle\n this.addEventListener(this.content, 'click', this.boundMethods.handleContentClick);\n\n // Mouse drag events\n this.addEventListener(this.content, 'mousedown', this.boundMethods.handleMouseDown);\n this.addEventListener(this.content, 'mousemove', this.boundMethods.handleMouseMove);\n this.addEventListener(this.content, 'mouseup', this.boundMethods.handleMouseUp);\n this.addEventListener(this.content, 'mouseleave', this.boundMethods.handleMouseUp);\n\n // Touch events\n this.addEventListener(this.content, 'touchstart', this.boundMethods.handleTouchStart, {passive: false});\n this.addEventListener(this.content, 'touchmove', this.boundMethods.handleTouchMove, {passive: false});\n this.addEventListener(this.content, 'touchend', this.boundMethods.handleTouchEnd);\n\n // Add auto-hide toggle button handler\n this.addEventListener(document.getElementById('zoomoraAutoHideBtn'), 'click', () => this.toggleAutoHide());\n\n // Add mouse/touch activity listeners for auto-hide\n this.addEventListener(this.zoomora, 'mousemove', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'touchstart', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'keydown', () => this.handleUserActivity());\n }\n\n /**\n * Add event listener with cleanup tracking\n * @param {Element} element - DOM element\n * @param {string} event - Event type\n * @param {Function} handler - Event handler\n * @param {Object} options - Event options\n */\n addEventListener(element, event, handler, options = {}) {\n if (!element) return;\n\n element.addEventListener(event, handler, options);\n\n // Track for cleanup\n const key = `${element.constructor.name}_${event}`;\n if (!this.eventListeners.has(key)) {\n this.eventListeners.set(key, []);\n }\n this.eventListeners.get(key).push({element, event, handler, options});\n }\n\n /**\n * Handle document click events\n * @param {Event} e - Click event\n */\n handleDocumentClick(e) {\n const target = e.target.closest(this.options.selector);\n if (target) {\n e.preventDefault();\n this.open(target);\n }\n }\n\n /**\n * Handle keyboard events\n * @param {KeyboardEvent} e - Keyboard event\n */\n handleKeydown(e) {\n if (!this.zoomora.classList.contains('active')) return;\n\n switch (e.key) {\n case 'Escape':\n if (this.isFullscreen) {\n this.exitFullscreen();\n } else {\n this.close();\n }\n break;\n case 'ArrowLeft':\n this.prev();\n break;\n case 'ArrowRight':\n this.next();\n break;\n case 'z':\n case 'Z':\n this.toggleZoom();\n break;\n case 'f':\n case 'F':\n this.toggleFullscreen();\n break;\n case 't':\n case 'T':\n this.toggleThumbnails();\n break;\n }\n }\n\n /**\n * Handle fullscreen change events\n */\n handleFullscreenChange() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (!isInFullscreen && this.isFullscreen) {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n }\n\n /**\n * Handle zoomora container clicks\n * @param {Event} e - Click event\n */\n handleZoomoraClick(e) {\n if (e.target === this.zoomora) {\n this.close();\n }\n }\n\n /**\n * Handle content clicks\n * @param {Event} e - Click event\n */\n handleContentClick(e) {\n const media = e.target.closest('.zoomora-media');\n if (media && !media.classList.contains('no-zoom') && !this.isDragging) {\n this.toggleZoom();\n }\n }\n\n /**\n * Handle mouse down events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseDown(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle mouse move events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle mouse up events\n */\n handleMouseUp() {\n this.endDrag();\n }\n\n /**\n * Handle touch start events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchStart(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle touch move events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle touch end events\n */\n handleTouchEnd() {\n this.endDrag();\n }\n\n /**\n * Get image source from element\n * @param {Element} item - DOM element\n * @returns {string} - Image source URL\n */\n getImageSource(item) {\n const src = item.dataset.src || item.src || item.getAttribute('src');\n const type = item.dataset.type || 'image';\n\n // Handle YouTube URLs for video types\n if (type === 'video' && src) {\n return this.convertToEmbedUrl(src);\n }\n\n return src;\n }\n\n /**\n * Convert YouTube URLs to embed format\n * @param url\n * @returns {*|string}\n */\n convertToEmbedUrl(url) {\n // If already an embed URL, return as is\n if (url.includes('youtube.com/embed/')) {\n return url;\n }\n\n // Handle different YouTube URL formats\n let videoId = null;\n let startTime = null;\n\n // Extract video ID and start time from different YouTube URL formats\n if (url.includes('youtube.com/watch')) {\n const urlParams = new URLSearchParams(url.split('?')[1]);\n videoId = urlParams.get('v');\n const t = urlParams.get('t');\n if (t) {\n // Convert time format (e.g., \"111s\" to seconds)\n startTime = t.replace('s', '');\n }\n } else if (url.includes('youtu.be/')) {\n const parts = url.split('/');\n const videoAndParams = parts[parts.length - 1];\n if (videoAndParams.includes('?')) {\n videoId = videoAndParams.split('?')[0];\n const urlParams = new URLSearchParams(videoAndParams.split('?')[1]);\n const t = urlParams.get('t');\n if (t) startTime = t.replace('s', '');\n } else {\n videoId = videoAndParams;\n }\n }\n\n if (videoId) {\n let embedUrl = `https://www.youtube.com/embed/${videoId}`;\n const params = new URLSearchParams();\n\n if (startTime) {\n params.append('start', startTime);\n }\n\n // Add other useful parameters\n params.append('rel', '0'); // Don't show related videos\n params.append('modestbranding', '1'); // Modest branding\n\n // Option: Add autoplay for YouTube videos (uncomment if desired)\n // params.append('autoplay', '1');\n\n if (params.toString()) {\n embedUrl += '?' + params.toString();\n }\n\n return embedUrl;\n }\n\n // If not a YouTube URL or couldn't parse, return original\n return url;\n }\n\n /**\n * Get thumbnail source from element\n * @param {Element} item - DOM element\n * @returns {string} - Thumbnail source URL\n */\n getThumbnailSource(item) {\n const type = item.dataset.type || 'image';\n\n // For video items, always use the img.src as thumbnail (poster image)\n if (type === 'video') {\n return item.src || item.getAttribute('src');\n }\n\n // For regular images, use data-src or fallback to src\n return item.dataset.src || item.src || item.getAttribute('src');\n }\n\n /**\n * Get group identifier from element\n * @param {Element} element - DOM element\n * @returns {string} - Group identifier\n */\n getGroup(element) {\n if (this.options.useHref) {\n return element.dataset.lightbox || element.dataset.gallery || 'default';\n }\n return element.dataset.zoomora || 'default';\n }\n\n /**\n * Open lightbox with specified element\n * @param {Element} element - DOM element to open\n */\n open(element) {\n if (!element) return;\n\n const group = this.getGroup(element);\n let groupSelector;\n\n if (this.options.useHref) {\n if (element.dataset.lightbox) {\n groupSelector = `[data-lightbox=\"${group}\"]`;\n } else if (element.dataset.gallery) {\n groupSelector = `[data-gallery=\"${group}\"]`;\n } else {\n groupSelector = this.options.selector;\n }\n } else {\n groupSelector = `[data-zoomora=\"${group}\"]`;\n }\n\n this.items = Array.from(document.querySelectorAll(groupSelector));\n this.currentIndex = Math.max(0, this.items.indexOf(element));\n\n // Reset states\n this.isZoomed = false;\n this.isFullscreen = false;\n this.thumbnailsVisible = true;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n this.zoomora.classList.add('active');\n document.body.style.overflow = 'hidden';\n\n this.loadContent();\n this.updateThumbnails();\n this.updateCounter();\n this.updateNavigation();\n this.updateCaption();\n this.updateButtons();\n\n // Initialize auto-hide if enabled\n if (this.autoHideEnabled) {\n this.startAutoHideTimer();\n } else {\n this.showControls();\n }\n\n // Trigger callback\n if (typeof this.options.onOpen === 'function') {\n this.options.onOpen(element, this.currentIndex);\n }\n }\n\n /**\n * Close lightbox\n */\n close() {\n if (this.isFullscreen) {\n this.exitFullscreen();\n }\n\n this.zoomora.classList.remove('active');\n document.body.style.overflow = '';\n this.isZoomed = false;\n this.isFullscreen = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('zoomed');\n media.style.transform = '';\n media.style.cursor = '';\n }\n\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n this.showControls();\n\n // Trigger callback\n if (typeof this.options.onClose === 'function') {\n this.options.onClose(this.currentIndex);\n }\n }\n\n /**\n * Navigate to previous item\n */\n prev() {\n if (this.currentIndex > 0) {\n this.currentIndex--;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onPrev === 'function') {\n this.options.onPrev(this.currentIndex);\n }\n }\n }\n\n /**\n * Navigate to next item\n */\n next() {\n if (this.currentIndex < this.items.length - 1) {\n this.currentIndex++;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onNext === 'function') {\n this.options.onNext(this.currentIndex);\n }\n }\n }\n\n /**\n * Load content for current item\n */\n loadContent() {\n if (!this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const src = this.getImageSource(item);\n const type = item.dataset.type || 'image';\n\n if (!src) {\n console.error('Zoomora: No source found for item');\n return;\n }\n\n // Show loading spinner\n this.loading.style.display = 'block';\n\n // Clear content but keep the loading reference intact\n // Don't replace innerHTML, just clear the slides\n if (this.slidesContainer) {\n this.slidesContainer.innerHTML = '';\n }\n\n // Add slight delay for smooth transition\n setTimeout(() => {\n this.renderContent(src, type, item);\n }, 100);\n }\n\n /**\n * Render content based on type\n * @param {string} src - Source URL\n * @param {string} type - Content type\n * @param {Element} item - Original item element\n */\n renderContent(src, type, item) {\n const slideContainer = document.createElement('div');\n slideContainer.className = 'zoomora-slide-container';\n\n // Create slide wrapper\n const slide = document.createElement('div');\n slide.className = `zoomora-slide ${this.options.transition === 'slide' ? 'slide-effect' : 'fade-effect'}`;\n slide.style.opacity = '0';\n slide.style.transform = this.options.transition === 'slide' ? 'translateX(100%)' : 'scale(0.8)';\n\n let mediaElement;\n\n try {\n switch (type) {\n case 'video':\n if (src.endsWith('.mp4') || src.endsWith('.webm') || src.endsWith('.ogg')) {\n const videoContainer = document.createElement('div');\n videoContainer.className = 'zoomora-video-container';\n\n mediaElement = document.createElement('video');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('preload', 'metadata');\n\n const posterSrc = item.src || item.getAttribute('src');\n if (posterSrc) {\n mediaElement.setAttribute('poster', posterSrc);\n }\n\n const playButton = document.createElement('div');\n playButton.className = 'zoomora-play-button';\n playButton.innerHTML = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\n playButton.addEventListener('click', () => {\n mediaElement.play();\n playButton.style.display = 'none';\n mediaElement.setAttribute('controls', '');\n });\n\n mediaElement.addEventListener('ended', () => {\n playButton.style.display = 'flex';\n });\n\n videoContainer.appendChild(mediaElement);\n videoContainer.appendChild(playButton);\n slideContainer.appendChild(videoContainer);\n } else {\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('allowfullscreen', '');\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n }\n break;\n\n case 'iframe':\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-iframe';\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n break;\n\n default:\n mediaElement = document.createElement('img');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-media';\n mediaElement.alt = item.alt || item.title || '';\n\n mediaElement.onload = () => {\n this.loading.style.display = 'none';\n this.checkZoomability(mediaElement);\n this.animateSlideIn(slide);\n };\n\n mediaElement.onerror = () => {\n this.loading.style.display = 'none';\n console.error('Zoomora: Failed to load image:', src);\n this.animateSlideIn(slide);\n };\n\n slideContainer.appendChild(mediaElement);\n }\n\n slide.appendChild(slideContainer);\n\n // Clear existing slides and add new one\n this.slidesContainer.innerHTML = '';\n this.slidesContainer.appendChild(slide);\n\n if (type !== 'image') {\n this.loading.style.display = 'none';\n this.animateSlideIn(slide);\n }\n\n } catch (error) {\n console.error('Zoomora: Error rendering content:', error);\n this.loading.style.display = 'none';\n }\n }\n\n // Animation helper\n animateSlideIn(slide) {\n // Force reflow\n slide.offsetHeight;\n\n // Add active class and animate\n slide.classList.add('active');\n\n if (this.options.transition === 'slide') {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'translateX(0)';\n slide.style.opacity = '1';\n } else {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'scale(1)';\n slide.style.opacity = '1';\n }\n }\n\n // Toggle auto-hide controls\n toggleAutoHide() {\n this.autoHideEnabled = !this.autoHideEnabled;\n const autoHideBtn = document.getElementById('zoomoraAutoHideBtn');\n\n if (this.autoHideEnabled) {\n autoHideBtn.classList.add('active');\n autoHideBtn.title = 'Disable Auto-Hide Controls';\n this.startAutoHideTimer();\n } else {\n autoHideBtn.classList.remove('active');\n autoHideBtn.title = 'Enable Auto-Hide Controls';\n this.stopAutoHideTimer();\n this.showControls();\n }\n }\n\n // Handle user activity\n handleUserActivity() {\n if (!this.autoHideEnabled) return;\n\n this.showControls();\n this.startAutoHideTimer();\n }\n\n // Start auto-hide timer\n startAutoHideTimer() {\n this.stopAutoHideTimer();\n\n this.autoHideTimeout = setTimeout(() => {\n this.hideControls();\n }, this.options.autoHideDelay);\n }\n\n // Stop auto-hide timer\n stopAutoHideTimer() {\n if (this.autoHideTimeout) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = null;\n }\n }\n\n // Show controls\n showControls() {\n if (this.isControlsVisible) return;\n\n this.isControlsVisible = true;\n this.zoomora.classList.remove('controls-hidden');\n\n // Animate controls back in\n if (this.header) {\n this.header.style.transform = 'translateY(0)';\n this.header.style.opacity = '1';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(0)';\n this.thumbs.style.opacity = '1';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(0)';\n this.prevBtn.style.opacity = '1';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(0)';\n this.nextBtn.style.opacity = '1';\n }\n }\n\n // Hide controls\n hideControls() {\n if (!this.isControlsVisible) return;\n\n this.isControlsVisible = false;\n this.zoomora.classList.add('controls-hidden');\n\n // Animate controls out\n if (this.header) {\n this.header.style.transform = 'translateY(-100%)';\n this.header.style.opacity = '0';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(100%)';\n this.thumbs.style.opacity = '0';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(-100%)';\n this.prevBtn.style.opacity = '0';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(100%)';\n this.nextBtn.style.opacity = '0';\n }\n }\n\n /**\n * Check if image can be zoomed\n * @param {HTMLImageElement} img - Image element\n */\n checkZoomability(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) return;\n\n const imgRect = img.getBoundingClientRect();\n const renderedWidth = imgRect.width;\n const renderedHeight = imgRect.height;\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n const isScaledDown = naturalWidth > renderedWidth || naturalHeight > renderedHeight;\n const zoomRatioX = naturalWidth / renderedWidth;\n const zoomRatioY = naturalHeight / renderedHeight;\n const maxZoomRatio = Math.max(zoomRatioX, zoomRatioY);\n\n // Store zoom info\n img.dataset.zoomRatio = maxZoomRatio;\n img.dataset.naturalWidth = naturalWidth;\n img.dataset.naturalHeight = naturalHeight;\n img.dataset.renderedWidth = renderedWidth;\n img.dataset.renderedHeight = renderedHeight;\n\n // Enable zoom if significantly scaled down\n if (isScaledDown && maxZoomRatio > 1.1) {\n img.classList.remove('no-zoom');\n } else {\n img.classList.add('no-zoom');\n }\n }\n\n /**\n * Update counter display\n */\n updateCounter() {\n if (this.options.showCounter && this.counter) {\n this.counter.textContent = `${this.currentIndex + 1} / ${this.items.length}`;\n }\n }\n\n /**\n * Update caption display\n */\n updateCaption() {\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption) {\n this.caption.textContent = caption;\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n this.caption.style.pointerEvents = 'auto';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n this.caption.style.pointerEvents = 'none';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n }\n }\n\n /**\n * Update thumbnails display\n */\n updateThumbnails() {\n if (!this.options.showThumbnails || !this.thumbs) return;\n\n if (this.items.length === 1) {\n this.caption.classList.add('single-item-thumbnail');\n this.thumbs.style.display = 'none';\n return;\n }\n\n this.caption.classList.remove('single-item-thumbnail');\n\n this.thumbs.style.display = 'flex';\n this.thumbs.innerHTML = '';\n\n this.items.forEach((item, index) => {\n const thumb = document.createElement('div');\n thumb.className = 'zoomora-thumb';\n if (index === this.currentIndex) thumb.classList.add('active');\n\n const img = document.createElement('img');\n const thumbSrc = this.getThumbnailSource(item);\n\n if (thumbSrc) {\n img.src = thumbSrc;\n img.alt = item.alt || item.title || '';\n img.onerror = () => {\n thumb.style.display = 'none';\n };\n }\n\n thumb.appendChild(img);\n\n thumb.addEventListener('click', () => {\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n });\n\n this.thumbs.appendChild(thumb);\n });\n }\n\n /**\n * Update navigation buttons\n */\n updateNavigation() {\n const prevBtn = document.getElementById('zoomoraPrevBtn');\n const nextBtn = document.getElementById('zoomoraNextBtn');\n\n if (prevBtn) {\n prevBtn.style.display = this.currentIndex > 0 ? 'flex' : 'none';\n }\n if (nextBtn) {\n nextBtn.style.display = this.currentIndex < this.items.length - 1 ? 'flex' : 'none';\n }\n }\n\n /**\n * Update control buttons\n */\n updateButtons() {\n const fullscreenBtn = document.getElementById('zoomoraFullscreenBtn');\n const collapseBtn = document.getElementById('zoomoraCollapseBtn');\n\n if (fullscreenBtn && collapseBtn) {\n if (this.isFullscreen) {\n fullscreenBtn.style.display = 'none';\n collapseBtn.style.display = 'flex';\n } else {\n fullscreenBtn.style.display = 'flex';\n collapseBtn.style.display = 'none';\n }\n }\n }\n\n /**\n * Toggle zoom state\n */\n toggleZoom() {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || media.tagName !== 'IMG' || media.classList.contains('no-zoom')) return;\n\n this.isZoomed = !this.isZoomed;\n media.classList.toggle('zoomed', this.isZoomed);\n\n if (this.isZoomed) {\n const zoomRatio = parseFloat(media.dataset.zoomRatio) || 2;\n let zoomScale = Math.min(zoomRatio, this.options.maxZoomScale);\n\n if (zoomRatio > 2.5) {\n zoomScale = Math.min(zoomRatio * 0.7, 2.5);\n }\n\n media.style.transform = `scale(${zoomScale})`;\n media.style.cursor = 'grab';\n media.dataset.currentZoomScale = zoomScale;\n this.currentScale = zoomScale;\n } else {\n media.style.transform = '';\n media.style.cursor = '';\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n }\n }\n\n /**\n * Toggle fullscreen mode\n */\n toggleFullscreen() {\n if (!this.isFullscreen) {\n this.enterFullscreen();\n } else {\n this.exitFullscreen();\n }\n }\n\n /**\n * Enter fullscreen mode\n */\n enterFullscreen() {\n const element = this.zoomora;\n const requestFullscreen = element.requestFullscreen ||\n element.webkitRequestFullscreen ||\n element.mozRequestFullScreen ||\n element.msRequestFullscreen;\n\n if (requestFullscreen) {\n requestFullscreen.call(element).then(() => {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not enter fullscreen:', err);\n this.fallbackFullscreen();\n });\n } else {\n this.fallbackFullscreen();\n }\n }\n\n /**\n * Exit fullscreen mode\n */\n exitFullscreen() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (isInFullscreen) {\n const exitFullscreen = document.exitFullscreen ||\n document.webkitExitFullscreen ||\n document.mozCancelFullScreen ||\n document.msExitFullscreen;\n\n if (exitFullscreen) {\n exitFullscreen.call(document).then(() => {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not exit fullscreen:', err);\n this.fallbackExitFullscreen();\n });\n } else {\n this.fallbackExitFullscreen();\n }\n } else {\n this.fallbackExitFullscreen();\n }\n }\n\n /**\n * Fallback fullscreen using CSS\n */\n fallbackFullscreen() {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Exit CSS fullscreen\n */\n fallbackExitFullscreen() {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Toggle thumbnails visibility\n */\n toggleThumbnails() {\n if (this.items.length === 1) return;\n\n this.thumbnailsVisible = !this.thumbnailsVisible;\n if (this.thumbs) {\n this.thumbs.classList.toggle('thumbs-hidden', !this.thumbnailsVisible);\n\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption && this.thumbs.classList.contains('thumbs-hidden')) {\n this.caption.style.bottom = '20px';\n this.caption.style.transition = 'bottom 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.bottom = '120px';\n }\n }\n }\n\n /**\n * Start drag operation\n * @param {Event} e - Mouse or touch event\n */\n startDrag(e) {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || !this.isZoomed) return;\n\n this.isDragging = true;\n media.style.cursor = 'grabbing';\n\n this.startX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n this.startY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n // Parse current transform\n const transform = media.style.transform;\n const scaleMatch = transform.match(/scale\\(([^)]+)\\)/);\n const translateMatch = transform.match(/translate\\(([^,]+),\\s*([^)]+)\\)/);\n\n this.currentScale = scaleMatch ? parseFloat(scaleMatch[1]) : 1;\n this.currentX = translateMatch ? parseFloat(translateMatch[1]) : 0;\n this.currentY = translateMatch ? parseFloat(translateMatch[2]) : 0;\n\n e.preventDefault();\n }\n\n /**\n * Handle drag movement\n * @param {Event} e - Mouse or touch event\n */\n drag(e) {\n if (!this.isDragging) return;\n\n e.preventDefault();\n const clientX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n const clientY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n const deltaX = clientX - this.startX;\n const deltaY = clientY - this.startY;\n\n const newX = this.currentX + deltaX;\n const newY = this.currentY + deltaY;\n\n const media = this.content.querySelector('.zoomora-media');\n if (!media) return;\n\n const mediaRect = media.getBoundingClientRect();\n const scale = this.currentScale;\n const maxX = (mediaRect.width * (scale - 1)) / 2;\n const maxY = (mediaRect.height * (scale - 1)) / 2;\n\n const constrainedX = Math.max(-maxX, Math.min(maxX, newX));\n const constrainedY = Math.max(-maxY, Math.min(maxY, newY));\n\n media.style.transform = `scale(${scale}) translate(${constrainedX}px, ${constrainedY}px)`;\n }\n\n /**\n * End drag operation\n */\n endDrag() {\n if (!this.isDragging) return;\n\n this.isDragging = false;\n const media = this.content.querySelector('.zoomora-media');\n if (media && this.isZoomed) {\n media.style.cursor = 'grab';\n }\n }\n\n /**\n * Go to specific item by index\n * @param {number} index - Item index\n */\n goTo(index) {\n if (index < 0 || index >= this.items.length) return;\n\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n }\n\n /**\n * Get current item index\n * @returns {number} - Current index\n */\n getCurrentIndex() {\n return this.currentIndex;\n }\n\n /**\n * Get total number of items\n * @returns {number} - Total items\n */\n getTotalItems() {\n return this.items.length;\n }\n\n /**\n * Check if lightbox is open\n * @returns {boolean} - True if open\n */\n isOpen() {\n return this.zoomora && this.zoomora.classList.contains('active');\n }\n\n /**\n * Update options\n * @param {Object} newOptions - New options to merge\n */\n updateOptions(newOptions) {\n this.options = {...this.options, ...newOptions};\n }\n\n /**\n * Refresh the lightbox (re-scan for items)\n */\n refresh() {\n if (this.isOpen()) {\n const currentItem = this.items[this.currentIndex];\n if (currentItem) {\n this.open(currentItem);\n }\n }\n }\n\n /**\n * Destroy the lightbox instance\n */\n destroy() {\n if (!this.isInitialized) return;\n\n // Close if open\n if (this.isOpen()) {\n this.close();\n }\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n\n // Remove all event listeners\n this.eventListeners.forEach((listeners, key) => {\n listeners.forEach(({element, event, handler, options}) => {\n if (element && element.removeEventListener) {\n element.removeEventListener(event, handler, options);\n }\n });\n });\n this.eventListeners.clear();\n\n // Remove DOM elements\n if (this.zoomora && this.zoomora.parentNode) {\n this.zoomora.parentNode.removeChild(this.zoomora);\n }\n\n // Reset properties\n this.isInitialized = false;\n this.items = [];\n this.currentIndex = 0;\n this.zoomora = null;\n this.content = null;\n this.counter = null;\n this.thumbs = null;\n this.loading = null;\n this.caption = null;\n }\n }\n\n // Export the class\n return Zoomora;\n}));"],"names":["this"],"mappings":"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"}
1
+ {"version":3,"file":"zoomora.es.js","sources":["../src/zoomora.js"],"sourcesContent":["/*!\n * Zoomora Lightbox Plugin v1.1.0\n * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features\n *\n * Copyright (c) 2025 Faruk Ahmed (FrontTheme)\n * Licensed under MIT License\n */\n\n// Import styles\nimport './styles/zoomora.scss';\n\n(function (global, factory) {\n 'use strict';\n\n if (typeof module === 'object' && typeof module.exports === 'object') {\n // CommonJS/Node.js\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(factory);\n } else {\n // Browser globals\n global.Zoomora = factory();\n }\n}(typeof window !== 'undefined' ? window : this, function () {\n 'use strict';\n\n /**\n * Zoomora Lightbox Plugin\n * @class\n */\n class Zoomora {\n /**\n * Default configuration options\n * @type {Object}\n */\n static get defaults() {\n return {\n selector: '[data-zoomora]',\n showCounter: true,\n showThumbnails: true,\n showFullscreen: true,\n showZoom: true,\n transition: 'fade', // 'fade' or 'slide'\n useHref: false, // Use href instead of data-src\n maxZoomScale: 3, // Maximum zoom scale\n zoomStep: 0.1, // Zoom step for scroll wheel\n animationDuration: 300, // Animation duration in ms\n onOpen: null, // Callback when lightbox opens\n onClose: null, // Callback when lightbox closes\n onNext: null, // Callback when navigating to next item\n onPrev: null, // Callback when navigating to previous item\n\n // Auto-hide controls\n showAutoHideToggle: true, // Show auto-hide toggle button\n autoHideDelay: 3000, // Delay in ms before hiding controls\n autoHideEnabled: false, // Default state of auto-hide\n };\n }\n\n /**\n * Constructor\n * @param {Object} options - Configuration options\n */\n constructor(options = {}) {\n this.options = {...Zoomora.defaults, ...options};\n this.currentIndex = 0;\n this.items = [];\n this.isZoomed = false;\n this.isFullscreen = false;\n this.isDragging = false;\n this.thumbnailsVisible = true;\n this.startX = 0;\n this.startY = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n this.isInitialized = false;\n this.eventListeners = new Map();\n\n // Auto-hide controls\n this.autoHideEnabled = false;\n this.autoHideTimeout = null;\n this.autoHideDelay = 3000;\n this.isControlsVisible = true;\n this.idleTimer = null;\n\n this.lastDragTime = 0;\n\n // Bound methods for event listeners\n this.boundMethods = {\n handleDocumentClick: this.handleDocumentClick.bind(this),\n handleKeydown: this.handleKeydown.bind(this),\n handleFullscreenChange: this.handleFullscreenChange.bind(this),\n handleZoomoraClick: this.handleZoomoraClick.bind(this),\n handleContentClick: this.handleContentClick.bind(this),\n handleMouseDown: this.handleMouseDown.bind(this),\n handleMouseMove: this.handleMouseMove.bind(this),\n handleMouseUp: this.handleMouseUp.bind(this),\n handleTouchStart: this.handleTouchStart.bind(this),\n handleTouchMove: this.handleTouchMove.bind(this),\n handleTouchEnd: this.handleTouchEnd.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Initialize the plugin\n */\n init() {\n if (this.isInitialized) {\n console.warn('Zoomora: Plugin already initialized');\n return;\n }\n\n try {\n this.createLightbox();\n this.bindEvents();\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Zoomora: Initialization failed', error);\n }\n }\n\n /**\n * Static method to bind to anchor tags with href\n * @param {string} selector - CSS selector\n * @param {Object} options - Configuration options\n * @returns {Zoomora} - New Zoomora instance\n */\n static bind(selector, options = {}) {\n const enhancedOptions = {\n ...options,\n selector: selector,\n useHref: true\n };\n return new Zoomora(enhancedOptions);\n }\n\n /**\n * Create lightbox HTML structure\n */\n createLightbox() {\n // Check if lightbox already exists\n if (document.getElementById('zoomoraLightbox')) {\n console.warn('Zoomora: Lightbox already exists in DOM');\n return;\n }\n\n // Build auto-hide button conditionally\n const autoHideButtonHTML = this.options.showAutoHideToggle ? `\n <button class=\"zoomora-btn\" id=\"zoomoraAutoHideBtn\" title=\"Toggle Auto-Hide Controls\">\n <i class=\"zoomorai-controls-off\"></i>\n </button>\n ` : '';\n\n const zoomoraHTML = `\n <div class=\"zoomora\" id=\"zoomoraLightbox\">\n <div class=\"zoomora-container\">\n <div class=\"zoomora-header\" id=\"zoomoraHeader\">\n <div class=\"zoomora-counter\" id=\"zoomoraCounter\">1 / 1</div>\n <div class=\"zoomora-controls\">\n <button class=\"zoomora-btn\" id=\"zoomoraThumbnailBtn\" title=\"Toggle Thumbnails\">\n <i class=\"zoomorai-thumbnails\"></i>\n </button>\n ${autoHideButtonHTML}\n <button class=\"zoomora-btn\" id=\"zoomoraZoomBtn\" title=\"Zoom\">\n <i class=\"zoomorai-zoom\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraFullscreenBtn\" title=\"Fullscreen\">\n <i class=\"zoomorai-expand\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCollapseBtn\" title=\"Exit Fullscreen\" style=\"display: none;\">\n <i class=\"zoomorai-collapse\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCloseBtn\" title=\"Close\">\n <i class=\"zoomorai-close\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"zoomora-content\" id=\"zoomoraContent\">\n <div class=\"zoomora-loading\" id=\"zoomoraLoading\"></div>\n <div class=\"zoomora-slides-container\" id=\"zoomoraSlidesContainer\"></div>\n </div>\n \n <button class=\"zoomora-nav prev\" id=\"zoomoraPrevBtn\">\n <i class=\"zoomorai-arrow-left\"></i>\n </button>\n <button class=\"zoomora-nav next\" id=\"zoomoraNextBtn\">\n <i class=\"zoomorai-arrow-right\"></i>\n </button>\n \n <div class=\"zoomora-caption\" id=\"zoomoraCaption\"></div>\n <div class=\"zoomora-thumbnails\" id=\"zoomoraThumbs\"></div>\n </div>\n </div>\n `;\n\n document.body.insertAdjacentHTML('beforeend', zoomoraHTML);\n\n // Cache DOM elements\n this.zoomora = document.getElementById('zoomoraLightbox');\n this.header = document.getElementById('zoomoraHeader');\n this.content = document.getElementById('zoomoraContent');\n this.slidesContainer = document.getElementById('zoomoraSlidesContainer');\n this.counter = document.getElementById('zoomoraCounter');\n this.thumbs = document.getElementById('zoomoraThumbs');\n this.loading = document.getElementById('zoomoraLoading');\n this.caption = document.getElementById('zoomoraCaption');\n this.prevBtn = document.getElementById('zoomoraPrevBtn');\n this.nextBtn = document.getElementById('zoomoraNextBtn');\n\n // Verify all elements were created\n if (!this.zoomora || !this.content || !this.counter || !this.thumbs || !this.loading || !this.caption) {\n throw new Error('Failed to create required DOM elements');\n }\n }\n\n /**\n * Bind event listeners\n */\n bindEvents() {\n // Document click handler for opening lightbox\n this.addEventListener(document, 'click', this.boundMethods.handleDocumentClick);\n\n // Control button handlers\n this.addEventListener(document.getElementById('zoomoraCloseBtn'), 'click', () => this.close());\n this.addEventListener(document.getElementById('zoomoraPrevBtn'), 'click', () => this.prev());\n this.addEventListener(document.getElementById('zoomoraNextBtn'), 'click', () => this.next());\n this.addEventListener(document.getElementById('zoomoraZoomBtn'), 'click', () => this.toggleZoom());\n this.addEventListener(document.getElementById('zoomoraFullscreenBtn'), 'click', () => this.toggleFullscreen());\n this.addEventListener(document.getElementById('zoomoraCollapseBtn'), 'click', () => this.exitFullscreen());\n this.addEventListener(document.getElementById('zoomoraThumbnailBtn'), 'click', () => this.toggleThumbnails());\n\n // Fullscreen change events\n this.addEventListener(document, 'fullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'webkitfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'mozfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'MSFullscreenChange', this.boundMethods.handleFullscreenChange);\n\n // Keyboard navigation\n this.addEventListener(document, 'keydown', this.boundMethods.handleKeydown);\n\n // Lightbox click to close\n this.addEventListener(this.zoomora, 'click', this.boundMethods.handleZoomoraClick);\n\n // Content click for zoom toggle\n this.addEventListener(this.content, 'click', this.boundMethods.handleContentClick);\n\n // Mouse drag events\n this.addEventListener(this.content, 'mousedown', this.boundMethods.handleMouseDown);\n this.addEventListener(this.content, 'mousemove', this.boundMethods.handleMouseMove);\n this.addEventListener(this.content, 'mouseup', this.boundMethods.handleMouseUp);\n this.addEventListener(this.content, 'mouseleave', this.boundMethods.handleMouseUp);\n\n // Touch events\n this.addEventListener(this.content, 'touchstart', this.boundMethods.handleTouchStart, {passive: false});\n this.addEventListener(this.content, 'touchmove', this.boundMethods.handleTouchMove, {passive: false});\n this.addEventListener(this.content, 'touchend', this.boundMethods.handleTouchEnd);\n\n // Add auto-hide toggle button handler (only if enabled)\n if (this.options.showAutoHideToggle) {\n this.addEventListener(document.getElementById('zoomoraAutoHideBtn'), 'click', () => this.toggleAutoHide());\n\n // Add mouse/touch activity listeners for auto-hide\n this.addEventListener(this.zoomora, 'mousemove', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'touchstart', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'keydown', () => this.handleUserActivity());\n }\n }\n\n /**\n * Add event listener with cleanup tracking\n * @param {Element} element - DOM element\n * @param {string} event - Event type\n * @param {Function} handler - Event handler\n * @param {Object} options - Event options\n */\n addEventListener(element, event, handler, options = {}) {\n if (!element) return;\n\n element.addEventListener(event, handler, options);\n\n // Track for cleanup\n const key = `${element.constructor.name}_${event}`;\n if (!this.eventListeners.has(key)) {\n this.eventListeners.set(key, []);\n }\n this.eventListeners.get(key).push({element, event, handler, options});\n }\n\n /**\n * Handle document click events\n * @param {Event} e - Click event\n */\n handleDocumentClick(e) {\n const target = e.target.closest(this.options.selector);\n if (target) {\n e.preventDefault();\n this.open(target);\n }\n }\n\n /**\n * Handle keyboard events\n * @param {KeyboardEvent} e - Keyboard event\n */\n handleKeydown(e) {\n if (!this.zoomora.classList.contains('active')) return;\n\n switch (e.key) {\n case 'Escape':\n if (this.isFullscreen) {\n this.exitFullscreen();\n } else {\n this.close();\n }\n break;\n case 'ArrowLeft':\n this.prev();\n break;\n case 'ArrowRight':\n this.next();\n break;\n case 'z':\n case 'Z':\n this.toggleZoom();\n break;\n case 'f':\n case 'F':\n this.toggleFullscreen();\n break;\n case 't':\n case 'T':\n this.toggleThumbnails();\n break;\n }\n }\n\n /**\n * Handle fullscreen change events\n */\n handleFullscreenChange() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (!isInFullscreen && this.isFullscreen) {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n }\n\n /**\n * Handle zoomora container clicks\n * @param {Event} e - Click event\n */\n handleZoomoraClick(e) {\n if (e.target === this.zoomora) {\n this.close();\n }\n }\n\n /**\n * Handle content clicks\n * @param {Event} e - Click event\n */\n handleContentClick(e) {\n // Ignore click if we just finished dragging (within 200ms)\n if (Date.now() - this.lastDragTime < 200) {\n return;\n }\n\n const media = e.target.closest('.zoomora-media');\n if (media && !media.classList.contains('no-zoom')) {\n this.toggleZoom();\n }\n }\n\n /**\n * Handle mouse down events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseDown(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle mouse move events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle mouse up events\n */\n handleMouseUp() {\n this.endDrag();\n }\n\n /**\n * Handle touch start events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchStart(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle touch move events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle touch end events\n */\n handleTouchEnd() {\n this.endDrag();\n }\n\n /**\n * Get image source from element\n * @param {Element} item - DOM element\n * @returns {string} - Image source URL\n */\n getImageSource(item) {\n const src = item.dataset.src || item.src || item.getAttribute('src');\n const type = item.dataset.type || 'image';\n\n // Handle YouTube URLs for video types\n if (type === 'video' && src) {\n return this.convertToEmbedUrl(src);\n }\n\n return src;\n }\n\n /**\n * Convert YouTube URLs to embed format\n * @param url\n * @returns {*|string}\n */\n convertToEmbedUrl(url) {\n // If already an embed URL, return as is\n if (url.includes('youtube.com/embed/')) {\n return url;\n }\n\n // Handle different YouTube URL formats\n let videoId = null;\n let startTime = null;\n\n // Extract video ID and start time from different YouTube URL formats\n if (url.includes('youtube.com/watch')) {\n const urlParams = new URLSearchParams(url.split('?')[1]);\n videoId = urlParams.get('v');\n const t = urlParams.get('t');\n if (t) {\n // Convert time format (e.g., \"111s\" to seconds)\n startTime = t.replace('s', '');\n }\n } else if (url.includes('youtu.be/')) {\n const parts = url.split('/');\n const videoAndParams = parts[parts.length - 1];\n if (videoAndParams.includes('?')) {\n videoId = videoAndParams.split('?')[0];\n const urlParams = new URLSearchParams(videoAndParams.split('?')[1]);\n const t = urlParams.get('t');\n if (t) startTime = t.replace('s', '');\n } else {\n videoId = videoAndParams;\n }\n }\n\n if (videoId) {\n let embedUrl = `https://www.youtube.com/embed/${videoId}`;\n const params = new URLSearchParams();\n\n if (startTime) {\n params.append('start', startTime);\n }\n\n // Add other useful parameters\n params.append('rel', '0'); // Don't show related videos\n params.append('modestbranding', '1'); // Modest branding\n\n // Option: Add autoplay for YouTube videos (uncomment if desired)\n // params.append('autoplay', '1');\n\n if (params.toString()) {\n embedUrl += '?' + params.toString();\n }\n\n return embedUrl;\n }\n\n // If not a YouTube URL or couldn't parse, return original\n return url;\n }\n\n /**\n * Get thumbnail source from element\n * @param {Element} item - DOM element\n * @returns {string} - Thumbnail source URL\n */\n getThumbnailSource(item) {\n const type = item.dataset.type || 'image';\n\n // For video items, always use the img.src as thumbnail (poster image)\n if (type === 'video') {\n return item.src || item.getAttribute('src');\n }\n\n // For regular images, use data-src or fallback to src\n return item.dataset.src || item.src || item.getAttribute('src');\n }\n\n /**\n * Get group identifier from element\n * @param {Element} element - DOM element\n * @returns {string} - Group identifier\n */\n getGroup(element) {\n if (this.options.useHref) {\n return element.dataset.lightbox || element.dataset.gallery || 'default';\n }\n return element.dataset.zoomora || 'default';\n }\n\n /**\n * Open lightbox with specified element\n * @param {Element} element - DOM element to open\n */\n open(element) {\n if (!element) return;\n\n const group = this.getGroup(element);\n let groupSelector;\n\n if (this.options.useHref) {\n if (element.dataset.lightbox) {\n groupSelector = `[data-lightbox=\"${group}\"]`;\n } else if (element.dataset.gallery) {\n groupSelector = `[data-gallery=\"${group}\"]`;\n } else {\n groupSelector = this.options.selector;\n }\n } else {\n groupSelector = `[data-zoomora=\"${group}\"]`;\n }\n\n this.items = Array.from(document.querySelectorAll(groupSelector));\n this.currentIndex = Math.max(0, this.items.indexOf(element));\n\n // Reset states\n this.isZoomed = false;\n this.isFullscreen = false;\n this.thumbnailsVisible = true;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n this.zoomora.classList.add('active');\n document.body.style.overflow = 'hidden';\n\n this.loadContent();\n this.updateThumbnails();\n this.updateCounter();\n this.updateNavigation();\n this.updateCaption();\n this.updateButtons();\n\n // Initialize auto-hide if enabled\n if (this.autoHideEnabled) {\n this.startAutoHideTimer();\n } else {\n this.showControls();\n }\n\n // Trigger callback\n if (typeof this.options.onOpen === 'function') {\n this.options.onOpen(element, this.currentIndex);\n }\n }\n\n /**\n * Close lightbox\n */\n close() {\n if (this.isFullscreen) {\n this.exitFullscreen();\n }\n\n this.zoomora.classList.remove('active');\n document.body.style.overflow = '';\n this.isZoomed = false;\n this.isFullscreen = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('zoomed');\n media.style.transform = '';\n media.style.cursor = '';\n }\n\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n this.showControls();\n\n // Trigger callback\n if (typeof this.options.onClose === 'function') {\n this.options.onClose(this.currentIndex);\n }\n }\n\n /**\n * Navigate to previous item\n */\n prev() {\n if (this.currentIndex > 0) {\n this.currentIndex--;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onPrev === 'function') {\n this.options.onPrev(this.currentIndex);\n }\n }\n }\n\n /**\n * Navigate to next item\n */\n next() {\n if (this.currentIndex < this.items.length - 1) {\n this.currentIndex++;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onNext === 'function') {\n this.options.onNext(this.currentIndex);\n }\n }\n }\n\n /**\n * Load content for current item\n */\n loadContent() {\n if (!this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const src = this.getImageSource(item);\n const type = item.dataset.type || 'image';\n\n if (!src) {\n console.error('Zoomora: No source found for item');\n return;\n }\n\n // Reset zoom state\n this.isZoomed = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n // Show loading spinner\n this.loading.style.display = 'block';\n\n if (this.slidesContainer) {\n this.slidesContainer.innerHTML = '';\n }\n\n setTimeout(() => {\n this.renderContent(src, type, item);\n }, 100);\n }\n\n /**\n * Render content based on type\n * @param {string} src - Source URL\n * @param {string} type - Content type\n * @param {Element} item - Original item element\n */\n renderContent(src, type, item) {\n const slideContainer = document.createElement('div');\n slideContainer.className = 'zoomora-slide-container';\n\n // Create slide wrapper\n const slide = document.createElement('div');\n slide.className = `zoomora-slide ${this.options.transition === 'slide' ? 'slide-effect' : 'fade-effect'}`;\n slide.style.opacity = '0';\n slide.style.transform = this.options.transition === 'slide' ? 'translateX(100%)' : 'scale(0.8)';\n\n let mediaElement;\n\n try {\n switch (type) {\n case 'video':\n if (src.endsWith('.mp4') || src.endsWith('.webm') || src.endsWith('.ogg')) {\n const videoContainer = document.createElement('div');\n videoContainer.className = 'zoomora-video-container';\n\n mediaElement = document.createElement('video');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('preload', 'metadata');\n\n const posterSrc = item.src || item.getAttribute('src');\n if (posterSrc) {\n mediaElement.setAttribute('poster', posterSrc);\n }\n\n const playButton = document.createElement('div');\n playButton.className = 'zoomora-play-button';\n playButton.innerHTML = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\n playButton.addEventListener('click', () => {\n mediaElement.play();\n playButton.style.display = 'none';\n mediaElement.setAttribute('controls', '');\n });\n\n mediaElement.addEventListener('ended', () => {\n playButton.style.display = 'flex';\n });\n\n videoContainer.appendChild(mediaElement);\n videoContainer.appendChild(playButton);\n slideContainer.appendChild(videoContainer);\n } else {\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('allowfullscreen', '');\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n }\n break;\n\n case 'iframe':\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-iframe';\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n break;\n\n default:\n mediaElement = document.createElement('img');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-media';\n mediaElement.alt = item.alt || item.title || '';\n\n mediaElement.onload = () => {\n this.loading.style.display = 'none';\n this.checkZoomability(mediaElement);\n this.animateSlideIn(slide);\n };\n\n mediaElement.onerror = () => {\n this.loading.style.display = 'none';\n console.error('Zoomora: Failed to load image:', src);\n this.animateSlideIn(slide);\n };\n\n slideContainer.appendChild(mediaElement);\n }\n\n slide.appendChild(slideContainer);\n\n // Clear existing slides and add new one\n this.slidesContainer.innerHTML = '';\n this.slidesContainer.appendChild(slide);\n\n if (type !== 'image') {\n this.loading.style.display = 'none';\n this.animateSlideIn(slide);\n }\n\n } catch (error) {\n console.error('Zoomora: Error rendering content:', error);\n this.loading.style.display = 'none';\n }\n }\n\n // Animation helper\n animateSlideIn(slide) {\n // Force reflow\n slide.offsetHeight;\n\n // Add active class and animate\n slide.classList.add('active');\n\n if (this.options.transition === 'slide') {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'translateX(0)';\n slide.style.opacity = '1';\n } else {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'scale(1)';\n slide.style.opacity = '1';\n }\n }\n\n // Toggle auto-hide controls\n toggleAutoHide() {\n this.autoHideEnabled = !this.autoHideEnabled;\n const autoHideBtn = document.getElementById('zoomoraAutoHideBtn');\n\n if (this.autoHideEnabled) {\n autoHideBtn.classList.add('active');\n autoHideBtn.title = 'Disable Auto-Hide Controls';\n this.startAutoHideTimer();\n } else {\n autoHideBtn.classList.remove('active');\n autoHideBtn.title = 'Enable Auto-Hide Controls';\n this.stopAutoHideTimer();\n this.showControls();\n }\n }\n\n // Handle user activity\n handleUserActivity() {\n if (!this.autoHideEnabled) return;\n\n this.showControls();\n this.startAutoHideTimer();\n }\n\n // Start auto-hide timer\n startAutoHideTimer() {\n this.stopAutoHideTimer();\n\n this.autoHideTimeout = setTimeout(() => {\n this.hideControls();\n }, this.options.autoHideDelay);\n }\n\n // Stop auto-hide timer\n stopAutoHideTimer() {\n if (this.autoHideTimeout) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = null;\n }\n }\n\n // Show controls\n showControls() {\n if (this.isControlsVisible) return;\n\n this.isControlsVisible = true;\n this.zoomora.classList.remove('controls-hidden');\n\n // Animate controls back in\n if (this.header) {\n this.header.style.transform = 'translateY(0)';\n this.header.style.opacity = '1';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(0)';\n this.thumbs.style.opacity = '1';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(0)';\n this.prevBtn.style.opacity = '1';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(0)';\n this.nextBtn.style.opacity = '1';\n }\n }\n\n // Hide controls\n hideControls() {\n if (!this.isControlsVisible) return;\n\n this.isControlsVisible = false;\n this.zoomora.classList.add('controls-hidden');\n\n // Animate controls out\n if (this.header) {\n this.header.style.transform = 'translateY(-100%)';\n this.header.style.opacity = '0';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(100%)';\n this.thumbs.style.opacity = '0';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(-100%)';\n this.prevBtn.style.opacity = '0';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(100%)';\n this.nextBtn.style.opacity = '0';\n }\n }\n\n /**\n * Check if image can be zoomed\n * @param {HTMLImageElement} img - Image element\n */\n checkZoomability(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) return;\n\n const imgRect = img.getBoundingClientRect();\n const renderedWidth = imgRect.width;\n const renderedHeight = imgRect.height;\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n const isScaledDown = naturalWidth > renderedWidth || naturalHeight > renderedHeight;\n const zoomRatioX = naturalWidth / renderedWidth;\n const zoomRatioY = naturalHeight / renderedHeight;\n const maxZoomRatio = Math.max(zoomRatioX, zoomRatioY);\n\n // Store zoom info\n img.dataset.zoomRatio = maxZoomRatio;\n img.dataset.naturalWidth = naturalWidth;\n img.dataset.naturalHeight = naturalHeight;\n img.dataset.renderedWidth = renderedWidth;\n img.dataset.renderedHeight = renderedHeight;\n\n // Enable zoom if significantly scaled down\n if (isScaledDown && maxZoomRatio > 1.1) {\n img.classList.remove('no-zoom');\n } else {\n img.classList.add('no-zoom');\n }\n }\n\n /**\n * Calculate zoom levels for an image\n * @param {HTMLImageElement} img - Image element\n * @returns {Object} Zoom configuration\n */\n /**\n * Calculate zoom levels for an image\n * @param {HTMLImageElement} img - Image element\n * @returns {Object} Zoom configuration\n */\n calculateZoomLevels(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) {\n return {canZoom: false, levels: [], currentLevel: 0};\n }\n\n // Get CONTAINER size (not current displayed image size)\n const container = this.content.getBoundingClientRect();\n const containerWidth = container.width;\n const containerHeight = container.height;\n\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n // Calculate what the ORIGINAL fit-to-screen scale would be\n const scaleToFitWidth = containerWidth / naturalWidth;\n const scaleToFitHeight = containerHeight / naturalHeight;\n const fitScale = Math.min(scaleToFitWidth, scaleToFitHeight);\n\n // If image naturally fits or is smaller than container, can't zoom\n if (fitScale >= 0.95) {\n return {canZoom: false, levels: [], currentLevel: 0};\n }\n\n // Calculate zoom levels based on FIT scale (not current scale)\n const levels = [1]; // Start with fit-to-screen\n\n // Add progressive levels: 1.5x, 2x, 3x\n if (fitScale * 1.5 <= 1) levels.push(1.5);\n if (fitScale * 2 <= 1) levels.push(2);\n if (fitScale * 3 <= 1) levels.push(3);\n\n // Add actual size (100%) as final level\n const actualSizeScale = 1 / fitScale;\n if (actualSizeScale > levels[levels.length - 1]) {\n levels.push(actualSizeScale);\n }\n\n return {\n canZoom: levels.length > 1,\n levels: levels,\n currentLevel: 0,\n baseScale: fitScale,\n naturalWidth: naturalWidth,\n naturalHeight: naturalHeight\n };\n }\n\n /**\n * Update counter display\n */\n updateCounter() {\n if (this.options.showCounter && this.counter) {\n this.counter.textContent = `${this.currentIndex + 1} / ${this.items.length}`;\n }\n }\n\n /**\n * Update caption display\n */\n updateCaption() {\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption) {\n this.caption.textContent = caption;\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n this.caption.style.pointerEvents = 'auto';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n this.caption.style.pointerEvents = 'none';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n }\n }\n\n /**\n * Update thumbnails display\n */\n updateThumbnails() {\n if (!this.options.showThumbnails || !this.thumbs) return;\n\n if (this.items.length === 1) {\n this.caption.classList.add('single-item-thumbnail');\n this.thumbs.style.display = 'none';\n return;\n }\n\n this.caption.classList.remove('single-item-thumbnail');\n\n this.thumbs.style.display = 'flex';\n this.thumbs.innerHTML = '';\n\n this.items.forEach((item, index) => {\n const thumb = document.createElement('div');\n thumb.className = 'zoomora-thumb';\n if (index === this.currentIndex) thumb.classList.add('active');\n\n const img = document.createElement('img');\n const thumbSrc = this.getThumbnailSource(item);\n\n if (thumbSrc) {\n img.src = thumbSrc;\n img.alt = item.alt || item.title || '';\n img.onerror = () => {\n thumb.style.display = 'none';\n };\n }\n\n thumb.appendChild(img);\n\n thumb.addEventListener('click', () => {\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n });\n\n this.thumbs.appendChild(thumb);\n });\n }\n\n /**\n * Update navigation buttons\n */\n updateNavigation() {\n const prevBtn = document.getElementById('zoomoraPrevBtn');\n const nextBtn = document.getElementById('zoomoraNextBtn');\n\n if (prevBtn) {\n prevBtn.style.display = this.currentIndex > 0 ? 'flex' : 'none';\n }\n if (nextBtn) {\n nextBtn.style.display = this.currentIndex < this.items.length - 1 ? 'flex' : 'none';\n }\n }\n\n /**\n * Update control buttons\n */\n updateButtons() {\n const fullscreenBtn = document.getElementById('zoomoraFullscreenBtn');\n const collapseBtn = document.getElementById('zoomoraCollapseBtn');\n\n if (fullscreenBtn && collapseBtn) {\n if (this.isFullscreen) {\n fullscreenBtn.style.display = 'none';\n collapseBtn.style.display = 'flex';\n } else {\n fullscreenBtn.style.display = 'flex';\n collapseBtn.style.display = 'none';\n }\n }\n }\n\n /**\n * Toggle zoom state\n */\n toggleZoom() {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || media.tagName !== 'IMG') return;\n\n // Calculate zoom levels\n const zoomConfig = this.calculateZoomLevels(media);\n\n if (!zoomConfig.canZoom) {\n console.log('Image cannot be zoomed (already at full size or larger)');\n return;\n }\n\n // Get or initialize current zoom level\n if (!media.dataset.zoomLevel) {\n media.dataset.zoomLevel = '0';\n }\n\n let currentLevel = parseInt(media.dataset.zoomLevel) || 0;\n\n // Cycle to next level\n currentLevel++;\n if (currentLevel >= zoomConfig.levels.length) {\n // Reset to fit-to-screen\n currentLevel = 0;\n }\n\n const targetScale = zoomConfig.levels[currentLevel];\n media.dataset.zoomLevel = currentLevel.toString();\n\n if (currentLevel === 0) {\n // Back to fit-to-screen\n this.isZoomed = false;\n this.isDragging = false;\n media.classList.remove('dragging');\n media.style.transform = '';\n media.style.cursor = 'pointer';\n media.classList.remove('zoomed');\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n } else {\n // Zoom in - reset position to center\n this.isZoomed = true;\n this.currentScale = targetScale;\n this.currentX = 0; // Always reset to center on zoom change\n this.currentY = 0;\n\n media.style.transform = `translate(0px, 0px) scale(${targetScale})`;\n media.style.cursor = 'grab';\n media.classList.add('zoomed');\n\n console.log(`Zoomed to level ${currentLevel}/${zoomConfig.levels.length - 1} (${(targetScale * 100).toFixed(0)}%)`);\n }\n }\n\n /**\n * Update image transform based on current state\n * @param {HTMLElement} media - Media element\n */\n updateImageTransform(media) {\n if (!media) return;\n\n if (this.currentScale === 1) {\n media.style.transform = '';\n } else {\n // IMPORTANT: translate in scaled space, so divide by scale\n const translateX = this.currentX / this.currentScale;\n const translateY = this.currentY / this.currentScale;\n media.style.transform = `scale(${this.currentScale}) translate(${translateX}px, ${translateY}px)`;\n }\n }\n\n /**\n * Toggle fullscreen mode\n */\n toggleFullscreen() {\n if (!this.isFullscreen) {\n this.enterFullscreen();\n } else {\n this.exitFullscreen();\n }\n }\n\n /**\n * Enter fullscreen mode\n */\n enterFullscreen() {\n const element = this.zoomora;\n const requestFullscreen = element.requestFullscreen ||\n element.webkitRequestFullscreen ||\n element.mozRequestFullScreen ||\n element.msRequestFullscreen;\n\n if (requestFullscreen) {\n requestFullscreen.call(element).then(() => {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not enter fullscreen:', err);\n this.fallbackFullscreen();\n });\n } else {\n this.fallbackFullscreen();\n }\n }\n\n /**\n * Exit fullscreen mode\n */\n exitFullscreen() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (isInFullscreen) {\n const exitFullscreen = document.exitFullscreen ||\n document.webkitExitFullscreen ||\n document.mozCancelFullScreen ||\n document.msExitFullscreen;\n\n if (exitFullscreen) {\n exitFullscreen.call(document).then(() => {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not exit fullscreen:', err);\n this.fallbackExitFullscreen();\n });\n } else {\n this.fallbackExitFullscreen();\n }\n } else {\n this.fallbackExitFullscreen();\n }\n }\n\n /**\n * Fallback fullscreen using CSS\n */\n fallbackFullscreen() {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Exit CSS fullscreen\n */\n fallbackExitFullscreen() {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Toggle thumbnails visibility\n */\n toggleThumbnails() {\n if (this.items.length === 1) return;\n\n this.thumbnailsVisible = !this.thumbnailsVisible;\n if (this.thumbs) {\n this.thumbs.classList.toggle('thumbs-hidden', !this.thumbnailsVisible);\n\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption && this.thumbs.classList.contains('thumbs-hidden')) {\n this.caption.style.bottom = '20px';\n this.caption.style.transition = 'bottom 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.bottom = '120px';\n }\n }\n }\n\n /**\n * Start drag operation\n * @param {Event} e - Mouse or touch event\n */\n startDrag(e) {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || !this.isZoomed) return;\n\n this.isDragging = true;\n media.classList.add('dragging');\n media.style.cursor = 'grabbing';\n\n this.startX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n this.startY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n // Read current position from transform\n const transform = window.getComputedStyle(media).transform;\n if (transform && transform !== 'none') {\n const matrix = new DOMMatrix(transform);\n this.currentX = matrix.m41;\n this.currentY = matrix.m42;\n } else {\n this.currentX = 0;\n this.currentY = 0;\n }\n\n e.preventDefault();\n }\n\n /**\n * Handle drag movement\n * @param {Event} e - Mouse or touch event\n */\n drag(e) {\n if (!this.isDragging) return;\n e.preventDefault();\n\n const media = this.content.querySelector('.zoomora-media');\n if (!media) return;\n\n const clientX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n const clientY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n const deltaX = clientX - this.startX;\n const deltaY = clientY - this.startY;\n\n let newX = this.currentX + deltaX;\n let newY = this.currentY + deltaY;\n\n // Calculate boundaries for BOTH width AND height\n const container = this.content.getBoundingClientRect();\n const mediaRect = media.getBoundingClientRect();\n\n // How much the scaled image overflows the container\n const overflowX = Math.max(0, (mediaRect.width - container.width) / 2);\n const overflowY = Math.max(0, (mediaRect.height - container.height) / 2);\n\n // Constrain drag to overflow boundaries\n if (overflowX > 0) {\n newX = Math.max(-overflowX, Math.min(overflowX, newX));\n } else {\n newX = 0; // Center horizontally if no overflow\n }\n\n if (overflowY > 0) {\n newY = Math.max(-overflowY, Math.min(overflowY, newY));\n } else {\n newY = 0; // Center vertically if no overflow\n }\n\n // Apply transform\n media.style.transform = `translate(${newX}px, ${newY}px) scale(${this.currentScale})`;\n\n // Update for next frame\n this.startX = clientX;\n this.startY = clientY;\n this.currentX = newX;\n this.currentY = newY;\n }\n\n /**\n * End drag operation\n */\n endDrag() {\n if (!this.isDragging) return;\n\n this.isDragging = false;\n this.lastDragTime = Date.now();\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('dragging');\n if (this.isZoomed) {\n media.style.cursor = 'grab';\n }\n }\n }\n\n /**\n * Go to specific item by index\n * @param {number} index - Item index\n */\n goTo(index) {\n if (index < 0 || index >= this.items.length) return;\n\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n }\n\n /**\n * Get current item index\n * @returns {number} - Current index\n */\n getCurrentIndex() {\n return this.currentIndex;\n }\n\n /**\n * Get total number of items\n * @returns {number} - Total items\n */\n getTotalItems() {\n return this.items.length;\n }\n\n /**\n * Check if lightbox is open\n * @returns {boolean} - True if open\n */\n isOpen() {\n return this.zoomora && this.zoomora.classList.contains('active');\n }\n\n /**\n * Update options\n * @param {Object} newOptions - New options to merge\n */\n updateOptions(newOptions) {\n this.options = {...this.options, ...newOptions};\n }\n\n /**\n * Refresh the lightbox (re-scan for items)\n */\n refresh() {\n if (this.isOpen()) {\n const currentItem = this.items[this.currentIndex];\n if (currentItem) {\n this.open(currentItem);\n }\n }\n }\n\n /**\n * Destroy the lightbox instance\n */\n destroy() {\n if (!this.isInitialized) return;\n\n // Close if open\n if (this.isOpen()) {\n this.close();\n }\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n\n // Remove all event listeners\n this.eventListeners.forEach((listeners, key) => {\n listeners.forEach(({element, event, handler, options}) => {\n if (element && element.removeEventListener) {\n element.removeEventListener(event, handler, options);\n }\n });\n });\n this.eventListeners.clear();\n\n // Remove DOM elements\n if (this.zoomora && this.zoomora.parentNode) {\n this.zoomora.parentNode.removeChild(this.zoomora);\n }\n\n // Reset properties\n this.isInitialized = false;\n this.items = [];\n this.currentIndex = 0;\n this.zoomora = null;\n this.content = null;\n this.counter = null;\n this.thumbs = null;\n this.loading = null;\n this.caption = null;\n }\n }\n\n // Export the class\n return Zoomora;\n}));"],"names":["this"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- var t,e,s=Object.defineProperty,o=Object.defineProperties,i=Object.getOwnPropertyDescriptors,n=Object.getOwnPropertyNames,a=Object.getOwnPropertySymbols,r=Object.prototype.hasOwnProperty,l=Object.prototype.propertyIsEnumerable,h=(t,e,o)=>e in t?s(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,d=(t,e)=>{for(var s in e||(e={}))r.call(e,s)&&h(t,s,e[s]);if(a)for(var s of a(e))l.call(e,s)&&h(t,s,e[s]);return t},c=(t={"zoomora.es.min.js"(t,e){
1
+ var t,e,s=Object.defineProperty,i=Object.defineProperties,n=Object.getOwnPropertyDescriptors,o=Object.getOwnPropertyNames,a=Object.getOwnPropertySymbols,r=Object.prototype.hasOwnProperty,l=Object.prototype.propertyIsEnumerable,h=(t,e,i)=>e in t?s(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,d=(t,e)=>{for(var s in e||(e={}))r.call(e,s)&&h(t,s,e[s]);if(a)for(var s of a(e))l.call(e,s)&&h(t,s,e[s]);return t},c=(t={"zoomora.es.min.js"(t,e){
2
2
  /*!
3
- * Zoomora Lightbox Plugin v1.0.0
3
+ * Zoomora Lightbox Plugin v1.1.0
4
4
  * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
5
5
  *
6
6
  * Copyright (c) 2025 Faruk Ahmed (FrontTheme)
7
7
  * Licensed under MIT License
8
8
  */
9
- var s,n;s="undefined"!=typeof window?window:void 0,n=function(){class t{static get defaults(){return{selector:"[data-zoomora]",showCounter:!0,showThumbnails:!0,showFullscreen:!0,showZoom:!0,transition:"fade",useHref:!1,maxZoomScale:3,zoomStep:.1,animationDuration:300,onOpen:null,onClose:null,onNext:null,onPrev:null,showAutoHideToggle:!0,autoHideDelay:3e3,autoHideEnabled:!1}}constructor(e={}){this.options=d(d({},t.defaults),e),this.currentIndex=0,this.items=[],this.isZoomed=!1,this.isFullscreen=!1,this.isDragging=!1,this.thumbnailsVisible=!0,this.startX=0,this.startY=0,this.currentX=0,this.currentY=0,this.currentScale=1,this.isInitialized=!1,this.eventListeners=new Map,this.autoHideEnabled=!1,this.autoHideTimeout=null,this.autoHideDelay=3e3,this.isControlsVisible=!0,this.idleTimer=null,this.boundMethods={handleDocumentClick:this.handleDocumentClick.bind(this),handleKeydown:this.handleKeydown.bind(this),handleFullscreenChange:this.handleFullscreenChange.bind(this),handleZoomoraClick:this.handleZoomoraClick.bind(this),handleContentClick:this.handleContentClick.bind(this),handleMouseDown:this.handleMouseDown.bind(this),handleMouseMove:this.handleMouseMove.bind(this),handleMouseUp:this.handleMouseUp.bind(this),handleTouchStart:this.handleTouchStart.bind(this),handleTouchMove:this.handleTouchMove.bind(this),handleTouchEnd:this.handleTouchEnd.bind(this)},this.init()}init(){if(this.isInitialized)console.warn("Zoomora: Plugin already initialized");else try{this.createLightbox(),this.bindEvents(),this.isInitialized=!0}catch(t){console.error("Zoomora: Initialization failed",t)}}static bind(e,s={}){const n=(a=d({},s),o(a,i({selector:e,useHref:!0})));var a;return new t(n)}createLightbox(){if(document.getElementById("zoomoraLightbox"))console.warn("Zoomora: Lightbox already exists in DOM");else if(document.body.insertAdjacentHTML("beforeend",'\n <div class="zoomora" id="zoomoraLightbox">\n <div class="zoomora-container">\n <div class="zoomora-header" id="zoomoraHeader">\n <div class="zoomora-counter" id="zoomoraCounter">1 / 1</div>\n <div class="zoomora-controls">\n <button class="zoomora-btn" id="zoomoraThumbnailBtn" title="Toggle Thumbnails">\n <i class="zoomorai-thumbnails"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraAutoHideBtn" title="Toggle Auto-Hide Controls">\n <i class="zoomorai-controls-off"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraZoomBtn" title="Zoom">\n <i class="zoomorai-zoom"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraFullscreenBtn" title="Fullscreen">\n <i class="zoomorai-expand"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraCollapseBtn" title="Exit Fullscreen" style="display: none;">\n <i class="zoomorai-collapse"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraCloseBtn" title="Close">\n <i class="zoomorai-close"></i>\n </button>\n </div>\n </div>\n \n <div class="zoomora-content" id="zoomoraContent">\n <div class="zoomora-loading" id="zoomoraLoading"></div>\n <div class="zoomora-slides-container" id="zoomoraSlidesContainer"></div>\n </div>\n \n <button class="zoomora-nav prev" id="zoomoraPrevBtn">\n <i class="zoomorai-arrow-left"></i>\n </button>\n <button class="zoomora-nav next" id="zoomoraNextBtn">\n <i class="zoomorai-arrow-right"></i>\n </button>\n \n <div class="zoomora-caption" id="zoomoraCaption"></div>\n <div class="zoomora-thumbnails" id="zoomoraThumbs"></div>\n </div>\n </div>\n '),this.zoomora=document.getElementById("zoomoraLightbox"),this.header=document.getElementById("zoomoraHeader"),this.content=document.getElementById("zoomoraContent"),this.slidesContainer=document.getElementById("zoomoraSlidesContainer"),this.counter=document.getElementById("zoomoraCounter"),this.thumbs=document.getElementById("zoomoraThumbs"),this.loading=document.getElementById("zoomoraLoading"),this.caption=document.getElementById("zoomoraCaption"),this.prevBtn=document.getElementById("zoomoraPrevBtn"),this.nextBtn=document.getElementById("zoomoraNextBtn"),!(this.zoomora&&this.content&&this.counter&&this.thumbs&&this.loading&&this.caption))throw new Error("Failed to create required DOM elements")}bindEvents(){this.addEventListener(document,"click",this.boundMethods.handleDocumentClick),this.addEventListener(document.getElementById("zoomoraCloseBtn"),"click",()=>this.close()),this.addEventListener(document.getElementById("zoomoraPrevBtn"),"click",()=>this.prev()),this.addEventListener(document.getElementById("zoomoraNextBtn"),"click",()=>this.next()),this.addEventListener(document.getElementById("zoomoraZoomBtn"),"click",()=>this.toggleZoom()),this.addEventListener(document.getElementById("zoomoraFullscreenBtn"),"click",()=>this.toggleFullscreen()),this.addEventListener(document.getElementById("zoomoraCollapseBtn"),"click",()=>this.exitFullscreen()),this.addEventListener(document.getElementById("zoomoraThumbnailBtn"),"click",()=>this.toggleThumbnails()),this.addEventListener(document,"fullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"webkitfullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"mozfullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"MSFullscreenChange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"keydown",this.boundMethods.handleKeydown),this.addEventListener(this.zoomora,"click",this.boundMethods.handleZoomoraClick),this.addEventListener(this.content,"click",this.boundMethods.handleContentClick),this.addEventListener(this.content,"mousedown",this.boundMethods.handleMouseDown),this.addEventListener(this.content,"mousemove",this.boundMethods.handleMouseMove),this.addEventListener(this.content,"mouseup",this.boundMethods.handleMouseUp),this.addEventListener(this.content,"mouseleave",this.boundMethods.handleMouseUp),this.addEventListener(this.content,"touchstart",this.boundMethods.handleTouchStart,{passive:!1}),this.addEventListener(this.content,"touchmove",this.boundMethods.handleTouchMove,{passive:!1}),this.addEventListener(this.content,"touchend",this.boundMethods.handleTouchEnd),this.addEventListener(document.getElementById("zoomoraAutoHideBtn"),"click",()=>this.toggleAutoHide()),this.addEventListener(this.zoomora,"mousemove",()=>this.handleUserActivity()),this.addEventListener(this.zoomora,"touchstart",()=>this.handleUserActivity()),this.addEventListener(this.zoomora,"keydown",()=>this.handleUserActivity())}addEventListener(t,e,s,o={}){if(!t)return;t.addEventListener(e,s,o);const i=`${t.constructor.name}_${e}`;this.eventListeners.has(i)||this.eventListeners.set(i,[]),this.eventListeners.get(i).push({element:t,event:e,handler:s,options:o})}handleDocumentClick(t){const e=t.target.closest(this.options.selector);e&&(t.preventDefault(),this.open(e))}handleKeydown(t){if(this.zoomora.classList.contains("active"))switch(t.key){case"Escape":this.isFullscreen?this.exitFullscreen():this.close();break;case"ArrowLeft":this.prev();break;case"ArrowRight":this.next();break;case"z":case"Z":this.toggleZoom();break;case"f":case"F":this.toggleFullscreen();break;case"t":case"T":this.toggleThumbnails()}}handleFullscreenChange(){!(document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons())}handleZoomoraClick(t){t.target===this.zoomora&&this.close()}handleContentClick(t){const e=t.target.closest(".zoomora-media");!e||e.classList.contains("no-zoom")||this.isDragging||this.toggleZoom()}handleMouseDown(t){this.startDrag(t)}handleMouseMove(t){this.drag(t)}handleMouseUp(){this.endDrag()}handleTouchStart(t){this.startDrag(t)}handleTouchMove(t){this.drag(t)}handleTouchEnd(){this.endDrag()}getImageSource(t){const e=t.dataset.src||t.src||t.getAttribute("src");return"video"===(t.dataset.type||"image")&&e?this.convertToEmbedUrl(e):e}convertToEmbedUrl(t){if(t.includes("youtube.com/embed/"))return t;let e=null,s=null;if(t.includes("youtube.com/watch")){const o=new URLSearchParams(t.split("?")[1]);e=o.get("v");const i=o.get("t");i&&(s=i.replace("s",""))}else if(t.includes("youtu.be/")){const o=t.split("/"),i=o[o.length-1];if(i.includes("?")){e=i.split("?")[0];const t=new URLSearchParams(i.split("?")[1]).get("t");t&&(s=t.replace("s",""))}else e=i}if(e){let t=`https://www.youtube.com/embed/${e}`;const o=new URLSearchParams;return s&&o.append("start",s),o.append("rel","0"),o.append("modestbranding","1"),o.toString()&&(t+="?"+o.toString()),t}return t}getThumbnailSource(t){return"video"===(t.dataset.type||"image")?t.src||t.getAttribute("src"):t.dataset.src||t.src||t.getAttribute("src")}getGroup(t){return this.options.useHref?t.dataset.lightbox||t.dataset.gallery||"default":t.dataset.zoomora||"default"}open(t){if(!t)return;const e=this.getGroup(t);let s;s=this.options.useHref?t.dataset.lightbox?`[data-lightbox="${e}"]`:t.dataset.gallery?`[data-gallery="${e}"]`:this.options.selector:`[data-zoomora="${e}"]`,this.items=Array.from(document.querySelectorAll(s)),this.currentIndex=Math.max(0,this.items.indexOf(t)),this.isZoomed=!1,this.isFullscreen=!1,this.thumbnailsVisible=!0,this.currentX=0,this.currentY=0,this.currentScale=1,this.zoomora.classList.add("active"),document.body.style.overflow="hidden",this.loadContent(),this.updateThumbnails(),this.updateCounter(),this.updateNavigation(),this.updateCaption(),this.updateButtons(),this.autoHideEnabled?this.startAutoHideTimer():this.showControls(),"function"==typeof this.options.onOpen&&this.options.onOpen(t,this.currentIndex)}close(){this.isFullscreen&&this.exitFullscreen(),this.zoomora.classList.remove("active"),document.body.style.overflow="",this.isZoomed=!1,this.isFullscreen=!1,this.currentX=0,this.currentY=0,this.currentScale=1;const t=this.content.querySelector(".zoomora-media");t&&(t.classList.remove("zoomed"),t.style.transform="",t.style.cursor=""),this.zoomora.classList.remove("fullscreen"),this.updateButtons(),this.stopAutoHideTimer(),this.showControls(),"function"==typeof this.options.onClose&&this.options.onClose(this.currentIndex)}prev(){this.currentIndex>0&&(this.currentIndex--,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption(),"function"==typeof this.options.onPrev&&this.options.onPrev(this.currentIndex))}next(){this.currentIndex<this.items.length-1&&(this.currentIndex++,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption(),"function"==typeof this.options.onNext&&this.options.onNext(this.currentIndex))}loadContent(){if(!this.items[this.currentIndex])return;const t=this.items[this.currentIndex],e=this.getImageSource(t),s=t.dataset.type||"image";e?(this.loading.style.display="block",this.slidesContainer&&(this.slidesContainer.innerHTML=""),setTimeout(()=>{this.renderContent(e,s,t)},100)):console.error("Zoomora: No source found for item")}renderContent(t,e,s){const o=document.createElement("div");o.className="zoomora-slide-container";const i=document.createElement("div");let n;i.className="zoomora-slide "+("slide"===this.options.transition?"slide-effect":"fade-effect"),i.style.opacity="0",i.style.transform="slide"===this.options.transition?"translateX(100%)":"scale(0.8)";try{switch(e){case"video":if(t.endsWith(".mp4")||t.endsWith(".webm")||t.endsWith(".ogg")){const e=document.createElement("div");e.className="zoomora-video-container",n=document.createElement("video"),n.src=t,n.className="zoomora-video",n.setAttribute("preload","metadata");const i=s.src||s.getAttribute("src");i&&n.setAttribute("poster",i);const a=document.createElement("div");a.className="zoomora-play-button",a.innerHTML='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>',a.addEventListener("click",()=>{n.play(),a.style.display="none",n.setAttribute("controls","")}),n.addEventListener("ended",()=>{a.style.display="flex"}),e.appendChild(n),e.appendChild(a),o.appendChild(e)}else n=document.createElement("iframe"),n.src=t,n.className="zoomora-video",n.setAttribute("allowfullscreen",""),n.setAttribute("frameborder","0"),o.appendChild(n);break;case"iframe":n=document.createElement("iframe"),n.src=t,n.className="zoomora-iframe",n.setAttribute("frameborder","0"),o.appendChild(n);break;default:n=document.createElement("img"),n.src=t,n.className="zoomora-media",n.alt=s.alt||s.title||"",n.onload=()=>{this.loading.style.display="none",this.checkZoomability(n),this.animateSlideIn(i)},n.onerror=()=>{this.loading.style.display="none",console.error("Zoomora: Failed to load image:",t),this.animateSlideIn(i)},o.appendChild(n)}i.appendChild(o),this.slidesContainer.innerHTML="",this.slidesContainer.appendChild(i),"image"!==e&&(this.loading.style.display="none",this.animateSlideIn(i))}catch(t){console.error("Zoomora: Error rendering content:",t),this.loading.style.display="none"}}animateSlideIn(t){t.offsetHeight,t.classList.add("active"),"slide"===this.options.transition?(t.style.transition=`transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`,t.style.transform="translateX(0)",t.style.opacity="1"):(t.style.transition=`transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`,t.style.transform="scale(1)",t.style.opacity="1")}toggleAutoHide(){this.autoHideEnabled=!this.autoHideEnabled;const t=document.getElementById("zoomoraAutoHideBtn");this.autoHideEnabled?(t.classList.add("active"),t.title="Disable Auto-Hide Controls",this.startAutoHideTimer()):(t.classList.remove("active"),t.title="Enable Auto-Hide Controls",this.stopAutoHideTimer(),this.showControls())}handleUserActivity(){this.autoHideEnabled&&(this.showControls(),this.startAutoHideTimer())}startAutoHideTimer(){this.stopAutoHideTimer(),this.autoHideTimeout=setTimeout(()=>{this.hideControls()},this.options.autoHideDelay)}stopAutoHideTimer(){this.autoHideTimeout&&(clearTimeout(this.autoHideTimeout),this.autoHideTimeout=null)}showControls(){this.isControlsVisible||(this.isControlsVisible=!0,this.zoomora.classList.remove("controls-hidden"),this.header&&(this.header.style.transform="translateY(0)",this.header.style.opacity="1"),this.caption&&(this.caption.style.transform="translateX(-50%) translateY(0)",this.caption.style.opacity="1"),this.thumbs&&(this.thumbs.style.transform="translateX(-50%) translateY(0)",this.thumbs.style.opacity="1"),this.prevBtn&&(this.prevBtn.style.transform="translateX(0)",this.prevBtn.style.opacity="1"),this.nextBtn&&(this.nextBtn.style.transform="translateX(0)",this.nextBtn.style.opacity="1"))}hideControls(){this.isControlsVisible&&(this.isControlsVisible=!1,this.zoomora.classList.add("controls-hidden"),this.header&&(this.header.style.transform="translateY(-100%)",this.header.style.opacity="0"),this.caption&&(this.caption.style.transform="translateX(-50%) translateY(100%)",this.caption.style.opacity="0"),this.thumbs&&(this.thumbs.style.transform="translateX(-50%) translateY(100%)",this.thumbs.style.opacity="0"),this.prevBtn&&(this.prevBtn.style.transform="translateX(-100%)",this.prevBtn.style.opacity="0"),this.nextBtn&&(this.nextBtn.style.transform="translateX(100%)",this.nextBtn.style.opacity="0"))}checkZoomability(t){if(!t||!t.naturalWidth||!t.naturalHeight)return;const e=t.getBoundingClientRect(),s=e.width,o=e.height,i=t.naturalWidth,n=t.naturalHeight,a=i>s||n>o,r=i/s,l=n/o,h=Math.max(r,l);t.dataset.zoomRatio=h,t.dataset.naturalWidth=i,t.dataset.naturalHeight=n,t.dataset.renderedWidth=s,t.dataset.renderedHeight=o,a&&h>1.1?t.classList.remove("no-zoom"):t.classList.add("no-zoom")}updateCounter(){this.options.showCounter&&this.counter&&(this.counter.textContent=`${this.currentIndex+1} / ${this.items.length}`)}updateCaption(){if(!this.caption||!this.items[this.currentIndex])return;const t=this.items[this.currentIndex],e=t.dataset.caption||t.title||"";e?(this.caption.textContent=e,this.caption.style.transform="translateX(-50%) translateY(0)",this.caption.style.opacity="1",this.caption.style.pointerEvents="auto",this.caption.style.transition="opacity 0.3s ease, transform 0.3s ease"):(this.caption.style.transform="translateX(-50%) translateY(100%)",this.caption.style.opacity="0",this.caption.style.pointerEvents="none",this.caption.style.transition="opacity 0.3s ease, transform 0.3s ease")}updateThumbnails(){if(this.options.showThumbnails&&this.thumbs){if(1===this.items.length)return this.caption.classList.add("single-item-thumbnail"),void(this.thumbs.style.display="none");this.caption.classList.remove("single-item-thumbnail"),this.thumbs.style.display="flex",this.thumbs.innerHTML="",this.items.forEach((t,e)=>{const s=document.createElement("div");s.className="zoomora-thumb",e===this.currentIndex&&s.classList.add("active");const o=document.createElement("img"),i=this.getThumbnailSource(t);i&&(o.src=i,o.alt=t.alt||t.title||"",o.onerror=()=>{s.style.display="none"}),s.appendChild(o),s.addEventListener("click",()=>{this.currentIndex=e,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption()}),this.thumbs.appendChild(s)})}}updateNavigation(){const t=document.getElementById("zoomoraPrevBtn"),e=document.getElementById("zoomoraNextBtn");t&&(t.style.display=this.currentIndex>0?"flex":"none"),e&&(e.style.display=this.currentIndex<this.items.length-1?"flex":"none")}updateButtons(){const t=document.getElementById("zoomoraFullscreenBtn"),e=document.getElementById("zoomoraCollapseBtn");t&&e&&(this.isFullscreen?(t.style.display="none",e.style.display="flex"):(t.style.display="flex",e.style.display="none"))}toggleZoom(){const t=this.content.querySelector(".zoomora-media");if(t&&"IMG"===t.tagName&&!t.classList.contains("no-zoom"))if(this.isZoomed=!this.isZoomed,t.classList.toggle("zoomed",this.isZoomed),this.isZoomed){const e=parseFloat(t.dataset.zoomRatio)||2;let s=Math.min(e,this.options.maxZoomScale);e>2.5&&(s=Math.min(.7*e,2.5)),t.style.transform=`scale(${s})`,t.style.cursor="grab",t.dataset.currentZoomScale=s,this.currentScale=s}else t.style.transform="",t.style.cursor="",this.currentX=0,this.currentY=0,this.currentScale=1}toggleFullscreen(){this.isFullscreen?this.exitFullscreen():this.enterFullscreen()}enterFullscreen(){const t=this.zoomora,e=t.requestFullscreen||t.webkitRequestFullscreen||t.mozRequestFullScreen||t.msRequestFullscreen;e?e.call(t).then(()=>{this.isFullscreen=!0,this.zoomora.classList.add("fullscreen"),this.updateButtons()}).catch(t=>{console.warn("Zoomora: Could not enter fullscreen:",t),this.fallbackFullscreen()}):this.fallbackFullscreen()}exitFullscreen(){if(document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement){const t=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;t?t.call(document).then(()=>{this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons()}).catch(t=>{console.warn("Zoomora: Could not exit fullscreen:",t),this.fallbackExitFullscreen()}):this.fallbackExitFullscreen()}else this.fallbackExitFullscreen()}fallbackFullscreen(){this.isFullscreen=!0,this.zoomora.classList.add("fullscreen"),this.updateButtons()}fallbackExitFullscreen(){this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons()}toggleThumbnails(){if(1!==this.items.length&&(this.thumbnailsVisible=!this.thumbnailsVisible,this.thumbs)){if(this.thumbs.classList.toggle("thumbs-hidden",!this.thumbnailsVisible),!this.caption||!this.items[this.currentIndex])return;const t=this.items[this.currentIndex];(t.dataset.caption||t.title)&&this.thumbs.classList.contains("thumbs-hidden")?(this.caption.style.bottom="20px",this.caption.style.transition="bottom 0.3s ease, transform 0.3s ease"):this.caption.style.bottom="120px"}}startDrag(t){const e=this.content.querySelector(".zoomora-media");if(!e||!this.isZoomed)return;this.isDragging=!0,e.style.cursor="grabbing",this.startX=t.clientX||t.touches&&t.touches[0].clientX||0,this.startY=t.clientY||t.touches&&t.touches[0].clientY||0;const s=e.style.transform,o=s.match(/scale\(([^)]+)\)/),i=s.match(/translate\(([^,]+),\s*([^)]+)\)/);this.currentScale=o?parseFloat(o[1]):1,this.currentX=i?parseFloat(i[1]):0,this.currentY=i?parseFloat(i[2]):0,t.preventDefault()}drag(t){if(!this.isDragging)return;t.preventDefault();const e=t.clientX||t.touches&&t.touches[0].clientX||0,s=t.clientY||t.touches&&t.touches[0].clientY||0,o=e-this.startX,i=s-this.startY,n=this.currentX+o,a=this.currentY+i,r=this.content.querySelector(".zoomora-media");if(!r)return;const l=r.getBoundingClientRect(),h=this.currentScale,d=l.width*(h-1)/2,c=l.height*(h-1)/2,u=Math.max(-d,Math.min(d,n)),m=Math.max(-c,Math.min(c,a));r.style.transform=`scale(${h}) translate(${u}px, ${m}px)`}endDrag(){if(!this.isDragging)return;this.isDragging=!1;const t=this.content.querySelector(".zoomora-media");t&&this.isZoomed&&(t.style.cursor="grab")}goTo(t){t<0||t>=this.items.length||(this.currentIndex=t,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption())}getCurrentIndex(){return this.currentIndex}getTotalItems(){return this.items.length}isOpen(){return this.zoomora&&this.zoomora.classList.contains("active")}updateOptions(t){this.options=d(d({},this.options),t)}refresh(){if(this.isOpen()){const t=this.items[this.currentIndex];t&&this.open(t)}}destroy(){this.isInitialized&&(this.isOpen()&&this.close(),this.stopAutoHideTimer(),this.eventListeners.forEach((t,e)=>{t.forEach(({element:t,event:e,handler:s,options:o})=>{t&&t.removeEventListener&&t.removeEventListener(e,s,o)})}),this.eventListeners.clear(),this.zoomora&&this.zoomora.parentNode&&this.zoomora.parentNode.removeChild(this.zoomora),this.isInitialized=!1,this.items=[],this.currentIndex=0,this.zoomora=null,this.content=null,this.counter=null,this.thumbs=null,this.loading=null,this.caption=null)}}return t},"object"==typeof e&&"object"==typeof e.exports?e.exports=n():"function"==typeof define&&define.amd?define(n):s.Zoomora=n()}},function(){return e||(0,t[n(t)[0]])((e={exports:{}}).exports,e),e.exports});export default c();
9
+ var s,o;s="undefined"!=typeof window?window:void 0,o=function(){class t{static get defaults(){return{selector:"[data-zoomora]",showCounter:!0,showThumbnails:!0,showFullscreen:!0,showZoom:!0,transition:"fade",useHref:!1,maxZoomScale:3,zoomStep:.1,animationDuration:300,onOpen:null,onClose:null,onNext:null,onPrev:null,showAutoHideToggle:!0,autoHideDelay:3e3,autoHideEnabled:!1}}constructor(e={}){this.options=d(d({},t.defaults),e),this.currentIndex=0,this.items=[],this.isZoomed=!1,this.isFullscreen=!1,this.isDragging=!1,this.thumbnailsVisible=!0,this.startX=0,this.startY=0,this.currentX=0,this.currentY=0,this.currentScale=1,this.isInitialized=!1,this.eventListeners=new Map,this.autoHideEnabled=!1,this.autoHideTimeout=null,this.autoHideDelay=3e3,this.isControlsVisible=!0,this.idleTimer=null,this.lastDragTime=0,this.boundMethods={handleDocumentClick:this.handleDocumentClick.bind(this),handleKeydown:this.handleKeydown.bind(this),handleFullscreenChange:this.handleFullscreenChange.bind(this),handleZoomoraClick:this.handleZoomoraClick.bind(this),handleContentClick:this.handleContentClick.bind(this),handleMouseDown:this.handleMouseDown.bind(this),handleMouseMove:this.handleMouseMove.bind(this),handleMouseUp:this.handleMouseUp.bind(this),handleTouchStart:this.handleTouchStart.bind(this),handleTouchMove:this.handleTouchMove.bind(this),handleTouchEnd:this.handleTouchEnd.bind(this)},this.init()}init(){if(!this.isInitialized)try{this.createLightbox(),this.bindEvents(),this.isInitialized=!0}catch(t){}}static bind(e,s={}){const o=(a=d({},s),i(a,n({selector:e,useHref:!0})));var a;return new t(o)}createLightbox(){if(document.getElementById("zoomoraLightbox"))return;const t=`\n <div class="zoomora" id="zoomoraLightbox">\n <div class="zoomora-container">\n <div class="zoomora-header" id="zoomoraHeader">\n <div class="zoomora-counter" id="zoomoraCounter">1 / 1</div>\n <div class="zoomora-controls">\n <button class="zoomora-btn" id="zoomoraThumbnailBtn" title="Toggle Thumbnails">\n <i class="zoomorai-thumbnails"></i>\n </button>\n ${this.options.showAutoHideToggle?'\n <button class="zoomora-btn" id="zoomoraAutoHideBtn" title="Toggle Auto-Hide Controls">\n <i class="zoomorai-controls-off"></i>\n </button>\n ':""}\n <button class="zoomora-btn" id="zoomoraZoomBtn" title="Zoom">\n <i class="zoomorai-zoom"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraFullscreenBtn" title="Fullscreen">\n <i class="zoomorai-expand"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraCollapseBtn" title="Exit Fullscreen" style="display: none;">\n <i class="zoomorai-collapse"></i>\n </button>\n <button class="zoomora-btn" id="zoomoraCloseBtn" title="Close">\n <i class="zoomorai-close"></i>\n </button>\n </div>\n </div>\n \n <div class="zoomora-content" id="zoomoraContent">\n <div class="zoomora-loading" id="zoomoraLoading"></div>\n <div class="zoomora-slides-container" id="zoomoraSlidesContainer"></div>\n </div>\n \n <button class="zoomora-nav prev" id="zoomoraPrevBtn">\n <i class="zoomorai-arrow-left"></i>\n </button>\n <button class="zoomora-nav next" id="zoomoraNextBtn">\n <i class="zoomorai-arrow-right"></i>\n </button>\n \n <div class="zoomora-caption" id="zoomoraCaption"></div>\n <div class="zoomora-thumbnails" id="zoomoraThumbs"></div>\n </div>\n </div>\n `;if(document.body.insertAdjacentHTML("beforeend",t),this.zoomora=document.getElementById("zoomoraLightbox"),this.header=document.getElementById("zoomoraHeader"),this.content=document.getElementById("zoomoraContent"),this.slidesContainer=document.getElementById("zoomoraSlidesContainer"),this.counter=document.getElementById("zoomoraCounter"),this.thumbs=document.getElementById("zoomoraThumbs"),this.loading=document.getElementById("zoomoraLoading"),this.caption=document.getElementById("zoomoraCaption"),this.prevBtn=document.getElementById("zoomoraPrevBtn"),this.nextBtn=document.getElementById("zoomoraNextBtn"),!(this.zoomora&&this.content&&this.counter&&this.thumbs&&this.loading&&this.caption))throw new Error("Failed to create required DOM elements")}bindEvents(){this.addEventListener(document,"click",this.boundMethods.handleDocumentClick),this.addEventListener(document.getElementById("zoomoraCloseBtn"),"click",()=>this.close()),this.addEventListener(document.getElementById("zoomoraPrevBtn"),"click",()=>this.prev()),this.addEventListener(document.getElementById("zoomoraNextBtn"),"click",()=>this.next()),this.addEventListener(document.getElementById("zoomoraZoomBtn"),"click",()=>this.toggleZoom()),this.addEventListener(document.getElementById("zoomoraFullscreenBtn"),"click",()=>this.toggleFullscreen()),this.addEventListener(document.getElementById("zoomoraCollapseBtn"),"click",()=>this.exitFullscreen()),this.addEventListener(document.getElementById("zoomoraThumbnailBtn"),"click",()=>this.toggleThumbnails()),this.addEventListener(document,"fullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"webkitfullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"mozfullscreenchange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"MSFullscreenChange",this.boundMethods.handleFullscreenChange),this.addEventListener(document,"keydown",this.boundMethods.handleKeydown),this.addEventListener(this.zoomora,"click",this.boundMethods.handleZoomoraClick),this.addEventListener(this.content,"click",this.boundMethods.handleContentClick),this.addEventListener(this.content,"mousedown",this.boundMethods.handleMouseDown),this.addEventListener(this.content,"mousemove",this.boundMethods.handleMouseMove),this.addEventListener(this.content,"mouseup",this.boundMethods.handleMouseUp),this.addEventListener(this.content,"mouseleave",this.boundMethods.handleMouseUp),this.addEventListener(this.content,"touchstart",this.boundMethods.handleTouchStart,{passive:!1}),this.addEventListener(this.content,"touchmove",this.boundMethods.handleTouchMove,{passive:!1}),this.addEventListener(this.content,"touchend",this.boundMethods.handleTouchEnd),this.options.showAutoHideToggle&&(this.addEventListener(document.getElementById("zoomoraAutoHideBtn"),"click",()=>this.toggleAutoHide()),this.addEventListener(this.zoomora,"mousemove",()=>this.handleUserActivity()),this.addEventListener(this.zoomora,"touchstart",()=>this.handleUserActivity()),this.addEventListener(this.zoomora,"keydown",()=>this.handleUserActivity()))}addEventListener(t,e,s,i={}){if(!t)return;t.addEventListener(e,s,i);const n=`${t.constructor.name}_${e}`;this.eventListeners.has(n)||this.eventListeners.set(n,[]),this.eventListeners.get(n).push({element:t,event:e,handler:s,options:i})}handleDocumentClick(t){const e=t.target.closest(this.options.selector);e&&(t.preventDefault(),this.open(e))}handleKeydown(t){if(this.zoomora.classList.contains("active"))switch(t.key){case"Escape":this.isFullscreen?this.exitFullscreen():this.close();break;case"ArrowLeft":this.prev();break;case"ArrowRight":this.next();break;case"z":case"Z":this.toggleZoom();break;case"f":case"F":this.toggleFullscreen();break;case"t":case"T":this.toggleThumbnails()}}handleFullscreenChange(){!(document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement)&&this.isFullscreen&&(this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons())}handleZoomoraClick(t){t.target===this.zoomora&&this.close()}handleContentClick(t){if(Date.now()-this.lastDragTime<200)return;const e=t.target.closest(".zoomora-media");e&&!e.classList.contains("no-zoom")&&this.toggleZoom()}handleMouseDown(t){this.startDrag(t)}handleMouseMove(t){this.drag(t)}handleMouseUp(){this.endDrag()}handleTouchStart(t){this.startDrag(t)}handleTouchMove(t){this.drag(t)}handleTouchEnd(){this.endDrag()}getImageSource(t){const e=t.dataset.src||t.src||t.getAttribute("src");return"video"===(t.dataset.type||"image")&&e?this.convertToEmbedUrl(e):e}convertToEmbedUrl(t){if(t.includes("youtube.com/embed/"))return t;let e=null,s=null;if(t.includes("youtube.com/watch")){const i=new URLSearchParams(t.split("?")[1]);e=i.get("v");const n=i.get("t");n&&(s=n.replace("s",""))}else if(t.includes("youtu.be/")){const i=t.split("/"),n=i[i.length-1];if(n.includes("?")){e=n.split("?")[0];const t=new URLSearchParams(n.split("?")[1]).get("t");t&&(s=t.replace("s",""))}else e=n}if(e){let t=`https://www.youtube.com/embed/${e}`;const i=new URLSearchParams;return s&&i.append("start",s),i.append("rel","0"),i.append("modestbranding","1"),i.toString()&&(t+="?"+i.toString()),t}return t}getThumbnailSource(t){return"video"===(t.dataset.type||"image")?t.src||t.getAttribute("src"):t.dataset.src||t.src||t.getAttribute("src")}getGroup(t){return this.options.useHref?t.dataset.lightbox||t.dataset.gallery||"default":t.dataset.zoomora||"default"}open(t){if(!t)return;const e=this.getGroup(t);let s;s=this.options.useHref?t.dataset.lightbox?`[data-lightbox="${e}"]`:t.dataset.gallery?`[data-gallery="${e}"]`:this.options.selector:`[data-zoomora="${e}"]`,this.items=Array.from(document.querySelectorAll(s)),this.currentIndex=Math.max(0,this.items.indexOf(t)),this.isZoomed=!1,this.isFullscreen=!1,this.thumbnailsVisible=!0,this.currentX=0,this.currentY=0,this.currentScale=1,this.zoomora.classList.add("active"),document.body.style.overflow="hidden",this.loadContent(),this.updateThumbnails(),this.updateCounter(),this.updateNavigation(),this.updateCaption(),this.updateButtons(),this.autoHideEnabled?this.startAutoHideTimer():this.showControls(),"function"==typeof this.options.onOpen&&this.options.onOpen(t,this.currentIndex)}close(){this.isFullscreen&&this.exitFullscreen(),this.zoomora.classList.remove("active"),document.body.style.overflow="",this.isZoomed=!1,this.isFullscreen=!1,this.currentX=0,this.currentY=0,this.currentScale=1;const t=this.content.querySelector(".zoomora-media");t&&(t.classList.remove("zoomed"),t.style.transform="",t.style.cursor=""),this.zoomora.classList.remove("fullscreen"),this.updateButtons(),this.stopAutoHideTimer(),this.showControls(),"function"==typeof this.options.onClose&&this.options.onClose(this.currentIndex)}prev(){this.currentIndex>0&&(this.currentIndex--,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption(),"function"==typeof this.options.onPrev&&this.options.onPrev(this.currentIndex))}next(){this.currentIndex<this.items.length-1&&(this.currentIndex++,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption(),"function"==typeof this.options.onNext&&this.options.onNext(this.currentIndex))}loadContent(){if(!this.items[this.currentIndex])return;const t=this.items[this.currentIndex],e=this.getImageSource(t),s=t.dataset.type||"image";e&&(this.isZoomed=!1,this.currentX=0,this.currentY=0,this.currentScale=1,this.loading.style.display="block",this.slidesContainer&&(this.slidesContainer.innerHTML=""),setTimeout(()=>{this.renderContent(e,s,t)},100))}renderContent(t,e,s){const i=document.createElement("div");i.className="zoomora-slide-container";const n=document.createElement("div");let o;n.className="zoomora-slide "+("slide"===this.options.transition?"slide-effect":"fade-effect"),n.style.opacity="0",n.style.transform="slide"===this.options.transition?"translateX(100%)":"scale(0.8)";try{switch(e){case"video":if(t.endsWith(".mp4")||t.endsWith(".webm")||t.endsWith(".ogg")){const e=document.createElement("div");e.className="zoomora-video-container",o=document.createElement("video"),o.src=t,o.className="zoomora-video",o.setAttribute("preload","metadata");const n=s.src||s.getAttribute("src");n&&o.setAttribute("poster",n);const a=document.createElement("div");a.className="zoomora-play-button",a.innerHTML='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>',a.addEventListener("click",()=>{o.play(),a.style.display="none",o.setAttribute("controls","")}),o.addEventListener("ended",()=>{a.style.display="flex"}),e.appendChild(o),e.appendChild(a),i.appendChild(e)}else o=document.createElement("iframe"),o.src=t,o.className="zoomora-video",o.setAttribute("allowfullscreen",""),o.setAttribute("frameborder","0"),i.appendChild(o);break;case"iframe":o=document.createElement("iframe"),o.src=t,o.className="zoomora-iframe",o.setAttribute("frameborder","0"),i.appendChild(o);break;default:o=document.createElement("img"),o.src=t,o.className="zoomora-media",o.alt=s.alt||s.title||"",o.onload=()=>{this.loading.style.display="none",this.checkZoomability(o),this.animateSlideIn(n)},o.onerror=()=>{this.loading.style.display="none",this.animateSlideIn(n)},i.appendChild(o)}n.appendChild(i),this.slidesContainer.innerHTML="",this.slidesContainer.appendChild(n),"image"!==e&&(this.loading.style.display="none",this.animateSlideIn(n))}catch(t){this.loading.style.display="none"}}animateSlideIn(t){t.offsetHeight,t.classList.add("active"),"slide"===this.options.transition?(t.style.transition=`transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`,t.style.transform="translateX(0)",t.style.opacity="1"):(t.style.transition=`transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`,t.style.transform="scale(1)",t.style.opacity="1")}toggleAutoHide(){this.autoHideEnabled=!this.autoHideEnabled;const t=document.getElementById("zoomoraAutoHideBtn");this.autoHideEnabled?(t.classList.add("active"),t.title="Disable Auto-Hide Controls",this.startAutoHideTimer()):(t.classList.remove("active"),t.title="Enable Auto-Hide Controls",this.stopAutoHideTimer(),this.showControls())}handleUserActivity(){this.autoHideEnabled&&(this.showControls(),this.startAutoHideTimer())}startAutoHideTimer(){this.stopAutoHideTimer(),this.autoHideTimeout=setTimeout(()=>{this.hideControls()},this.options.autoHideDelay)}stopAutoHideTimer(){this.autoHideTimeout&&(clearTimeout(this.autoHideTimeout),this.autoHideTimeout=null)}showControls(){this.isControlsVisible||(this.isControlsVisible=!0,this.zoomora.classList.remove("controls-hidden"),this.header&&(this.header.style.transform="translateY(0)",this.header.style.opacity="1"),this.caption&&(this.caption.style.transform="translateX(-50%) translateY(0)",this.caption.style.opacity="1"),this.thumbs&&(this.thumbs.style.transform="translateX(-50%) translateY(0)",this.thumbs.style.opacity="1"),this.prevBtn&&(this.prevBtn.style.transform="translateX(0)",this.prevBtn.style.opacity="1"),this.nextBtn&&(this.nextBtn.style.transform="translateX(0)",this.nextBtn.style.opacity="1"))}hideControls(){this.isControlsVisible&&(this.isControlsVisible=!1,this.zoomora.classList.add("controls-hidden"),this.header&&(this.header.style.transform="translateY(-100%)",this.header.style.opacity="0"),this.caption&&(this.caption.style.transform="translateX(-50%) translateY(100%)",this.caption.style.opacity="0"),this.thumbs&&(this.thumbs.style.transform="translateX(-50%) translateY(100%)",this.thumbs.style.opacity="0"),this.prevBtn&&(this.prevBtn.style.transform="translateX(-100%)",this.prevBtn.style.opacity="0"),this.nextBtn&&(this.nextBtn.style.transform="translateX(100%)",this.nextBtn.style.opacity="0"))}checkZoomability(t){if(!t||!t.naturalWidth||!t.naturalHeight)return;const e=t.getBoundingClientRect(),s=e.width,i=e.height,n=t.naturalWidth,o=t.naturalHeight,a=n>s||o>i,r=n/s,l=o/i,h=Math.max(r,l);t.dataset.zoomRatio=h,t.dataset.naturalWidth=n,t.dataset.naturalHeight=o,t.dataset.renderedWidth=s,t.dataset.renderedHeight=i,a&&h>1.1?t.classList.remove("no-zoom"):t.classList.add("no-zoom")}calculateZoomLevels(t){if(!t||!t.naturalWidth||!t.naturalHeight)return{canZoom:!1,levels:[],currentLevel:0};const e=this.content.getBoundingClientRect(),s=e.width,i=e.height,n=t.naturalWidth,o=t.naturalHeight,a=s/n,r=i/o,l=Math.min(a,r);if(l>=.95)return{canZoom:!1,levels:[],currentLevel:0};const h=[1];1.5*l<=1&&h.push(1.5),2*l<=1&&h.push(2),3*l<=1&&h.push(3);const d=1/l;return d>h[h.length-1]&&h.push(d),{canZoom:h.length>1,levels:h,currentLevel:0,baseScale:l,naturalWidth:n,naturalHeight:o}}updateCounter(){this.options.showCounter&&this.counter&&(this.counter.textContent=`${this.currentIndex+1} / ${this.items.length}`)}updateCaption(){if(!this.caption||!this.items[this.currentIndex])return;const t=this.items[this.currentIndex],e=t.dataset.caption||t.title||"";e?(this.caption.textContent=e,this.caption.style.transform="translateX(-50%) translateY(0)",this.caption.style.opacity="1",this.caption.style.pointerEvents="auto",this.caption.style.transition="opacity 0.3s ease, transform 0.3s ease"):(this.caption.style.transform="translateX(-50%) translateY(100%)",this.caption.style.opacity="0",this.caption.style.pointerEvents="none",this.caption.style.transition="opacity 0.3s ease, transform 0.3s ease")}updateThumbnails(){if(this.options.showThumbnails&&this.thumbs){if(1===this.items.length)return this.caption.classList.add("single-item-thumbnail"),void(this.thumbs.style.display="none");this.caption.classList.remove("single-item-thumbnail"),this.thumbs.style.display="flex",this.thumbs.innerHTML="",this.items.forEach((t,e)=>{const s=document.createElement("div");s.className="zoomora-thumb",e===this.currentIndex&&s.classList.add("active");const i=document.createElement("img"),n=this.getThumbnailSource(t);n&&(i.src=n,i.alt=t.alt||t.title||"",i.onerror=()=>{s.style.display="none"}),s.appendChild(i),s.addEventListener("click",()=>{this.currentIndex=e,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption()}),this.thumbs.appendChild(s)})}}updateNavigation(){const t=document.getElementById("zoomoraPrevBtn"),e=document.getElementById("zoomoraNextBtn");t&&(t.style.display=this.currentIndex>0?"flex":"none"),e&&(e.style.display=this.currentIndex<this.items.length-1?"flex":"none")}updateButtons(){const t=document.getElementById("zoomoraFullscreenBtn"),e=document.getElementById("zoomoraCollapseBtn");t&&e&&(this.isFullscreen?(t.style.display="none",e.style.display="flex"):(t.style.display="flex",e.style.display="none"))}toggleZoom(){const t=this.content.querySelector(".zoomora-media");if(!t||"IMG"!==t.tagName)return;const e=this.calculateZoomLevels(t);if(!e.canZoom)return;t.dataset.zoomLevel||(t.dataset.zoomLevel="0");let s=parseInt(t.dataset.zoomLevel)||0;s++,s>=e.levels.length&&(s=0);const i=e.levels[s];t.dataset.zoomLevel=s.toString(),0===s?(this.isZoomed=!1,this.isDragging=!1,t.classList.remove("dragging"),t.style.transform="",t.style.cursor="pointer",t.classList.remove("zoomed"),this.currentX=0,this.currentY=0,this.currentScale=1):(this.isZoomed=!0,this.currentScale=i,this.currentX=0,this.currentY=0,t.style.transform=`translate(0px, 0px) scale(${i})`,t.style.cursor="grab",t.classList.add("zoomed"))}updateImageTransform(t){if(t)if(1===this.currentScale)t.style.transform="";else{const e=this.currentX/this.currentScale,s=this.currentY/this.currentScale;t.style.transform=`scale(${this.currentScale}) translate(${e}px, ${s}px)`}}toggleFullscreen(){this.isFullscreen?this.exitFullscreen():this.enterFullscreen()}enterFullscreen(){const t=this.zoomora,e=t.requestFullscreen||t.webkitRequestFullscreen||t.mozRequestFullScreen||t.msRequestFullscreen;e?e.call(t).then(()=>{this.isFullscreen=!0,this.zoomora.classList.add("fullscreen"),this.updateButtons()}).catch(t=>{this.fallbackFullscreen()}):this.fallbackFullscreen()}exitFullscreen(){if(document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement){const t=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;t?t.call(document).then(()=>{this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons()}).catch(t=>{this.fallbackExitFullscreen()}):this.fallbackExitFullscreen()}else this.fallbackExitFullscreen()}fallbackFullscreen(){this.isFullscreen=!0,this.zoomora.classList.add("fullscreen"),this.updateButtons()}fallbackExitFullscreen(){this.isFullscreen=!1,this.zoomora.classList.remove("fullscreen"),this.updateButtons()}toggleThumbnails(){if(1!==this.items.length&&(this.thumbnailsVisible=!this.thumbnailsVisible,this.thumbs)){if(this.thumbs.classList.toggle("thumbs-hidden",!this.thumbnailsVisible),!this.caption||!this.items[this.currentIndex])return;const t=this.items[this.currentIndex];(t.dataset.caption||t.title)&&this.thumbs.classList.contains("thumbs-hidden")?(this.caption.style.bottom="20px",this.caption.style.transition="bottom 0.3s ease, transform 0.3s ease"):this.caption.style.bottom="120px"}}startDrag(t){const e=this.content.querySelector(".zoomora-media");if(!e||!this.isZoomed)return;this.isDragging=!0,e.classList.add("dragging"),e.style.cursor="grabbing",this.startX=t.clientX||t.touches&&t.touches[0].clientX||0,this.startY=t.clientY||t.touches&&t.touches[0].clientY||0;const s=window.getComputedStyle(e).transform;if(s&&"none"!==s){const t=new DOMMatrix(s);this.currentX=t.m41,this.currentY=t.m42}else this.currentX=0,this.currentY=0;t.preventDefault()}drag(t){if(!this.isDragging)return;t.preventDefault();const e=this.content.querySelector(".zoomora-media");if(!e)return;const s=t.clientX||t.touches&&t.touches[0].clientX||0,i=t.clientY||t.touches&&t.touches[0].clientY||0,n=s-this.startX,o=i-this.startY;let a=this.currentX+n,r=this.currentY+o;const l=this.content.getBoundingClientRect(),h=e.getBoundingClientRect(),d=Math.max(0,(h.width-l.width)/2),c=Math.max(0,(h.height-l.height)/2);a=d>0?Math.max(-d,Math.min(d,a)):0,r=c>0?Math.max(-c,Math.min(c,r)):0,e.style.transform=`translate(${a}px, ${r}px) scale(${this.currentScale})`,this.startX=s,this.startY=i,this.currentX=a,this.currentY=r}endDrag(){if(!this.isDragging)return;this.isDragging=!1,this.lastDragTime=Date.now();const t=this.content.querySelector(".zoomora-media");t&&(t.classList.remove("dragging"),this.isZoomed&&(t.style.cursor="grab"))}goTo(t){t<0||t>=this.items.length||(this.currentIndex=t,this.loadContent(),this.updateCounter(),this.updateThumbnails(),this.updateNavigation(),this.updateCaption())}getCurrentIndex(){return this.currentIndex}getTotalItems(){return this.items.length}isOpen(){return this.zoomora&&this.zoomora.classList.contains("active")}updateOptions(t){this.options=d(d({},this.options),t)}refresh(){if(this.isOpen()){const t=this.items[this.currentIndex];t&&this.open(t)}}destroy(){this.isInitialized&&(this.isOpen()&&this.close(),this.stopAutoHideTimer(),this.eventListeners.forEach((t,e)=>{t.forEach(({element:t,event:e,handler:s,options:i})=>{t&&t.removeEventListener&&t.removeEventListener(e,s,i)})}),this.eventListeners.clear(),this.zoomora&&this.zoomora.parentNode&&this.zoomora.parentNode.removeChild(this.zoomora),this.isInitialized=!1,this.items=[],this.currentIndex=0,this.zoomora=null,this.content=null,this.counter=null,this.thumbs=null,this.loading=null,this.caption=null)}}return t},"object"==typeof e&&"object"==typeof e.exports?e.exports=o():"function"==typeof define&&define.amd?define(o):s.Zoomora=o()}},function(){return e||(0,t[o(t)[0]])((e={exports:{}}).exports,e),e.exports});export default c();
10
10
  //# sourceMappingURL=zoomora.es.min.js.map