vidply 1.0.8 → 1.0.9

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,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/renderers/HTML5Renderer.js", "../src/index.js", "../src/utils/EventEmitter.js", "../src/utils/DOMUtils.js", "../src/i18n/translations.js", "../src/i18n/i18n.js", "../src/utils/TimeUtils.js", "../src/icons/Icons.js", "../src/controls/ControlBar.js", "../src/utils/StorageManager.js", "../src/controls/CaptionManager.js", "../src/controls/KeyboardManager.js", "../src/controls/TranscriptManager.js", "../src/core/Player.js", "../src/renderers/YouTubeRenderer.js", "../src/renderers/VimeoRenderer.js", "../src/renderers/HLSRenderer.js", "../src/features/PlaylistManager.js"],
4
- "sourcesContent": ["/**\r\n * HTML5 Media Renderer\r\n */\r\n\r\nexport class HTML5Renderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n }\r\n\r\n async init() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n this.attachEvents();\r\n \r\n // Set preload\r\n this.media.preload = this.player.options.preload;\r\n \r\n // Load media\r\n this.media.load();\r\n }\r\n\r\n attachEvents() {\r\n // Playback events\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n \r\n // Pause other players if enabled\r\n if (this.player.options.pauseOthersOnPlay) {\r\n this.pauseOtherPlayers();\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n // Handle loop\r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n \r\n if (this.player.options.onVolumeChange) {\r\n this.player.options.onVolumeChange.call(this.player, this.media.volume);\r\n }\r\n });\r\n\r\n this.media.addEventListener('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.media.addEventListener('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('progress', () => {\r\n if (this.media.buffered.length > 0) {\r\n const buffered = this.media.buffered.end(this.media.buffered.length - 1);\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n\r\n this.media.addEventListener('error', (e) => {\r\n this.player.handleError(this.media.error);\r\n });\r\n\r\n this.media.addEventListener('ratechange', () => {\r\n this.player.state.playbackSpeed = this.media.playbackRate;\r\n this.player.emit('ratechange', this.media.playbackRate);\r\n });\r\n }\r\n\r\n pauseOtherPlayers() {\r\n // Pause other VidPly instances\r\n const allPlayers = document.querySelectorAll('.vidply-player');\r\n allPlayers.forEach(playerEl => {\r\n if (playerEl !== this.player.container) {\r\n const video = playerEl.querySelector('video, audio');\r\n if (video && !video.paused) {\r\n video.pause();\r\n }\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n const promise = this.media.play();\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n \r\n // If autoplay failed, try muted autoplay\r\n if (this.player.options.autoplay && !this.player.state.muted) {\r\n this.player.log('Retrying play with muted audio', 'info');\r\n this.media.muted = true;\r\n this.media.play().catch(err => {\r\n this.player.handleError(err);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n /**\r\n * Get available quality levels from source elements\r\n * @returns {Array} Array of quality objects with index, height, width, and src\r\n */\r\n getQualities() {\r\n const sources = Array.from(this.media.querySelectorAll('source'));\r\n \r\n if (sources.length <= 1) {\r\n return [];\r\n }\r\n\r\n return sources.map((source, index) => {\r\n // Try to extract quality from data attributes or label\r\n const label = source.getAttribute('data-quality') || source.getAttribute('label') || '';\r\n const height = source.getAttribute('data-height') || this.extractHeightFromLabel(label);\r\n const width = source.getAttribute('data-width') || '';\r\n \r\n return {\r\n index,\r\n height: height ? parseInt(height) : 0,\r\n width: width ? parseInt(width) : 0,\r\n src: source.src,\r\n type: source.type,\r\n name: label || (height ? `${height}p` : `Quality ${index + 1}`)\r\n };\r\n }).filter(q => q.height > 0); // Only return qualities with valid height\r\n }\r\n\r\n /**\r\n * Extract height from quality label (e.g., \"1080p\" -> 1080)\r\n * @param {string} label \r\n * @returns {number}\r\n */\r\n extractHeightFromLabel(label) {\r\n const match = label.match(/(\\d+)p/i);\r\n return match ? parseInt(match[1]) : 0;\r\n }\r\n\r\n /**\r\n * Switch to a specific quality level\r\n * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)\r\n */\r\n switchQuality(qualityIndex) {\r\n const qualities = this.getQualities();\r\n \r\n if (qualityIndex < 0 || qualityIndex >= qualities.length) {\r\n this.player.log('Invalid quality index', 'warn');\r\n return;\r\n }\r\n\r\n const quality = qualities[qualityIndex];\r\n const currentTime = this.media.currentTime;\r\n const wasPlaying = !this.media.paused;\r\n\r\n // Store the current source for comparison\r\n const currentSrc = this.media.currentSrc;\r\n \r\n // Don't switch if already at this quality\r\n if (currentSrc === quality.src) {\r\n this.player.log('Already at this quality level', 'info');\r\n return;\r\n }\r\n\r\n this.player.log(`Switching to quality: ${quality.name}`, 'info');\r\n\r\n // Update the src\r\n this.media.src = quality.src;\r\n \r\n // Wait for the new source to load, then restore playback state\r\n const onLoadedMetadata = () => {\r\n this.media.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n \r\n // Restore playback position\r\n this.media.currentTime = currentTime;\r\n \r\n // Resume playback if it was playing\r\n if (wasPlaying) {\r\n this.media.play().catch(err => {\r\n this.player.log('Failed to resume playback after quality switch', 'warn');\r\n });\r\n }\r\n \r\n // Emit quality change event\r\n this.player.emit('qualitychange', { quality: quality.name, index: qualityIndex });\r\n };\r\n\r\n this.media.addEventListener('loadedmetadata', onLoadedMetadata);\r\n this.media.load();\r\n }\r\n\r\n /**\r\n * Get current quality index\r\n * @returns {number}\r\n */\r\n getCurrentQuality() {\r\n const qualities = this.getQualities();\r\n const currentSrc = this.media.currentSrc;\r\n \r\n for (let i = 0; i < qualities.length; i++) {\r\n if (qualities[i].src === currentSrc) {\r\n return i;\r\n }\r\n }\r\n \r\n return 0; // Default to first quality if not found\r\n }\r\n\r\n destroy() {\r\n // Remove event listeners\r\n this.media.removeEventListener('loadedmetadata', () => {});\r\n this.media.removeEventListener('play', () => {});\r\n this.media.removeEventListener('pause', () => {});\r\n // ... (other listeners would be removed in a real implementation)\r\n }\r\n}\r\n\r\n", "/**\r\n * VidPly - Universal Video Player\r\n * Main Entry Point\r\n */\r\n\r\nimport { Player } from './core/Player.js';\r\nimport { PlaylistManager } from './features/PlaylistManager.js';\r\n\r\n// Auto-initialize players\r\nfunction initializePlayers() {\r\n const elements = document.querySelectorAll('[data-vidply]');\r\n \r\n elements.forEach(element => {\r\n // Parse options from data attribute (JSON format)\r\n const options = element.dataset.vidplyOptions \r\n ? JSON.parse(element.dataset.vidplyOptions)\r\n : {};\r\n \r\n // Parse individual data attributes and merge with options\r\n // This allows for easier HTML-based configuration\r\n const dataOptions = parseDataAttributes(element.dataset);\r\n const mergedOptions = { ...dataOptions, ...options };\r\n \r\n // Create player instance\r\n new Player(element, mergedOptions);\r\n });\r\n}\r\n\r\n// Helper function to parse data attributes into options\r\nfunction parseDataAttributes(dataset) {\r\n const options = {};\r\n \r\n // Map of data attribute names to option keys (camelCase conversion)\r\n const attributeMap = {\r\n // Sign Language\r\n 'signLanguageSrc': 'signLanguageSrc',\r\n 'signLanguageButton': 'signLanguageButton',\r\n 'signLanguagePosition': 'signLanguagePosition',\r\n \r\n // Audio Description\r\n 'audioDescriptionSrc': 'audioDescriptionSrc',\r\n 'audioDescriptionButton': 'audioDescriptionButton',\r\n \r\n // Other common options\r\n 'autoplay': 'autoplay',\r\n 'loop': 'loop',\r\n 'muted': 'muted',\r\n 'controls': 'controls',\r\n 'poster': 'poster',\r\n 'width': 'width',\r\n 'height': 'height',\r\n 'language': 'language',\r\n 'captions': 'captions',\r\n 'captionsDefault': 'captionsDefault',\r\n 'transcript': 'transcript',\r\n 'transcriptButton': 'transcriptButton',\r\n 'keyboard': 'keyboard',\r\n 'responsive': 'responsive',\r\n 'pipButton': 'pipButton',\r\n 'fullscreenButton': 'fullscreenButton'\r\n };\r\n \r\n // Parse each data attribute\r\n Object.keys(attributeMap).forEach(dataKey => {\r\n const optionKey = attributeMap[dataKey];\r\n const value = dataset[dataKey];\r\n \r\n if (value !== undefined) {\r\n // Convert string values to appropriate types\r\n if (value === 'true') {\r\n options[optionKey] = true;\r\n } else if (value === 'false') {\r\n options[optionKey] = false;\r\n } else if (!isNaN(value) && value !== '') {\r\n options[optionKey] = Number(value);\r\n } else {\r\n options[optionKey] = value;\r\n }\r\n }\r\n });\r\n \r\n return options;\r\n}\r\n\r\n// Auto-initialize on DOM ready\r\nif (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initializePlayers);\r\n} else {\r\n initializePlayers();\r\n}\r\n\r\n// Export for manual initialization\r\nexport { Player, PlaylistManager };\r\nexport default Player;\r\n\r\n", "/**\r\n * Simple EventEmitter implementation\r\n */\r\n\r\nexport class EventEmitter {\r\n constructor() {\r\n this.events = {};\r\n }\r\n\r\n on(event, listener) {\r\n if (!this.events[event]) {\r\n this.events[event] = [];\r\n }\r\n this.events[event].push(listener);\r\n return this;\r\n }\r\n\r\n once(event, listener) {\r\n const onceListener = (...args) => {\r\n listener(...args);\r\n this.off(event, onceListener);\r\n };\r\n return this.on(event, onceListener);\r\n }\r\n\r\n off(event, listener) {\r\n if (!this.events[event]) return this;\r\n \r\n if (!listener) {\r\n delete this.events[event];\r\n } else {\r\n this.events[event] = this.events[event].filter(l => l !== listener);\r\n }\r\n \r\n return this;\r\n }\r\n\r\n emit(event, ...args) {\r\n if (!this.events[event]) return this;\r\n \r\n this.events[event].forEach(listener => {\r\n listener(...args);\r\n });\r\n \r\n return this;\r\n }\r\n\r\n removeAllListeners() {\r\n this.events = {};\r\n return this;\r\n }\r\n}\r\n\r\n", "/**\r\n * DOM manipulation utilities\r\n */\r\n\r\nexport const DOMUtils = {\r\n createElement(tag, options = {}) {\r\n const element = document.createElement(tag);\r\n \r\n if (options.className) {\r\n element.className = options.className;\r\n }\r\n \r\n if (options.attributes) {\r\n Object.entries(options.attributes).forEach(([key, value]) => {\r\n element.setAttribute(key, value);\r\n });\r\n }\r\n \r\n if (options.innerHTML) {\r\n element.innerHTML = options.innerHTML;\r\n }\r\n \r\n if (options.textContent) {\r\n element.textContent = options.textContent;\r\n }\r\n \r\n if (options.style) {\r\n Object.assign(element.style, options.style);\r\n }\r\n \r\n if (options.children) {\r\n options.children.forEach(child => {\r\n if (child) element.appendChild(child);\r\n });\r\n }\r\n \r\n return element;\r\n },\r\n\r\n addClass(element, className) {\r\n if (element && className) {\r\n element.classList.add(className);\r\n }\r\n },\r\n\r\n removeClass(element, className) {\r\n if (element && className) {\r\n element.classList.remove(className);\r\n }\r\n },\r\n\r\n toggleClass(element, className) {\r\n if (element && className) {\r\n element.classList.toggle(className);\r\n }\r\n },\r\n\r\n hasClass(element, className) {\r\n return element && element.classList.contains(className);\r\n },\r\n\r\n show(element) {\r\n if (element) {\r\n element.style.display = '';\r\n }\r\n },\r\n\r\n hide(element) {\r\n if (element) {\r\n element.style.display = 'none';\r\n }\r\n },\r\n\r\n fadeIn(element, duration = 300) {\r\n if (!element) return;\r\n \r\n element.style.opacity = '0';\r\n element.style.display = '';\r\n \r\n let start = null;\r\n const animate = (timestamp) => {\r\n if (!start) start = timestamp;\r\n const progress = timestamp - start;\r\n const opacity = Math.min(progress / duration, 1);\r\n \r\n element.style.opacity = opacity;\r\n \r\n if (progress < duration) {\r\n requestAnimationFrame(animate);\r\n }\r\n };\r\n \r\n requestAnimationFrame(animate);\r\n },\r\n\r\n fadeOut(element, duration = 300) {\r\n if (!element) return;\r\n \r\n const startOpacity = parseFloat(getComputedStyle(element).opacity) || 1;\r\n let start = null;\r\n \r\n const animate = (timestamp) => {\r\n if (!start) start = timestamp;\r\n const progress = timestamp - start;\r\n const opacity = Math.max(startOpacity - (progress / duration), 0);\r\n \r\n element.style.opacity = opacity;\r\n \r\n if (progress < duration) {\r\n requestAnimationFrame(animate);\r\n } else {\r\n element.style.display = 'none';\r\n }\r\n };\r\n \r\n requestAnimationFrame(animate);\r\n },\r\n\r\n offset(element) {\r\n if (!element) return { top: 0, left: 0 };\r\n \r\n const rect = element.getBoundingClientRect();\r\n return {\r\n top: rect.top + window.pageYOffset,\r\n left: rect.left + window.pageXOffset,\r\n width: rect.width,\r\n height: rect.height\r\n };\r\n },\r\n\r\n escapeHTML(str) {\r\n const div = document.createElement('div');\r\n div.textContent = str;\r\n return div.innerHTML;\r\n },\r\n\r\n sanitizeHTML(html) {\r\n // Basic HTML sanitization - allow safe tags for VTT captions\r\n // Since we control the HTML (from VTT parsing), we can safely allow these tags\r\n const temp = document.createElement('div');\r\n \r\n // Strip out any potentially dangerous tags/attributes\r\n // Allow: strong, em, u, span, b, i with class and data-voice attributes\r\n const safeHtml = html\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '')\r\n .replace(/on\\w+\\s*=/gi, '') // Remove event handlers\r\n .replace(/javascript:/gi, ''); // Remove javascript: protocol\r\n \r\n temp.innerHTML = safeHtml;\r\n return temp.innerHTML;\r\n }\r\n};\r\n\r\n", "/**\r\n * Translation strings for VidPly\r\n */\r\n\r\nexport const translations = {\r\n en: {\r\n player: {\r\n label: 'Video Player',\r\n play: 'Play',\r\n pause: 'Pause',\r\n stop: 'Stop',\r\n restart: 'Restart from beginning',\r\n rewind: 'Rewind',\r\n forward: 'Forward',\r\n rewindSeconds: 'Rewind {seconds} seconds',\r\n forwardSeconds: 'Forward {seconds} seconds',\r\n previous: 'Previous track',\r\n next: 'Next track',\r\n volume: 'Volume',\r\n mute: 'Mute',\r\n unmute: 'Unmute',\r\n fullscreen: 'Fullscreen',\r\n exitFullscreen: 'Exit Fullscreen',\r\n captions: 'Captions',\r\n chapters: 'Chapters',\r\n quality: 'Quality',\r\n captionStyling: 'Caption styling',\r\n transcript: 'Toggle transcript',\r\n audioDescription: 'Audio description',\r\n signLanguage: 'Sign language video',\r\n settings: 'Settings',\r\n speed: 'Playback Speed',\r\n pip: 'Picture in Picture',\r\n currentTime: 'Current time',\r\n duration: 'Duration',\r\n progress: 'Progress',\r\n seekForward: 'Seek forward {seconds} seconds',\r\n seekBackward: 'Seek backward {seconds} seconds',\r\n volumeUp: 'Volume up',\r\n volumeDown: 'Volume down',\r\n loading: 'Loading...',\r\n loadingChapters: 'Loading chapters...',\r\n error: 'Error loading media',\r\n buffering: 'Buffering...',\r\n signLanguageVideo: 'Sign Language Video',\r\n noChapters: 'No chapters available',\r\n noCaptions: 'No captions available',\r\n auto: 'Auto',\r\n autoQuality: 'Auto (no quality selection available)',\r\n noQuality: 'Quality selection not available',\r\n signLanguageDragResize: 'Sign Language Video - Press D to drag with keyboard, R to resize',\r\n signLanguageDragActive: 'Sign Language Video - Drag mode active. Use arrow keys to move, Escape to exit.',\r\n signLanguageResizeActive: 'Sign Language Video - Resize mode active. Use left/right arrow keys to resize, Escape to exit.',\r\n resizeHandle: 'Resize {direction} corner'\r\n },\r\n captions: {\r\n off: 'Off',\r\n select: 'Select captions',\r\n fontSize: 'Font Size',\r\n fontFamily: 'Font Family',\r\n color: 'Text Color',\r\n backgroundColor: 'Background Color',\r\n opacity: 'Opacity'\r\n },\r\n fontSizes: {\r\n small: 'Small',\r\n normal: 'Normal',\r\n large: 'Large',\r\n xlarge: 'X-Large'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Text Color',\r\n background: 'Background',\r\n font: 'Font',\r\n fontSize: 'Font Size',\r\n opacity: 'Opacity'\r\n },\r\n audioDescription: {\r\n enable: 'Enable audio description',\r\n disable: 'Disable audio description'\r\n },\r\n signLanguage: {\r\n show: 'Show sign language video',\r\n hide: 'Hide sign language video'\r\n },\r\n transcript: {\r\n title: 'Transcript',\r\n close: 'Close transcript',\r\n loading: 'Loading transcript...',\r\n noTranscript: 'No transcript available for this video.',\r\n settings: 'Transcript settings. Press Enter to open menu, or D to enable drag mode',\r\n keyboardDragMode: 'Toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n keyboardDragActive: '\u2328\uFE0F Keyboard Drag Mode Active (Arrow keys to move, Shift+Arrows for large steps, D or ESC to exit)',\r\n resizeWindow: 'Resize Window',\r\n styleTranscript: 'Open transcript style settings',\r\n closeMenu: 'Close Menu',\r\n styleTitle: 'Transcript Style'\r\n },\r\n settings: {\r\n title: 'Settings',\r\n quality: 'Quality',\r\n speed: 'Speed',\r\n captions: 'Captions',\r\n language: 'Language',\r\n reset: 'Reset to defaults',\r\n close: 'Close'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Time display',\r\n durationPrefix: 'Duration: ',\r\n hour: '{count} hour',\r\n hours: '{count} hours',\r\n minute: '{count} minute',\r\n minutes: '{count} minutes',\r\n second: '{count} second',\r\n seconds: '{count} seconds'\r\n }\r\n },\r\n \r\n de: {\r\n player: {\r\n label: 'Videoplayer',\r\n play: 'Abspielen',\r\n pause: 'Pause',\r\n stop: 'Stopp',\r\n restart: 'Von vorne beginnen',\r\n rewind: 'Zur\u00FCckspulen',\r\n forward: 'Vorspulen',\r\n rewindSeconds: '{seconds} Sekunden zur\u00FCckspulen',\r\n forwardSeconds: '{seconds} Sekunden vorspulen',\r\n previous: 'Vorheriger Titel',\r\n next: 'N\u00E4chster Titel',\r\n volume: 'Lautst\u00E4rke',\r\n mute: 'Stumm',\r\n unmute: 'Ton ein',\r\n fullscreen: 'Vollbild',\r\n exitFullscreen: 'Vollbild beenden',\r\n captions: 'Untertitel',\r\n chapters: 'Kapitel',\r\n quality: 'Qualit\u00E4t',\r\n captionStyling: 'Untertitel-Stil',\r\n transcript: 'Transkript umschalten',\r\n audioDescription: 'Audiodeskription',\r\n signLanguage: 'Geb\u00E4rdensprache-Video',\r\n settings: 'Einstellungen',\r\n speed: 'Wiedergabegeschwindigkeit',\r\n pip: 'Bild-in-Bild',\r\n currentTime: 'Aktuelle Zeit',\r\n duration: 'Dauer',\r\n progress: 'Fortschritt',\r\n seekForward: '{seconds} Sekunden vorspulen',\r\n seekBackward: '{seconds} Sekunden zur\u00FCckspulen',\r\n volumeUp: 'Lauter',\r\n volumeDown: 'Leiser',\r\n loading: 'L\u00E4dt...',\r\n loadingChapters: 'Kapitel werden geladen...',\r\n error: 'Fehler beim Laden',\r\n buffering: 'Puffern...',\r\n signLanguageVideo: 'Geb\u00E4rdensprache-Video',\r\n noChapters: 'Keine Kapitel verf\u00FCgbar',\r\n noCaptions: 'Keine Untertitel verf\u00FCgbar',\r\n auto: 'Automatisch',\r\n autoQuality: 'Automatisch (keine Qualit\u00E4tsauswahl verf\u00FCgbar)',\r\n noQuality: 'Qualit\u00E4tsauswahl nicht verf\u00FCgbar',\r\n signLanguageDragResize: 'Geb\u00E4rdensprache-Video - Dr\u00FCcken Sie D zum Verschieben per Tastatur, R zum \u00C4ndern der Gr\u00F6\u00DFe',\r\n signLanguageDragActive: 'Geb\u00E4rdensprache-Video - Verschiebemodus aktiv. Pfeiltasten zum Bewegen, Escape zum Beenden.',\r\n signLanguageResizeActive: 'Geb\u00E4rdensprache-Video - Gr\u00F6\u00DFen\u00E4nderungsmodus aktiv. Links-/Rechts-Pfeiltasten zum \u00C4ndern der Gr\u00F6\u00DFe, Escape zum Beenden.',\r\n resizeHandle: 'Gr\u00F6\u00DFen\u00E4nderung {direction}-Ecke'\r\n },\r\n captions: {\r\n off: 'Aus',\r\n select: 'Untertitel ausw\u00E4hlen',\r\n fontSize: 'Schriftgr\u00F6\u00DFe',\r\n fontFamily: 'Schriftart',\r\n color: 'Textfarbe',\r\n backgroundColor: 'Hintergrundfarbe',\r\n opacity: 'Deckkraft'\r\n },\r\n fontSizes: {\r\n small: 'Klein',\r\n normal: 'Normal',\r\n large: 'Gro\u00DF',\r\n xlarge: 'Sehr gro\u00DF'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Textfarbe',\r\n background: 'Hintergrund',\r\n font: 'Schrift',\r\n fontSize: 'Schriftgr\u00F6\u00DFe',\r\n opacity: 'Deckkraft'\r\n },\r\n audioDescription: {\r\n enable: 'Audiodeskription aktivieren',\r\n disable: 'Audiodeskription deaktivieren'\r\n },\r\n signLanguage: {\r\n show: 'Geb\u00E4rdensprache-Video anzeigen',\r\n hide: 'Geb\u00E4rdensprache-Video ausblenden'\r\n },\r\n transcript: {\r\n title: 'Transkript',\r\n close: 'Transkript schlie\u00DFen',\r\n loading: 'Transkript wird geladen...',\r\n noTranscript: 'Kein Transkript f\u00FCr dieses Video verf\u00FCgbar.',\r\n settings: 'Transkript-Einstellungen. Eingabetaste zum \u00D6ffnen des Men\u00FCs dr\u00FCcken oder D zum Aktivieren des Verschiebemodus',\r\n keyboardDragMode: 'Tastatur-Verschiebemodus mit Pfeiltasten umschalten. Tastenkombination: D-Taste',\r\n keyboardDragActive: '\u2328\uFE0F Tastatur-Verschiebemodus aktiv (Pfeiltasten zum Bewegen, Umschalt+Pfeiltasten f\u00FCr gro\u00DFe Schritte, D oder ESC zum Beenden)',\r\n resizeWindow: 'Fenster vergr\u00F6\u00DFern/verkleinern',\r\n styleTranscript: 'Transkript-Stileinstellungen \u00F6ffnen',\r\n closeMenu: 'Men\u00FC schlie\u00DFen',\r\n styleTitle: 'Transkript-Stil'\r\n },\r\n settings: {\r\n title: 'Einstellungen',\r\n quality: 'Qualit\u00E4t',\r\n speed: 'Geschwindigkeit',\r\n captions: 'Untertitel',\r\n language: 'Sprache',\r\n reset: 'Zur\u00FCcksetzen',\r\n close: 'Schlie\u00DFen'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Zeitanzeige',\r\n durationPrefix: 'Dauer: ',\r\n hour: '{count} Stunde',\r\n hours: '{count} Stunden',\r\n minute: '{count} Minute',\r\n minutes: '{count} Minuten',\r\n second: '{count} Sekunde',\r\n seconds: '{count} Sekunden'\r\n }\r\n },\r\n\r\n es: {\r\n player: {\r\n label: 'Reproductor de video',\r\n play: 'Reproducir',\r\n pause: 'Pausa',\r\n stop: 'Detener',\r\n restart: 'Reiniciar desde el principio',\r\n rewind: 'Retroceder',\r\n forward: 'Avanzar',\r\n rewindSeconds: 'Retroceder {seconds} segundos',\r\n forwardSeconds: 'Avanzar {seconds} segundos',\r\n previous: 'Pista anterior',\r\n next: 'Siguiente pista',\r\n volume: 'Volumen',\r\n mute: 'Silenciar',\r\n unmute: 'Activar sonido',\r\n fullscreen: 'Pantalla completa',\r\n exitFullscreen: 'Salir de pantalla completa',\r\n captions: 'Subt\u00EDtulos',\r\n chapters: 'Cap\u00EDtulos',\r\n quality: 'Calidad',\r\n captionStyling: 'Estilo de subt\u00EDtulos',\r\n transcript: 'Alternar transcripci\u00F3n',\r\n audioDescription: 'Audiodescripci\u00F3n',\r\n signLanguage: 'Video en lengua de se\u00F1as',\r\n settings: 'Configuraci\u00F3n',\r\n speed: 'Velocidad de reproducci\u00F3n',\r\n pip: 'Imagen en imagen',\r\n currentTime: 'Tiempo actual',\r\n duration: 'Duraci\u00F3n',\r\n progress: 'Progreso',\r\n seekForward: 'Avanzar {seconds} segundos',\r\n seekBackward: 'Retroceder {seconds} segundos',\r\n volumeUp: 'Subir volumen',\r\n volumeDown: 'Bajar volumen',\r\n loading: 'Cargando...',\r\n loadingChapters: 'Cargando cap\u00EDtulos...',\r\n error: 'Error al cargar',\r\n buffering: 'Almacenando en b\u00FAfer...',\r\n signLanguageVideo: 'Video en Lengua de Se\u00F1as',\r\n noChapters: 'No hay cap\u00EDtulos disponibles',\r\n noCaptions: 'No hay subt\u00EDtulos disponibles',\r\n auto: 'Autom\u00E1tico',\r\n autoQuality: 'Autom\u00E1tico (selecci\u00F3n de calidad no disponible)',\r\n noQuality: 'Selecci\u00F3n de calidad no disponible',\r\n signLanguageDragResize: 'Video en Lengua de Se\u00F1as - Presione D para arrastrar con el teclado, R para cambiar el tama\u00F1o',\r\n signLanguageDragActive: 'Video en Lengua de Se\u00F1as - Modo de arrastre activo. Use las teclas de flecha para mover, Escape para salir.',\r\n signLanguageResizeActive: 'Video en Lengua de Se\u00F1as - Modo de cambio de tama\u00F1o activo. Use las teclas de flecha izquierda/derecha para cambiar el tama\u00F1o, Escape para salir.',\r\n resizeHandle: 'Cambiar tama\u00F1o esquina {direction}'\r\n },\r\n captions: {\r\n off: 'Desactivado',\r\n select: 'Seleccionar subt\u00EDtulos',\r\n fontSize: 'Tama\u00F1o de fuente',\r\n fontFamily: 'Familia de fuente',\r\n color: 'Color de texto',\r\n backgroundColor: 'Color de fondo',\r\n opacity: 'Opacidad'\r\n },\r\n fontSizes: {\r\n small: 'Peque\u00F1o',\r\n normal: 'Normal',\r\n large: 'Grande',\r\n xlarge: 'Muy grande'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Color de texto',\r\n background: 'Fondo',\r\n font: 'Fuente',\r\n fontSize: 'Tama\u00F1o de fuente',\r\n opacity: 'Opacidad'\r\n },\r\n audioDescription: {\r\n enable: 'Activar audiodescripci\u00F3n',\r\n disable: 'Desactivar audiodescripci\u00F3n'\r\n },\r\n signLanguage: {\r\n show: 'Mostrar video en lengua de se\u00F1as',\r\n hide: 'Ocultar video en lengua de se\u00F1as'\r\n },\r\n transcript: {\r\n title: 'Transcripci\u00F3n',\r\n close: 'Cerrar transcripci\u00F3n',\r\n loading: 'Cargando transcripci\u00F3n...',\r\n noTranscript: 'No hay transcripci\u00F3n disponible para este video.',\r\n settings: 'Configuraci\u00F3n de transcripci\u00F3n. Presione Enter para abrir el men\u00FA o D para activar el modo de arrastre',\r\n keyboardDragMode: 'Alternar modo de arrastre con teclado usando teclas de flecha. Atajo: tecla D',\r\n keyboardDragActive: '\u2328\uFE0F Modo de Arrastre con Teclado Activo (Teclas de flecha para mover, May\u00FAs+Flechas para pasos grandes, D o ESC para salir)',\r\n resizeWindow: 'Cambiar tama\u00F1o de ventana',\r\n styleTranscript: 'Abrir configuraci\u00F3n de estilo de transcripci\u00F3n',\r\n closeMenu: 'Cerrar men\u00FA',\r\n styleTitle: 'Estilo de Transcripci\u00F3n'\r\n },\r\n settings: {\r\n title: 'Configuraci\u00F3n',\r\n quality: 'Calidad',\r\n speed: 'Velocidad',\r\n captions: 'Subt\u00EDtulos',\r\n language: 'Idioma',\r\n reset: 'Restablecer',\r\n close: 'Cerrar'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Visualizaci\u00F3n de tiempo',\r\n durationPrefix: 'Duraci\u00F3n: ',\r\n hour: '{count} hora',\r\n hours: '{count} horas',\r\n minute: '{count} minuto',\r\n minutes: '{count} minutos',\r\n second: '{count} segundo',\r\n seconds: '{count} segundos'\r\n }\r\n },\r\n\r\n fr: {\r\n player: {\r\n label: 'Lecteur vid\u00E9o',\r\n play: 'Lecture',\r\n pause: 'Pause',\r\n stop: 'Arr\u00EAt',\r\n restart: 'Red\u00E9marrer du d\u00E9but',\r\n rewind: 'Reculer',\r\n forward: 'Avancer',\r\n rewindSeconds: 'Reculer de {seconds} secondes',\r\n forwardSeconds: 'Avancer de {seconds} secondes',\r\n previous: 'Piste pr\u00E9c\u00E9dente',\r\n next: 'Piste suivante',\r\n volume: 'Volume',\r\n mute: 'Muet',\r\n unmute: 'Activer le son',\r\n fullscreen: 'Plein \u00E9cran',\r\n exitFullscreen: 'Quitter le plein \u00E9cran',\r\n captions: 'Sous-titres',\r\n chapters: 'Chapitres',\r\n quality: 'Qualit\u00E9',\r\n captionStyling: 'Style des sous-titres',\r\n transcript: 'Activer/d\u00E9sactiver la transcription',\r\n audioDescription: 'Audiodescription',\r\n signLanguage: 'Vid\u00E9o en langue des signes',\r\n settings: 'Param\u00E8tres',\r\n speed: 'Vitesse de lecture',\r\n pip: 'Image dans l\\'image',\r\n currentTime: 'Temps actuel',\r\n duration: 'Dur\u00E9e',\r\n progress: 'Progression',\r\n seekForward: 'Avancer de {seconds} secondes',\r\n seekBackward: 'Reculer de {seconds} secondes',\r\n volumeUp: 'Augmenter le volume',\r\n volumeDown: 'Diminuer le volume',\r\n loading: 'Chargement...',\r\n loadingChapters: 'Chargement des chapitres...',\r\n error: 'Erreur de chargement',\r\n buffering: 'Mise en m\u00E9moire tampon...',\r\n signLanguageVideo: 'Vid\u00E9o en Langue des Signes',\r\n noChapters: 'Aucun chapitre disponible',\r\n noCaptions: 'Aucun sous-titre disponible',\r\n auto: 'Automatique',\r\n autoQuality: 'Automatique (s\u00E9lection de qualit\u00E9 non disponible)',\r\n noQuality: 'S\u00E9lection de qualit\u00E9 non disponible',\r\n signLanguageDragResize: 'Vid\u00E9o en Langue des Signes - Appuyez sur D pour d\u00E9placer avec le clavier, R pour redimensionner',\r\n signLanguageDragActive: 'Vid\u00E9o en Langue des Signes - Mode glissement actif. Utilisez les touches fl\u00E9ch\u00E9es pour d\u00E9placer, \u00C9chap pour quitter.',\r\n signLanguageResizeActive: 'Vid\u00E9o en Langue des Signes - Mode redimensionnement actif. Utilisez les touches fl\u00E9ch\u00E9es gauche/droite pour redimensionner, \u00C9chap pour quitter.',\r\n resizeHandle: 'Redimensionner coin {direction}'\r\n },\r\n captions: {\r\n off: 'D\u00E9sactiv\u00E9',\r\n select: 'S\u00E9lectionner les sous-titres',\r\n fontSize: 'Taille de police',\r\n fontFamily: 'Police',\r\n color: 'Couleur du texte',\r\n backgroundColor: 'Couleur de fond',\r\n opacity: 'Opacit\u00E9'\r\n },\r\n fontSizes: {\r\n small: 'Petit',\r\n normal: 'Normal',\r\n large: 'Grand',\r\n xlarge: 'Tr\u00E8s grand'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Couleur du texte',\r\n background: 'Arri\u00E8re-plan',\r\n font: 'Police',\r\n fontSize: 'Taille de police',\r\n opacity: 'Opacit\u00E9'\r\n },\r\n audioDescription: {\r\n enable: 'Activer l\\'audiodescription',\r\n disable: 'D\u00E9sactiver l\\'audiodescription'\r\n },\r\n signLanguage: {\r\n show: 'Afficher la vid\u00E9o en langue des signes',\r\n hide: 'Masquer la vid\u00E9o en langue des signes'\r\n },\r\n transcript: {\r\n title: 'Transcription',\r\n close: 'Fermer la transcription',\r\n loading: 'Chargement de la transcription...',\r\n noTranscript: 'Aucune transcription disponible pour cette vid\u00E9o.',\r\n settings: 'Param\u00E8tres de transcription. Appuyez sur Entr\u00E9e pour ouvrir le menu ou D pour activer le mode glissement',\r\n keyboardDragMode: 'Basculer le mode glissement avec les touches fl\u00E9ch\u00E9es. Raccourci: touche D',\r\n keyboardDragActive: '\u2328\uFE0F Mode Glissement Clavier Actif (Touches fl\u00E9ch\u00E9es pour d\u00E9placer, Maj+Fl\u00E9ch\u00E9es pour grands pas, D ou \u00C9chap pour quitter)',\r\n resizeWindow: 'Redimensionner la fen\u00EAtre',\r\n styleTranscript: 'Ouvrir les param\u00E8tres de style de transcription',\r\n closeMenu: 'Fermer le menu',\r\n styleTitle: 'Style de Transcription'\r\n },\r\n settings: {\r\n title: 'Param\u00E8tres',\r\n quality: 'Qualit\u00E9',\r\n speed: 'Vitesse',\r\n captions: 'Sous-titres',\r\n language: 'Langue',\r\n reset: 'R\u00E9initialiser',\r\n close: 'Fermer'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Affichage du temps',\r\n durationPrefix: 'Dur\u00E9e : ',\r\n hour: '{count} heure',\r\n hours: '{count} heures',\r\n minute: '{count} minute',\r\n minutes: '{count} minutes',\r\n second: '{count} seconde',\r\n seconds: '{count} secondes'\r\n }\r\n },\r\n\r\n ja: {\r\n player: {\r\n label: '\u30D3\u30C7\u30AA\u30D7\u30EC\u30FC\u30E4\u30FC',\r\n play: '\u518D\u751F',\r\n pause: '\u4E00\u6642\u505C\u6B62',\r\n stop: '\u505C\u6B62',\r\n restart: '\u6700\u521D\u304B\u3089\u518D\u751F',\r\n rewind: '\u5DFB\u304D\u623B\u3057',\r\n forward: '\u65E9\u9001\u308A',\r\n rewindSeconds: '{seconds}\u79D2\u623B\u3059',\r\n forwardSeconds: '{seconds}\u79D2\u9032\u3081\u308B',\r\n previous: '\u524D\u306E\u30C8\u30E9\u30C3\u30AF',\r\n next: '\u6B21\u306E\u30C8\u30E9\u30C3\u30AF',\r\n volume: '\u97F3\u91CF',\r\n mute: '\u30DF\u30E5\u30FC\u30C8',\r\n unmute: '\u30DF\u30E5\u30FC\u30C8\u89E3\u9664',\r\n fullscreen: '\u5168\u753B\u9762\u8868\u793A',\r\n exitFullscreen: '\u5168\u753B\u9762\u8868\u793A\u3092\u7D42\u4E86',\r\n captions: '\u5B57\u5E55',\r\n chapters: '\u30C1\u30E3\u30D7\u30BF\u30FC',\r\n quality: '\u753B\u8CEA',\r\n captionStyling: '\u5B57\u5E55\u30B9\u30BF\u30A4\u30EB',\r\n transcript: '\u6587\u5B57\u8D77\u3053\u3057\u5207\u308A\u66FF\u3048',\r\n audioDescription: '\u97F3\u58F0\u89E3\u8AAC',\r\n signLanguage: '\u624B\u8A71\u52D5\u753B',\r\n settings: '\u8A2D\u5B9A',\r\n speed: '\u518D\u751F\u901F\u5EA6',\r\n pip: '\u30D4\u30AF\u30C1\u30E3\u30FC\u30A4\u30F3\u30D4\u30AF\u30C1\u30E3\u30FC',\r\n currentTime: '\u73FE\u5728\u306E\u6642\u9593',\r\n duration: '\u518D\u751F\u6642\u9593',\r\n progress: '\u9032\u884C\u72B6\u6CC1',\r\n seekForward: '{seconds}\u79D2\u9032\u3081\u308B',\r\n seekBackward: '{seconds}\u79D2\u623B\u3059',\r\n volumeUp: '\u97F3\u91CF\u3092\u4E0A\u3052\u308B',\r\n volumeDown: '\u97F3\u91CF\u3092\u4E0B\u3052\u308B',\r\n loading: '\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n loadingChapters: '\u30C1\u30E3\u30D7\u30BF\u30FC\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n error: '\u8AAD\u307F\u8FBC\u307F\u30A8\u30E9\u30FC',\r\n buffering: '\u30D0\u30C3\u30D5\u30A1\u30EA\u30F3\u30B0\u4E2D...',\r\n signLanguageVideo: '\u624B\u8A71\u52D5\u753B',\r\n noChapters: '\u30C1\u30E3\u30D7\u30BF\u30FC\u304C\u3042\u308A\u307E\u305B\u3093',\r\n noCaptions: '\u5B57\u5E55\u304C\u3042\u308A\u307E\u305B\u3093',\r\n auto: '\u81EA\u52D5',\r\n autoQuality: '\u81EA\u52D5\uFF08\u753B\u8CEA\u9078\u629E\u4E0D\u53EF\uFF09',\r\n noQuality: '\u753B\u8CEA\u9078\u629E\u4E0D\u53EF',\r\n signLanguageDragResize: '\u624B\u8A71\u52D5\u753B - \u30AD\u30FC\u30DC\u30FC\u30C9\u3067\u30C9\u30E9\u30C3\u30B0\u3059\u308B\u306B\u306FD\u30AD\u30FC\u3092\u3001\u30B5\u30A4\u30BA\u5909\u66F4\u3059\u308B\u306B\u306FR\u30AD\u30FC\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044',\r\n signLanguageDragActive: '\u624B\u8A71\u52D5\u753B - \u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u304C\u6709\u52B9\u3067\u3059\u3002\u77E2\u5370\u30AD\u30FC\u3067\u79FB\u52D5\u3001Escape\u3067\u7D42\u4E86\u3057\u307E\u3059\u3002',\r\n signLanguageResizeActive: '\u624B\u8A71\u52D5\u753B - \u30B5\u30A4\u30BA\u5909\u66F4\u30E2\u30FC\u30C9\u304C\u6709\u52B9\u3067\u3059\u3002\u5DE6\u53F3\u306E\u77E2\u5370\u30AD\u30FC\u3067\u30B5\u30A4\u30BA\u5909\u66F4\u3001Escape\u3067\u7D42\u4E86\u3057\u307E\u3059\u3002',\r\n resizeHandle: '{direction}\u30B3\u30FC\u30CA\u30FC\u306E\u30B5\u30A4\u30BA\u5909\u66F4'\r\n },\r\n captions: {\r\n off: '\u30AA\u30D5',\r\n select: '\u5B57\u5E55\u3092\u9078\u629E',\r\n fontSize: '\u30D5\u30A9\u30F3\u30C8\u30B5\u30A4\u30BA',\r\n fontFamily: '\u30D5\u30A9\u30F3\u30C8',\r\n color: '\u30C6\u30AD\u30B9\u30C8\u306E\u8272',\r\n backgroundColor: '\u80CC\u666F\u8272',\r\n opacity: '\u4E0D\u900F\u660E\u5EA6'\r\n },\r\n fontSizes: {\r\n small: '\u5C0F',\r\n normal: '\u6A19\u6E96',\r\n large: '\u5927',\r\n xlarge: '\u7279\u5927'\r\n },\r\n fontFamilies: {\r\n sansSerif: '\u30B5\u30F3\u30BB\u30EA\u30D5',\r\n serif: '\u30BB\u30EA\u30D5',\r\n monospace: '\u7B49\u5E45'\r\n },\r\n styleLabels: {\r\n textColor: '\u30C6\u30AD\u30B9\u30C8\u306E\u8272',\r\n background: '\u80CC\u666F',\r\n font: '\u30D5\u30A9\u30F3\u30C8',\r\n fontSize: '\u30D5\u30A9\u30F3\u30C8\u30B5\u30A4\u30BA',\r\n opacity: '\u4E0D\u900F\u660E\u5EA6'\r\n },\r\n audioDescription: {\r\n enable: '\u97F3\u58F0\u89E3\u8AAC\u3092\u6709\u52B9\u306B\u3059\u308B',\r\n disable: '\u97F3\u58F0\u89E3\u8AAC\u3092\u7121\u52B9\u306B\u3059\u308B'\r\n },\r\n signLanguage: {\r\n show: '\u624B\u8A71\u52D5\u753B\u3092\u8868\u793A',\r\n hide: '\u624B\u8A71\u52D5\u753B\u3092\u975E\u8868\u793A'\r\n },\r\n transcript: {\r\n title: '\u6587\u5B57\u8D77\u3053\u3057',\r\n close: '\u6587\u5B57\u8D77\u3053\u3057\u3092\u9589\u3058\u308B',\r\n loading: '\u6587\u5B57\u8D77\u3053\u3057\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n noTranscript: '\u3053\u306E\u30D3\u30C7\u30AA\u306E\u6587\u5B57\u8D77\u3053\u3057\u306F\u3042\u308A\u307E\u305B\u3093\u3002',\r\n settings: '\u6587\u5B57\u8D77\u3053\u3057\u8A2D\u5B9A\u3002Enter\u30AD\u30FC\u3067\u30E1\u30CB\u30E5\u30FC\u3092\u958B\u304F\u3001\u307E\u305F\u306FD\u30AD\u30FC\u3067\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u3092\u6709\u52B9\u306B\u3059\u308B',\r\n keyboardDragMode: '\u77E2\u5370\u30AD\u30FC\u3067\u30AD\u30FC\u30DC\u30FC\u30C9\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u3092\u5207\u308A\u66FF\u3048\u3002\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\uFF1AD\u30AD\u30FC',\r\n keyboardDragActive: '\u2328\uFE0F \u30AD\u30FC\u30DC\u30FC\u30C9\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u6709\u52B9\uFF08\u77E2\u5370\u30AD\u30FC\u3067\u79FB\u52D5\u3001Shift+\u77E2\u5370\u30AD\u30FC\u3067\u5927\u304D\u304F\u79FB\u52D5\u3001D\u307E\u305F\u306FESC\u3067\u7D42\u4E86\uFF09',\r\n resizeWindow: '\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u30B5\u30A4\u30BA\u5909\u66F4',\r\n styleTranscript: '\u6587\u5B57\u8D77\u3053\u3057\u30B9\u30BF\u30A4\u30EB\u8A2D\u5B9A\u3092\u958B\u304F',\r\n closeMenu: '\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B',\r\n styleTitle: '\u6587\u5B57\u8D77\u3053\u3057\u30B9\u30BF\u30A4\u30EB'\r\n },\r\n settings: {\r\n title: '\u8A2D\u5B9A',\r\n quality: '\u753B\u8CEA',\r\n speed: '\u901F\u5EA6',\r\n captions: '\u5B57\u5E55',\r\n language: '\u8A00\u8A9E',\r\n reset: '\u30EA\u30BB\u30C3\u30C8',\r\n close: '\u9589\u3058\u308B'\r\n },\r\n speeds: {\r\n normal: '\u901A\u5E38'\r\n },\r\n time: {\r\n display: '\u6642\u9593\u8868\u793A',\r\n durationPrefix: '\u518D\u751F\u6642\u9593: ',\r\n hour: '{count}\u6642\u9593',\r\n hours: '{count}\u6642\u9593',\r\n minute: '{count}\u5206',\r\n minutes: '{count}\u5206',\r\n second: '{count}\u79D2',\r\n seconds: '{count}\u79D2'\r\n }\r\n }\r\n};\r\n\r\n", "/**\r\n * Internationalization system\r\n */\r\n\r\nimport { translations } from './translations.js';\r\n\r\nclass I18n {\r\n constructor() {\r\n this.currentLanguage = 'en';\r\n this.translations = translations;\r\n }\r\n\r\n setLanguage(lang) {\r\n if (this.translations[lang]) {\r\n this.currentLanguage = lang;\r\n } else {\r\n console.warn(`Language \"${lang}\" not found, falling back to English`);\r\n this.currentLanguage = 'en';\r\n }\r\n }\r\n\r\n getLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n t(key, replacements = {}) {\r\n const keys = key.split('.');\r\n let value = this.translations[this.currentLanguage];\r\n \r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k];\r\n } else {\r\n // Fallback to English\r\n value = this.translations.en;\r\n for (const fallbackKey of keys) {\r\n if (value && typeof value === 'object' && fallbackKey in value) {\r\n value = value[fallbackKey];\r\n } else {\r\n return key; // Return key if not found\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n \r\n // Replace placeholders\r\n if (typeof value === 'string') {\r\n Object.entries(replacements).forEach(([placeholder, replacement]) => {\r\n value = value.replace(new RegExp(`{${placeholder}}`, 'g'), replacement);\r\n });\r\n }\r\n \r\n return value;\r\n }\r\n\r\n addTranslation(lang, translations) {\r\n if (!this.translations[lang]) {\r\n this.translations[lang] = {};\r\n }\r\n Object.assign(this.translations[lang], translations);\r\n }\r\n}\r\n\r\nexport const i18n = new I18n();\r\n\r\n", "/**\r\n * Time formatting and conversion utilities\r\n */\r\n\r\nimport {i18n} from '../i18n/i18n.js';\r\n\r\nexport const TimeUtils = {\r\n /**\r\n * Format seconds to time string (HH:MM:SS or MM:SS)\r\n */\r\n formatTime(seconds, alwaysShowHours = false) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return alwaysShowHours ? '00:00:00' : '00:00';\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const pad = (num) => String(num).padStart(2, '0');\r\n \r\n if (hours > 0 || alwaysShowHours) {\r\n return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;\r\n }\r\n \r\n return `${pad(minutes)}:${pad(secs)}`;\r\n },\r\n\r\n /**\r\n * Parse time string to seconds\r\n */\r\n parseTime(timeString) {\r\n const parts = timeString.split(':').map(p => parseInt(p, 10));\r\n \r\n if (parts.length === 3) {\r\n // HH:MM:SS\r\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\r\n } else if (parts.length === 2) {\r\n // MM:SS\r\n return parts[0] * 60 + parts[1];\r\n } else if (parts.length === 1) {\r\n // SS\r\n return parts[0];\r\n }\r\n \r\n return 0;\r\n },\r\n\r\n /**\r\n * Format seconds to readable duration\r\n */\r\n formatDuration(seconds) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return i18n.t('time.seconds', { count: 0 });\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const parts = [];\r\n \r\n if (hours > 0) {\r\n const key = hours === 1 ? 'time.hour' : 'time.hours';\r\n parts.push(i18n.t(key, { count: hours }));\r\n }\r\n if (minutes > 0) {\r\n const key = minutes === 1 ? 'time.minute' : 'time.minutes';\r\n parts.push(i18n.t(key, { count: minutes }));\r\n }\r\n if (secs > 0 || parts.length === 0) {\r\n const key = secs === 1 ? 'time.second' : 'time.seconds';\r\n parts.push(i18n.t(key, { count: secs }));\r\n }\r\n \r\n return parts.join(', ');\r\n },\r\n\r\n /**\r\n * Format percentage\r\n */\r\n formatPercentage(value, total) {\r\n if (total === 0) return 0;\r\n return Math.round((value / total) * 100);\r\n }\r\n};\r\n\r\n", "/**\r\n * SVG Icon Library for VidPly\r\n * Optimized with common viewBox and fill attributes\r\n */\r\n\r\n// SVG paths only (viewBox and fill added by wrapper)\r\nconst iconPaths = {\r\n play: `<path d=\"M8 5v14l11-7z\"/>`,\r\n\r\n pause: `<path d=\"M6 4h4v16H6V4zm8 0h4v16h-4V4z\"/>`,\r\n\r\n stop: `<rect x=\"6\" y=\"6\" width=\"12\" height=\"12\"/>`,\r\n\r\n rewind: `<path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\"/>`,\r\n\r\n forward: `<path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\"/>`,\r\n\r\n skipPrevious: `<path d=\"M6 6h2v12H6V6zm3 6l8.5 6V6L9 12z\"/>`,\r\n\r\n skipNext: `<path d=\"M16 6h2v12h-2V6zM6 6l8.5 6L6 18V6z\"/>`,\r\n\r\n restart: `<path d=\"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"/>`,\r\n\r\n volumeHigh: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/>`,\r\n\r\n volumeMedium: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"/>`,\r\n\r\n volumeLow: `<path d=\"M7 9v6h4l5 5V4l-5 5H7z\"/>`,\r\n\r\n volumeMuted: `<path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/>`,\r\n\r\n fullscreen: `<path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/>`,\r\n\r\n fullscreenExit: `<path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/>`,\r\n\r\n settings: `<path d=\"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z\"/>`,\r\n\r\n captions: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/>`,\r\n\r\n captionsOff: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/><path d=\"M0 0h24v24H0z\" fill=\"none\"/>`,\r\n\r\n pip: `<path d=\"M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z\"/>`,\r\n\r\n speed: `<path d=\"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z\"/><path d=\"M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z\"/>`,\r\n\r\n close: `<path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>`,\r\n\r\n check: `<path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>`,\r\n\r\n arrowUp: `<path d=\"M7 14l5-5 5 5z\"/>`,\r\n\r\n arrowDown: `<path d=\"M7 10l5 5 5-5z\"/>`,\r\n\r\n arrowLeft: `<path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/>`,\r\n\r\n arrowRight: `<path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/>`,\r\n\r\n loading: `<path d=\"M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z\"/>`,\r\n\r\n error: `<path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>`,\r\n\r\n download: `<path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"/>`,\r\n\r\n link: `<path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/>`,\r\n\r\n playlist: `<path d=\"M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z\"/>`,\r\n\r\n language: `<path d=\"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z\"/>`,\r\n\r\n hd: `<path d=\"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z\"/>`,\r\n\r\n transcript: `<path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/>`,\r\n\r\n audioDescription: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"currentColor\">AD</text>`,\r\n \r\n audioDescriptionOn: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"#1a1a1a\" stroke=\"#1a1a1a\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"#ffffff\">AD</text>`,\r\n\r\n signLanguage: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n signLanguageOn: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n speaker: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"/>`,\r\n\r\n music: `<path d=\"M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7zm-1.5 16c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\"/>`,\r\n\r\n moreVertical: `<path d=\"M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/>`,\r\n\r\n moreHorizontal: `<path d=\"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/>`,\r\n \r\n move: `<path d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\"/>`,\r\n \r\n resize: `<path d=\"M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v2.5L7 11l3-3.5V10h4V7.5l3 3.5-3 3.5z\"/>`\r\n};\r\n\r\n// Optimized wrapper that adds common SVG attributes\r\nconst svgWrapper = (paths) => `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\">${paths}</svg>`;\r\n\r\n// Export Icons object with SVG wrappers\r\nexport const Icons = Object.fromEntries(\r\n Object.entries(iconPaths).map(([key, value]) => [key, svgWrapper(value)])\r\n);\r\n\r\nexport function getIcon(name) {\r\n return Icons[name] || Icons.play;\r\n}\r\n\r\nexport function createIconElement(name, className = '') {\r\n const wrapper = document.createElement('span');\r\n wrapper.className = `vidply-icon ${className}`.trim();\r\n wrapper.innerHTML = getIcon(name);\r\n wrapper.setAttribute('aria-hidden', 'true');\r\n return wrapper;\r\n}\r\n\r\n/**\r\n * Create the large centered play button overlay (complete SVG)\r\n * @returns {SVGElement} Complete SVG element with circle background and play icon\r\n */\r\nexport function createPlayOverlay() {\r\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\r\n svg.setAttribute('class', 'vidply-play-overlay');\r\n svg.setAttribute('viewBox', '0 0 80 80');\r\n svg.setAttribute('width', '80');\r\n svg.setAttribute('height', '80');\r\n svg.setAttribute('aria-hidden', 'true');\r\n svg.setAttribute('role', 'presentation');\r\n svg.style.cursor = 'pointer';\r\n\r\n // Create filter for drop shadow\r\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\r\n const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;\r\n const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');\r\n filter.setAttribute('id', filterId);\r\n filter.setAttribute('x', '-50%');\r\n filter.setAttribute('y', '-50%');\r\n filter.setAttribute('width', '200%');\r\n filter.setAttribute('height', '200%');\r\n\r\n const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');\r\n feGaussianBlur.setAttribute('in', 'SourceAlpha');\r\n feGaussianBlur.setAttribute('stdDeviation', '3');\r\n\r\n const feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');\r\n feOffset.setAttribute('dx', '0');\r\n feOffset.setAttribute('dy', '2');\r\n feOffset.setAttribute('result', 'offsetblur');\r\n\r\n const feComponentTransfer = document.createElementNS('http://www.w3.org/2000/svg', 'feComponentTransfer');\r\n const feFuncA = document.createElementNS('http://www.w3.org/2000/svg', 'feFuncA');\r\n feFuncA.setAttribute('type', 'linear');\r\n feFuncA.setAttribute('slope', '0.3');\r\n feComponentTransfer.appendChild(feFuncA);\r\n\r\n const feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');\r\n const feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n const feMergeNode2 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n feMergeNode2.setAttribute('in', 'SourceGraphic');\r\n feMerge.appendChild(feMergeNode1);\r\n feMerge.appendChild(feMergeNode2);\r\n\r\n filter.appendChild(feGaussianBlur);\r\n filter.appendChild(feOffset);\r\n filter.appendChild(feComponentTransfer);\r\n filter.appendChild(feMerge);\r\n defs.appendChild(filter);\r\n svg.appendChild(defs);\r\n\r\n // White circle background\r\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n circle.setAttribute('cx', '40');\r\n circle.setAttribute('cy', '40');\r\n circle.setAttribute('r', '40');\r\n circle.setAttribute('fill', 'rgba(255, 255, 255, 0.95)');\r\n circle.setAttribute('filter', `url(#${filterId})`);\r\n circle.setAttribute('class', 'vidply-play-overlay-bg');\r\n svg.appendChild(circle);\r\n\r\n // Play icon triangle (centered with optical adjustment)\r\n const playTriangle = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');\r\n playTriangle.setAttribute('points', '32,28 32,52 54,40');\r\n playTriangle.setAttribute('fill', '#0a406e');\r\n playTriangle.setAttribute('class', 'vidply-play-overlay-icon');\r\n svg.appendChild(playTriangle);\r\n\r\n return svg;\r\n}\r\n\r\n", "/**\r\n * Control Bar Component\r\n */\r\n\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {TimeUtils} from '../utils/TimeUtils.js';\r\nimport {createIconElement} from '../icons/Icons.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\n\r\nexport class ControlBar {\r\n constructor(player) {\r\n this.player = player;\r\n this.element = null;\r\n this.controls = {};\r\n this.hideTimeout = null;\r\n this.isDraggingProgress = false;\r\n this.isDraggingVolume = false;\r\n\r\n this.init();\r\n }\r\n\r\n init() {\r\n this.createElement();\r\n this.createControls();\r\n this.attachEvents();\r\n this.setupAutoHide();\r\n }\r\n\r\n // Helper method to check if we're on a mobile device\r\n isMobile() {\r\n return window.innerWidth < 640;\r\n }\r\n\r\n // Smart menu positioning to avoid overflow\r\n positionMenu(menu, button) {\r\n const isMobile = this.isMobile();\r\n \r\n if (isMobile) {\r\n // Use bottom sheet on mobile - already styled via CSS\r\n return;\r\n }\r\n\r\n // Desktop: Smart positioning\r\n setTimeout(() => {\r\n const buttonRect = button.getBoundingClientRect();\r\n const menuRect = menu.getBoundingClientRect();\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n \r\n const spaceAbove = buttonRect.top;\r\n const spaceBelow = viewportHeight - buttonRect.bottom;\r\n \r\n // Prefer above, but switch to below if not enough space\r\n if (spaceAbove < menuRect.height + 20 && spaceBelow > spaceAbove) {\r\n menu.style.bottom = 'auto';\r\n menu.style.top = 'calc(100% + 8px)';\r\n menu.classList.add('vidply-menu-below');\r\n }\r\n \r\n // Check horizontal overflow\r\n const menuLeft = buttonRect.left + buttonRect.width / 2 - menuRect.width / 2;\r\n if (menuLeft < 10) {\r\n // Too far left, align to left edge\r\n menu.style.right = 'auto';\r\n menu.style.left = '0';\r\n menu.style.transform = 'translateX(0)';\r\n } else if (menuLeft + menuRect.width > viewportWidth - 10) {\r\n // Too far right, align to right edge\r\n menu.style.left = 'auto';\r\n menu.style.right = '0';\r\n menu.style.transform = 'translateX(0)';\r\n }\r\n }, 0);\r\n }\r\n\r\n\r\n // Helper method to attach close-on-outside-click behavior to menus\r\n attachMenuCloseHandler(menu, button, preventCloseOnInteraction = false) {\r\n // Position menu smartly\r\n this.positionMenu(menu, button);\r\n \r\n setTimeout(() => {\r\n const closeMenu = (e) => {\r\n // If this menu has form controls, don't close when clicking inside\r\n if (preventCloseOnInteraction && menu.contains(e.target)) {\r\n return;\r\n }\r\n\r\n // Check if click is outside menu and button\r\n if (!menu.contains(e.target) && !button.contains(e.target)) {\r\n menu.remove();\r\n document.removeEventListener('click', closeMenu);\r\n document.removeEventListener('keydown', handleEscape);\r\n }\r\n };\r\n\r\n const handleEscape = (e) => {\r\n if (e.key === 'Escape') {\r\n menu.remove();\r\n document.removeEventListener('click', closeMenu);\r\n document.removeEventListener('keydown', handleEscape);\r\n // Return focus to button\r\n button.focus();\r\n }\r\n };\r\n\r\n document.addEventListener('click', closeMenu);\r\n document.addEventListener('keydown', handleEscape);\r\n }, 100);\r\n }\r\n\r\n // Helper method to add keyboard navigation to menus (arrow keys)\r\n attachMenuKeyboardNavigation(menu) {\r\n const menuItems = Array.from(menu.querySelectorAll(`.${this.player.options.classPrefix}-menu-item`));\r\n \r\n if (menuItems.length === 0) return;\r\n\r\n const handleKeyDown = (e) => {\r\n const currentIndex = menuItems.indexOf(document.activeElement);\r\n \r\n switch (e.key) {\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n const nextIndex = (currentIndex + 1) % menuItems.length;\r\n menuItems[nextIndex].focus();\r\n break;\r\n \r\n case 'ArrowUp':\r\n e.preventDefault();\r\n const prevIndex = (currentIndex - 1 + menuItems.length) % menuItems.length;\r\n menuItems[prevIndex].focus();\r\n break;\r\n \r\n case 'Home':\r\n e.preventDefault();\r\n menuItems[0].focus();\r\n break;\r\n \r\n case 'End':\r\n e.preventDefault();\r\n menuItems[menuItems.length - 1].focus();\r\n break;\r\n \r\n case 'Enter':\r\n case ' ':\r\n e.preventDefault();\r\n if (document.activeElement && menuItems.includes(document.activeElement)) {\r\n document.activeElement.click();\r\n }\r\n break;\r\n }\r\n };\r\n\r\n menu.addEventListener('keydown', handleKeyDown);\r\n }\r\n\r\n createElement() {\r\n this.element = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls`,\r\n attributes: {\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.label') + ' controls'\r\n }\r\n });\r\n }\r\n\r\n createControls() {\r\n // Progress bar container\r\n if (this.player.options.progressBar) {\r\n this.createProgressBar();\r\n }\r\n\r\n // Button container\r\n const buttonContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-buttons`\r\n });\r\n\r\n // Left buttons\r\n const leftButtons = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-left`\r\n });\r\n\r\n // Previous track button (if playlist)\r\n if (this.player.playlistManager) {\r\n leftButtons.appendChild(this.createPreviousButton());\r\n }\r\n\r\n // Play/Pause button\r\n if (this.player.options.playPauseButton) {\r\n leftButtons.appendChild(this.createPlayPauseButton());\r\n }\r\n\r\n // Restart button (right beside play button)\r\n leftButtons.appendChild(this.createRestartButton());\r\n\r\n // Next track button (if playlist)\r\n if (this.player.playlistManager) {\r\n leftButtons.appendChild(this.createNextButton());\r\n }\r\n\r\n // Rewind button (not shown in playlist mode)\r\n if (!this.player.playlistManager) {\r\n leftButtons.appendChild(this.createRewindButton());\r\n }\r\n\r\n // Forward button (not shown in playlist mode)\r\n if (!this.player.playlistManager) {\r\n leftButtons.appendChild(this.createForwardButton());\r\n }\r\n\r\n // Volume control\r\n if (this.player.options.volumeControl) {\r\n leftButtons.appendChild(this.createVolumeControl());\r\n }\r\n\r\n // Time display\r\n if (this.player.options.currentTime || this.player.options.duration) {\r\n leftButtons.appendChild(this.createTimeDisplay());\r\n }\r\n\r\n // Right buttons\r\n this.rightButtons = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-right`\r\n });\r\n\r\n // Check for available features\r\n const hasChapters = this.hasChapterTracks();\r\n const hasCaptions = this.hasCaptionTracks();\r\n const hasQualityLevels = this.hasQualityLevels();\r\n const hasAudioDescription = this.hasAudioDescription();\r\n\r\n // Chapters button - only show if chapters are available\r\n if (this.player.options.chaptersButton && hasChapters) {\r\n this.rightButtons.appendChild(this.createChaptersButton());\r\n }\r\n\r\n // Quality button - only show if quality levels are available\r\n if (this.player.options.qualityButton && hasQualityLevels) {\r\n this.rightButtons.appendChild(this.createQualityButton());\r\n }\r\n\r\n // Caption styling button (font, size, color) - only show if captions are available\r\n if (this.player.options.captionStyleButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createCaptionStyleButton());\r\n }\r\n\r\n // Speed button - always available\r\n if (this.player.options.speedButton) {\r\n this.rightButtons.appendChild(this.createSpeedButton());\r\n }\r\n\r\n // Captions language selector button - only show if captions are available\r\n if (this.player.options.captionsButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createCaptionsButton());\r\n }\r\n\r\n // Transcript button - only show if captions/subtitles are available\r\n if (this.player.options.transcriptButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createTranscriptButton());\r\n }\r\n\r\n // Audio Description button - only show if audio description source is available\r\n if (this.player.options.audioDescriptionButton && hasAudioDescription) {\r\n this.rightButtons.appendChild(this.createAudioDescriptionButton());\r\n }\r\n\r\n // Sign Language button - only show if sign language source is available\r\n const hasSignLanguage = this.hasSignLanguage();\r\n if (this.player.options.signLanguageButton && hasSignLanguage) {\r\n this.rightButtons.appendChild(this.createSignLanguageButton());\r\n }\r\n\r\n // PiP button\r\n if (this.player.options.pipButton && 'pictureInPictureEnabled' in document) {\r\n this.rightButtons.appendChild(this.createPipButton());\r\n }\r\n\r\n // Fullscreen button\r\n if (this.player.options.fullscreenButton) {\r\n this.rightButtons.appendChild(this.createFullscreenButton());\r\n }\r\n\r\n buttonContainer.appendChild(leftButtons);\r\n buttonContainer.appendChild(this.rightButtons);\r\n this.element.appendChild(buttonContainer);\r\n }\r\n\r\n // Helper methods to check for available features\r\n hasChapterTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n for (let i = 0; i < textTracks.length; i++) {\r\n if (textTracks[i].kind === 'chapters') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n hasCaptionTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n for (let i = 0; i < textTracks.length; i++) {\r\n if (textTracks[i].kind === 'captions' || textTracks[i].kind === 'subtitles') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n hasQualityLevels() {\r\n // Check if renderer supports quality selection\r\n if (this.player.renderer && this.player.renderer.getQualities) {\r\n const qualities = this.player.renderer.getQualities();\r\n return qualities && qualities.length > 1;\r\n }\r\n return false;\r\n }\r\n\r\n hasAudioDescription() {\r\n // Check for audio-described video source OR description tracks\r\n if (this.player.audioDescriptionSrc && this.player.audioDescriptionSrc.length > 0) {\r\n return true;\r\n }\r\n \r\n // Check for description tracks\r\n const textTracks = Array.from(this.player.element.textTracks || []);\r\n return textTracks.some(track => track.kind === 'descriptions');\r\n }\r\n\r\n hasSignLanguage() {\r\n return this.player.signLanguageSrc && this.player.signLanguageSrc.length > 0;\r\n }\r\n\r\n createProgressBar() {\r\n const progressContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-container`,\r\n attributes: {\r\n 'role': 'slider',\r\n 'aria-label': i18n.t('player.progress'),\r\n 'aria-valuemin': '0',\r\n 'aria-valuemax': '100',\r\n 'aria-valuenow': '0',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Buffered progress\r\n this.controls.buffered = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-buffered`\r\n });\r\n\r\n // Played progress\r\n this.controls.played = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-played`\r\n });\r\n\r\n // Progress handle\r\n this.controls.progressHandle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-handle`\r\n });\r\n\r\n // Tooltip\r\n this.controls.progressTooltip = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-tooltip`\r\n });\r\n\r\n progressContainer.appendChild(this.controls.buffered);\r\n progressContainer.appendChild(this.controls.played);\r\n this.controls.played.appendChild(this.controls.progressHandle);\r\n progressContainer.appendChild(this.controls.progressTooltip);\r\n\r\n this.controls.progress = progressContainer;\r\n this.element.appendChild(progressContainer);\r\n\r\n // Progress bar events\r\n this.setupProgressBarEvents();\r\n }\r\n\r\n setupProgressBarEvents() {\r\n const progress = this.controls.progress;\r\n\r\n const updateProgress = (clientX) => {\r\n const rect = progress.getBoundingClientRect();\r\n const percent = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n const time = percent * this.player.state.duration;\r\n return {percent, time};\r\n };\r\n\r\n // Mouse events\r\n progress.addEventListener('mousedown', (e) => {\r\n this.isDraggingProgress = true;\r\n const {time} = updateProgress(e.clientX);\r\n this.player.seek(time);\r\n });\r\n\r\n document.addEventListener('mousemove', (e) => {\r\n if (this.isDraggingProgress) {\r\n const {time} = updateProgress(e.clientX);\r\n this.player.seek(time);\r\n }\r\n });\r\n\r\n document.addEventListener('mouseup', () => {\r\n this.isDraggingProgress = false;\r\n });\r\n\r\n // Hover tooltip\r\n progress.addEventListener('mousemove', (e) => {\r\n if (!this.isDraggingProgress) {\r\n const {time} = updateProgress(e.clientX);\r\n this.controls.progressTooltip.textContent = TimeUtils.formatTime(time);\r\n this.controls.progressTooltip.style.left = `${e.clientX - progress.getBoundingClientRect().left}px`;\r\n this.controls.progressTooltip.style.display = 'block';\r\n }\r\n });\r\n\r\n progress.addEventListener('mouseleave', () => {\r\n this.controls.progressTooltip.style.display = 'none';\r\n });\r\n\r\n // Keyboard navigation\r\n progress.addEventListener('keydown', (e) => {\r\n if (e.key === 'ArrowLeft') {\r\n e.preventDefault();\r\n this.player.seekBackward(5);\r\n } else if (e.key === 'ArrowRight') {\r\n e.preventDefault();\r\n this.player.seekForward(5);\r\n }\r\n });\r\n\r\n // Touch events\r\n progress.addEventListener('touchstart', (e) => {\r\n this.isDraggingProgress = true;\r\n const touch = e.touches[0];\r\n const {time} = updateProgress(touch.clientX);\r\n this.player.seek(time);\r\n });\r\n\r\n progress.addEventListener('touchmove', (e) => {\r\n if (this.isDraggingProgress) {\r\n e.preventDefault();\r\n const touch = e.touches[0];\r\n const {time} = updateProgress(touch.clientX);\r\n this.player.seek(time);\r\n }\r\n });\r\n\r\n progress.addEventListener('touchend', () => {\r\n this.isDraggingProgress = false;\r\n });\r\n }\r\n\r\n createPlayPauseButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-play-pause`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.play')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('play'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggle();\r\n });\r\n\r\n this.controls.playPause = button;\r\n return button;\r\n }\r\n\r\n createRestartButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-restart`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.restart')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('restart'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seek(0);\r\n this.player.play();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createPreviousButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-previous`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.previous')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('skipPrevious'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.playlistManager) {\r\n this.player.playlistManager.previous();\r\n }\r\n });\r\n\r\n // Update button state\r\n const updateState = () => {\r\n if (this.player.playlistManager) {\r\n button.disabled = !this.player.playlistManager.hasPrevious() && !this.player.playlistManager.options.loop;\r\n }\r\n };\r\n this.player.on('playlisttrackchange', updateState);\r\n updateState();\r\n\r\n this.controls.previous = button;\r\n return button;\r\n }\r\n\r\n createNextButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-next`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.next')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('skipNext'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.playlistManager) {\r\n this.player.playlistManager.next();\r\n }\r\n });\r\n\r\n // Update button state\r\n const updateState = () => {\r\n if (this.player.playlistManager) {\r\n button.disabled = !this.player.playlistManager.hasNext() && !this.player.playlistManager.options.loop;\r\n }\r\n };\r\n this.player.on('playlisttrackchange', updateState);\r\n updateState();\r\n\r\n this.controls.next = button;\r\n return button;\r\n }\r\n\r\n createRewindButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-rewind`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.rewindSeconds', { seconds: 15 })\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('rewind'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seekBackward(15);\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createForwardButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-forward`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.forwardSeconds', { seconds: 15 })\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('forward'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seekForward(15);\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createVolumeControl() {\r\n // Mute/Volume button\r\n const muteButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-mute`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.volume'),\r\n 'aria-haspopup': 'true'\r\n }\r\n });\r\n\r\n muteButton.appendChild(createIconElement('volumeHigh'));\r\n\r\n // Toggle mute on right click, show volume slider on left click\r\n muteButton.addEventListener('contextmenu', (e) => {\r\n e.preventDefault();\r\n this.player.toggleMute();\r\n });\r\n\r\n muteButton.addEventListener('click', () => {\r\n this.showVolumeSlider(muteButton);\r\n });\r\n\r\n this.controls.mute = muteButton;\r\n\r\n return muteButton;\r\n }\r\n\r\n showVolumeSlider(button) {\r\n // Remove existing slider if any\r\n const existingSlider = document.querySelector(`.${this.player.options.classPrefix}-volume-menu`);\r\n if (existingSlider) {\r\n existingSlider.remove();\r\n return;\r\n }\r\n\r\n // Volume menu container\r\n const volumeMenu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-menu ${this.player.options.classPrefix}-menu`\r\n });\r\n\r\n const volumeSlider = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-slider`,\r\n attributes: {\r\n 'role': 'slider',\r\n 'aria-label': i18n.t('player.volume'),\r\n 'aria-valuemin': '0',\r\n 'aria-valuemax': '100',\r\n 'aria-valuenow': String(Math.round(this.player.state.volume * 100)),\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n const volumeTrack = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-track`\r\n });\r\n\r\n const volumeFill = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-fill`\r\n });\r\n\r\n const volumeHandle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-handle`\r\n });\r\n\r\n volumeTrack.appendChild(volumeFill);\r\n volumeFill.appendChild(volumeHandle);\r\n volumeSlider.appendChild(volumeTrack);\r\n volumeMenu.appendChild(volumeSlider);\r\n\r\n // Volume slider events\r\n const updateVolume = (clientY) => {\r\n const rect = volumeTrack.getBoundingClientRect();\r\n const percent = Math.max(0, Math.min(1, 1 - ((clientY - rect.top) / rect.height)));\r\n this.player.setVolume(percent);\r\n };\r\n\r\n volumeSlider.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n this.isDraggingVolume = true;\r\n updateVolume(e.clientY);\r\n });\r\n\r\n document.addEventListener('mousemove', (e) => {\r\n if (this.isDraggingVolume) {\r\n updateVolume(e.clientY);\r\n }\r\n });\r\n\r\n document.addEventListener('mouseup', () => {\r\n this.isDraggingVolume = false;\r\n });\r\n\r\n // Keyboard volume control\r\n volumeSlider.addEventListener('keydown', (e) => {\r\n if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n this.player.setVolume(Math.min(1, this.player.state.volume + 0.1));\r\n } else if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n this.player.setVolume(Math.max(0, this.player.state.volume - 0.1));\r\n }\r\n });\r\n\r\n // Prevent menu from closing when interacting with slider\r\n volumeMenu.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n // Append menu to button\r\n button.appendChild(volumeMenu);\r\n\r\n this.controls.volumeSlider = volumeSlider;\r\n this.controls.volumeFill = volumeFill;\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(volumeMenu, button, true);\r\n }\r\n\r\n createTimeDisplay() {\r\n const container = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-time`,\r\n attributes: {\r\n 'role': 'group',\r\n 'aria-label': i18n.t('time.display')\r\n }\r\n });\r\n\r\n // Current time - visual text hidden, only aria-label announced\r\n this.controls.currentTimeDisplay = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-current-time`,\r\n attributes: {\r\n 'aria-label': i18n.t('time.seconds', { count: 0 })\r\n }\r\n });\r\n \r\n // Create visual text inside, hidden from screen readers\r\n const currentTimeVisual = DOMUtils.createElement('span', {\r\n textContent: '00:00',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n this.controls.currentTimeDisplay.appendChild(currentTimeVisual);\r\n this.controls.currentTimeVisual = currentTimeVisual;\r\n\r\n const separator = DOMUtils.createElement('span', {\r\n textContent: ' / ',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n\r\n // Duration - visual text hidden, only aria-label announced\r\n this.controls.durationDisplay = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-duration`,\r\n attributes: {\r\n 'aria-label': i18n.t('time.durationPrefix') + i18n.t('time.seconds', { count: 0 })\r\n }\r\n });\r\n \r\n // Create visual text inside, hidden from screen readers\r\n const durationVisual = DOMUtils.createElement('span', {\r\n textContent: '00:00',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n this.controls.durationDisplay.appendChild(durationVisual);\r\n this.controls.durationVisual = durationVisual;\r\n\r\n container.appendChild(this.controls.currentTimeDisplay);\r\n container.appendChild(separator);\r\n container.appendChild(this.controls.durationDisplay);\r\n\r\n return container;\r\n }\r\n\r\n createChaptersButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-chapters`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.chapters'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('playlist'));\r\n\r\n button.addEventListener('click', () => {\r\n this.showChaptersMenu(button);\r\n });\r\n\r\n this.controls.chapters = button;\r\n return button;\r\n }\r\n\r\n showChaptersMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-chapters-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-chapters-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.chapters')\r\n }\r\n });\r\n\r\n // Get chapter tracks\r\n const chapterTracks = Array.from(this.player.element.textTracks).filter(\r\n track => track.kind === 'chapters'\r\n );\r\n\r\n if (chapterTracks.length === 0) {\r\n // No chapters available\r\n const noChaptersItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noChapters'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noChaptersItem);\r\n } else {\r\n const chapterTrack = chapterTracks[0];\r\n\r\n // Ensure track is in 'hidden' mode to load cues\r\n if (chapterTrack.mode === 'disabled') {\r\n chapterTrack.mode = 'hidden';\r\n }\r\n\r\n if (!chapterTrack.cues || chapterTrack.cues.length === 0) {\r\n // Cues not loaded yet - wait for them to load\r\n const loadingItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.loadingChapters'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(loadingItem);\r\n\r\n // Listen for track load event\r\n const onTrackLoad = () => {\r\n // Remove loading message and rebuild menu\r\n menu.remove();\r\n this.showChaptersMenu(button);\r\n };\r\n\r\n chapterTrack.addEventListener('load', onTrackLoad, {once: true});\r\n\r\n // Also try again after a short delay as fallback\r\n setTimeout(() => {\r\n if (chapterTrack.cues && chapterTrack.cues.length > 0 && document.contains(menu)) {\r\n menu.remove();\r\n this.showChaptersMenu(button);\r\n }\r\n }, 500);\r\n } else {\r\n // Display chapters\r\n const cues = chapterTrack.cues;\r\n for (let i = 0; i < cues.length; i++) {\r\n const cue = cues[i];\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n const timeLabel = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-chapter-time`,\r\n textContent: TimeUtils.formatTime(cue.startTime)\r\n });\r\n\r\n const titleLabel = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-chapter-title`,\r\n textContent: cue.text\r\n });\r\n\r\n item.appendChild(timeLabel);\r\n item.appendChild(document.createTextNode(' '));\r\n item.appendChild(titleLabel);\r\n\r\n item.addEventListener('click', () => {\r\n this.player.seek(cue.startTime);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n }\r\n \r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n \r\n // Focus first item\r\n setTimeout(() => {\r\n const firstItem = menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (firstItem) {\r\n firstItem.focus();\r\n }\r\n }, 0);\r\n }\r\n }\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n }\r\n\r\n createQualityButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-quality`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.quality'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('hd'));\r\n\r\n // Add quality indicator text\r\n const qualityText = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-quality-text`,\r\n textContent: ''\r\n });\r\n button.appendChild(qualityText);\r\n\r\n button.addEventListener('click', () => {\r\n this.showQualityMenu(button);\r\n });\r\n\r\n this.controls.quality = button;\r\n this.controls.qualityText = qualityText;\r\n \r\n // Update quality indicator after a short delay to ensure renderer is ready\r\n setTimeout(() => this.updateQualityIndicator(), 500);\r\n \r\n return button;\r\n }\r\n\r\n showQualityMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-quality-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-quality-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.quality')\r\n }\r\n });\r\n\r\n // Check if renderer supports quality selection\r\n if (this.player.renderer && this.player.renderer.getQualities) {\r\n const qualities = this.player.renderer.getQualities();\r\n const currentQuality = this.player.renderer.getCurrentQuality ? this.player.renderer.getCurrentQuality() : -1;\r\n const isHLS = this.player.renderer.hls !== undefined;\r\n\r\n if (qualities.length === 0) {\r\n // No qualities available\r\n const noQualityItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.autoQuality'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noQualityItem);\r\n } else {\r\n let activeItem = null;\r\n \r\n // Auto quality option (only for HLS)\r\n if (isHLS) {\r\n const autoItem = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.auto'),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Check if auto is currently selected\r\n const isAuto = this.player.renderer.hls && this.player.renderer.hls.currentLevel === -1;\r\n if (isAuto) {\r\n autoItem.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n autoItem.appendChild(createIconElement('check'));\r\n activeItem = autoItem;\r\n }\r\n\r\n autoItem.addEventListener('click', () => {\r\n if (this.player.renderer.switchQuality) {\r\n this.player.renderer.switchQuality(-1); // -1 for auto\r\n }\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(autoItem);\r\n }\r\n\r\n // Quality options\r\n qualities.forEach(quality => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: quality.name || `${quality.height}p`,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Highlight current quality\r\n if (quality.index === currentQuality) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n if (this.player.renderer.switchQuality) {\r\n this.player.renderer.switchQuality(quality.index);\r\n }\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n \r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n \r\n // Focus active item or first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n } else {\r\n // No quality support\r\n const noSupportItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noQuality'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noSupportItem);\r\n }\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n }\r\n\r\n createCaptionStyleButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-caption-style`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.captionStyling'),\r\n 'aria-haspopup': 'menu',\r\n 'title': i18n.t('player.captionStyling')\r\n }\r\n });\r\n\r\n // Create \"Aa\" text icon for styling\r\n const textIcon = DOMUtils.createElement('span', {\r\n textContent: 'Aa',\r\n style: {\r\n fontSize: '14px',\r\n fontWeight: 'bold'\r\n }\r\n });\r\n button.appendChild(textIcon);\r\n\r\n button.addEventListener('click', () => {\r\n this.showCaptionStyleMenu(button);\r\n });\r\n\r\n this.controls.captionStyle = button;\r\n return button;\r\n }\r\n\r\n showCaptionStyleMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-caption-style-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-caption-style-menu ${this.player.options.classPrefix}-menu ${this.player.options.classPrefix}-settings-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.captionStyling')\r\n }\r\n });\r\n\r\n // Prevent menu from closing when clicking inside\r\n menu.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n // Check if there are any caption tracks\r\n if (!this.player.captionManager || this.player.captionManager.tracks.length === 0) {\r\n // Show \"No captions available\" message\r\n const noTracksItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noCaptions'),\r\n style: {opacity: '0.5', cursor: 'default', padding: '12px 16px'}\r\n });\r\n menu.appendChild(noTracksItem);\r\n\r\n // Append menu to button\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button, true);\r\n return;\r\n }\r\n\r\n // Font Size\r\n const fontSizeGroup = this.createStyleControl(\r\n i18n.t('styleLabels.fontSize'),\r\n 'captionsFontSize',\r\n [\r\n {label: i18n.t('fontSizes.small'), value: '87.5%'},\r\n {label: i18n.t('fontSizes.normal'), value: '100%'},\r\n {label: i18n.t('fontSizes.large'), value: '125%'},\r\n {label: i18n.t('fontSizes.xlarge'), value: '150%'}\r\n ]\r\n );\r\n menu.appendChild(fontSizeGroup);\r\n\r\n // Font Family\r\n const fontFamilyGroup = this.createStyleControl(\r\n i18n.t('styleLabels.font'),\r\n 'captionsFontFamily',\r\n [\r\n {label: i18n.t('fontFamilies.sansSerif'), value: 'sans-serif'},\r\n {label: i18n.t('fontFamilies.serif'), value: 'serif'},\r\n {label: i18n.t('fontFamilies.monospace'), value: 'monospace'}\r\n ]\r\n );\r\n menu.appendChild(fontFamilyGroup);\r\n\r\n // Text Color\r\n const colorGroup = this.createColorControl(i18n.t('styleLabels.textColor'), 'captionsColor');\r\n menu.appendChild(colorGroup);\r\n\r\n // Background Color\r\n const bgColorGroup = this.createColorControl(i18n.t('styleLabels.background'), 'captionsBackgroundColor');\r\n menu.appendChild(bgColorGroup);\r\n\r\n // Opacity\r\n const opacityGroup = this.createOpacityControl(i18n.t('styleLabels.opacity'), 'captionsOpacity');\r\n menu.appendChild(opacityGroup);\r\n\r\n // Set min-width for caption style menu\r\n menu.style.minWidth = '220px';\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click (but not when interacting with controls)\r\n this.attachMenuCloseHandler(menu, button, true);\r\n\r\n // Auto-focus the first select element\r\n setTimeout(() => {\r\n const firstSelect = menu.querySelector('select');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n createStyleControl(label, property, options) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n display: 'block',\r\n fontSize: '12px',\r\n marginBottom: '4px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const select = DOMUtils.createElement('select', {\r\n className: `${this.player.options.classPrefix}-style-select`,\r\n style: {\r\n width: '100%',\r\n padding: '6px',\r\n background: 'var(--vidply-white)',\r\n border: '1px solid var(--vidply-white-10)',\r\n borderRadius: '4px',\r\n color: 'var(--vidply-black)',\r\n fontSize: '13px'\r\n }\r\n });\r\n\r\n const currentValue = this.player.options[property];\r\n options.forEach(opt => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: opt.label,\r\n attributes: {value: opt.value}\r\n });\r\n if (opt.value === currentValue) {\r\n option.selected = true;\r\n }\r\n select.appendChild(option);\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n select.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', (e) => {\r\n e.stopPropagation();\r\n this.player.options[property] = e.target.value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n e.target.value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(select);\r\n return group;\r\n }\r\n\r\n createColorControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n display: 'block',\r\n fontSize: '12px',\r\n marginBottom: '4px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n type: 'color',\r\n value: this.player.options[property]\r\n },\r\n style: {\r\n width: '100%',\r\n height: '32px',\r\n padding: '2px',\r\n background: 'rgba(255,255,255,0.1)',\r\n border: '1px solid rgba(255,255,255,0.2)',\r\n borderRadius: '4px',\r\n cursor: 'pointer'\r\n }\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n input.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('change', (e) => {\r\n e.stopPropagation();\r\n this.player.options[property] = e.target.value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n e.target.value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n createOpacityControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelContainer = DOMUtils.createElement('div', {\r\n style: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n marginBottom: '4px'\r\n }\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n fontSize: '12px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n\r\n const valueEl = DOMUtils.createElement('span', {\r\n textContent: Math.round(this.player.options[property] * 100) + '%',\r\n style: {\r\n fontSize: '12px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n\r\n labelContainer.appendChild(labelEl);\r\n labelContainer.appendChild(valueEl);\r\n group.appendChild(labelContainer);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n type: 'range',\r\n min: '0',\r\n max: '1',\r\n step: '0.1',\r\n value: String(this.player.options[property])\r\n },\r\n style: {\r\n width: '100%',\r\n cursor: 'pointer'\r\n }\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n input.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n e.stopPropagation();\r\n const value = parseFloat(e.target.value);\r\n valueEl.textContent = Math.round(value * 100) + '%';\r\n this.player.options[property] = value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n createSpeedButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-speed`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.speed'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('speed'));\r\n\r\n const speedText = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-speed-text`,\r\n textContent: '1x'\r\n });\r\n button.appendChild(speedText);\r\n\r\n button.addEventListener('click', () => {\r\n this.showSpeedMenu(button);\r\n });\r\n\r\n this.controls.speed = button;\r\n this.controls.speedText = speedText;\r\n return button;\r\n }\r\n\r\n formatSpeedLabel(speed) {\r\n // Special case: 1x is \"Normal\" (translated)\r\n if (speed === 1) {\r\n return i18n.t('speeds.normal');\r\n }\r\n \r\n // For other speeds, format with locale-specific decimal separator\r\n const speedStr = speed.toLocaleString(i18n.getLanguage(), {\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 2\r\n });\r\n \r\n return `${speedStr}\u00D7`;\r\n }\r\n\r\n showSpeedMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-speed-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-speed-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu'\r\n }\r\n });\r\n\r\n const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\r\n let activeItem = null;\r\n\r\n speeds.forEach(speed => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: this.formatSpeedLabel(speed),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n if (speed === this.player.state.playbackSpeed) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n this.player.setPlaybackSpeed(speed);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n\r\n // Focus the active item or first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n createCaptionsButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-captions-button`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.captions'),\r\n 'aria-pressed': 'false',\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('captionsOff'));\r\n\r\n button.addEventListener('click', () => {\r\n this.showCaptionsMenu(button);\r\n });\r\n\r\n this.controls.captions = button;\r\n return button;\r\n }\r\n\r\n showCaptionsMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-captions-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-captions-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('captions.select')\r\n }\r\n });\r\n\r\n // Check if there are any caption tracks\r\n if (!this.player.captionManager || this.player.captionManager.tracks.length === 0) {\r\n // Show \"No captions available\" message\r\n const noTracksItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noCaptions'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noTracksItem);\r\n\r\n // Append menu to button\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n return;\r\n }\r\n\r\n let activeItem = null;\r\n\r\n // Off option\r\n const offItem = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('captions.off'),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n if (!this.player.state.captionsEnabled) {\r\n offItem.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n offItem.appendChild(createIconElement('check'));\r\n activeItem = offItem;\r\n }\r\n\r\n offItem.addEventListener('click', () => {\r\n this.player.disableCaptions();\r\n this.updateCaptionsButton();\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(offItem);\r\n\r\n // Available tracks\r\n const tracks = this.player.captionManager.getAvailableTracks();\r\n tracks.forEach(track => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: track.label,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'lang': track.language,\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Check if this is the current track\r\n if (this.player.state.captionsEnabled &&\r\n this.player.captionManager.currentTrack === this.player.captionManager.tracks[track.index]) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n this.player.captionManager.switchTrack(track.index);\r\n this.updateCaptionsButton();\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Add keyboard navigation for the menu\r\n this.attachMenuKeyboardNavigation(menu);\r\n\r\n // Close menu on outside click and Escape key\r\n this.attachMenuCloseHandler(menu, button);\r\n\r\n // Focus the active item or the first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n updateCaptionsButton() {\r\n if (!this.controls.captions) return;\r\n\r\n const icon = this.controls.captions.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.captionsEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('captions').innerHTML :\r\n createIconElement('captionsOff').innerHTML;\r\n\r\n this.controls.captions.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n }\r\n\r\n createTranscriptButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-transcript`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.transcript'),\r\n 'aria-pressed': 'false'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('transcript'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.transcriptManager) {\r\n this.player.transcriptManager.toggleTranscript();\r\n this.updateTranscriptButton();\r\n }\r\n });\r\n\r\n this.controls.transcript = button;\r\n return button;\r\n }\r\n\r\n updateTranscriptButton() {\r\n if (!this.controls.transcript) return;\r\n\r\n const isVisible = this.player.transcriptManager && this.player.transcriptManager.isVisible;\r\n this.controls.transcript.setAttribute('aria-pressed', isVisible ? 'true' : 'false');\r\n }\r\n\r\n createAudioDescriptionButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-audio-description`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.audioDescription'),\r\n 'aria-pressed': 'false',\r\n 'title': i18n.t('player.audioDescription')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('audioDescription'));\r\n\r\n button.addEventListener('click', async () => {\r\n await this.player.toggleAudioDescription();\r\n this.updateAudioDescriptionButton();\r\n });\r\n\r\n this.controls.audioDescription = button;\r\n return button;\r\n }\r\n\r\n updateAudioDescriptionButton() {\r\n if (!this.controls.audioDescription) return;\r\n\r\n const icon = this.controls.audioDescription.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.audioDescriptionEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('audioDescriptionOn').innerHTML :\r\n createIconElement('audioDescription').innerHTML;\r\n\r\n this.controls.audioDescription.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n this.controls.audioDescription.setAttribute('aria-label',\r\n isEnabled ? i18n.t('audioDescription.disable') : i18n.t('audioDescription.enable')\r\n );\r\n }\r\n\r\n createSignLanguageButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-sign-language`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.signLanguage'),\r\n 'aria-pressed': 'false',\r\n 'title': i18n.t('player.signLanguage')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('signLanguage'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggleSignLanguage();\r\n this.updateSignLanguageButton();\r\n });\r\n\r\n this.controls.signLanguage = button;\r\n return button;\r\n }\r\n\r\n updateSignLanguageButton() {\r\n if (!this.controls.signLanguage) return;\r\n\r\n const icon = this.controls.signLanguage.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.signLanguageEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('signLanguageOn').innerHTML :\r\n createIconElement('signLanguage').innerHTML;\r\n\r\n this.controls.signLanguage.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n this.controls.signLanguage.setAttribute('aria-label',\r\n isEnabled ? i18n.t('signLanguage.hide') : i18n.t('signLanguage.show')\r\n );\r\n }\r\n\r\n createSettingsButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-settings`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.settings')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('settings'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.showSettings();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createPipButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-pip`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.pip')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('pip'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.togglePiP();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createFullscreenButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-fullscreen`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.fullscreen')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('fullscreen'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggleFullscreen();\r\n });\r\n\r\n this.controls.fullscreen = button;\r\n return button;\r\n }\r\n\r\n attachEvents() {\r\n // Update controls based on player state\r\n this.player.on('play', () => this.updatePlayPauseButton());\r\n this.player.on('pause', () => this.updatePlayPauseButton());\r\n this.player.on('timeupdate', () => this.updateProgress());\r\n this.player.on('loadedmetadata', () => {\r\n this.updateDuration();\r\n this.ensureQualityButton();\r\n this.updateQualityIndicator();\r\n });\r\n this.player.on('volumechange', () => this.updateVolumeDisplay());\r\n this.player.on('progress', () => this.updateBuffered());\r\n this.player.on('playbackspeedchange', () => this.updateSpeedDisplay());\r\n this.player.on('fullscreenchange', () => this.updateFullscreenButton());\r\n this.player.on('captionsenabled', () => this.updateCaptionsButton());\r\n this.player.on('captionsdisabled', () => this.updateCaptionsButton());\r\n this.player.on('audiodescriptionenabled', () => this.updateAudioDescriptionButton());\r\n this.player.on('audiodescriptiondisabled', () => this.updateAudioDescriptionButton());\r\n this.player.on('signlanguageenabled', () => this.updateSignLanguageButton());\r\n this.player.on('signlanguagedisabled', () => this.updateSignLanguageButton());\r\n this.player.on('qualitychange', () => this.updateQualityIndicator());\r\n this.player.on('hlslevelswitched', () => this.updateQualityIndicator());\r\n this.player.on('hlsmanifestparsed', () => {\r\n this.ensureQualityButton();\r\n this.updateQualityIndicator();\r\n });\r\n }\r\n\r\n updatePlayPauseButton() {\r\n if (!this.controls.playPause) return;\r\n\r\n const icon = this.controls.playPause.querySelector('.vidply-icon');\r\n const isPlaying = this.player.state.playing;\r\n\r\n icon.innerHTML = isPlaying ?\r\n createIconElement('pause').innerHTML :\r\n createIconElement('play').innerHTML;\r\n\r\n this.controls.playPause.setAttribute('aria-label',\r\n isPlaying ? i18n.t('player.pause') : i18n.t('player.play')\r\n );\r\n }\r\n\r\n updateProgress() {\r\n if (!this.controls.played) return;\r\n\r\n const percent = (this.player.state.currentTime / this.player.state.duration) * 100;\r\n this.controls.played.style.width = `${percent}%`;\r\n this.controls.progress.setAttribute('aria-valuenow', String(Math.round(percent)));\r\n\r\n if (this.controls.currentTimeVisual) {\r\n const currentTime = this.player.state.currentTime;\r\n // Update visual text (hidden from screen readers)\r\n this.controls.currentTimeVisual.textContent = TimeUtils.formatTime(currentTime);\r\n // Update aria-label with human-readable format\r\n this.controls.currentTimeDisplay.setAttribute('aria-label', TimeUtils.formatDuration(currentTime));\r\n }\r\n }\r\n\r\n updateDuration() {\r\n if (this.controls.durationVisual) {\r\n const duration = this.player.state.duration;\r\n // Update visual text (hidden from screen readers)\r\n this.controls.durationVisual.textContent = TimeUtils.formatTime(duration);\r\n // Update aria-label with human-readable format\r\n this.controls.durationDisplay.setAttribute('aria-label', i18n.t('time.durationPrefix') + TimeUtils.formatDuration(duration));\r\n }\r\n }\r\n\r\n updateVolumeDisplay() {\r\n const percent = this.player.state.volume * 100;\r\n\r\n // Update volume fill bar if it exists\r\n if (this.controls.volumeFill) {\r\n this.controls.volumeFill.style.height = `${percent}%`;\r\n }\r\n\r\n // Update mute button icon (should always work even if slider not shown)\r\n if (this.controls.mute) {\r\n const icon = this.controls.mute.querySelector('.vidply-icon');\r\n if (icon) {\r\n let iconName;\r\n\r\n if (this.player.state.muted || this.player.state.volume === 0) {\r\n iconName = 'volumeMuted';\r\n } else if (this.player.state.volume < 0.3) {\r\n iconName = 'volumeLow';\r\n } else if (this.player.state.volume < 0.7) {\r\n iconName = 'volumeMedium';\r\n } else {\r\n iconName = 'volumeHigh';\r\n }\r\n\r\n icon.innerHTML = createIconElement(iconName).innerHTML;\r\n\r\n this.controls.mute.setAttribute('aria-label',\r\n this.player.state.muted ? i18n.t('player.unmute') : i18n.t('player.mute')\r\n );\r\n }\r\n }\r\n\r\n // Update volume slider attribute if it exists\r\n if (this.controls.volumeSlider) {\r\n this.controls.volumeSlider.setAttribute('aria-valuenow', String(Math.round(percent)));\r\n }\r\n }\r\n\r\n updateBuffered() {\r\n if (!this.controls.buffered || !this.player.element.buffered || this.player.element.buffered.length === 0) return;\r\n\r\n const buffered = this.player.element.buffered.end(this.player.element.buffered.length - 1);\r\n const percent = (buffered / this.player.state.duration) * 100;\r\n this.controls.buffered.style.width = `${percent}%`;\r\n }\r\n\r\n updateSpeedDisplay() {\r\n if (this.controls.speedText) {\r\n this.controls.speedText.textContent = `${this.player.state.playbackSpeed}x`;\r\n }\r\n }\r\n\r\n updateFullscreenButton() {\r\n if (!this.controls.fullscreen) return;\r\n\r\n const icon = this.controls.fullscreen.querySelector('.vidply-icon');\r\n const isFullscreen = this.player.state.fullscreen;\r\n\r\n icon.innerHTML = isFullscreen ?\r\n createIconElement('fullscreenExit').innerHTML :\r\n createIconElement('fullscreen').innerHTML;\r\n\r\n this.controls.fullscreen.setAttribute('aria-label',\r\n isFullscreen ? i18n.t('player.exitFullscreen') : i18n.t('player.fullscreen')\r\n );\r\n }\r\n\r\n /**\r\n * Ensure quality button exists if qualities are available\r\n * This is called after renderer initialization to dynamically add the button\r\n */\r\n ensureQualityButton() {\r\n // Skip if quality button is disabled\r\n if (!this.player.options.qualityButton) return;\r\n \r\n // Skip if button already exists\r\n if (this.controls.quality) return;\r\n \r\n // Check if qualities are now available\r\n if (!this.hasQualityLevels()) return;\r\n \r\n // Create and insert the quality button before the speed button\r\n const qualityButton = this.createQualityButton();\r\n \r\n // Find the speed button or caption style button to insert before\r\n const speedButton = this.rightButtons.querySelector(`.${this.player.options.classPrefix}-speed`);\r\n const captionStyleButton = this.rightButtons.querySelector(`.${this.player.options.classPrefix}-caption-style`);\r\n const insertBefore = captionStyleButton || speedButton;\r\n \r\n if (insertBefore) {\r\n this.rightButtons.insertBefore(qualityButton, insertBefore);\r\n } else {\r\n // If no reference button, add it at the beginning of right buttons\r\n this.rightButtons.insertBefore(qualityButton, this.rightButtons.firstChild);\r\n }\r\n \r\n this.player.log('Quality button added dynamically', 'info');\r\n }\r\n\r\n updateQualityIndicator() {\r\n if (!this.controls.qualityText) return;\r\n if (!this.player.renderer || !this.player.renderer.getQualities) return;\r\n\r\n const qualities = this.player.renderer.getQualities();\r\n if (qualities.length === 0) {\r\n this.controls.qualityText.textContent = '';\r\n return;\r\n }\r\n\r\n // Get current quality\r\n let currentQualityText = '';\r\n \r\n // Check if it's HLS with auto mode\r\n if (this.player.renderer.hls && this.player.renderer.hls.currentLevel === -1) {\r\n currentQualityText = 'Auto';\r\n } else if (this.player.renderer.getCurrentQuality) {\r\n const currentIndex = this.player.renderer.getCurrentQuality();\r\n const currentQuality = qualities.find(q => q.index === currentIndex);\r\n if (currentQuality) {\r\n currentQualityText = currentQuality.height ? `${currentQuality.height}p` : '';\r\n }\r\n }\r\n\r\n this.controls.qualityText.textContent = currentQualityText;\r\n }\r\n\r\n setupAutoHide() {\r\n if (this.player.element.tagName !== 'VIDEO') return;\r\n\r\n const showControls = () => {\r\n this.element.classList.add(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.container.classList.add(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.state.controlsVisible = true;\r\n\r\n clearTimeout(this.hideTimeout);\r\n\r\n if (this.player.state.playing) {\r\n this.hideTimeout = setTimeout(() => {\r\n this.element.classList.remove(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.container.classList.remove(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.state.controlsVisible = false;\r\n }, this.player.options.hideControlsDelay);\r\n }\r\n };\r\n\r\n this.player.container.addEventListener('mousemove', showControls);\r\n this.player.container.addEventListener('touchstart', showControls);\r\n this.player.container.addEventListener('click', showControls);\r\n\r\n // Show controls on focus\r\n this.element.addEventListener('focusin', showControls);\r\n\r\n // Always show when paused\r\n this.player.on('pause', () => {\r\n showControls();\r\n clearTimeout(this.hideTimeout);\r\n });\r\n\r\n this.player.on('play', () => {\r\n showControls();\r\n });\r\n\r\n // Initial state\r\n showControls();\r\n }\r\n\r\n show() {\r\n this.element.style.display = '';\r\n }\r\n\r\n hide() {\r\n this.element.style.display = 'none';\r\n }\r\n\r\n destroy() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n }\r\n\r\n if (this.element && this.element.parentNode) {\r\n this.element.parentNode.removeChild(this.element);\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * StorageManager - Handles persistent storage of user preferences\r\n */\r\n\r\nexport class StorageManager {\r\n constructor(namespace = 'vidply') {\r\n this.namespace = namespace;\r\n this.storage = this.isStorageAvailable() ? localStorage : null;\r\n }\r\n\r\n /**\r\n * Check if localStorage is available\r\n */\r\n isStorageAvailable() {\r\n try {\r\n const test = '__storage_test__';\r\n localStorage.setItem(test, test);\r\n localStorage.removeItem(test);\r\n return true;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a namespaced key\r\n */\r\n getKey(key) {\r\n return `${this.namespace}_${key}`;\r\n }\r\n\r\n /**\r\n * Save a value to storage\r\n */\r\n set(key, value) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.setItem(namespacedKey, JSON.stringify(value));\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to save to localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a value from storage\r\n */\r\n get(key, defaultValue = null) {\r\n if (!this.storage) return defaultValue;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n const value = this.storage.getItem(namespacedKey);\r\n return value ? JSON.parse(value) : defaultValue;\r\n } catch (e) {\r\n console.warn('Failed to read from localStorage:', e);\r\n return defaultValue;\r\n }\r\n }\r\n\r\n /**\r\n * Remove a value from storage\r\n */\r\n remove(key) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.removeItem(namespacedKey);\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to remove from localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all namespaced values\r\n */\r\n clear() {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const keys = Object.keys(this.storage);\r\n keys.forEach(key => {\r\n if (key.startsWith(this.namespace)) {\r\n this.storage.removeItem(key);\r\n }\r\n });\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to clear localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Save transcript preferences\r\n */\r\n saveTranscriptPreferences(preferences) {\r\n return this.set('transcript_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get transcript preferences\r\n */\r\n getTranscriptPreferences() {\r\n return this.get('transcript_preferences', null);\r\n }\r\n\r\n /**\r\n * Save caption preferences\r\n */\r\n saveCaptionPreferences(preferences) {\r\n return this.set('caption_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get caption preferences\r\n */\r\n getCaptionPreferences() {\r\n return this.get('caption_preferences', null);\r\n }\r\n\r\n /**\r\n * Save player preferences (volume, speed, etc.)\r\n */\r\n savePlayerPreferences(preferences) {\r\n return this.set('player_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get player preferences\r\n */\r\n getPlayerPreferences() {\r\n return this.get('player_preferences', null);\r\n }\r\n\r\n /**\r\n * Save sign language preferences (position and size)\r\n */\r\n saveSignLanguagePreferences(preferences) {\r\n return this.set('sign_language_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get sign language preferences\r\n */\r\n getSignLanguagePreferences() {\r\n return this.get('sign_language_preferences', null);\r\n }\r\n}\r\n\r\n", "/**\r\n * Caption/Subtitle Manager\r\n */\r\n\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\nimport {StorageManager} from '../utils/StorageManager.js';\r\n\r\nexport class CaptionManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.element = null;\r\n this.tracks = [];\r\n this.currentTrack = null;\r\n this.currentCue = null;\r\n \r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Load saved preferences\r\n this.loadSavedPreferences();\r\n\r\n this.init();\r\n }\r\n \r\n loadSavedPreferences() {\r\n const saved = this.storage.getCaptionPreferences();\r\n if (saved) {\r\n // Override player options with saved preferences\r\n if (saved.fontSize) this.player.options.captionsFontSize = saved.fontSize;\r\n if (saved.fontFamily) this.player.options.captionsFontFamily = saved.fontFamily;\r\n if (saved.color) this.player.options.captionsColor = saved.color;\r\n if (saved.backgroundColor) this.player.options.captionsBackgroundColor = saved.backgroundColor;\r\n if (saved.opacity !== undefined) this.player.options.captionsOpacity = saved.opacity;\r\n }\r\n }\r\n \r\n saveCaptionPreferences() {\r\n this.storage.saveCaptionPreferences({\r\n fontSize: this.player.options.captionsFontSize,\r\n fontFamily: this.player.options.captionsFontFamily,\r\n color: this.player.options.captionsColor,\r\n backgroundColor: this.player.options.captionsBackgroundColor,\r\n opacity: this.player.options.captionsOpacity\r\n });\r\n }\r\n\r\n init() {\r\n this.createElement();\r\n this.loadTracks();\r\n this.attachEvents();\r\n\r\n if (this.player.options.captionsDefault && this.tracks.length > 0) {\r\n this.enable();\r\n }\r\n }\r\n\r\n createElement() {\r\n this.element = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-captions`,\r\n attributes: {\r\n 'aria-live': 'polite',\r\n 'aria-atomic': 'true',\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.captions')\r\n }\r\n });\r\n\r\n // Apply caption styles\r\n this.updateStyles();\r\n\r\n // Append to videoWrapper if it exists, otherwise to container\r\n const target = this.player.videoWrapper || this.player.container;\r\n target.appendChild(this.element);\r\n }\r\n\r\n loadTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n\r\n for (let i = 0; i < textTracks.length; i++) {\r\n const track = textTracks[i];\r\n\r\n if (track.kind === 'subtitles' || track.kind === 'captions') {\r\n this.tracks.push({\r\n track: track,\r\n language: track.language,\r\n label: track.label,\r\n kind: track.kind,\r\n index: i\r\n });\r\n\r\n // Disable all tracks initially\r\n track.mode = 'hidden';\r\n }\r\n }\r\n }\r\n\r\n attachEvents() {\r\n this.player.on('timeupdate', () => {\r\n this.updateCaptions();\r\n });\r\n\r\n this.player.on('captionschange', () => {\r\n this.updateStyles();\r\n });\r\n }\r\n\r\n enable(trackIndex = 0) {\r\n if (this.tracks.length === 0) {\r\n return;\r\n }\r\n\r\n // Disable current track\r\n if (this.currentTrack) {\r\n this.currentTrack.track.mode = 'hidden';\r\n }\r\n\r\n // Enable selected track\r\n const selectedTrack = this.tracks[trackIndex];\r\n\r\n if (selectedTrack) {\r\n // Set to 'hidden' not 'showing' to prevent browser from displaying native captions\r\n // We'll handle the display ourselves\r\n selectedTrack.track.mode = 'hidden';\r\n this.currentTrack = selectedTrack;\r\n this.player.state.captionsEnabled = true;\r\n\r\n // Remove any existing cuechange listener\r\n if (this.cueChangeHandler) {\r\n selectedTrack.track.removeEventListener('cuechange', this.cueChangeHandler);\r\n }\r\n\r\n // Add event listener for cue changes\r\n this.cueChangeHandler = () => {\r\n this.updateCaptions();\r\n };\r\n selectedTrack.track.addEventListener('cuechange', this.cueChangeHandler);\r\n\r\n this.player.emit('captionsenabled', selectedTrack);\r\n }\r\n }\r\n\r\n disable() {\r\n if (this.currentTrack) {\r\n this.currentTrack.track.mode = 'hidden';\r\n this.currentTrack = null;\r\n }\r\n\r\n this.element.style.display = 'none';\r\n this.element.innerHTML = '';\r\n this.currentCue = null;\r\n this.player.state.captionsEnabled = false;\r\n this.player.emit('captionsdisabled');\r\n }\r\n\r\n updateCaptions() {\r\n if (!this.currentTrack) {\r\n return;\r\n }\r\n\r\n if (!this.currentTrack.track.activeCues) {\r\n return;\r\n }\r\n\r\n const activeCues = this.currentTrack.track.activeCues;\r\n\r\n if (activeCues.length > 0) {\r\n const cue = activeCues[0];\r\n\r\n // Only update if the cue has changed\r\n if (this.currentCue !== cue) {\r\n this.currentCue = cue;\r\n\r\n // Parse and display cue text\r\n let text = cue.text;\r\n\r\n // Handle VTT formatting\r\n text = this.parseVTTFormatting(text);\r\n\r\n this.element.innerHTML = DOMUtils.sanitizeHTML(text);\r\n\r\n // Make sure it's visible when there's content\r\n this.element.style.display = 'block';\r\n\r\n this.player.emit('captionchange', cue);\r\n }\r\n } else if (this.currentCue) {\r\n // Clear caption\r\n this.element.innerHTML = '';\r\n this.element.style.display = 'none';\r\n this.currentCue = null;\r\n }\r\n }\r\n\r\n parseVTTFormatting(text) {\r\n // Basic VTT tag support\r\n text = text.replace(/<c[^>]*>(.*?)<\\/c>/g, '<span class=\"caption-class\">$1</span>');\r\n text = text.replace(/<b>(.*?)<\\/b>/g, '<strong>$1</strong>');\r\n text = text.replace(/<i>(.*?)<\\/i>/g, '<em>$1</em>');\r\n text = text.replace(/<u>(.*?)<\\/u>/g, '<u>$1</u>');\r\n\r\n // Voice tags\r\n text = text.replace(/<v\\s+([^>]+)>(.*?)<\\/v>/g, '<span class=\"caption-voice\" data-voice=\"$1\">$2</span>');\r\n\r\n return text;\r\n }\r\n\r\n updateStyles() {\r\n if (!this.element) return;\r\n\r\n const options = this.player.options;\r\n\r\n this.element.style.fontSize = options.captionsFontSize;\r\n this.element.style.fontFamily = options.captionsFontFamily;\r\n this.element.style.color = options.captionsColor;\r\n this.element.style.backgroundColor = this.hexToRgba(\r\n options.captionsBackgroundColor,\r\n options.captionsOpacity\r\n );\r\n }\r\n\r\n hexToRgba(hex, alpha) {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (result) {\r\n return `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${alpha})`;\r\n }\r\n return hex;\r\n }\r\n\r\n setCaptionStyle(property, value) {\r\n switch (property) {\r\n case 'fontSize':\r\n this.player.options.captionsFontSize = value;\r\n break;\r\n case 'fontFamily':\r\n this.player.options.captionsFontFamily = value;\r\n break;\r\n case 'color':\r\n this.player.options.captionsColor = value;\r\n break;\r\n case 'backgroundColor':\r\n this.player.options.captionsBackgroundColor = value;\r\n break;\r\n case 'opacity':\r\n this.player.options.captionsOpacity = value;\r\n break;\r\n }\r\n\r\n this.updateStyles();\r\n this.saveCaptionPreferences();\r\n this.player.emit('captionschange');\r\n }\r\n\r\n getAvailableTracks() {\r\n return this.tracks.map((t, index) => ({\r\n index,\r\n language: t.language,\r\n label: t.label || t.language,\r\n kind: t.kind\r\n }));\r\n }\r\n\r\n switchTrack(trackIndex) {\r\n if (trackIndex >= 0 && trackIndex < this.tracks.length) {\r\n this.disable();\r\n this.enable(trackIndex);\r\n }\r\n }\r\n\r\n destroy() {\r\n this.disable();\r\n\r\n if (this.element && this.element.parentNode) {\r\n this.element.parentNode.removeChild(this.element);\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * Keyboard Accessibility Manager\r\n */\r\n\r\nexport class KeyboardManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.shortcuts = player.options.keyboardShortcuts;\r\n \r\n this.init();\r\n }\r\n\r\n init() {\r\n this.attachEvents();\r\n }\r\n\r\n attachEvents() {\r\n // Listen for keyboard events on the player container\r\n this.player.container.addEventListener('keydown', (e) => {\r\n this.handleKeydown(e);\r\n });\r\n\r\n // Make player container focusable\r\n if (!this.player.container.hasAttribute('tabindex')) {\r\n this.player.container.setAttribute('tabindex', '0');\r\n }\r\n }\r\n\r\n handleKeydown(e) {\r\n // Don't handle if target is an input element\r\n if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {\r\n return;\r\n }\r\n\r\n const key = e.key;\r\n let handled = false;\r\n\r\n // Check each shortcut category\r\n for (const [action, keys] of Object.entries(this.shortcuts)) {\r\n if (keys.includes(key)) {\r\n handled = this.executeAction(action, e);\r\n if (handled) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.announceAction(action);\r\n break;\r\n }\r\n }\r\n }\r\n \r\n // Log unhandled keys for debugging (in development)\r\n if (!handled && this.player.options.debug) {\r\n console.log('[VidPly] Unhandled key:', e.key, 'code:', e.code, 'shiftKey:', e.shiftKey);\r\n }\r\n }\r\n\r\n executeAction(action, event) {\r\n switch (action) {\r\n case 'play-pause':\r\n this.player.toggle();\r\n return true;\r\n\r\n case 'volume-up':\r\n this.player.setVolume(Math.min(1, this.player.state.volume + 0.1));\r\n return true;\r\n\r\n case 'volume-down':\r\n this.player.setVolume(Math.max(0, this.player.state.volume - 0.1));\r\n return true;\r\n\r\n case 'seek-forward':\r\n this.player.seekForward();\r\n return true;\r\n\r\n case 'seek-backward':\r\n this.player.seekBackward();\r\n return true;\r\n\r\n case 'mute':\r\n this.player.toggleMute();\r\n return true;\r\n\r\n case 'fullscreen':\r\n this.player.toggleFullscreen();\r\n return true;\r\n\r\n case 'captions':\r\n // If only one caption track, toggle on/off\r\n // If multiple tracks, open caption menu\r\n if (this.player.captionManager && this.player.captionManager.tracks.length > 1) {\r\n // Get captions button from control bar\r\n const captionsButton = this.player.controlBar && this.player.controlBar.controls.captions;\r\n if (captionsButton) {\r\n this.player.controlBar.showCaptionsMenu(captionsButton);\r\n } else {\r\n // Fallback to toggle if button doesn't exist\r\n this.player.toggleCaptions();\r\n }\r\n } else {\r\n this.player.toggleCaptions();\r\n }\r\n return true;\r\n\r\n case 'caption-style-menu':\r\n // Open caption style menu\r\n if (this.player.controlBar && this.player.controlBar.controls.captionStyle) {\r\n this.player.controlBar.showCaptionStyleMenu(this.player.controlBar.controls.captionStyle);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'speed-up':\r\n this.player.setPlaybackSpeed(\r\n Math.min(2, this.player.state.playbackSpeed + 0.25)\r\n );\r\n return true;\r\n\r\n case 'speed-down':\r\n this.player.setPlaybackSpeed(\r\n Math.max(0.25, this.player.state.playbackSpeed - 0.25)\r\n );\r\n return true;\r\n\r\n case 'speed-menu':\r\n // Open speed menu\r\n if (this.player.controlBar && this.player.controlBar.controls.speed) {\r\n this.player.controlBar.showSpeedMenu(this.player.controlBar.controls.speed);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'quality-menu':\r\n // Open quality menu\r\n if (this.player.controlBar && this.player.controlBar.controls.quality) {\r\n this.player.controlBar.showQualityMenu(this.player.controlBar.controls.quality);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'chapters-menu':\r\n // Open chapters menu\r\n if (this.player.controlBar && this.player.controlBar.controls.chapters) {\r\n this.player.controlBar.showChaptersMenu(this.player.controlBar.controls.chapters);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'transcript-toggle':\r\n // Toggle transcript\r\n if (this.player.transcriptManager) {\r\n this.player.transcriptManager.toggleTranscript();\r\n return true;\r\n }\r\n return false;\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n announceAction(action) {\r\n if (!this.player.options.screenReaderAnnouncements) return;\r\n\r\n let message = '';\r\n\r\n switch (action) {\r\n case 'play-pause':\r\n message = this.player.state.playing ? 'Playing' : 'Paused';\r\n break;\r\n case 'volume-up':\r\n message = `Volume ${Math.round(this.player.state.volume * 100)}%`;\r\n break;\r\n case 'volume-down':\r\n message = `Volume ${Math.round(this.player.state.volume * 100)}%`;\r\n break;\r\n case 'mute':\r\n message = this.player.state.muted ? 'Muted' : 'Unmuted';\r\n break;\r\n case 'fullscreen':\r\n message = this.player.state.fullscreen ? 'Fullscreen' : 'Exit fullscreen';\r\n break;\r\n case 'captions':\r\n message = this.player.state.captionsEnabled ? 'Captions on' : 'Captions off';\r\n break;\r\n case 'speed-up':\r\n case 'speed-down':\r\n message = `Speed ${this.player.state.playbackSpeed}x`;\r\n break;\r\n }\r\n\r\n if (message) {\r\n this.announce(message);\r\n }\r\n }\r\n\r\n announce(message, priority = 'polite') {\r\n // Create or get announcement element\r\n let announcer = document.getElementById('vidply-announcer');\r\n \r\n if (!announcer) {\r\n announcer = document.createElement('div');\r\n announcer.id = 'vidply-announcer';\r\n announcer.className = 'vidply-sr-only';\r\n announcer.setAttribute('aria-live', priority);\r\n announcer.setAttribute('aria-atomic', 'true');\r\n announcer.style.cssText = `\r\n position: absolute;\r\n left: -10000px;\r\n width: 1px;\r\n height: 1px;\r\n overflow: hidden;\r\n `;\r\n document.body.appendChild(announcer);\r\n }\r\n\r\n // Clear and set new message\r\n announcer.textContent = '';\r\n setTimeout(() => {\r\n announcer.textContent = message;\r\n }, 100);\r\n }\r\n\r\n updateShortcut(action, keys) {\r\n if (Array.isArray(keys)) {\r\n this.shortcuts[action] = keys;\r\n }\r\n }\r\n\r\n destroy() {\r\n // Event listeners are automatically removed when the container is destroyed\r\n }\r\n}\r\n\r\n", "/**\r\n * Transcript Manager Component\r\n * Manages transcript display and interaction\r\n */\r\n\r\nimport { DOMUtils } from '../utils/DOMUtils.js';\r\nimport { TimeUtils } from '../utils/TimeUtils.js';\r\nimport { createIconElement } from '../icons/Icons.js';\r\nimport { i18n } from '../i18n/i18n.js';\r\nimport { StorageManager } from '../utils/StorageManager.js';\r\n\r\nexport class TranscriptManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.transcriptWindow = null;\r\n this.transcriptEntries = [];\r\n this.metadataCues = [];\r\n this.currentActiveEntry = null;\r\n this.isVisible = false;\r\n \r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Dragging state\r\n this.isDragging = false;\r\n this.dragOffsetX = 0;\r\n this.dragOffsetY = 0;\r\n \r\n // Resizing state\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.resizeStartX = 0;\r\n this.resizeStartY = 0;\r\n this.resizeStartWidth = 0;\r\n this.resizeStartHeight = 0;\r\n this.resizeEnabled = false;\r\n \r\n // Settings menu state\r\n this.settingsMenuVisible = false;\r\n this.settingsMenu = null;\r\n this.settingsButton = null;\r\n this.settingsMenuJustOpened = false;\r\n \r\n // Keyboard drag mode\r\n this.keyboardDragMode = false;\r\n \r\n // Style dialog state\r\n this.styleDialog = null;\r\n this.styleDialogVisible = false;\r\n this.styleDialogJustOpened = false;\r\n \r\n // Load saved preferences from localStorage\r\n const savedPreferences = this.storage.getTranscriptPreferences();\r\n \r\n // Transcript styling options (with defaults, then player options, then saved preferences)\r\n this.transcriptStyle = {\r\n fontSize: savedPreferences?.fontSize || this.player.options.transcriptFontSize || '100%',\r\n fontFamily: savedPreferences?.fontFamily || this.player.options.transcriptFontFamily || 'sans-serif',\r\n color: savedPreferences?.color || this.player.options.transcriptColor || '#ffffff',\r\n backgroundColor: savedPreferences?.backgroundColor || this.player.options.transcriptBackgroundColor || '#1e1e1e',\r\n opacity: savedPreferences?.opacity ?? this.player.options.transcriptOpacity ?? 0.98\r\n };\r\n \r\n // Store event handlers for cleanup\r\n this.handlers = {\r\n timeupdate: () => this.updateActiveEntry(),\r\n resize: null,\r\n mousemove: null,\r\n mouseup: null,\r\n touchmove: null,\r\n touchend: null,\r\n mousedown: null,\r\n touchstart: null,\r\n keydown: null,\r\n settingsClick: null,\r\n settingsKeydown: null,\r\n documentClick: null,\r\n styleDialogKeydown: null\r\n };\r\n \r\n this.init();\r\n }\r\n\r\n init() {\r\n // Listen for time updates to highlight active transcript entry\r\n this.player.on('timeupdate', this.handlers.timeupdate);\r\n \r\n // Reposition transcript when entering/exiting fullscreen\r\n this.player.on('fullscreenchange', () => {\r\n if (this.isVisible) {\r\n // Add a small delay to ensure DOM has updated after fullscreen transition\r\n setTimeout(() => this.positionTranscript(), 100);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Toggle transcript window visibility\r\n */\r\n toggleTranscript() {\r\n if (this.isVisible) {\r\n this.hideTranscript();\r\n } else {\r\n this.showTranscript();\r\n }\r\n }\r\n\r\n /**\r\n * Show transcript window\r\n */\r\n showTranscript() {\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'flex';\r\n this.isVisible = true;\r\n \r\n // Focus the settings button for keyboard accessibility\r\n setTimeout(() => {\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }, 150);\r\n return;\r\n }\r\n\r\n // Create transcript window\r\n this.createTranscriptWindow();\r\n this.loadTranscriptData();\r\n \r\n // Show the window\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'flex';\r\n // Re-position after showing (in case window was resized while hidden)\r\n setTimeout(() => this.positionTranscript(), 0);\r\n \r\n // Focus the settings button for keyboard accessibility\r\n setTimeout(() => {\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }, 150);\r\n }\r\n this.isVisible = true;\r\n }\r\n\r\n /**\r\n * Hide transcript window\r\n */\r\n hideTranscript() {\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'none';\r\n this.isVisible = false;\r\n }\r\n }\r\n\r\n /**\r\n * Create the transcript window UI\r\n */\r\n createTranscriptWindow() {\r\n this.transcriptWindow = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-window`,\r\n attributes: {\r\n 'role': 'dialog',\r\n 'aria-label': 'Video Transcript',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Header (draggable)\r\n this.transcriptHeader = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-header`,\r\n attributes: {\r\n 'aria-label': 'Drag to reposition transcript. Use arrow keys to move, Home to reset position, Escape to close.',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Header left side (settings button + title)\r\n this.headerLeft = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-header-left`\r\n });\r\n\r\n // Settings button\r\n this.settingsButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.settings'),\r\n 'aria-expanded': 'false'\r\n }\r\n });\r\n this.settingsButton.appendChild(createIconElement('settings'));\r\n this.handlers.settingsClick = (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n } else {\r\n this.showSettingsMenu();\r\n }\r\n };\r\n this.settingsButton.addEventListener('click', this.handlers.settingsClick);\r\n \r\n // Keyboard handler for settings button\r\n this.handlers.settingsKeydown = (e) => {\r\n // D key to toggle keyboard drag mode\r\n if (e.key === 'd' || e.key === 'D') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.toggleKeyboardDragMode();\r\n }\r\n // R key to toggle resize mode\r\n else if (e.key === 'r' || e.key === 'R') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.toggleResizeMode();\r\n }\r\n // Escape to close menu if open\r\n else if (e.key === 'Escape' && this.settingsMenuVisible) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideSettingsMenu();\r\n }\r\n };\r\n this.settingsButton.addEventListener('keydown', this.handlers.settingsKeydown);\r\n\r\n const title = DOMUtils.createElement('h3', {\r\n textContent: i18n.t('transcript.title')\r\n });\r\n\r\n this.headerLeft.appendChild(this.settingsButton);\r\n this.headerLeft.appendChild(title);\r\n\r\n const closeButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-close`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.close')\r\n }\r\n });\r\n closeButton.appendChild(createIconElement('close'));\r\n closeButton.addEventListener('click', () => this.hideTranscript());\r\n\r\n this.transcriptHeader.appendChild(this.headerLeft);\r\n this.transcriptHeader.appendChild(closeButton);\r\n\r\n // Content container\r\n this.transcriptContent = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-content`\r\n });\r\n\r\n this.transcriptWindow.appendChild(this.transcriptHeader);\r\n this.transcriptWindow.appendChild(this.transcriptContent);\r\n\r\n // Append to player container\r\n this.player.container.appendChild(this.transcriptWindow);\r\n \r\n // Position it next to the video wrapper\r\n this.positionTranscript();\r\n \r\n // Setup drag functionality\r\n this.setupDragAndDrop();\r\n \r\n // Setup document click handler to close settings menu and style dialog\r\n // DON'T add it yet - it will be added when the menu is first opened\r\n this.handlers.documentClick = (e) => {\r\n // Ignore if menu was just opened (prevents immediate closing)\r\n if (this.settingsMenuJustOpened) {\r\n return;\r\n }\r\n \r\n // Ignore if style dialog was just opened (prevents immediate closing)\r\n if (this.styleDialogJustOpened) {\r\n return;\r\n }\r\n \r\n // Ignore clicks on the settings button itself\r\n if (this.settingsButton && this.settingsButton.contains(e.target)) {\r\n return;\r\n }\r\n \r\n // Ignore clicks on the settings menu items\r\n if (this.settingsMenu && this.settingsMenu.contains(e.target)) {\r\n return;\r\n }\r\n \r\n // Close settings menu if clicking outside\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n }\r\n \r\n // Close style dialog if clicking outside (but not on settings button)\r\n if (this.styleDialogVisible && this.styleDialog && \r\n !this.styleDialog.contains(e.target)) {\r\n this.hideStyleDialog();\r\n }\r\n };\r\n // Store flag to track if handler has been added\r\n this.documentClickHandlerAdded = false;\r\n \r\n // Re-position on window resize (debounced)\r\n let resizeTimeout;\r\n this.handlers.resize = () => {\r\n clearTimeout(resizeTimeout);\r\n resizeTimeout = setTimeout(() => this.positionTranscript(), 100);\r\n };\r\n window.addEventListener('resize', this.handlers.resize);\r\n }\r\n \r\n /**\r\n * Position transcript window next to video\r\n */\r\n positionTranscript() {\r\n if (!this.transcriptWindow || !this.player.videoWrapper || !this.isVisible) return;\r\n \r\n const isMobile = window.innerWidth < 640;\r\n const videoRect = this.player.videoWrapper.getBoundingClientRect();\r\n \r\n // Check if player is in fullscreen mode\r\n const isFullscreen = this.player.state.fullscreen;\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile: Position underneath the video and controls as part of the layout\r\n this.transcriptWindow.style.position = 'relative';\r\n this.transcriptWindow.style.left = '0';\r\n this.transcriptWindow.style.right = '0';\r\n this.transcriptWindow.style.bottom = 'auto';\r\n this.transcriptWindow.style.top = 'auto';\r\n this.transcriptWindow.style.width = '100%';\r\n this.transcriptWindow.style.maxWidth = '100%';\r\n this.transcriptWindow.style.maxHeight = '400px';\r\n this.transcriptWindow.style.height = 'auto';\r\n this.transcriptWindow.style.borderRadius = '0';\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.border = 'none';\r\n this.transcriptWindow.style.borderTop = '1px solid var(--vidply-border-light)';\r\n this.transcriptWindow.style.boxShadow = 'none';\r\n // Disable dragging on mobile\r\n if (this.transcriptHeader) {\r\n this.transcriptHeader.style.cursor = 'default';\r\n }\r\n \r\n // Ensure transcript is at the container level for proper stacking\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n } else if (isFullscreen) {\r\n // In fullscreen: position in bottom right corner inside the video\r\n this.transcriptWindow.style.position = 'fixed';\r\n this.transcriptWindow.style.left = 'auto';\r\n this.transcriptWindow.style.right = '20px';\r\n this.transcriptWindow.style.bottom = '80px'; // Above controls\r\n this.transcriptWindow.style.top = 'auto';\r\n this.transcriptWindow.style.maxHeight = 'calc(100vh - 180px)'; // Leave space for controls\r\n this.transcriptWindow.style.height = 'auto';\r\n this.transcriptWindow.style.width = '400px';\r\n this.transcriptWindow.style.maxWidth = '400px';\r\n this.transcriptWindow.style.borderRadius = '8px';\r\n this.transcriptWindow.style.border = '1px solid var(--vidply-border)';\r\n this.transcriptWindow.style.borderTop = '';\r\n \r\n // Move back to container for fullscreen\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n } else {\r\n // Desktop mode: position next to video\r\n this.transcriptWindow.style.position = 'absolute';\r\n this.transcriptWindow.style.left = `${videoRect.width + 8}px`;\r\n this.transcriptWindow.style.right = 'auto';\r\n this.transcriptWindow.style.bottom = 'auto';\r\n this.transcriptWindow.style.top = '0';\r\n this.transcriptWindow.style.height = `${videoRect.height}px`;\r\n this.transcriptWindow.style.maxHeight = 'none';\r\n this.transcriptWindow.style.width = '400px';\r\n this.transcriptWindow.style.maxWidth = '400px';\r\n this.transcriptWindow.style.borderRadius = '8px';\r\n this.transcriptWindow.style.border = '1px solid var(--vidply-border)';\r\n this.transcriptWindow.style.borderTop = '';\r\n // Enable dragging on desktop\r\n if (this.transcriptHeader) {\r\n this.transcriptHeader.style.cursor = 'move';\r\n }\r\n \r\n // Move back to container for desktop\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Load transcript data from caption/subtitle tracks\r\n */\r\n loadTranscriptData() {\r\n this.transcriptEntries = [];\r\n this.transcriptContent.innerHTML = '';\r\n\r\n // Get all text tracks\r\n const textTracks = Array.from(this.player.element.textTracks);\r\n \r\n // Find different track types\r\n const captionTrack = textTracks.find(\r\n track => track.kind === 'captions' || track.kind === 'subtitles'\r\n );\r\n const descriptionTrack = textTracks.find(track => track.kind === 'descriptions');\r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n\r\n // We need at least one track type\r\n if (!captionTrack && !descriptionTrack && !metadataTrack) {\r\n this.showNoTranscriptMessage();\r\n return;\r\n }\r\n\r\n // Enable all tracks to load cues\r\n const tracksToLoad = [captionTrack, descriptionTrack, metadataTrack].filter(Boolean);\r\n tracksToLoad.forEach(track => {\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n });\r\n\r\n // Check if any tracks are still loading\r\n const needsLoading = tracksToLoad.some(track => !track.cues || track.cues.length === 0);\r\n \r\n if (needsLoading) {\r\n // Wait for cues to load\r\n const loadingMessage = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-loading`,\r\n textContent: i18n.t('transcript.loading')\r\n });\r\n this.transcriptContent.appendChild(loadingMessage);\r\n\r\n let loaded = 0;\r\n const onLoad = () => {\r\n loaded++;\r\n if (loaded >= tracksToLoad.length) {\r\n this.loadTranscriptData();\r\n }\r\n };\r\n\r\n tracksToLoad.forEach(track => {\r\n track.addEventListener('load', onLoad, { once: true });\r\n });\r\n\r\n // Fallback timeout\r\n setTimeout(() => {\r\n this.loadTranscriptData();\r\n }, 500);\r\n \r\n return;\r\n }\r\n\r\n // Collect all cues from all tracks with their type\r\n const allCues = [];\r\n \r\n if (captionTrack && captionTrack.cues) {\r\n Array.from(captionTrack.cues).forEach(cue => {\r\n allCues.push({ cue, type: 'caption' });\r\n });\r\n }\r\n \r\n if (descriptionTrack && descriptionTrack.cues) {\r\n Array.from(descriptionTrack.cues).forEach(cue => {\r\n allCues.push({ cue, type: 'description' });\r\n });\r\n }\r\n \r\n // Store metadata separately for programmatic use (don't display in transcript)\r\n if (metadataTrack && metadataTrack.cues) {\r\n this.metadataCues = Array.from(metadataTrack.cues);\r\n this.setupMetadataHandling();\r\n }\r\n\r\n // Sort all cues by start time\r\n allCues.sort((a, b) => a.cue.startTime - b.cue.startTime);\r\n\r\n // Build transcript from captions and descriptions only\r\n allCues.forEach((item, index) => {\r\n const entry = this.createTranscriptEntry(item.cue, index, item.type);\r\n this.transcriptEntries.push({\r\n element: entry,\r\n cue: item.cue,\r\n type: item.type,\r\n startTime: item.cue.startTime,\r\n endTime: item.cue.endTime\r\n });\r\n this.transcriptContent.appendChild(entry);\r\n });\r\n \r\n // Apply current styles to newly loaded entries\r\n this.applyTranscriptStyles();\r\n }\r\n\r\n /**\r\n * Setup metadata handling\r\n * Metadata cues are not displayed but can be used programmatically\r\n */\r\n setupMetadataHandling() {\r\n if (!this.metadataCues || this.metadataCues.length === 0) {\r\n return;\r\n }\r\n\r\n // Listen for cuechange events on the metadata track to trigger custom actions\r\n const textTracks = Array.from(this.player.element.textTracks);\r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n \r\n if (metadataTrack) {\r\n metadataTrack.addEventListener('cuechange', () => {\r\n const activeCues = Array.from(metadataTrack.activeCues || []);\r\n activeCues.forEach(cue => {\r\n this.handleMetadataCue(cue);\r\n });\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Handle individual metadata cues\r\n * Parses metadata text and emits events or triggers actions\r\n */\r\n handleMetadataCue(cue) {\r\n const text = cue.text.trim();\r\n \r\n // Emit a generic metadata event that developers can listen to\r\n this.player.emit('metadata', {\r\n time: cue.startTime,\r\n endTime: cue.endTime,\r\n text: text,\r\n cue: cue\r\n });\r\n\r\n // Parse for specific commands (examples based on wwa_meta.vtt format)\r\n if (text.includes('PAUSE')) {\r\n // Emit pause suggestion event (don't auto-pause, let developer decide)\r\n this.player.emit('metadata:pause', { time: cue.startTime, text: text });\r\n }\r\n\r\n // Parse for focus directives\r\n const focusMatch = text.match(/FOCUS:([\\w#-]+)/);\r\n if (focusMatch) {\r\n this.player.emit('metadata:focus', { \r\n time: cue.startTime, \r\n target: focusMatch[1],\r\n text: text \r\n });\r\n }\r\n\r\n // Parse for hashtag references\r\n const hashtags = text.match(/#[\\w-]+/g);\r\n if (hashtags) {\r\n this.player.emit('metadata:hashtags', {\r\n time: cue.startTime,\r\n hashtags: hashtags,\r\n text: text\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Create a single transcript entry element\r\n */\r\n createTranscriptEntry(cue, index, type = 'caption') {\r\n const entry = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-entry ${this.player.options.classPrefix}-transcript-${type}`,\r\n attributes: {\r\n 'data-start': String(cue.startTime),\r\n 'data-end': String(cue.endTime),\r\n 'data-type': type,\r\n 'role': 'button',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n const timestamp = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-transcript-time`,\r\n textContent: TimeUtils.formatTime(cue.startTime)\r\n });\r\n\r\n const text = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-transcript-text`,\r\n textContent: this.stripVTTFormatting(cue.text)\r\n });\r\n\r\n entry.appendChild(timestamp);\r\n entry.appendChild(text);\r\n\r\n // Click to seek\r\n const seekToTime = () => {\r\n this.player.seek(cue.startTime);\r\n if (this.player.state.paused) {\r\n this.player.play();\r\n }\r\n };\r\n\r\n entry.addEventListener('click', seekToTime);\r\n entry.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n seekToTime();\r\n }\r\n });\r\n\r\n return entry;\r\n }\r\n\r\n /**\r\n * Strip VTT formatting tags from text\r\n */\r\n stripVTTFormatting(text) {\r\n // Remove VTT tags like <v Speaker>, <c>, etc.\r\n return text\r\n .replace(/<[^>]+>/g, '')\r\n .replace(/\\n/g, ' ')\r\n .trim();\r\n }\r\n\r\n /**\r\n * Show message when no transcript is available\r\n */\r\n showNoTranscriptMessage() {\r\n const message = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-empty`,\r\n textContent: i18n.t('transcript.noTranscript')\r\n });\r\n this.transcriptContent.appendChild(message);\r\n }\r\n\r\n /**\r\n * Update active transcript entry based on current time\r\n */\r\n updateActiveEntry() {\r\n if (!this.isVisible || this.transcriptEntries.length === 0) return;\r\n\r\n const currentTime = this.player.state.currentTime;\r\n \r\n // Find the entry that matches current time\r\n const activeEntry = this.transcriptEntries.find(\r\n entry => currentTime >= entry.startTime && currentTime < entry.endTime\r\n );\r\n\r\n if (activeEntry && activeEntry !== this.currentActiveEntry) {\r\n // Remove previous active class\r\n if (this.currentActiveEntry) {\r\n this.currentActiveEntry.element.classList.remove(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n }\r\n\r\n // Add active class to current entry\r\n activeEntry.element.classList.add(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n \r\n // Scroll to active entry\r\n this.scrollToEntry(activeEntry.element);\r\n \r\n this.currentActiveEntry = activeEntry;\r\n } else if (!activeEntry && this.currentActiveEntry) {\r\n // No active entry, remove active class\r\n this.currentActiveEntry.element.classList.remove(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n this.currentActiveEntry = null;\r\n }\r\n }\r\n\r\n /**\r\n * Scroll transcript window to show active entry\r\n */\r\n scrollToEntry(entryElement) {\r\n if (!this.transcriptContent) return;\r\n\r\n const contentRect = this.transcriptContent.getBoundingClientRect();\r\n const entryRect = entryElement.getBoundingClientRect();\r\n\r\n // Check if entry is out of view\r\n if (entryRect.top < contentRect.top || entryRect.bottom > contentRect.bottom) {\r\n // Scroll to center the entry\r\n const scrollTop = entryElement.offsetTop - (this.transcriptContent.clientHeight / 2) + (entryElement.clientHeight / 2);\r\n this.transcriptContent.scrollTo({\r\n top: scrollTop,\r\n behavior: 'smooth'\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Setup drag and drop functionality\r\n */\r\n setupDragAndDrop() {\r\n if (!this.transcriptHeader || !this.transcriptWindow) return;\r\n\r\n // Create and store handler functions\r\n this.handlers.mousedown = (e) => {\r\n // Don't drag if clicking on close button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-close`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on settings button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on settings menu\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings-menu`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on style dialog\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-style-dialog`)) {\r\n return;\r\n }\r\n \r\n this.startDragging(e.clientX, e.clientY);\r\n e.preventDefault();\r\n };\r\n\r\n this.handlers.mousemove = (e) => {\r\n if (this.isDragging) {\r\n this.drag(e.clientX, e.clientY);\r\n }\r\n };\r\n\r\n this.handlers.mouseup = () => {\r\n if (this.isDragging) {\r\n this.stopDragging();\r\n }\r\n };\r\n\r\n this.handlers.touchstart = (e) => {\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-close`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching settings button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching settings menu\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings-menu`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching style dialog\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-style-dialog`)) {\r\n return;\r\n }\r\n \r\n const isMobile = window.innerWidth < 640;\r\n const isFullscreen = this.player.state.fullscreen;\r\n const touch = e.touches[0];\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile (not fullscreen): No dragging/swiping, transcript is part of layout\r\n return;\r\n } else {\r\n // Desktop or fullscreen: Normal dragging\r\n this.startDragging(touch.clientX, touch.clientY);\r\n }\r\n };\r\n\r\n this.handlers.touchmove = (e) => {\r\n const isMobile = window.innerWidth < 640;\r\n const isFullscreen = this.player.state.fullscreen;\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile (not fullscreen): No dragging/swiping\r\n return;\r\n } else if (this.isDragging) {\r\n // Desktop or fullscreen: Normal drag\r\n const touch = e.touches[0];\r\n this.drag(touch.clientX, touch.clientY);\r\n e.preventDefault();\r\n }\r\n };\r\n\r\n this.handlers.touchend = () => {\r\n if (this.isDragging) {\r\n // Stop dragging\r\n this.stopDragging();\r\n }\r\n };\r\n\r\n this.handlers.keydown = (e) => {\r\n // Handle arrow keys only in keyboard drag mode\r\n if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {\r\n if (!this.keyboardDragMode) {\r\n // Not in drag mode, let other handlers deal with it\r\n return;\r\n }\r\n \r\n // In drag mode - move the window\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const step = e.shiftKey ? 50 : 10; // Larger steps with Shift key\r\n \r\n // Get current position\r\n let currentLeft = parseFloat(this.transcriptWindow.style.left) || 0;\r\n let currentTop = parseFloat(this.transcriptWindow.style.top) || 0;\r\n \r\n // If window is still centered with transform, convert to absolute position first\r\n const computedStyle = window.getComputedStyle(this.transcriptWindow);\r\n if (computedStyle.transform !== 'none') {\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n currentLeft = rect.left;\r\n currentTop = rect.top;\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.left = `${currentLeft}px`;\r\n this.transcriptWindow.style.top = `${currentTop}px`;\r\n }\r\n \r\n // Calculate new position based on arrow key\r\n let newX = currentLeft;\r\n let newY = currentTop;\r\n\r\n switch(e.key) {\r\n case 'ArrowLeft':\r\n newX -= step;\r\n break;\r\n case 'ArrowRight':\r\n newX += step;\r\n break;\r\n case 'ArrowUp':\r\n newY -= step;\r\n break;\r\n case 'ArrowDown':\r\n newY += step;\r\n break;\r\n }\r\n\r\n // Set new position directly\r\n this.transcriptWindow.style.left = `${newX}px`;\r\n this.transcriptWindow.style.top = `${newY}px`;\r\n return;\r\n }\r\n \r\n // Handle other special keys\r\n if (e.key === 'Home') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.resetPosition();\r\n return;\r\n }\r\n \r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.styleDialogVisible) {\r\n // Close style dialog first\r\n this.hideStyleDialog();\r\n } else if (this.keyboardDragMode) {\r\n // Exit drag mode\r\n this.disableKeyboardDragMode();\r\n } else if (this.settingsMenuVisible) {\r\n // Close settings menu\r\n this.hideSettingsMenu();\r\n } else {\r\n // Close transcript\r\n this.hideTranscript();\r\n }\r\n return;\r\n }\r\n };\r\n\r\n // Add event listeners using stored handlers\r\n this.transcriptHeader.addEventListener('mousedown', this.handlers.mousedown);\r\n document.addEventListener('mousemove', this.handlers.mousemove);\r\n document.addEventListener('mouseup', this.handlers.mouseup);\r\n \r\n this.transcriptHeader.addEventListener('touchstart', this.handlers.touchstart);\r\n document.addEventListener('touchmove', this.handlers.touchmove);\r\n document.addEventListener('touchend', this.handlers.touchend);\r\n \r\n this.transcriptHeader.addEventListener('keydown', this.handlers.keydown);\r\n }\r\n\r\n /**\r\n * Start dragging\r\n */\r\n startDragging(clientX, clientY) {\r\n // Get current rendered position (this is where it actually appears on screen)\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n \r\n // Get the parent container position (player container)\r\n const containerRect = this.player.container.getBoundingClientRect();\r\n \r\n // Calculate position RELATIVE to container (not viewport)\r\n const relativeLeft = rect.left - containerRect.left;\r\n const relativeTop = rect.top - containerRect.top;\r\n \r\n // If window is centered with transform, convert to absolute position\r\n const computedStyle = window.getComputedStyle(this.transcriptWindow);\r\n if (computedStyle.transform !== 'none') {\r\n // Remove transform and set position relative to container\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.left = `${relativeLeft}px`;\r\n this.transcriptWindow.style.top = `${relativeTop}px`;\r\n }\r\n \r\n // Calculate offset based on viewport coordinates (where user clicked)\r\n this.dragOffsetX = clientX - rect.left;\r\n this.dragOffsetY = clientY - rect.top;\r\n \r\n this.isDragging = true;\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-dragging`);\r\n document.body.style.cursor = 'grabbing';\r\n document.body.style.userSelect = 'none';\r\n }\r\n\r\n /**\r\n * Perform drag\r\n */\r\n drag(clientX, clientY) {\r\n if (!this.isDragging) return;\r\n\r\n // Calculate new viewport position based on mouse position minus the offset\r\n const newViewportX = clientX - this.dragOffsetX;\r\n const newViewportY = clientY - this.dragOffsetY;\r\n \r\n // Convert to position relative to container\r\n const containerRect = this.player.container.getBoundingClientRect();\r\n const newX = newViewportX - containerRect.left;\r\n const newY = newViewportY - containerRect.top;\r\n \r\n // During drag, set position relative to container\r\n this.transcriptWindow.style.left = `${newX}px`;\r\n this.transcriptWindow.style.top = `${newY}px`;\r\n }\r\n\r\n /**\r\n * Stop dragging\r\n */\r\n stopDragging() {\r\n this.isDragging = false;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-dragging`);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n }\r\n\r\n /**\r\n * Set window position with boundary constraints\r\n */\r\n setPosition(x, y) {\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n \r\n // Use document dimensions for fixed positioning\r\n const viewportWidth = document.documentElement.clientWidth;\r\n const viewportHeight = document.documentElement.clientHeight;\r\n \r\n // Very relaxed boundaries - allow window to go mostly off-screen\r\n // Just keep a small part visible so user can always drag it back\r\n const minVisible = 100; // Keep at least 100px visible\r\n const minX = -(rect.width - minVisible); // Can go way off-screen to the left\r\n const minY = -(rect.height - minVisible); // Can go way off-screen to the top\r\n const maxX = viewportWidth - minVisible; // Can go way off-screen to the right\r\n const maxY = viewportHeight - minVisible; // Can go way off-screen to the bottom\r\n \r\n // Clamp position to boundaries (very loose)\r\n x = Math.max(minX, Math.min(x, maxX));\r\n y = Math.max(minY, Math.min(y, maxY));\r\n \r\n this.transcriptWindow.style.left = `${x}px`;\r\n this.transcriptWindow.style.top = `${y}px`;\r\n this.transcriptWindow.style.transform = 'none';\r\n }\r\n\r\n /**\r\n * Reset position to center\r\n */\r\n resetPosition() {\r\n this.transcriptWindow.style.left = '50%';\r\n this.transcriptWindow.style.top = '50%';\r\n this.transcriptWindow.style.transform = 'translate(-50%, -50%)';\r\n }\r\n\r\n /**\r\n * Toggle keyboard drag mode\r\n */\r\n toggleKeyboardDragMode() {\r\n if (this.keyboardDragMode) {\r\n this.disableKeyboardDragMode();\r\n } else {\r\n this.enableKeyboardDragMode();\r\n }\r\n }\r\n\r\n /**\r\n * Enable keyboard drag mode\r\n */\r\n enableKeyboardDragMode() {\r\n this.keyboardDragMode = true;\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-keyboard-drag`);\r\n \r\n // Update settings button aria label\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-label', 'Keyboard drag mode active. Use arrow keys to move window. Press D or Escape to exit.');\r\n }\r\n \r\n // Add visual indicator\r\n const indicator = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-drag-indicator`,\r\n textContent: i18n.t('transcript.keyboardDragActive')\r\n });\r\n this.transcriptHeader.appendChild(indicator);\r\n \r\n // Hide settings menu if open\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n }\r\n \r\n // Focus the header for keyboard navigation\r\n this.transcriptHeader.focus();\r\n }\r\n\r\n /**\r\n * Disable keyboard drag mode\r\n */\r\n disableKeyboardDragMode() {\r\n this.keyboardDragMode = false;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-keyboard-drag`);\r\n \r\n // Update settings button aria label\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-label', 'Transcript settings. Press Enter to open menu, or D to enable drag mode');\r\n }\r\n \r\n // Remove visual indicator\r\n const indicator = this.transcriptHeader.querySelector(`.${this.player.options.classPrefix}-transcript-drag-indicator`);\r\n if (indicator) {\r\n indicator.remove();\r\n }\r\n \r\n // Focus back to settings button\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }\r\n\r\n /**\r\n * Toggle settings menu visibility\r\n */\r\n toggleSettingsMenu() {\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n } else {\r\n this.showSettingsMenu();\r\n }\r\n }\r\n\r\n /**\r\n * Show settings menu\r\n */\r\n showSettingsMenu() {\r\n // Set flag to prevent immediate closing\r\n this.settingsMenuJustOpened = true;\r\n setTimeout(() => {\r\n this.settingsMenuJustOpened = false;\r\n }, 350);\r\n \r\n // Add document click handler on FIRST menu open (not at window creation)\r\n if (!this.documentClickHandlerAdded) {\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handlers.documentClick);\r\n this.documentClickHandlerAdded = true;\r\n }, 300);\r\n }\r\n \r\n if (this.settingsMenu) {\r\n this.settingsMenu.style.display = 'block';\r\n this.settingsMenuVisible = true;\r\n return;\r\n }\r\n // Create settings menu\r\n this.settingsMenu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-menu`\r\n });\r\n\r\n // Keyboard drag option\r\n const keyboardDragOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.keyboardDragMode')\r\n }\r\n });\r\n const keyboardIcon = createIconElement('move');\r\n const keyboardText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.keyboardDragMode')\r\n });\r\n keyboardDragOption.appendChild(keyboardIcon);\r\n keyboardDragOption.appendChild(keyboardText);\r\n keyboardDragOption.addEventListener('click', () => {\r\n this.toggleKeyboardDragMode();\r\n this.hideSettingsMenu();\r\n });\r\n \r\n // Style option\r\n const styleOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.styleTranscript')\r\n }\r\n });\r\n const styleIcon = createIconElement('settings');\r\n const styleText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.styleTranscript')\r\n });\r\n styleOption.appendChild(styleIcon);\r\n styleOption.appendChild(styleText);\r\n styleOption.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideSettingsMenu();\r\n // Delay to ensure menu is fully closed before opening dialog\r\n setTimeout(() => {\r\n this.showStyleDialog();\r\n }, 50);\r\n });\r\n\r\n // Resize option\r\n const resizeOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.resizeWindow')\r\n }\r\n });\r\n const resizeIcon = createIconElement('resize');\r\n const resizeText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.resizeWindow')\r\n });\r\n resizeOption.appendChild(resizeIcon);\r\n resizeOption.appendChild(resizeText);\r\n resizeOption.addEventListener('click', () => {\r\n this.toggleResizeMode();\r\n this.hideSettingsMenu();\r\n });\r\n\r\n // Close option\r\n const closeOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.closeMenu')\r\n }\r\n });\r\n const closeIcon = createIconElement('close');\r\n const closeText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.closeMenu')\r\n });\r\n closeOption.appendChild(closeIcon);\r\n closeOption.appendChild(closeText);\r\n closeOption.addEventListener('click', () => {\r\n this.hideSettingsMenu();\r\n });\r\n\r\n this.settingsMenu.appendChild(keyboardDragOption);\r\n this.settingsMenu.appendChild(resizeOption);\r\n this.settingsMenu.appendChild(styleOption);\r\n this.settingsMenu.appendChild(closeOption);\r\n\r\n // Append menu to header left container for proper positioning\r\n if (this.headerLeft) {\r\n this.headerLeft.appendChild(this.settingsMenu);\r\n } else {\r\n this.transcriptHeader.appendChild(this.settingsMenu);\r\n }\r\n \r\n // Set the menu as visible and display it\r\n this.settingsMenuVisible = true;\r\n this.settingsMenu.style.display = 'block';\r\n \r\n // Update aria-expanded\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-expanded', 'true');\r\n }\r\n \r\n // Focus first menu item\r\n setTimeout(() => {\r\n const firstItem = this.settingsMenu.querySelector(`.${this.player.options.classPrefix}-transcript-settings-item`);\r\n if (firstItem) {\r\n firstItem.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Hide settings menu\r\n */\r\n hideSettingsMenu() {\r\n if (this.settingsMenu) {\r\n this.settingsMenu.style.display = 'none';\r\n this.settingsMenuVisible = false;\r\n this.settingsMenuJustOpened = false;\r\n \r\n // Update aria-expanded\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-expanded', 'false');\r\n // Return focus to settings button\r\n this.settingsButton.focus();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Enable move mode (gives visual feedback)\r\n */\r\n enableMoveMode() {\r\n // Add visual feedback for move mode\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-move-mode`);\r\n \r\n // Show tooltip about keyboard drag option\r\n const tooltip = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-move-tooltip`,\r\n textContent: 'Drag with mouse or press D for keyboard drag mode'\r\n });\r\n this.transcriptHeader.appendChild(tooltip);\r\n \r\n // Remove after 2 seconds\r\n setTimeout(() => {\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-move-mode`);\r\n if (tooltip.parentNode) {\r\n tooltip.remove();\r\n }\r\n }, 2000);\r\n }\r\n\r\n /**\r\n * Toggle resize mode\r\n */\r\n toggleResizeMode() {\r\n this.resizeEnabled = !this.resizeEnabled;\r\n \r\n if (this.resizeEnabled) {\r\n this.enableResizeHandles();\r\n } else {\r\n this.disableResizeHandles();\r\n }\r\n }\r\n\r\n /**\r\n * Enable resize handles\r\n */\r\n enableResizeHandles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Add resize handles if they don't exist\r\n const directions = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\r\n \r\n directions.forEach(direction => {\r\n const handle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-resize-handle ${this.player.options.classPrefix}-transcript-resize-${direction}`,\r\n attributes: {\r\n 'data-direction': direction\r\n }\r\n });\r\n\r\n handle.addEventListener('mousedown', (e) => this.startResize(e, direction));\r\n handle.addEventListener('touchstart', (e) => this.startResize(e.touches[0], direction));\r\n\r\n this.transcriptWindow.appendChild(handle);\r\n });\r\n\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-resizable`);\r\n\r\n // Setup resize event handlers\r\n this.handlers.resizeMove = (e) => {\r\n if (this.isResizing) {\r\n this.performResize(e.clientX, e.clientY);\r\n }\r\n };\r\n\r\n this.handlers.resizeEnd = () => {\r\n if (this.isResizing) {\r\n this.stopResize();\r\n }\r\n };\r\n\r\n this.handlers.resizeTouchMove = (e) => {\r\n if (this.isResizing) {\r\n this.performResize(e.touches[0].clientX, e.touches[0].clientY);\r\n e.preventDefault();\r\n }\r\n };\r\n\r\n document.addEventListener('mousemove', this.handlers.resizeMove);\r\n document.addEventListener('mouseup', this.handlers.resizeEnd);\r\n document.addEventListener('touchmove', this.handlers.resizeTouchMove);\r\n document.addEventListener('touchend', this.handlers.resizeEnd);\r\n }\r\n\r\n /**\r\n * Disable resize handles\r\n */\r\n disableResizeHandles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Remove all resize handles\r\n const handles = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-resize-handle`);\r\n handles.forEach(handle => handle.remove());\r\n\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-resizable`);\r\n\r\n // Remove resize event handlers\r\n if (this.handlers.resizeMove) {\r\n document.removeEventListener('mousemove', this.handlers.resizeMove);\r\n }\r\n if (this.handlers.resizeEnd) {\r\n document.removeEventListener('mouseup', this.handlers.resizeEnd);\r\n }\r\n if (this.handlers.resizeTouchMove) {\r\n document.removeEventListener('touchmove', this.handlers.resizeTouchMove);\r\n }\r\n document.removeEventListener('touchend', this.handlers.resizeEnd);\r\n }\r\n\r\n /**\r\n * Start resizing\r\n */\r\n startResize(e, direction) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n this.isResizing = true;\r\n this.resizeDirection = direction;\r\n this.resizeStartX = e.clientX;\r\n this.resizeStartY = e.clientY;\r\n\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n this.resizeStartWidth = rect.width;\r\n this.resizeStartHeight = rect.height;\r\n\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-resizing`);\r\n document.body.style.cursor = this.getResizeCursor(direction);\r\n document.body.style.userSelect = 'none';\r\n }\r\n\r\n /**\r\n * Perform resize\r\n */\r\n performResize(clientX, clientY) {\r\n if (!this.isResizing) return;\r\n\r\n const deltaX = clientX - this.resizeStartX;\r\n const deltaY = clientY - this.resizeStartY;\r\n\r\n let newWidth = this.resizeStartWidth;\r\n let newHeight = this.resizeStartHeight;\r\n\r\n const direction = this.resizeDirection;\r\n\r\n // Calculate new dimensions based on direction\r\n if (direction.includes('e')) {\r\n newWidth = this.resizeStartWidth + deltaX;\r\n }\r\n if (direction.includes('w')) {\r\n newWidth = this.resizeStartWidth - deltaX;\r\n }\r\n if (direction.includes('s')) {\r\n newHeight = this.resizeStartHeight + deltaY;\r\n }\r\n if (direction.includes('n')) {\r\n newHeight = this.resizeStartHeight - deltaY;\r\n }\r\n\r\n // Apply minimum and maximum constraints\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n const maxWidth = window.innerWidth - 40;\r\n const maxHeight = window.innerHeight - 40;\r\n\r\n newWidth = Math.max(minWidth, Math.min(newWidth, maxWidth));\r\n newHeight = Math.max(minHeight, Math.min(newHeight, maxHeight));\r\n\r\n // Apply new dimensions\r\n this.transcriptWindow.style.width = `${newWidth}px`;\r\n this.transcriptWindow.style.height = `${newHeight}px`;\r\n this.transcriptWindow.style.maxWidth = `${newWidth}px`;\r\n this.transcriptWindow.style.maxHeight = `${newHeight}px`;\r\n\r\n // Adjust position if resizing from top or left\r\n if (direction.includes('w')) {\r\n const currentLeft = parseFloat(this.transcriptWindow.style.left) || 0;\r\n this.transcriptWindow.style.left = `${currentLeft + (this.resizeStartWidth - newWidth)}px`;\r\n }\r\n if (direction.includes('n')) {\r\n const currentTop = parseFloat(this.transcriptWindow.style.top) || 0;\r\n this.transcriptWindow.style.top = `${currentTop + (this.resizeStartHeight - newHeight)}px`;\r\n }\r\n }\r\n\r\n /**\r\n * Stop resizing\r\n */\r\n stopResize() {\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-resizing`);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n }\r\n\r\n /**\r\n * Get cursor style for resize direction\r\n */\r\n getResizeCursor(direction) {\r\n const cursors = {\r\n 'n': 'ns-resize',\r\n 's': 'ns-resize',\r\n 'e': 'ew-resize',\r\n 'w': 'ew-resize',\r\n 'ne': 'nesw-resize',\r\n 'nw': 'nwse-resize',\r\n 'se': 'nwse-resize',\r\n 'sw': 'nesw-resize'\r\n };\r\n return cursors[direction] || 'default';\r\n }\r\n\r\n /**\r\n * Show style dialog\r\n */\r\n showStyleDialog() {\r\n // If dialog already exists, just show it\r\n if (this.styleDialog) {\r\n this.styleDialog.style.display = 'block';\r\n this.styleDialogVisible = true;\r\n \r\n // Set flag to prevent immediate closing from document click\r\n this.styleDialogJustOpened = true;\r\n setTimeout(() => {\r\n this.styleDialogJustOpened = false;\r\n }, 350);\r\n \r\n // Focus first control\r\n setTimeout(() => {\r\n const firstSelect = this.styleDialog.querySelector('select, input');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n return;\r\n }\r\n\r\n // Create style dialog\r\n this.styleDialog = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-dialog`\r\n });\r\n\r\n // Dialog title\r\n const title = DOMUtils.createElement('h4', {\r\n textContent: i18n.t('transcript.styleTitle'),\r\n className: `${this.player.options.classPrefix}-transcript-style-title`\r\n });\r\n this.styleDialog.appendChild(title);\r\n\r\n // Font Size\r\n const fontSizeControl = this.createStyleSelectControl(\r\n i18n.t('captions.fontSize'),\r\n 'fontSize',\r\n [\r\n { label: i18n.t('fontSizes.small'), value: '87.5%' },\r\n { label: i18n.t('fontSizes.normal'), value: '100%' },\r\n { label: i18n.t('fontSizes.large'), value: '125%' },\r\n { label: i18n.t('fontSizes.xlarge'), value: '150%' }\r\n ]\r\n );\r\n this.styleDialog.appendChild(fontSizeControl);\r\n\r\n // Font Family\r\n const fontFamilyControl = this.createStyleSelectControl(\r\n i18n.t('captions.fontFamily'),\r\n 'fontFamily',\r\n [\r\n { label: i18n.t('fontFamilies.sansSerif'), value: 'sans-serif' },\r\n { label: i18n.t('fontFamilies.serif'), value: 'serif' },\r\n { label: i18n.t('fontFamilies.monospace'), value: 'monospace' }\r\n ]\r\n );\r\n this.styleDialog.appendChild(fontFamilyControl);\r\n\r\n // Text Color\r\n const colorControl = this.createStyleColorControl(i18n.t('captions.color'), 'color');\r\n this.styleDialog.appendChild(colorControl);\r\n\r\n // Background Color\r\n const bgColorControl = this.createStyleColorControl(i18n.t('captions.backgroundColor'), 'backgroundColor');\r\n this.styleDialog.appendChild(bgColorControl);\r\n\r\n // Opacity\r\n const opacityControl = this.createStyleOpacityControl(i18n.t('captions.opacity'), 'opacity');\r\n this.styleDialog.appendChild(opacityControl);\r\n\r\n // Close button\r\n const closeBtn = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-style-close`,\r\n textContent: i18n.t('settings.close'),\r\n attributes: {\r\n 'type': 'button'\r\n }\r\n });\r\n closeBtn.addEventListener('click', () => this.hideStyleDialog());\r\n this.styleDialog.appendChild(closeBtn);\r\n\r\n // ESC key handler for style dialog\r\n this.handlers.styleDialogKeydown = (e) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideStyleDialog();\r\n }\r\n };\r\n this.styleDialog.addEventListener('keydown', this.handlers.styleDialogKeydown);\r\n\r\n // Append to header left container (same as settings menu) for correct positioning\r\n if (this.headerLeft) {\r\n this.headerLeft.appendChild(this.styleDialog);\r\n } else {\r\n this.transcriptHeader.appendChild(this.styleDialog);\r\n }\r\n \r\n // Apply current styles\r\n this.applyTranscriptStyles();\r\n \r\n // Important: Set visible state and display before focusing\r\n this.styleDialogVisible = true;\r\n this.styleDialog.style.display = 'block';\r\n \r\n // Set flag to prevent immediate closing from document click\r\n this.styleDialogJustOpened = true;\r\n setTimeout(() => {\r\n this.styleDialogJustOpened = false;\r\n }, 350);\r\n \r\n // Focus first control for keyboard accessibility\r\n setTimeout(() => {\r\n const firstSelect = this.styleDialog.querySelector('select, input');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Hide style dialog\r\n */\r\n hideStyleDialog() {\r\n if (this.styleDialog) {\r\n this.styleDialog.style.display = 'none';\r\n this.styleDialogVisible = false;\r\n \r\n // Return focus to settings button\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Create style select control\r\n */\r\n createStyleSelectControl(label, property, options) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const select = DOMUtils.createElement('select', {\r\n className: `${this.player.options.classPrefix}-transcript-style-select`\r\n });\r\n\r\n options.forEach(opt => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: opt.label,\r\n attributes: {\r\n 'value': opt.value\r\n }\r\n });\r\n if (this.transcriptStyle[property] === opt.value) {\r\n option.selected = true;\r\n }\r\n select.appendChild(option);\r\n });\r\n\r\n select.addEventListener('change', (e) => {\r\n this.transcriptStyle[property] = e.target.value;\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n group.appendChild(select);\r\n return group;\r\n }\r\n\r\n /**\r\n * Create style color control\r\n */\r\n createStyleColorControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n 'type': 'color',\r\n 'value': this.transcriptStyle[property]\r\n },\r\n className: `${this.player.options.classPrefix}-transcript-style-color`\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n this.transcriptStyle[property] = e.target.value;\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n /**\r\n * Create style opacity control\r\n */\r\n createStyleOpacityControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const valueDisplay = DOMUtils.createElement('span', {\r\n textContent: Math.round(this.transcriptStyle[property] * 100) + '%',\r\n className: `${this.player.options.classPrefix}-transcript-style-value`\r\n });\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n 'type': 'range',\r\n 'min': '0',\r\n 'max': '1',\r\n 'step': '0.1',\r\n 'value': String(this.transcriptStyle[property])\r\n },\r\n className: `${this.player.options.classPrefix}-transcript-style-range`\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n const value = parseFloat(e.target.value);\r\n this.transcriptStyle[property] = value;\r\n valueDisplay.textContent = Math.round(value * 100) + '%';\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n const inputContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-range-container`\r\n });\r\n inputContainer.appendChild(input);\r\n inputContainer.appendChild(valueDisplay);\r\n\r\n group.appendChild(labelEl);\r\n group.appendChild(inputContainer);\r\n return group;\r\n }\r\n\r\n /**\r\n * Save transcript preferences to localStorage\r\n */\r\n savePreferences() {\r\n this.storage.saveTranscriptPreferences(this.transcriptStyle);\r\n }\r\n\r\n /**\r\n * Apply transcript styles\r\n */\r\n applyTranscriptStyles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Apply to transcript window background\r\n this.transcriptWindow.style.backgroundColor = this.transcriptStyle.backgroundColor;\r\n this.transcriptWindow.style.opacity = String(this.transcriptStyle.opacity);\r\n\r\n // Apply to content area\r\n if (this.transcriptContent) {\r\n this.transcriptContent.style.fontSize = this.transcriptStyle.fontSize;\r\n this.transcriptContent.style.fontFamily = this.transcriptStyle.fontFamily;\r\n this.transcriptContent.style.color = this.transcriptStyle.color;\r\n }\r\n\r\n // Apply to all text entries (important: override CSS defaults)\r\n const textEntries = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-text`);\r\n textEntries.forEach(entry => {\r\n entry.style.fontSize = this.transcriptStyle.fontSize;\r\n entry.style.fontFamily = this.transcriptStyle.fontFamily;\r\n entry.style.color = this.transcriptStyle.color;\r\n });\r\n \r\n // Apply to timestamp entries as well\r\n const timeEntries = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-time`);\r\n timeEntries.forEach(entry => {\r\n entry.style.fontFamily = this.transcriptStyle.fontFamily;\r\n });\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Disable modes if active\r\n if (this.resizeEnabled) {\r\n this.disableResizeHandles();\r\n }\r\n if (this.keyboardDragMode) {\r\n this.disableKeyboardDragMode();\r\n }\r\n\r\n // Remove timeupdate listener from player\r\n if (this.handlers.timeupdate) {\r\n this.player.off('timeupdate', this.handlers.timeupdate);\r\n }\r\n\r\n // Remove drag event listeners\r\n if (this.transcriptHeader) {\r\n if (this.handlers.mousedown) {\r\n this.transcriptHeader.removeEventListener('mousedown', this.handlers.mousedown);\r\n }\r\n if (this.handlers.touchstart) {\r\n this.transcriptHeader.removeEventListener('touchstart', this.handlers.touchstart);\r\n }\r\n if (this.handlers.keydown) {\r\n this.transcriptHeader.removeEventListener('keydown', this.handlers.keydown);\r\n }\r\n }\r\n \r\n // Remove settings button event listeners\r\n if (this.settingsButton) {\r\n if (this.handlers.settingsClick) {\r\n this.settingsButton.removeEventListener('click', this.handlers.settingsClick);\r\n }\r\n if (this.handlers.settingsKeydown) {\r\n this.settingsButton.removeEventListener('keydown', this.handlers.settingsKeydown);\r\n }\r\n }\r\n \r\n // Remove style dialog event listeners\r\n if (this.styleDialog && this.handlers.styleDialogKeydown) {\r\n this.styleDialog.removeEventListener('keydown', this.handlers.styleDialogKeydown);\r\n }\r\n\r\n // Remove document-level listeners\r\n if (this.handlers.mousemove) {\r\n document.removeEventListener('mousemove', this.handlers.mousemove);\r\n }\r\n if (this.handlers.mouseup) {\r\n document.removeEventListener('mouseup', this.handlers.mouseup);\r\n }\r\n if (this.handlers.touchmove) {\r\n document.removeEventListener('touchmove', this.handlers.touchmove);\r\n }\r\n if (this.handlers.touchend) {\r\n document.removeEventListener('touchend', this.handlers.touchend);\r\n }\r\n if (this.handlers.documentClick) {\r\n document.removeEventListener('click', this.handlers.documentClick);\r\n }\r\n \r\n // Remove window-level listeners\r\n if (this.handlers.resize) {\r\n window.removeEventListener('resize', this.handlers.resize);\r\n }\r\n\r\n // Clear handlers\r\n this.handlers = null;\r\n\r\n // Remove DOM element\r\n if (this.transcriptWindow && this.transcriptWindow.parentNode) {\r\n this.transcriptWindow.parentNode.removeChild(this.transcriptWindow);\r\n }\r\n \r\n this.transcriptWindow = null;\r\n this.transcriptHeader = null;\r\n this.transcriptContent = null;\r\n this.transcriptEntries = [];\r\n this.settingsMenu = null;\r\n this.styleDialog = null;\r\n }\r\n}\r\n", "/**\r\n * VidPly - Universal Video Player\r\n * Main Player Class\r\n */\r\n\r\nimport {EventEmitter} from '../utils/EventEmitter.js';\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {ControlBar} from '../controls/ControlBar.js';\r\nimport {CaptionManager} from '../controls/CaptionManager.js';\r\nimport {KeyboardManager} from '../controls/KeyboardManager.js';\r\nimport {TranscriptManager} from '../controls/TranscriptManager.js';\r\nimport {HTML5Renderer} from '../renderers/HTML5Renderer.js';\r\nimport {YouTubeRenderer} from '../renderers/YouTubeRenderer.js';\r\nimport {VimeoRenderer} from '../renderers/VimeoRenderer.js';\r\nimport {HLSRenderer} from '../renderers/HLSRenderer.js';\r\nimport {createPlayOverlay} from '../icons/Icons.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\nimport {StorageManager} from '../utils/StorageManager.js';\r\n\r\nexport class Player extends EventEmitter {\r\n constructor(element, options = {}) {\r\n super();\r\n\r\n this.element = typeof element === 'string' ? document.querySelector(element) : element;\r\n if (!this.element) {\r\n throw new Error('VidPly: Element not found');\r\n }\r\n\r\n // Auto-create media element if a non-media element is provided\r\n if (this.element.tagName !== 'VIDEO' && this.element.tagName !== 'AUDIO') {\r\n const mediaType = options.mediaType || 'video';\r\n const mediaElement = document.createElement(mediaType);\r\n\r\n // Copy attributes from the div to the media element\r\n Array.from(this.element.attributes).forEach(attr => {\r\n if (attr.name !== 'id' && attr.name !== 'class' && !attr.name.startsWith('data-')) {\r\n mediaElement.setAttribute(attr.name, attr.value);\r\n }\r\n });\r\n\r\n // Copy any track elements from the div\r\n const tracks = this.element.querySelectorAll('track');\r\n tracks.forEach(track => {\r\n mediaElement.appendChild(track.cloneNode(true));\r\n });\r\n\r\n // Clear the div and insert the media element\r\n this.element.innerHTML = '';\r\n this.element.appendChild(mediaElement);\r\n\r\n // Update element reference to the actual media element\r\n this.element = mediaElement;\r\n }\r\n\r\n // Default options\r\n this.options = {\r\n // Display\r\n width: null,\r\n height: null,\r\n poster: null,\r\n responsive: true,\r\n fillContainer: false,\r\n\r\n // Playback\r\n autoplay: false,\r\n loop: false,\r\n muted: false,\r\n volume: 0.8,\r\n playbackSpeed: 1.0,\r\n preload: 'metadata',\r\n startTime: 0,\r\n playsInline: true, // Enable inline playback on iOS (prevents native fullscreen)\r\n\r\n // Controls\r\n controls: true,\r\n hideControlsDelay: 3000,\r\n playPauseButton: true,\r\n progressBar: true,\r\n currentTime: true,\r\n duration: true,\r\n volumeControl: true,\r\n muteButton: true,\r\n chaptersButton: true,\r\n qualityButton: true,\r\n captionStyleButton: true,\r\n speedButton: true,\r\n captionsButton: true,\r\n transcriptButton: true,\r\n fullscreenButton: true,\r\n pipButton: false,\r\n\r\n // Seeking\r\n seekInterval: 10,\r\n seekIntervalLarge: 30,\r\n\r\n // Captions\r\n captions: true,\r\n captionsDefault: false,\r\n captionsFontSize: '100%',\r\n captionsFontFamily: 'sans-serif',\r\n captionsColor: '#FFFFFF',\r\n captionsBackgroundColor: '#000000',\r\n captionsOpacity: 0.8,\r\n\r\n // Audio Description\r\n audioDescription: true,\r\n audioDescriptionSrc: null, // URL to audio-described version\r\n audioDescriptionButton: true,\r\n\r\n // Sign Language\r\n signLanguage: true,\r\n signLanguageSrc: null, // URL to sign language video\r\n signLanguageButton: true,\r\n signLanguagePosition: 'bottom-right', // Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'\r\n\r\n // Transcripts\r\n transcript: false,\r\n transcriptPosition: 'external',\r\n transcriptContainer: null,\r\n\r\n // Keyboard\r\n keyboard: true,\r\n keyboardShortcuts: {\r\n 'play-pause': [' ', 'p', 'k'],\r\n 'volume-up': ['ArrowUp'],\r\n 'volume-down': ['ArrowDown'],\r\n 'seek-forward': ['ArrowRight'],\r\n 'seek-backward': ['ArrowLeft'],\r\n 'mute': ['m'],\r\n 'fullscreen': ['f'],\r\n 'captions': ['c'],\r\n 'caption-style-menu': ['a'],\r\n 'speed-up': ['>'],\r\n 'speed-down': ['<'],\r\n 'speed-menu': ['s'],\r\n 'quality-menu': ['q'],\r\n 'chapters-menu': ['j'],\r\n 'transcript-toggle': ['t']\r\n },\r\n\r\n // Accessibility\r\n ariaLabels: {},\r\n screenReaderAnnouncements: true,\r\n highContrast: false,\r\n focusHighlight: true,\r\n\r\n // Languages\r\n language: 'en',\r\n languages: ['en'],\r\n\r\n // Advanced\r\n debug: false,\r\n classPrefix: 'vidply',\r\n iconType: 'svg',\r\n pauseOthersOnPlay: true,\r\n\r\n // Callbacks\r\n onReady: null,\r\n onPlay: null,\r\n onPause: null,\r\n onEnded: null,\r\n onTimeUpdate: null,\r\n onVolumeChange: null,\r\n onError: null,\r\n\r\n ...options\r\n };\r\n\r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Load saved player preferences\r\n const savedPrefs = this.storage.getPlayerPreferences();\r\n if (savedPrefs) {\r\n if (savedPrefs.volume !== undefined) this.options.volume = savedPrefs.volume;\r\n if (savedPrefs.playbackSpeed !== undefined) this.options.playbackSpeed = savedPrefs.playbackSpeed;\r\n if (savedPrefs.muted !== undefined) this.options.muted = savedPrefs.muted;\r\n }\r\n \r\n // State\r\n this.state = {\r\n ready: false,\r\n playing: false,\r\n paused: true,\r\n ended: false,\r\n buffering: false,\r\n seeking: false,\r\n muted: this.options.muted,\r\n volume: this.options.volume,\r\n currentTime: 0,\r\n duration: 0,\r\n playbackSpeed: this.options.playbackSpeed,\r\n fullscreen: false,\r\n pip: false,\r\n captionsEnabled: this.options.captionsDefault,\r\n currentCaption: null,\r\n controlsVisible: true,\r\n audioDescriptionEnabled: false,\r\n signLanguageEnabled: false\r\n };\r\n\r\n // Store original source for toggling\r\n this.originalSrc = null;\r\n this.audioDescriptionSrc = this.options.audioDescriptionSrc;\r\n this.signLanguageSrc = this.options.signLanguageSrc;\r\n this.signLanguageVideo = null;\r\n // Store references to source elements with audio description attributes\r\n this.audioDescriptionSourceElement = null;\r\n this.originalAudioDescriptionSource = null;\r\n // Store caption tracks that should be swapped for audio description\r\n this.audioDescriptionCaptionTracks = [];\r\n\r\n // Components\r\n this.container = null;\r\n this.renderer = null;\r\n this.controlBar = null;\r\n this.captionManager = null;\r\n this.keyboardManager = null;\r\n this.settingsDialog = null;\r\n\r\n // Initialize\r\n this.init();\r\n }\r\n\r\n async init() {\r\n try {\r\n this.log('Initializing VidPly player');\r\n\r\n // Auto-detect language from HTML lang attribute if not explicitly set\r\n if (!this.options.language || this.options.language === 'en') {\r\n const htmlLang = this.detectHtmlLanguage();\r\n if (htmlLang) {\r\n this.options.language = htmlLang;\r\n this.log(`Auto-detected language from HTML: ${htmlLang}`);\r\n }\r\n }\r\n\r\n // Set language\r\n i18n.setLanguage(this.options.language);\r\n\r\n // Create container\r\n this.createContainer();\r\n\r\n // Detect and initialize renderer (only if source exists)\r\n const src = this.element.src || this.element.querySelector('source')?.src;\r\n if (src) {\r\n await this.initializeRenderer();\r\n } else {\r\n this.log('No initial source - waiting for playlist or manual load');\r\n }\r\n\r\n // Create controls\r\n if (this.options.controls) {\r\n this.controlBar = new ControlBar(this);\r\n this.videoWrapper.appendChild(this.controlBar.element);\r\n }\r\n\r\n // Initialize captions\r\n if (this.options.captions) {\r\n this.captionManager = new CaptionManager(this);\r\n }\r\n\r\n // Initialize transcript\r\n if (this.options.transcript || this.options.transcriptButton) {\r\n this.transcriptManager = new TranscriptManager(this);\r\n }\r\n\r\n // Initialize keyboard controls\r\n if (this.options.keyboard) {\r\n this.keyboardManager = new KeyboardManager(this);\r\n }\r\n\r\n // Setup responsive handlers\r\n this.setupResponsiveHandlers();\r\n\r\n // Set initial state\r\n if (this.options.startTime > 0) {\r\n this.seek(this.options.startTime);\r\n }\r\n\r\n if (this.options.muted) {\r\n this.mute();\r\n }\r\n\r\n if (this.options.volume !== 0.8) {\r\n this.setVolume(this.options.volume);\r\n }\r\n\r\n // Mark as ready\r\n this.state.ready = true;\r\n this.emit('ready');\r\n\r\n if (this.options.onReady) {\r\n this.options.onReady.call(this);\r\n }\r\n\r\n // Autoplay if enabled\r\n if (this.options.autoplay) {\r\n this.play();\r\n }\r\n\r\n this.log('Player initialized successfully');\r\n } catch (error) {\r\n this.handleError(error);\r\n }\r\n }\r\n\r\n /**\r\n * Detect language from HTML lang attribute\r\n * @returns {string|null} Language code if available in translations, null otherwise\r\n */\r\n detectHtmlLanguage() {\r\n // Try to get lang from html element\r\n const htmlLang = document.documentElement.lang || document.documentElement.getAttribute('lang');\r\n\r\n if (!htmlLang) {\r\n return null;\r\n }\r\n\r\n // Normalize the language code (e.g., \"en-US\" -> \"en\", \"de-DE\" -> \"de\")\r\n const normalizedLang = htmlLang.toLowerCase().split('-')[0];\r\n\r\n // Check if this language is available in our translations\r\n const availableLanguages = ['en', 'de', 'es', 'fr', 'ja'];\r\n\r\n if (availableLanguages.includes(normalizedLang)) {\r\n return normalizedLang;\r\n }\r\n\r\n // Language not available, will fallback to English\r\n this.log(`Language \"${htmlLang}\" not available, using English as fallback`);\r\n return 'en';\r\n }\r\n\r\n createContainer() {\r\n // Create main container\r\n this.container = DOMUtils.createElement('div', {\r\n className: `${this.options.classPrefix}-player`,\r\n attributes: {\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.label'),\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Add media type class\r\n const mediaType = this.element.tagName.toLowerCase();\r\n this.container.classList.add(`${this.options.classPrefix}-${mediaType}`);\r\n\r\n // Add responsive class\r\n if (this.options.responsive) {\r\n this.container.classList.add(`${this.options.classPrefix}-responsive`);\r\n }\r\n\r\n // Create video wrapper (for proper positioning of controls)\r\n this.videoWrapper = DOMUtils.createElement('div', {\r\n className: `${this.options.classPrefix}-video-wrapper`\r\n });\r\n\r\n // Wrap original element\r\n this.element.parentNode.insertBefore(this.container, this.element);\r\n this.container.appendChild(this.videoWrapper);\r\n this.videoWrapper.appendChild(this.element);\r\n\r\n // Hide native controls and set dimensions\r\n this.element.controls = false;\r\n this.element.removeAttribute('controls');\r\n this.element.setAttribute('tabindex', '-1'); // Remove from tab order\r\n this.element.style.width = '100%';\r\n this.element.style.height = '100%';\r\n\r\n // Enable inline playback on iOS (prevents native fullscreen)\r\n // This allows custom controls to work on iOS devices\r\n if (this.element.tagName === 'VIDEO' && this.options.playsInline) {\r\n this.element.setAttribute('playsinline', '');\r\n this.element.setAttribute('webkit-playsinline', ''); // For older iOS versions\r\n this.element.playsInline = true; // Property version\r\n }\r\n\r\n // Set dimensions\r\n if (this.options.width) {\r\n this.container.style.width = typeof this.options.width === 'number'\r\n ? `${this.options.width}px`\r\n : this.options.width;\r\n }\r\n\r\n if (this.options.height) {\r\n this.container.style.height = typeof this.options.height === 'number'\r\n ? `${this.options.height}px`\r\n : this.options.height;\r\n }\r\n\r\n // Set poster\r\n if (this.options.poster && this.element.tagName === 'VIDEO') {\r\n this.element.poster = this.options.poster;\r\n }\r\n\r\n // Create centered play button overlay (only for video)\r\n if (this.element.tagName === 'VIDEO') {\r\n this.createPlayButtonOverlay();\r\n }\r\n\r\n // Make video/audio element clickable to toggle play/pause\r\n this.element.style.cursor = 'pointer';\r\n this.element.addEventListener('click', (e) => {\r\n // Prevent if clicking on native controls (shouldn't happen but just in case)\r\n if (e.target === this.element) {\r\n this.toggle();\r\n }\r\n });\r\n }\r\n\r\n createPlayButtonOverlay() {\r\n // Create complete SVG play button from Icons.js\r\n this.playButtonOverlay = createPlayOverlay();\r\n\r\n // Add click handler\r\n this.playButtonOverlay.addEventListener('click', () => {\r\n this.toggle();\r\n });\r\n\r\n // Add to video wrapper\r\n this.videoWrapper.appendChild(this.playButtonOverlay);\r\n\r\n // Show/hide based on play state\r\n this.on('play', () => {\r\n this.playButtonOverlay.style.opacity = '0';\r\n this.playButtonOverlay.style.pointerEvents = 'none';\r\n });\r\n\r\n this.on('pause', () => {\r\n this.playButtonOverlay.style.opacity = '1';\r\n this.playButtonOverlay.style.pointerEvents = 'auto';\r\n });\r\n\r\n this.on('ended', () => {\r\n this.playButtonOverlay.style.opacity = '1';\r\n this.playButtonOverlay.style.pointerEvents = 'auto';\r\n });\r\n }\r\n\r\n async initializeRenderer() {\r\n const src = this.element.src || this.element.querySelector('source')?.src;\r\n\r\n if (!src) {\r\n throw new Error('No media source found');\r\n }\r\n\r\n // Check for source elements with audio description attributes\r\n const sourceElements = this.element.querySelectorAll('source');\r\n for (const sourceEl of sourceElements) {\r\n const descSrc = sourceEl.getAttribute('data-desc-src');\r\n const origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n if (descSrc || origSrc) {\r\n // Found a source element with audio description attributes\r\n // Store the first one as reference, but we'll search all of them when toggling\r\n if (!this.audioDescriptionSourceElement) {\r\n this.audioDescriptionSourceElement = sourceEl;\r\n }\r\n \r\n if (origSrc) {\r\n // Store the original src from the attribute for this source\r\n if (!this.originalAudioDescriptionSource) {\r\n this.originalAudioDescriptionSource = origSrc;\r\n }\r\n // Store the original src from the first source element that has data-orig-src\r\n if (!this.originalSrc) {\r\n this.originalSrc = origSrc;\r\n }\r\n } else {\r\n // If data-orig-src is not set, use the current src attribute\r\n const currentSrcAttr = sourceEl.getAttribute('src');\r\n if (!this.originalAudioDescriptionSource && currentSrcAttr) {\r\n this.originalAudioDescriptionSource = currentSrcAttr;\r\n }\r\n if (!this.originalSrc && currentSrcAttr) {\r\n this.originalSrc = currentSrcAttr;\r\n }\r\n }\r\n \r\n // Store audio description source from data-desc-src (use first one found)\r\n if (descSrc && !this.audioDescriptionSrc) {\r\n this.audioDescriptionSrc = descSrc;\r\n }\r\n // Continue checking all source elements to ensure we capture all audio description sources\r\n }\r\n }\r\n\r\n // Check for caption/subtitle tracks with audio description versions\r\n // Only tracks with explicit data-desc-src attribute are swapped (no auto-detection to avoid 404 errors)\r\n // Description tracks (kind=\"descriptions\") are NOT swapped - they're for transcripts\r\n const trackElements = this.element.querySelectorAll('track');\r\n trackElements.forEach(trackEl => {\r\n const trackKind = trackEl.getAttribute('kind');\r\n const trackDescSrc = trackEl.getAttribute('data-desc-src');\r\n \r\n // Only handle caption/subtitle tracks (not description tracks)\r\n // Description tracks stay as-is since they're for transcripts\r\n // Include captions, subtitles, and chapters tracks that can be swapped for audio description\r\n if (trackKind === 'captions' || trackKind === 'subtitles' || trackKind === 'chapters') {\r\n if (trackDescSrc) {\r\n // Found a track with explicit data-desc-src - this is the described version\r\n this.audioDescriptionCaptionTracks.push({\r\n trackElement: trackEl,\r\n originalSrc: trackEl.getAttribute('src'),\r\n describedSrc: trackDescSrc,\r\n originalTrackSrc: trackEl.getAttribute('data-orig-src') || trackEl.getAttribute('src'),\r\n explicit: true // Explicitly defined, so we should validate it\r\n });\r\n this.log(`Found explicit described ${trackKind} track: ${trackEl.getAttribute('src')} -> ${trackDescSrc}`);\r\n }\r\n // Note: Auto-detection disabled to avoid 404 console errors\r\n // If you want described tracks, add data-desc-src attribute to the track element\r\n }\r\n // Description tracks (kind=\"descriptions\") are ignored - they remain unchanged for transcripts\r\n });\r\n\r\n // Store original source for audio description toggling (fallback if not set above)\r\n if (!this.originalSrc) {\r\n this.originalSrc = src;\r\n }\r\n\r\n // Detect media type\r\n let renderer;\r\n\r\n if (src.includes('youtube.com') || src.includes('youtu.be')) {\r\n renderer = YouTubeRenderer;\r\n } else if (src.includes('vimeo.com')) {\r\n renderer = VimeoRenderer;\r\n } else if (src.includes('.m3u8')) {\r\n renderer = HLSRenderer;\r\n } else {\r\n renderer = HTML5Renderer;\r\n }\r\n\r\n this.log(`Using ${renderer.name} renderer`);\r\n this.renderer = new renderer(this);\r\n await this.renderer.init();\r\n }\r\n\r\n /**\r\n * Load new media source (for playlists)\r\n * @param {Object} config - Media configuration\r\n * @param {string} config.src - Media source URL\r\n * @param {string} config.type - Media MIME type\r\n * @param {string} [config.poster] - Poster image URL\r\n * @param {Array} [config.tracks] - Text tracks (captions, chapters, etc.)\r\n */\r\n async load(config) {\r\n try {\r\n this.log('Loading new media:', config.src);\r\n\r\n // Pause current playback\r\n if (this.renderer) {\r\n this.pause();\r\n }\r\n\r\n // Clear existing text tracks\r\n const existingTracks = this.element.querySelectorAll('track');\r\n existingTracks.forEach(track => track.remove());\r\n\r\n // Update media element\r\n this.element.src = config.src;\r\n\r\n if (config.type) {\r\n this.element.type = config.type;\r\n }\r\n\r\n if (config.poster && this.element.tagName === 'VIDEO') {\r\n this.element.poster = config.poster;\r\n }\r\n\r\n // Add new text tracks\r\n if (config.tracks && config.tracks.length > 0) {\r\n config.tracks.forEach(trackConfig => {\r\n const track = document.createElement('track');\r\n track.src = trackConfig.src;\r\n track.kind = trackConfig.kind || 'captions';\r\n track.srclang = trackConfig.srclang || 'en';\r\n track.label = trackConfig.label || trackConfig.srclang;\r\n\r\n if (trackConfig.default) {\r\n track.default = true;\r\n }\r\n\r\n this.element.appendChild(track);\r\n });\r\n }\r\n\r\n // Check if we need to change renderer type\r\n const shouldChangeRenderer = this.shouldChangeRenderer(config.src);\r\n\r\n // Destroy old renderer if changing types\r\n if (shouldChangeRenderer && this.renderer) {\r\n this.renderer.destroy();\r\n this.renderer = null;\r\n }\r\n\r\n // Initialize or reinitialize renderer\r\n if (!this.renderer || shouldChangeRenderer) {\r\n await this.initializeRenderer();\r\n } else {\r\n // Just reload the current renderer with the updated element\r\n this.renderer.media = this.element; // Update media reference\r\n this.element.load();\r\n }\r\n\r\n // Reinitialize caption manager to pick up new tracks\r\n if (this.captionManager) {\r\n this.captionManager.destroy();\r\n this.captionManager = new CaptionManager(this);\r\n }\r\n \r\n // Reinitialize transcript manager to pick up new tracks\r\n if (this.transcriptManager) {\r\n const wasVisible = this.transcriptManager.isVisible;\r\n this.transcriptManager.destroy();\r\n this.transcriptManager = new TranscriptManager(this);\r\n \r\n // Restore visibility state if transcript was open\r\n if (wasVisible) {\r\n this.transcriptManager.showTranscript();\r\n }\r\n }\r\n \r\n // Update control bar to show/hide feature buttons based on new tracks\r\n if (this.controlBar) {\r\n this.updateControlBar();\r\n }\r\n\r\n this.emit('sourcechange', config);\r\n this.log('Media loaded successfully');\r\n\r\n } catch (error) {\r\n this.handleError(error);\r\n }\r\n }\r\n\r\n /**\r\n * Check if we need to change renderer type\r\n * @param {string} src - New source URL\r\n * @returns {boolean}\r\n */\r\n /**\r\n * Update control bar to refresh button visibility based on available features\r\n */\r\n updateControlBar() {\r\n if (!this.controlBar) return;\r\n \r\n const controlBar = this.controlBar;\r\n \r\n // Clear existing controls content\r\n controlBar.element.innerHTML = '';\r\n \r\n // Recreate controls with updated feature detection\r\n controlBar.createControls();\r\n \r\n // Reattach events for the new controls\r\n controlBar.attachEvents();\r\n controlBar.setupAutoHide();\r\n }\r\n \r\n shouldChangeRenderer(src) {\r\n if (!this.renderer) return true;\r\n\r\n const isYouTube = src.includes('youtube.com') || src.includes('youtu.be');\r\n const isVimeo = src.includes('vimeo.com');\r\n const isHLS = src.includes('.m3u8');\r\n\r\n const currentRendererName = this.renderer.constructor.name;\r\n\r\n if (isYouTube && currentRendererName !== 'YouTubeRenderer') return true;\r\n if (isVimeo && currentRendererName !== 'VimeoRenderer') return true;\r\n if (isHLS && currentRendererName !== 'HLSRenderer') return true;\r\n if (!isYouTube && !isVimeo && !isHLS && currentRendererName !== 'HTML5Renderer') return true;\r\n\r\n return false;\r\n }\r\n\r\n // Playback controls\r\n play() {\r\n if (this.renderer) {\r\n this.renderer.play();\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.renderer) {\r\n this.renderer.pause();\r\n }\r\n }\r\n\r\n stop() {\r\n this.pause();\r\n this.seek(0);\r\n }\r\n\r\n toggle() {\r\n if (this.state.playing) {\r\n this.pause();\r\n } else {\r\n this.play();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.renderer) {\r\n this.renderer.seek(time);\r\n }\r\n }\r\n\r\n seekForward(interval = this.options.seekInterval) {\r\n this.seek(Math.min(this.state.currentTime + interval, this.state.duration));\r\n }\r\n\r\n seekBackward(interval = this.options.seekInterval) {\r\n this.seek(Math.max(this.state.currentTime - interval, 0));\r\n }\r\n\r\n // Volume controls\r\n setVolume(volume) {\r\n const newVolume = Math.max(0, Math.min(1, volume));\r\n if (this.renderer) {\r\n this.renderer.setVolume(newVolume);\r\n }\r\n this.state.volume = newVolume;\r\n\r\n if (newVolume > 0 && this.state.muted) {\r\n this.state.muted = false;\r\n }\r\n \r\n this.savePlayerPreferences();\r\n }\r\n\r\n getVolume() {\r\n return this.state.volume;\r\n }\r\n\r\n mute() {\r\n if (this.renderer) {\r\n this.renderer.setMuted(true);\r\n }\r\n this.state.muted = true;\r\n this.savePlayerPreferences();\r\n this.emit('volumechange');\r\n }\r\n\r\n unmute() {\r\n if (this.renderer) {\r\n this.renderer.setMuted(false);\r\n }\r\n this.state.muted = false;\r\n this.savePlayerPreferences();\r\n this.emit('volumechange');\r\n }\r\n\r\n toggleMute() {\r\n if (this.state.muted) {\r\n this.unmute();\r\n } else {\r\n this.mute();\r\n }\r\n }\r\n\r\n // Playback speed\r\n setPlaybackSpeed(speed) {\r\n const newSpeed = Math.max(0.25, Math.min(2, speed));\r\n if (this.renderer) {\r\n this.renderer.setPlaybackSpeed(newSpeed);\r\n }\r\n this.state.playbackSpeed = newSpeed;\r\n this.savePlayerPreferences();\r\n this.emit('playbackspeedchange', newSpeed);\r\n }\r\n\r\n getPlaybackSpeed() {\r\n return this.state.playbackSpeed;\r\n }\r\n \r\n // Save player preferences to localStorage\r\n savePlayerPreferences() {\r\n this.storage.savePlayerPreferences({\r\n volume: this.state.volume,\r\n muted: this.state.muted,\r\n playbackSpeed: this.state.playbackSpeed\r\n });\r\n }\r\n\r\n // Fullscreen\r\n enterFullscreen() {\r\n const elem = this.container;\r\n\r\n if (elem.requestFullscreen) {\r\n elem.requestFullscreen();\r\n } else if (elem.webkitRequestFullscreen) {\r\n elem.webkitRequestFullscreen();\r\n } else if (elem.mozRequestFullScreen) {\r\n elem.mozRequestFullScreen();\r\n } else if (elem.msRequestFullscreen) {\r\n elem.msRequestFullscreen();\r\n }\r\n\r\n this.state.fullscreen = true;\r\n this.container.classList.add(`${this.options.classPrefix}-fullscreen`);\r\n this.emit('fullscreenchange', true);\r\n }\r\n\r\n exitFullscreen() {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if (document.webkitExitFullscreen) {\r\n document.webkitExitFullscreen();\r\n } else if (document.mozCancelFullScreen) {\r\n document.mozCancelFullScreen();\r\n } else if (document.msExitFullscreen) {\r\n document.msExitFullscreen();\r\n }\r\n\r\n this.state.fullscreen = false;\r\n this.container.classList.remove(`${this.options.classPrefix}-fullscreen`);\r\n this.emit('fullscreenchange', false);\r\n }\r\n\r\n toggleFullscreen() {\r\n if (this.state.fullscreen) {\r\n this.exitFullscreen();\r\n } else {\r\n this.enterFullscreen();\r\n }\r\n }\r\n\r\n // Picture-in-Picture\r\n enterPiP() {\r\n if (this.element.requestPictureInPicture) {\r\n this.element.requestPictureInPicture();\r\n this.state.pip = true;\r\n this.emit('pipchange', true);\r\n }\r\n }\r\n\r\n exitPiP() {\r\n if (document.pictureInPictureElement) {\r\n document.exitPictureInPicture();\r\n this.state.pip = false;\r\n this.emit('pipchange', false);\r\n }\r\n }\r\n\r\n togglePiP() {\r\n if (this.state.pip) {\r\n this.exitPiP();\r\n } else {\r\n this.enterPiP();\r\n }\r\n }\r\n\r\n // Captions\r\n enableCaptions() {\r\n if (this.captionManager) {\r\n this.captionManager.enable();\r\n this.state.captionsEnabled = true;\r\n }\r\n }\r\n\r\n disableCaptions() {\r\n if (this.captionManager) {\r\n this.captionManager.disable();\r\n this.state.captionsEnabled = false;\r\n }\r\n }\r\n\r\n toggleCaptions() {\r\n if (this.state.captionsEnabled) {\r\n this.disableCaptions();\r\n } else {\r\n this.enableCaptions();\r\n }\r\n }\r\n\r\n /**\r\n * Check if a track file exists\r\n * @param {string} url - Track file URL\r\n * @returns {Promise<boolean>} - True if file exists\r\n */\r\n async validateTrackExists(url) {\r\n try {\r\n const response = await fetch(url, { method: 'HEAD', cache: 'no-cache' });\r\n return response.ok;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n // Audio Description\r\n async enableAudioDescription() {\r\n // Check if we have source elements with data-desc-src (even if audioDescriptionSrc is not set)\r\n const hasSourceElementsWithDesc = Array.from(this.element.querySelectorAll('source')).some(el => el.getAttribute('data-desc-src'));\r\n const hasTracksWithDesc = this.audioDescriptionCaptionTracks.length > 0;\r\n \r\n if (!this.audioDescriptionSrc && !hasSourceElementsWithDesc && !hasTracksWithDesc) {\r\n console.warn('VidPly: No audio description source, source elements, or tracks provided');\r\n return;\r\n }\r\n\r\n // Store current playback state\r\n const currentTime = this.state.currentTime;\r\n const wasPlaying = this.state.playing;\r\n\r\n // Store swapped tracks for transcript reload (declare at function scope)\r\n let swappedTracksForTranscript = [];\r\n\r\n // Switch to audio-described version\r\n // If we have a source element with audio description attributes, update that instead\r\n if (this.audioDescriptionSourceElement) {\r\n const currentSrc = this.element.currentSrc || this.element.src;\r\n \r\n // Find the source element that matches the currently active source\r\n const sourceElements = Array.from(this.element.querySelectorAll('source'));\r\n let sourceElementToUpdate = null;\r\n let descSrc = this.audioDescriptionSrc;\r\n \r\n for (const sourceEl of sourceElements) {\r\n const sourceSrc = sourceEl.getAttribute('src');\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n \r\n // Check if this source matches the current source (by filename)\r\n // Match by full path or just filename\r\n const sourceFilename = sourceSrc ? sourceSrc.split('/').pop() : '';\r\n const currentFilename = currentSrc ? currentSrc.split('/').pop() : '';\r\n \r\n if (currentSrc && (currentSrc === sourceSrc || \r\n currentSrc.includes(sourceSrc) || \r\n currentSrc.includes(sourceFilename) ||\r\n (sourceFilename && currentFilename === sourceFilename))) {\r\n sourceElementToUpdate = sourceEl;\r\n if (descSrcAttr) {\r\n descSrc = descSrcAttr;\r\n } else if (sourceSrc) {\r\n // If no data-desc-src, try to construct it from the source\r\n // But prefer the stored audioDescriptionSrc if available\r\n descSrc = this.audioDescriptionSrc || descSrc;\r\n }\r\n break;\r\n }\r\n }\r\n \r\n // If we didn't find a match, use the stored source element\r\n if (!sourceElementToUpdate) {\r\n sourceElementToUpdate = this.audioDescriptionSourceElement;\r\n // Ensure we have the correct descSrc from the stored element\r\n const storedDescSrc = sourceElementToUpdate.getAttribute('data-desc-src');\r\n if (storedDescSrc) {\r\n descSrc = storedDescSrc;\r\n }\r\n }\r\n \r\n // Swap caption tracks to described versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n // Swap tracks: validate explicit tracks, but try auto-detected tracks without validation\r\n // This avoids 404 errors while still allowing auto-detection to work\r\n const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {\r\n if (trackInfo.trackElement && trackInfo.describedSrc) {\r\n // Only validate explicitly defined tracks (to confirm they exist)\r\n // Auto-detected tracks are used without validation (browser will handle missing files gracefully)\r\n if (trackInfo.explicit === true) {\r\n try {\r\n const exists = await this.validateTrackExists(trackInfo.describedSrc);\r\n return { trackInfo, exists };\r\n } catch (error) {\r\n // Silently handle validation errors\r\n return { trackInfo, exists: false };\r\n }\r\n } else {\r\n // This shouldn't happen since auto-detection is disabled\r\n // But if it does, don't validate to avoid 404s\r\n return { trackInfo, exists: false };\r\n }\r\n }\r\n return { trackInfo, exists: false };\r\n });\r\n \r\n const validationResults = await Promise.all(validationPromises);\r\n const tracksToSwap = validationResults.filter(result => result.exists);\r\n \r\n if (tracksToSwap.length > 0) {\r\n // Store original track modes before removing tracks\r\n const trackModes = new Map();\r\n tracksToSwap.forEach(({ trackInfo }) => {\r\n const textTrack = trackInfo.trackElement.track;\r\n if (textTrack) {\r\n trackModes.set(trackInfo, {\r\n wasShowing: textTrack.mode === 'showing',\r\n wasHidden: textTrack.mode === 'hidden'\r\n });\r\n } else {\r\n trackModes.set(trackInfo, {\r\n wasShowing: false,\r\n wasHidden: false\r\n });\r\n }\r\n });\r\n \r\n // Store all track information before removing\r\n const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {\r\n const oldSrc = trackInfo.trackElement.getAttribute('src');\r\n const parent = trackInfo.trackElement.parentNode;\r\n const nextSibling = trackInfo.trackElement.nextSibling;\r\n \r\n // Store all attributes from the old track\r\n const attributes = {};\r\n Array.from(trackInfo.trackElement.attributes).forEach(attr => {\r\n attributes[attr.name] = attr.value;\r\n });\r\n \r\n return {\r\n trackInfo,\r\n oldSrc,\r\n parent,\r\n nextSibling,\r\n attributes\r\n };\r\n });\r\n \r\n // Remove ALL old tracks first to force browser to clear TextTrack objects\r\n tracksToReadd.forEach(({ trackInfo }) => {\r\n trackInfo.trackElement.remove();\r\n });\r\n \r\n // Force browser to process the removal by calling load()\r\n this.element.load();\r\n \r\n // Wait for browser to process the removal, then add new tracks\r\n setTimeout(() => {\r\n tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {\r\n swappedTracksForTranscript.push(trackInfo);\r\n \r\n // Create a completely new track element (not a clone) to force browser to create new TextTrack\r\n const newTrackElement = document.createElement('track');\r\n newTrackElement.setAttribute('src', trackInfo.describedSrc);\r\n \r\n // Copy all attributes except src and data-desc-src\r\n Object.keys(attributes).forEach(attrName => {\r\n if (attrName !== 'src' && attrName !== 'data-desc-src') {\r\n newTrackElement.setAttribute(attrName, attributes[attrName]);\r\n }\r\n });\r\n \r\n // Insert new track element\r\n if (nextSibling && nextSibling.parentNode) {\r\n parent.insertBefore(newTrackElement, nextSibling);\r\n } else {\r\n parent.appendChild(newTrackElement);\r\n }\r\n \r\n // Update reference to the new track element\r\n trackInfo.trackElement = newTrackElement;\r\n });\r\n \r\n // After all new tracks are added, force browser to reload media element again\r\n // This ensures new track elements are processed and new TextTrack objects are created\r\n this.element.load();\r\n \r\n // Wait for loadedmetadata event before accessing new TextTrack objects\r\n const setupNewTracks = () => {\r\n // Wait a bit more for browser to fully process the new track elements\r\n setTimeout(() => {\r\n swappedTracksForTranscript.forEach((trackInfo) => {\r\n const trackElement = trackInfo.trackElement;\r\n const newTextTrack = trackElement.track;\r\n \r\n if (newTextTrack) {\r\n // Get original mode from stored map\r\n const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };\r\n \r\n // Set mode to load the new track\r\n newTextTrack.mode = 'hidden'; // Use hidden to load cues without showing\r\n \r\n // Restore original mode after track loads\r\n // Note: CaptionManager will handle enabling captions separately\r\n const restoreMode = () => {\r\n if (modeInfo.wasShowing) {\r\n // Set to hidden - CaptionManager will set it to showing when it enables\r\n newTextTrack.mode = 'hidden';\r\n } else if (modeInfo.wasHidden) {\r\n newTextTrack.mode = 'hidden';\r\n } else {\r\n newTextTrack.mode = 'disabled';\r\n }\r\n };\r\n \r\n // Wait for track to load\r\n if (newTextTrack.readyState >= 2) { // LOADED\r\n restoreMode();\r\n } else {\r\n newTextTrack.addEventListener('load', restoreMode, { once: true });\r\n newTextTrack.addEventListener('error', restoreMode, { once: true });\r\n }\r\n }\r\n });\r\n }, 300); // Additional wait for browser to process track elements\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Already loaded, wait a bit and setup\r\n setTimeout(setupNewTracks, 200);\r\n } else {\r\n this.element.addEventListener('loadedmetadata', setupNewTracks, { once: true });\r\n // Fallback timeout\r\n setTimeout(setupNewTracks, 2000);\r\n }\r\n }, 100); // Wait 100ms after first load() before adding new tracks\r\n \r\n const skippedCount = validationResults.length - tracksToSwap.length;\r\n }\r\n }\r\n \r\n // Update all source elements that have data-desc-src to their described versions\r\n // Force browser to pick up changes by removing and re-adding source elements\r\n // Get source elements (may have been defined in if block above, but get fresh list here)\r\n const allSourceElements = Array.from(this.element.querySelectorAll('source'));\r\n const sourcesToUpdate = [];\r\n \r\n allSourceElements.forEach((sourceEl) => {\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n const currentSrc = sourceEl.getAttribute('src');\r\n \r\n if (descSrcAttr) {\r\n const type = sourceEl.getAttribute('type');\r\n let origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n // Store current src as data-orig-src if not already set\r\n if (!origSrc) {\r\n origSrc = currentSrc;\r\n }\r\n \r\n // Store info for re-adding with described src\r\n sourcesToUpdate.push({\r\n src: descSrcAttr, // Use described version\r\n type: type,\r\n origSrc: origSrc,\r\n descSrc: descSrcAttr\r\n });\r\n } else {\r\n // Source element without data-desc-src - keep as-is\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n sourcesToUpdate.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: null\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n allSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with updated src attributes (described versions)\r\n sourcesToUpdate.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload by calling load() on the element\r\n // This should pick up the new src attributes from the re-added source elements\r\n // and also reload the track elements\r\n this.element.load();\r\n \r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n \r\n // Wait a bit more for tracks to be recognized and loaded after video metadata loads\r\n await new Promise(resolve => setTimeout(resolve, 300));\r\n\r\n // Hide poster if video hasn't started yet (poster should hide when we seek or play)\r\n if (this.element.tagName === 'VIDEO' && currentTime === 0 && !wasPlaying) {\r\n // Force poster to hide by doing a minimal seek or loading first frame\r\n // Setting readyState check or seeking to 0.001 seconds will hide the poster\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Seek to a tiny fraction to trigger poster hiding without actually moving\r\n this.element.currentTime = 0.001;\r\n // Then seek back to 0 after a brief moment to ensure poster stays hidden\r\n setTimeout(() => {\r\n this.element.currentTime = 0;\r\n }, 10);\r\n }\r\n }\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Update state and emit event\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n } else {\r\n // Fallback to updating element src directly\r\n // Swap caption tracks to described versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n // Swap tracks: validate explicit tracks, but try auto-detected tracks without validation\r\n const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {\r\n if (trackInfo.trackElement && trackInfo.describedSrc) {\r\n // Only validate explicitly defined tracks\r\n // Auto-detected tracks are used without validation (no 404s)\r\n if (trackInfo.explicit === true) {\r\n try {\r\n const exists = await this.validateTrackExists(trackInfo.describedSrc);\r\n return { trackInfo, exists };\r\n } catch (error) {\r\n return { trackInfo, exists: false };\r\n }\r\n } else {\r\n // This shouldn't happen since auto-detection is disabled\r\n return { trackInfo, exists: false };\r\n }\r\n }\r\n return { trackInfo, exists: false };\r\n });\r\n \r\n const validationResults = await Promise.all(validationPromises);\r\n const tracksToSwap = validationResults.filter(result => result.exists);\r\n \r\n if (tracksToSwap.length > 0) {\r\n // Store original track modes before removing tracks\r\n const trackModes = new Map();\r\n tracksToSwap.forEach(({ trackInfo }) => {\r\n const textTrack = trackInfo.trackElement.track;\r\n if (textTrack) {\r\n trackModes.set(trackInfo, {\r\n wasShowing: textTrack.mode === 'showing',\r\n wasHidden: textTrack.mode === 'hidden'\r\n });\r\n } else {\r\n trackModes.set(trackInfo, {\r\n wasShowing: false,\r\n wasHidden: false\r\n });\r\n }\r\n });\r\n \r\n // Store all track information before removing\r\n const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {\r\n const oldSrc = trackInfo.trackElement.getAttribute('src');\r\n const parent = trackInfo.trackElement.parentNode;\r\n const nextSibling = trackInfo.trackElement.nextSibling;\r\n \r\n // Store all attributes from the old track\r\n const attributes = {};\r\n Array.from(trackInfo.trackElement.attributes).forEach(attr => {\r\n attributes[attr.name] = attr.value;\r\n });\r\n \r\n return {\r\n trackInfo,\r\n oldSrc,\r\n parent,\r\n nextSibling,\r\n attributes\r\n };\r\n });\r\n \r\n // Remove ALL old tracks first to force browser to clear TextTrack objects\r\n tracksToReadd.forEach(({ trackInfo }) => {\r\n trackInfo.trackElement.remove();\r\n });\r\n \r\n // Force browser to process the removal by calling load()\r\n this.element.load();\r\n \r\n // Wait for browser to process the removal, then add new tracks\r\n setTimeout(() => {\r\n tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {\r\n swappedTracksForTranscript.push(trackInfo);\r\n \r\n // Create a completely new track element (not a clone) to force browser to create new TextTrack\r\n const newTrackElement = document.createElement('track');\r\n newTrackElement.setAttribute('src', trackInfo.describedSrc);\r\n \r\n // Copy all attributes except src and data-desc-src\r\n Object.keys(attributes).forEach(attrName => {\r\n if (attrName !== 'src' && attrName !== 'data-desc-src') {\r\n newTrackElement.setAttribute(attrName, attributes[attrName]);\r\n }\r\n });\r\n \r\n // Insert new track element\r\n if (nextSibling && nextSibling.parentNode) {\r\n parent.insertBefore(newTrackElement, nextSibling);\r\n } else {\r\n parent.appendChild(newTrackElement);\r\n }\r\n \r\n // Update reference to the new track element\r\n trackInfo.trackElement = newTrackElement;\r\n });\r\n \r\n // After all new tracks are added, force browser to reload media element again\r\n this.element.load();\r\n \r\n // Wait for loadedmetadata event before accessing new TextTrack objects\r\n const setupNewTracks = () => {\r\n // Wait a bit more for browser to fully process the new track elements\r\n setTimeout(() => {\r\n swappedTracksForTranscript.forEach((trackInfo) => {\r\n const trackElement = trackInfo.trackElement;\r\n const newTextTrack = trackElement.track;\r\n \r\n if (newTextTrack) {\r\n // Get original mode from stored map\r\n const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };\r\n \r\n // Set mode to load the new track\r\n newTextTrack.mode = 'hidden'; // Use hidden to load cues without showing\r\n \r\n // Restore original mode after track loads\r\n const restoreMode = () => {\r\n if (modeInfo.wasShowing) {\r\n // Set to hidden - CaptionManager will set it to showing when it enables\r\n newTextTrack.mode = 'hidden';\r\n } else if (modeInfo.wasHidden) {\r\n newTextTrack.mode = 'hidden';\r\n } else {\r\n newTextTrack.mode = 'disabled';\r\n }\r\n };\r\n \r\n // Wait for track to load\r\n if (newTextTrack.readyState >= 2) { // LOADED\r\n restoreMode();\r\n } else {\r\n newTextTrack.addEventListener('load', restoreMode, { once: true });\r\n newTextTrack.addEventListener('error', restoreMode, { once: true });\r\n }\r\n }\r\n });\r\n }, 300); // Additional wait for browser to process track elements\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Already loaded, wait a bit and setup\r\n setTimeout(setupNewTracks, 200);\r\n } else {\r\n this.element.addEventListener('loadedmetadata', setupNewTracks, { once: true });\r\n // Fallback timeout\r\n setTimeout(setupNewTracks, 2000);\r\n }\r\n }, 100); // Wait 100ms after first load() before adding new tracks\r\n }\r\n }\r\n \r\n // Check if we have source elements with data-desc-src (fallback method)\r\n const fallbackSourceElements = Array.from(this.element.querySelectorAll('source'));\r\n const hasSourceElementsWithDesc = fallbackSourceElements.some(el => el.getAttribute('data-desc-src'));\r\n \r\n if (hasSourceElementsWithDesc) {\r\n const fallbackSourcesToUpdate = [];\r\n \r\n fallbackSourceElements.forEach((sourceEl) => {\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n const currentSrc = sourceEl.getAttribute('src');\r\n \r\n if (descSrcAttr) {\r\n const type = sourceEl.getAttribute('type');\r\n let origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n if (!origSrc) {\r\n origSrc = currentSrc;\r\n }\r\n \r\n fallbackSourcesToUpdate.push({\r\n src: descSrcAttr,\r\n type: type,\r\n origSrc: origSrc,\r\n descSrc: descSrcAttr\r\n });\r\n } else {\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n fallbackSourcesToUpdate.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: null\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n fallbackSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with updated src attributes\r\n fallbackSourcesToUpdate.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload\r\n this.element.load();\r\n } else {\r\n // Fallback to updating element src directly (for videos without source elements)\r\n this.element.src = this.audioDescriptionSrc;\r\n }\r\n }\r\n\r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n\r\n // Hide poster if video hasn't started yet (poster should hide when we seek or play)\r\n if (this.element.tagName === 'VIDEO' && currentTime === 0 && !wasPlaying) {\r\n // Force poster to hide by doing a minimal seek or loading first frame\r\n // Setting readyState check or seeking to 0.001 seconds will hide the poster\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Seek to a tiny fraction to trigger poster hiding without actually moving\r\n this.element.currentTime = 0.001;\r\n // Then seek back to 0 after a brief moment to ensure poster stays hidden\r\n setTimeout(() => {\r\n this.element.currentTime = 0;\r\n }, 10);\r\n }\r\n }\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Reload CaptionManager tracks if tracks were swapped (so it has fresh references)\r\n if (swappedTracksForTranscript.length > 0 && this.captionManager) {\r\n // Store if captions were enabled and which track\r\n const wasCaptionsEnabled = this.state.captionsEnabled;\r\n let currentTrackInfo = null;\r\n if (this.captionManager.currentTrack) {\r\n const currentTrackIndex = this.captionManager.tracks.findIndex(t => t.track === this.captionManager.currentTrack.track);\r\n if (currentTrackIndex >= 0) {\r\n currentTrackInfo = {\r\n language: this.captionManager.tracks[currentTrackIndex].language,\r\n kind: this.captionManager.tracks[currentTrackIndex].kind\r\n };\r\n }\r\n }\r\n \r\n // Wait a bit for new tracks to be available, then reload\r\n setTimeout(() => {\r\n // Reload tracks to get fresh references to new TextTrack objects\r\n this.captionManager.tracks = [];\r\n this.captionManager.loadTracks();\r\n \r\n // Re-enable captions if they were enabled before\r\n if (wasCaptionsEnabled && currentTrackInfo && this.captionManager.tracks.length > 0) {\r\n // Find the track by language and kind to match the swapped track\r\n const matchingTrackIndex = this.captionManager.tracks.findIndex(t => \r\n t.language === currentTrackInfo.language && t.kind === currentTrackInfo.kind\r\n );\r\n \r\n if (matchingTrackIndex >= 0) {\r\n this.captionManager.enable(matchingTrackIndex);\r\n } else if (this.captionManager.tracks.length > 0) {\r\n // Fallback: enable first track\r\n this.captionManager.enable(0);\r\n }\r\n }\r\n }, 600); // Wait for tracks to be processed\r\n }\r\n\r\n // Reload transcript if visible (after video metadata loaded, tracks should be available)\r\n // Reload regardless of whether caption tracks were swapped, in case tracks changed\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n // Wait for tracks to load after source swap\r\n // If tracks were swapped, wait for them to load; otherwise wait a bit for any track changes\r\n const swappedTracks = typeof swappedTracksForTranscript !== 'undefined' ? swappedTracksForTranscript : [];\r\n \r\n if (swappedTracks.length > 0) {\r\n // Wait for swapped tracks to load their new cues\r\n // Since we re-added track elements and called load(), wait for loadedmetadata event\r\n // which is when the browser processes track elements\r\n const onMetadataLoaded = () => {\r\n // Get fresh track references from the video element's textTracks collection\r\n // This ensures we get the actual textTrack objects that the browser created\r\n const allTextTracks = Array.from(this.element.textTracks);\r\n \r\n // Find the tracks that match our swapped tracks by language and kind\r\n // Match by checking the track element's src attribute\r\n const freshTracks = swappedTracks.map((trackInfo) => {\r\n const trackEl = trackInfo.trackElement;\r\n const expectedSrc = trackEl.getAttribute('src');\r\n const srclang = trackEl.getAttribute('srclang');\r\n const kind = trackEl.getAttribute('kind');\r\n \r\n // Find matching track in textTracks collection\r\n // First try to match by the track element reference\r\n let foundTrack = allTextTracks.find(track => trackEl.track === track);\r\n \r\n // If not found, try matching by language and kind, but verify src\r\n if (!foundTrack) {\r\n foundTrack = allTextTracks.find(track => {\r\n if (track.language === srclang && \r\n (track.kind === kind || (kind === 'captions' && track.kind === 'subtitles'))) {\r\n // Verify the src matches\r\n const trackElementForTrack = Array.from(this.element.querySelectorAll('track')).find(\r\n el => el.track === track\r\n );\r\n if (trackElementForTrack) {\r\n const actualSrc = trackElementForTrack.getAttribute('src');\r\n if (actualSrc === expectedSrc) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n });\r\n }\r\n \r\n // Verify the track element's src matches what we expect\r\n if (foundTrack) {\r\n const trackElement = Array.from(this.element.querySelectorAll('track')).find(\r\n el => el.track === foundTrack\r\n );\r\n if (trackElement && trackElement.getAttribute('src') !== expectedSrc) {\r\n return null;\r\n }\r\n }\r\n \r\n return foundTrack;\r\n }).filter(Boolean);\r\n \r\n if (freshTracks.length === 0) {\r\n // Fallback: just reload after delay - transcript manager will find tracks itself\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 1000);\r\n return;\r\n }\r\n \r\n // Ensure tracks are in hidden mode to load cues for transcript\r\n freshTracks.forEach(track => {\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n });\r\n \r\n let loadedCount = 0;\r\n const checkLoaded = () => {\r\n loadedCount++;\r\n if (loadedCount >= freshTracks.length) {\r\n // Give a bit more time for cues to be fully parsed\r\n // Also ensure we're getting the latest TextTrack references\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n // Force transcript manager to get fresh track references\r\n // Clear any cached track references by forcing a fresh read\r\n // The transcript manager will find tracks from this.element.textTracks\r\n // which should now have the new TextTrack objects with the described captions\r\n \r\n // Verify the tracks have the correct src before reloading transcript\r\n const allTextTracks = Array.from(this.element.textTracks);\r\n const swappedTrackSrcs = swappedTracks.map(t => t.describedSrc);\r\n const hasCorrectTracks = freshTracks.some(track => {\r\n const trackEl = Array.from(this.element.querySelectorAll('track')).find(\r\n el => el.track === track\r\n );\r\n return trackEl && swappedTrackSrcs.includes(trackEl.getAttribute('src'));\r\n });\r\n \r\n if (hasCorrectTracks || freshTracks.length > 0) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }\r\n }, 800); // Increased wait time to ensure cues are fully loaded\r\n }\r\n };\r\n \r\n freshTracks.forEach(track => {\r\n // Ensure track is in hidden mode to load cues (required for transcript)\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n \r\n // Check if track has cues loaded\r\n // Verify the track element's src matches the expected described src\r\n const trackElementForTrack = Array.from(this.element.querySelectorAll('track')).find(\r\n el => el.track === track\r\n );\r\n const actualSrc = trackElementForTrack ? trackElementForTrack.getAttribute('src') : null;\r\n \r\n // Find the expected src from swappedTracks\r\n const expectedTrackInfo = swappedTracks.find(t => {\r\n const tEl = t.trackElement;\r\n return tEl && (tEl.track === track || \r\n (tEl.getAttribute('srclang') === track.language && \r\n tEl.getAttribute('kind') === track.kind));\r\n });\r\n const expectedSrc = expectedTrackInfo ? expectedTrackInfo.describedSrc : null;\r\n \r\n // Only proceed if the src matches (or we can't verify)\r\n if (expectedSrc && actualSrc && actualSrc !== expectedSrc) {\r\n // Wrong track, skip it\r\n checkLoaded(); // Count it as loaded to not block\r\n return;\r\n }\r\n \r\n if (track.readyState >= 2 && track.cues && track.cues.length > 0) { // LOADED with cues\r\n // Track already loaded with cues\r\n checkLoaded();\r\n } else {\r\n // Force track to load by setting mode\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n \r\n // Wait for track to load\r\n const onTrackLoad = () => {\r\n // Wait a bit for cues to be fully parsed\r\n setTimeout(checkLoaded, 300);\r\n };\r\n \r\n if (track.readyState >= 2) {\r\n // Already loaded, but might not have cues yet\r\n // Wait a bit and check again\r\n setTimeout(() => {\r\n if (track.cues && track.cues.length > 0) {\r\n checkLoaded();\r\n } else {\r\n // Still no cues, wait for load event\r\n track.addEventListener('load', onTrackLoad, { once: true });\r\n }\r\n }, 100);\r\n } else {\r\n track.addEventListener('load', onTrackLoad, { once: true });\r\n track.addEventListener('error', () => {\r\n // Even on error, try to reload transcript\r\n checkLoaded();\r\n }, { once: true });\r\n }\r\n }\r\n });\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n // Also wait for the tracks to be fully processed after the second load()\r\n const waitForTracks = () => {\r\n // Wait a bit more to ensure new TextTrack objects are created\r\n setTimeout(() => {\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n onMetadataLoaded();\r\n } else {\r\n this.element.addEventListener('loadedmetadata', onMetadataLoaded, { once: true });\r\n // Fallback timeout\r\n setTimeout(onMetadataLoaded, 2000);\r\n }\r\n }, 500); // Wait 500ms after second load() for tracks to be processed\r\n };\r\n \r\n waitForTracks();\r\n \r\n // Fallback timeout - longer to ensure tracks are loaded\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 5000);\r\n } else {\r\n // No tracks swapped, just wait a bit and reload\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 800);\r\n }\r\n }\r\n\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n }\r\n\r\n async disableAudioDescription() {\r\n if (!this.originalSrc) {\r\n return;\r\n }\r\n\r\n // Store current playback state\r\n const currentTime = this.state.currentTime;\r\n const wasPlaying = this.state.playing;\r\n\r\n // Swap caption/chapter tracks back to original versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n this.audioDescriptionCaptionTracks.forEach(trackInfo => {\r\n if (trackInfo.trackElement && trackInfo.originalTrackSrc) {\r\n trackInfo.trackElement.setAttribute('src', trackInfo.originalTrackSrc);\r\n }\r\n });\r\n }\r\n \r\n // Swap source elements back to original versions\r\n // Check if we have source elements with data-orig-src\r\n const allSourceElements = Array.from(this.element.querySelectorAll('source'));\r\n const hasSourceElementsToSwap = allSourceElements.some(el => el.getAttribute('data-orig-src'));\r\n \r\n if (hasSourceElementsToSwap) {\r\n const sourcesToRestore = [];\r\n \r\n allSourceElements.forEach((sourceEl) => {\r\n const origSrcAttr = sourceEl.getAttribute('data-orig-src');\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n \r\n if (origSrcAttr) {\r\n // Swap back to original src\r\n const type = sourceEl.getAttribute('type');\r\n sourcesToRestore.push({\r\n src: origSrcAttr, // Use original version\r\n type: type,\r\n origSrc: origSrcAttr,\r\n descSrc: descSrcAttr // Keep data-desc-src for future swaps\r\n });\r\n } else {\r\n // Keep as-is (no data-orig-src means it wasn't swapped)\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n sourcesToRestore.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: descSrcAttr\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n allSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with original src attributes\r\n sourcesToRestore.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload\r\n this.element.load();\r\n } else {\r\n // Fallback to updating element src directly (for videos without source elements)\r\n const originalSrcToUse = this.originalAudioDescriptionSource || this.originalSrc;\r\n this.element.src = originalSrcToUse;\r\n this.element.load();\r\n }\r\n\r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Reload transcript if visible (after video metadata loaded, tracks should be available)\r\n // Reload regardless of whether caption tracks were swapped, in case tracks changed\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n // Wait for tracks to load after source swap\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 500);\r\n }\r\n\r\n this.state.audioDescriptionEnabled = false;\r\n this.emit('audiodescriptiondisabled');\r\n }\r\n\r\n async toggleAudioDescription() {\r\n // Check if we have description tracks or audio-described video\r\n const textTracks = Array.from(this.element.textTracks || []);\r\n const descriptionTrack = textTracks.find(track => track.kind === 'descriptions');\r\n \r\n // Check if we have audio-described video source (either from options or source elements with data-desc-src)\r\n const hasAudioDescriptionSrc = this.audioDescriptionSrc || \r\n Array.from(this.element.querySelectorAll('source')).some(el => el.getAttribute('data-desc-src'));\r\n \r\n if (descriptionTrack && hasAudioDescriptionSrc) {\r\n // We have both: toggle description track AND swap caption tracks/sources\r\n if (this.state.audioDescriptionEnabled) {\r\n // Disable: toggle description track off and swap captions/sources back\r\n descriptionTrack.mode = 'hidden';\r\n await this.disableAudioDescription();\r\n } else {\r\n // Enable: swap caption tracks/sources and toggle description track on\r\n await this.enableAudioDescription();\r\n descriptionTrack.mode = 'showing';\r\n }\r\n } else if (descriptionTrack) {\r\n // Only description track, no audio-described video source to swap\r\n // Toggle description track\r\n if (descriptionTrack.mode === 'showing') {\r\n descriptionTrack.mode = 'hidden';\r\n this.state.audioDescriptionEnabled = false;\r\n this.emit('audiodescriptiondisabled');\r\n } else {\r\n descriptionTrack.mode = 'showing';\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n }\r\n } else if (hasAudioDescriptionSrc) {\r\n // Use audio-described video source (no description track)\r\n if (this.state.audioDescriptionEnabled) {\r\n await this.disableAudioDescription();\r\n } else {\r\n await this.enableAudioDescription();\r\n }\r\n }\r\n }\r\n\r\n // Sign Language\r\n enableSignLanguage() {\r\n if (!this.signLanguageSrc) {\r\n console.warn('No sign language video source provided');\r\n return;\r\n }\r\n\r\n if (this.signLanguageWrapper) {\r\n // Already exists, just show it\r\n this.signLanguageWrapper.style.display = 'block';\r\n this.state.signLanguageEnabled = true;\r\n this.emit('signlanguageenabled');\r\n return;\r\n }\r\n\r\n // Create wrapper container\r\n this.signLanguageWrapper = document.createElement('div');\r\n this.signLanguageWrapper.className = 'vidply-sign-language-wrapper';\r\n this.signLanguageWrapper.setAttribute('tabindex', '0');\r\n this.signLanguageWrapper.setAttribute('aria-label', 'Sign Language Video - Press D to drag with keyboard, R to resize');\r\n\r\n // Create sign language video element\r\n this.signLanguageVideo = document.createElement('video');\r\n this.signLanguageVideo.className = 'vidply-sign-language-video';\r\n this.signLanguageVideo.src = this.signLanguageSrc;\r\n this.signLanguageVideo.setAttribute('aria-label', i18n.t('player.signLanguage'));\r\n this.signLanguageVideo.muted = true; // Sign language video should be muted\r\n\r\n // Create resize handles\r\n const resizeHandles = ['nw', 'ne', 'sw', 'se'].map(dir => {\r\n const handle = document.createElement('div');\r\n handle.className = `vidply-sign-resize-handle vidply-sign-resize-${dir}`;\r\n handle.setAttribute('data-direction', dir);\r\n handle.setAttribute('aria-label', `Resize ${dir.toUpperCase()}`);\r\n return handle;\r\n });\r\n\r\n // Append video and handles to wrapper\r\n this.signLanguageWrapper.appendChild(this.signLanguageVideo);\r\n resizeHandles.forEach(handle => this.signLanguageWrapper.appendChild(handle));\r\n\r\n // Set width FIRST to ensure proper dimensions\r\n const saved = this.storage.getSignLanguagePreferences();\r\n if (saved && saved.size && saved.size.width) {\r\n this.signLanguageWrapper.style.width = saved.size.width;\r\n } else {\r\n this.signLanguageWrapper.style.width = '280px'; // Default width\r\n }\r\n // Height is always auto to maintain aspect ratio\r\n this.signLanguageWrapper.style.height = 'auto';\r\n \r\n // Position is always calculated fresh - use option or default to bottom-right\r\n this.signLanguageDesiredPosition = this.options.signLanguagePosition || 'bottom-right';\r\n\r\n // Add to main player container (NOT videoWrapper) to avoid overflow:hidden clipping\r\n this.container.appendChild(this.signLanguageWrapper);\r\n\r\n // Set position immediately after appending\r\n requestAnimationFrame(() => {\r\n this.constrainSignLanguagePosition();\r\n });\r\n\r\n // Sync with main video\r\n this.signLanguageVideo.currentTime = this.state.currentTime;\r\n if (!this.state.paused) {\r\n this.signLanguageVideo.play();\r\n }\r\n\r\n // Setup drag and resize\r\n this.setupSignLanguageInteraction();\r\n\r\n // Create bound handlers to store references for cleanup\r\n this.signLanguageHandlers = {\r\n play: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.play();\r\n }\r\n },\r\n pause: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.pause();\r\n }\r\n },\r\n timeupdate: () => {\r\n if (this.signLanguageVideo && Math.abs(this.signLanguageVideo.currentTime - this.state.currentTime) > 0.5) {\r\n this.signLanguageVideo.currentTime = this.state.currentTime;\r\n }\r\n },\r\n ratechange: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.playbackRate = this.state.playbackSpeed;\r\n }\r\n }\r\n };\r\n\r\n // Sync playback\r\n this.on('play', this.signLanguageHandlers.play);\r\n this.on('pause', this.signLanguageHandlers.pause);\r\n this.on('timeupdate', this.signLanguageHandlers.timeupdate);\r\n this.on('ratechange', this.signLanguageHandlers.ratechange);\r\n\r\n this.state.signLanguageEnabled = true;\r\n this.emit('signlanguageenabled');\r\n }\r\n\r\n disableSignLanguage() {\r\n if (this.signLanguageWrapper) {\r\n this.signLanguageWrapper.style.display = 'none';\r\n }\r\n this.state.signLanguageEnabled = false;\r\n this.emit('signlanguagedisabled');\r\n }\r\n\r\n toggleSignLanguage() {\r\n if (this.state.signLanguageEnabled) {\r\n this.disableSignLanguage();\r\n } else {\r\n this.enableSignLanguage();\r\n }\r\n }\r\n\r\n setupSignLanguageInteraction() {\r\n if (!this.signLanguageWrapper) return;\r\n\r\n let isDragging = false;\r\n let isResizing = false;\r\n let resizeDirection = null;\r\n let startX = 0;\r\n let startY = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let dragMode = false;\r\n let resizeMode = false;\r\n\r\n // Mouse drag on video element\r\n const onMouseDownVideo = (e) => {\r\n if (e.target !== this.signLanguageVideo) return;\r\n e.preventDefault();\r\n isDragging = true;\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n startLeft = rect.left;\r\n startTop = rect.top;\r\n this.signLanguageWrapper.classList.add('vidply-sign-dragging');\r\n };\r\n\r\n // Mouse resize on handles\r\n const onMouseDownHandle = (e) => {\r\n if (!e.target.classList.contains('vidply-sign-resize-handle')) return;\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n resizeDirection = e.target.getAttribute('data-direction');\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n startLeft = rect.left;\r\n startTop = rect.top;\r\n startWidth = rect.width;\r\n startHeight = rect.height;\r\n this.signLanguageWrapper.classList.add('vidply-sign-resizing');\r\n };\r\n\r\n const onMouseMove = (e) => {\r\n if (isDragging) {\r\n const deltaX = e.clientX - startX;\r\n const deltaY = e.clientY - startY;\r\n \r\n // Get videoWrapper and container dimensions\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n const wrapperRect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper position relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n \r\n // Calculate new position (in client coordinates)\r\n let newLeft = startLeft + deltaX - containerRect.left;\r\n let newTop = startTop + deltaY - containerRect.top;\r\n \r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n newLeft = Math.max(videoWrapperLeft, Math.min(newLeft, videoWrapperLeft + videoWrapperRect.width - wrapperRect.width));\r\n newTop = Math.max(videoWrapperTop, Math.min(newTop, videoWrapperTop + videoWrapperRect.height - wrapperRect.height - controlsHeight));\r\n \r\n this.signLanguageWrapper.style.left = `${newLeft}px`;\r\n this.signLanguageWrapper.style.top = `${newTop}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n } else if (isResizing) {\r\n const deltaX = e.clientX - startX;\r\n \r\n // Get videoWrapper and container dimensions\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n \r\n let newWidth = startWidth;\r\n let newLeft = startLeft - containerRect.left;\r\n\r\n // Only resize width, let height auto-adjust to maintain aspect ratio\r\n if (resizeDirection.includes('e')) {\r\n newWidth = Math.max(150, startWidth + deltaX);\r\n // Constrain width to not exceed videoWrapper right edge\r\n const maxWidth = (videoWrapperRect.right - startLeft);\r\n newWidth = Math.min(newWidth, maxWidth);\r\n }\r\n if (resizeDirection.includes('w')) {\r\n const proposedWidth = Math.max(150, startWidth - deltaX);\r\n const proposedLeft = startLeft + (startWidth - proposedWidth) - containerRect.left;\r\n // Constrain to not go beyond videoWrapper left edge\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n if (proposedLeft >= videoWrapperLeft) {\r\n newWidth = proposedWidth;\r\n newLeft = proposedLeft;\r\n }\r\n }\r\n\r\n this.signLanguageWrapper.style.width = `${newWidth}px`;\r\n this.signLanguageWrapper.style.height = 'auto'; // Let video maintain aspect ratio\r\n if (resizeDirection.includes('w')) {\r\n this.signLanguageWrapper.style.left = `${newLeft}px`;\r\n }\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n if (isDragging || isResizing) {\r\n this.saveSignLanguagePreferences();\r\n }\r\n isDragging = false;\r\n isResizing = false;\r\n resizeDirection = null;\r\n this.signLanguageWrapper.classList.remove('vidply-sign-dragging', 'vidply-sign-resizing');\r\n };\r\n\r\n // Keyboard controls\r\n const onKeyDown = (e) => {\r\n // Toggle drag mode with D key\r\n if (e.key === 'd' || e.key === 'D') {\r\n dragMode = !dragMode;\r\n resizeMode = false;\r\n this.signLanguageWrapper.classList.toggle('vidply-sign-keyboard-drag', dragMode);\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-resize');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Toggle resize mode with R key\r\n if (e.key === 'r' || e.key === 'R') {\r\n resizeMode = !resizeMode;\r\n dragMode = false;\r\n this.signLanguageWrapper.classList.toggle('vidply-sign-keyboard-resize', resizeMode);\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-drag');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Escape to exit modes\r\n if (e.key === 'Escape') {\r\n dragMode = false;\r\n resizeMode = false;\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-drag', 'vidply-sign-keyboard-resize');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Arrow keys for drag/resize\r\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\r\n const step = e.shiftKey ? 10 : 5;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Get videoWrapper and container bounds\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper position relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n\r\n if (dragMode) {\r\n // Get current position relative to container\r\n let left = rect.left - containerRect.left;\r\n let top = rect.top - containerRect.top;\r\n\r\n if (e.key === 'ArrowLeft') left -= step;\r\n if (e.key === 'ArrowRight') left += step;\r\n if (e.key === 'ArrowUp') top -= step;\r\n if (e.key === 'ArrowDown') top += step;\r\n\r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n left = Math.max(videoWrapperLeft, Math.min(left, videoWrapperLeft + videoWrapperRect.width - rect.width));\r\n top = Math.max(videoWrapperTop, Math.min(top, videoWrapperTop + videoWrapperRect.height - rect.height - controlsHeight));\r\n\r\n this.signLanguageWrapper.style.left = `${left}px`;\r\n this.signLanguageWrapper.style.top = `${top}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n this.saveSignLanguagePreferences();\r\n e.preventDefault();\r\n } else if (resizeMode) {\r\n let width = rect.width;\r\n\r\n // Only adjust width, height will auto-adjust to maintain aspect ratio\r\n if (e.key === 'ArrowLeft') width -= step;\r\n if (e.key === 'ArrowRight') width += step;\r\n // Up/Down also adjusts width for simplicity\r\n if (e.key === 'ArrowUp') width += step;\r\n if (e.key === 'ArrowDown') width -= step;\r\n\r\n // Constrain width\r\n width = Math.max(150, width);\r\n // Don't let it exceed videoWrapper width\r\n width = Math.min(width, videoWrapperRect.width);\r\n\r\n this.signLanguageWrapper.style.width = `${width}px`;\r\n this.signLanguageWrapper.style.height = 'auto';\r\n this.saveSignLanguagePreferences();\r\n e.preventDefault();\r\n }\r\n }\r\n };\r\n\r\n // Attach event listeners\r\n this.signLanguageVideo.addEventListener('mousedown', onMouseDownVideo);\r\n const handles = this.signLanguageWrapper.querySelectorAll('.vidply-sign-resize-handle');\r\n handles.forEach(handle => handle.addEventListener('mousedown', onMouseDownHandle));\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n this.signLanguageWrapper.addEventListener('keydown', onKeyDown);\r\n\r\n // Store for cleanup\r\n this.signLanguageInteractionHandlers = {\r\n mouseDownVideo: onMouseDownVideo,\r\n mouseDownHandle: onMouseDownHandle,\r\n mouseMove: onMouseMove,\r\n mouseUp: onMouseUp,\r\n keyDown: onKeyDown,\r\n handles\r\n };\r\n }\r\n\r\n constrainSignLanguagePosition() {\r\n if (!this.signLanguageWrapper || !this.videoWrapper) return;\r\n \r\n // Ensure width is set\r\n if (!this.signLanguageWrapper.style.width || this.signLanguageWrapper.style.width === '') {\r\n this.signLanguageWrapper.style.width = '280px'; // Default width\r\n }\r\n \r\n // Get videoWrapper position relative to the player CONTAINER (where sign language video is attached)\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n const wrapperRect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper's position and dimensions relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n const videoWrapperWidth = videoWrapperRect.width;\r\n const videoWrapperHeight = videoWrapperRect.height;\r\n \r\n // Use estimated height if video hasn't loaded yet (16:9 aspect ratio)\r\n let wrapperWidth = wrapperRect.width || 280;\r\n let wrapperHeight = wrapperRect.height || ((280 * 9) / 16); // Estimate based on 16:9 aspect ratio\r\n \r\n let left, top;\r\n const margin = 16; // Margin from edges\r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Always calculate fresh position based on desired location (relative to videoWrapper)\r\n const position = this.signLanguageDesiredPosition || 'bottom-right';\r\n \r\n switch (position) {\r\n case 'bottom-right':\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n break;\r\n case 'bottom-left':\r\n left = videoWrapperLeft + margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n break;\r\n case 'top-right':\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + margin;\r\n break;\r\n case 'top-left':\r\n left = videoWrapperLeft + margin;\r\n top = videoWrapperTop + margin;\r\n break;\r\n default:\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n }\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n left = Math.max(videoWrapperLeft, Math.min(left, videoWrapperLeft + videoWrapperWidth - wrapperWidth));\r\n top = Math.max(videoWrapperTop, Math.min(top, videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight));\r\n \r\n // Apply constrained position\r\n this.signLanguageWrapper.style.left = `${left}px`;\r\n this.signLanguageWrapper.style.top = `${top}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes if any were applied\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n }\r\n\r\n saveSignLanguagePreferences() {\r\n if (!this.signLanguageWrapper) return;\r\n \r\n // Only save width - position is always calculated fresh to bottom-right\r\n this.storage.saveSignLanguagePreferences({\r\n size: {\r\n width: this.signLanguageWrapper.style.width\r\n // Height is auto - maintained by aspect ratio\r\n }\r\n });\r\n }\r\n\r\n cleanupSignLanguage() {\r\n // Remove event listeners\r\n if (this.signLanguageHandlers) {\r\n this.off('play', this.signLanguageHandlers.play);\r\n this.off('pause', this.signLanguageHandlers.pause);\r\n this.off('timeupdate', this.signLanguageHandlers.timeupdate);\r\n this.off('ratechange', this.signLanguageHandlers.ratechange);\r\n this.signLanguageHandlers = null;\r\n }\r\n\r\n // Remove interaction handlers\r\n if (this.signLanguageInteractionHandlers) {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.removeEventListener('mousedown', this.signLanguageInteractionHandlers.mouseDownVideo);\r\n }\r\n if (this.signLanguageInteractionHandlers.handles) {\r\n this.signLanguageInteractionHandlers.handles.forEach(handle => {\r\n handle.removeEventListener('mousedown', this.signLanguageInteractionHandlers.mouseDownHandle);\r\n });\r\n }\r\n document.removeEventListener('mousemove', this.signLanguageInteractionHandlers.mouseMove);\r\n document.removeEventListener('mouseup', this.signLanguageInteractionHandlers.mouseUp);\r\n if (this.signLanguageWrapper) {\r\n this.signLanguageWrapper.removeEventListener('keydown', this.signLanguageInteractionHandlers.keyDown);\r\n }\r\n this.signLanguageInteractionHandlers = null;\r\n }\r\n\r\n // Remove video and wrapper elements\r\n if (this.signLanguageWrapper && this.signLanguageWrapper.parentNode) {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.pause();\r\n this.signLanguageVideo.src = '';\r\n }\r\n this.signLanguageWrapper.parentNode.removeChild(this.signLanguageWrapper);\r\n this.signLanguageWrapper = null;\r\n this.signLanguageVideo = null;\r\n }\r\n }\r\n\r\n // Settings\r\n // Settings dialog removed - using individual control buttons instead\r\n showSettings() {\r\n console.warn('[VidPly] Settings dialog has been removed. Use individual control buttons (speed, captions, etc.)');\r\n }\r\n\r\n hideSettings() {\r\n // No-op - settings dialog removed\r\n }\r\n\r\n // Utility methods\r\n getCurrentTime() {\r\n return this.state.currentTime;\r\n }\r\n\r\n getDuration() {\r\n return this.state.duration;\r\n }\r\n\r\n isPlaying() {\r\n return this.state.playing;\r\n }\r\n\r\n isPaused() {\r\n return this.state.paused;\r\n }\r\n\r\n isEnded() {\r\n return this.state.ended;\r\n }\r\n\r\n isMuted() {\r\n return this.state.muted;\r\n }\r\n\r\n isFullscreen() {\r\n return this.state.fullscreen;\r\n }\r\n\r\n // Error handling\r\n handleError(error) {\r\n this.log('Error:', error, 'error');\r\n this.emit('error', error);\r\n\r\n if (this.options.onError) {\r\n this.options.onError.call(this, error);\r\n }\r\n }\r\n\r\n // Logging\r\n log(message, type = 'log') {\r\n if (this.options.debug) {\r\n console[type](`[VidPly]`, message);\r\n }\r\n }\r\n\r\n // Setup responsive handlers\r\n setupResponsiveHandlers() {\r\n // Use ResizeObserver for efficient resize tracking\r\n if (typeof ResizeObserver !== 'undefined') {\r\n this.resizeObserver = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n const width = entry.contentRect.width;\r\n\r\n // Update control bar for viewport\r\n if (this.controlBar && typeof this.controlBar.updateControlsForViewport === 'function') {\r\n this.controlBar.updateControlsForViewport(width);\r\n }\r\n\r\n // Update transcript positioning\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n }\r\n });\r\n\r\n this.resizeObserver.observe(this.container);\r\n } else {\r\n // Fallback to window resize event\r\n this.resizeHandler = () => {\r\n const width = this.container.clientWidth;\r\n\r\n if (this.controlBar && typeof this.controlBar.updateControlsForViewport === 'function') {\r\n this.controlBar.updateControlsForViewport(width);\r\n }\r\n\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n };\r\n\r\n window.addEventListener('resize', this.resizeHandler);\r\n }\r\n\r\n // Also listen for orientation changes on mobile\r\n if (window.matchMedia) {\r\n this.orientationHandler = (e) => {\r\n // Wait for layout to settle\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n }, 100);\r\n };\r\n\r\n const orientationQuery = window.matchMedia('(orientation: portrait)');\r\n if (orientationQuery.addEventListener) {\r\n orientationQuery.addEventListener('change', this.orientationHandler);\r\n } else if (orientationQuery.addListener) {\r\n // Fallback for older browsers\r\n orientationQuery.addListener(this.orientationHandler);\r\n }\r\n\r\n this.orientationQuery = orientationQuery;\r\n }\r\n\r\n // Listen for native fullscreen change events (e.g., when user presses ESC)\r\n this.fullscreenChangeHandler = () => {\r\n const isFullscreen = !!(\r\n document.fullscreenElement ||\r\n document.webkitFullscreenElement ||\r\n document.mozFullScreenElement ||\r\n document.msFullscreenElement\r\n );\r\n\r\n // Only update if state has changed\r\n if (this.state.fullscreen !== isFullscreen) {\r\n this.state.fullscreen = isFullscreen;\r\n \r\n if (isFullscreen) {\r\n this.container.classList.add(`${this.options.classPrefix}-fullscreen`);\r\n } else {\r\n this.container.classList.remove(`${this.options.classPrefix}-fullscreen`);\r\n }\r\n \r\n this.emit('fullscreenchange', isFullscreen);\r\n \r\n // Update fullscreen button icon\r\n if (this.controlBar) {\r\n this.controlBar.updateFullscreenButton();\r\n }\r\n \r\n // Reposition sign language video after fullscreen transition\r\n if (this.signLanguageWrapper && this.signLanguageWrapper.style.display !== 'none') {\r\n // Use setTimeout to ensure layout has updated after fullscreen transition\r\n // Longer delay to account for CSS transition animations and layout recalculation\r\n setTimeout(() => {\r\n // Use requestAnimationFrame to ensure the browser has fully rendered the layout\r\n requestAnimationFrame(() => {\r\n // Clear saved size and reset to default for the new container size\r\n this.storage.saveSignLanguagePreferences({ size: null });\r\n this.signLanguageDesiredPosition = 'bottom-right';\r\n // Reset to default width for the new container\r\n this.signLanguageWrapper.style.width = isFullscreen ? '400px' : '280px';\r\n this.constrainSignLanguagePosition();\r\n });\r\n }, 500);\r\n }\r\n }\r\n };\r\n\r\n // Add listeners for all vendor-prefixed fullscreenchange events\r\n document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('mozfullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('MSFullscreenChange', this.fullscreenChangeHandler);\r\n }\r\n\r\n // Cleanup\r\n destroy() {\r\n this.log('Destroying player');\r\n\r\n if (this.renderer) {\r\n this.renderer.destroy();\r\n }\r\n\r\n if (this.controlBar) {\r\n this.controlBar.destroy();\r\n }\r\n\r\n if (this.captionManager) {\r\n this.captionManager.destroy();\r\n }\r\n\r\n if (this.keyboardManager) {\r\n this.keyboardManager.destroy();\r\n }\r\n\r\n if (this.transcriptManager) {\r\n this.transcriptManager.destroy();\r\n }\r\n\r\n // Cleanup sign language video and listeners\r\n this.cleanupSignLanguage();\r\n\r\n // Cleanup play overlay button\r\n if (this.playButtonOverlay && this.playButtonOverlay.parentNode) {\r\n this.playButtonOverlay.remove();\r\n this.playButtonOverlay = null;\r\n }\r\n\r\n // Cleanup resize observer\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n\r\n // Cleanup window resize handler\r\n if (this.resizeHandler) {\r\n window.removeEventListener('resize', this.resizeHandler);\r\n this.resizeHandler = null;\r\n }\r\n\r\n // Cleanup orientation change handler\r\n if (this.orientationQuery && this.orientationHandler) {\r\n if (this.orientationQuery.removeEventListener) {\r\n this.orientationQuery.removeEventListener('change', this.orientationHandler);\r\n } else if (this.orientationQuery.removeListener) {\r\n this.orientationQuery.removeListener(this.orientationHandler);\r\n }\r\n this.orientationQuery = null;\r\n this.orientationHandler = null;\r\n }\r\n\r\n // Cleanup fullscreen change handler\r\n if (this.fullscreenChangeHandler) {\r\n document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('mozfullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('MSFullscreenChange', this.fullscreenChangeHandler);\r\n this.fullscreenChangeHandler = null;\r\n }\r\n\r\n // Remove container\r\n if (this.container && this.container.parentNode) {\r\n this.container.parentNode.insertBefore(this.element, this.container);\r\n this.container.parentNode.removeChild(this.container);\r\n }\r\n\r\n this.removeAllListeners();\r\n }\r\n}\r\n\r\n// Static instances tracker for pause others functionality\r\nPlayer.instances = [];\r\n\r\n", "/**\r\n * YouTube Renderer\r\n */\r\n\r\nexport class YouTubeRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.youtube = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL\r\n this.videoId = this.extractVideoId(this.player.element.src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid YouTube URL');\r\n }\r\n\r\n // Load YouTube IFrame API\r\n await this.loadYouTubeAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([^&\\s]+)/,\r\n /youtube\\.com\\/embed\\/([^&\\s]+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadYouTubeAPI() {\r\n // Check if API is already loaded\r\n if (window.YT && window.YT.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Check if script is already being loaded\r\n if (window.onYouTubeIframeAPIReady) {\r\n const originalCallback = window.onYouTubeIframeAPIReady;\r\n window.onYouTubeIframeAPIReady = () => {\r\n originalCallback();\r\n resolve();\r\n };\r\n return;\r\n }\r\n\r\n // Load the API script\r\n const tag = document.createElement('script');\r\n tag.src = 'https://www.youtube.com/iframe_api';\r\n \r\n window.onYouTubeIframeAPIReady = () => {\r\n resolve();\r\n };\r\n\r\n tag.onerror = () => reject(new Error('Failed to load YouTube API'));\r\n \r\n const firstScriptTag = document.getElementsByTagName('script')[0];\r\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.height = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n return new Promise((resolve) => {\r\n this.youtube = new window.YT.Player(this.iframe.id, {\r\n videoId: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n playerVars: {\r\n controls: 0,\r\n disablekb: 1,\r\n fs: 0,\r\n modestbranding: 1,\r\n rel: 0,\r\n showinfo: 0,\r\n iv_load_policy: 3,\r\n autoplay: this.player.options.autoplay ? 1 : 0,\r\n mute: this.player.options.muted ? 1 : 0,\r\n start: this.player.options.startTime || 0\r\n },\r\n events: {\r\n onReady: (event) => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n resolve();\r\n },\r\n onStateChange: (event) => this.handleStateChange(event),\r\n onError: (event) => this.handleError(event)\r\n }\r\n });\r\n });\r\n }\r\n\r\n attachEvents() {\r\n // Set up polling for time updates (YouTube doesn't provide timeupdate events)\r\n this.timeUpdateInterval = setInterval(() => {\r\n if (this.isReady && this.youtube) {\r\n const currentTime = this.youtube.getCurrentTime();\r\n const duration = this.youtube.getDuration();\r\n \r\n this.player.state.currentTime = currentTime;\r\n this.player.state.duration = duration;\r\n \r\n this.player.emit('timeupdate', currentTime);\r\n }\r\n }, 250);\r\n\r\n // Initial metadata\r\n if (this.youtube.getDuration) {\r\n this.player.state.duration = this.youtube.getDuration();\r\n this.player.emit('loadedmetadata');\r\n }\r\n }\r\n\r\n handleStateChange(event) {\r\n const states = window.YT.PlayerState;\r\n\r\n switch (event.data) {\r\n case states.PLAYING:\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.state.buffering = false;\r\n this.player.emit('play');\r\n this.player.emit('playing');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n break;\r\n\r\n case states.PAUSED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n break;\r\n\r\n case states.ENDED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.youtube.seekTo(0);\r\n this.youtube.playVideo();\r\n }\r\n break;\r\n\r\n case states.BUFFERING:\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n break;\r\n\r\n case states.CUED:\r\n this.player.emit('loadedmetadata');\r\n break;\r\n }\r\n }\r\n\r\n handleError(event) {\r\n const errors = {\r\n 2: 'Invalid video ID',\r\n 5: 'HTML5 player error',\r\n 100: 'Video not found',\r\n 101: 'Video not allowed to be played in embedded players',\r\n 150: 'Video not allowed to be played in embedded players'\r\n };\r\n\r\n const error = new Error(errors[event.data] || 'YouTube player error');\r\n this.player.handleError(error);\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.playVideo();\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.pauseVideo();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.seekTo(time, true);\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setVolume(volume * 100);\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.youtube) {\r\n if (muted) {\r\n this.youtube.mute();\r\n } else {\r\n this.youtube.unMute();\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setPlaybackRate(speed);\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.timeUpdateInterval) {\r\n clearInterval(this.timeUpdateInterval);\r\n }\r\n\r\n if (this.youtube && this.youtube.destroy) {\r\n this.youtube.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * Vimeo Renderer\r\n */\r\n\r\nexport class VimeoRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.vimeo = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL\r\n this.videoId = this.extractVideoId(this.player.element.src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid Vimeo URL');\r\n }\r\n\r\n // Load Vimeo Player API\r\n await this.loadVimeoAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /vimeo\\.com\\/(\\d+)/,\r\n /vimeo\\.com\\/video\\/(\\d+)/,\r\n /player\\.vimeo\\.com\\/video\\/(\\d+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadVimeoAPI() {\r\n // Check if API is already loaded\r\n if (window.Vimeo && window.Vimeo.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://player.vimeo.com/api/player.js';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load Vimeo API'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `vimeo-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.height = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n const options = {\r\n id: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n controls: false,\r\n autoplay: this.player.options.autoplay,\r\n muted: this.player.options.muted,\r\n loop: this.player.options.loop,\r\n keyboard: false\r\n };\r\n\r\n if (this.player.options.startTime > 0) {\r\n options.startTime = this.player.options.startTime;\r\n }\r\n\r\n this.vimeo = new window.Vimeo.Player(this.iframe.id, options);\r\n\r\n // Wait for player to be ready\r\n await this.vimeo.ready();\r\n this.isReady = true;\r\n\r\n this.attachEvents();\r\n\r\n // Get initial duration\r\n try {\r\n const duration = await this.vimeo.getDuration();\r\n this.player.state.duration = duration;\r\n this.player.emit('loadedmetadata');\r\n } catch (error) {\r\n this.player.log('Error getting duration:', error, 'warn');\r\n }\r\n }\r\n\r\n attachEvents() {\r\n this.vimeo.on('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('timeupdate', (data) => {\r\n this.player.state.currentTime = data.seconds;\r\n this.player.state.duration = data.duration;\r\n this.player.emit('timeupdate', data.seconds);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, data.seconds);\r\n }\r\n });\r\n\r\n this.vimeo.on('volumechange', (data) => {\r\n this.player.state.volume = data.volume;\r\n this.player.emit('volumechange', data.volume);\r\n });\r\n\r\n this.vimeo.on('bufferstart', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.vimeo.on('bufferend', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.vimeo.on('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.vimeo.on('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.vimeo.on('playbackratechange', (data) => {\r\n this.player.state.playbackSpeed = data.playbackRate;\r\n this.player.emit('ratechange', data.playbackRate);\r\n });\r\n\r\n this.vimeo.on('error', (error) => {\r\n this.player.handleError(new Error(`Vimeo error: ${error.message}`));\r\n });\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.play().catch(error => {\r\n this.player.log('Play error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.pause().catch(error => {\r\n this.player.log('Pause error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setCurrentTime(time).catch(error => {\r\n this.player.log('Seek error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setVolume(volume).catch(error => {\r\n this.player.log('Volume error:', error, 'warn');\r\n });\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.vimeo) {\r\n if (muted) {\r\n this.vimeo.setVolume(0);\r\n } else {\r\n this.vimeo.setVolume(this.player.state.volume);\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setPlaybackRate(speed).catch(error => {\r\n this.player.log('Playback rate error:', error, 'warn');\r\n });\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.vimeo && this.vimeo.destroy) {\r\n this.vimeo.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * HLS Streaming Renderer\r\n * Uses hls.js for browsers that don't natively support HLS\r\n */\r\n\r\nexport class HLSRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n this.hls = null;\r\n }\r\n\r\n async init() {\r\n // Check if browser natively supports HLS (Safari)\r\n if (this.canPlayNatively()) {\r\n this.player.log('Using native HLS support');\r\n await this.initNative();\r\n } else {\r\n this.player.log('Using hls.js for HLS support');\r\n await this.initHlsJs();\r\n }\r\n }\r\n\r\n canPlayNatively() {\r\n const video = document.createElement('video');\r\n return video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n }\r\n\r\n async initNative() {\r\n // Use HTML5 renderer for native HLS support\r\n const HTML5Renderer = (await import('./HTML5Renderer.js')).HTML5Renderer;\r\n const renderer = new HTML5Renderer(this.player);\r\n await renderer.init();\r\n \r\n // Copy methods\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach(method => {\r\n if (method !== 'constructor' && typeof renderer[method] === 'function') {\r\n this[method] = renderer[method].bind(renderer);\r\n }\r\n });\r\n }\r\n\r\n async initHlsJs() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n // Load hls.js if not already loaded\r\n if (!window.Hls) {\r\n await this.loadHlsJs();\r\n }\r\n\r\n if (!window.Hls.isSupported()) {\r\n throw new Error('HLS is not supported in this browser');\r\n }\r\n\r\n // Create hls.js instance with better error recovery\r\n this.hls = new window.Hls({\r\n debug: this.player.options.debug,\r\n enableWorker: true,\r\n lowLatencyMode: false,\r\n backBufferLength: 90,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n maxBufferSize: 60 * 1000 * 1000,\r\n maxBufferHole: 0.5,\r\n // Network retry settings\r\n manifestLoadingTimeOut: 10000,\r\n manifestLoadingMaxRetry: 4,\r\n manifestLoadingRetryDelay: 1000,\r\n manifestLoadingMaxRetryTimeout: 64000,\r\n levelLoadingTimeOut: 10000,\r\n levelLoadingMaxRetry: 4,\r\n levelLoadingRetryDelay: 1000,\r\n levelLoadingMaxRetryTimeout: 64000,\r\n fragLoadingTimeOut: 20000,\r\n fragLoadingMaxRetry: 6,\r\n fragLoadingRetryDelay: 1000,\r\n fragLoadingMaxRetryTimeout: 64000\r\n });\r\n\r\n // Attach media element\r\n this.hls.attachMedia(this.media);\r\n\r\n // Load source - Get from attribute to avoid blob URL conversion\r\n let src;\r\n const sourceElement = this.player.element.querySelector('source');\r\n if (sourceElement) {\r\n // Use getAttribute to get the original URL, not the blob-converted one\r\n src = sourceElement.getAttribute('src');\r\n } else {\r\n // Fallback to element's src attribute\r\n src = this.player.element.getAttribute('src') || this.player.element.src;\r\n }\r\n \r\n this.player.log(`Loading HLS source: ${src}`, 'log');\r\n \r\n if (!src) {\r\n throw new Error('No HLS source found');\r\n }\r\n \r\n this.hls.loadSource(src);\r\n\r\n // Attach events\r\n this.attachHlsEvents();\r\n this.attachMediaEvents();\r\n }\r\n\r\n async loadHlsJs() {\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load hls.js'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n attachHlsEvents() {\r\n this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {\r\n this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');\r\n this.player.emit('hlsmanifestparsed', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {\r\n this.player.log('HLS level switched to ' + data.level);\r\n this.player.emit('hlslevelswitched', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.ERROR, (event, data) => {\r\n this.handleHlsError(data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.FRAG_BUFFERED, () => {\r\n this.player.state.buffering = false;\r\n });\r\n }\r\n\r\n attachMediaEvents() {\r\n // Use same events as HTML5 renderer\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('error', () => {\r\n this.player.handleError(this.media.error);\r\n });\r\n }\r\n\r\n handleHlsError(data) {\r\n // Log detailed error info\r\n this.player.log(`HLS Error - Type: ${data.type}, Details: ${data.details}, Fatal: ${data.fatal}`, 'warn');\r\n if (data.response) {\r\n this.player.log(`Response code: ${data.response.code}, URL: ${data.response.url}`, 'warn');\r\n }\r\n \r\n if (data.fatal) {\r\n switch (data.type) {\r\n case window.Hls.ErrorTypes.NETWORK_ERROR:\r\n this.player.log('Fatal network error, trying to recover...', 'error');\r\n this.player.log(`Network error details: ${data.details}`, 'error');\r\n setTimeout(() => {\r\n this.hls.startLoad();\r\n }, 1000);\r\n break;\r\n \r\n case window.Hls.ErrorTypes.MEDIA_ERROR:\r\n this.player.log('Fatal media error, trying to recover...', 'error');\r\n this.hls.recoverMediaError();\r\n break;\r\n \r\n default:\r\n this.player.log('Fatal error, cannot recover', 'error');\r\n this.player.handleError(new Error(`HLS Error: ${data.type} - ${data.details}`));\r\n this.hls.destroy();\r\n break;\r\n }\r\n } else {\r\n this.player.log('Non-fatal HLS error: ' + data.details, 'warn');\r\n }\r\n }\r\n\r\n play() {\r\n const promise = this.media.play();\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n switchQuality(levelIndex) {\r\n if (this.hls) {\r\n this.hls.currentLevel = levelIndex;\r\n }\r\n }\r\n\r\n getQualities() {\r\n if (this.hls && this.hls.levels) {\r\n return this.hls.levels.map((level, index) => ({\r\n index,\r\n height: level.height,\r\n width: level.width,\r\n bitrate: level.bitrate,\r\n name: `${level.height}p`\r\n }));\r\n }\r\n return [];\r\n }\r\n\r\n destroy() {\r\n if (this.hls) {\r\n this.hls.destroy();\r\n this.hls = null;\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * VidPly Playlist Manager\r\n * Manages playlists for audio and video content\r\n */\r\n\r\nimport { DOMUtils } from '../utils/DOMUtils.js';\r\nimport { createIconElement } from '../icons/Icons.js';\r\n\r\nexport class PlaylistManager {\r\n constructor(player, options = {}) {\r\n this.player = player;\r\n this.tracks = [];\r\n this.currentIndex = -1;\r\n \r\n // Options\r\n this.options = {\r\n autoAdvance: options.autoAdvance !== false, // Default true\r\n loop: options.loop || false,\r\n showPanel: options.showPanel !== false, // Default true\r\n ...options\r\n };\r\n \r\n // UI elements\r\n this.container = null;\r\n this.playlistPanel = null;\r\n this.trackInfoElement = null;\r\n \r\n // Bind methods\r\n this.handleTrackEnd = this.handleTrackEnd.bind(this);\r\n this.handleTrackError = this.handleTrackError.bind(this);\r\n \r\n // Register this playlist manager with the player\r\n this.player.playlistManager = this;\r\n \r\n // Initialize\r\n this.init();\r\n \r\n // Update controls to add playlist buttons\r\n this.updatePlayerControls();\r\n }\r\n \r\n init() {\r\n // Listen for track end\r\n this.player.on('ended', this.handleTrackEnd);\r\n this.player.on('error', this.handleTrackError);\r\n \r\n // Create UI if needed\r\n if (this.options.showPanel) {\r\n this.createUI();\r\n }\r\n }\r\n \r\n /**\r\n * Update player controls to add playlist navigation buttons\r\n */\r\n updatePlayerControls() {\r\n if (!this.player.controlBar) return;\r\n \r\n const controlBar = this.player.controlBar;\r\n \r\n // Clear existing controls content (except the element itself)\r\n controlBar.element.innerHTML = '';\r\n \r\n // Recreate controls with playlist buttons now available\r\n controlBar.createControls();\r\n \r\n // Reattach events for the new controls\r\n controlBar.attachEvents();\r\n controlBar.setupAutoHide();\r\n }\r\n \r\n /**\r\n * Load a playlist\r\n * @param {Array} tracks - Array of track objects\r\n */\r\n loadPlaylist(tracks) {\r\n this.tracks = tracks;\r\n this.currentIndex = -1;\r\n \r\n // Add playlist class to container\r\n if (this.container) {\r\n this.container.classList.add('vidply-has-playlist');\r\n }\r\n \r\n // Update UI\r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n \r\n // Auto-play first track\r\n if (tracks.length > 0) {\r\n this.play(0);\r\n }\r\n }\r\n \r\n /**\r\n * Play a specific track\r\n * @param {number} index - Track index\r\n * @param {boolean} userInitiated - Whether this was triggered by user action (default: false)\r\n */\r\n play(index, userInitiated = false) {\r\n if (index < 0 || index >= this.tracks.length) {\r\n console.warn('VidPly Playlist: Invalid track index', index);\r\n return;\r\n }\r\n \r\n const track = this.tracks[index];\r\n \r\n // Update current index\r\n this.currentIndex = index;\r\n \r\n // Load track into player\r\n this.player.load({\r\n src: track.src,\r\n type: track.type,\r\n poster: track.poster,\r\n tracks: track.tracks || []\r\n });\r\n \r\n // Update UI\r\n this.updateTrackInfo(track);\r\n this.updatePlaylistUI();\r\n \r\n // Emit event\r\n this.player.emit('playlisttrackchange', {\r\n index: index,\r\n item: track,\r\n total: this.tracks.length\r\n });\r\n \r\n // Return focus to player for keyboard navigation (only on user action)\r\n if (userInitiated && this.player.container) {\r\n this.player.container.focus();\r\n }\r\n \r\n // Auto-play\r\n setTimeout(() => {\r\n this.player.play();\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Play next track\r\n */\r\n next() {\r\n let nextIndex = this.currentIndex + 1;\r\n \r\n if (nextIndex >= this.tracks.length) {\r\n if (this.options.loop) {\r\n nextIndex = 0;\r\n } else {\r\n return;\r\n }\r\n }\r\n \r\n this.play(nextIndex);\r\n }\r\n \r\n /**\r\n * Play previous track\r\n */\r\n previous() {\r\n let prevIndex = this.currentIndex - 1;\r\n \r\n if (prevIndex < 0) {\r\n if (this.options.loop) {\r\n prevIndex = this.tracks.length - 1;\r\n } else {\r\n return;\r\n }\r\n }\r\n \r\n this.play(prevIndex);\r\n }\r\n \r\n /**\r\n * Handle track end\r\n */\r\n handleTrackEnd() {\r\n if (this.options.autoAdvance) {\r\n this.next();\r\n }\r\n }\r\n \r\n /**\r\n * Handle track error\r\n */\r\n handleTrackError(e) {\r\n console.error('VidPly Playlist: Track error', e);\r\n \r\n // Try next track\r\n if (this.options.autoAdvance) {\r\n setTimeout(() => {\r\n this.next();\r\n }, 1000);\r\n }\r\n }\r\n \r\n /**\r\n * Create playlist UI\r\n */\r\n createUI() {\r\n // Find player container\r\n this.container = this.player.container;\r\n \r\n if (!this.container) {\r\n console.warn('VidPly Playlist: No container found');\r\n return;\r\n }\r\n \r\n // Create track info element (shows current track)\r\n this.trackInfoElement = DOMUtils.createElement('div', {\r\n className: 'vidply-track-info',\r\n role: 'status',\r\n 'aria-live': 'polite',\r\n 'aria-atomic': 'true'\r\n });\r\n this.trackInfoElement.style.display = 'none';\r\n \r\n this.container.appendChild(this.trackInfoElement);\r\n \r\n // Create playlist panel with proper landmark\r\n this.playlistPanel = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-panel',\r\n role: 'region',\r\n 'aria-label': 'Media playlist'\r\n });\r\n this.playlistPanel.style.display = 'none';\r\n \r\n this.container.appendChild(this.playlistPanel);\r\n }\r\n \r\n /**\r\n * Update track info display\r\n */\r\n updateTrackInfo(track) {\r\n if (!this.trackInfoElement) return;\r\n \r\n const trackNumber = this.currentIndex + 1;\r\n const totalTracks = this.tracks.length;\r\n const trackTitle = track.title || 'Untitled';\r\n const trackArtist = track.artist || '';\r\n \r\n // Screen reader announcement\r\n const announcement = `Now playing: Track ${trackNumber} of ${totalTracks}. ${trackTitle}${trackArtist ? ' by ' + trackArtist : ''}`;\r\n \r\n this.trackInfoElement.innerHTML = `\r\n <span class=\"vidply-sr-only\">${DOMUtils.escapeHTML(announcement)}</span>\r\n <div class=\"vidply-track-number\" aria-hidden=\"true\">Track ${trackNumber} of ${totalTracks}</div>\r\n <div class=\"vidply-track-title\" aria-hidden=\"true\">${DOMUtils.escapeHTML(trackTitle)}</div>\r\n ${trackArtist ? `<div class=\"vidply-track-artist\" aria-hidden=\"true\">${DOMUtils.escapeHTML(trackArtist)}</div>` : ''}\r\n `;\r\n \r\n this.trackInfoElement.style.display = 'block';\r\n }\r\n \r\n /**\r\n * Render playlist\r\n */\r\n renderPlaylist() {\r\n if (!this.playlistPanel) return;\r\n \r\n // Clear existing\r\n this.playlistPanel.innerHTML = '';\r\n \r\n // Create header\r\n const header = DOMUtils.createElement('h2', {\r\n className: 'vidply-playlist-header',\r\n id: 'vidply-playlist-heading'\r\n });\r\n header.textContent = `Playlist (${this.tracks.length})`;\r\n this.playlistPanel.appendChild(header);\r\n \r\n // Add keyboard instructions (visually hidden)\r\n const instructions = DOMUtils.createElement('div', {\r\n className: 'vidply-sr-only',\r\n 'aria-hidden': 'false'\r\n });\r\n instructions.textContent = 'Use arrow keys to navigate between tracks. Press Enter or Space to play a track. Press Home or End to jump to first or last track.';\r\n this.playlistPanel.appendChild(instructions);\r\n \r\n // Create list (proper ul element)\r\n const list = DOMUtils.createElement('ul', {\r\n className: 'vidply-playlist-list',\r\n 'aria-labelledby': 'vidply-playlist-heading',\r\n 'aria-describedby': 'vidply-playlist-instructions'\r\n });\r\n \r\n // Add list description\r\n const listDescription = DOMUtils.createElement('div', {\r\n className: 'vidply-sr-only',\r\n id: 'vidply-playlist-instructions'\r\n });\r\n listDescription.textContent = `Playlist with ${this.tracks.length} ${this.tracks.length === 1 ? 'track' : 'tracks'}`;\r\n this.playlistPanel.appendChild(listDescription);\r\n \r\n this.tracks.forEach((track, index) => {\r\n const item = this.createPlaylistItem(track, index);\r\n list.appendChild(item);\r\n });\r\n \r\n this.playlistPanel.appendChild(list);\r\n this.playlistPanel.style.display = 'block';\r\n }\r\n \r\n /**\r\n * Create playlist item element\r\n */\r\n createPlaylistItem(track, index) {\r\n const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;\r\n const trackTitle = track.title || `Track ${index + 1}`;\r\n const trackArtist = track.artist ? ` by ${track.artist}` : '';\r\n const isActive = index === this.currentIndex;\r\n const statusText = isActive ? 'Currently playing' : 'Not playing';\r\n const actionText = isActive ? 'Press Enter to restart' : 'Press Enter to play';\r\n \r\n const item = DOMUtils.createElement('li', {\r\n className: 'vidply-playlist-item',\r\n tabIndex: index === 0 ? 0 : -1, // Only first item is in tab order initially\r\n 'aria-label': `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`,\r\n 'aria-posinset': index + 1,\r\n 'aria-setsize': this.tracks.length,\r\n 'data-playlist-index': index\r\n });\r\n \r\n // Add active class if current\r\n if (isActive) {\r\n item.classList.add('vidply-playlist-item-active');\r\n item.setAttribute('aria-current', 'true');\r\n item.setAttribute('tabIndex', '0'); // Active item should always be tabbable\r\n }\r\n \r\n // Add screen reader only position info\r\n const positionInfo = DOMUtils.createElement('span', {\r\n className: 'vidply-sr-only'\r\n });\r\n positionInfo.textContent = `${trackPosition}: `;\r\n item.appendChild(positionInfo);\r\n \r\n // Thumbnail or icon\r\n const thumbnail = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-thumbnail',\r\n 'aria-hidden': 'true'\r\n });\r\n \r\n if (track.poster) {\r\n thumbnail.style.backgroundImage = `url(${track.poster})`;\r\n thumbnail.setAttribute('role', 'img');\r\n thumbnail.setAttribute('aria-label', `${trackTitle} thumbnail`);\r\n } else {\r\n // Show music/speaker icon for audio tracks\r\n const icon = createIconElement('music');\r\n icon.classList.add('vidply-playlist-thumbnail-icon');\r\n thumbnail.appendChild(icon);\r\n }\r\n \r\n item.appendChild(thumbnail);\r\n \r\n // Info\r\n const info = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-info',\r\n 'aria-hidden': 'true'\r\n });\r\n \r\n const title = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-title'\r\n });\r\n title.textContent = trackTitle;\r\n info.appendChild(title);\r\n \r\n if (track.artist) {\r\n const artist = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-artist'\r\n });\r\n artist.textContent = track.artist;\r\n info.appendChild(artist);\r\n }\r\n \r\n item.appendChild(info);\r\n \r\n // Status indicator for screen readers\r\n if (isActive) {\r\n const statusIndicator = DOMUtils.createElement('span', {\r\n className: 'vidply-sr-only'\r\n });\r\n statusIndicator.textContent = ' (Currently playing)';\r\n item.appendChild(statusIndicator);\r\n }\r\n \r\n // Play icon\r\n const playIcon = createIconElement('play');\r\n playIcon.classList.add('vidply-playlist-item-icon');\r\n playIcon.setAttribute('aria-hidden', 'true');\r\n item.appendChild(playIcon);\r\n \r\n // Click handler\r\n item.addEventListener('click', () => {\r\n this.play(index, true); // User-initiated\r\n });\r\n \r\n // Keyboard handler\r\n item.addEventListener('keydown', (e) => {\r\n this.handlePlaylistItemKeydown(e, index);\r\n });\r\n \r\n return item;\r\n }\r\n \r\n /**\r\n * Handle keyboard navigation in playlist items\r\n */\r\n handlePlaylistItemKeydown(e, index) {\r\n const items = Array.from(this.playlistPanel.querySelectorAll('.vidply-playlist-item'));\r\n let newIndex = -1;\r\n \r\n switch(e.key) {\r\n case 'Enter':\r\n case ' ':\r\n e.preventDefault();\r\n this.play(index, true); // User-initiated\r\n break;\r\n \r\n case 'ArrowDown':\r\n e.preventDefault();\r\n // Move to next item\r\n if (index < items.length - 1) {\r\n newIndex = index + 1;\r\n }\r\n break;\r\n \r\n case 'ArrowUp':\r\n e.preventDefault();\r\n // Move to previous item\r\n if (index > 0) {\r\n newIndex = index - 1;\r\n }\r\n break;\r\n \r\n case 'Home':\r\n e.preventDefault();\r\n // Move to first item\r\n newIndex = 0;\r\n break;\r\n \r\n case 'End':\r\n e.preventDefault();\r\n // Move to last item\r\n newIndex = items.length - 1;\r\n break;\r\n }\r\n \r\n // Update tab indices for roving tabindex pattern\r\n if (newIndex !== -1 && newIndex !== index) {\r\n items[index].setAttribute('tabIndex', '-1');\r\n items[newIndex].setAttribute('tabIndex', '0');\r\n items[newIndex].focus();\r\n }\r\n }\r\n \r\n /**\r\n * Update playlist UI (highlight current track)\r\n */\r\n updatePlaylistUI() {\r\n if (!this.playlistPanel) return;\r\n \r\n const items = this.playlistPanel.querySelectorAll('.vidply-playlist-item');\r\n \r\n items.forEach((item, index) => {\r\n const track = this.tracks[index];\r\n const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;\r\n const trackTitle = track.title || `Track ${index + 1}`;\r\n const trackArtist = track.artist ? ` by ${track.artist}` : '';\r\n \r\n if (index === this.currentIndex) {\r\n item.classList.add('vidply-playlist-item-active');\r\n item.setAttribute('aria-current', 'true');\r\n item.setAttribute('tabIndex', '0'); // Active item should be tabbable\r\n \r\n const statusText = 'Currently playing';\r\n const actionText = 'Press Enter to restart';\r\n item.setAttribute('aria-label', `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`);\r\n \r\n // Scroll into view\r\n item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n } else {\r\n item.classList.remove('vidply-playlist-item-active');\r\n item.removeAttribute('aria-current');\r\n item.setAttribute('tabIndex', '-1'); // Remove from tab order (use arrow keys)\r\n \r\n const statusText = 'Not playing';\r\n const actionText = 'Press Enter to play';\r\n item.setAttribute('aria-label', `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`);\r\n }\r\n });\r\n }\r\n \r\n /**\r\n * Get current track\r\n */\r\n getCurrentTrack() {\r\n return this.tracks[this.currentIndex] || null;\r\n }\r\n \r\n /**\r\n * Get playlist info\r\n */\r\n getPlaylistInfo() {\r\n return {\r\n currentIndex: this.currentIndex,\r\n totalTracks: this.tracks.length,\r\n currentTrack: this.getCurrentTrack(),\r\n hasNext: this.hasNext(),\r\n hasPrevious: this.hasPrevious()\r\n };\r\n }\r\n \r\n /**\r\n * Check if there is a next track\r\n */\r\n hasNext() {\r\n if (this.options.loop) return true;\r\n return this.currentIndex < this.tracks.length - 1;\r\n }\r\n \r\n /**\r\n * Check if there is a previous track\r\n */\r\n hasPrevious() {\r\n if (this.options.loop) return true;\r\n return this.currentIndex > 0;\r\n }\r\n \r\n /**\r\n * Add track to playlist\r\n */\r\n addTrack(track) {\r\n this.tracks.push(track);\r\n \r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n }\r\n \r\n /**\r\n * Remove track from playlist\r\n */\r\n removeTrack(index) {\r\n if (index < 0 || index >= this.tracks.length) return;\r\n \r\n this.tracks.splice(index, 1);\r\n \r\n // Adjust current index if needed\r\n if (index < this.currentIndex) {\r\n this.currentIndex--;\r\n } else if (index === this.currentIndex) {\r\n // Current track was removed, play next or stop\r\n if (this.currentIndex >= this.tracks.length) {\r\n this.currentIndex = this.tracks.length - 1;\r\n }\r\n \r\n if (this.currentIndex >= 0) {\r\n this.play(this.currentIndex);\r\n }\r\n }\r\n \r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n }\r\n \r\n /**\r\n * Clear playlist\r\n */\r\n clear() {\r\n this.tracks = [];\r\n this.currentIndex = -1;\r\n \r\n if (this.playlistPanel) {\r\n this.playlistPanel.innerHTML = '';\r\n this.playlistPanel.style.display = 'none';\r\n }\r\n \r\n if (this.trackInfoElement) {\r\n this.trackInfoElement.innerHTML = '';\r\n this.trackInfoElement.style.display = 'none';\r\n }\r\n }\r\n \r\n /**\r\n * Destroy playlist manager\r\n */\r\n destroy() {\r\n // Remove event listeners\r\n this.player.off('ended', this.handleTrackEnd);\r\n this.player.off('error', this.handleTrackError);\r\n \r\n // Remove UI\r\n if (this.trackInfoElement) {\r\n this.trackInfoElement.remove();\r\n }\r\n \r\n if (this.playlistPanel) {\r\n this.playlistPanel.remove();\r\n }\r\n \r\n // Clear data\r\n this.clear();\r\n }\r\n}\r\n\r\nexport default PlaylistManager;\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\r\n * HTML5 Media Renderer\r\n */\r\n\r\nexport class HTML5Renderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n }\r\n\r\n async init() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n this.attachEvents();\r\n \r\n // Set preload\r\n this.media.preload = this.player.options.preload;\r\n \r\n // Load media\r\n this.media.load();\r\n }\r\n\r\n attachEvents() {\r\n // Playback events\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n \r\n // Pause other players if enabled\r\n if (this.player.options.pauseOthersOnPlay) {\r\n this.pauseOtherPlayers();\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n // Handle loop\r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n \r\n if (this.player.options.onVolumeChange) {\r\n this.player.options.onVolumeChange.call(this.player, this.media.volume);\r\n }\r\n });\r\n\r\n this.media.addEventListener('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.media.addEventListener('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('progress', () => {\r\n if (this.media.buffered.length > 0) {\r\n const buffered = this.media.buffered.end(this.media.buffered.length - 1);\r\n this.player.emit('progress', buffered);\r\n }\r\n });\r\n\r\n this.media.addEventListener('error', (e) => {\r\n this.player.handleError(this.media.error);\r\n });\r\n\r\n this.media.addEventListener('ratechange', () => {\r\n this.player.state.playbackSpeed = this.media.playbackRate;\r\n this.player.emit('ratechange', this.media.playbackRate);\r\n });\r\n }\r\n\r\n pauseOtherPlayers() {\r\n // Pause other VidPly instances\r\n const allPlayers = document.querySelectorAll('.vidply-player');\r\n allPlayers.forEach(playerEl => {\r\n if (playerEl !== this.player.container) {\r\n const video = playerEl.querySelector('video, audio');\r\n if (video && !video.paused) {\r\n video.pause();\r\n }\r\n }\r\n });\r\n }\r\n\r\n play() {\r\n const promise = this.media.play();\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n \r\n // If autoplay failed, try muted autoplay\r\n if (this.player.options.autoplay && !this.player.state.muted) {\r\n this.player.log('Retrying play with muted audio', 'info');\r\n this.media.muted = true;\r\n this.media.play().catch(err => {\r\n this.player.handleError(err);\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n /**\r\n * Get available quality levels from source elements\r\n * @returns {Array} Array of quality objects with index, height, width, and src\r\n */\r\n getQualities() {\r\n const sources = Array.from(this.media.querySelectorAll('source'));\r\n \r\n if (sources.length <= 1) {\r\n return [];\r\n }\r\n\r\n return sources.map((source, index) => {\r\n // Try to extract quality from data attributes or label\r\n const label = source.getAttribute('data-quality') || source.getAttribute('label') || '';\r\n const height = source.getAttribute('data-height') || this.extractHeightFromLabel(label);\r\n const width = source.getAttribute('data-width') || '';\r\n \r\n return {\r\n index,\r\n height: height ? parseInt(height) : 0,\r\n width: width ? parseInt(width) : 0,\r\n src: source.src,\r\n type: source.type,\r\n name: label || (height ? `${height}p` : `Quality ${index + 1}`)\r\n };\r\n }).filter(q => q.height > 0); // Only return qualities with valid height\r\n }\r\n\r\n /**\r\n * Extract height from quality label (e.g., \"1080p\" -> 1080)\r\n * @param {string} label \r\n * @returns {number}\r\n */\r\n extractHeightFromLabel(label) {\r\n const match = label.match(/(\\d+)p/i);\r\n return match ? parseInt(match[1]) : 0;\r\n }\r\n\r\n /**\r\n * Switch to a specific quality level\r\n * @param {number} qualityIndex - Index of the quality level (-1 for auto, not applicable for HTML5)\r\n */\r\n switchQuality(qualityIndex) {\r\n const qualities = this.getQualities();\r\n \r\n if (qualityIndex < 0 || qualityIndex >= qualities.length) {\r\n this.player.log('Invalid quality index', 'warn');\r\n return;\r\n }\r\n\r\n const quality = qualities[qualityIndex];\r\n const currentTime = this.media.currentTime;\r\n const wasPlaying = !this.media.paused;\r\n\r\n // Store the current source for comparison\r\n const currentSrc = this.media.currentSrc;\r\n \r\n // Don't switch if already at this quality\r\n if (currentSrc === quality.src) {\r\n this.player.log('Already at this quality level', 'info');\r\n return;\r\n }\r\n\r\n this.player.log(`Switching to quality: ${quality.name}`, 'info');\r\n\r\n // Update the src\r\n this.media.src = quality.src;\r\n \r\n // Wait for the new source to load, then restore playback state\r\n const onLoadedMetadata = () => {\r\n this.media.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n \r\n // Restore playback position\r\n this.media.currentTime = currentTime;\r\n \r\n // Resume playback if it was playing\r\n if (wasPlaying) {\r\n this.media.play().catch(err => {\r\n this.player.log('Failed to resume playback after quality switch', 'warn');\r\n });\r\n }\r\n \r\n // Emit quality change event\r\n this.player.emit('qualitychange', { quality: quality.name, index: qualityIndex });\r\n };\r\n\r\n this.media.addEventListener('loadedmetadata', onLoadedMetadata);\r\n this.media.load();\r\n }\r\n\r\n /**\r\n * Get current quality index\r\n * @returns {number}\r\n */\r\n getCurrentQuality() {\r\n const qualities = this.getQualities();\r\n const currentSrc = this.media.currentSrc;\r\n \r\n for (let i = 0; i < qualities.length; i++) {\r\n if (qualities[i].src === currentSrc) {\r\n return i;\r\n }\r\n }\r\n \r\n return 0; // Default to first quality if not found\r\n }\r\n\r\n destroy() {\r\n // Remove event listeners\r\n this.media.removeEventListener('loadedmetadata', () => {});\r\n this.media.removeEventListener('play', () => {});\r\n this.media.removeEventListener('pause', () => {});\r\n // ... (other listeners would be removed in a real implementation)\r\n }\r\n}\r\n\r\n", "/**\r\n * VidPly - Universal Video Player\r\n * Main Entry Point\r\n */\r\n\r\nimport { Player } from './core/Player.js';\r\nimport { PlaylistManager } from './features/PlaylistManager.js';\r\n\r\n// Auto-initialize players\r\nfunction initializePlayers() {\r\n const elements = document.querySelectorAll('[data-vidply]');\r\n \r\n elements.forEach(element => {\r\n // Parse options from data attribute (JSON format)\r\n const options = element.dataset.vidplyOptions \r\n ? JSON.parse(element.dataset.vidplyOptions)\r\n : {};\r\n \r\n // Parse individual data attributes and merge with options\r\n // This allows for easier HTML-based configuration\r\n const dataOptions = parseDataAttributes(element.dataset);\r\n const mergedOptions = { ...dataOptions, ...options };\r\n \r\n // Create player instance\r\n new Player(element, mergedOptions);\r\n });\r\n}\r\n\r\n// Helper function to parse data attributes into options\r\nfunction parseDataAttributes(dataset) {\r\n const options = {};\r\n \r\n // Map of data attribute names to option keys (camelCase conversion)\r\n const attributeMap = {\r\n // Sign Language\r\n 'signLanguageSrc': 'signLanguageSrc',\r\n 'signLanguageButton': 'signLanguageButton',\r\n 'signLanguagePosition': 'signLanguagePosition',\r\n \r\n // Audio Description\r\n 'audioDescriptionSrc': 'audioDescriptionSrc',\r\n 'audioDescriptionButton': 'audioDescriptionButton',\r\n \r\n // Other common options\r\n 'autoplay': 'autoplay',\r\n 'loop': 'loop',\r\n 'muted': 'muted',\r\n 'controls': 'controls',\r\n 'poster': 'poster',\r\n 'width': 'width',\r\n 'height': 'height',\r\n 'language': 'language',\r\n 'captions': 'captions',\r\n 'captionsDefault': 'captionsDefault',\r\n 'transcript': 'transcript',\r\n 'transcriptButton': 'transcriptButton',\r\n 'keyboard': 'keyboard',\r\n 'responsive': 'responsive',\r\n 'pipButton': 'pipButton',\r\n 'fullscreenButton': 'fullscreenButton'\r\n };\r\n \r\n // Parse each data attribute\r\n Object.keys(attributeMap).forEach(dataKey => {\r\n const optionKey = attributeMap[dataKey];\r\n const value = dataset[dataKey];\r\n \r\n if (value !== undefined) {\r\n // Convert string values to appropriate types\r\n if (value === 'true') {\r\n options[optionKey] = true;\r\n } else if (value === 'false') {\r\n options[optionKey] = false;\r\n } else if (!isNaN(value) && value !== '') {\r\n options[optionKey] = Number(value);\r\n } else {\r\n options[optionKey] = value;\r\n }\r\n }\r\n });\r\n \r\n return options;\r\n}\r\n\r\n// Auto-initialize on DOM ready\r\nif (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initializePlayers);\r\n} else {\r\n initializePlayers();\r\n}\r\n\r\n// Export for manual initialization\r\nexport { Player, PlaylistManager };\r\nexport default Player;\r\n\r\n", "/**\r\n * Simple EventEmitter implementation\r\n */\r\n\r\nexport class EventEmitter {\r\n constructor() {\r\n this.events = {};\r\n }\r\n\r\n on(event, listener) {\r\n if (!this.events[event]) {\r\n this.events[event] = [];\r\n }\r\n this.events[event].push(listener);\r\n return this;\r\n }\r\n\r\n once(event, listener) {\r\n const onceListener = (...args) => {\r\n listener(...args);\r\n this.off(event, onceListener);\r\n };\r\n return this.on(event, onceListener);\r\n }\r\n\r\n off(event, listener) {\r\n if (!this.events[event]) return this;\r\n \r\n if (!listener) {\r\n delete this.events[event];\r\n } else {\r\n this.events[event] = this.events[event].filter(l => l !== listener);\r\n }\r\n \r\n return this;\r\n }\r\n\r\n emit(event, ...args) {\r\n if (!this.events[event]) return this;\r\n \r\n this.events[event].forEach(listener => {\r\n listener(...args);\r\n });\r\n \r\n return this;\r\n }\r\n\r\n removeAllListeners() {\r\n this.events = {};\r\n return this;\r\n }\r\n}\r\n\r\n", "/**\r\n * DOM manipulation utilities\r\n */\r\n\r\nexport const DOMUtils = {\r\n createElement(tag, options = {}) {\r\n const element = document.createElement(tag);\r\n \r\n if (options.className) {\r\n element.className = options.className;\r\n }\r\n \r\n if (options.attributes) {\r\n Object.entries(options.attributes).forEach(([key, value]) => {\r\n element.setAttribute(key, value);\r\n });\r\n }\r\n \r\n if (options.innerHTML) {\r\n element.innerHTML = options.innerHTML;\r\n }\r\n \r\n if (options.textContent) {\r\n element.textContent = options.textContent;\r\n }\r\n \r\n if (options.style) {\r\n Object.assign(element.style, options.style);\r\n }\r\n \r\n if (options.children) {\r\n options.children.forEach(child => {\r\n if (child) element.appendChild(child);\r\n });\r\n }\r\n \r\n return element;\r\n },\r\n\r\n addClass(element, className) {\r\n if (element && className) {\r\n element.classList.add(className);\r\n }\r\n },\r\n\r\n removeClass(element, className) {\r\n if (element && className) {\r\n element.classList.remove(className);\r\n }\r\n },\r\n\r\n toggleClass(element, className) {\r\n if (element && className) {\r\n element.classList.toggle(className);\r\n }\r\n },\r\n\r\n hasClass(element, className) {\r\n return element && element.classList.contains(className);\r\n },\r\n\r\n show(element) {\r\n if (element) {\r\n element.style.display = '';\r\n }\r\n },\r\n\r\n hide(element) {\r\n if (element) {\r\n element.style.display = 'none';\r\n }\r\n },\r\n\r\n fadeIn(element, duration = 300) {\r\n if (!element) return;\r\n \r\n element.style.opacity = '0';\r\n element.style.display = '';\r\n \r\n let start = null;\r\n const animate = (timestamp) => {\r\n if (!start) start = timestamp;\r\n const progress = timestamp - start;\r\n const opacity = Math.min(progress / duration, 1);\r\n \r\n element.style.opacity = opacity;\r\n \r\n if (progress < duration) {\r\n requestAnimationFrame(animate);\r\n }\r\n };\r\n \r\n requestAnimationFrame(animate);\r\n },\r\n\r\n fadeOut(element, duration = 300) {\r\n if (!element) return;\r\n \r\n const startOpacity = parseFloat(getComputedStyle(element).opacity) || 1;\r\n let start = null;\r\n \r\n const animate = (timestamp) => {\r\n if (!start) start = timestamp;\r\n const progress = timestamp - start;\r\n const opacity = Math.max(startOpacity - (progress / duration), 0);\r\n \r\n element.style.opacity = opacity;\r\n \r\n if (progress < duration) {\r\n requestAnimationFrame(animate);\r\n } else {\r\n element.style.display = 'none';\r\n }\r\n };\r\n \r\n requestAnimationFrame(animate);\r\n },\r\n\r\n offset(element) {\r\n if (!element) return { top: 0, left: 0 };\r\n \r\n const rect = element.getBoundingClientRect();\r\n return {\r\n top: rect.top + window.pageYOffset,\r\n left: rect.left + window.pageXOffset,\r\n width: rect.width,\r\n height: rect.height\r\n };\r\n },\r\n\r\n escapeHTML(str) {\r\n const div = document.createElement('div');\r\n div.textContent = str;\r\n return div.innerHTML;\r\n },\r\n\r\n sanitizeHTML(html) {\r\n // Basic HTML sanitization - allow safe tags for VTT captions\r\n // Since we control the HTML (from VTT parsing), we can safely allow these tags\r\n const temp = document.createElement('div');\r\n \r\n // Strip out any potentially dangerous tags/attributes\r\n // Allow: strong, em, u, span, b, i with class and data-voice attributes\r\n const safeHtml = html\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '')\r\n .replace(/on\\w+\\s*=/gi, '') // Remove event handlers\r\n .replace(/javascript:/gi, ''); // Remove javascript: protocol\r\n \r\n temp.innerHTML = safeHtml;\r\n return temp.innerHTML;\r\n }\r\n};\r\n\r\n", "/**\r\n * Translation strings for VidPly\r\n */\r\n\r\nexport const translations = {\r\n en: {\r\n player: {\r\n label: 'Video Player',\r\n play: 'Play',\r\n pause: 'Pause',\r\n stop: 'Stop',\r\n restart: 'Restart from beginning',\r\n rewind: 'Rewind',\r\n forward: 'Forward',\r\n rewindSeconds: 'Rewind {seconds} seconds',\r\n forwardSeconds: 'Forward {seconds} seconds',\r\n previous: 'Previous track',\r\n next: 'Next track',\r\n volume: 'Volume',\r\n mute: 'Mute',\r\n unmute: 'Unmute',\r\n fullscreen: 'Fullscreen',\r\n exitFullscreen: 'Exit Fullscreen',\r\n captions: 'Captions',\r\n chapters: 'Chapters',\r\n quality: 'Quality',\r\n captionStyling: 'Caption styling',\r\n transcript: 'Toggle transcript',\r\n audioDescription: 'Audio description',\r\n signLanguage: 'Sign language video',\r\n settings: 'Settings',\r\n speed: 'Playback Speed',\r\n pip: 'Picture in Picture',\r\n currentTime: 'Current time',\r\n duration: 'Duration',\r\n progress: 'Progress',\r\n seekForward: 'Seek forward {seconds} seconds',\r\n seekBackward: 'Seek backward {seconds} seconds',\r\n volumeUp: 'Volume up',\r\n volumeDown: 'Volume down',\r\n loading: 'Loading...',\r\n loadingChapters: 'Loading chapters...',\r\n error: 'Error loading media',\r\n buffering: 'Buffering...',\r\n signLanguageVideo: 'Sign Language Video',\r\n noChapters: 'No chapters available',\r\n noCaptions: 'No captions available',\r\n auto: 'Auto',\r\n autoQuality: 'Auto (no quality selection available)',\r\n noQuality: 'Quality selection not available',\r\n signLanguageDragResize: 'Sign Language Video - Press D to drag with keyboard, R to resize',\r\n signLanguageDragActive: 'Sign Language Video - Drag mode active. Use arrow keys to move, Escape to exit.',\r\n signLanguageResizeActive: 'Sign Language Video - Resize mode active. Use left/right arrow keys to resize, Escape to exit.',\r\n resizeHandle: 'Resize {direction} corner'\r\n },\r\n captions: {\r\n off: 'Off',\r\n select: 'Select captions',\r\n fontSize: 'Font Size',\r\n fontFamily: 'Font Family',\r\n color: 'Text Color',\r\n backgroundColor: 'Background Color',\r\n opacity: 'Opacity'\r\n },\r\n fontSizes: {\r\n small: 'Small',\r\n normal: 'Normal',\r\n large: 'Large',\r\n xlarge: 'X-Large'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Text Color',\r\n background: 'Background',\r\n font: 'Font',\r\n fontSize: 'Font Size',\r\n opacity: 'Opacity'\r\n },\r\n audioDescription: {\r\n enable: 'Enable audio description',\r\n disable: 'Disable audio description'\r\n },\r\n signLanguage: {\r\n show: 'Show sign language video',\r\n hide: 'Hide sign language video'\r\n },\r\n transcript: {\r\n title: 'Transcript',\r\n close: 'Close transcript',\r\n loading: 'Loading transcript...',\r\n noTranscript: 'No transcript available for this video.',\r\n settings: 'Transcript settings. Press Enter to open menu, or D to enable drag mode',\r\n keyboardDragMode: 'Toggle keyboard drag mode with arrow keys. Shortcut: D key',\r\n keyboardDragActive: '\u2328\uFE0F Keyboard Drag Mode Active (Arrow keys to move, Shift+Arrows for large steps, D or ESC to exit)',\r\n resizeWindow: 'Resize Window',\r\n styleTranscript: 'Open transcript style settings',\r\n closeMenu: 'Close Menu',\r\n styleTitle: 'Transcript Style',\r\n autoscroll: 'Autoscroll'\r\n },\r\n settings: {\r\n title: 'Settings',\r\n quality: 'Quality',\r\n speed: 'Speed',\r\n captions: 'Captions',\r\n language: 'Language',\r\n reset: 'Reset to defaults',\r\n close: 'Close'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Time display',\r\n durationPrefix: 'Duration: ',\r\n hour: '{count} hour',\r\n hours: '{count} hours',\r\n minute: '{count} minute',\r\n minutes: '{count} minutes',\r\n second: '{count} second',\r\n seconds: '{count} seconds'\r\n }\r\n },\r\n \r\n de: {\r\n player: {\r\n label: 'Videoplayer',\r\n play: 'Abspielen',\r\n pause: 'Pause',\r\n stop: 'Stopp',\r\n restart: 'Von vorne beginnen',\r\n rewind: 'Zur\u00FCckspulen',\r\n forward: 'Vorspulen',\r\n rewindSeconds: '{seconds} Sekunden zur\u00FCckspulen',\r\n forwardSeconds: '{seconds} Sekunden vorspulen',\r\n previous: 'Vorheriger Titel',\r\n next: 'N\u00E4chster Titel',\r\n volume: 'Lautst\u00E4rke',\r\n mute: 'Stumm',\r\n unmute: 'Ton ein',\r\n fullscreen: 'Vollbild',\r\n exitFullscreen: 'Vollbild beenden',\r\n captions: 'Untertitel',\r\n chapters: 'Kapitel',\r\n quality: 'Qualit\u00E4t',\r\n captionStyling: 'Untertitel-Stil',\r\n transcript: 'Transkript umschalten',\r\n audioDescription: 'Audiodeskription',\r\n signLanguage: 'Geb\u00E4rdensprache-Video',\r\n settings: 'Einstellungen',\r\n speed: 'Wiedergabegeschwindigkeit',\r\n pip: 'Bild-in-Bild',\r\n currentTime: 'Aktuelle Zeit',\r\n duration: 'Dauer',\r\n progress: 'Fortschritt',\r\n seekForward: '{seconds} Sekunden vorspulen',\r\n seekBackward: '{seconds} Sekunden zur\u00FCckspulen',\r\n volumeUp: 'Lauter',\r\n volumeDown: 'Leiser',\r\n loading: 'L\u00E4dt...',\r\n loadingChapters: 'Kapitel werden geladen...',\r\n error: 'Fehler beim Laden',\r\n buffering: 'Puffern...',\r\n signLanguageVideo: 'Geb\u00E4rdensprache-Video',\r\n noChapters: 'Keine Kapitel verf\u00FCgbar',\r\n noCaptions: 'Keine Untertitel verf\u00FCgbar',\r\n auto: 'Automatisch',\r\n autoQuality: 'Automatisch (keine Qualit\u00E4tsauswahl verf\u00FCgbar)',\r\n noQuality: 'Qualit\u00E4tsauswahl nicht verf\u00FCgbar',\r\n signLanguageDragResize: 'Geb\u00E4rdensprache-Video - Dr\u00FCcken Sie D zum Verschieben per Tastatur, R zum \u00C4ndern der Gr\u00F6\u00DFe',\r\n signLanguageDragActive: 'Geb\u00E4rdensprache-Video - Verschiebemodus aktiv. Pfeiltasten zum Bewegen, Escape zum Beenden.',\r\n signLanguageResizeActive: 'Geb\u00E4rdensprache-Video - Gr\u00F6\u00DFen\u00E4nderungsmodus aktiv. Links-/Rechts-Pfeiltasten zum \u00C4ndern der Gr\u00F6\u00DFe, Escape zum Beenden.',\r\n resizeHandle: 'Gr\u00F6\u00DFen\u00E4nderung {direction}-Ecke'\r\n },\r\n captions: {\r\n off: 'Aus',\r\n select: 'Untertitel ausw\u00E4hlen',\r\n fontSize: 'Schriftgr\u00F6\u00DFe',\r\n fontFamily: 'Schriftart',\r\n color: 'Textfarbe',\r\n backgroundColor: 'Hintergrundfarbe',\r\n opacity: 'Deckkraft'\r\n },\r\n fontSizes: {\r\n small: 'Klein',\r\n normal: 'Normal',\r\n large: 'Gro\u00DF',\r\n xlarge: 'Sehr gro\u00DF'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Textfarbe',\r\n background: 'Hintergrund',\r\n font: 'Schrift',\r\n fontSize: 'Schriftgr\u00F6\u00DFe',\r\n opacity: 'Deckkraft'\r\n },\r\n audioDescription: {\r\n enable: 'Audiodeskription aktivieren',\r\n disable: 'Audiodeskription deaktivieren'\r\n },\r\n signLanguage: {\r\n show: 'Geb\u00E4rdensprache-Video anzeigen',\r\n hide: 'Geb\u00E4rdensprache-Video ausblenden'\r\n },\r\n transcript: {\r\n title: 'Transkript',\r\n close: 'Transkript schlie\u00DFen',\r\n loading: 'Transkript wird geladen...',\r\n noTranscript: 'Kein Transkript f\u00FCr dieses Video verf\u00FCgbar.',\r\n settings: 'Transkript-Einstellungen. Eingabetaste zum \u00D6ffnen des Men\u00FCs dr\u00FCcken oder D zum Aktivieren des Verschiebemodus',\r\n keyboardDragMode: 'Tastatur-Verschiebemodus mit Pfeiltasten umschalten. Tastenkombination: D-Taste',\r\n keyboardDragActive: '\u2328\uFE0F Tastatur-Verschiebemodus aktiv (Pfeiltasten zum Bewegen, Umschalt+Pfeiltasten f\u00FCr gro\u00DFe Schritte, D oder ESC zum Beenden)',\r\n resizeWindow: 'Fenster vergr\u00F6\u00DFern/verkleinern',\r\n styleTranscript: 'Transkript-Stileinstellungen \u00F6ffnen',\r\n closeMenu: 'Men\u00FC schlie\u00DFen',\r\n styleTitle: 'Transkript-Stil',\r\n autoscroll: 'Automatisches Scrollen'\r\n },\r\n settings: {\r\n title: 'Einstellungen',\r\n quality: 'Qualit\u00E4t',\r\n speed: 'Geschwindigkeit',\r\n captions: 'Untertitel',\r\n language: 'Sprache',\r\n reset: 'Zur\u00FCcksetzen',\r\n close: 'Schlie\u00DFen'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Zeitanzeige',\r\n durationPrefix: 'Dauer: ',\r\n hour: '{count} Stunde',\r\n hours: '{count} Stunden',\r\n minute: '{count} Minute',\r\n minutes: '{count} Minuten',\r\n second: '{count} Sekunde',\r\n seconds: '{count} Sekunden'\r\n }\r\n },\r\n\r\n es: {\r\n player: {\r\n label: 'Reproductor de video',\r\n play: 'Reproducir',\r\n pause: 'Pausa',\r\n stop: 'Detener',\r\n restart: 'Reiniciar desde el principio',\r\n rewind: 'Retroceder',\r\n forward: 'Avanzar',\r\n rewindSeconds: 'Retroceder {seconds} segundos',\r\n forwardSeconds: 'Avanzar {seconds} segundos',\r\n previous: 'Pista anterior',\r\n next: 'Siguiente pista',\r\n volume: 'Volumen',\r\n mute: 'Silenciar',\r\n unmute: 'Activar sonido',\r\n fullscreen: 'Pantalla completa',\r\n exitFullscreen: 'Salir de pantalla completa',\r\n captions: 'Subt\u00EDtulos',\r\n chapters: 'Cap\u00EDtulos',\r\n quality: 'Calidad',\r\n captionStyling: 'Estilo de subt\u00EDtulos',\r\n transcript: 'Alternar transcripci\u00F3n',\r\n audioDescription: 'Audiodescripci\u00F3n',\r\n signLanguage: 'Video en lengua de se\u00F1as',\r\n settings: 'Configuraci\u00F3n',\r\n speed: 'Velocidad de reproducci\u00F3n',\r\n pip: 'Imagen en imagen',\r\n currentTime: 'Tiempo actual',\r\n duration: 'Duraci\u00F3n',\r\n progress: 'Progreso',\r\n seekForward: 'Avanzar {seconds} segundos',\r\n seekBackward: 'Retroceder {seconds} segundos',\r\n volumeUp: 'Subir volumen',\r\n volumeDown: 'Bajar volumen',\r\n loading: 'Cargando...',\r\n loadingChapters: 'Cargando cap\u00EDtulos...',\r\n error: 'Error al cargar',\r\n buffering: 'Almacenando en b\u00FAfer...',\r\n signLanguageVideo: 'Video en Lengua de Se\u00F1as',\r\n noChapters: 'No hay cap\u00EDtulos disponibles',\r\n noCaptions: 'No hay subt\u00EDtulos disponibles',\r\n auto: 'Autom\u00E1tico',\r\n autoQuality: 'Autom\u00E1tico (selecci\u00F3n de calidad no disponible)',\r\n noQuality: 'Selecci\u00F3n de calidad no disponible',\r\n signLanguageDragResize: 'Video en Lengua de Se\u00F1as - Presione D para arrastrar con el teclado, R para cambiar el tama\u00F1o',\r\n signLanguageDragActive: 'Video en Lengua de Se\u00F1as - Modo de arrastre activo. Use las teclas de flecha para mover, Escape para salir.',\r\n signLanguageResizeActive: 'Video en Lengua de Se\u00F1as - Modo de cambio de tama\u00F1o activo. Use las teclas de flecha izquierda/derecha para cambiar el tama\u00F1o, Escape para salir.',\r\n resizeHandle: 'Cambiar tama\u00F1o esquina {direction}'\r\n },\r\n captions: {\r\n off: 'Desactivado',\r\n select: 'Seleccionar subt\u00EDtulos',\r\n fontSize: 'Tama\u00F1o de fuente',\r\n fontFamily: 'Familia de fuente',\r\n color: 'Color de texto',\r\n backgroundColor: 'Color de fondo',\r\n opacity: 'Opacidad'\r\n },\r\n fontSizes: {\r\n small: 'Peque\u00F1o',\r\n normal: 'Normal',\r\n large: 'Grande',\r\n xlarge: 'Muy grande'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Color de texto',\r\n background: 'Fondo',\r\n font: 'Fuente',\r\n fontSize: 'Tama\u00F1o de fuente',\r\n opacity: 'Opacidad'\r\n },\r\n audioDescription: {\r\n enable: 'Activar audiodescripci\u00F3n',\r\n disable: 'Desactivar audiodescripci\u00F3n'\r\n },\r\n signLanguage: {\r\n show: 'Mostrar video en lengua de se\u00F1as',\r\n hide: 'Ocultar video en lengua de se\u00F1as'\r\n },\r\n transcript: {\r\n title: 'Transcripci\u00F3n',\r\n close: 'Cerrar transcripci\u00F3n',\r\n loading: 'Cargando transcripci\u00F3n...',\r\n noTranscript: 'No hay transcripci\u00F3n disponible para este video.',\r\n settings: 'Configuraci\u00F3n de transcripci\u00F3n. Presione Enter para abrir el men\u00FA o D para activar el modo de arrastre',\r\n keyboardDragMode: 'Alternar modo de arrastre con teclado usando teclas de flecha. Atajo: tecla D',\r\n keyboardDragActive: '\u2328\uFE0F Modo de Arrastre con Teclado Activo (Teclas de flecha para mover, May\u00FAs+Flechas para pasos grandes, D o ESC para salir)',\r\n resizeWindow: 'Cambiar tama\u00F1o de ventana',\r\n styleTranscript: 'Abrir configuraci\u00F3n de estilo de transcripci\u00F3n',\r\n closeMenu: 'Cerrar men\u00FA',\r\n styleTitle: 'Estilo de Transcripci\u00F3n',\r\n autoscroll: 'Desplazamiento autom\u00E1tico'\r\n },\r\n settings: {\r\n title: 'Configuraci\u00F3n',\r\n quality: 'Calidad',\r\n speed: 'Velocidad',\r\n captions: 'Subt\u00EDtulos',\r\n language: 'Idioma',\r\n reset: 'Restablecer',\r\n close: 'Cerrar'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Visualizaci\u00F3n de tiempo',\r\n durationPrefix: 'Duraci\u00F3n: ',\r\n hour: '{count} hora',\r\n hours: '{count} horas',\r\n minute: '{count} minuto',\r\n minutes: '{count} minutos',\r\n second: '{count} segundo',\r\n seconds: '{count} segundos'\r\n }\r\n },\r\n\r\n fr: {\r\n player: {\r\n label: 'Lecteur vid\u00E9o',\r\n play: 'Lecture',\r\n pause: 'Pause',\r\n stop: 'Arr\u00EAt',\r\n restart: 'Red\u00E9marrer du d\u00E9but',\r\n rewind: 'Reculer',\r\n forward: 'Avancer',\r\n rewindSeconds: 'Reculer de {seconds} secondes',\r\n forwardSeconds: 'Avancer de {seconds} secondes',\r\n previous: 'Piste pr\u00E9c\u00E9dente',\r\n next: 'Piste suivante',\r\n volume: 'Volume',\r\n mute: 'Muet',\r\n unmute: 'Activer le son',\r\n fullscreen: 'Plein \u00E9cran',\r\n exitFullscreen: 'Quitter le plein \u00E9cran',\r\n captions: 'Sous-titres',\r\n chapters: 'Chapitres',\r\n quality: 'Qualit\u00E9',\r\n captionStyling: 'Style des sous-titres',\r\n transcript: 'Activer/d\u00E9sactiver la transcription',\r\n audioDescription: 'Audiodescription',\r\n signLanguage: 'Vid\u00E9o en langue des signes',\r\n settings: 'Param\u00E8tres',\r\n speed: 'Vitesse de lecture',\r\n pip: 'Image dans l\\'image',\r\n currentTime: 'Temps actuel',\r\n duration: 'Dur\u00E9e',\r\n progress: 'Progression',\r\n seekForward: 'Avancer de {seconds} secondes',\r\n seekBackward: 'Reculer de {seconds} secondes',\r\n volumeUp: 'Augmenter le volume',\r\n volumeDown: 'Diminuer le volume',\r\n loading: 'Chargement...',\r\n loadingChapters: 'Chargement des chapitres...',\r\n error: 'Erreur de chargement',\r\n buffering: 'Mise en m\u00E9moire tampon...',\r\n signLanguageVideo: 'Vid\u00E9o en Langue des Signes',\r\n noChapters: 'Aucun chapitre disponible',\r\n noCaptions: 'Aucun sous-titre disponible',\r\n auto: 'Automatique',\r\n autoQuality: 'Automatique (s\u00E9lection de qualit\u00E9 non disponible)',\r\n noQuality: 'S\u00E9lection de qualit\u00E9 non disponible',\r\n signLanguageDragResize: 'Vid\u00E9o en Langue des Signes - Appuyez sur D pour d\u00E9placer avec le clavier, R pour redimensionner',\r\n signLanguageDragActive: 'Vid\u00E9o en Langue des Signes - Mode glissement actif. Utilisez les touches fl\u00E9ch\u00E9es pour d\u00E9placer, \u00C9chap pour quitter.',\r\n signLanguageResizeActive: 'Vid\u00E9o en Langue des Signes - Mode redimensionnement actif. Utilisez les touches fl\u00E9ch\u00E9es gauche/droite pour redimensionner, \u00C9chap pour quitter.',\r\n resizeHandle: 'Redimensionner coin {direction}'\r\n },\r\n captions: {\r\n off: 'D\u00E9sactiv\u00E9',\r\n select: 'S\u00E9lectionner les sous-titres',\r\n fontSize: 'Taille de police',\r\n fontFamily: 'Police',\r\n color: 'Couleur du texte',\r\n backgroundColor: 'Couleur de fond',\r\n opacity: 'Opacit\u00E9'\r\n },\r\n fontSizes: {\r\n small: 'Petit',\r\n normal: 'Normal',\r\n large: 'Grand',\r\n xlarge: 'Tr\u00E8s grand'\r\n },\r\n fontFamilies: {\r\n sansSerif: 'Sans-serif',\r\n serif: 'Serif',\r\n monospace: 'Monospace'\r\n },\r\n styleLabels: {\r\n textColor: 'Couleur du texte',\r\n background: 'Arri\u00E8re-plan',\r\n font: 'Police',\r\n fontSize: 'Taille de police',\r\n opacity: 'Opacit\u00E9'\r\n },\r\n audioDescription: {\r\n enable: 'Activer l\\'audiodescription',\r\n disable: 'D\u00E9sactiver l\\'audiodescription'\r\n },\r\n signLanguage: {\r\n show: 'Afficher la vid\u00E9o en langue des signes',\r\n hide: 'Masquer la vid\u00E9o en langue des signes'\r\n },\r\n transcript: {\r\n title: 'Transcription',\r\n close: 'Fermer la transcription',\r\n loading: 'Chargement de la transcription...',\r\n noTranscript: 'Aucune transcription disponible pour cette vid\u00E9o.',\r\n settings: 'Param\u00E8tres de transcription. Appuyez sur Entr\u00E9e pour ouvrir le menu ou D pour activer le mode glissement',\r\n keyboardDragMode: 'Basculer le mode glissement avec les touches fl\u00E9ch\u00E9es. Raccourci: touche D',\r\n keyboardDragActive: '\u2328\uFE0F Mode Glissement Clavier Actif (Touches fl\u00E9ch\u00E9es pour d\u00E9placer, Maj+Fl\u00E9ch\u00E9es pour grands pas, D ou \u00C9chap pour quitter)',\r\n resizeWindow: 'Redimensionner la fen\u00EAtre',\r\n styleTranscript: 'Ouvrir les param\u00E8tres de style de transcription',\r\n closeMenu: 'Fermer le menu',\r\n styleTitle: 'Style de Transcription',\r\n autoscroll: 'D\u00E9filement automatique'\r\n },\r\n settings: {\r\n title: 'Param\u00E8tres',\r\n quality: 'Qualit\u00E9',\r\n speed: 'Vitesse',\r\n captions: 'Sous-titres',\r\n language: 'Langue',\r\n reset: 'R\u00E9initialiser',\r\n close: 'Fermer'\r\n },\r\n speeds: {\r\n normal: 'Normal'\r\n },\r\n time: {\r\n display: 'Affichage du temps',\r\n durationPrefix: 'Dur\u00E9e : ',\r\n hour: '{count} heure',\r\n hours: '{count} heures',\r\n minute: '{count} minute',\r\n minutes: '{count} minutes',\r\n second: '{count} seconde',\r\n seconds: '{count} secondes'\r\n }\r\n },\r\n\r\n ja: {\r\n player: {\r\n label: '\u30D3\u30C7\u30AA\u30D7\u30EC\u30FC\u30E4\u30FC',\r\n play: '\u518D\u751F',\r\n pause: '\u4E00\u6642\u505C\u6B62',\r\n stop: '\u505C\u6B62',\r\n restart: '\u6700\u521D\u304B\u3089\u518D\u751F',\r\n rewind: '\u5DFB\u304D\u623B\u3057',\r\n forward: '\u65E9\u9001\u308A',\r\n rewindSeconds: '{seconds}\u79D2\u623B\u3059',\r\n forwardSeconds: '{seconds}\u79D2\u9032\u3081\u308B',\r\n previous: '\u524D\u306E\u30C8\u30E9\u30C3\u30AF',\r\n next: '\u6B21\u306E\u30C8\u30E9\u30C3\u30AF',\r\n volume: '\u97F3\u91CF',\r\n mute: '\u30DF\u30E5\u30FC\u30C8',\r\n unmute: '\u30DF\u30E5\u30FC\u30C8\u89E3\u9664',\r\n fullscreen: '\u5168\u753B\u9762\u8868\u793A',\r\n exitFullscreen: '\u5168\u753B\u9762\u8868\u793A\u3092\u7D42\u4E86',\r\n captions: '\u5B57\u5E55',\r\n chapters: '\u30C1\u30E3\u30D7\u30BF\u30FC',\r\n quality: '\u753B\u8CEA',\r\n captionStyling: '\u5B57\u5E55\u30B9\u30BF\u30A4\u30EB',\r\n transcript: '\u6587\u5B57\u8D77\u3053\u3057\u5207\u308A\u66FF\u3048',\r\n audioDescription: '\u97F3\u58F0\u89E3\u8AAC',\r\n signLanguage: '\u624B\u8A71\u52D5\u753B',\r\n settings: '\u8A2D\u5B9A',\r\n speed: '\u518D\u751F\u901F\u5EA6',\r\n pip: '\u30D4\u30AF\u30C1\u30E3\u30FC\u30A4\u30F3\u30D4\u30AF\u30C1\u30E3\u30FC',\r\n currentTime: '\u73FE\u5728\u306E\u6642\u9593',\r\n duration: '\u518D\u751F\u6642\u9593',\r\n progress: '\u9032\u884C\u72B6\u6CC1',\r\n seekForward: '{seconds}\u79D2\u9032\u3081\u308B',\r\n seekBackward: '{seconds}\u79D2\u623B\u3059',\r\n volumeUp: '\u97F3\u91CF\u3092\u4E0A\u3052\u308B',\r\n volumeDown: '\u97F3\u91CF\u3092\u4E0B\u3052\u308B',\r\n loading: '\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n loadingChapters: '\u30C1\u30E3\u30D7\u30BF\u30FC\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n error: '\u8AAD\u307F\u8FBC\u307F\u30A8\u30E9\u30FC',\r\n buffering: '\u30D0\u30C3\u30D5\u30A1\u30EA\u30F3\u30B0\u4E2D...',\r\n signLanguageVideo: '\u624B\u8A71\u52D5\u753B',\r\n noChapters: '\u30C1\u30E3\u30D7\u30BF\u30FC\u304C\u3042\u308A\u307E\u305B\u3093',\r\n noCaptions: '\u5B57\u5E55\u304C\u3042\u308A\u307E\u305B\u3093',\r\n auto: '\u81EA\u52D5',\r\n autoQuality: '\u81EA\u52D5\uFF08\u753B\u8CEA\u9078\u629E\u4E0D\u53EF\uFF09',\r\n noQuality: '\u753B\u8CEA\u9078\u629E\u4E0D\u53EF',\r\n signLanguageDragResize: '\u624B\u8A71\u52D5\u753B - \u30AD\u30FC\u30DC\u30FC\u30C9\u3067\u30C9\u30E9\u30C3\u30B0\u3059\u308B\u306B\u306FD\u30AD\u30FC\u3092\u3001\u30B5\u30A4\u30BA\u5909\u66F4\u3059\u308B\u306B\u306FR\u30AD\u30FC\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044',\r\n signLanguageDragActive: '\u624B\u8A71\u52D5\u753B - \u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u304C\u6709\u52B9\u3067\u3059\u3002\u77E2\u5370\u30AD\u30FC\u3067\u79FB\u52D5\u3001Escape\u3067\u7D42\u4E86\u3057\u307E\u3059\u3002',\r\n signLanguageResizeActive: '\u624B\u8A71\u52D5\u753B - \u30B5\u30A4\u30BA\u5909\u66F4\u30E2\u30FC\u30C9\u304C\u6709\u52B9\u3067\u3059\u3002\u5DE6\u53F3\u306E\u77E2\u5370\u30AD\u30FC\u3067\u30B5\u30A4\u30BA\u5909\u66F4\u3001Escape\u3067\u7D42\u4E86\u3057\u307E\u3059\u3002',\r\n resizeHandle: '{direction}\u30B3\u30FC\u30CA\u30FC\u306E\u30B5\u30A4\u30BA\u5909\u66F4'\r\n },\r\n captions: {\r\n off: '\u30AA\u30D5',\r\n select: '\u5B57\u5E55\u3092\u9078\u629E',\r\n fontSize: '\u30D5\u30A9\u30F3\u30C8\u30B5\u30A4\u30BA',\r\n fontFamily: '\u30D5\u30A9\u30F3\u30C8',\r\n color: '\u30C6\u30AD\u30B9\u30C8\u306E\u8272',\r\n backgroundColor: '\u80CC\u666F\u8272',\r\n opacity: '\u4E0D\u900F\u660E\u5EA6'\r\n },\r\n fontSizes: {\r\n small: '\u5C0F',\r\n normal: '\u6A19\u6E96',\r\n large: '\u5927',\r\n xlarge: '\u7279\u5927'\r\n },\r\n fontFamilies: {\r\n sansSerif: '\u30B5\u30F3\u30BB\u30EA\u30D5',\r\n serif: '\u30BB\u30EA\u30D5',\r\n monospace: '\u7B49\u5E45'\r\n },\r\n styleLabels: {\r\n textColor: '\u30C6\u30AD\u30B9\u30C8\u306E\u8272',\r\n background: '\u80CC\u666F',\r\n font: '\u30D5\u30A9\u30F3\u30C8',\r\n fontSize: '\u30D5\u30A9\u30F3\u30C8\u30B5\u30A4\u30BA',\r\n opacity: '\u4E0D\u900F\u660E\u5EA6'\r\n },\r\n audioDescription: {\r\n enable: '\u97F3\u58F0\u89E3\u8AAC\u3092\u6709\u52B9\u306B\u3059\u308B',\r\n disable: '\u97F3\u58F0\u89E3\u8AAC\u3092\u7121\u52B9\u306B\u3059\u308B'\r\n },\r\n signLanguage: {\r\n show: '\u624B\u8A71\u52D5\u753B\u3092\u8868\u793A',\r\n hide: '\u624B\u8A71\u52D5\u753B\u3092\u975E\u8868\u793A'\r\n },\r\n transcript: {\r\n title: '\u6587\u5B57\u8D77\u3053\u3057',\r\n close: '\u6587\u5B57\u8D77\u3053\u3057\u3092\u9589\u3058\u308B',\r\n loading: '\u6587\u5B57\u8D77\u3053\u3057\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D...',\r\n noTranscript: '\u3053\u306E\u30D3\u30C7\u30AA\u306E\u6587\u5B57\u8D77\u3053\u3057\u306F\u3042\u308A\u307E\u305B\u3093\u3002',\r\n settings: '\u6587\u5B57\u8D77\u3053\u3057\u8A2D\u5B9A\u3002Enter\u30AD\u30FC\u3067\u30E1\u30CB\u30E5\u30FC\u3092\u958B\u304F\u3001\u307E\u305F\u306FD\u30AD\u30FC\u3067\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u3092\u6709\u52B9\u306B\u3059\u308B',\r\n keyboardDragMode: '\u77E2\u5370\u30AD\u30FC\u3067\u30AD\u30FC\u30DC\u30FC\u30C9\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u3092\u5207\u308A\u66FF\u3048\u3002\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\uFF1AD\u30AD\u30FC',\r\n keyboardDragActive: '\u2328\uFE0F \u30AD\u30FC\u30DC\u30FC\u30C9\u30C9\u30E9\u30C3\u30B0\u30E2\u30FC\u30C9\u6709\u52B9\uFF08\u77E2\u5370\u30AD\u30FC\u3067\u79FB\u52D5\u3001Shift+\u77E2\u5370\u30AD\u30FC\u3067\u5927\u304D\u304F\u79FB\u52D5\u3001D\u307E\u305F\u306FESC\u3067\u7D42\u4E86\uFF09',\r\n resizeWindow: '\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u30B5\u30A4\u30BA\u5909\u66F4',\r\n styleTranscript: '\u6587\u5B57\u8D77\u3053\u3057\u30B9\u30BF\u30A4\u30EB\u8A2D\u5B9A\u3092\u958B\u304F',\r\n closeMenu: '\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B',\r\n styleTitle: '\u6587\u5B57\u8D77\u3053\u3057\u30B9\u30BF\u30A4\u30EB',\r\n autoscroll: '\u81EA\u52D5\u30B9\u30AF\u30ED\u30FC\u30EB'\r\n },\r\n settings: {\r\n title: '\u8A2D\u5B9A',\r\n quality: '\u753B\u8CEA',\r\n speed: '\u901F\u5EA6',\r\n captions: '\u5B57\u5E55',\r\n language: '\u8A00\u8A9E',\r\n reset: '\u30EA\u30BB\u30C3\u30C8',\r\n close: '\u9589\u3058\u308B'\r\n },\r\n speeds: {\r\n normal: '\u901A\u5E38'\r\n },\r\n time: {\r\n display: '\u6642\u9593\u8868\u793A',\r\n durationPrefix: '\u518D\u751F\u6642\u9593: ',\r\n hour: '{count}\u6642\u9593',\r\n hours: '{count}\u6642\u9593',\r\n minute: '{count}\u5206',\r\n minutes: '{count}\u5206',\r\n second: '{count}\u79D2',\r\n seconds: '{count}\u79D2'\r\n }\r\n }\r\n};\r\n\r\n", "/**\r\n * Internationalization system\r\n */\r\n\r\nimport { translations } from './translations.js';\r\n\r\nclass I18n {\r\n constructor() {\r\n this.currentLanguage = 'en';\r\n this.translations = translations;\r\n }\r\n\r\n setLanguage(lang) {\r\n if (this.translations[lang]) {\r\n this.currentLanguage = lang;\r\n } else {\r\n console.warn(`Language \"${lang}\" not found, falling back to English`);\r\n this.currentLanguage = 'en';\r\n }\r\n }\r\n\r\n getLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n t(key, replacements = {}) {\r\n const keys = key.split('.');\r\n let value = this.translations[this.currentLanguage];\r\n \r\n for (const k of keys) {\r\n if (value && typeof value === 'object' && k in value) {\r\n value = value[k];\r\n } else {\r\n // Fallback to English\r\n value = this.translations.en;\r\n for (const fallbackKey of keys) {\r\n if (value && typeof value === 'object' && fallbackKey in value) {\r\n value = value[fallbackKey];\r\n } else {\r\n return key; // Return key if not found\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n \r\n // Replace placeholders\r\n if (typeof value === 'string') {\r\n Object.entries(replacements).forEach(([placeholder, replacement]) => {\r\n value = value.replace(new RegExp(`{${placeholder}}`, 'g'), replacement);\r\n });\r\n }\r\n \r\n return value;\r\n }\r\n\r\n addTranslation(lang, translations) {\r\n if (!this.translations[lang]) {\r\n this.translations[lang] = {};\r\n }\r\n Object.assign(this.translations[lang], translations);\r\n }\r\n}\r\n\r\nexport const i18n = new I18n();\r\n\r\n", "/**\r\n * Time formatting and conversion utilities\r\n */\r\n\r\nimport {i18n} from '../i18n/i18n.js';\r\n\r\nexport const TimeUtils = {\r\n /**\r\n * Format seconds to time string (HH:MM:SS or MM:SS)\r\n */\r\n formatTime(seconds, alwaysShowHours = false) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return alwaysShowHours ? '00:00:00' : '00:00';\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const pad = (num) => String(num).padStart(2, '0');\r\n \r\n if (hours > 0 || alwaysShowHours) {\r\n return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`;\r\n }\r\n \r\n return `${pad(minutes)}:${pad(secs)}`;\r\n },\r\n\r\n /**\r\n * Parse time string to seconds\r\n */\r\n parseTime(timeString) {\r\n const parts = timeString.split(':').map(p => parseInt(p, 10));\r\n \r\n if (parts.length === 3) {\r\n // HH:MM:SS\r\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\r\n } else if (parts.length === 2) {\r\n // MM:SS\r\n return parts[0] * 60 + parts[1];\r\n } else if (parts.length === 1) {\r\n // SS\r\n return parts[0];\r\n }\r\n \r\n return 0;\r\n },\r\n\r\n /**\r\n * Format seconds to readable duration\r\n */\r\n formatDuration(seconds) {\r\n if (!isFinite(seconds) || seconds < 0) {\r\n return i18n.t('time.seconds', { count: 0 });\r\n }\r\n \r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n const secs = Math.floor(seconds % 60);\r\n \r\n const parts = [];\r\n \r\n if (hours > 0) {\r\n const key = hours === 1 ? 'time.hour' : 'time.hours';\r\n parts.push(i18n.t(key, { count: hours }));\r\n }\r\n if (minutes > 0) {\r\n const key = minutes === 1 ? 'time.minute' : 'time.minutes';\r\n parts.push(i18n.t(key, { count: minutes }));\r\n }\r\n if (secs > 0 || parts.length === 0) {\r\n const key = secs === 1 ? 'time.second' : 'time.seconds';\r\n parts.push(i18n.t(key, { count: secs }));\r\n }\r\n \r\n return parts.join(', ');\r\n },\r\n\r\n /**\r\n * Format percentage\r\n */\r\n formatPercentage(value, total) {\r\n if (total === 0) return 0;\r\n return Math.round((value / total) * 100);\r\n }\r\n};\r\n\r\n", "/**\r\n * SVG Icon Library for VidPly\r\n * Optimized with common viewBox and fill attributes\r\n */\r\n\r\n// SVG paths only (viewBox and fill added by wrapper)\r\nconst iconPaths = {\r\n play: `<path d=\"M8 5v14l11-7z\"/>`,\r\n\r\n pause: `<path d=\"M6 4h4v16H6V4zm8 0h4v16h-4V4z\"/>`,\r\n\r\n stop: `<rect x=\"6\" y=\"6\" width=\"12\" height=\"12\"/>`,\r\n\r\n rewind: `<path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\"/>`,\r\n\r\n forward: `<path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\"/>`,\r\n\r\n skipPrevious: `<path d=\"M6 6h2v12H6V6zm3 6l8.5 6V6L9 12z\"/>`,\r\n\r\n skipNext: `<path d=\"M16 6h2v12h-2V6zM6 6l8.5 6L6 18V6z\"/>`,\r\n\r\n restart: `<path d=\"M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"/>`,\r\n\r\n volumeHigh: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/>`,\r\n\r\n volumeMedium: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"/>`,\r\n\r\n volumeLow: `<path d=\"M7 9v6h4l5 5V4l-5 5H7z\"/>`,\r\n\r\n volumeMuted: `<path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/>`,\r\n\r\n fullscreen: `<path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/>`,\r\n\r\n fullscreenExit: `<path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/>`,\r\n\r\n settings: `<path d=\"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z\"/>`,\r\n\r\n captions: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/>`,\r\n\r\n captionsOff: `<path d=\"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z\"/><path d=\"M0 0h24v24H0z\" fill=\"none\"/>`,\r\n\r\n pip: `<path d=\"M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z\"/>`,\r\n\r\n speed: `<path d=\"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44z\"/><path d=\"M10.59 15.41a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z\"/>`,\r\n\r\n close: `<path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>`,\r\n\r\n check: `<path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>`,\r\n\r\n arrowUp: `<path d=\"M7 14l5-5 5 5z\"/>`,\r\n\r\n arrowDown: `<path d=\"M7 10l5 5 5-5z\"/>`,\r\n\r\n arrowLeft: `<path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/>`,\r\n\r\n arrowRight: `<path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/>`,\r\n\r\n loading: `<path d=\"M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z\"/>`,\r\n\r\n error: `<path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>`,\r\n\r\n download: `<path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"/>`,\r\n\r\n link: `<path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"/>`,\r\n\r\n playlist: `<path d=\"M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z\"/>`,\r\n\r\n language: `<path d=\"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z\"/>`,\r\n\r\n hd: `<path d=\"M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z\"/>`,\r\n\r\n transcript: `<path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/>`,\r\n\r\n audioDescription: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"#ffffff\" stroke=\"#ffffff\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"#1a1a1a\">AD</text>`,\r\n \r\n audioDescriptionOn: `<rect x=\"2\" y=\"5\" width=\"20\" height=\"14\" rx=\"2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"/><text x=\"12\" y=\"16\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"currentColor\">AD</text>`,\r\n\r\n signLanguage: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n signLanguageOn: `<g transform=\"scale(1.5)\"><path d=\"M16 11.3c-.1-.9-4.8 1.3-5.4 1.1-2.6-1 5.8-1.3 5.1-2.9s-5.1 1.5-6 1.4C6.5 9.4 16.5 9.1 13.5 8c-1.9-.6-8.8 2.9-6.8.4.7-.6.7-1.9-.7-1.7-9.7 7.2-.7 12.2 8.8 7 0-1.3-3.5.4-4.1.4-2.6 0 5.6-2 5.4-3ZM3.9 7.8c3.2-4.2 3.7 1.2 6 .1s.2-.2.2-.3c.7-2.7 2.5-7.5-1.5-1.3-1.6 0 1.1-4 1-4.6C8.9-1 7.3 4.4 7.2 4.9c-1.6.7-.9-1.4-.7-1.5 3-6-.6-3.1-.9.4-2.5 1.8 0-2.8 0-3.5C2.8-.9 4 9.4 1.1 4.9S.1 4.6 0 5c-.4 2.7 2.6 7.2 3.9 2.8Z\"/></g>`,\r\n\r\n speaker: `<path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z\"/>`,\r\n\r\n music: `<path d=\"M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7zm-1.5 16c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\"/>`,\r\n\r\n moreVertical: `<path d=\"M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/>`,\r\n\r\n moreHorizontal: `<path d=\"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/>`,\r\n \r\n move: `<path d=\"M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z\"/>`,\r\n \r\n resize: `<path d=\"M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v2.5L7 11l3-3.5V10h4V7.5l3 3.5-3 3.5z\"/>`\r\n};\r\n\r\n// Optimized wrapper that adds common SVG attributes\r\nconst svgWrapper = (paths) => `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\">${paths}</svg>`;\r\n\r\n// Export Icons object with SVG wrappers\r\nexport const Icons = Object.fromEntries(\r\n Object.entries(iconPaths).map(([key, value]) => [key, svgWrapper(value)])\r\n);\r\n\r\nexport function getIcon(name) {\r\n return Icons[name] || Icons.play;\r\n}\r\n\r\nexport function createIconElement(name, className = '') {\r\n const wrapper = document.createElement('span');\r\n wrapper.className = `vidply-icon ${className}`.trim();\r\n wrapper.innerHTML = getIcon(name);\r\n wrapper.setAttribute('aria-hidden', 'true');\r\n return wrapper;\r\n}\r\n\r\n/**\r\n * Create the large centered play button overlay (complete SVG)\r\n * @returns {SVGElement} Complete SVG element with circle background and play icon\r\n */\r\nexport function createPlayOverlay() {\r\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\r\n svg.setAttribute('class', 'vidply-play-overlay');\r\n svg.setAttribute('viewBox', '0 0 80 80');\r\n svg.setAttribute('width', '80');\r\n svg.setAttribute('height', '80');\r\n svg.setAttribute('aria-hidden', 'true');\r\n svg.setAttribute('role', 'presentation');\r\n svg.style.cursor = 'pointer';\r\n\r\n // Create filter for drop shadow\r\n const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\r\n const filterId = `vidply-play-shadow-${Math.random().toString(36).substr(2, 9)}`;\r\n const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');\r\n filter.setAttribute('id', filterId);\r\n filter.setAttribute('x', '-50%');\r\n filter.setAttribute('y', '-50%');\r\n filter.setAttribute('width', '200%');\r\n filter.setAttribute('height', '200%');\r\n\r\n const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');\r\n feGaussianBlur.setAttribute('in', 'SourceAlpha');\r\n feGaussianBlur.setAttribute('stdDeviation', '3');\r\n\r\n const feOffset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');\r\n feOffset.setAttribute('dx', '0');\r\n feOffset.setAttribute('dy', '2');\r\n feOffset.setAttribute('result', 'offsetblur');\r\n\r\n const feComponentTransfer = document.createElementNS('http://www.w3.org/2000/svg', 'feComponentTransfer');\r\n const feFuncA = document.createElementNS('http://www.w3.org/2000/svg', 'feFuncA');\r\n feFuncA.setAttribute('type', 'linear');\r\n feFuncA.setAttribute('slope', '0.3');\r\n feComponentTransfer.appendChild(feFuncA);\r\n\r\n const feMerge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');\r\n const feMergeNode1 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n const feMergeNode2 = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');\r\n feMergeNode2.setAttribute('in', 'SourceGraphic');\r\n feMerge.appendChild(feMergeNode1);\r\n feMerge.appendChild(feMergeNode2);\r\n\r\n filter.appendChild(feGaussianBlur);\r\n filter.appendChild(feOffset);\r\n filter.appendChild(feComponentTransfer);\r\n filter.appendChild(feMerge);\r\n defs.appendChild(filter);\r\n svg.appendChild(defs);\r\n\r\n // White circle background\r\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n circle.setAttribute('cx', '40');\r\n circle.setAttribute('cy', '40');\r\n circle.setAttribute('r', '40');\r\n circle.setAttribute('fill', 'rgba(255, 255, 255, 0.95)');\r\n circle.setAttribute('filter', `url(#${filterId})`);\r\n circle.setAttribute('class', 'vidply-play-overlay-bg');\r\n svg.appendChild(circle);\r\n\r\n // Play icon triangle (centered with optical adjustment)\r\n const playTriangle = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');\r\n playTriangle.setAttribute('points', '32,28 32,52 54,40');\r\n playTriangle.setAttribute('fill', '#0a406e');\r\n playTriangle.setAttribute('class', 'vidply-play-overlay-icon');\r\n svg.appendChild(playTriangle);\r\n\r\n return svg;\r\n}\r\n\r\n", "/**\r\n * Control Bar Component\r\n */\r\n\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {TimeUtils} from '../utils/TimeUtils.js';\r\nimport {createIconElement} from '../icons/Icons.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\n\r\nexport class ControlBar {\r\n constructor(player) {\r\n this.player = player;\r\n this.element = null;\r\n this.controls = {};\r\n this.hideTimeout = null;\r\n this.isDraggingProgress = false;\r\n this.isDraggingVolume = false;\r\n\r\n this.init();\r\n }\r\n\r\n init() {\r\n this.createElement();\r\n this.createControls();\r\n this.attachEvents();\r\n this.setupAutoHide();\r\n }\r\n\r\n // Helper method to check if we're on a mobile device\r\n isMobile() {\r\n return window.innerWidth < 640;\r\n }\r\n\r\n // Smart menu positioning to avoid overflow\r\n positionMenu(menu, button) {\r\n const isMobile = this.isMobile();\r\n \r\n if (isMobile) {\r\n // Use bottom sheet on mobile - already styled via CSS\r\n return;\r\n }\r\n\r\n // Desktop: Smart positioning\r\n setTimeout(() => {\r\n const buttonRect = button.getBoundingClientRect();\r\n const menuRect = menu.getBoundingClientRect();\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n \r\n const spaceAbove = buttonRect.top;\r\n const spaceBelow = viewportHeight - buttonRect.bottom;\r\n \r\n // Prefer above, but switch to below if not enough space\r\n if (spaceAbove < menuRect.height + 20 && spaceBelow > spaceAbove) {\r\n menu.style.bottom = 'auto';\r\n menu.style.top = 'calc(100% + 8px)';\r\n menu.classList.add('vidply-menu-below');\r\n }\r\n \r\n // Check horizontal overflow\r\n const menuLeft = buttonRect.left + buttonRect.width / 2 - menuRect.width / 2;\r\n if (menuLeft < 10) {\r\n // Too far left, align to left edge\r\n menu.style.right = 'auto';\r\n menu.style.left = '0';\r\n menu.style.transform = 'translateX(0)';\r\n } else if (menuLeft + menuRect.width > viewportWidth - 10) {\r\n // Too far right, align to right edge\r\n menu.style.left = 'auto';\r\n menu.style.right = '0';\r\n menu.style.transform = 'translateX(0)';\r\n }\r\n }, 0);\r\n }\r\n\r\n\r\n // Helper method to attach close-on-outside-click behavior to menus\r\n attachMenuCloseHandler(menu, button, preventCloseOnInteraction = false) {\r\n // Position menu smartly\r\n this.positionMenu(menu, button);\r\n \r\n setTimeout(() => {\r\n const closeMenu = (e) => {\r\n // If this menu has form controls, don't close when clicking inside\r\n if (preventCloseOnInteraction && menu.contains(e.target)) {\r\n return;\r\n }\r\n\r\n // Check if click is outside menu and button\r\n if (!menu.contains(e.target) && !button.contains(e.target)) {\r\n menu.remove();\r\n document.removeEventListener('click', closeMenu);\r\n document.removeEventListener('keydown', handleEscape);\r\n }\r\n };\r\n\r\n const handleEscape = (e) => {\r\n if (e.key === 'Escape') {\r\n menu.remove();\r\n document.removeEventListener('click', closeMenu);\r\n document.removeEventListener('keydown', handleEscape);\r\n // Return focus to button\r\n button.focus();\r\n }\r\n };\r\n\r\n document.addEventListener('click', closeMenu);\r\n document.addEventListener('keydown', handleEscape);\r\n }, 100);\r\n }\r\n\r\n // Helper method to add keyboard navigation to menus (arrow keys)\r\n attachMenuKeyboardNavigation(menu) {\r\n const menuItems = Array.from(menu.querySelectorAll(`.${this.player.options.classPrefix}-menu-item`));\r\n \r\n if (menuItems.length === 0) return;\r\n\r\n const handleKeyDown = (e) => {\r\n const currentIndex = menuItems.indexOf(document.activeElement);\r\n \r\n switch (e.key) {\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n const nextIndex = (currentIndex + 1) % menuItems.length;\r\n menuItems[nextIndex].focus();\r\n break;\r\n \r\n case 'ArrowUp':\r\n e.preventDefault();\r\n const prevIndex = (currentIndex - 1 + menuItems.length) % menuItems.length;\r\n menuItems[prevIndex].focus();\r\n break;\r\n \r\n case 'Home':\r\n e.preventDefault();\r\n menuItems[0].focus();\r\n break;\r\n \r\n case 'End':\r\n e.preventDefault();\r\n menuItems[menuItems.length - 1].focus();\r\n break;\r\n \r\n case 'Enter':\r\n case ' ':\r\n e.preventDefault();\r\n if (document.activeElement && menuItems.includes(document.activeElement)) {\r\n document.activeElement.click();\r\n }\r\n break;\r\n }\r\n };\r\n\r\n menu.addEventListener('keydown', handleKeyDown);\r\n }\r\n\r\n createElement() {\r\n this.element = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls`,\r\n attributes: {\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.label') + ' controls'\r\n }\r\n });\r\n }\r\n\r\n createControls() {\r\n // Progress bar container\r\n if (this.player.options.progressBar) {\r\n this.createProgressBar();\r\n }\r\n\r\n // Button container\r\n const buttonContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-buttons`\r\n });\r\n\r\n // Left buttons\r\n const leftButtons = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-left`\r\n });\r\n\r\n // Previous track button (if playlist)\r\n if (this.player.playlistManager) {\r\n leftButtons.appendChild(this.createPreviousButton());\r\n }\r\n\r\n // Play/Pause button\r\n if (this.player.options.playPauseButton) {\r\n leftButtons.appendChild(this.createPlayPauseButton());\r\n }\r\n\r\n // Restart button (right beside play button)\r\n leftButtons.appendChild(this.createRestartButton());\r\n\r\n // Next track button (if playlist)\r\n if (this.player.playlistManager) {\r\n leftButtons.appendChild(this.createNextButton());\r\n }\r\n\r\n // Rewind button (not shown in playlist mode)\r\n if (!this.player.playlistManager) {\r\n leftButtons.appendChild(this.createRewindButton());\r\n }\r\n\r\n // Forward button (not shown in playlist mode)\r\n if (!this.player.playlistManager) {\r\n leftButtons.appendChild(this.createForwardButton());\r\n }\r\n\r\n // Volume control\r\n if (this.player.options.volumeControl) {\r\n leftButtons.appendChild(this.createVolumeControl());\r\n }\r\n\r\n // Time display\r\n if (this.player.options.currentTime || this.player.options.duration) {\r\n leftButtons.appendChild(this.createTimeDisplay());\r\n }\r\n\r\n // Right buttons\r\n this.rightButtons = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-controls-right`\r\n });\r\n\r\n // Check for available features\r\n const hasChapters = this.hasChapterTracks();\r\n const hasCaptions = this.hasCaptionTracks();\r\n const hasQualityLevels = this.hasQualityLevels();\r\n const hasAudioDescription = this.hasAudioDescription();\r\n\r\n // Chapters button - only show if chapters are available\r\n if (this.player.options.chaptersButton && hasChapters) {\r\n this.rightButtons.appendChild(this.createChaptersButton());\r\n }\r\n\r\n // Quality button - only show if quality levels are available\r\n if (this.player.options.qualityButton && hasQualityLevels) {\r\n this.rightButtons.appendChild(this.createQualityButton());\r\n }\r\n\r\n // Caption styling button (font, size, color) - only show if captions are available\r\n if (this.player.options.captionStyleButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createCaptionStyleButton());\r\n }\r\n\r\n // Speed button - always available\r\n if (this.player.options.speedButton) {\r\n this.rightButtons.appendChild(this.createSpeedButton());\r\n }\r\n\r\n // Captions language selector button - only show if captions are available\r\n if (this.player.options.captionsButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createCaptionsButton());\r\n }\r\n\r\n // Transcript button - only show if captions/subtitles are available\r\n if (this.player.options.transcriptButton && hasCaptions) {\r\n this.rightButtons.appendChild(this.createTranscriptButton());\r\n }\r\n\r\n // Audio Description button - only show if audio description source is available\r\n if (this.player.options.audioDescriptionButton && hasAudioDescription) {\r\n this.rightButtons.appendChild(this.createAudioDescriptionButton());\r\n }\r\n\r\n // Sign Language button - only show if sign language source is available\r\n const hasSignLanguage = this.hasSignLanguage();\r\n if (this.player.options.signLanguageButton && hasSignLanguage) {\r\n this.rightButtons.appendChild(this.createSignLanguageButton());\r\n }\r\n\r\n // PiP button\r\n if (this.player.options.pipButton && 'pictureInPictureEnabled' in document) {\r\n this.rightButtons.appendChild(this.createPipButton());\r\n }\r\n\r\n // Fullscreen button\r\n if (this.player.options.fullscreenButton) {\r\n this.rightButtons.appendChild(this.createFullscreenButton());\r\n }\r\n\r\n buttonContainer.appendChild(leftButtons);\r\n buttonContainer.appendChild(this.rightButtons);\r\n this.element.appendChild(buttonContainer);\r\n }\r\n\r\n // Helper methods to check for available features\r\n hasChapterTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n for (let i = 0; i < textTracks.length; i++) {\r\n if (textTracks[i].kind === 'chapters') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n hasCaptionTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n for (let i = 0; i < textTracks.length; i++) {\r\n if (textTracks[i].kind === 'captions' || textTracks[i].kind === 'subtitles') {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n hasQualityLevels() {\r\n // Check if renderer supports quality selection\r\n if (this.player.renderer && this.player.renderer.getQualities) {\r\n const qualities = this.player.renderer.getQualities();\r\n return qualities && qualities.length > 1;\r\n }\r\n return false;\r\n }\r\n\r\n hasAudioDescription() {\r\n // Check for audio-described video source OR description tracks\r\n if (this.player.audioDescriptionSrc && this.player.audioDescriptionSrc.length > 0) {\r\n return true;\r\n }\r\n \r\n // Check for description tracks\r\n const textTracks = Array.from(this.player.element.textTracks || []);\r\n return textTracks.some(track => track.kind === 'descriptions');\r\n }\r\n\r\n hasSignLanguage() {\r\n return this.player.signLanguageSrc && this.player.signLanguageSrc.length > 0;\r\n }\r\n\r\n createProgressBar() {\r\n const progressContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-container`,\r\n attributes: {\r\n 'role': 'slider',\r\n 'aria-label': i18n.t('player.progress'),\r\n 'aria-valuemin': '0',\r\n 'aria-valuemax': '100',\r\n 'aria-valuenow': '0',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Buffered progress\r\n this.controls.buffered = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-buffered`\r\n });\r\n\r\n // Played progress\r\n this.controls.played = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-played`\r\n });\r\n\r\n // Progress handle\r\n this.controls.progressHandle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-handle`\r\n });\r\n\r\n // Tooltip\r\n this.controls.progressTooltip = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-progress-tooltip`\r\n });\r\n\r\n progressContainer.appendChild(this.controls.buffered);\r\n progressContainer.appendChild(this.controls.played);\r\n this.controls.played.appendChild(this.controls.progressHandle);\r\n progressContainer.appendChild(this.controls.progressTooltip);\r\n\r\n this.controls.progress = progressContainer;\r\n this.element.appendChild(progressContainer);\r\n\r\n // Progress bar events\r\n this.setupProgressBarEvents();\r\n }\r\n\r\n setupProgressBarEvents() {\r\n const progress = this.controls.progress;\r\n\r\n const updateProgress = (clientX) => {\r\n const rect = progress.getBoundingClientRect();\r\n const percent = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n const time = percent * this.player.state.duration;\r\n return {percent, time};\r\n };\r\n\r\n // Mouse events\r\n progress.addEventListener('mousedown', (e) => {\r\n this.isDraggingProgress = true;\r\n const {time} = updateProgress(e.clientX);\r\n this.player.seek(time);\r\n });\r\n\r\n document.addEventListener('mousemove', (e) => {\r\n if (this.isDraggingProgress) {\r\n const {time} = updateProgress(e.clientX);\r\n this.player.seek(time);\r\n }\r\n });\r\n\r\n document.addEventListener('mouseup', () => {\r\n this.isDraggingProgress = false;\r\n });\r\n\r\n // Hover tooltip\r\n progress.addEventListener('mousemove', (e) => {\r\n if (!this.isDraggingProgress) {\r\n const {time} = updateProgress(e.clientX);\r\n this.controls.progressTooltip.textContent = TimeUtils.formatTime(time);\r\n this.controls.progressTooltip.style.left = `${e.clientX - progress.getBoundingClientRect().left}px`;\r\n this.controls.progressTooltip.style.display = 'block';\r\n }\r\n });\r\n\r\n progress.addEventListener('mouseleave', () => {\r\n this.controls.progressTooltip.style.display = 'none';\r\n });\r\n\r\n // Keyboard navigation\r\n progress.addEventListener('keydown', (e) => {\r\n if (e.key === 'ArrowLeft') {\r\n e.preventDefault();\r\n this.player.seekBackward(5);\r\n } else if (e.key === 'ArrowRight') {\r\n e.preventDefault();\r\n this.player.seekForward(5);\r\n }\r\n });\r\n\r\n // Touch events\r\n progress.addEventListener('touchstart', (e) => {\r\n this.isDraggingProgress = true;\r\n const touch = e.touches[0];\r\n const {time} = updateProgress(touch.clientX);\r\n this.player.seek(time);\r\n });\r\n\r\n progress.addEventListener('touchmove', (e) => {\r\n if (this.isDraggingProgress) {\r\n e.preventDefault();\r\n const touch = e.touches[0];\r\n const {time} = updateProgress(touch.clientX);\r\n this.player.seek(time);\r\n }\r\n });\r\n\r\n progress.addEventListener('touchend', () => {\r\n this.isDraggingProgress = false;\r\n });\r\n }\r\n\r\n createPlayPauseButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-play-pause`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.play')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('play'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggle();\r\n });\r\n\r\n this.controls.playPause = button;\r\n return button;\r\n }\r\n\r\n createRestartButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-restart`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.restart')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('restart'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seek(0);\r\n this.player.play();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createPreviousButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-previous`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.previous')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('skipPrevious'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.playlistManager) {\r\n this.player.playlistManager.previous();\r\n }\r\n });\r\n\r\n // Update button state\r\n const updateState = () => {\r\n if (this.player.playlistManager) {\r\n button.disabled = !this.player.playlistManager.hasPrevious() && !this.player.playlistManager.options.loop;\r\n }\r\n };\r\n this.player.on('playlisttrackchange', updateState);\r\n updateState();\r\n\r\n this.controls.previous = button;\r\n return button;\r\n }\r\n\r\n createNextButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-next`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.next')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('skipNext'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.playlistManager) {\r\n this.player.playlistManager.next();\r\n }\r\n });\r\n\r\n // Update button state\r\n const updateState = () => {\r\n if (this.player.playlistManager) {\r\n button.disabled = !this.player.playlistManager.hasNext() && !this.player.playlistManager.options.loop;\r\n }\r\n };\r\n this.player.on('playlisttrackchange', updateState);\r\n updateState();\r\n\r\n this.controls.next = button;\r\n return button;\r\n }\r\n\r\n createRewindButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-rewind`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.rewindSeconds', { seconds: 15 })\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('rewind'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seekBackward(15);\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createForwardButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-forward`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.forwardSeconds', { seconds: 15 })\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('forward'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.seekForward(15);\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createVolumeControl() {\r\n // Mute/Volume button\r\n const muteButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-mute`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.volume'),\r\n 'aria-haspopup': 'true'\r\n }\r\n });\r\n\r\n muteButton.appendChild(createIconElement('volumeHigh'));\r\n\r\n // Toggle mute on right click, show volume slider on left click\r\n muteButton.addEventListener('contextmenu', (e) => {\r\n e.preventDefault();\r\n this.player.toggleMute();\r\n });\r\n\r\n muteButton.addEventListener('click', () => {\r\n this.showVolumeSlider(muteButton);\r\n });\r\n\r\n this.controls.mute = muteButton;\r\n\r\n return muteButton;\r\n }\r\n\r\n showVolumeSlider(button) {\r\n // Remove existing slider if any\r\n const existingSlider = document.querySelector(`.${this.player.options.classPrefix}-volume-menu`);\r\n if (existingSlider) {\r\n existingSlider.remove();\r\n return;\r\n }\r\n\r\n // Volume menu container\r\n const volumeMenu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-menu ${this.player.options.classPrefix}-menu`\r\n });\r\n\r\n const volumeSlider = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-slider`,\r\n attributes: {\r\n 'role': 'slider',\r\n 'aria-label': i18n.t('player.volume'),\r\n 'aria-valuemin': '0',\r\n 'aria-valuemax': '100',\r\n 'aria-valuenow': String(Math.round(this.player.state.volume * 100)),\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n const volumeTrack = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-track`\r\n });\r\n\r\n const volumeFill = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-fill`\r\n });\r\n\r\n const volumeHandle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-volume-handle`\r\n });\r\n\r\n volumeTrack.appendChild(volumeFill);\r\n volumeFill.appendChild(volumeHandle);\r\n volumeSlider.appendChild(volumeTrack);\r\n volumeMenu.appendChild(volumeSlider);\r\n\r\n // Volume slider events\r\n const updateVolume = (clientY) => {\r\n const rect = volumeTrack.getBoundingClientRect();\r\n const percent = Math.max(0, Math.min(1, 1 - ((clientY - rect.top) / rect.height)));\r\n this.player.setVolume(percent);\r\n };\r\n\r\n volumeSlider.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n this.isDraggingVolume = true;\r\n updateVolume(e.clientY);\r\n });\r\n\r\n document.addEventListener('mousemove', (e) => {\r\n if (this.isDraggingVolume) {\r\n updateVolume(e.clientY);\r\n }\r\n });\r\n\r\n document.addEventListener('mouseup', () => {\r\n this.isDraggingVolume = false;\r\n });\r\n\r\n // Keyboard volume control\r\n volumeSlider.addEventListener('keydown', (e) => {\r\n if (e.key === 'ArrowUp') {\r\n e.preventDefault();\r\n this.player.setVolume(Math.min(1, this.player.state.volume + 0.1));\r\n } else if (e.key === 'ArrowDown') {\r\n e.preventDefault();\r\n this.player.setVolume(Math.max(0, this.player.state.volume - 0.1));\r\n }\r\n });\r\n\r\n // Prevent menu from closing when interacting with slider\r\n volumeMenu.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n // Append menu to button\r\n button.appendChild(volumeMenu);\r\n\r\n this.controls.volumeSlider = volumeSlider;\r\n this.controls.volumeFill = volumeFill;\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(volumeMenu, button, true);\r\n }\r\n\r\n createTimeDisplay() {\r\n const container = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-time`,\r\n attributes: {\r\n 'role': 'group',\r\n 'aria-label': i18n.t('time.display')\r\n }\r\n });\r\n\r\n // Current time - visual text hidden, only aria-label announced\r\n this.controls.currentTimeDisplay = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-current-time`,\r\n attributes: {\r\n 'aria-label': i18n.t('time.seconds', { count: 0 })\r\n }\r\n });\r\n \r\n // Create visual text inside, hidden from screen readers\r\n const currentTimeVisual = DOMUtils.createElement('span', {\r\n textContent: '00:00',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n this.controls.currentTimeDisplay.appendChild(currentTimeVisual);\r\n this.controls.currentTimeVisual = currentTimeVisual;\r\n\r\n const separator = DOMUtils.createElement('span', {\r\n textContent: ' / ',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n\r\n // Duration - visual text hidden, only aria-label announced\r\n this.controls.durationDisplay = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-duration`,\r\n attributes: {\r\n 'aria-label': i18n.t('time.durationPrefix') + i18n.t('time.seconds', { count: 0 })\r\n }\r\n });\r\n \r\n // Create visual text inside, hidden from screen readers\r\n const durationVisual = DOMUtils.createElement('span', {\r\n textContent: '00:00',\r\n attributes: {\r\n 'aria-hidden': 'true'\r\n }\r\n });\r\n this.controls.durationDisplay.appendChild(durationVisual);\r\n this.controls.durationVisual = durationVisual;\r\n\r\n container.appendChild(this.controls.currentTimeDisplay);\r\n container.appendChild(separator);\r\n container.appendChild(this.controls.durationDisplay);\r\n\r\n return container;\r\n }\r\n\r\n createChaptersButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-chapters`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.chapters'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('playlist'));\r\n\r\n button.addEventListener('click', () => {\r\n this.showChaptersMenu(button);\r\n });\r\n\r\n this.controls.chapters = button;\r\n return button;\r\n }\r\n\r\n showChaptersMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-chapters-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-chapters-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.chapters')\r\n }\r\n });\r\n\r\n // Get chapter tracks\r\n const chapterTracks = Array.from(this.player.element.textTracks).filter(\r\n track => track.kind === 'chapters'\r\n );\r\n\r\n if (chapterTracks.length === 0) {\r\n // No chapters available\r\n const noChaptersItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noChapters'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noChaptersItem);\r\n } else {\r\n const chapterTrack = chapterTracks[0];\r\n\r\n // Ensure track is in 'hidden' mode to load cues\r\n if (chapterTrack.mode === 'disabled') {\r\n chapterTrack.mode = 'hidden';\r\n }\r\n\r\n if (!chapterTrack.cues || chapterTrack.cues.length === 0) {\r\n // Cues not loaded yet - wait for them to load\r\n const loadingItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.loadingChapters'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(loadingItem);\r\n\r\n // Listen for track load event\r\n const onTrackLoad = () => {\r\n // Remove loading message and rebuild menu\r\n menu.remove();\r\n this.showChaptersMenu(button);\r\n };\r\n\r\n chapterTrack.addEventListener('load', onTrackLoad, {once: true});\r\n\r\n // Also try again after a short delay as fallback\r\n setTimeout(() => {\r\n if (chapterTrack.cues && chapterTrack.cues.length > 0 && document.contains(menu)) {\r\n menu.remove();\r\n this.showChaptersMenu(button);\r\n }\r\n }, 500);\r\n } else {\r\n // Display chapters\r\n const cues = chapterTrack.cues;\r\n for (let i = 0; i < cues.length; i++) {\r\n const cue = cues[i];\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n const timeLabel = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-chapter-time`,\r\n textContent: TimeUtils.formatTime(cue.startTime)\r\n });\r\n\r\n const titleLabel = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-chapter-title`,\r\n textContent: cue.text\r\n });\r\n\r\n item.appendChild(timeLabel);\r\n item.appendChild(document.createTextNode(' '));\r\n item.appendChild(titleLabel);\r\n\r\n item.addEventListener('click', () => {\r\n this.player.seek(cue.startTime);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n }\r\n \r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n \r\n // Focus first item\r\n setTimeout(() => {\r\n const firstItem = menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (firstItem) {\r\n firstItem.focus();\r\n }\r\n }, 0);\r\n }\r\n }\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n }\r\n\r\n createQualityButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-quality`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.quality'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('hd'));\r\n\r\n // Add quality indicator text\r\n const qualityText = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-quality-text`,\r\n textContent: ''\r\n });\r\n button.appendChild(qualityText);\r\n\r\n button.addEventListener('click', () => {\r\n this.showQualityMenu(button);\r\n });\r\n\r\n this.controls.quality = button;\r\n this.controls.qualityText = qualityText;\r\n \r\n // Update quality indicator after a short delay to ensure renderer is ready\r\n setTimeout(() => this.updateQualityIndicator(), 500);\r\n \r\n return button;\r\n }\r\n\r\n showQualityMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-quality-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-quality-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.quality')\r\n }\r\n });\r\n\r\n // Check if renderer supports quality selection\r\n if (this.player.renderer && this.player.renderer.getQualities) {\r\n const qualities = this.player.renderer.getQualities();\r\n const currentQuality = this.player.renderer.getCurrentQuality ? this.player.renderer.getCurrentQuality() : -1;\r\n const isHLS = this.player.renderer.hls !== undefined;\r\n\r\n if (qualities.length === 0) {\r\n // No qualities available\r\n const noQualityItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.autoQuality'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noQualityItem);\r\n } else {\r\n let activeItem = null;\r\n \r\n // Auto quality option (only for HLS)\r\n if (isHLS) {\r\n const autoItem = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.auto'),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Check if auto is currently selected\r\n const isAuto = this.player.renderer.hls && this.player.renderer.hls.currentLevel === -1;\r\n if (isAuto) {\r\n autoItem.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n autoItem.appendChild(createIconElement('check'));\r\n activeItem = autoItem;\r\n }\r\n\r\n autoItem.addEventListener('click', () => {\r\n if (this.player.renderer.switchQuality) {\r\n this.player.renderer.switchQuality(-1); // -1 for auto\r\n }\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(autoItem);\r\n }\r\n\r\n // Quality options\r\n qualities.forEach(quality => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: quality.name || `${quality.height}p`,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Highlight current quality\r\n if (quality.index === currentQuality) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n if (this.player.renderer.switchQuality) {\r\n this.player.renderer.switchQuality(quality.index);\r\n }\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n \r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n \r\n // Focus active item or first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n } else {\r\n // No quality support\r\n const noSupportItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noQuality'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noSupportItem);\r\n }\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n }\r\n\r\n createCaptionStyleButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-caption-style`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.captionStyling'),\r\n 'aria-haspopup': 'menu',\r\n 'title': i18n.t('player.captionStyling')\r\n }\r\n });\r\n\r\n // Create \"Aa\" text icon for styling\r\n const textIcon = DOMUtils.createElement('span', {\r\n textContent: 'Aa',\r\n style: {\r\n fontSize: '14px',\r\n fontWeight: 'bold'\r\n }\r\n });\r\n button.appendChild(textIcon);\r\n\r\n button.addEventListener('click', () => {\r\n this.showCaptionStyleMenu(button);\r\n });\r\n\r\n this.controls.captionStyle = button;\r\n return button;\r\n }\r\n\r\n showCaptionStyleMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-caption-style-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-caption-style-menu ${this.player.options.classPrefix}-menu ${this.player.options.classPrefix}-settings-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('player.captionStyling')\r\n }\r\n });\r\n\r\n // Prevent menu from closing when clicking inside\r\n menu.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n // Check if there are any caption tracks\r\n if (!this.player.captionManager || this.player.captionManager.tracks.length === 0) {\r\n // Show \"No captions available\" message\r\n const noTracksItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noCaptions'),\r\n style: {opacity: '0.5', cursor: 'default', padding: '12px 16px'}\r\n });\r\n menu.appendChild(noTracksItem);\r\n\r\n // Append menu to button\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button, true);\r\n return;\r\n }\r\n\r\n // Font Size\r\n const fontSizeGroup = this.createStyleControl(\r\n i18n.t('styleLabels.fontSize'),\r\n 'captionsFontSize',\r\n [\r\n {label: i18n.t('fontSizes.small'), value: '87.5%'},\r\n {label: i18n.t('fontSizes.normal'), value: '100%'},\r\n {label: i18n.t('fontSizes.large'), value: '125%'},\r\n {label: i18n.t('fontSizes.xlarge'), value: '150%'}\r\n ]\r\n );\r\n menu.appendChild(fontSizeGroup);\r\n\r\n // Font Family\r\n const fontFamilyGroup = this.createStyleControl(\r\n i18n.t('styleLabels.font'),\r\n 'captionsFontFamily',\r\n [\r\n {label: i18n.t('fontFamilies.sansSerif'), value: 'sans-serif'},\r\n {label: i18n.t('fontFamilies.serif'), value: 'serif'},\r\n {label: i18n.t('fontFamilies.monospace'), value: 'monospace'}\r\n ]\r\n );\r\n menu.appendChild(fontFamilyGroup);\r\n\r\n // Text Color\r\n const colorGroup = this.createColorControl(i18n.t('styleLabels.textColor'), 'captionsColor');\r\n menu.appendChild(colorGroup);\r\n\r\n // Background Color\r\n const bgColorGroup = this.createColorControl(i18n.t('styleLabels.background'), 'captionsBackgroundColor');\r\n menu.appendChild(bgColorGroup);\r\n\r\n // Opacity\r\n const opacityGroup = this.createOpacityControl(i18n.t('styleLabels.opacity'), 'captionsOpacity');\r\n menu.appendChild(opacityGroup);\r\n\r\n // Set min-width for caption style menu\r\n menu.style.minWidth = '220px';\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click (but not when interacting with controls)\r\n this.attachMenuCloseHandler(menu, button, true);\r\n\r\n // Auto-focus the first select element\r\n setTimeout(() => {\r\n const firstSelect = menu.querySelector('select');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n createStyleControl(label, property, options) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n display: 'block',\r\n fontSize: '12px',\r\n marginBottom: '4px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const select = DOMUtils.createElement('select', {\r\n className: `${this.player.options.classPrefix}-style-select`,\r\n style: {\r\n width: '100%',\r\n padding: '6px',\r\n background: 'var(--vidply-white)',\r\n border: '1px solid var(--vidply-white-10)',\r\n borderRadius: '4px',\r\n color: 'var(--vidply-black)',\r\n fontSize: '13px'\r\n }\r\n });\r\n\r\n const currentValue = this.player.options[property];\r\n options.forEach(opt => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: opt.label,\r\n attributes: {value: opt.value}\r\n });\r\n if (opt.value === currentValue) {\r\n option.selected = true;\r\n }\r\n select.appendChild(option);\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n select.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', (e) => {\r\n e.stopPropagation();\r\n this.player.options[property] = e.target.value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n e.target.value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(select);\r\n return group;\r\n }\r\n\r\n createColorControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n display: 'block',\r\n fontSize: '12px',\r\n marginBottom: '4px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n type: 'color',\r\n value: this.player.options[property]\r\n },\r\n style: {\r\n width: '100%',\r\n height: '32px',\r\n padding: '2px',\r\n background: 'rgba(255,255,255,0.1)',\r\n border: '1px solid rgba(255,255,255,0.2)',\r\n borderRadius: '4px',\r\n cursor: 'pointer'\r\n }\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n input.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('change', (e) => {\r\n e.stopPropagation();\r\n this.player.options[property] = e.target.value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n e.target.value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n createOpacityControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-style-group`\r\n });\r\n\r\n const labelContainer = DOMUtils.createElement('div', {\r\n style: {\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n marginBottom: '4px'\r\n }\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label,\r\n style: {\r\n fontSize: '12px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n\r\n const valueEl = DOMUtils.createElement('span', {\r\n textContent: Math.round(this.player.options[property] * 100) + '%',\r\n style: {\r\n fontSize: '12px',\r\n color: 'rgba(255,255,255,0.7)'\r\n }\r\n });\r\n\r\n labelContainer.appendChild(labelEl);\r\n labelContainer.appendChild(valueEl);\r\n group.appendChild(labelContainer);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n type: 'range',\r\n min: '0',\r\n max: '1',\r\n step: '0.1',\r\n value: String(this.player.options[property])\r\n },\r\n style: {\r\n width: '100%',\r\n cursor: 'pointer'\r\n }\r\n });\r\n\r\n // Prevent clicks from closing the menu\r\n input.addEventListener('mousedown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n e.stopPropagation();\r\n const value = parseFloat(e.target.value);\r\n valueEl.textContent = Math.round(value * 100) + '%';\r\n this.player.options[property] = value;\r\n if (this.player.captionManager) {\r\n this.player.captionManager.setCaptionStyle(\r\n property.replace('captions', '').charAt(0).toLowerCase() + property.replace('captions', '').slice(1),\r\n value\r\n );\r\n }\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n createSpeedButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-speed`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.speed'),\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('speed'));\r\n\r\n const speedText = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-speed-text`,\r\n textContent: '1x'\r\n });\r\n button.appendChild(speedText);\r\n\r\n button.addEventListener('click', () => {\r\n this.showSpeedMenu(button);\r\n });\r\n\r\n this.controls.speed = button;\r\n this.controls.speedText = speedText;\r\n return button;\r\n }\r\n\r\n formatSpeedLabel(speed) {\r\n // Special case: 1x is \"Normal\" (translated)\r\n if (speed === 1) {\r\n return i18n.t('speeds.normal');\r\n }\r\n \r\n // For other speeds, format with locale-specific decimal separator\r\n const speedStr = speed.toLocaleString(i18n.getLanguage(), {\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 2\r\n });\r\n \r\n return `${speedStr}\u00D7`;\r\n }\r\n\r\n showSpeedMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-speed-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-speed-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu'\r\n }\r\n });\r\n\r\n const speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];\r\n let activeItem = null;\r\n\r\n speeds.forEach(speed => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: this.formatSpeedLabel(speed),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n if (speed === this.player.state.playbackSpeed) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n this.player.setPlaybackSpeed(speed);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Add keyboard navigation\r\n this.attachMenuKeyboardNavigation(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n\r\n // Focus the active item or first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n createCaptionsButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-captions-button`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.captions'),\r\n 'aria-pressed': 'false',\r\n 'aria-haspopup': 'menu'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('captionsOff'));\r\n\r\n button.addEventListener('click', () => {\r\n this.showCaptionsMenu(button);\r\n });\r\n\r\n this.controls.captions = button;\r\n return button;\r\n }\r\n\r\n showCaptionsMenu(button) {\r\n // Remove existing menu if any\r\n const existingMenu = document.querySelector(`.${this.player.options.classPrefix}-captions-menu`);\r\n if (existingMenu) {\r\n existingMenu.remove();\r\n return;\r\n }\r\n\r\n const menu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-captions-menu ${this.player.options.classPrefix}-menu`,\r\n attributes: {\r\n 'role': 'menu',\r\n 'aria-label': i18n.t('captions.select')\r\n }\r\n });\r\n\r\n // Check if there are any caption tracks\r\n if (!this.player.captionManager || this.player.captionManager.tracks.length === 0) {\r\n // Show \"No captions available\" message\r\n const noTracksItem = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('player.noCaptions'),\r\n style: {opacity: '0.5', cursor: 'default'}\r\n });\r\n menu.appendChild(noTracksItem);\r\n\r\n // Append menu to button\r\n button.appendChild(menu);\r\n\r\n // Close menu on outside click\r\n this.attachMenuCloseHandler(menu, button);\r\n return;\r\n }\r\n\r\n let activeItem = null;\r\n\r\n // Off option\r\n const offItem = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: i18n.t('captions.off'),\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n if (!this.player.state.captionsEnabled) {\r\n offItem.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n offItem.appendChild(createIconElement('check'));\r\n activeItem = offItem;\r\n }\r\n\r\n offItem.addEventListener('click', () => {\r\n this.player.disableCaptions();\r\n this.updateCaptionsButton();\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(offItem);\r\n\r\n // Available tracks\r\n const tracks = this.player.captionManager.getAvailableTracks();\r\n tracks.forEach(track => {\r\n const item = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-menu-item`,\r\n textContent: track.label,\r\n attributes: {\r\n 'type': 'button',\r\n 'role': 'menuitem',\r\n 'lang': track.language,\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Check if this is the current track\r\n if (this.player.state.captionsEnabled &&\r\n this.player.captionManager.currentTrack === this.player.captionManager.tracks[track.index]) {\r\n item.classList.add(`${this.player.options.classPrefix}-menu-item-active`);\r\n item.appendChild(createIconElement('check'));\r\n activeItem = item;\r\n }\r\n\r\n item.addEventListener('click', () => {\r\n this.player.captionManager.switchTrack(track.index);\r\n this.updateCaptionsButton();\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(item);\r\n });\r\n\r\n // Append menu directly to button for proper positioning\r\n button.appendChild(menu);\r\n\r\n // Add keyboard navigation for the menu\r\n this.attachMenuKeyboardNavigation(menu);\r\n\r\n // Close menu on outside click and Escape key\r\n this.attachMenuCloseHandler(menu, button);\r\n\r\n // Focus the active item or the first item\r\n setTimeout(() => {\r\n const focusTarget = activeItem || menu.querySelector(`.${this.player.options.classPrefix}-menu-item`);\r\n if (focusTarget) {\r\n focusTarget.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n updateCaptionsButton() {\r\n if (!this.controls.captions) return;\r\n\r\n const icon = this.controls.captions.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.captionsEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('captions').innerHTML :\r\n createIconElement('captionsOff').innerHTML;\r\n\r\n this.controls.captions.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n }\r\n\r\n createTranscriptButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-transcript`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.transcript'),\r\n 'aria-pressed': 'false'\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('transcript'));\r\n\r\n button.addEventListener('click', () => {\r\n if (this.player.transcriptManager) {\r\n this.player.transcriptManager.toggleTranscript();\r\n this.updateTranscriptButton();\r\n }\r\n });\r\n\r\n this.controls.transcript = button;\r\n return button;\r\n }\r\n\r\n updateTranscriptButton() {\r\n if (!this.controls.transcript) return;\r\n\r\n const isVisible = this.player.transcriptManager && this.player.transcriptManager.isVisible;\r\n this.controls.transcript.setAttribute('aria-pressed', isVisible ? 'true' : 'false');\r\n }\r\n\r\n createAudioDescriptionButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-audio-description`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.audioDescription'),\r\n 'aria-pressed': 'false',\r\n 'title': i18n.t('player.audioDescription')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('audioDescription'));\r\n\r\n button.addEventListener('click', async () => {\r\n await this.player.toggleAudioDescription();\r\n this.updateAudioDescriptionButton();\r\n });\r\n\r\n this.controls.audioDescription = button;\r\n return button;\r\n }\r\n\r\n updateAudioDescriptionButton() {\r\n if (!this.controls.audioDescription) return;\r\n\r\n const icon = this.controls.audioDescription.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.audioDescriptionEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('audioDescriptionOn').innerHTML :\r\n createIconElement('audioDescription').innerHTML;\r\n\r\n this.controls.audioDescription.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n this.controls.audioDescription.setAttribute('aria-label',\r\n isEnabled ? i18n.t('audioDescription.disable') : i18n.t('audioDescription.enable')\r\n );\r\n }\r\n\r\n createSignLanguageButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-sign-language`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.signLanguage'),\r\n 'aria-pressed': 'false',\r\n 'title': i18n.t('player.signLanguage')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('signLanguage'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggleSignLanguage();\r\n this.updateSignLanguageButton();\r\n });\r\n\r\n this.controls.signLanguage = button;\r\n return button;\r\n }\r\n\r\n updateSignLanguageButton() {\r\n if (!this.controls.signLanguage) return;\r\n\r\n const icon = this.controls.signLanguage.querySelector('.vidply-icon');\r\n const isEnabled = this.player.state.signLanguageEnabled;\r\n\r\n icon.innerHTML = isEnabled ?\r\n createIconElement('signLanguageOn').innerHTML :\r\n createIconElement('signLanguage').innerHTML;\r\n\r\n this.controls.signLanguage.setAttribute('aria-pressed', isEnabled ? 'true' : 'false');\r\n this.controls.signLanguage.setAttribute('aria-label',\r\n isEnabled ? i18n.t('signLanguage.hide') : i18n.t('signLanguage.show')\r\n );\r\n }\r\n\r\n createSettingsButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-settings`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.settings')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('settings'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.showSettings();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createPipButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-pip`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.pip')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('pip'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.togglePiP();\r\n });\r\n\r\n return button;\r\n }\r\n\r\n createFullscreenButton() {\r\n const button = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-button ${this.player.options.classPrefix}-fullscreen`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('player.fullscreen')\r\n }\r\n });\r\n\r\n button.appendChild(createIconElement('fullscreen'));\r\n\r\n button.addEventListener('click', () => {\r\n this.player.toggleFullscreen();\r\n });\r\n\r\n this.controls.fullscreen = button;\r\n return button;\r\n }\r\n\r\n attachEvents() {\r\n // Update controls based on player state\r\n this.player.on('play', () => this.updatePlayPauseButton());\r\n this.player.on('pause', () => this.updatePlayPauseButton());\r\n this.player.on('timeupdate', () => this.updateProgress());\r\n this.player.on('loadedmetadata', () => {\r\n this.updateDuration();\r\n this.ensureQualityButton();\r\n this.updateQualityIndicator();\r\n });\r\n this.player.on('volumechange', () => this.updateVolumeDisplay());\r\n this.player.on('progress', () => this.updateBuffered());\r\n this.player.on('playbackspeedchange', () => this.updateSpeedDisplay());\r\n this.player.on('fullscreenchange', () => this.updateFullscreenButton());\r\n this.player.on('captionsenabled', () => this.updateCaptionsButton());\r\n this.player.on('captionsdisabled', () => this.updateCaptionsButton());\r\n this.player.on('audiodescriptionenabled', () => this.updateAudioDescriptionButton());\r\n this.player.on('audiodescriptiondisabled', () => this.updateAudioDescriptionButton());\r\n this.player.on('signlanguageenabled', () => this.updateSignLanguageButton());\r\n this.player.on('signlanguagedisabled', () => this.updateSignLanguageButton());\r\n this.player.on('qualitychange', () => this.updateQualityIndicator());\r\n this.player.on('hlslevelswitched', () => this.updateQualityIndicator());\r\n this.player.on('hlsmanifestparsed', () => {\r\n this.ensureQualityButton();\r\n this.updateQualityIndicator();\r\n });\r\n }\r\n\r\n updatePlayPauseButton() {\r\n if (!this.controls.playPause) return;\r\n\r\n const icon = this.controls.playPause.querySelector('.vidply-icon');\r\n const isPlaying = this.player.state.playing;\r\n\r\n icon.innerHTML = isPlaying ?\r\n createIconElement('pause').innerHTML :\r\n createIconElement('play').innerHTML;\r\n\r\n this.controls.playPause.setAttribute('aria-label',\r\n isPlaying ? i18n.t('player.pause') : i18n.t('player.play')\r\n );\r\n }\r\n\r\n updateProgress() {\r\n if (!this.controls.played) return;\r\n\r\n const percent = (this.player.state.currentTime / this.player.state.duration) * 100;\r\n this.controls.played.style.width = `${percent}%`;\r\n this.controls.progress.setAttribute('aria-valuenow', String(Math.round(percent)));\r\n\r\n if (this.controls.currentTimeVisual) {\r\n const currentTime = this.player.state.currentTime;\r\n // Update visual text (hidden from screen readers)\r\n this.controls.currentTimeVisual.textContent = TimeUtils.formatTime(currentTime);\r\n // Update aria-label with human-readable format\r\n this.controls.currentTimeDisplay.setAttribute('aria-label', TimeUtils.formatDuration(currentTime));\r\n }\r\n }\r\n\r\n updateDuration() {\r\n if (this.controls.durationVisual) {\r\n const duration = this.player.state.duration;\r\n // Update visual text (hidden from screen readers)\r\n this.controls.durationVisual.textContent = TimeUtils.formatTime(duration);\r\n // Update aria-label with human-readable format\r\n this.controls.durationDisplay.setAttribute('aria-label', i18n.t('time.durationPrefix') + TimeUtils.formatDuration(duration));\r\n }\r\n }\r\n\r\n updateVolumeDisplay() {\r\n const percent = this.player.state.volume * 100;\r\n\r\n // Update volume fill bar if it exists\r\n if (this.controls.volumeFill) {\r\n this.controls.volumeFill.style.height = `${percent}%`;\r\n }\r\n\r\n // Update mute button icon (should always work even if slider not shown)\r\n if (this.controls.mute) {\r\n const icon = this.controls.mute.querySelector('.vidply-icon');\r\n if (icon) {\r\n let iconName;\r\n\r\n if (this.player.state.muted || this.player.state.volume === 0) {\r\n iconName = 'volumeMuted';\r\n } else if (this.player.state.volume < 0.3) {\r\n iconName = 'volumeLow';\r\n } else if (this.player.state.volume < 0.7) {\r\n iconName = 'volumeMedium';\r\n } else {\r\n iconName = 'volumeHigh';\r\n }\r\n\r\n icon.innerHTML = createIconElement(iconName).innerHTML;\r\n\r\n this.controls.mute.setAttribute('aria-label',\r\n this.player.state.muted ? i18n.t('player.unmute') : i18n.t('player.mute')\r\n );\r\n }\r\n }\r\n\r\n // Update volume slider attribute if it exists\r\n if (this.controls.volumeSlider) {\r\n this.controls.volumeSlider.setAttribute('aria-valuenow', String(Math.round(percent)));\r\n }\r\n }\r\n\r\n updateBuffered() {\r\n if (!this.controls.buffered || !this.player.element.buffered || this.player.element.buffered.length === 0) return;\r\n\r\n const buffered = this.player.element.buffered.end(this.player.element.buffered.length - 1);\r\n const percent = (buffered / this.player.state.duration) * 100;\r\n this.controls.buffered.style.width = `${percent}%`;\r\n }\r\n\r\n updateSpeedDisplay() {\r\n if (this.controls.speedText) {\r\n this.controls.speedText.textContent = `${this.player.state.playbackSpeed}x`;\r\n }\r\n }\r\n\r\n updateFullscreenButton() {\r\n if (!this.controls.fullscreen) return;\r\n\r\n const icon = this.controls.fullscreen.querySelector('.vidply-icon');\r\n const isFullscreen = this.player.state.fullscreen;\r\n\r\n icon.innerHTML = isFullscreen ?\r\n createIconElement('fullscreenExit').innerHTML :\r\n createIconElement('fullscreen').innerHTML;\r\n\r\n this.controls.fullscreen.setAttribute('aria-label',\r\n isFullscreen ? i18n.t('player.exitFullscreen') : i18n.t('player.fullscreen')\r\n );\r\n }\r\n\r\n /**\r\n * Ensure quality button exists if qualities are available\r\n * This is called after renderer initialization to dynamically add the button\r\n */\r\n ensureQualityButton() {\r\n // Skip if quality button is disabled\r\n if (!this.player.options.qualityButton) return;\r\n \r\n // Skip if button already exists\r\n if (this.controls.quality) return;\r\n \r\n // Check if qualities are now available\r\n if (!this.hasQualityLevels()) return;\r\n \r\n // Create and insert the quality button before the speed button\r\n const qualityButton = this.createQualityButton();\r\n \r\n // Find the speed button or caption style button to insert before\r\n const speedButton = this.rightButtons.querySelector(`.${this.player.options.classPrefix}-speed`);\r\n const captionStyleButton = this.rightButtons.querySelector(`.${this.player.options.classPrefix}-caption-style`);\r\n const insertBefore = captionStyleButton || speedButton;\r\n \r\n if (insertBefore) {\r\n this.rightButtons.insertBefore(qualityButton, insertBefore);\r\n } else {\r\n // If no reference button, add it at the beginning of right buttons\r\n this.rightButtons.insertBefore(qualityButton, this.rightButtons.firstChild);\r\n }\r\n \r\n this.player.log('Quality button added dynamically', 'info');\r\n }\r\n\r\n updateQualityIndicator() {\r\n if (!this.controls.qualityText) return;\r\n if (!this.player.renderer || !this.player.renderer.getQualities) return;\r\n\r\n const qualities = this.player.renderer.getQualities();\r\n if (qualities.length === 0) {\r\n this.controls.qualityText.textContent = '';\r\n return;\r\n }\r\n\r\n // Get current quality\r\n let currentQualityText = '';\r\n \r\n // Check if it's HLS with auto mode\r\n if (this.player.renderer.hls && this.player.renderer.hls.currentLevel === -1) {\r\n currentQualityText = 'Auto';\r\n } else if (this.player.renderer.getCurrentQuality) {\r\n const currentIndex = this.player.renderer.getCurrentQuality();\r\n const currentQuality = qualities.find(q => q.index === currentIndex);\r\n if (currentQuality) {\r\n currentQualityText = currentQuality.height ? `${currentQuality.height}p` : '';\r\n }\r\n }\r\n\r\n this.controls.qualityText.textContent = currentQualityText;\r\n }\r\n\r\n setupAutoHide() {\r\n if (this.player.element.tagName !== 'VIDEO') return;\r\n\r\n const showControls = () => {\r\n this.element.classList.add(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.container.classList.add(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.state.controlsVisible = true;\r\n\r\n clearTimeout(this.hideTimeout);\r\n\r\n if (this.player.state.playing) {\r\n this.hideTimeout = setTimeout(() => {\r\n this.element.classList.remove(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.container.classList.remove(`${this.player.options.classPrefix}-controls-visible`);\r\n this.player.state.controlsVisible = false;\r\n }, this.player.options.hideControlsDelay);\r\n }\r\n };\r\n\r\n this.player.container.addEventListener('mousemove', showControls);\r\n this.player.container.addEventListener('touchstart', showControls);\r\n this.player.container.addEventListener('click', showControls);\r\n\r\n // Show controls on focus\r\n this.element.addEventListener('focusin', showControls);\r\n\r\n // Always show when paused\r\n this.player.on('pause', () => {\r\n showControls();\r\n clearTimeout(this.hideTimeout);\r\n });\r\n\r\n this.player.on('play', () => {\r\n showControls();\r\n });\r\n\r\n // Initial state\r\n showControls();\r\n }\r\n\r\n show() {\r\n this.element.style.display = '';\r\n }\r\n\r\n hide() {\r\n this.element.style.display = 'none';\r\n }\r\n\r\n destroy() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n }\r\n\r\n if (this.element && this.element.parentNode) {\r\n this.element.parentNode.removeChild(this.element);\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * StorageManager - Handles persistent storage of user preferences\r\n */\r\n\r\nexport class StorageManager {\r\n constructor(namespace = 'vidply') {\r\n this.namespace = namespace;\r\n this.storage = this.isStorageAvailable() ? localStorage : null;\r\n }\r\n\r\n /**\r\n * Check if localStorage is available\r\n */\r\n isStorageAvailable() {\r\n try {\r\n const test = '__storage_test__';\r\n localStorage.setItem(test, test);\r\n localStorage.removeItem(test);\r\n return true;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a namespaced key\r\n */\r\n getKey(key) {\r\n return `${this.namespace}_${key}`;\r\n }\r\n\r\n /**\r\n * Save a value to storage\r\n */\r\n set(key, value) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.setItem(namespacedKey, JSON.stringify(value));\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to save to localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Get a value from storage\r\n */\r\n get(key, defaultValue = null) {\r\n if (!this.storage) return defaultValue;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n const value = this.storage.getItem(namespacedKey);\r\n return value ? JSON.parse(value) : defaultValue;\r\n } catch (e) {\r\n console.warn('Failed to read from localStorage:', e);\r\n return defaultValue;\r\n }\r\n }\r\n\r\n /**\r\n * Remove a value from storage\r\n */\r\n remove(key) {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const namespacedKey = this.getKey(key);\r\n this.storage.removeItem(namespacedKey);\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to remove from localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clear all namespaced values\r\n */\r\n clear() {\r\n if (!this.storage) return false;\r\n \r\n try {\r\n const keys = Object.keys(this.storage);\r\n keys.forEach(key => {\r\n if (key.startsWith(this.namespace)) {\r\n this.storage.removeItem(key);\r\n }\r\n });\r\n return true;\r\n } catch (e) {\r\n console.warn('Failed to clear localStorage:', e);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Save transcript preferences\r\n */\r\n saveTranscriptPreferences(preferences) {\r\n return this.set('transcript_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get transcript preferences\r\n */\r\n getTranscriptPreferences() {\r\n return this.get('transcript_preferences', null);\r\n }\r\n\r\n /**\r\n * Save caption preferences\r\n */\r\n saveCaptionPreferences(preferences) {\r\n return this.set('caption_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get caption preferences\r\n */\r\n getCaptionPreferences() {\r\n return this.get('caption_preferences', null);\r\n }\r\n\r\n /**\r\n * Save player preferences (volume, speed, etc.)\r\n */\r\n savePlayerPreferences(preferences) {\r\n return this.set('player_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get player preferences\r\n */\r\n getPlayerPreferences() {\r\n return this.get('player_preferences', null);\r\n }\r\n\r\n /**\r\n * Save sign language preferences (position and size)\r\n */\r\n saveSignLanguagePreferences(preferences) {\r\n return this.set('sign_language_preferences', preferences);\r\n }\r\n\r\n /**\r\n * Get sign language preferences\r\n */\r\n getSignLanguagePreferences() {\r\n return this.get('sign_language_preferences', null);\r\n }\r\n}\r\n\r\n", "/**\r\n * Caption/Subtitle Manager\r\n */\r\n\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\nimport {StorageManager} from '../utils/StorageManager.js';\r\n\r\nexport class CaptionManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.element = null;\r\n this.tracks = [];\r\n this.currentTrack = null;\r\n this.currentCue = null;\r\n \r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Load saved preferences\r\n this.loadSavedPreferences();\r\n\r\n this.init();\r\n }\r\n \r\n loadSavedPreferences() {\r\n const saved = this.storage.getCaptionPreferences();\r\n if (saved) {\r\n // Override player options with saved preferences\r\n if (saved.fontSize) this.player.options.captionsFontSize = saved.fontSize;\r\n if (saved.fontFamily) this.player.options.captionsFontFamily = saved.fontFamily;\r\n if (saved.color) this.player.options.captionsColor = saved.color;\r\n if (saved.backgroundColor) this.player.options.captionsBackgroundColor = saved.backgroundColor;\r\n if (saved.opacity !== undefined) this.player.options.captionsOpacity = saved.opacity;\r\n }\r\n }\r\n \r\n saveCaptionPreferences() {\r\n this.storage.saveCaptionPreferences({\r\n fontSize: this.player.options.captionsFontSize,\r\n fontFamily: this.player.options.captionsFontFamily,\r\n color: this.player.options.captionsColor,\r\n backgroundColor: this.player.options.captionsBackgroundColor,\r\n opacity: this.player.options.captionsOpacity\r\n });\r\n }\r\n\r\n init() {\r\n this.createElement();\r\n this.loadTracks();\r\n this.attachEvents();\r\n\r\n if (this.player.options.captionsDefault && this.tracks.length > 0) {\r\n this.enable();\r\n }\r\n }\r\n\r\n createElement() {\r\n this.element = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-captions`,\r\n attributes: {\r\n 'aria-live': 'polite',\r\n 'aria-atomic': 'true',\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.captions')\r\n }\r\n });\r\n\r\n // Apply caption styles\r\n this.updateStyles();\r\n\r\n // Append to videoWrapper if it exists, otherwise to container\r\n const target = this.player.videoWrapper || this.player.container;\r\n target.appendChild(this.element);\r\n }\r\n\r\n loadTracks() {\r\n const textTracks = this.player.element.textTracks;\r\n\r\n for (let i = 0; i < textTracks.length; i++) {\r\n const track = textTracks[i];\r\n\r\n if (track.kind === 'subtitles' || track.kind === 'captions') {\r\n this.tracks.push({\r\n track: track,\r\n language: track.language,\r\n label: track.label,\r\n kind: track.kind,\r\n index: i\r\n });\r\n\r\n // Disable all tracks initially\r\n track.mode = 'hidden';\r\n }\r\n }\r\n }\r\n\r\n attachEvents() {\r\n this.player.on('timeupdate', () => {\r\n this.updateCaptions();\r\n });\r\n\r\n this.player.on('captionschange', () => {\r\n this.updateStyles();\r\n });\r\n }\r\n\r\n enable(trackIndex = 0) {\r\n if (this.tracks.length === 0) {\r\n return;\r\n }\r\n\r\n // Disable current track\r\n if (this.currentTrack) {\r\n this.currentTrack.track.mode = 'hidden';\r\n }\r\n\r\n // Enable selected track\r\n const selectedTrack = this.tracks[trackIndex];\r\n\r\n if (selectedTrack) {\r\n // Set to 'hidden' not 'showing' to prevent browser from displaying native captions\r\n // We'll handle the display ourselves\r\n selectedTrack.track.mode = 'hidden';\r\n this.currentTrack = selectedTrack;\r\n this.player.state.captionsEnabled = true;\r\n\r\n // Remove any existing cuechange listener\r\n if (this.cueChangeHandler) {\r\n selectedTrack.track.removeEventListener('cuechange', this.cueChangeHandler);\r\n }\r\n\r\n // Add event listener for cue changes\r\n this.cueChangeHandler = () => {\r\n this.updateCaptions();\r\n };\r\n selectedTrack.track.addEventListener('cuechange', this.cueChangeHandler);\r\n\r\n this.player.emit('captionsenabled', selectedTrack);\r\n }\r\n }\r\n\r\n disable() {\r\n if (this.currentTrack) {\r\n this.currentTrack.track.mode = 'hidden';\r\n this.currentTrack = null;\r\n }\r\n\r\n this.element.style.display = 'none';\r\n this.element.innerHTML = '';\r\n this.currentCue = null;\r\n this.player.state.captionsEnabled = false;\r\n this.player.emit('captionsdisabled');\r\n }\r\n\r\n updateCaptions() {\r\n if (!this.currentTrack) {\r\n return;\r\n }\r\n\r\n if (!this.currentTrack.track.activeCues) {\r\n return;\r\n }\r\n\r\n const activeCues = this.currentTrack.track.activeCues;\r\n\r\n if (activeCues.length > 0) {\r\n const cue = activeCues[0];\r\n\r\n // Only update if the cue has changed\r\n if (this.currentCue !== cue) {\r\n this.currentCue = cue;\r\n\r\n // Parse and display cue text\r\n let text = cue.text;\r\n\r\n // Handle VTT formatting\r\n text = this.parseVTTFormatting(text);\r\n\r\n this.element.innerHTML = DOMUtils.sanitizeHTML(text);\r\n\r\n // Make sure it's visible when there's content\r\n this.element.style.display = 'block';\r\n\r\n this.player.emit('captionchange', cue);\r\n }\r\n } else if (this.currentCue) {\r\n // Clear caption\r\n this.element.innerHTML = '';\r\n this.element.style.display = 'none';\r\n this.currentCue = null;\r\n }\r\n }\r\n\r\n parseVTTFormatting(text) {\r\n // Basic VTT tag support\r\n text = text.replace(/<c[^>]*>(.*?)<\\/c>/g, '<span class=\"caption-class\">$1</span>');\r\n text = text.replace(/<b>(.*?)<\\/b>/g, '<strong>$1</strong>');\r\n text = text.replace(/<i>(.*?)<\\/i>/g, '<em>$1</em>');\r\n text = text.replace(/<u>(.*?)<\\/u>/g, '<u>$1</u>');\r\n\r\n // Voice tags\r\n text = text.replace(/<v\\s+([^>]+)>(.*?)<\\/v>/g, '<span class=\"caption-voice\" data-voice=\"$1\">$2</span>');\r\n\r\n return text;\r\n }\r\n\r\n updateStyles() {\r\n if (!this.element) return;\r\n\r\n const options = this.player.options;\r\n\r\n this.element.style.fontSize = options.captionsFontSize;\r\n this.element.style.fontFamily = options.captionsFontFamily;\r\n this.element.style.color = options.captionsColor;\r\n this.element.style.backgroundColor = this.hexToRgba(\r\n options.captionsBackgroundColor,\r\n options.captionsOpacity\r\n );\r\n }\r\n\r\n hexToRgba(hex, alpha) {\r\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\r\n if (result) {\r\n return `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${alpha})`;\r\n }\r\n return hex;\r\n }\r\n\r\n setCaptionStyle(property, value) {\r\n switch (property) {\r\n case 'fontSize':\r\n this.player.options.captionsFontSize = value;\r\n break;\r\n case 'fontFamily':\r\n this.player.options.captionsFontFamily = value;\r\n break;\r\n case 'color':\r\n this.player.options.captionsColor = value;\r\n break;\r\n case 'backgroundColor':\r\n this.player.options.captionsBackgroundColor = value;\r\n break;\r\n case 'opacity':\r\n this.player.options.captionsOpacity = value;\r\n break;\r\n }\r\n\r\n this.updateStyles();\r\n this.saveCaptionPreferences();\r\n this.player.emit('captionschange');\r\n }\r\n\r\n getAvailableTracks() {\r\n return this.tracks.map((t, index) => ({\r\n index,\r\n language: t.language,\r\n label: t.label || t.language,\r\n kind: t.kind\r\n }));\r\n }\r\n\r\n switchTrack(trackIndex) {\r\n if (trackIndex >= 0 && trackIndex < this.tracks.length) {\r\n this.disable();\r\n this.enable(trackIndex);\r\n }\r\n }\r\n\r\n destroy() {\r\n this.disable();\r\n\r\n if (this.element && this.element.parentNode) {\r\n this.element.parentNode.removeChild(this.element);\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * Keyboard Accessibility Manager\r\n */\r\n\r\nexport class KeyboardManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.shortcuts = player.options.keyboardShortcuts;\r\n \r\n this.init();\r\n }\r\n\r\n init() {\r\n this.attachEvents();\r\n }\r\n\r\n attachEvents() {\r\n // Listen for keyboard events on the player container\r\n this.player.container.addEventListener('keydown', (e) => {\r\n this.handleKeydown(e);\r\n });\r\n\r\n // Make player container focusable\r\n if (!this.player.container.hasAttribute('tabindex')) {\r\n this.player.container.setAttribute('tabindex', '0');\r\n }\r\n }\r\n\r\n handleKeydown(e) {\r\n // Don't handle if target is an input element\r\n if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {\r\n return;\r\n }\r\n\r\n const key = e.key;\r\n let handled = false;\r\n\r\n // Check each shortcut category\r\n for (const [action, keys] of Object.entries(this.shortcuts)) {\r\n if (keys.includes(key)) {\r\n handled = this.executeAction(action, e);\r\n if (handled) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.announceAction(action);\r\n break;\r\n }\r\n }\r\n }\r\n \r\n // Log unhandled keys for debugging (in development)\r\n if (!handled && this.player.options.debug) {\r\n console.log('[VidPly] Unhandled key:', e.key, 'code:', e.code, 'shiftKey:', e.shiftKey);\r\n }\r\n }\r\n\r\n executeAction(action, event) {\r\n switch (action) {\r\n case 'play-pause':\r\n this.player.toggle();\r\n return true;\r\n\r\n case 'volume-up':\r\n this.player.setVolume(Math.min(1, this.player.state.volume + 0.1));\r\n return true;\r\n\r\n case 'volume-down':\r\n this.player.setVolume(Math.max(0, this.player.state.volume - 0.1));\r\n return true;\r\n\r\n case 'seek-forward':\r\n this.player.seekForward();\r\n return true;\r\n\r\n case 'seek-backward':\r\n this.player.seekBackward();\r\n return true;\r\n\r\n case 'mute':\r\n this.player.toggleMute();\r\n return true;\r\n\r\n case 'fullscreen':\r\n this.player.toggleFullscreen();\r\n return true;\r\n\r\n case 'captions':\r\n // If only one caption track, toggle on/off\r\n // If multiple tracks, open caption menu\r\n if (this.player.captionManager && this.player.captionManager.tracks.length > 1) {\r\n // Get captions button from control bar\r\n const captionsButton = this.player.controlBar && this.player.controlBar.controls.captions;\r\n if (captionsButton) {\r\n this.player.controlBar.showCaptionsMenu(captionsButton);\r\n } else {\r\n // Fallback to toggle if button doesn't exist\r\n this.player.toggleCaptions();\r\n }\r\n } else {\r\n this.player.toggleCaptions();\r\n }\r\n return true;\r\n\r\n case 'caption-style-menu':\r\n // Open caption style menu\r\n if (this.player.controlBar && this.player.controlBar.controls.captionStyle) {\r\n this.player.controlBar.showCaptionStyleMenu(this.player.controlBar.controls.captionStyle);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'speed-up':\r\n this.player.setPlaybackSpeed(\r\n Math.min(2, this.player.state.playbackSpeed + 0.25)\r\n );\r\n return true;\r\n\r\n case 'speed-down':\r\n this.player.setPlaybackSpeed(\r\n Math.max(0.25, this.player.state.playbackSpeed - 0.25)\r\n );\r\n return true;\r\n\r\n case 'speed-menu':\r\n // Open speed menu\r\n if (this.player.controlBar && this.player.controlBar.controls.speed) {\r\n this.player.controlBar.showSpeedMenu(this.player.controlBar.controls.speed);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'quality-menu':\r\n // Open quality menu\r\n if (this.player.controlBar && this.player.controlBar.controls.quality) {\r\n this.player.controlBar.showQualityMenu(this.player.controlBar.controls.quality);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'chapters-menu':\r\n // Open chapters menu\r\n if (this.player.controlBar && this.player.controlBar.controls.chapters) {\r\n this.player.controlBar.showChaptersMenu(this.player.controlBar.controls.chapters);\r\n return true;\r\n }\r\n return false;\r\n\r\n case 'transcript-toggle':\r\n // Toggle transcript\r\n if (this.player.transcriptManager) {\r\n this.player.transcriptManager.toggleTranscript();\r\n return true;\r\n }\r\n return false;\r\n\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n announceAction(action) {\r\n if (!this.player.options.screenReaderAnnouncements) return;\r\n\r\n let message = '';\r\n\r\n switch (action) {\r\n case 'play-pause':\r\n message = this.player.state.playing ? 'Playing' : 'Paused';\r\n break;\r\n case 'volume-up':\r\n message = `Volume ${Math.round(this.player.state.volume * 100)}%`;\r\n break;\r\n case 'volume-down':\r\n message = `Volume ${Math.round(this.player.state.volume * 100)}%`;\r\n break;\r\n case 'mute':\r\n message = this.player.state.muted ? 'Muted' : 'Unmuted';\r\n break;\r\n case 'fullscreen':\r\n message = this.player.state.fullscreen ? 'Fullscreen' : 'Exit fullscreen';\r\n break;\r\n case 'captions':\r\n message = this.player.state.captionsEnabled ? 'Captions on' : 'Captions off';\r\n break;\r\n case 'speed-up':\r\n case 'speed-down':\r\n message = `Speed ${this.player.state.playbackSpeed}x`;\r\n break;\r\n }\r\n\r\n if (message) {\r\n this.announce(message);\r\n }\r\n }\r\n\r\n announce(message, priority = 'polite') {\r\n // Create or get announcement element\r\n let announcer = document.getElementById('vidply-announcer');\r\n \r\n if (!announcer) {\r\n announcer = document.createElement('div');\r\n announcer.id = 'vidply-announcer';\r\n announcer.className = 'vidply-sr-only';\r\n announcer.setAttribute('aria-live', priority);\r\n announcer.setAttribute('aria-atomic', 'true');\r\n announcer.style.cssText = `\r\n position: absolute;\r\n left: -10000px;\r\n width: 1px;\r\n height: 1px;\r\n overflow: hidden;\r\n `;\r\n document.body.appendChild(announcer);\r\n }\r\n\r\n // Clear and set new message\r\n announcer.textContent = '';\r\n setTimeout(() => {\r\n announcer.textContent = message;\r\n }, 100);\r\n }\r\n\r\n updateShortcut(action, keys) {\r\n if (Array.isArray(keys)) {\r\n this.shortcuts[action] = keys;\r\n }\r\n }\r\n\r\n destroy() {\r\n // Event listeners are automatically removed when the container is destroyed\r\n }\r\n}\r\n\r\n", "/**\r\n * Transcript Manager Component\r\n * Manages transcript display and interaction\r\n */\r\n\r\nimport { DOMUtils } from '../utils/DOMUtils.js';\r\nimport { TimeUtils } from '../utils/TimeUtils.js';\r\nimport { createIconElement } from '../icons/Icons.js';\r\nimport { i18n } from '../i18n/i18n.js';\r\nimport { StorageManager } from '../utils/StorageManager.js';\r\n\r\nexport class TranscriptManager {\r\n constructor(player) {\r\n this.player = player;\r\n this.transcriptWindow = null;\r\n this.transcriptEntries = [];\r\n this.metadataCues = [];\r\n this.currentActiveEntry = null;\r\n this.isVisible = false;\r\n \r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Dragging state\r\n this.isDragging = false;\r\n this.dragOffsetX = 0;\r\n this.dragOffsetY = 0;\r\n \r\n // Resizing state\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.resizeStartX = 0;\r\n this.resizeStartY = 0;\r\n this.resizeStartWidth = 0;\r\n this.resizeStartHeight = 0;\r\n this.resizeEnabled = false;\r\n \r\n // Settings menu state\r\n this.settingsMenuVisible = false;\r\n this.settingsMenu = null;\r\n this.settingsButton = null;\r\n this.settingsMenuJustOpened = false;\r\n \r\n // Keyboard drag mode\r\n this.keyboardDragMode = false;\r\n \r\n // Style dialog state\r\n this.styleDialog = null;\r\n this.styleDialogVisible = false;\r\n this.styleDialogJustOpened = false;\r\n \r\n // Language selector state\r\n this.languageSelector = null;\r\n this.currentTranscriptLanguage = null;\r\n this.availableTranscriptLanguages = [];\r\n this.languageSelectorHandler = null;\r\n \r\n // Load saved preferences from localStorage\r\n const savedPreferences = this.storage.getTranscriptPreferences();\r\n \r\n // Autoscroll state (default: true)\r\n this.autoscrollEnabled = savedPreferences?.autoscroll !== undefined ? savedPreferences.autoscroll : true;\r\n \r\n // Transcript styling options (with defaults, then player options, then saved preferences)\r\n this.transcriptStyle = {\r\n fontSize: savedPreferences?.fontSize || this.player.options.transcriptFontSize || '100%',\r\n fontFamily: savedPreferences?.fontFamily || this.player.options.transcriptFontFamily || 'sans-serif',\r\n color: savedPreferences?.color || this.player.options.transcriptColor || '#ffffff',\r\n backgroundColor: savedPreferences?.backgroundColor || this.player.options.transcriptBackgroundColor || '#1e1e1e',\r\n opacity: savedPreferences?.opacity ?? this.player.options.transcriptOpacity ?? 0.98\r\n };\r\n \r\n // Store event handlers for cleanup\r\n this.handlers = {\r\n timeupdate: () => this.updateActiveEntry(),\r\n resize: null,\r\n mousemove: null,\r\n mouseup: null,\r\n touchmove: null,\r\n touchend: null,\r\n mousedown: null,\r\n touchstart: null,\r\n keydown: null,\r\n settingsClick: null,\r\n settingsKeydown: null,\r\n documentClick: null,\r\n styleDialogKeydown: null\r\n };\r\n \r\n // Timeout management (for cleanup)\r\n this.timeouts = new Set();\r\n \r\n this.init();\r\n }\r\n\r\n init() {\r\n // Set up metadata handling immediately (independent of transcript display)\r\n this.setupMetadataHandlingOnLoad();\r\n \r\n // Listen for time updates to highlight active transcript entry\r\n this.player.on('timeupdate', this.handlers.timeupdate);\r\n \r\n // Reposition transcript when entering/exiting fullscreen\r\n this.player.on('fullscreenchange', () => {\r\n if (this.isVisible) {\r\n // Add a small delay to ensure DOM has updated after fullscreen transition\r\n this.setManagedTimeout(() => this.positionTranscript(), 100);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Toggle transcript window visibility\r\n */\r\n toggleTranscript() {\r\n if (this.isVisible) {\r\n this.hideTranscript();\r\n } else {\r\n this.showTranscript();\r\n }\r\n }\r\n\r\n /**\r\n * Show transcript window\r\n */\r\n showTranscript() {\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'flex';\r\n this.isVisible = true;\r\n \r\n // Focus the settings button for keyboard accessibility\r\n this.setManagedTimeout(() => {\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }, 150);\r\n return;\r\n }\r\n\r\n // Create transcript window\r\n this.createTranscriptWindow();\r\n this.loadTranscriptData();\r\n \r\n // Show the window\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'flex';\r\n // Re-position after showing (in case window was resized while hidden)\r\n this.setManagedTimeout(() => this.positionTranscript(), 0);\r\n \r\n // Focus the settings button for keyboard accessibility\r\n this.setManagedTimeout(() => {\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }, 150);\r\n }\r\n this.isVisible = true;\r\n }\r\n\r\n /**\r\n * Hide transcript window\r\n */\r\n hideTranscript() {\r\n if (this.transcriptWindow) {\r\n this.transcriptWindow.style.display = 'none';\r\n this.isVisible = false;\r\n }\r\n }\r\n\r\n /**\r\n * Create the transcript window UI\r\n */\r\n createTranscriptWindow() {\r\n this.transcriptWindow = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-window`,\r\n attributes: {\r\n 'role': 'dialog',\r\n 'aria-label': 'Video Transcript',\r\n 'tabindex': '-1'\r\n }\r\n });\r\n\r\n // Header (draggable)\r\n this.transcriptHeader = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-header`,\r\n attributes: {\r\n 'aria-label': 'Drag to reposition transcript. Use arrow keys to move, Home to reset position, Escape to close.',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Header left side (settings button + title)\r\n this.headerLeft = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-header-left`\r\n });\r\n\r\n // Settings button\r\n this.settingsButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.settings'),\r\n 'aria-expanded': 'false'\r\n }\r\n });\r\n this.settingsButton.appendChild(createIconElement('settings'));\r\n this.handlers.settingsClick = (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n } else {\r\n this.showSettingsMenu();\r\n }\r\n };\r\n this.settingsButton.addEventListener('click', this.handlers.settingsClick);\r\n \r\n // Keyboard handler for settings button\r\n this.handlers.settingsKeydown = (e) => {\r\n // D key to toggle keyboard drag mode\r\n if (e.key === 'd' || e.key === 'D') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.toggleKeyboardDragMode();\r\n }\r\n // R key to toggle resize mode\r\n else if (e.key === 'r' || e.key === 'R') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.toggleResizeMode();\r\n }\r\n // Escape to close menu if open\r\n else if (e.key === 'Escape' && this.settingsMenuVisible) {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideSettingsMenu();\r\n }\r\n };\r\n this.settingsButton.addEventListener('keydown', this.handlers.settingsKeydown);\r\n\r\n const title = DOMUtils.createElement('h3', {\r\n textContent: i18n.t('transcript.title')\r\n });\r\n\r\n // Autoscroll checkbox\r\n const autoscrollLabel = DOMUtils.createElement('label', {\r\n className: `${this.player.options.classPrefix}-transcript-autoscroll-label`,\r\n attributes: {\r\n 'title': i18n.t('transcript.autoscroll')\r\n }\r\n });\r\n \r\n this.autoscrollCheckbox = DOMUtils.createElement('input', {\r\n attributes: {\r\n 'type': 'checkbox',\r\n 'checked': this.autoscrollEnabled,\r\n 'aria-label': i18n.t('transcript.autoscroll')\r\n }\r\n });\r\n \r\n const autoscrollText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.autoscroll'),\r\n className: `${this.player.options.classPrefix}-transcript-autoscroll-text`\r\n });\r\n \r\n autoscrollLabel.appendChild(this.autoscrollCheckbox);\r\n autoscrollLabel.appendChild(autoscrollText);\r\n \r\n // Handle autoscroll checkbox change\r\n this.autoscrollCheckbox.addEventListener('change', (e) => {\r\n this.autoscrollEnabled = e.target.checked;\r\n this.saveAutoscrollPreference();\r\n });\r\n\r\n this.headerLeft.appendChild(this.settingsButton);\r\n this.headerLeft.appendChild(title);\r\n this.headerLeft.appendChild(autoscrollLabel);\r\n \r\n // Language selector (will be populated after tracks are loaded)\r\n this.languageSelector = DOMUtils.createElement('select', {\r\n className: `${this.player.options.classPrefix}-transcript-language-select`,\r\n attributes: {\r\n 'aria-label': i18n.t('settings.language') || 'Language',\r\n 'style': 'display: none;' // Hidden until we detect multiple languages\r\n }\r\n });\r\n this.headerLeft.appendChild(this.languageSelector);\r\n\r\n const closeButton = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-close`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.close')\r\n }\r\n });\r\n closeButton.appendChild(createIconElement('close'));\r\n closeButton.addEventListener('click', () => this.hideTranscript());\r\n\r\n this.transcriptHeader.appendChild(this.headerLeft);\r\n this.transcriptHeader.appendChild(closeButton);\r\n\r\n // Content container\r\n this.transcriptContent = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-content`\r\n });\r\n\r\n this.transcriptWindow.appendChild(this.transcriptHeader);\r\n this.transcriptWindow.appendChild(this.transcriptContent);\r\n\r\n // Append to player container\r\n this.player.container.appendChild(this.transcriptWindow);\r\n \r\n // Position it next to the video wrapper\r\n this.positionTranscript();\r\n \r\n // Setup drag functionality\r\n this.setupDragAndDrop();\r\n \r\n // Setup document click handler to close settings menu and style dialog\r\n // DON'T add it yet - it will be added when the menu is first opened\r\n this.handlers.documentClick = (e) => {\r\n // Ignore if menu was just opened (prevents immediate closing)\r\n if (this.settingsMenuJustOpened) {\r\n return;\r\n }\r\n \r\n // Ignore if style dialog was just opened (prevents immediate closing)\r\n if (this.styleDialogJustOpened) {\r\n return;\r\n }\r\n \r\n // Ignore clicks on the settings button itself\r\n if (this.settingsButton && this.settingsButton.contains(e.target)) {\r\n return;\r\n }\r\n \r\n // Ignore clicks on the settings menu items\r\n if (this.settingsMenu && this.settingsMenu.contains(e.target)) {\r\n return;\r\n }\r\n \r\n // Close settings menu if clicking outside\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n }\r\n \r\n // Close style dialog if clicking outside (but not on settings button)\r\n if (this.styleDialogVisible && this.styleDialog && \r\n !this.styleDialog.contains(e.target)) {\r\n this.hideStyleDialog();\r\n }\r\n };\r\n // Store flag to track if handler has been added\r\n this.documentClickHandlerAdded = false;\r\n \r\n // Re-position on window resize (debounced)\r\n let resizeTimeout;\r\n this.handlers.resize = () => {\r\n if (resizeTimeout) {\r\n this.clearManagedTimeout(resizeTimeout);\r\n }\r\n resizeTimeout = this.setManagedTimeout(() => this.positionTranscript(), 100);\r\n };\r\n window.addEventListener('resize', this.handlers.resize);\r\n }\r\n \r\n /**\r\n * Position transcript window next to video\r\n */\r\n positionTranscript() {\r\n if (!this.transcriptWindow || !this.player.videoWrapper || !this.isVisible) return;\r\n \r\n const isMobile = window.innerWidth < 640;\r\n const videoRect = this.player.videoWrapper.getBoundingClientRect();\r\n \r\n // Check if player is in fullscreen mode\r\n const isFullscreen = this.player.state.fullscreen;\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile: Position underneath the video and controls as part of the layout\r\n this.transcriptWindow.style.position = 'relative';\r\n this.transcriptWindow.style.left = '0';\r\n this.transcriptWindow.style.right = '0';\r\n this.transcriptWindow.style.bottom = 'auto';\r\n this.transcriptWindow.style.top = 'auto';\r\n this.transcriptWindow.style.width = '100%';\r\n this.transcriptWindow.style.maxWidth = '100%';\r\n this.transcriptWindow.style.maxHeight = '400px';\r\n this.transcriptWindow.style.height = 'auto';\r\n this.transcriptWindow.style.borderRadius = '0';\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.border = 'none';\r\n this.transcriptWindow.style.borderTop = '1px solid var(--vidply-border-light)';\r\n this.transcriptWindow.style.boxShadow = 'none';\r\n // Disable dragging on mobile\r\n if (this.transcriptHeader) {\r\n this.transcriptHeader.style.cursor = 'default';\r\n }\r\n \r\n // Ensure transcript is at the container level for proper stacking\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n } else if (isFullscreen) {\r\n // In fullscreen: position in bottom right corner inside the video\r\n this.transcriptWindow.style.position = 'fixed';\r\n this.transcriptWindow.style.left = 'auto';\r\n this.transcriptWindow.style.right = '20px';\r\n this.transcriptWindow.style.bottom = '80px'; // Above controls\r\n this.transcriptWindow.style.top = 'auto';\r\n this.transcriptWindow.style.maxHeight = 'calc(100vh - 180px)'; // Leave space for controls\r\n this.transcriptWindow.style.height = 'auto';\r\n this.transcriptWindow.style.width = '400px';\r\n this.transcriptWindow.style.maxWidth = '400px';\r\n this.transcriptWindow.style.borderRadius = '8px';\r\n this.transcriptWindow.style.border = '1px solid var(--vidply-border)';\r\n this.transcriptWindow.style.borderTop = '';\r\n \r\n // Move back to container for fullscreen\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n } else {\r\n // Desktop mode: position next to video\r\n this.transcriptWindow.style.position = 'absolute';\r\n this.transcriptWindow.style.left = `${videoRect.width + 8}px`;\r\n this.transcriptWindow.style.right = 'auto';\r\n this.transcriptWindow.style.bottom = 'auto';\r\n this.transcriptWindow.style.top = '0';\r\n this.transcriptWindow.style.height = `${videoRect.height}px`;\r\n this.transcriptWindow.style.maxHeight = 'none';\r\n this.transcriptWindow.style.width = '400px';\r\n this.transcriptWindow.style.maxWidth = '400px';\r\n this.transcriptWindow.style.borderRadius = '8px';\r\n this.transcriptWindow.style.border = '1px solid var(--vidply-border)';\r\n this.transcriptWindow.style.borderTop = '';\r\n // Enable dragging on desktop\r\n if (this.transcriptHeader) {\r\n this.transcriptHeader.style.cursor = 'move';\r\n }\r\n \r\n // Move back to container for desktop\r\n if (this.transcriptWindow.parentNode !== this.player.container) {\r\n this.player.container.appendChild(this.transcriptWindow);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get available transcript languages from tracks\r\n */\r\n getAvailableTranscriptLanguages() {\r\n const textTracks = this.player.textTracks;\r\n const languages = new Map();\r\n \r\n // Collect all caption/subtitle tracks with their languages\r\n textTracks.forEach(track => {\r\n if ((track.kind === 'captions' || track.kind === 'subtitles') && track.language) {\r\n if (!languages.has(track.language)) {\r\n languages.set(track.language, {\r\n language: track.language,\r\n label: track.label || track.language,\r\n track: track\r\n });\r\n }\r\n }\r\n });\r\n \r\n return Array.from(languages.values());\r\n }\r\n\r\n /**\r\n * Update language selector dropdown\r\n */\r\n updateLanguageSelector() {\r\n if (!this.languageSelector) return;\r\n \r\n this.availableTranscriptLanguages = this.getAvailableTranscriptLanguages();\r\n \r\n // Clear existing options\r\n this.languageSelector.innerHTML = '';\r\n \r\n // Only show selector if there are 2+ languages\r\n if (this.availableTranscriptLanguages.length < 2) {\r\n this.languageSelector.style.display = 'none';\r\n return;\r\n }\r\n \r\n // Show selector and populate options\r\n this.languageSelector.style.display = 'block';\r\n \r\n this.availableTranscriptLanguages.forEach((langInfo, index) => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: langInfo.label,\r\n attributes: {\r\n 'value': langInfo.language\r\n }\r\n });\r\n this.languageSelector.appendChild(option);\r\n });\r\n \r\n // Set current selection\r\n if (this.currentTranscriptLanguage) {\r\n this.languageSelector.value = this.currentTranscriptLanguage;\r\n } else if (this.availableTranscriptLanguages.length > 0) {\r\n // Default to first language or active track\r\n const activeTrack = this.player.textTracks.find(\r\n track => (track.kind === 'captions' || track.kind === 'subtitles') && track.mode === 'showing'\r\n );\r\n this.currentTranscriptLanguage = activeTrack ? activeTrack.language : this.availableTranscriptLanguages[0].language;\r\n this.languageSelector.value = this.currentTranscriptLanguage;\r\n }\r\n \r\n // Remove existing change listener if any\r\n if (this.languageSelectorHandler) {\r\n this.languageSelector.removeEventListener('change', this.languageSelectorHandler);\r\n }\r\n \r\n // Handle language change\r\n this.languageSelectorHandler = (e) => {\r\n this.currentTranscriptLanguage = e.target.value;\r\n this.loadTranscriptData();\r\n };\r\n this.languageSelector.addEventListener('change', this.languageSelectorHandler);\r\n }\r\n\r\n /**\r\n * Load transcript data from caption/subtitle tracks\r\n */\r\n loadTranscriptData() {\r\n this.transcriptEntries = [];\r\n this.transcriptContent.innerHTML = '';\r\n\r\n // Get all text tracks\r\n const textTracks = this.player.textTracks;\r\n \r\n // Find track for selected language, or default to first available\r\n let captionTrack = null;\r\n if (this.currentTranscriptLanguage) {\r\n captionTrack = textTracks.find(\r\n track => (track.kind === 'captions' || track.kind === 'subtitles') && \r\n track.language === this.currentTranscriptLanguage\r\n );\r\n }\r\n \r\n // Fallback to first available caption/subtitle track\r\n if (!captionTrack) {\r\n captionTrack = textTracks.find(\r\n track => track.kind === 'captions' || track.kind === 'subtitles'\r\n );\r\n if (captionTrack) {\r\n this.currentTranscriptLanguage = captionTrack.language;\r\n }\r\n }\r\n \r\n // Find description track matching the selected language\r\n let descriptionTrack = null;\r\n if (this.currentTranscriptLanguage) {\r\n descriptionTrack = textTracks.find(\r\n track => track.kind === 'descriptions' && track.language === this.currentTranscriptLanguage\r\n );\r\n }\r\n // Fallback to first available description track if no match found\r\n if (!descriptionTrack) {\r\n descriptionTrack = textTracks.find(track => track.kind === 'descriptions');\r\n }\r\n \r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n\r\n // We need at least one track type\r\n if (!captionTrack && !descriptionTrack && !metadataTrack) {\r\n this.showNoTranscriptMessage();\r\n return;\r\n }\r\n\r\n // Enable all tracks to load cues\r\n const tracksToLoad = [captionTrack, descriptionTrack, metadataTrack].filter(Boolean);\r\n tracksToLoad.forEach(track => {\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n });\r\n\r\n // Check if any tracks are still loading\r\n const needsLoading = tracksToLoad.some(track => !track.cues || track.cues.length === 0);\r\n \r\n if (needsLoading) {\r\n // Wait for cues to load\r\n const loadingMessage = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-loading`,\r\n textContent: i18n.t('transcript.loading')\r\n });\r\n this.transcriptContent.appendChild(loadingMessage);\r\n\r\n let loaded = 0;\r\n const onLoad = () => {\r\n loaded++;\r\n if (loaded >= tracksToLoad.length) {\r\n this.loadTranscriptData();\r\n }\r\n };\r\n\r\n tracksToLoad.forEach(track => {\r\n track.addEventListener('load', onLoad, { once: true });\r\n });\r\n\r\n // Fallback timeout\r\n this.setManagedTimeout(() => {\r\n this.loadTranscriptData();\r\n }, 500);\r\n \r\n return;\r\n }\r\n\r\n // Collect all cues from all tracks with their type\r\n const allCues = [];\r\n \r\n if (captionTrack && captionTrack.cues) {\r\n Array.from(captionTrack.cues).forEach(cue => {\r\n allCues.push({ cue, type: 'caption' });\r\n });\r\n }\r\n \r\n if (descriptionTrack && descriptionTrack.cues) {\r\n Array.from(descriptionTrack.cues).forEach(cue => {\r\n allCues.push({ cue, type: 'description' });\r\n });\r\n }\r\n \r\n // Store metadata separately for programmatic use (don't display in transcript)\r\n if (metadataTrack && metadataTrack.cues) {\r\n this.metadataCues = Array.from(metadataTrack.cues);\r\n this.setupMetadataHandling();\r\n }\r\n\r\n // Sort all cues by start time\r\n allCues.sort((a, b) => a.cue.startTime - b.cue.startTime);\r\n\r\n // Build transcript from captions and descriptions only\r\n allCues.forEach((item, index) => {\r\n const entry = this.createTranscriptEntry(item.cue, index, item.type);\r\n this.transcriptEntries.push({\r\n element: entry,\r\n cue: item.cue,\r\n type: item.type,\r\n startTime: item.cue.startTime,\r\n endTime: item.cue.endTime\r\n });\r\n this.transcriptContent.appendChild(entry);\r\n });\r\n \r\n // Apply current styles to newly loaded entries\r\n this.applyTranscriptStyles();\r\n \r\n // Update language selector after loading\r\n this.updateLanguageSelector();\r\n }\r\n\r\n /**\r\n * Setup metadata handling on player load\r\n * This runs independently of transcript loading\r\n */\r\n setupMetadataHandlingOnLoad() {\r\n // Wait for metadata to be loaded\r\n const setupMetadata = () => {\r\n const textTracks = this.player.textTracks;\r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n \r\n if (metadataTrack) {\r\n // Enable the metadata track so cuechange events fire\r\n // Use 'hidden' mode so it doesn't display anything, but events still work\r\n if (metadataTrack.mode === 'disabled') {\r\n metadataTrack.mode = 'hidden';\r\n }\r\n \r\n // Check if we already added the listener\r\n if (this.metadataCueChangeHandler) {\r\n metadataTrack.removeEventListener('cuechange', this.metadataCueChangeHandler);\r\n }\r\n \r\n // Add event listener for cue changes\r\n this.metadataCueChangeHandler = () => {\r\n const activeCues = Array.from(metadataTrack.activeCues || []);\r\n if (activeCues.length > 0) {\r\n // Debug logging (can be removed in production)\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata] Active cues:', activeCues.map(c => ({\r\n start: c.startTime,\r\n end: c.endTime,\r\n text: c.text\r\n })));\r\n }\r\n }\r\n activeCues.forEach(cue => {\r\n this.handleMetadataCue(cue);\r\n });\r\n };\r\n \r\n metadataTrack.addEventListener('cuechange', this.metadataCueChangeHandler);\r\n \r\n // Debug: Log metadata track setup\r\n if (this.player.options.debug) {\r\n const cueCount = metadataTrack.cues ? metadataTrack.cues.length : 0;\r\n console.log('[VidPly Metadata] Track enabled,', cueCount, 'cues available');\r\n }\r\n } else if (this.player.options.debug) {\r\n console.warn('[VidPly Metadata] No metadata track found');\r\n }\r\n };\r\n \r\n // Try immediately\r\n setupMetadata();\r\n \r\n // Also try after loadedmetadata event\r\n this.player.on('loadedmetadata', setupMetadata);\r\n }\r\n\r\n /**\r\n * Setup metadata handling\r\n * Metadata cues are not displayed but can be used programmatically\r\n * This is called when transcript data is loaded (for storing cues)\r\n */\r\n setupMetadataHandling() {\r\n if (!this.metadataCues || this.metadataCues.length === 0) {\r\n return;\r\n }\r\n\r\n // The actual event handling is set up in setupMetadataHandlingOnLoad()\r\n // This method just stores the cues for reference\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata]', this.metadataCues.length, 'cues stored from transcript load');\r\n }\r\n }\r\n\r\n /**\r\n * Handle individual metadata cues\r\n * Parses metadata text and emits events or triggers actions\r\n */\r\n handleMetadataCue(cue) {\r\n const text = cue.text.trim();\r\n \r\n // Debug logging\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata] Processing cue:', {\r\n time: cue.startTime,\r\n text: text\r\n });\r\n }\r\n \r\n // Emit a generic metadata event that developers can listen to\r\n this.player.emit('metadata', {\r\n time: cue.startTime,\r\n endTime: cue.endTime,\r\n text: text,\r\n cue: cue\r\n });\r\n\r\n // Parse for specific commands (examples based on wwa_meta.vtt format)\r\n if (text.includes('PAUSE')) {\r\n // Automatically pause the video\r\n if (!this.player.state.paused) {\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata] Pausing video at', cue.startTime);\r\n }\r\n this.player.pause();\r\n }\r\n // Also emit event for developers who want to listen\r\n this.player.emit('metadata:pause', { time: cue.startTime, text: text });\r\n }\r\n\r\n // Parse for focus directives\r\n const focusMatch = text.match(/FOCUS:([\\w#-]+)/);\r\n if (focusMatch) {\r\n const targetSelector = focusMatch[1];\r\n // Automatically focus the target element\r\n const targetElement = document.querySelector(targetSelector);\r\n if (targetElement) {\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata] Focusing element:', targetSelector);\r\n }\r\n // Use setTimeout to ensure DOM is ready\r\n this.setManagedTimeout(() => {\r\n targetElement.focus();\r\n }, 10);\r\n } else if (this.player.options.debug) {\r\n console.warn('[VidPly Metadata] Element not found:', targetSelector);\r\n }\r\n // Also emit event for developers who want to listen\r\n this.player.emit('metadata:focus', { \r\n time: cue.startTime, \r\n target: targetSelector,\r\n element: targetElement,\r\n text: text \r\n });\r\n }\r\n\r\n // Parse for hashtag references\r\n const hashtags = text.match(/#[\\w-]+/g);\r\n if (hashtags) {\r\n if (this.player.options.debug) {\r\n console.log('[VidPly Metadata] Hashtags found:', hashtags);\r\n }\r\n this.player.emit('metadata:hashtags', {\r\n time: cue.startTime,\r\n hashtags: hashtags,\r\n text: text\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Create a single transcript entry element\r\n */\r\n createTranscriptEntry(cue, index, type = 'caption') {\r\n const entry = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-entry ${this.player.options.classPrefix}-transcript-${type}`,\r\n attributes: {\r\n 'data-start': String(cue.startTime),\r\n 'data-end': String(cue.endTime),\r\n 'data-type': type,\r\n 'role': 'button',\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n const timestamp = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-transcript-time`,\r\n textContent: TimeUtils.formatTime(cue.startTime)\r\n });\r\n\r\n const text = DOMUtils.createElement('span', {\r\n className: `${this.player.options.classPrefix}-transcript-text`,\r\n textContent: this.stripVTTFormatting(cue.text)\r\n });\r\n\r\n entry.appendChild(timestamp);\r\n entry.appendChild(text);\r\n\r\n // Click to seek\r\n const seekToTime = () => {\r\n this.player.seek(cue.startTime);\r\n if (this.player.state.paused) {\r\n this.player.play();\r\n }\r\n };\r\n\r\n entry.addEventListener('click', seekToTime);\r\n entry.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n seekToTime();\r\n }\r\n });\r\n\r\n return entry;\r\n }\r\n\r\n /**\r\n * Strip VTT formatting tags from text\r\n */\r\n stripVTTFormatting(text) {\r\n // Remove VTT tags like <v Speaker>, <c>, etc.\r\n return text\r\n .replace(/<[^>]+>/g, '')\r\n .replace(/\\n/g, ' ')\r\n .trim();\r\n }\r\n\r\n /**\r\n * Show message when no transcript is available\r\n */\r\n showNoTranscriptMessage() {\r\n const message = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-empty`,\r\n textContent: i18n.t('transcript.noTranscript')\r\n });\r\n this.transcriptContent.appendChild(message);\r\n }\r\n\r\n /**\r\n * Update active transcript entry based on current time\r\n */\r\n updateActiveEntry() {\r\n if (!this.isVisible || this.transcriptEntries.length === 0) return;\r\n\r\n const currentTime = this.player.state.currentTime;\r\n \r\n // Find the entry that matches current time\r\n const activeEntry = this.transcriptEntries.find(\r\n entry => currentTime >= entry.startTime && currentTime < entry.endTime\r\n );\r\n\r\n if (activeEntry && activeEntry !== this.currentActiveEntry) {\r\n // Remove previous active class\r\n if (this.currentActiveEntry) {\r\n this.currentActiveEntry.element.classList.remove(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n }\r\n\r\n // Add active class to current entry\r\n activeEntry.element.classList.add(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n \r\n // Scroll to active entry\r\n this.scrollToEntry(activeEntry.element);\r\n \r\n this.currentActiveEntry = activeEntry;\r\n } else if (!activeEntry && this.currentActiveEntry) {\r\n // No active entry, remove active class\r\n this.currentActiveEntry.element.classList.remove(\r\n `${this.player.options.classPrefix}-transcript-entry-active`\r\n );\r\n this.currentActiveEntry = null;\r\n }\r\n }\r\n\r\n /**\r\n * Scroll transcript window to show active entry\r\n */\r\n scrollToEntry(entryElement) {\r\n if (!this.transcriptContent || !this.autoscrollEnabled) return;\r\n\r\n const contentRect = this.transcriptContent.getBoundingClientRect();\r\n const entryRect = entryElement.getBoundingClientRect();\r\n\r\n // Check if entry is out of view\r\n if (entryRect.top < contentRect.top || entryRect.bottom > contentRect.bottom) {\r\n // Scroll to center the entry\r\n const scrollTop = entryElement.offsetTop - (this.transcriptContent.clientHeight / 2) + (entryElement.clientHeight / 2);\r\n this.transcriptContent.scrollTo({\r\n top: scrollTop,\r\n behavior: 'smooth'\r\n });\r\n }\r\n }\r\n \r\n /**\r\n * Save autoscroll preference to localStorage\r\n */\r\n saveAutoscrollPreference() {\r\n const savedPreferences = this.storage.getTranscriptPreferences() || {};\r\n savedPreferences.autoscroll = this.autoscrollEnabled;\r\n this.storage.saveTranscriptPreferences(savedPreferences);\r\n }\r\n\r\n /**\r\n * Setup drag and drop functionality\r\n */\r\n setupDragAndDrop() {\r\n if (!this.transcriptHeader || !this.transcriptWindow) return;\r\n\r\n // Create and store handler functions\r\n this.handlers.mousedown = (e) => {\r\n // Don't drag if clicking on close button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-close`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on settings button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on language selector\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-language-select`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on settings menu\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings-menu`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if clicking on style dialog\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-style-dialog`)) {\r\n return;\r\n }\r\n \r\n this.startDragging(e.clientX, e.clientY);\r\n e.preventDefault();\r\n };\r\n\r\n this.handlers.mousemove = (e) => {\r\n if (this.isDragging) {\r\n this.drag(e.clientX, e.clientY);\r\n }\r\n };\r\n\r\n this.handlers.mouseup = () => {\r\n if (this.isDragging) {\r\n this.stopDragging();\r\n }\r\n };\r\n\r\n this.handlers.touchstart = (e) => {\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-close`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching settings button\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching language selector\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-language-select`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching settings menu\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-settings-menu`)) {\r\n return;\r\n }\r\n \r\n // Don't drag if touching style dialog\r\n if (e.target.closest(`.${this.player.options.classPrefix}-transcript-style-dialog`)) {\r\n return;\r\n }\r\n \r\n const isMobile = window.innerWidth < 640;\r\n const isFullscreen = this.player.state.fullscreen;\r\n const touch = e.touches[0];\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile (not fullscreen): No dragging/swiping, transcript is part of layout\r\n return;\r\n } else {\r\n // Desktop or fullscreen: Normal dragging\r\n this.startDragging(touch.clientX, touch.clientY);\r\n }\r\n };\r\n\r\n this.handlers.touchmove = (e) => {\r\n const isMobile = window.innerWidth < 640;\r\n const isFullscreen = this.player.state.fullscreen;\r\n \r\n if (isMobile && !isFullscreen) {\r\n // Mobile (not fullscreen): No dragging/swiping\r\n return;\r\n } else if (this.isDragging) {\r\n // Desktop or fullscreen: Normal drag\r\n const touch = e.touches[0];\r\n this.drag(touch.clientX, touch.clientY);\r\n e.preventDefault();\r\n }\r\n };\r\n\r\n this.handlers.touchend = () => {\r\n if (this.isDragging) {\r\n // Stop dragging\r\n this.stopDragging();\r\n }\r\n };\r\n\r\n this.handlers.keydown = (e) => {\r\n // Handle arrow keys only in keyboard drag mode\r\n if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {\r\n if (!this.keyboardDragMode) {\r\n // Not in drag mode, let other handlers deal with it\r\n return;\r\n }\r\n \r\n // In drag mode - move the window\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const step = e.shiftKey ? 50 : 10; // Larger steps with Shift key\r\n \r\n // Get current position\r\n let currentLeft = parseFloat(this.transcriptWindow.style.left) || 0;\r\n let currentTop = parseFloat(this.transcriptWindow.style.top) || 0;\r\n \r\n // If window is still centered with transform, convert to absolute position first\r\n const computedStyle = window.getComputedStyle(this.transcriptWindow);\r\n if (computedStyle.transform !== 'none') {\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n currentLeft = rect.left;\r\n currentTop = rect.top;\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.left = `${currentLeft}px`;\r\n this.transcriptWindow.style.top = `${currentTop}px`;\r\n }\r\n \r\n // Calculate new position based on arrow key\r\n let newX = currentLeft;\r\n let newY = currentTop;\r\n\r\n switch(e.key) {\r\n case 'ArrowLeft':\r\n newX -= step;\r\n break;\r\n case 'ArrowRight':\r\n newX += step;\r\n break;\r\n case 'ArrowUp':\r\n newY -= step;\r\n break;\r\n case 'ArrowDown':\r\n newY += step;\r\n break;\r\n }\r\n\r\n // Set new position directly\r\n this.transcriptWindow.style.left = `${newX}px`;\r\n this.transcriptWindow.style.top = `${newY}px`;\r\n return;\r\n }\r\n \r\n // Handle other special keys\r\n if (e.key === 'Home') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.resetPosition();\r\n return;\r\n }\r\n \r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.styleDialogVisible) {\r\n // Close style dialog first\r\n this.hideStyleDialog();\r\n } else if (this.keyboardDragMode) {\r\n // Exit drag mode\r\n this.disableKeyboardDragMode();\r\n } else if (this.settingsMenuVisible) {\r\n // Close settings menu\r\n this.hideSettingsMenu();\r\n } else {\r\n // Close transcript\r\n this.hideTranscript();\r\n }\r\n return;\r\n }\r\n };\r\n\r\n // Add event listeners using stored handlers\r\n this.transcriptHeader.addEventListener('mousedown', this.handlers.mousedown);\r\n document.addEventListener('mousemove', this.handlers.mousemove);\r\n document.addEventListener('mouseup', this.handlers.mouseup);\r\n \r\n this.transcriptHeader.addEventListener('touchstart', this.handlers.touchstart);\r\n document.addEventListener('touchmove', this.handlers.touchmove);\r\n document.addEventListener('touchend', this.handlers.touchend);\r\n \r\n this.transcriptHeader.addEventListener('keydown', this.handlers.keydown);\r\n }\r\n\r\n /**\r\n * Start dragging\r\n */\r\n startDragging(clientX, clientY) {\r\n // Get current rendered position (this is where it actually appears on screen)\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n \r\n // Get the parent container position (player container)\r\n const containerRect = this.player.container.getBoundingClientRect();\r\n \r\n // Calculate position RELATIVE to container (not viewport)\r\n const relativeLeft = rect.left - containerRect.left;\r\n const relativeTop = rect.top - containerRect.top;\r\n \r\n // If window is centered with transform, convert to absolute position\r\n const computedStyle = window.getComputedStyle(this.transcriptWindow);\r\n if (computedStyle.transform !== 'none') {\r\n // Remove transform and set position relative to container\r\n this.transcriptWindow.style.transform = 'none';\r\n this.transcriptWindow.style.left = `${relativeLeft}px`;\r\n this.transcriptWindow.style.top = `${relativeTop}px`;\r\n }\r\n \r\n // Calculate offset based on viewport coordinates (where user clicked)\r\n this.dragOffsetX = clientX - rect.left;\r\n this.dragOffsetY = clientY - rect.top;\r\n \r\n this.isDragging = true;\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-dragging`);\r\n document.body.style.cursor = 'grabbing';\r\n document.body.style.userSelect = 'none';\r\n }\r\n\r\n /**\r\n * Perform drag\r\n */\r\n drag(clientX, clientY) {\r\n if (!this.isDragging) return;\r\n\r\n // Calculate new viewport position based on mouse position minus the offset\r\n const newViewportX = clientX - this.dragOffsetX;\r\n const newViewportY = clientY - this.dragOffsetY;\r\n \r\n // Convert to position relative to container\r\n const containerRect = this.player.container.getBoundingClientRect();\r\n const newX = newViewportX - containerRect.left;\r\n const newY = newViewportY - containerRect.top;\r\n \r\n // During drag, set position relative to container\r\n this.transcriptWindow.style.left = `${newX}px`;\r\n this.transcriptWindow.style.top = `${newY}px`;\r\n }\r\n\r\n /**\r\n * Stop dragging\r\n */\r\n stopDragging() {\r\n this.isDragging = false;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-dragging`);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n }\r\n\r\n /**\r\n * Set window position with boundary constraints\r\n */\r\n setPosition(x, y) {\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n \r\n // Use document dimensions for fixed positioning\r\n const viewportWidth = document.documentElement.clientWidth;\r\n const viewportHeight = document.documentElement.clientHeight;\r\n \r\n // Very relaxed boundaries - allow window to go mostly off-screen\r\n // Just keep a small part visible so user can always drag it back\r\n const minVisible = 100; // Keep at least 100px visible\r\n const minX = -(rect.width - minVisible); // Can go way off-screen to the left\r\n const minY = -(rect.height - minVisible); // Can go way off-screen to the top\r\n const maxX = viewportWidth - minVisible; // Can go way off-screen to the right\r\n const maxY = viewportHeight - minVisible; // Can go way off-screen to the bottom\r\n \r\n // Clamp position to boundaries (very loose)\r\n x = Math.max(minX, Math.min(x, maxX));\r\n y = Math.max(minY, Math.min(y, maxY));\r\n \r\n this.transcriptWindow.style.left = `${x}px`;\r\n this.transcriptWindow.style.top = `${y}px`;\r\n this.transcriptWindow.style.transform = 'none';\r\n }\r\n\r\n /**\r\n * Reset position to center\r\n */\r\n resetPosition() {\r\n this.transcriptWindow.style.left = '50%';\r\n this.transcriptWindow.style.top = '50%';\r\n this.transcriptWindow.style.transform = 'translate(-50%, -50%)';\r\n }\r\n\r\n /**\r\n * Toggle keyboard drag mode\r\n */\r\n toggleKeyboardDragMode() {\r\n if (this.keyboardDragMode) {\r\n this.disableKeyboardDragMode();\r\n } else {\r\n this.enableKeyboardDragMode();\r\n }\r\n }\r\n\r\n /**\r\n * Enable keyboard drag mode\r\n */\r\n enableKeyboardDragMode() {\r\n this.keyboardDragMode = true;\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-keyboard-drag`);\r\n \r\n // Update settings button aria label\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-label', 'Keyboard drag mode active. Use arrow keys to move window. Press D or Escape to exit.');\r\n }\r\n \r\n // Add visual indicator\r\n const indicator = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-drag-indicator`,\r\n textContent: i18n.t('transcript.keyboardDragActive')\r\n });\r\n this.transcriptHeader.appendChild(indicator);\r\n \r\n // Hide settings menu if open\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n }\r\n \r\n // Focus the header for keyboard navigation\r\n this.transcriptHeader.focus();\r\n }\r\n\r\n /**\r\n * Disable keyboard drag mode\r\n */\r\n disableKeyboardDragMode() {\r\n this.keyboardDragMode = false;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-keyboard-drag`);\r\n \r\n // Update settings button aria label\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-label', 'Transcript settings. Press Enter to open menu, or D to enable drag mode');\r\n }\r\n \r\n // Remove visual indicator\r\n const indicator = this.transcriptHeader.querySelector(`.${this.player.options.classPrefix}-transcript-drag-indicator`);\r\n if (indicator) {\r\n indicator.remove();\r\n }\r\n \r\n // Focus back to settings button\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }\r\n\r\n /**\r\n * Toggle settings menu visibility\r\n */\r\n toggleSettingsMenu() {\r\n if (this.settingsMenuVisible) {\r\n this.hideSettingsMenu();\r\n } else {\r\n this.showSettingsMenu();\r\n }\r\n }\r\n\r\n /**\r\n * Show settings menu\r\n */\r\n showSettingsMenu() {\r\n // Set flag to prevent immediate closing\r\n this.settingsMenuJustOpened = true;\r\n setTimeout(() => {\r\n this.settingsMenuJustOpened = false;\r\n }, 350);\r\n \r\n // Add document click handler on FIRST menu open (not at window creation)\r\n if (!this.documentClickHandlerAdded) {\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handlers.documentClick);\r\n this.documentClickHandlerAdded = true;\r\n }, 300);\r\n }\r\n \r\n if (this.settingsMenu) {\r\n this.settingsMenu.style.display = 'block';\r\n this.settingsMenuVisible = true;\r\n return;\r\n }\r\n // Create settings menu\r\n this.settingsMenu = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-menu`\r\n });\r\n\r\n // Keyboard drag option\r\n const keyboardDragOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.keyboardDragMode')\r\n }\r\n });\r\n const keyboardIcon = createIconElement('move');\r\n const keyboardText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.keyboardDragMode')\r\n });\r\n keyboardDragOption.appendChild(keyboardIcon);\r\n keyboardDragOption.appendChild(keyboardText);\r\n keyboardDragOption.addEventListener('click', () => {\r\n this.toggleKeyboardDragMode();\r\n this.hideSettingsMenu();\r\n });\r\n \r\n // Style option\r\n const styleOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.styleTranscript')\r\n }\r\n });\r\n const styleIcon = createIconElement('settings');\r\n const styleText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.styleTranscript')\r\n });\r\n styleOption.appendChild(styleIcon);\r\n styleOption.appendChild(styleText);\r\n styleOption.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideSettingsMenu();\r\n // Delay to ensure menu is fully closed before opening dialog\r\n setTimeout(() => {\r\n this.showStyleDialog();\r\n }, 50);\r\n });\r\n\r\n // Resize option\r\n const resizeOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.resizeWindow')\r\n }\r\n });\r\n const resizeIcon = createIconElement('resize');\r\n const resizeText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.resizeWindow')\r\n });\r\n resizeOption.appendChild(resizeIcon);\r\n resizeOption.appendChild(resizeText);\r\n resizeOption.addEventListener('click', () => {\r\n this.toggleResizeMode();\r\n this.hideSettingsMenu();\r\n });\r\n\r\n // Close option\r\n const closeOption = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-settings-item`,\r\n attributes: {\r\n 'type': 'button',\r\n 'aria-label': i18n.t('transcript.closeMenu')\r\n }\r\n });\r\n const closeIcon = createIconElement('close');\r\n const closeText = DOMUtils.createElement('span', {\r\n textContent: i18n.t('transcript.closeMenu')\r\n });\r\n closeOption.appendChild(closeIcon);\r\n closeOption.appendChild(closeText);\r\n closeOption.addEventListener('click', () => {\r\n this.hideSettingsMenu();\r\n });\r\n\r\n this.settingsMenu.appendChild(keyboardDragOption);\r\n this.settingsMenu.appendChild(resizeOption);\r\n this.settingsMenu.appendChild(styleOption);\r\n this.settingsMenu.appendChild(closeOption);\r\n\r\n // Append menu to header left container for proper positioning\r\n if (this.headerLeft) {\r\n this.headerLeft.appendChild(this.settingsMenu);\r\n } else {\r\n this.transcriptHeader.appendChild(this.settingsMenu);\r\n }\r\n \r\n // Set the menu as visible and display it\r\n this.settingsMenuVisible = true;\r\n this.settingsMenu.style.display = 'block';\r\n \r\n // Update aria-expanded\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-expanded', 'true');\r\n }\r\n \r\n // Focus first menu item\r\n setTimeout(() => {\r\n const firstItem = this.settingsMenu.querySelector(`.${this.player.options.classPrefix}-transcript-settings-item`);\r\n if (firstItem) {\r\n firstItem.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Hide settings menu\r\n */\r\n hideSettingsMenu() {\r\n if (this.settingsMenu) {\r\n this.settingsMenu.style.display = 'none';\r\n this.settingsMenuVisible = false;\r\n this.settingsMenuJustOpened = false;\r\n \r\n // Update aria-expanded\r\n if (this.settingsButton) {\r\n this.settingsButton.setAttribute('aria-expanded', 'false');\r\n // Return focus to settings button\r\n this.settingsButton.focus();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Enable move mode (gives visual feedback)\r\n */\r\n enableMoveMode() {\r\n // Add visual feedback for move mode\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-move-mode`);\r\n \r\n // Show tooltip about keyboard drag option\r\n const tooltip = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-move-tooltip`,\r\n textContent: 'Drag with mouse or press D for keyboard drag mode'\r\n });\r\n this.transcriptHeader.appendChild(tooltip);\r\n \r\n // Remove after 2 seconds\r\n setTimeout(() => {\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-move-mode`);\r\n if (tooltip.parentNode) {\r\n tooltip.remove();\r\n }\r\n }, 2000);\r\n }\r\n\r\n /**\r\n * Toggle resize mode\r\n */\r\n toggleResizeMode() {\r\n this.resizeEnabled = !this.resizeEnabled;\r\n \r\n if (this.resizeEnabled) {\r\n this.enableResizeHandles();\r\n } else {\r\n this.disableResizeHandles();\r\n }\r\n }\r\n\r\n /**\r\n * Enable resize handles\r\n */\r\n enableResizeHandles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Add resize handles if they don't exist\r\n const directions = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'];\r\n \r\n directions.forEach(direction => {\r\n const handle = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-resize-handle ${this.player.options.classPrefix}-transcript-resize-${direction}`,\r\n attributes: {\r\n 'data-direction': direction\r\n }\r\n });\r\n\r\n handle.addEventListener('mousedown', (e) => this.startResize(e, direction));\r\n handle.addEventListener('touchstart', (e) => this.startResize(e.touches[0], direction));\r\n\r\n this.transcriptWindow.appendChild(handle);\r\n });\r\n\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-resizable`);\r\n\r\n // Setup resize event handlers\r\n this.handlers.resizeMove = (e) => {\r\n if (this.isResizing) {\r\n this.performResize(e.clientX, e.clientY);\r\n }\r\n };\r\n\r\n this.handlers.resizeEnd = () => {\r\n if (this.isResizing) {\r\n this.stopResize();\r\n }\r\n };\r\n\r\n this.handlers.resizeTouchMove = (e) => {\r\n if (this.isResizing) {\r\n this.performResize(e.touches[0].clientX, e.touches[0].clientY);\r\n e.preventDefault();\r\n }\r\n };\r\n\r\n document.addEventListener('mousemove', this.handlers.resizeMove);\r\n document.addEventListener('mouseup', this.handlers.resizeEnd);\r\n document.addEventListener('touchmove', this.handlers.resizeTouchMove);\r\n document.addEventListener('touchend', this.handlers.resizeEnd);\r\n }\r\n\r\n /**\r\n * Disable resize handles\r\n */\r\n disableResizeHandles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Remove all resize handles\r\n const handles = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-resize-handle`);\r\n handles.forEach(handle => handle.remove());\r\n\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-resizable`);\r\n\r\n // Remove resize event handlers\r\n if (this.handlers.resizeMove) {\r\n document.removeEventListener('mousemove', this.handlers.resizeMove);\r\n }\r\n if (this.handlers.resizeEnd) {\r\n document.removeEventListener('mouseup', this.handlers.resizeEnd);\r\n }\r\n if (this.handlers.resizeTouchMove) {\r\n document.removeEventListener('touchmove', this.handlers.resizeTouchMove);\r\n }\r\n document.removeEventListener('touchend', this.handlers.resizeEnd);\r\n }\r\n\r\n /**\r\n * Start resizing\r\n */\r\n startResize(e, direction) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n this.isResizing = true;\r\n this.resizeDirection = direction;\r\n this.resizeStartX = e.clientX;\r\n this.resizeStartY = e.clientY;\r\n\r\n const rect = this.transcriptWindow.getBoundingClientRect();\r\n this.resizeStartWidth = rect.width;\r\n this.resizeStartHeight = rect.height;\r\n\r\n this.transcriptWindow.classList.add(`${this.player.options.classPrefix}-transcript-resizing`);\r\n document.body.style.cursor = this.getResizeCursor(direction);\r\n document.body.style.userSelect = 'none';\r\n }\r\n\r\n /**\r\n * Perform resize\r\n */\r\n performResize(clientX, clientY) {\r\n if (!this.isResizing) return;\r\n\r\n const deltaX = clientX - this.resizeStartX;\r\n const deltaY = clientY - this.resizeStartY;\r\n\r\n let newWidth = this.resizeStartWidth;\r\n let newHeight = this.resizeStartHeight;\r\n\r\n const direction = this.resizeDirection;\r\n\r\n // Calculate new dimensions based on direction\r\n if (direction.includes('e')) {\r\n newWidth = this.resizeStartWidth + deltaX;\r\n }\r\n if (direction.includes('w')) {\r\n newWidth = this.resizeStartWidth - deltaX;\r\n }\r\n if (direction.includes('s')) {\r\n newHeight = this.resizeStartHeight + deltaY;\r\n }\r\n if (direction.includes('n')) {\r\n newHeight = this.resizeStartHeight - deltaY;\r\n }\r\n\r\n // Apply minimum and maximum constraints\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n const maxWidth = window.innerWidth - 40;\r\n const maxHeight = window.innerHeight - 40;\r\n\r\n newWidth = Math.max(minWidth, Math.min(newWidth, maxWidth));\r\n newHeight = Math.max(minHeight, Math.min(newHeight, maxHeight));\r\n\r\n // Apply new dimensions\r\n this.transcriptWindow.style.width = `${newWidth}px`;\r\n this.transcriptWindow.style.height = `${newHeight}px`;\r\n this.transcriptWindow.style.maxWidth = `${newWidth}px`;\r\n this.transcriptWindow.style.maxHeight = `${newHeight}px`;\r\n\r\n // Adjust position if resizing from top or left\r\n if (direction.includes('w')) {\r\n const currentLeft = parseFloat(this.transcriptWindow.style.left) || 0;\r\n this.transcriptWindow.style.left = `${currentLeft + (this.resizeStartWidth - newWidth)}px`;\r\n }\r\n if (direction.includes('n')) {\r\n const currentTop = parseFloat(this.transcriptWindow.style.top) || 0;\r\n this.transcriptWindow.style.top = `${currentTop + (this.resizeStartHeight - newHeight)}px`;\r\n }\r\n }\r\n\r\n /**\r\n * Stop resizing\r\n */\r\n stopResize() {\r\n this.isResizing = false;\r\n this.resizeDirection = null;\r\n this.transcriptWindow.classList.remove(`${this.player.options.classPrefix}-transcript-resizing`);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n }\r\n\r\n /**\r\n * Get cursor style for resize direction\r\n */\r\n getResizeCursor(direction) {\r\n const cursors = {\r\n 'n': 'ns-resize',\r\n 's': 'ns-resize',\r\n 'e': 'ew-resize',\r\n 'w': 'ew-resize',\r\n 'ne': 'nesw-resize',\r\n 'nw': 'nwse-resize',\r\n 'se': 'nwse-resize',\r\n 'sw': 'nesw-resize'\r\n };\r\n return cursors[direction] || 'default';\r\n }\r\n\r\n /**\r\n * Show style dialog\r\n */\r\n showStyleDialog() {\r\n // If dialog already exists, just show it\r\n if (this.styleDialog) {\r\n this.styleDialog.style.display = 'block';\r\n this.styleDialogVisible = true;\r\n \r\n // Set flag to prevent immediate closing from document click\r\n this.styleDialogJustOpened = true;\r\n setTimeout(() => {\r\n this.styleDialogJustOpened = false;\r\n }, 350);\r\n \r\n // Focus first control\r\n setTimeout(() => {\r\n const firstSelect = this.styleDialog.querySelector('select, input');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n return;\r\n }\r\n\r\n // Create style dialog\r\n this.styleDialog = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-dialog`\r\n });\r\n\r\n // Dialog title\r\n const title = DOMUtils.createElement('h4', {\r\n textContent: i18n.t('transcript.styleTitle'),\r\n className: `${this.player.options.classPrefix}-transcript-style-title`\r\n });\r\n this.styleDialog.appendChild(title);\r\n\r\n // Font Size\r\n const fontSizeControl = this.createStyleSelectControl(\r\n i18n.t('captions.fontSize'),\r\n 'fontSize',\r\n [\r\n { label: i18n.t('fontSizes.small'), value: '87.5%' },\r\n { label: i18n.t('fontSizes.normal'), value: '100%' },\r\n { label: i18n.t('fontSizes.large'), value: '125%' },\r\n { label: i18n.t('fontSizes.xlarge'), value: '150%' }\r\n ]\r\n );\r\n this.styleDialog.appendChild(fontSizeControl);\r\n\r\n // Font Family\r\n const fontFamilyControl = this.createStyleSelectControl(\r\n i18n.t('captions.fontFamily'),\r\n 'fontFamily',\r\n [\r\n { label: i18n.t('fontFamilies.sansSerif'), value: 'sans-serif' },\r\n { label: i18n.t('fontFamilies.serif'), value: 'serif' },\r\n { label: i18n.t('fontFamilies.monospace'), value: 'monospace' }\r\n ]\r\n );\r\n this.styleDialog.appendChild(fontFamilyControl);\r\n\r\n // Text Color\r\n const colorControl = this.createStyleColorControl(i18n.t('captions.color'), 'color');\r\n this.styleDialog.appendChild(colorControl);\r\n\r\n // Background Color\r\n const bgColorControl = this.createStyleColorControl(i18n.t('captions.backgroundColor'), 'backgroundColor');\r\n this.styleDialog.appendChild(bgColorControl);\r\n\r\n // Opacity\r\n const opacityControl = this.createStyleOpacityControl(i18n.t('captions.opacity'), 'opacity');\r\n this.styleDialog.appendChild(opacityControl);\r\n\r\n // Close button\r\n const closeBtn = DOMUtils.createElement('button', {\r\n className: `${this.player.options.classPrefix}-transcript-style-close`,\r\n textContent: i18n.t('settings.close'),\r\n attributes: {\r\n 'type': 'button'\r\n }\r\n });\r\n closeBtn.addEventListener('click', () => this.hideStyleDialog());\r\n this.styleDialog.appendChild(closeBtn);\r\n\r\n // ESC key handler for style dialog\r\n this.handlers.styleDialogKeydown = (e) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n this.hideStyleDialog();\r\n }\r\n };\r\n this.styleDialog.addEventListener('keydown', this.handlers.styleDialogKeydown);\r\n\r\n // Append to header left container (same as settings menu) for correct positioning\r\n if (this.headerLeft) {\r\n this.headerLeft.appendChild(this.styleDialog);\r\n } else {\r\n this.transcriptHeader.appendChild(this.styleDialog);\r\n }\r\n \r\n // Apply current styles\r\n this.applyTranscriptStyles();\r\n \r\n // Important: Set visible state and display before focusing\r\n this.styleDialogVisible = true;\r\n this.styleDialog.style.display = 'block';\r\n \r\n // Set flag to prevent immediate closing from document click\r\n this.styleDialogJustOpened = true;\r\n setTimeout(() => {\r\n this.styleDialogJustOpened = false;\r\n }, 350);\r\n \r\n // Focus first control for keyboard accessibility\r\n setTimeout(() => {\r\n const firstSelect = this.styleDialog.querySelector('select, input');\r\n if (firstSelect) {\r\n firstSelect.focus();\r\n }\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Hide style dialog\r\n */\r\n hideStyleDialog() {\r\n if (this.styleDialog) {\r\n this.styleDialog.style.display = 'none';\r\n this.styleDialogVisible = false;\r\n \r\n // Return focus to settings button\r\n if (this.settingsButton) {\r\n this.settingsButton.focus();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Create style select control\r\n */\r\n createStyleSelectControl(label, property, options) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const select = DOMUtils.createElement('select', {\r\n className: `${this.player.options.classPrefix}-transcript-style-select`\r\n });\r\n\r\n options.forEach(opt => {\r\n const option = DOMUtils.createElement('option', {\r\n textContent: opt.label,\r\n attributes: {\r\n 'value': opt.value\r\n }\r\n });\r\n if (this.transcriptStyle[property] === opt.value) {\r\n option.selected = true;\r\n }\r\n select.appendChild(option);\r\n });\r\n\r\n select.addEventListener('change', (e) => {\r\n this.transcriptStyle[property] = e.target.value;\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n group.appendChild(select);\r\n return group;\r\n }\r\n\r\n /**\r\n * Create style color control\r\n */\r\n createStyleColorControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n 'type': 'color',\r\n 'value': this.transcriptStyle[property]\r\n },\r\n className: `${this.player.options.classPrefix}-transcript-style-color`\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n this.transcriptStyle[property] = e.target.value;\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n group.appendChild(input);\r\n return group;\r\n }\r\n\r\n /**\r\n * Create style opacity control\r\n */\r\n createStyleOpacityControl(label, property) {\r\n const group = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-group`\r\n });\r\n\r\n const labelEl = DOMUtils.createElement('label', {\r\n textContent: label\r\n });\r\n group.appendChild(labelEl);\r\n\r\n const valueDisplay = DOMUtils.createElement('span', {\r\n textContent: Math.round(this.transcriptStyle[property] * 100) + '%',\r\n className: `${this.player.options.classPrefix}-transcript-style-value`\r\n });\r\n\r\n const input = DOMUtils.createElement('input', {\r\n attributes: {\r\n 'type': 'range',\r\n 'min': '0',\r\n 'max': '1',\r\n 'step': '0.1',\r\n 'value': String(this.transcriptStyle[property])\r\n },\r\n className: `${this.player.options.classPrefix}-transcript-style-range`\r\n });\r\n\r\n input.addEventListener('input', (e) => {\r\n const value = parseFloat(e.target.value);\r\n this.transcriptStyle[property] = value;\r\n valueDisplay.textContent = Math.round(value * 100) + '%';\r\n this.applyTranscriptStyles();\r\n this.savePreferences();\r\n });\r\n\r\n const inputContainer = DOMUtils.createElement('div', {\r\n className: `${this.player.options.classPrefix}-transcript-style-range-container`\r\n });\r\n inputContainer.appendChild(input);\r\n inputContainer.appendChild(valueDisplay);\r\n\r\n group.appendChild(labelEl);\r\n group.appendChild(inputContainer);\r\n return group;\r\n }\r\n\r\n /**\r\n * Save transcript preferences to localStorage\r\n */\r\n savePreferences() {\r\n this.storage.saveTranscriptPreferences(this.transcriptStyle);\r\n }\r\n\r\n /**\r\n * Apply transcript styles\r\n */\r\n applyTranscriptStyles() {\r\n if (!this.transcriptWindow) return;\r\n\r\n // Apply to transcript window background\r\n this.transcriptWindow.style.backgroundColor = this.transcriptStyle.backgroundColor;\r\n this.transcriptWindow.style.opacity = String(this.transcriptStyle.opacity);\r\n\r\n // Apply to content area\r\n if (this.transcriptContent) {\r\n this.transcriptContent.style.fontSize = this.transcriptStyle.fontSize;\r\n this.transcriptContent.style.fontFamily = this.transcriptStyle.fontFamily;\r\n this.transcriptContent.style.color = this.transcriptStyle.color;\r\n }\r\n\r\n // Apply to all text entries (important: override CSS defaults)\r\n const textEntries = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-text`);\r\n textEntries.forEach(entry => {\r\n entry.style.fontSize = this.transcriptStyle.fontSize;\r\n entry.style.fontFamily = this.transcriptStyle.fontFamily;\r\n entry.style.color = this.transcriptStyle.color;\r\n });\r\n \r\n // Apply to timestamp entries as well\r\n const timeEntries = this.transcriptWindow.querySelectorAll(`.${this.player.options.classPrefix}-transcript-time`);\r\n timeEntries.forEach(entry => {\r\n entry.style.fontFamily = this.transcriptStyle.fontFamily;\r\n });\r\n }\r\n\r\n /**\r\n * Set a managed timeout that will be cleaned up on destroy\r\n * @param {Function} callback - Callback function\r\n * @param {number} delay - Delay in milliseconds\r\n * @returns {number} Timeout ID\r\n */\r\n setManagedTimeout(callback, delay) {\r\n const timeoutId = setTimeout(() => {\r\n this.timeouts.delete(timeoutId);\r\n callback();\r\n }, delay);\r\n this.timeouts.add(timeoutId);\r\n return timeoutId;\r\n }\r\n\r\n /**\r\n * Clear a managed timeout\r\n * @param {number} timeoutId - Timeout ID to clear\r\n */\r\n clearManagedTimeout(timeoutId) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n this.timeouts.delete(timeoutId);\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Disable modes if active\r\n if (this.resizeEnabled) {\r\n this.disableResizeHandles();\r\n }\r\n if (this.keyboardDragMode) {\r\n this.disableKeyboardDragMode();\r\n }\r\n\r\n // Remove timeupdate listener from player\r\n if (this.handlers.timeupdate) {\r\n this.player.off('timeupdate', this.handlers.timeupdate);\r\n }\r\n\r\n // Remove drag event listeners\r\n if (this.transcriptHeader) {\r\n if (this.handlers.mousedown) {\r\n this.transcriptHeader.removeEventListener('mousedown', this.handlers.mousedown);\r\n }\r\n if (this.handlers.touchstart) {\r\n this.transcriptHeader.removeEventListener('touchstart', this.handlers.touchstart);\r\n }\r\n if (this.handlers.keydown) {\r\n this.transcriptHeader.removeEventListener('keydown', this.handlers.keydown);\r\n }\r\n }\r\n \r\n // Remove settings button event listeners\r\n if (this.settingsButton) {\r\n if (this.handlers.settingsClick) {\r\n this.settingsButton.removeEventListener('click', this.handlers.settingsClick);\r\n }\r\n if (this.handlers.settingsKeydown) {\r\n this.settingsButton.removeEventListener('keydown', this.handlers.settingsKeydown);\r\n }\r\n }\r\n \r\n // Remove style dialog event listeners\r\n if (this.styleDialog && this.handlers.styleDialogKeydown) {\r\n this.styleDialog.removeEventListener('keydown', this.handlers.styleDialogKeydown);\r\n }\r\n\r\n // Remove document-level listeners\r\n if (this.handlers.mousemove) {\r\n document.removeEventListener('mousemove', this.handlers.mousemove);\r\n }\r\n if (this.handlers.mouseup) {\r\n document.removeEventListener('mouseup', this.handlers.mouseup);\r\n }\r\n if (this.handlers.touchmove) {\r\n document.removeEventListener('touchmove', this.handlers.touchmove);\r\n }\r\n if (this.handlers.touchend) {\r\n document.removeEventListener('touchend', this.handlers.touchend);\r\n }\r\n if (this.handlers.documentClick) {\r\n document.removeEventListener('click', this.handlers.documentClick);\r\n }\r\n \r\n // Remove window-level listeners\r\n if (this.handlers.resize) {\r\n window.removeEventListener('resize', this.handlers.resize);\r\n }\r\n\r\n // Cleanup all managed timeouts\r\n this.timeouts.forEach(timeoutId => clearTimeout(timeoutId));\r\n this.timeouts.clear();\r\n\r\n // Clear handlers\r\n this.handlers = null;\r\n\r\n // Remove DOM element\r\n if (this.transcriptWindow && this.transcriptWindow.parentNode) {\r\n this.transcriptWindow.parentNode.removeChild(this.transcriptWindow);\r\n }\r\n \r\n this.transcriptWindow = null;\r\n this.transcriptHeader = null;\r\n this.transcriptContent = null;\r\n this.transcriptEntries = [];\r\n this.settingsMenu = null;\r\n this.styleDialog = null;\r\n }\r\n}\r\n", "/**\r\n * VidPly - Universal Video Player\r\n * Main Player Class\r\n */\r\n\r\nimport {EventEmitter} from '../utils/EventEmitter.js';\r\nimport {DOMUtils} from '../utils/DOMUtils.js';\r\nimport {ControlBar} from '../controls/ControlBar.js';\r\nimport {CaptionManager} from '../controls/CaptionManager.js';\r\nimport {KeyboardManager} from '../controls/KeyboardManager.js';\r\nimport {TranscriptManager} from '../controls/TranscriptManager.js';\r\nimport {HTML5Renderer} from '../renderers/HTML5Renderer.js';\r\nimport {YouTubeRenderer} from '../renderers/YouTubeRenderer.js';\r\nimport {VimeoRenderer} from '../renderers/VimeoRenderer.js';\r\nimport {HLSRenderer} from '../renderers/HLSRenderer.js';\r\nimport {createPlayOverlay} from '../icons/Icons.js';\r\nimport {i18n} from '../i18n/i18n.js';\r\nimport {StorageManager} from '../utils/StorageManager.js';\r\n\r\nexport class Player extends EventEmitter {\r\n constructor(element, options = {}) {\r\n super();\r\n\r\n this.element = typeof element === 'string' ? document.querySelector(element) : element;\r\n if (!this.element) {\r\n throw new Error('VidPly: Element not found');\r\n }\r\n\r\n // Auto-create media element if a non-media element is provided\r\n if (this.element.tagName !== 'VIDEO' && this.element.tagName !== 'AUDIO') {\r\n const mediaType = options.mediaType || 'video';\r\n const mediaElement = document.createElement(mediaType);\r\n\r\n // Copy attributes from the div to the media element\r\n Array.from(this.element.attributes).forEach(attr => {\r\n if (attr.name !== 'id' && attr.name !== 'class' && !attr.name.startsWith('data-')) {\r\n mediaElement.setAttribute(attr.name, attr.value);\r\n }\r\n });\r\n\r\n // Copy any track elements from the div\r\n const tracks = this.element.querySelectorAll('track');\r\n tracks.forEach(track => {\r\n mediaElement.appendChild(track.cloneNode(true));\r\n });\r\n\r\n // Clear the div and insert the media element\r\n this.element.innerHTML = '';\r\n this.element.appendChild(mediaElement);\r\n\r\n // Update element reference to the actual media element\r\n this.element = mediaElement;\r\n }\r\n\r\n // Default options\r\n this.options = {\r\n // Display\r\n width: null,\r\n height: null,\r\n poster: null,\r\n responsive: true,\r\n fillContainer: false,\r\n\r\n // Playback\r\n autoplay: false,\r\n loop: false,\r\n muted: false,\r\n volume: 0.8,\r\n playbackSpeed: 1.0,\r\n preload: 'metadata',\r\n startTime: 0,\r\n playsInline: true, // Enable inline playback on iOS (prevents native fullscreen)\r\n\r\n // Controls\r\n controls: true,\r\n hideControlsDelay: 3000,\r\n playPauseButton: true,\r\n progressBar: true,\r\n currentTime: true,\r\n duration: true,\r\n volumeControl: true,\r\n muteButton: true,\r\n chaptersButton: true,\r\n qualityButton: true,\r\n captionStyleButton: true,\r\n speedButton: true,\r\n captionsButton: true,\r\n transcriptButton: true,\r\n fullscreenButton: true,\r\n pipButton: false,\r\n\r\n // Seeking\r\n seekInterval: 10,\r\n seekIntervalLarge: 30,\r\n\r\n // Captions\r\n captions: true,\r\n captionsDefault: false,\r\n captionsFontSize: '100%',\r\n captionsFontFamily: 'sans-serif',\r\n captionsColor: '#FFFFFF',\r\n captionsBackgroundColor: '#000000',\r\n captionsOpacity: 0.8,\r\n\r\n // Audio Description\r\n audioDescription: true,\r\n audioDescriptionSrc: null, // URL to audio-described version\r\n audioDescriptionButton: true,\r\n\r\n // Sign Language\r\n signLanguage: true,\r\n signLanguageSrc: null, // URL to sign language video\r\n signLanguageButton: true,\r\n signLanguagePosition: 'bottom-right', // Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'\r\n\r\n // Transcripts\r\n transcript: false,\r\n transcriptPosition: 'external',\r\n transcriptContainer: null,\r\n\r\n // Keyboard\r\n keyboard: true,\r\n keyboardShortcuts: {\r\n 'play-pause': [' ', 'p', 'k'],\r\n 'volume-up': ['ArrowUp'],\r\n 'volume-down': ['ArrowDown'],\r\n 'seek-forward': ['ArrowRight'],\r\n 'seek-backward': ['ArrowLeft'],\r\n 'mute': ['m'],\r\n 'fullscreen': ['f'],\r\n 'captions': ['c'],\r\n 'caption-style-menu': ['a'],\r\n 'speed-up': ['>'],\r\n 'speed-down': ['<'],\r\n 'speed-menu': ['s'],\r\n 'quality-menu': ['q'],\r\n 'chapters-menu': ['j'],\r\n 'transcript-toggle': ['t']\r\n },\r\n\r\n // Accessibility\r\n ariaLabels: {},\r\n screenReaderAnnouncements: true,\r\n highContrast: false,\r\n focusHighlight: true,\r\n metadataAlerts: {},\r\n metadataHashtags: {},\r\n\r\n // Languages\r\n language: 'en',\r\n languages: ['en'],\r\n\r\n // Advanced\r\n debug: false,\r\n classPrefix: 'vidply',\r\n iconType: 'svg',\r\n pauseOthersOnPlay: true,\r\n\r\n // Callbacks\r\n onReady: null,\r\n onPlay: null,\r\n onPause: null,\r\n onEnded: null,\r\n onTimeUpdate: null,\r\n onVolumeChange: null,\r\n onError: null,\r\n\r\n ...options\r\n };\r\n\r\n this.options.metadataAlerts = this.options.metadataAlerts || {};\r\n this.options.metadataHashtags = this.options.metadataHashtags || {};\r\n\r\n // Storage manager\r\n this.storage = new StorageManager('vidply');\r\n \r\n // Load saved player preferences\r\n const savedPrefs = this.storage.getPlayerPreferences();\r\n if (savedPrefs) {\r\n if (savedPrefs.volume !== undefined) this.options.volume = savedPrefs.volume;\r\n if (savedPrefs.playbackSpeed !== undefined) this.options.playbackSpeed = savedPrefs.playbackSpeed;\r\n if (savedPrefs.muted !== undefined) this.options.muted = savedPrefs.muted;\r\n }\r\n \r\n // State\r\n this.state = {\r\n ready: false,\r\n playing: false,\r\n paused: true,\r\n ended: false,\r\n buffering: false,\r\n seeking: false,\r\n muted: this.options.muted,\r\n volume: this.options.volume,\r\n currentTime: 0,\r\n duration: 0,\r\n playbackSpeed: this.options.playbackSpeed,\r\n fullscreen: false,\r\n pip: false,\r\n captionsEnabled: this.options.captionsDefault,\r\n currentCaption: null,\r\n controlsVisible: true,\r\n audioDescriptionEnabled: false,\r\n signLanguageEnabled: false\r\n };\r\n\r\n // Store original source for toggling\r\n this.originalSrc = null;\r\n this.audioDescriptionSrc = this.options.audioDescriptionSrc;\r\n this.signLanguageSrc = this.options.signLanguageSrc;\r\n this.signLanguageVideo = null;\r\n // Store references to source elements with audio description attributes\r\n this.audioDescriptionSourceElement = null;\r\n this.originalAudioDescriptionSource = null;\r\n // Store caption tracks that should be swapped for audio description\r\n this.audioDescriptionCaptionTracks = [];\r\n\r\n // DOM query cache (for performance optimization)\r\n this._textTracksCache = null;\r\n this._textTracksDirty = true;\r\n this._sourceElementsCache = null;\r\n this._sourceElementsDirty = true;\r\n this._trackElementsCache = null;\r\n this._trackElementsDirty = true;\r\n\r\n // Timeout management (for cleanup)\r\n this.timeouts = new Set();\r\n\r\n // Components\r\n this.container = null;\r\n this.renderer = null;\r\n this.controlBar = null;\r\n this.captionManager = null;\r\n this.keyboardManager = null;\r\n this.settingsDialog = null;\r\n \r\n // Metadata handling\r\n this.metadataCueChangeHandler = null;\r\n this.metadataAlertHandlers = new Map();\r\n\r\n // Initialize\r\n this.init();\r\n }\r\n\r\n async init() {\r\n try {\r\n this.log('Initializing VidPly player');\r\n\r\n // Auto-detect language from HTML lang attribute if not explicitly set\r\n if (!this.options.language || this.options.language === 'en') {\r\n const htmlLang = this.detectHtmlLanguage();\r\n if (htmlLang) {\r\n this.options.language = htmlLang;\r\n this.log(`Auto-detected language from HTML: ${htmlLang}`);\r\n }\r\n }\r\n\r\n // Set language\r\n i18n.setLanguage(this.options.language);\r\n\r\n // Create container\r\n this.createContainer();\r\n\r\n // Detect and initialize renderer (only if source exists)\r\n const src = this.element.src || this.element.querySelector('source')?.src;\r\n if (src) {\r\n await this.initializeRenderer();\r\n } else {\r\n this.log('No initial source - waiting for playlist or manual load');\r\n }\r\n\r\n // Create controls\r\n if (this.options.controls) {\r\n this.controlBar = new ControlBar(this);\r\n this.videoWrapper.appendChild(this.controlBar.element);\r\n }\r\n\r\n // Initialize captions\r\n if (this.options.captions) {\r\n this.captionManager = new CaptionManager(this);\r\n }\r\n\r\n // Initialize transcript\r\n if (this.options.transcript || this.options.transcriptButton) {\r\n this.transcriptManager = new TranscriptManager(this);\r\n }\r\n \r\n // Always set up metadata track handling (independent of transcript)\r\n this.setupMetadataHandling();\r\n\r\n // Initialize keyboard controls\r\n if (this.options.keyboard) {\r\n this.keyboardManager = new KeyboardManager(this);\r\n }\r\n\r\n // Setup responsive handlers\r\n this.setupResponsiveHandlers();\r\n\r\n // Set initial state\r\n if (this.options.startTime > 0) {\r\n this.seek(this.options.startTime);\r\n }\r\n\r\n if (this.options.muted) {\r\n this.mute();\r\n }\r\n\r\n if (this.options.volume !== 0.8) {\r\n this.setVolume(this.options.volume);\r\n }\r\n\r\n // Mark as ready\r\n this.state.ready = true;\r\n this.emit('ready');\r\n\r\n if (this.options.onReady) {\r\n this.options.onReady.call(this);\r\n }\r\n\r\n // Autoplay if enabled\r\n if (this.options.autoplay) {\r\n this.play();\r\n }\r\n\r\n this.log('Player initialized successfully');\r\n } catch (error) {\r\n this.handleError(error);\r\n }\r\n }\r\n\r\n /**\r\n * Detect language from HTML lang attribute\r\n * @returns {string|null} Language code if available in translations, null otherwise\r\n */\r\n detectHtmlLanguage() {\r\n // Try to get lang from html element\r\n const htmlLang = document.documentElement.lang || document.documentElement.getAttribute('lang');\r\n\r\n if (!htmlLang) {\r\n return null;\r\n }\r\n\r\n // Normalize the language code (e.g., \"en-US\" -> \"en\", \"de-DE\" -> \"de\")\r\n const normalizedLang = htmlLang.toLowerCase().split('-')[0];\r\n\r\n // Check if this language is available in our translations\r\n const availableLanguages = ['en', 'de', 'es', 'fr', 'ja'];\r\n\r\n if (availableLanguages.includes(normalizedLang)) {\r\n return normalizedLang;\r\n }\r\n\r\n // Language not available, will fallback to English\r\n this.log(`Language \"${htmlLang}\" not available, using English as fallback`);\r\n return 'en';\r\n }\r\n\r\n createContainer() {\r\n // Create main container\r\n this.container = DOMUtils.createElement('div', {\r\n className: `${this.options.classPrefix}-player`,\r\n attributes: {\r\n 'role': 'region',\r\n 'aria-label': i18n.t('player.label'),\r\n 'tabindex': '0'\r\n }\r\n });\r\n\r\n // Add media type class\r\n const mediaType = this.element.tagName.toLowerCase();\r\n this.container.classList.add(`${this.options.classPrefix}-${mediaType}`);\r\n\r\n // Add responsive class\r\n if (this.options.responsive) {\r\n this.container.classList.add(`${this.options.classPrefix}-responsive`);\r\n }\r\n\r\n // Create video wrapper (for proper positioning of controls)\r\n this.videoWrapper = DOMUtils.createElement('div', {\r\n className: `${this.options.classPrefix}-video-wrapper`\r\n });\r\n\r\n // Wrap original element\r\n this.element.parentNode.insertBefore(this.container, this.element);\r\n this.container.appendChild(this.videoWrapper);\r\n this.videoWrapper.appendChild(this.element);\r\n\r\n // Hide native controls and set dimensions\r\n this.element.controls = false;\r\n this.element.removeAttribute('controls');\r\n this.element.setAttribute('tabindex', '-1'); // Remove from tab order\r\n this.element.style.width = '100%';\r\n this.element.style.height = '100%';\r\n\r\n // Enable inline playback on iOS (prevents native fullscreen)\r\n // This allows custom controls to work on iOS devices\r\n if (this.element.tagName === 'VIDEO' && this.options.playsInline) {\r\n this.element.setAttribute('playsinline', '');\r\n this.element.setAttribute('webkit-playsinline', ''); // For older iOS versions\r\n this.element.playsInline = true; // Property version\r\n }\r\n\r\n // Set dimensions\r\n if (this.options.width) {\r\n this.container.style.width = typeof this.options.width === 'number'\r\n ? `${this.options.width}px`\r\n : this.options.width;\r\n }\r\n\r\n if (this.options.height) {\r\n this.container.style.height = typeof this.options.height === 'number'\r\n ? `${this.options.height}px`\r\n : this.options.height;\r\n }\r\n\r\n // Set poster\r\n if (this.options.poster && this.element.tagName === 'VIDEO') {\r\n this.element.poster = this.options.poster;\r\n }\r\n\r\n // Create centered play button overlay (only for video)\r\n if (this.element.tagName === 'VIDEO') {\r\n this.createPlayButtonOverlay();\r\n }\r\n \r\n // Store reference to player on element for easy access\r\n this.element.vidply = this;\r\n \r\n // Add to static instances array\r\n Player.instances.push(this);\r\n\r\n // Make video/audio element clickable to toggle play/pause\r\n this.element.style.cursor = 'pointer';\r\n this.element.addEventListener('click', (e) => {\r\n // Prevent if clicking on native controls (shouldn't happen but just in case)\r\n if (e.target === this.element) {\r\n this.toggle();\r\n }\r\n });\r\n }\r\n\r\n createPlayButtonOverlay() {\r\n // Create complete SVG play button from Icons.js\r\n this.playButtonOverlay = createPlayOverlay();\r\n\r\n // Add click handler\r\n this.playButtonOverlay.addEventListener('click', () => {\r\n this.toggle();\r\n });\r\n\r\n // Add to video wrapper\r\n this.videoWrapper.appendChild(this.playButtonOverlay);\r\n\r\n // Show/hide based on play state\r\n this.on('play', () => {\r\n this.playButtonOverlay.style.opacity = '0';\r\n this.playButtonOverlay.style.pointerEvents = 'none';\r\n });\r\n\r\n this.on('pause', () => {\r\n this.playButtonOverlay.style.opacity = '1';\r\n this.playButtonOverlay.style.pointerEvents = 'auto';\r\n });\r\n\r\n this.on('ended', () => {\r\n this.playButtonOverlay.style.opacity = '1';\r\n this.playButtonOverlay.style.pointerEvents = 'auto';\r\n });\r\n }\r\n\r\n async initializeRenderer() {\r\n const src = this.element.src || this.element.querySelector('source')?.src;\r\n\r\n if (!src) {\r\n throw new Error('No media source found');\r\n }\r\n\r\n // Check for source elements with audio description attributes\r\n const sourceElements = this.sourceElements;\r\n for (const sourceEl of sourceElements) {\r\n const descSrc = sourceEl.getAttribute('data-desc-src');\r\n const origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n if (descSrc || origSrc) {\r\n // Found a source element with audio description attributes\r\n // Store the first one as reference, but we'll search all of them when toggling\r\n if (!this.audioDescriptionSourceElement) {\r\n this.audioDescriptionSourceElement = sourceEl;\r\n }\r\n \r\n if (origSrc) {\r\n // Store the original src from the attribute for this source\r\n if (!this.originalAudioDescriptionSource) {\r\n this.originalAudioDescriptionSource = origSrc;\r\n }\r\n // Store the original src from the first source element that has data-orig-src\r\n if (!this.originalSrc) {\r\n this.originalSrc = origSrc;\r\n }\r\n } else {\r\n // If data-orig-src is not set, use the current src attribute\r\n const currentSrcAttr = sourceEl.getAttribute('src');\r\n if (!this.originalAudioDescriptionSource && currentSrcAttr) {\r\n this.originalAudioDescriptionSource = currentSrcAttr;\r\n }\r\n if (!this.originalSrc && currentSrcAttr) {\r\n this.originalSrc = currentSrcAttr;\r\n }\r\n }\r\n \r\n // Store audio description source from data-desc-src (use first one found)\r\n if (descSrc && !this.audioDescriptionSrc) {\r\n this.audioDescriptionSrc = descSrc;\r\n }\r\n // Continue checking all source elements to ensure we capture all audio description sources\r\n }\r\n }\r\n\r\n // Check for caption/subtitle tracks with audio description versions\r\n // Only tracks with explicit data-desc-src attribute are swapped (no auto-detection to avoid 404 errors)\r\n // Description tracks (kind=\"descriptions\") are NOT swapped - they're for transcripts\r\n const trackElements = this.trackElements;\r\n trackElements.forEach(trackEl => {\r\n const trackKind = trackEl.getAttribute('kind');\r\n const trackDescSrc = trackEl.getAttribute('data-desc-src');\r\n \r\n // Only handle caption/subtitle tracks (not description tracks)\r\n // Description tracks stay as-is since they're for transcripts\r\n // Include captions, subtitles, and chapters tracks that can be swapped for audio description\r\n if (trackKind === 'captions' || trackKind === 'subtitles' || trackKind === 'chapters') {\r\n if (trackDescSrc) {\r\n // Found a track with explicit data-desc-src - this is the described version\r\n this.audioDescriptionCaptionTracks.push({\r\n trackElement: trackEl,\r\n originalSrc: trackEl.getAttribute('src'),\r\n describedSrc: trackDescSrc,\r\n originalTrackSrc: trackEl.getAttribute('data-orig-src') || trackEl.getAttribute('src'),\r\n explicit: true // Explicitly defined, so we should validate it\r\n });\r\n this.log(`Found explicit described ${trackKind} track: ${trackEl.getAttribute('src')} -> ${trackDescSrc}`);\r\n }\r\n // Note: Auto-detection disabled to avoid 404 console errors\r\n // If you want described tracks, add data-desc-src attribute to the track element\r\n }\r\n // Description tracks (kind=\"descriptions\") are ignored - they remain unchanged for transcripts\r\n });\r\n\r\n // Store original source for audio description toggling (fallback if not set above)\r\n if (!this.originalSrc) {\r\n this.originalSrc = src;\r\n }\r\n\r\n // Detect media type\r\n let renderer;\r\n\r\n if (src.includes('youtube.com') || src.includes('youtu.be')) {\r\n renderer = YouTubeRenderer;\r\n } else if (src.includes('vimeo.com')) {\r\n renderer = VimeoRenderer;\r\n } else if (src.includes('.m3u8')) {\r\n renderer = HLSRenderer;\r\n } else {\r\n renderer = HTML5Renderer;\r\n }\r\n\r\n this.log(`Using ${renderer.name} renderer`);\r\n this.renderer = new renderer(this);\r\n await this.renderer.init();\r\n \r\n // Invalidate cache after renderer initialization (tracks may have changed)\r\n this.invalidateTrackCache();\r\n }\r\n\r\n /**\r\n * Get cached text tracks array\r\n * @returns {Array} Array of text tracks\r\n */\r\n get textTracks() {\r\n if (!this._textTracksCache || this._textTracksDirty) {\r\n this._textTracksCache = Array.from(this.element.textTracks || []);\r\n this._textTracksDirty = false;\r\n }\r\n return this._textTracksCache;\r\n }\r\n\r\n /**\r\n * Get cached source elements array\r\n * @returns {Array} Array of source elements\r\n */\r\n get sourceElements() {\r\n if (!this._sourceElementsCache || this._sourceElementsDirty) {\r\n this._sourceElementsCache = Array.from(this.element.querySelectorAll('source'));\r\n this._sourceElementsDirty = false;\r\n }\r\n return this._sourceElementsCache;\r\n }\r\n\r\n /**\r\n * Get cached track elements array\r\n * @returns {Array} Array of track elements\r\n */\r\n get trackElements() {\r\n if (!this._trackElementsCache || this._trackElementsDirty) {\r\n this._trackElementsCache = Array.from(this.element.querySelectorAll('track'));\r\n this._trackElementsDirty = false;\r\n }\r\n return this._trackElementsCache;\r\n }\r\n\r\n /**\r\n * Invalidate DOM query cache (call when tracks/sources change)\r\n */\r\n invalidateTrackCache() {\r\n this._textTracksDirty = true;\r\n this._trackElementsDirty = true;\r\n this._sourceElementsDirty = true;\r\n }\r\n\r\n /**\r\n * Find a text track by kind and optionally language\r\n * @param {string} kind - Track kind (captions, subtitles, descriptions, chapters, metadata)\r\n * @param {string} [language] - Optional language code\r\n * @returns {TextTrack|null} Found track or null\r\n */\r\n findTextTrack(kind, language = null) {\r\n const tracks = this.textTracks;\r\n if (language) {\r\n return tracks.find(t => t.kind === kind && t.language === language);\r\n }\r\n return tracks.find(t => t.kind === kind);\r\n }\r\n\r\n /**\r\n * Find a source element by attribute\r\n * @param {string} attribute - Attribute name (e.g., 'data-desc-src')\r\n * @param {string} [value] - Optional attribute value\r\n * @returns {Element|null} Found source element or null\r\n */\r\n findSourceElement(attribute, value = null) {\r\n const sources = this.sourceElements;\r\n if (value) {\r\n return sources.find(el => el.getAttribute(attribute) === value);\r\n }\r\n return sources.find(el => el.hasAttribute(attribute));\r\n }\r\n\r\n /**\r\n * Find a track element by its associated TextTrack\r\n * @param {TextTrack} track - The TextTrack object\r\n * @returns {Element|null} Found track element or null\r\n */\r\n findTrackElement(track) {\r\n return this.trackElements.find(el => el.track === track);\r\n }\r\n\r\n /**\r\n * Set a managed timeout that will be cleaned up on destroy\r\n * @param {Function} callback - Callback function\r\n * @param {number} delay - Delay in milliseconds\r\n * @returns {number} Timeout ID\r\n */\r\n setManagedTimeout(callback, delay) {\r\n const timeoutId = setTimeout(() => {\r\n this.timeouts.delete(timeoutId);\r\n callback();\r\n }, delay);\r\n this.timeouts.add(timeoutId);\r\n return timeoutId;\r\n }\r\n\r\n /**\r\n * Clear a managed timeout\r\n * @param {number} timeoutId - Timeout ID to clear\r\n */\r\n clearManagedTimeout(timeoutId) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n this.timeouts.delete(timeoutId);\r\n }\r\n }\r\n\r\n /**\r\n * Load new media source (for playlists)\r\n * @param {Object} config - Media configuration\r\n * @param {string} config.src - Media source URL\r\n * @param {string} config.type - Media MIME type\r\n * @param {string} [config.poster] - Poster image URL\r\n * @param {Array} [config.tracks] - Text tracks (captions, chapters, etc.)\r\n */\r\n async load(config) {\r\n try {\r\n this.log('Loading new media:', config.src);\r\n\r\n // Pause current playback\r\n if (this.renderer) {\r\n this.pause();\r\n }\r\n\r\n // Clear existing text tracks\r\n const existingTracks = this.trackElements;\r\n existingTracks.forEach(track => track.remove());\r\n this.invalidateTrackCache();\r\n\r\n // Update media element\r\n this.element.src = config.src;\r\n\r\n if (config.type) {\r\n this.element.type = config.type;\r\n }\r\n\r\n if (config.poster && this.element.tagName === 'VIDEO') {\r\n this.element.poster = config.poster;\r\n }\r\n\r\n // Add new text tracks\r\n if (config.tracks && config.tracks.length > 0) {\r\n config.tracks.forEach(trackConfig => {\r\n const track = document.createElement('track');\r\n track.src = trackConfig.src;\r\n track.kind = trackConfig.kind || 'captions';\r\n track.srclang = trackConfig.srclang || 'en';\r\n track.label = trackConfig.label || trackConfig.srclang;\r\n\r\n if (trackConfig.default) {\r\n track.default = true;\r\n }\r\n\r\n this.element.appendChild(track);\r\n });\r\n this.invalidateTrackCache();\r\n }\r\n\r\n // Check if we need to change renderer type\r\n const shouldChangeRenderer = this.shouldChangeRenderer(config.src);\r\n\r\n // Destroy old renderer if changing types\r\n if (shouldChangeRenderer && this.renderer) {\r\n this.renderer.destroy();\r\n this.renderer = null;\r\n }\r\n\r\n // Initialize or reinitialize renderer\r\n if (!this.renderer || shouldChangeRenderer) {\r\n await this.initializeRenderer();\r\n } else {\r\n // Just reload the current renderer with the updated element\r\n this.renderer.media = this.element; // Update media reference\r\n this.element.load();\r\n }\r\n\r\n // Reinitialize caption manager to pick up new tracks\r\n if (this.captionManager) {\r\n this.captionManager.destroy();\r\n this.captionManager = new CaptionManager(this);\r\n }\r\n \r\n // Reinitialize transcript manager to pick up new tracks\r\n if (this.transcriptManager) {\r\n const wasVisible = this.transcriptManager.isVisible;\r\n this.transcriptManager.destroy();\r\n this.transcriptManager = new TranscriptManager(this);\r\n \r\n // Restore visibility state if transcript was open\r\n if (wasVisible) {\r\n this.transcriptManager.showTranscript();\r\n }\r\n }\r\n \r\n // Update control bar to show/hide feature buttons based on new tracks\r\n if (this.controlBar) {\r\n this.updateControlBar();\r\n }\r\n\r\n this.emit('sourcechange', config);\r\n this.log('Media loaded successfully');\r\n\r\n } catch (error) {\r\n this.handleError(error);\r\n }\r\n }\r\n\r\n /**\r\n * Check if we need to change renderer type\r\n * @param {string} src - New source URL\r\n * @returns {boolean}\r\n */\r\n /**\r\n * Update control bar to refresh button visibility based on available features\r\n */\r\n updateControlBar() {\r\n if (!this.controlBar) return;\r\n \r\n const controlBar = this.controlBar;\r\n \r\n // Clear existing controls content\r\n controlBar.element.innerHTML = '';\r\n \r\n // Recreate controls with updated feature detection\r\n controlBar.createControls();\r\n \r\n // Reattach events for the new controls\r\n controlBar.attachEvents();\r\n controlBar.setupAutoHide();\r\n }\r\n \r\n shouldChangeRenderer(src) {\r\n if (!this.renderer) return true;\r\n\r\n const isYouTube = src.includes('youtube.com') || src.includes('youtu.be');\r\n const isVimeo = src.includes('vimeo.com');\r\n const isHLS = src.includes('.m3u8');\r\n\r\n const currentRendererName = this.renderer.constructor.name;\r\n\r\n if (isYouTube && currentRendererName !== 'YouTubeRenderer') return true;\r\n if (isVimeo && currentRendererName !== 'VimeoRenderer') return true;\r\n if (isHLS && currentRendererName !== 'HLSRenderer') return true;\r\n if (!isYouTube && !isVimeo && !isHLS && currentRendererName !== 'HTML5Renderer') return true;\r\n\r\n return false;\r\n }\r\n\r\n // Playback controls\r\n play() {\r\n if (this.renderer) {\r\n this.renderer.play();\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.renderer) {\r\n this.renderer.pause();\r\n }\r\n }\r\n\r\n stop() {\r\n this.pause();\r\n this.seek(0);\r\n }\r\n\r\n toggle() {\r\n if (this.state.playing) {\r\n this.pause();\r\n } else {\r\n this.play();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.renderer) {\r\n this.renderer.seek(time);\r\n }\r\n }\r\n\r\n seekForward(interval = this.options.seekInterval) {\r\n this.seek(Math.min(this.state.currentTime + interval, this.state.duration));\r\n }\r\n\r\n seekBackward(interval = this.options.seekInterval) {\r\n this.seek(Math.max(this.state.currentTime - interval, 0));\r\n }\r\n\r\n // Volume controls\r\n setVolume(volume) {\r\n const newVolume = Math.max(0, Math.min(1, volume));\r\n if (this.renderer) {\r\n this.renderer.setVolume(newVolume);\r\n }\r\n this.state.volume = newVolume;\r\n\r\n if (newVolume > 0 && this.state.muted) {\r\n this.state.muted = false;\r\n }\r\n \r\n this.savePlayerPreferences();\r\n }\r\n\r\n getVolume() {\r\n return this.state.volume;\r\n }\r\n\r\n mute() {\r\n if (this.renderer) {\r\n this.renderer.setMuted(true);\r\n }\r\n this.state.muted = true;\r\n this.savePlayerPreferences();\r\n this.emit('volumechange');\r\n }\r\n\r\n unmute() {\r\n if (this.renderer) {\r\n this.renderer.setMuted(false);\r\n }\r\n this.state.muted = false;\r\n this.savePlayerPreferences();\r\n this.emit('volumechange');\r\n }\r\n\r\n toggleMute() {\r\n if (this.state.muted) {\r\n this.unmute();\r\n } else {\r\n this.mute();\r\n }\r\n }\r\n\r\n // Playback speed\r\n setPlaybackSpeed(speed) {\r\n const newSpeed = Math.max(0.25, Math.min(2, speed));\r\n if (this.renderer) {\r\n this.renderer.setPlaybackSpeed(newSpeed);\r\n }\r\n this.state.playbackSpeed = newSpeed;\r\n this.savePlayerPreferences();\r\n this.emit('playbackspeedchange', newSpeed);\r\n }\r\n\r\n getPlaybackSpeed() {\r\n return this.state.playbackSpeed;\r\n }\r\n \r\n // Save player preferences to localStorage\r\n savePlayerPreferences() {\r\n this.storage.savePlayerPreferences({\r\n volume: this.state.volume,\r\n muted: this.state.muted,\r\n playbackSpeed: this.state.playbackSpeed\r\n });\r\n }\r\n\r\n // Fullscreen\r\n enterFullscreen() {\r\n const elem = this.container;\r\n\r\n if (elem.requestFullscreen) {\r\n elem.requestFullscreen();\r\n } else if (elem.webkitRequestFullscreen) {\r\n elem.webkitRequestFullscreen();\r\n } else if (elem.mozRequestFullScreen) {\r\n elem.mozRequestFullScreen();\r\n } else if (elem.msRequestFullscreen) {\r\n elem.msRequestFullscreen();\r\n }\r\n\r\n this.state.fullscreen = true;\r\n this.container.classList.add(`${this.options.classPrefix}-fullscreen`);\r\n this.emit('fullscreenchange', true);\r\n }\r\n\r\n exitFullscreen() {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if (document.webkitExitFullscreen) {\r\n document.webkitExitFullscreen();\r\n } else if (document.mozCancelFullScreen) {\r\n document.mozCancelFullScreen();\r\n } else if (document.msExitFullscreen) {\r\n document.msExitFullscreen();\r\n }\r\n\r\n this.state.fullscreen = false;\r\n this.container.classList.remove(`${this.options.classPrefix}-fullscreen`);\r\n this.emit('fullscreenchange', false);\r\n }\r\n\r\n toggleFullscreen() {\r\n if (this.state.fullscreen) {\r\n this.exitFullscreen();\r\n } else {\r\n this.enterFullscreen();\r\n }\r\n }\r\n\r\n // Picture-in-Picture\r\n enterPiP() {\r\n if (this.element.requestPictureInPicture) {\r\n this.element.requestPictureInPicture();\r\n this.state.pip = true;\r\n this.emit('pipchange', true);\r\n }\r\n }\r\n\r\n exitPiP() {\r\n if (document.pictureInPictureElement) {\r\n document.exitPictureInPicture();\r\n this.state.pip = false;\r\n this.emit('pipchange', false);\r\n }\r\n }\r\n\r\n togglePiP() {\r\n if (this.state.pip) {\r\n this.exitPiP();\r\n } else {\r\n this.enterPiP();\r\n }\r\n }\r\n\r\n // Captions\r\n enableCaptions() {\r\n if (this.captionManager) {\r\n this.captionManager.enable();\r\n this.state.captionsEnabled = true;\r\n }\r\n }\r\n\r\n disableCaptions() {\r\n if (this.captionManager) {\r\n this.captionManager.disable();\r\n this.state.captionsEnabled = false;\r\n }\r\n }\r\n\r\n toggleCaptions() {\r\n if (this.state.captionsEnabled) {\r\n this.disableCaptions();\r\n } else {\r\n this.enableCaptions();\r\n }\r\n }\r\n\r\n /**\r\n * Check if a track file exists\r\n * @param {string} url - Track file URL\r\n * @returns {Promise<boolean>} - True if file exists\r\n */\r\n async validateTrackExists(url) {\r\n try {\r\n const response = await fetch(url, { method: 'HEAD', cache: 'no-cache' });\r\n return response.ok;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n // Audio Description\r\n async enableAudioDescription() {\r\n // Check if we have source elements with data-desc-src (even if audioDescriptionSrc is not set)\r\n const hasSourceElementsWithDesc = this.sourceElements.some(el => el.getAttribute('data-desc-src'));\r\n const hasTracksWithDesc = this.audioDescriptionCaptionTracks.length > 0;\r\n \r\n if (!this.audioDescriptionSrc && !hasSourceElementsWithDesc && !hasTracksWithDesc) {\r\n console.warn('VidPly: No audio description source, source elements, or tracks provided');\r\n return;\r\n }\r\n\r\n // Store current playback state\r\n const currentTime = this.state.currentTime;\r\n const wasPlaying = this.state.playing;\r\n\r\n // Store swapped tracks for transcript reload (declare at function scope)\r\n let swappedTracksForTranscript = [];\r\n\r\n // Switch to audio-described version\r\n // If we have a source element with audio description attributes, update that instead\r\n if (this.audioDescriptionSourceElement) {\r\n const currentSrc = this.element.currentSrc || this.element.src;\r\n \r\n // Find the source element that matches the currently active source\r\n const sourceElements = this.sourceElements;\r\n let sourceElementToUpdate = null;\r\n let descSrc = this.audioDescriptionSrc;\r\n \r\n for (const sourceEl of sourceElements) {\r\n const sourceSrc = sourceEl.getAttribute('src');\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n \r\n // Check if this source matches the current source (by filename)\r\n // Match by full path or just filename\r\n const sourceFilename = sourceSrc ? sourceSrc.split('/').pop() : '';\r\n const currentFilename = currentSrc ? currentSrc.split('/').pop() : '';\r\n \r\n if (currentSrc && (currentSrc === sourceSrc || \r\n currentSrc.includes(sourceSrc) || \r\n currentSrc.includes(sourceFilename) ||\r\n (sourceFilename && currentFilename === sourceFilename))) {\r\n sourceElementToUpdate = sourceEl;\r\n if (descSrcAttr) {\r\n descSrc = descSrcAttr;\r\n } else if (sourceSrc) {\r\n // If no data-desc-src, try to construct it from the source\r\n // But prefer the stored audioDescriptionSrc if available\r\n descSrc = this.audioDescriptionSrc || descSrc;\r\n }\r\n break;\r\n }\r\n }\r\n \r\n // If we didn't find a match, use the stored source element\r\n if (!sourceElementToUpdate) {\r\n sourceElementToUpdate = this.audioDescriptionSourceElement;\r\n // Ensure we have the correct descSrc from the stored element\r\n const storedDescSrc = sourceElementToUpdate.getAttribute('data-desc-src');\r\n if (storedDescSrc) {\r\n descSrc = storedDescSrc;\r\n }\r\n }\r\n \r\n // Swap caption tracks to described versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n // Swap tracks: validate explicit tracks, but try auto-detected tracks without validation\r\n // This avoids 404 errors while still allowing auto-detection to work\r\n const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {\r\n if (trackInfo.trackElement && trackInfo.describedSrc) {\r\n // Only validate explicitly defined tracks (to confirm they exist)\r\n // Auto-detected tracks are used without validation (browser will handle missing files gracefully)\r\n if (trackInfo.explicit === true) {\r\n try {\r\n const exists = await this.validateTrackExists(trackInfo.describedSrc);\r\n return { trackInfo, exists };\r\n } catch (error) {\r\n // Silently handle validation errors\r\n return { trackInfo, exists: false };\r\n }\r\n } else {\r\n // This shouldn't happen since auto-detection is disabled\r\n // But if it does, don't validate to avoid 404s\r\n return { trackInfo, exists: false };\r\n }\r\n }\r\n return { trackInfo, exists: false };\r\n });\r\n \r\n const validationResults = await Promise.all(validationPromises);\r\n const tracksToSwap = validationResults.filter(result => result.exists);\r\n \r\n if (tracksToSwap.length > 0) {\r\n // Store original track modes before removing tracks\r\n const trackModes = new Map();\r\n tracksToSwap.forEach(({ trackInfo }) => {\r\n const textTrack = trackInfo.trackElement.track;\r\n if (textTrack) {\r\n trackModes.set(trackInfo, {\r\n wasShowing: textTrack.mode === 'showing',\r\n wasHidden: textTrack.mode === 'hidden'\r\n });\r\n } else {\r\n trackModes.set(trackInfo, {\r\n wasShowing: false,\r\n wasHidden: false\r\n });\r\n }\r\n });\r\n \r\n // Store all track information before removing\r\n const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {\r\n const oldSrc = trackInfo.trackElement.getAttribute('src');\r\n const parent = trackInfo.trackElement.parentNode;\r\n const nextSibling = trackInfo.trackElement.nextSibling;\r\n \r\n // Store all attributes from the old track\r\n const attributes = {};\r\n Array.from(trackInfo.trackElement.attributes).forEach(attr => {\r\n attributes[attr.name] = attr.value;\r\n });\r\n \r\n return {\r\n trackInfo,\r\n oldSrc,\r\n parent,\r\n nextSibling,\r\n attributes\r\n };\r\n });\r\n \r\n // Remove ALL old tracks first to force browser to clear TextTrack objects\r\n tracksToReadd.forEach(({ trackInfo }) => {\r\n trackInfo.trackElement.remove();\r\n });\r\n \r\n // Force browser to process the removal by calling load()\r\n this.element.load();\r\n \r\n // Wait for browser to process the removal, then add new tracks\r\n setTimeout(() => {\r\n tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {\r\n swappedTracksForTranscript.push(trackInfo);\r\n \r\n // Create a completely new track element (not a clone) to force browser to create new TextTrack\r\n const newTrackElement = document.createElement('track');\r\n newTrackElement.setAttribute('src', trackInfo.describedSrc);\r\n \r\n // Copy all attributes except src and data-desc-src\r\n Object.keys(attributes).forEach(attrName => {\r\n if (attrName !== 'src' && attrName !== 'data-desc-src') {\r\n newTrackElement.setAttribute(attrName, attributes[attrName]);\r\n }\r\n });\r\n \r\n // Insert new track element\r\n if (nextSibling && nextSibling.parentNode) {\r\n parent.insertBefore(newTrackElement, nextSibling);\r\n } else {\r\n parent.appendChild(newTrackElement);\r\n }\r\n \r\n // Update reference to the new track element\r\n trackInfo.trackElement = newTrackElement;\r\n });\r\n \r\n // After all new tracks are added, force browser to reload media element again\r\n // This ensures new track elements are processed and new TextTrack objects are created\r\n this.element.load();\r\n this.invalidateTrackCache();\r\n \r\n // Wait for loadedmetadata event before accessing new TextTrack objects\r\n const setupNewTracks = () => {\r\n // Wait a bit more for browser to fully process the new track elements\r\n this.setManagedTimeout(() => {\r\n swappedTracksForTranscript.forEach((trackInfo) => {\r\n const trackElement = trackInfo.trackElement;\r\n const newTextTrack = trackElement.track;\r\n \r\n if (newTextTrack) {\r\n // Get original mode from stored map\r\n const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };\r\n \r\n // Set mode to load the new track\r\n newTextTrack.mode = 'hidden'; // Use hidden to load cues without showing\r\n \r\n // Restore original mode after track loads\r\n // Note: CaptionManager will handle enabling captions separately\r\n const restoreMode = () => {\r\n if (modeInfo.wasShowing) {\r\n // Set to hidden - CaptionManager will set it to showing when it enables\r\n newTextTrack.mode = 'hidden';\r\n } else if (modeInfo.wasHidden) {\r\n newTextTrack.mode = 'hidden';\r\n } else {\r\n newTextTrack.mode = 'disabled';\r\n }\r\n };\r\n \r\n // Wait for track to load\r\n if (newTextTrack.readyState >= 2) { // LOADED\r\n restoreMode();\r\n } else {\r\n newTextTrack.addEventListener('load', restoreMode, { once: true });\r\n newTextTrack.addEventListener('error', restoreMode, { once: true });\r\n }\r\n }\r\n });\r\n }, 300); // Additional wait for browser to process track elements\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Already loaded, wait a bit and setup\r\n setTimeout(setupNewTracks, 200);\r\n } else {\r\n this.element.addEventListener('loadedmetadata', setupNewTracks, { once: true });\r\n // Fallback timeout\r\n setTimeout(setupNewTracks, 2000);\r\n }\r\n }, 100); // Wait 100ms after first load() before adding new tracks\r\n \r\n const skippedCount = validationResults.length - tracksToSwap.length;\r\n }\r\n }\r\n \r\n // Update all source elements that have data-desc-src to their described versions\r\n // Force browser to pick up changes by removing and re-adding source elements\r\n // Get source elements (may have been defined in if block above, but get fresh list here)\r\n const allSourceElements = this.sourceElements;\r\n const sourcesToUpdate = [];\r\n \r\n allSourceElements.forEach((sourceEl) => {\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n const currentSrc = sourceEl.getAttribute('src');\r\n \r\n if (descSrcAttr) {\r\n const type = sourceEl.getAttribute('type');\r\n let origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n // Store current src as data-orig-src if not already set\r\n if (!origSrc) {\r\n origSrc = currentSrc;\r\n }\r\n \r\n // Store info for re-adding with described src\r\n sourcesToUpdate.push({\r\n src: descSrcAttr, // Use described version\r\n type: type,\r\n origSrc: origSrc,\r\n descSrc: descSrcAttr\r\n });\r\n } else {\r\n // Source element without data-desc-src - keep as-is\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n sourcesToUpdate.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: null\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n allSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with updated src attributes (described versions)\r\n sourcesToUpdate.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload by calling load() on the element\r\n // This should pick up the new src attributes from the re-added source elements\r\n // and also reload the track elements\r\n this.element.load();\r\n \r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n \r\n // Wait a bit more for tracks to be recognized and loaded after video metadata loads\r\n await new Promise(resolve => setTimeout(resolve, 300));\r\n\r\n // Hide poster if video hasn't started yet (poster should hide when we seek or play)\r\n if (this.element.tagName === 'VIDEO' && currentTime === 0 && !wasPlaying) {\r\n // Force poster to hide by doing a minimal seek or loading first frame\r\n // Setting readyState check or seeking to 0.001 seconds will hide the poster\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Seek to a tiny fraction to trigger poster hiding without actually moving\r\n this.element.currentTime = 0.001;\r\n // Then seek back to 0 after a brief moment to ensure poster stays hidden\r\n setTimeout(() => {\r\n this.element.currentTime = 0;\r\n }, 10);\r\n }\r\n }\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Update state and emit event\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n } else {\r\n // Fallback to updating element src directly\r\n // Swap caption tracks to described versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n // Swap tracks: validate explicit tracks, but try auto-detected tracks without validation\r\n const validationPromises = this.audioDescriptionCaptionTracks.map(async (trackInfo) => {\r\n if (trackInfo.trackElement && trackInfo.describedSrc) {\r\n // Only validate explicitly defined tracks\r\n // Auto-detected tracks are used without validation (no 404s)\r\n if (trackInfo.explicit === true) {\r\n try {\r\n const exists = await this.validateTrackExists(trackInfo.describedSrc);\r\n return { trackInfo, exists };\r\n } catch (error) {\r\n return { trackInfo, exists: false };\r\n }\r\n } else {\r\n // This shouldn't happen since auto-detection is disabled\r\n return { trackInfo, exists: false };\r\n }\r\n }\r\n return { trackInfo, exists: false };\r\n });\r\n \r\n const validationResults = await Promise.all(validationPromises);\r\n const tracksToSwap = validationResults.filter(result => result.exists);\r\n \r\n if (tracksToSwap.length > 0) {\r\n // Store original track modes before removing tracks\r\n const trackModes = new Map();\r\n tracksToSwap.forEach(({ trackInfo }) => {\r\n const textTrack = trackInfo.trackElement.track;\r\n if (textTrack) {\r\n trackModes.set(trackInfo, {\r\n wasShowing: textTrack.mode === 'showing',\r\n wasHidden: textTrack.mode === 'hidden'\r\n });\r\n } else {\r\n trackModes.set(trackInfo, {\r\n wasShowing: false,\r\n wasHidden: false\r\n });\r\n }\r\n });\r\n \r\n // Store all track information before removing\r\n const tracksToReadd = tracksToSwap.map(({ trackInfo }) => {\r\n const oldSrc = trackInfo.trackElement.getAttribute('src');\r\n const parent = trackInfo.trackElement.parentNode;\r\n const nextSibling = trackInfo.trackElement.nextSibling;\r\n \r\n // Store all attributes from the old track\r\n const attributes = {};\r\n Array.from(trackInfo.trackElement.attributes).forEach(attr => {\r\n attributes[attr.name] = attr.value;\r\n });\r\n \r\n return {\r\n trackInfo,\r\n oldSrc,\r\n parent,\r\n nextSibling,\r\n attributes\r\n };\r\n });\r\n \r\n // Remove ALL old tracks first to force browser to clear TextTrack objects\r\n tracksToReadd.forEach(({ trackInfo }) => {\r\n trackInfo.trackElement.remove();\r\n });\r\n \r\n // Force browser to process the removal by calling load()\r\n this.element.load();\r\n \r\n // Wait for browser to process the removal, then add new tracks\r\n setTimeout(() => {\r\n tracksToReadd.forEach(({ trackInfo, oldSrc, parent, nextSibling, attributes }) => {\r\n swappedTracksForTranscript.push(trackInfo);\r\n \r\n // Create a completely new track element (not a clone) to force browser to create new TextTrack\r\n const newTrackElement = document.createElement('track');\r\n newTrackElement.setAttribute('src', trackInfo.describedSrc);\r\n \r\n // Copy all attributes except src and data-desc-src\r\n Object.keys(attributes).forEach(attrName => {\r\n if (attrName !== 'src' && attrName !== 'data-desc-src') {\r\n newTrackElement.setAttribute(attrName, attributes[attrName]);\r\n }\r\n });\r\n \r\n // Insert new track element\r\n if (nextSibling && nextSibling.parentNode) {\r\n parent.insertBefore(newTrackElement, nextSibling);\r\n } else {\r\n parent.appendChild(newTrackElement);\r\n }\r\n \r\n // Update reference to the new track element\r\n trackInfo.trackElement = newTrackElement;\r\n });\r\n \r\n // After all new tracks are added, force browser to reload media element again\r\n this.element.load();\r\n \r\n // Wait for loadedmetadata event before accessing new TextTrack objects\r\n const setupNewTracks = () => {\r\n // Wait a bit more for browser to fully process the new track elements\r\n setTimeout(() => {\r\n swappedTracksForTranscript.forEach((trackInfo) => {\r\n const trackElement = trackInfo.trackElement;\r\n const newTextTrack = trackElement.track;\r\n \r\n if (newTextTrack) {\r\n // Get original mode from stored map\r\n const modeInfo = trackModes.get(trackInfo) || { wasShowing: false, wasHidden: false };\r\n \r\n // Set mode to load the new track\r\n newTextTrack.mode = 'hidden'; // Use hidden to load cues without showing\r\n \r\n // Restore original mode after track loads\r\n const restoreMode = () => {\r\n if (modeInfo.wasShowing) {\r\n // Set to hidden - CaptionManager will set it to showing when it enables\r\n newTextTrack.mode = 'hidden';\r\n } else if (modeInfo.wasHidden) {\r\n newTextTrack.mode = 'hidden';\r\n } else {\r\n newTextTrack.mode = 'disabled';\r\n }\r\n };\r\n \r\n // Wait for track to load\r\n if (newTextTrack.readyState >= 2) { // LOADED\r\n restoreMode();\r\n } else {\r\n newTextTrack.addEventListener('load', restoreMode, { once: true });\r\n newTextTrack.addEventListener('error', restoreMode, { once: true });\r\n }\r\n }\r\n });\r\n }, 300); // Additional wait for browser to process track elements\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Already loaded, wait a bit and setup\r\n setTimeout(setupNewTracks, 200);\r\n } else {\r\n this.element.addEventListener('loadedmetadata', setupNewTracks, { once: true });\r\n // Fallback timeout\r\n setTimeout(setupNewTracks, 2000);\r\n }\r\n }, 100); // Wait 100ms after first load() before adding new tracks\r\n }\r\n }\r\n \r\n // Check if we have source elements with data-desc-src (fallback method)\r\n const fallbackSourceElements = this.sourceElements;\r\n const hasSourceElementsWithDesc = fallbackSourceElements.some(el => el.getAttribute('data-desc-src'));\r\n \r\n if (hasSourceElementsWithDesc) {\r\n const fallbackSourcesToUpdate = [];\r\n \r\n fallbackSourceElements.forEach((sourceEl) => {\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n const currentSrc = sourceEl.getAttribute('src');\r\n \r\n if (descSrcAttr) {\r\n const type = sourceEl.getAttribute('type');\r\n let origSrc = sourceEl.getAttribute('data-orig-src');\r\n \r\n if (!origSrc) {\r\n origSrc = currentSrc;\r\n }\r\n \r\n fallbackSourcesToUpdate.push({\r\n src: descSrcAttr,\r\n type: type,\r\n origSrc: origSrc,\r\n descSrc: descSrcAttr\r\n });\r\n } else {\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n fallbackSourcesToUpdate.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: null\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n fallbackSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with updated src attributes\r\n fallbackSourcesToUpdate.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload\r\n this.element.load();\r\n this.invalidateTrackCache();\r\n } else {\r\n // Fallback to updating element src directly (for videos without source elements)\r\n this.element.src = this.audioDescriptionSrc;\r\n }\r\n }\r\n\r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n\r\n // Hide poster if video hasn't started yet (poster should hide when we seek or play)\r\n if (this.element.tagName === 'VIDEO' && currentTime === 0 && !wasPlaying) {\r\n // Force poster to hide by doing a minimal seek or loading first frame\r\n // Setting readyState check or seeking to 0.001 seconds will hide the poster\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n // Seek to a tiny fraction to trigger poster hiding without actually moving\r\n this.element.currentTime = 0.001;\r\n // Then seek back to 0 after a brief moment to ensure poster stays hidden\r\n this.setManagedTimeout(() => {\r\n this.element.currentTime = 0;\r\n }, 10);\r\n }\r\n }\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Reload CaptionManager tracks if tracks were swapped (so it has fresh references)\r\n if (swappedTracksForTranscript.length > 0 && this.captionManager) {\r\n // Store if captions were enabled and which track\r\n const wasCaptionsEnabled = this.state.captionsEnabled;\r\n let currentTrackInfo = null;\r\n if (this.captionManager.currentTrack) {\r\n const currentTrackIndex = this.captionManager.tracks.findIndex(t => t.track === this.captionManager.currentTrack.track);\r\n if (currentTrackIndex >= 0) {\r\n currentTrackInfo = {\r\n language: this.captionManager.tracks[currentTrackIndex].language,\r\n kind: this.captionManager.tracks[currentTrackIndex].kind\r\n };\r\n }\r\n }\r\n \r\n // Wait a bit for new tracks to be available, then reload\r\n setTimeout(() => {\r\n // Reload tracks to get fresh references to new TextTrack objects\r\n this.captionManager.tracks = [];\r\n this.captionManager.loadTracks();\r\n \r\n // Re-enable captions if they were enabled before\r\n if (wasCaptionsEnabled && currentTrackInfo && this.captionManager.tracks.length > 0) {\r\n // Find the track by language and kind to match the swapped track\r\n const matchingTrackIndex = this.captionManager.tracks.findIndex(t => \r\n t.language === currentTrackInfo.language && t.kind === currentTrackInfo.kind\r\n );\r\n \r\n if (matchingTrackIndex >= 0) {\r\n this.captionManager.enable(matchingTrackIndex);\r\n } else if (this.captionManager.tracks.length > 0) {\r\n // Fallback: enable first track\r\n this.captionManager.enable(0);\r\n }\r\n }\r\n }, 600); // Wait for tracks to be processed\r\n }\r\n\r\n // Reload transcript if visible (after video metadata loaded, tracks should be available)\r\n // Reload regardless of whether caption tracks were swapped, in case tracks changed\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n // Wait for tracks to load after source swap\r\n // If tracks were swapped, wait for them to load; otherwise wait a bit for any track changes\r\n const swappedTracks = typeof swappedTracksForTranscript !== 'undefined' ? swappedTracksForTranscript : [];\r\n \r\n if (swappedTracks.length > 0) {\r\n // Wait for swapped tracks to load their new cues\r\n // Since we re-added track elements and called load(), wait for loadedmetadata event\r\n // which is when the browser processes track elements\r\n const onMetadataLoaded = () => {\r\n // Get fresh track references from the video element's textTracks collection\r\n // This ensures we get the actual textTrack objects that the browser created\r\n // Invalidate cache first to get fresh tracks after swap\r\n this.invalidateTrackCache();\r\n const allTextTracks = this.textTracks;\r\n \r\n // Find the tracks that match our swapped tracks by language and kind\r\n // Match by checking the track element's src attribute\r\n const freshTracks = swappedTracks.map((trackInfo) => {\r\n const trackEl = trackInfo.trackElement;\r\n const expectedSrc = trackEl.getAttribute('src');\r\n const srclang = trackEl.getAttribute('srclang');\r\n const kind = trackEl.getAttribute('kind');\r\n \r\n // Find matching track in textTracks collection\r\n // First try to match by the track element reference\r\n let foundTrack = allTextTracks.find(track => trackEl.track === track);\r\n \r\n // If not found, try matching by language and kind, but verify src\r\n if (!foundTrack) {\r\n foundTrack = allTextTracks.find(track => {\r\n if (track.language === srclang && \r\n (track.kind === kind || (kind === 'captions' && track.kind === 'subtitles'))) {\r\n // Verify the src matches\r\n const trackElementForTrack = this.findTrackElement(track);\r\n if (trackElementForTrack) {\r\n const actualSrc = trackElementForTrack.getAttribute('src');\r\n if (actualSrc === expectedSrc) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n });\r\n }\r\n \r\n // Verify the track element's src matches what we expect\r\n if (foundTrack) {\r\n const trackElement = this.findTrackElement(foundTrack);\r\n if (trackElement && trackElement.getAttribute('src') !== expectedSrc) {\r\n return null;\r\n }\r\n }\r\n \r\n return foundTrack;\r\n }).filter(Boolean);\r\n \r\n if (freshTracks.length === 0) {\r\n // Fallback: just reload after delay - transcript manager will find tracks itself\r\n this.setManagedTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 1000);\r\n return;\r\n }\r\n \r\n // Ensure tracks are in hidden mode to load cues for transcript\r\n freshTracks.forEach(track => {\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n });\r\n \r\n let loadedCount = 0;\r\n const checkLoaded = () => {\r\n loadedCount++;\r\n if (loadedCount >= freshTracks.length) {\r\n // Give a bit more time for cues to be fully parsed\r\n // Also ensure we're getting the latest TextTrack references\r\n this.setManagedTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n // Force transcript manager to get fresh track references\r\n // Clear any cached track references by forcing a fresh read\r\n // The transcript manager will find tracks from this.element.textTracks\r\n // which should now have the new TextTrack objects with the described captions\r\n \r\n // Verify the tracks have the correct src before reloading transcript\r\n this.invalidateTrackCache();\r\n const allTextTracks = this.textTracks;\r\n const swappedTrackSrcs = swappedTracks.map(t => t.describedSrc);\r\n const hasCorrectTracks = freshTracks.some(track => {\r\n const trackEl = this.findTrackElement(track);\r\n return trackEl && swappedTrackSrcs.includes(trackEl.getAttribute('src'));\r\n });\r\n \r\n if (hasCorrectTracks || freshTracks.length > 0) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }\r\n }, 800); // Increased wait time to ensure cues are fully loaded\r\n }\r\n };\r\n \r\n freshTracks.forEach(track => {\r\n // Ensure track is in hidden mode to load cues (required for transcript)\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n \r\n // Check if track has cues loaded\r\n // Verify the track element's src matches the expected described src\r\n const trackElementForTrack = this.findTrackElement(track);\r\n const actualSrc = trackElementForTrack ? trackElementForTrack.getAttribute('src') : null;\r\n \r\n // Find the expected src from swappedTracks\r\n const expectedTrackInfo = swappedTracks.find(t => {\r\n const tEl = t.trackElement;\r\n return tEl && (tEl.track === track || \r\n (tEl.getAttribute('srclang') === track.language && \r\n tEl.getAttribute('kind') === track.kind));\r\n });\r\n const expectedSrc = expectedTrackInfo ? expectedTrackInfo.describedSrc : null;\r\n \r\n // Only proceed if the src matches (or we can't verify)\r\n if (expectedSrc && actualSrc && actualSrc !== expectedSrc) {\r\n // Wrong track, skip it\r\n checkLoaded(); // Count it as loaded to not block\r\n return;\r\n }\r\n \r\n if (track.readyState >= 2 && track.cues && track.cues.length > 0) { // LOADED with cues\r\n // Track already loaded with cues\r\n checkLoaded();\r\n } else {\r\n // Force track to load by setting mode\r\n if (track.mode === 'disabled') {\r\n track.mode = 'hidden';\r\n }\r\n \r\n // Wait for track to load\r\n const onTrackLoad = () => {\r\n // Wait a bit for cues to be fully parsed\r\n this.setManagedTimeout(checkLoaded, 300);\r\n };\r\n \r\n if (track.readyState >= 2) {\r\n // Already loaded, but might not have cues yet\r\n // Wait a bit and check again\r\n this.setManagedTimeout(() => {\r\n if (track.cues && track.cues.length > 0) {\r\n checkLoaded();\r\n } else {\r\n // Still no cues, wait for load event\r\n track.addEventListener('load', onTrackLoad, { once: true });\r\n }\r\n }, 100);\r\n } else {\r\n track.addEventListener('load', onTrackLoad, { once: true });\r\n track.addEventListener('error', () => {\r\n // Even on error, try to reload transcript\r\n checkLoaded();\r\n }, { once: true });\r\n }\r\n }\r\n });\r\n };\r\n \r\n // Wait for loadedmetadata event which fires when browser processes track elements\r\n // Also wait for the tracks to be fully processed after the second load()\r\n const waitForTracks = () => {\r\n // Wait a bit more to ensure new TextTrack objects are created\r\n this.setManagedTimeout(() => {\r\n if (this.element.readyState >= 1) { // HAVE_METADATA\r\n onMetadataLoaded();\r\n } else {\r\n this.element.addEventListener('loadedmetadata', onMetadataLoaded, { once: true });\r\n // Fallback timeout\r\n this.setManagedTimeout(onMetadataLoaded, 2000);\r\n }\r\n }, 500); // Wait 500ms after second load() for tracks to be processed\r\n };\r\n \r\n waitForTracks();\r\n \r\n // Fallback timeout - longer to ensure tracks are loaded\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 5000);\r\n } else {\r\n // No tracks swapped, just wait a bit and reload\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 800);\r\n }\r\n }\r\n\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n }\r\n\r\n async disableAudioDescription() {\r\n if (!this.originalSrc) {\r\n return;\r\n }\r\n\r\n // Store current playback state\r\n const currentTime = this.state.currentTime;\r\n const wasPlaying = this.state.playing;\r\n\r\n // Swap caption/chapter tracks back to original versions BEFORE loading\r\n if (this.audioDescriptionCaptionTracks.length > 0) {\r\n this.audioDescriptionCaptionTracks.forEach(trackInfo => {\r\n if (trackInfo.trackElement && trackInfo.originalTrackSrc) {\r\n trackInfo.trackElement.setAttribute('src', trackInfo.originalTrackSrc);\r\n }\r\n });\r\n }\r\n \r\n // Swap source elements back to original versions\r\n // Check if we have source elements with data-orig-src\r\n const allSourceElements = this.sourceElements;\r\n const hasSourceElementsToSwap = allSourceElements.some(el => el.getAttribute('data-orig-src'));\r\n \r\n if (hasSourceElementsToSwap) {\r\n const sourcesToRestore = [];\r\n \r\n allSourceElements.forEach((sourceEl) => {\r\n const origSrcAttr = sourceEl.getAttribute('data-orig-src');\r\n const descSrcAttr = sourceEl.getAttribute('data-desc-src');\r\n \r\n if (origSrcAttr) {\r\n // Swap back to original src\r\n const type = sourceEl.getAttribute('type');\r\n sourcesToRestore.push({\r\n src: origSrcAttr, // Use original version\r\n type: type,\r\n origSrc: origSrcAttr,\r\n descSrc: descSrcAttr // Keep data-desc-src for future swaps\r\n });\r\n } else {\r\n // Keep as-is (no data-orig-src means it wasn't swapped)\r\n const type = sourceEl.getAttribute('type');\r\n const src = sourceEl.getAttribute('src');\r\n sourcesToRestore.push({\r\n src: src,\r\n type: type,\r\n origSrc: null,\r\n descSrc: descSrcAttr\r\n });\r\n }\r\n });\r\n \r\n // Remove all source elements\r\n allSourceElements.forEach(sourceEl => {\r\n sourceEl.remove();\r\n });\r\n \r\n // Re-add them with original src attributes\r\n sourcesToRestore.forEach(sourceInfo => {\r\n const newSource = document.createElement('source');\r\n newSource.setAttribute('src', sourceInfo.src);\r\n if (sourceInfo.type) {\r\n newSource.setAttribute('type', sourceInfo.type);\r\n }\r\n if (sourceInfo.origSrc) {\r\n newSource.setAttribute('data-orig-src', sourceInfo.origSrc);\r\n }\r\n if (sourceInfo.descSrc) {\r\n newSource.setAttribute('data-desc-src', sourceInfo.descSrc);\r\n }\r\n this.element.appendChild(newSource);\r\n });\r\n \r\n // Force reload\r\n this.element.load();\r\n } else {\r\n // Fallback to updating element src directly (for videos without source elements)\r\n const originalSrcToUse = this.originalAudioDescriptionSource || this.originalSrc;\r\n this.element.src = originalSrcToUse;\r\n this.element.load();\r\n }\r\n\r\n // Wait for new source to load\r\n await new Promise((resolve) => {\r\n const onLoadedMetadata = () => {\r\n this.element.removeEventListener('loadedmetadata', onLoadedMetadata);\r\n resolve();\r\n };\r\n this.element.addEventListener('loadedmetadata', onLoadedMetadata);\r\n });\r\n\r\n // Restore playback position\r\n this.seek(currentTime);\r\n\r\n if (wasPlaying) {\r\n this.play();\r\n }\r\n\r\n // Reload transcript if visible (after video metadata loaded, tracks should be available)\r\n // Reload regardless of whether caption tracks were swapped, in case tracks changed\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n // Wait for tracks to load after source swap\r\n this.setManagedTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.loadTranscriptData) {\r\n this.transcriptManager.loadTranscriptData();\r\n }\r\n }, 500);\r\n }\r\n\r\n this.state.audioDescriptionEnabled = false;\r\n this.emit('audiodescriptiondisabled');\r\n }\r\n\r\n async toggleAudioDescription() {\r\n // Check if we have description tracks or audio-described video\r\n const descriptionTrack = this.findTextTrack('descriptions');\r\n \r\n // Check if we have audio-described video source (either from options or source elements with data-desc-src)\r\n const hasAudioDescriptionSrc = this.audioDescriptionSrc || \r\n this.sourceElements.some(el => el.getAttribute('data-desc-src'));\r\n \r\n if (descriptionTrack && hasAudioDescriptionSrc) {\r\n // We have both: toggle description track AND swap caption tracks/sources\r\n if (this.state.audioDescriptionEnabled) {\r\n // Disable: toggle description track off and swap captions/sources back\r\n descriptionTrack.mode = 'hidden';\r\n await this.disableAudioDescription();\r\n } else {\r\n // Enable: swap caption tracks/sources and toggle description track on\r\n await this.enableAudioDescription();\r\n // Wait for tracks to be ready after source swap, then enable description track\r\n // Use a longer timeout to ensure tracks are loaded after source swap\r\n const enableDescriptionTrack = () => {\r\n this.invalidateTrackCache();\r\n const descTrack = this.findTextTrack('descriptions');\r\n if (descTrack) {\r\n // Set to 'hidden' first if it's in 'disabled' mode, then to 'showing'\r\n if (descTrack.mode === 'disabled') {\r\n descTrack.mode = 'hidden';\r\n // Use setTimeout to ensure the browser processes the mode change\r\n this.setManagedTimeout(() => {\r\n descTrack.mode = 'showing';\r\n }, 50);\r\n } else {\r\n descTrack.mode = 'showing';\r\n }\r\n } else if (this.element.readyState < 2) {\r\n // Tracks not ready yet, wait a bit more\r\n this.setManagedTimeout(enableDescriptionTrack, 100);\r\n }\r\n };\r\n // Wait for metadata to load first\r\n if (this.element.readyState >= 1) {\r\n this.setManagedTimeout(enableDescriptionTrack, 200);\r\n } else {\r\n this.element.addEventListener('loadedmetadata', () => {\r\n this.setManagedTimeout(enableDescriptionTrack, 200);\r\n }, { once: true });\r\n }\r\n }\r\n } else if (descriptionTrack) {\r\n // Only description track, no audio-described video source to swap\r\n // Toggle description track\r\n if (descriptionTrack.mode === 'showing') {\r\n descriptionTrack.mode = 'hidden';\r\n this.state.audioDescriptionEnabled = false;\r\n this.emit('audiodescriptiondisabled');\r\n } else {\r\n descriptionTrack.mode = 'showing';\r\n this.state.audioDescriptionEnabled = true;\r\n this.emit('audiodescriptionenabled');\r\n }\r\n } else if (hasAudioDescriptionSrc) {\r\n // Use audio-described video source (no description track)\r\n if (this.state.audioDescriptionEnabled) {\r\n await this.disableAudioDescription();\r\n } else {\r\n await this.enableAudioDescription();\r\n }\r\n }\r\n }\r\n\r\n // Sign Language\r\n enableSignLanguage() {\r\n if (!this.signLanguageSrc) {\r\n console.warn('No sign language video source provided');\r\n return;\r\n }\r\n\r\n if (this.signLanguageWrapper) {\r\n // Already exists, just show it\r\n this.signLanguageWrapper.style.display = 'block';\r\n this.state.signLanguageEnabled = true;\r\n this.emit('signlanguageenabled');\r\n return;\r\n }\r\n\r\n // Create wrapper container\r\n this.signLanguageWrapper = document.createElement('div');\r\n this.signLanguageWrapper.className = 'vidply-sign-language-wrapper';\r\n this.signLanguageWrapper.setAttribute('tabindex', '0');\r\n this.signLanguageWrapper.setAttribute('aria-label', 'Sign Language Video - Press D to drag with keyboard, R to resize');\r\n\r\n // Create sign language video element\r\n this.signLanguageVideo = document.createElement('video');\r\n this.signLanguageVideo.className = 'vidply-sign-language-video';\r\n this.signLanguageVideo.src = this.signLanguageSrc;\r\n this.signLanguageVideo.setAttribute('aria-label', i18n.t('player.signLanguage'));\r\n this.signLanguageVideo.muted = true; // Sign language video should be muted\r\n\r\n // Create resize handles\r\n const resizeHandles = ['nw', 'ne', 'sw', 'se'].map(dir => {\r\n const handle = document.createElement('div');\r\n handle.className = `vidply-sign-resize-handle vidply-sign-resize-${dir}`;\r\n handle.setAttribute('data-direction', dir);\r\n handle.setAttribute('aria-label', `Resize ${dir.toUpperCase()}`);\r\n return handle;\r\n });\r\n\r\n // Append video and handles to wrapper\r\n this.signLanguageWrapper.appendChild(this.signLanguageVideo);\r\n resizeHandles.forEach(handle => this.signLanguageWrapper.appendChild(handle));\r\n\r\n // Set width FIRST to ensure proper dimensions\r\n const saved = this.storage.getSignLanguagePreferences();\r\n if (saved && saved.size && saved.size.width) {\r\n this.signLanguageWrapper.style.width = saved.size.width;\r\n } else {\r\n this.signLanguageWrapper.style.width = '280px'; // Default width\r\n }\r\n // Height is always auto to maintain aspect ratio\r\n this.signLanguageWrapper.style.height = 'auto';\r\n \r\n // Position is always calculated fresh - use option or default to bottom-right\r\n this.signLanguageDesiredPosition = this.options.signLanguagePosition || 'bottom-right';\r\n\r\n // Add to main player container (NOT videoWrapper) to avoid overflow:hidden clipping\r\n this.container.appendChild(this.signLanguageWrapper);\r\n\r\n // Set position immediately after appending\r\n requestAnimationFrame(() => {\r\n this.constrainSignLanguagePosition();\r\n });\r\n\r\n // Sync with main video\r\n this.signLanguageVideo.currentTime = this.state.currentTime;\r\n if (!this.state.paused) {\r\n this.signLanguageVideo.play();\r\n }\r\n\r\n // Setup drag and resize\r\n this.setupSignLanguageInteraction();\r\n\r\n // Create bound handlers to store references for cleanup\r\n this.signLanguageHandlers = {\r\n play: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.play();\r\n }\r\n },\r\n pause: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.pause();\r\n }\r\n },\r\n timeupdate: () => {\r\n if (this.signLanguageVideo && Math.abs(this.signLanguageVideo.currentTime - this.state.currentTime) > 0.5) {\r\n this.signLanguageVideo.currentTime = this.state.currentTime;\r\n }\r\n },\r\n ratechange: () => {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.playbackRate = this.state.playbackSpeed;\r\n }\r\n }\r\n };\r\n\r\n // Sync playback\r\n this.on('play', this.signLanguageHandlers.play);\r\n this.on('pause', this.signLanguageHandlers.pause);\r\n this.on('timeupdate', this.signLanguageHandlers.timeupdate);\r\n this.on('ratechange', this.signLanguageHandlers.ratechange);\r\n\r\n this.state.signLanguageEnabled = true;\r\n this.emit('signlanguageenabled');\r\n }\r\n\r\n disableSignLanguage() {\r\n if (this.signLanguageWrapper) {\r\n this.signLanguageWrapper.style.display = 'none';\r\n }\r\n this.state.signLanguageEnabled = false;\r\n this.emit('signlanguagedisabled');\r\n }\r\n\r\n toggleSignLanguage() {\r\n if (this.state.signLanguageEnabled) {\r\n this.disableSignLanguage();\r\n } else {\r\n this.enableSignLanguage();\r\n }\r\n }\r\n\r\n setupSignLanguageInteraction() {\r\n if (!this.signLanguageWrapper) return;\r\n\r\n let isDragging = false;\r\n let isResizing = false;\r\n let resizeDirection = null;\r\n let startX = 0;\r\n let startY = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let dragMode = false;\r\n let resizeMode = false;\r\n\r\n // Mouse drag on video element\r\n const onMouseDownVideo = (e) => {\r\n if (e.target !== this.signLanguageVideo) return;\r\n e.preventDefault();\r\n isDragging = true;\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n startLeft = rect.left;\r\n startTop = rect.top;\r\n this.signLanguageWrapper.classList.add('vidply-sign-dragging');\r\n };\r\n\r\n // Mouse resize on handles\r\n const onMouseDownHandle = (e) => {\r\n if (!e.target.classList.contains('vidply-sign-resize-handle')) return;\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n resizeDirection = e.target.getAttribute('data-direction');\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n startLeft = rect.left;\r\n startTop = rect.top;\r\n startWidth = rect.width;\r\n startHeight = rect.height;\r\n this.signLanguageWrapper.classList.add('vidply-sign-resizing');\r\n };\r\n\r\n const onMouseMove = (e) => {\r\n if (isDragging) {\r\n const deltaX = e.clientX - startX;\r\n const deltaY = e.clientY - startY;\r\n \r\n // Get videoWrapper and container dimensions\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n const wrapperRect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper position relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n \r\n // Calculate new position (in client coordinates)\r\n let newLeft = startLeft + deltaX - containerRect.left;\r\n let newTop = startTop + deltaY - containerRect.top;\r\n \r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n newLeft = Math.max(videoWrapperLeft, Math.min(newLeft, videoWrapperLeft + videoWrapperRect.width - wrapperRect.width));\r\n newTop = Math.max(videoWrapperTop, Math.min(newTop, videoWrapperTop + videoWrapperRect.height - wrapperRect.height - controlsHeight));\r\n \r\n this.signLanguageWrapper.style.left = `${newLeft}px`;\r\n this.signLanguageWrapper.style.top = `${newTop}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n } else if (isResizing) {\r\n const deltaX = e.clientX - startX;\r\n \r\n // Get videoWrapper and container dimensions\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n \r\n let newWidth = startWidth;\r\n let newLeft = startLeft - containerRect.left;\r\n\r\n // Only resize width, let height auto-adjust to maintain aspect ratio\r\n if (resizeDirection.includes('e')) {\r\n newWidth = Math.max(150, startWidth + deltaX);\r\n // Constrain width to not exceed videoWrapper right edge\r\n const maxWidth = (videoWrapperRect.right - startLeft);\r\n newWidth = Math.min(newWidth, maxWidth);\r\n }\r\n if (resizeDirection.includes('w')) {\r\n const proposedWidth = Math.max(150, startWidth - deltaX);\r\n const proposedLeft = startLeft + (startWidth - proposedWidth) - containerRect.left;\r\n // Constrain to not go beyond videoWrapper left edge\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n if (proposedLeft >= videoWrapperLeft) {\r\n newWidth = proposedWidth;\r\n newLeft = proposedLeft;\r\n }\r\n }\r\n\r\n this.signLanguageWrapper.style.width = `${newWidth}px`;\r\n this.signLanguageWrapper.style.height = 'auto'; // Let video maintain aspect ratio\r\n if (resizeDirection.includes('w')) {\r\n this.signLanguageWrapper.style.left = `${newLeft}px`;\r\n }\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n if (isDragging || isResizing) {\r\n this.saveSignLanguagePreferences();\r\n }\r\n isDragging = false;\r\n isResizing = false;\r\n resizeDirection = null;\r\n this.signLanguageWrapper.classList.remove('vidply-sign-dragging', 'vidply-sign-resizing');\r\n };\r\n\r\n // Keyboard controls\r\n const onKeyDown = (e) => {\r\n // Toggle drag mode with D key\r\n if (e.key === 'd' || e.key === 'D') {\r\n dragMode = !dragMode;\r\n resizeMode = false;\r\n this.signLanguageWrapper.classList.toggle('vidply-sign-keyboard-drag', dragMode);\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-resize');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Toggle resize mode with R key\r\n if (e.key === 'r' || e.key === 'R') {\r\n resizeMode = !resizeMode;\r\n dragMode = false;\r\n this.signLanguageWrapper.classList.toggle('vidply-sign-keyboard-resize', resizeMode);\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-drag');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Escape to exit modes\r\n if (e.key === 'Escape') {\r\n dragMode = false;\r\n resizeMode = false;\r\n this.signLanguageWrapper.classList.remove('vidply-sign-keyboard-drag', 'vidply-sign-keyboard-resize');\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n // Arrow keys for drag/resize\r\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\r\n const step = e.shiftKey ? 10 : 5;\r\n const rect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Get videoWrapper and container bounds\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper position relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n\r\n if (dragMode) {\r\n // Get current position relative to container\r\n let left = rect.left - containerRect.left;\r\n let top = rect.top - containerRect.top;\r\n\r\n if (e.key === 'ArrowLeft') left -= step;\r\n if (e.key === 'ArrowRight') left += step;\r\n if (e.key === 'ArrowUp') top -= step;\r\n if (e.key === 'ArrowDown') top += step;\r\n\r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n left = Math.max(videoWrapperLeft, Math.min(left, videoWrapperLeft + videoWrapperRect.width - rect.width));\r\n top = Math.max(videoWrapperTop, Math.min(top, videoWrapperTop + videoWrapperRect.height - rect.height - controlsHeight));\r\n\r\n this.signLanguageWrapper.style.left = `${left}px`;\r\n this.signLanguageWrapper.style.top = `${top}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n this.saveSignLanguagePreferences();\r\n e.preventDefault();\r\n } else if (resizeMode) {\r\n let width = rect.width;\r\n\r\n // Only adjust width, height will auto-adjust to maintain aspect ratio\r\n if (e.key === 'ArrowLeft') width -= step;\r\n if (e.key === 'ArrowRight') width += step;\r\n // Up/Down also adjusts width for simplicity\r\n if (e.key === 'ArrowUp') width += step;\r\n if (e.key === 'ArrowDown') width -= step;\r\n\r\n // Constrain width\r\n width = Math.max(150, width);\r\n // Don't let it exceed videoWrapper width\r\n width = Math.min(width, videoWrapperRect.width);\r\n\r\n this.signLanguageWrapper.style.width = `${width}px`;\r\n this.signLanguageWrapper.style.height = 'auto';\r\n this.saveSignLanguagePreferences();\r\n e.preventDefault();\r\n }\r\n }\r\n };\r\n\r\n // Attach event listeners\r\n this.signLanguageVideo.addEventListener('mousedown', onMouseDownVideo);\r\n const handles = this.signLanguageWrapper.querySelectorAll('.vidply-sign-resize-handle');\r\n handles.forEach(handle => handle.addEventListener('mousedown', onMouseDownHandle));\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n this.signLanguageWrapper.addEventListener('keydown', onKeyDown);\r\n\r\n // Store for cleanup\r\n this.signLanguageInteractionHandlers = {\r\n mouseDownVideo: onMouseDownVideo,\r\n mouseDownHandle: onMouseDownHandle,\r\n mouseMove: onMouseMove,\r\n mouseUp: onMouseUp,\r\n keyDown: onKeyDown,\r\n handles\r\n };\r\n }\r\n\r\n constrainSignLanguagePosition() {\r\n if (!this.signLanguageWrapper || !this.videoWrapper) return;\r\n \r\n // Ensure width is set\r\n if (!this.signLanguageWrapper.style.width || this.signLanguageWrapper.style.width === '') {\r\n this.signLanguageWrapper.style.width = '280px'; // Default width\r\n }\r\n \r\n // Get videoWrapper position relative to the player CONTAINER (where sign language video is attached)\r\n const videoWrapperRect = this.videoWrapper.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n const wrapperRect = this.signLanguageWrapper.getBoundingClientRect();\r\n \r\n // Calculate videoWrapper's position and dimensions relative to container\r\n const videoWrapperLeft = videoWrapperRect.left - containerRect.left;\r\n const videoWrapperTop = videoWrapperRect.top - containerRect.top;\r\n const videoWrapperWidth = videoWrapperRect.width;\r\n const videoWrapperHeight = videoWrapperRect.height;\r\n \r\n // Use estimated height if video hasn't loaded yet (16:9 aspect ratio)\r\n let wrapperWidth = wrapperRect.width || 280;\r\n let wrapperHeight = wrapperRect.height || ((280 * 9) / 16); // Estimate based on 16:9 aspect ratio\r\n \r\n let left, top;\r\n const margin = 16; // Margin from edges\r\n const controlsHeight = 95; // Height of controls when visible\r\n \r\n // Always calculate fresh position based on desired location (relative to videoWrapper)\r\n const position = this.signLanguageDesiredPosition || 'bottom-right';\r\n \r\n switch (position) {\r\n case 'bottom-right':\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n break;\r\n case 'bottom-left':\r\n left = videoWrapperLeft + margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n break;\r\n case 'top-right':\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + margin;\r\n break;\r\n case 'top-left':\r\n left = videoWrapperLeft + margin;\r\n top = videoWrapperTop + margin;\r\n break;\r\n default:\r\n left = videoWrapperLeft + videoWrapperWidth - wrapperWidth - margin;\r\n top = videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight;\r\n }\r\n \r\n // Constrain to videoWrapper bounds (ensuring it stays above controls)\r\n left = Math.max(videoWrapperLeft, Math.min(left, videoWrapperLeft + videoWrapperWidth - wrapperWidth));\r\n top = Math.max(videoWrapperTop, Math.min(top, videoWrapperTop + videoWrapperHeight - wrapperHeight - controlsHeight));\r\n \r\n // Apply constrained position\r\n this.signLanguageWrapper.style.left = `${left}px`;\r\n this.signLanguageWrapper.style.top = `${top}px`;\r\n this.signLanguageWrapper.style.right = 'auto';\r\n this.signLanguageWrapper.style.bottom = 'auto';\r\n // Remove position classes if any were applied\r\n this.signLanguageWrapper.classList.remove(...Array.from(this.signLanguageWrapper.classList).filter(c => c.startsWith('vidply-sign-position-')));\r\n }\r\n\r\n saveSignLanguagePreferences() {\r\n if (!this.signLanguageWrapper) return;\r\n \r\n // Only save width - position is always calculated fresh to bottom-right\r\n this.storage.saveSignLanguagePreferences({\r\n size: {\r\n width: this.signLanguageWrapper.style.width\r\n // Height is auto - maintained by aspect ratio\r\n }\r\n });\r\n }\r\n\r\n cleanupSignLanguage() {\r\n // Remove event listeners\r\n if (this.signLanguageHandlers) {\r\n this.off('play', this.signLanguageHandlers.play);\r\n this.off('pause', this.signLanguageHandlers.pause);\r\n this.off('timeupdate', this.signLanguageHandlers.timeupdate);\r\n this.off('ratechange', this.signLanguageHandlers.ratechange);\r\n this.signLanguageHandlers = null;\r\n }\r\n\r\n // Remove interaction handlers\r\n if (this.signLanguageInteractionHandlers) {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.removeEventListener('mousedown', this.signLanguageInteractionHandlers.mouseDownVideo);\r\n }\r\n if (this.signLanguageInteractionHandlers.handles) {\r\n this.signLanguageInteractionHandlers.handles.forEach(handle => {\r\n handle.removeEventListener('mousedown', this.signLanguageInteractionHandlers.mouseDownHandle);\r\n });\r\n }\r\n document.removeEventListener('mousemove', this.signLanguageInteractionHandlers.mouseMove);\r\n document.removeEventListener('mouseup', this.signLanguageInteractionHandlers.mouseUp);\r\n if (this.signLanguageWrapper) {\r\n this.signLanguageWrapper.removeEventListener('keydown', this.signLanguageInteractionHandlers.keyDown);\r\n }\r\n this.signLanguageInteractionHandlers = null;\r\n }\r\n\r\n // Remove video and wrapper elements\r\n if (this.signLanguageWrapper && this.signLanguageWrapper.parentNode) {\r\n if (this.signLanguageVideo) {\r\n this.signLanguageVideo.pause();\r\n this.signLanguageVideo.src = '';\r\n }\r\n this.signLanguageWrapper.parentNode.removeChild(this.signLanguageWrapper);\r\n this.signLanguageWrapper = null;\r\n this.signLanguageVideo = null;\r\n }\r\n }\r\n\r\n // Settings\r\n // Settings dialog removed - using individual control buttons instead\r\n showSettings() {\r\n console.warn('[VidPly] Settings dialog has been removed. Use individual control buttons (speed, captions, etc.)');\r\n }\r\n\r\n hideSettings() {\r\n // No-op - settings dialog removed\r\n }\r\n\r\n // Utility methods\r\n getCurrentTime() {\r\n return this.state.currentTime;\r\n }\r\n\r\n getDuration() {\r\n return this.state.duration;\r\n }\r\n\r\n isPlaying() {\r\n return this.state.playing;\r\n }\r\n\r\n isPaused() {\r\n return this.state.paused;\r\n }\r\n\r\n isEnded() {\r\n return this.state.ended;\r\n }\r\n\r\n isMuted() {\r\n return this.state.muted;\r\n }\r\n\r\n isFullscreen() {\r\n return this.state.fullscreen;\r\n }\r\n\r\n // Error handling\r\n handleError(error) {\r\n this.log('Error:', error, 'error');\r\n this.emit('error', error);\r\n\r\n if (this.options.onError) {\r\n this.options.onError.call(this, error);\r\n }\r\n }\r\n\r\n // Logging\r\n log(...messages) {\r\n if (!this.options.debug) {\r\n return;\r\n }\r\n\r\n let type = 'log';\r\n if (messages.length > 0) {\r\n const potentialType = messages[messages.length - 1];\r\n if (typeof potentialType === 'string' && console[potentialType]) {\r\n type = potentialType;\r\n messages = messages.slice(0, -1);\r\n }\r\n }\r\n\r\n if (messages.length === 0) {\r\n messages = [''];\r\n }\r\n\r\n if (typeof console[type] === 'function') {\r\n console[type]('[VidPly]', ...messages);\r\n } else {\r\n console.log('[VidPly]', ...messages);\r\n }\r\n }\r\n\r\n // Setup responsive handlers\r\n setupResponsiveHandlers() {\r\n // Use ResizeObserver for efficient resize tracking\r\n if (typeof ResizeObserver !== 'undefined') {\r\n this.resizeObserver = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n const width = entry.contentRect.width;\r\n\r\n // Update control bar for viewport\r\n if (this.controlBar && typeof this.controlBar.updateControlsForViewport === 'function') {\r\n this.controlBar.updateControlsForViewport(width);\r\n }\r\n\r\n // Update transcript positioning\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n }\r\n });\r\n\r\n this.resizeObserver.observe(this.container);\r\n } else {\r\n // Fallback to window resize event\r\n this.resizeHandler = () => {\r\n const width = this.container.clientWidth;\r\n\r\n if (this.controlBar && typeof this.controlBar.updateControlsForViewport === 'function') {\r\n this.controlBar.updateControlsForViewport(width);\r\n }\r\n\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n };\r\n\r\n window.addEventListener('resize', this.resizeHandler);\r\n }\r\n\r\n // Also listen for orientation changes on mobile\r\n if (window.matchMedia) {\r\n this.orientationHandler = (e) => {\r\n // Wait for layout to settle\r\n setTimeout(() => {\r\n if (this.transcriptManager && this.transcriptManager.isVisible) {\r\n this.transcriptManager.positionTranscript();\r\n }\r\n }, 100);\r\n };\r\n\r\n const orientationQuery = window.matchMedia('(orientation: portrait)');\r\n if (orientationQuery.addEventListener) {\r\n orientationQuery.addEventListener('change', this.orientationHandler);\r\n } else if (orientationQuery.addListener) {\r\n // Fallback for older browsers\r\n orientationQuery.addListener(this.orientationHandler);\r\n }\r\n\r\n this.orientationQuery = orientationQuery;\r\n }\r\n\r\n // Listen for native fullscreen change events (e.g., when user presses ESC)\r\n this.fullscreenChangeHandler = () => {\r\n const isFullscreen = !!(\r\n document.fullscreenElement ||\r\n document.webkitFullscreenElement ||\r\n document.mozFullScreenElement ||\r\n document.msFullscreenElement\r\n );\r\n\r\n // Only update if state has changed\r\n if (this.state.fullscreen !== isFullscreen) {\r\n this.state.fullscreen = isFullscreen;\r\n \r\n if (isFullscreen) {\r\n this.container.classList.add(`${this.options.classPrefix}-fullscreen`);\r\n } else {\r\n this.container.classList.remove(`${this.options.classPrefix}-fullscreen`);\r\n }\r\n \r\n this.emit('fullscreenchange', isFullscreen);\r\n \r\n // Update fullscreen button icon\r\n if (this.controlBar) {\r\n this.controlBar.updateFullscreenButton();\r\n }\r\n \r\n // Reposition sign language video after fullscreen transition\r\n if (this.signLanguageWrapper && this.signLanguageWrapper.style.display !== 'none') {\r\n // Use setTimeout to ensure layout has updated after fullscreen transition\r\n // Longer delay to account for CSS transition animations and layout recalculation\r\n this.setManagedTimeout(() => {\r\n // Use requestAnimationFrame to ensure the browser has fully rendered the layout\r\n requestAnimationFrame(() => {\r\n // Clear saved size and reset to default for the new container size\r\n this.storage.saveSignLanguagePreferences({ size: null });\r\n this.signLanguageDesiredPosition = 'bottom-right';\r\n // Reset to default width for the new container\r\n this.signLanguageWrapper.style.width = isFullscreen ? '400px' : '280px';\r\n this.constrainSignLanguagePosition();\r\n });\r\n }, 500);\r\n }\r\n }\r\n };\r\n\r\n // Add listeners for all vendor-prefixed fullscreenchange events\r\n document.addEventListener('fullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('mozfullscreenchange', this.fullscreenChangeHandler);\r\n document.addEventListener('MSFullscreenChange', this.fullscreenChangeHandler);\r\n }\r\n\r\n // Cleanup\r\n destroy() {\r\n this.log('Destroying player');\r\n\r\n if (this.renderer) {\r\n this.renderer.destroy();\r\n }\r\n\r\n if (this.controlBar) {\r\n this.controlBar.destroy();\r\n }\r\n\r\n if (this.captionManager) {\r\n this.captionManager.destroy();\r\n }\r\n\r\n if (this.keyboardManager) {\r\n this.keyboardManager.destroy();\r\n }\r\n\r\n if (this.transcriptManager) {\r\n this.transcriptManager.destroy();\r\n }\r\n\r\n // Cleanup sign language video and listeners\r\n this.cleanupSignLanguage();\r\n\r\n // Cleanup play overlay button\r\n if (this.playButtonOverlay && this.playButtonOverlay.parentNode) {\r\n this.playButtonOverlay.remove();\r\n this.playButtonOverlay = null;\r\n }\r\n\r\n // Cleanup resize observer\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n\r\n // Cleanup window resize handler\r\n if (this.resizeHandler) {\r\n window.removeEventListener('resize', this.resizeHandler);\r\n this.resizeHandler = null;\r\n }\r\n\r\n // Cleanup orientation change handler\r\n if (this.orientationQuery && this.orientationHandler) {\r\n if (this.orientationQuery.removeEventListener) {\r\n this.orientationQuery.removeEventListener('change', this.orientationHandler);\r\n } else if (this.orientationQuery.removeListener) {\r\n this.orientationQuery.removeListener(this.orientationHandler);\r\n }\r\n this.orientationQuery = null;\r\n this.orientationHandler = null;\r\n }\r\n\r\n // Cleanup fullscreen change handler\r\n if (this.fullscreenChangeHandler) {\r\n document.removeEventListener('fullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('webkitfullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('mozfullscreenchange', this.fullscreenChangeHandler);\r\n document.removeEventListener('MSFullscreenChange', this.fullscreenChangeHandler);\r\n this.fullscreenChangeHandler = null;\r\n }\r\n\r\n // Cleanup all managed timeouts\r\n this.timeouts.forEach(timeoutId => clearTimeout(timeoutId));\r\n this.timeouts.clear();\r\n\r\n // Cleanup metadata handling\r\n if (this.metadataCueChangeHandler) {\r\n const textTracks = this.textTracks;\r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n if (metadataTrack) {\r\n metadataTrack.removeEventListener('cuechange', this.metadataCueChangeHandler);\r\n }\r\n this.metadataCueChangeHandler = null;\r\n }\r\n\r\n if (this.metadataAlertHandlers && this.metadataAlertHandlers.size > 0) {\r\n this.metadataAlertHandlers.forEach(({ button, handler }) => {\r\n if (button && handler) {\r\n button.removeEventListener('click', handler);\r\n }\r\n });\r\n this.metadataAlertHandlers.clear();\r\n }\r\n\r\n // Remove container\r\n if (this.container && this.container.parentNode) {\r\n this.container.parentNode.insertBefore(this.element, this.container);\r\n this.container.parentNode.removeChild(this.container);\r\n }\r\n\r\n this.removeAllListeners();\r\n }\r\n\r\n /**\r\n * Setup metadata track handling\r\n * This enables metadata tracks and listens for cue changes to trigger actions\r\n */\r\n setupMetadataHandling() {\r\n const setupMetadata = () => {\r\n const textTracks = this.textTracks;\r\n const metadataTrack = textTracks.find(track => track.kind === 'metadata');\r\n \r\n if (metadataTrack) {\r\n // Enable the metadata track so cuechange events fire\r\n // Use 'hidden' mode so it doesn't display anything, but events still work\r\n if (metadataTrack.mode === 'disabled') {\r\n metadataTrack.mode = 'hidden';\r\n }\r\n \r\n // Remove existing listener if any\r\n if (this.metadataCueChangeHandler) {\r\n metadataTrack.removeEventListener('cuechange', this.metadataCueChangeHandler);\r\n }\r\n \r\n // Add event listener for cue changes\r\n this.metadataCueChangeHandler = () => {\r\n const activeCues = Array.from(metadataTrack.activeCues || []);\r\n if (activeCues.length > 0) {\r\n // Debug logging\r\n if (this.options.debug) {\r\n this.log('[Metadata] Active cues:', activeCues.map(c => ({\r\n start: c.startTime,\r\n end: c.endTime,\r\n text: c.text\r\n })));\r\n }\r\n }\r\n activeCues.forEach(cue => {\r\n this.handleMetadataCue(cue);\r\n });\r\n };\r\n \r\n metadataTrack.addEventListener('cuechange', this.metadataCueChangeHandler);\r\n \r\n // Debug: Log metadata track setup\r\n if (this.options.debug) {\r\n const cueCount = metadataTrack.cues ? metadataTrack.cues.length : 0;\r\n this.log('[Metadata] Track enabled,', cueCount, 'cues available');\r\n }\r\n } else if (this.options.debug) {\r\n this.log('[Metadata] No metadata track found');\r\n }\r\n };\r\n \r\n // Try immediately\r\n setupMetadata();\r\n \r\n // Also try after loadedmetadata event (tracks might not be ready yet)\r\n this.on('loadedmetadata', setupMetadata);\r\n }\r\n\r\n normalizeMetadataSelector(selector) {\r\n if (!selector) {\r\n return null;\r\n }\r\n const trimmed = selector.trim();\r\n if (!trimmed) {\r\n return null;\r\n }\r\n if (trimmed.startsWith('#') || trimmed.startsWith('.') || trimmed.startsWith('[')) {\r\n return trimmed;\r\n }\r\n return `#${trimmed}`;\r\n }\r\n\r\n resolveMetadataConfig(map, key) {\r\n if (!map || !key) {\r\n return null;\r\n }\r\n if (Object.prototype.hasOwnProperty.call(map, key)) {\r\n return map[key];\r\n }\r\n const withoutHash = key.replace(/^#/, '');\r\n if (Object.prototype.hasOwnProperty.call(map, withoutHash)) {\r\n return map[withoutHash];\r\n }\r\n return null;\r\n }\r\n\r\n cacheMetadataAlertContent(element, config = {}) {\r\n if (!element) {\r\n return;\r\n }\r\n const titleSelector = config.titleSelector || '[data-vidply-alert-title], h3, header';\r\n const messageSelector = config.messageSelector || '[data-vidply-alert-message], p';\r\n\r\n const titleEl = element.querySelector(titleSelector);\r\n if (titleEl && !titleEl.dataset.vidplyAlertTitleOriginal) {\r\n titleEl.dataset.vidplyAlertTitleOriginal = titleEl.textContent.trim();\r\n }\r\n\r\n const messageEl = element.querySelector(messageSelector);\r\n if (messageEl && !messageEl.dataset.vidplyAlertMessageOriginal) {\r\n messageEl.dataset.vidplyAlertMessageOriginal = messageEl.textContent.trim();\r\n }\r\n }\r\n\r\n restoreMetadataAlertContent(element, config = {}) {\r\n if (!element) {\r\n return;\r\n }\r\n const titleSelector = config.titleSelector || '[data-vidply-alert-title], h3, header';\r\n const messageSelector = config.messageSelector || '[data-vidply-alert-message], p';\r\n\r\n const titleEl = element.querySelector(titleSelector);\r\n if (titleEl && titleEl.dataset.vidplyAlertTitleOriginal) {\r\n titleEl.textContent = titleEl.dataset.vidplyAlertTitleOriginal;\r\n }\r\n\r\n const messageEl = element.querySelector(messageSelector);\r\n if (messageEl && messageEl.dataset.vidplyAlertMessageOriginal) {\r\n messageEl.textContent = messageEl.dataset.vidplyAlertMessageOriginal;\r\n }\r\n }\r\n\r\n focusMetadataTarget(target, fallbackElement = null) {\r\n if (!target || target === 'none') {\r\n return;\r\n }\r\n\r\n if (target === 'alert' && fallbackElement) {\r\n fallbackElement.focus();\r\n return;\r\n }\r\n\r\n if (target === 'player') {\r\n if (this.container) {\r\n this.container.focus();\r\n }\r\n return;\r\n }\r\n\r\n if (target === 'media') {\r\n this.element.focus();\r\n return;\r\n }\r\n\r\n if (target === 'playButton') {\r\n const playButton = this.controlBar?.controls?.playPause;\r\n if (playButton) {\r\n playButton.focus();\r\n }\r\n return;\r\n }\r\n\r\n if (typeof target === 'string') {\r\n const targetElement = document.querySelector(target);\r\n if (targetElement) {\r\n if (targetElement.tabIndex === -1 && !targetElement.hasAttribute('tabindex')) {\r\n targetElement.setAttribute('tabindex', '-1');\r\n }\r\n targetElement.focus();\r\n }\r\n }\r\n }\r\n\r\n handleMetadataAlert(selector, options = {}) {\r\n if (!selector) {\r\n return;\r\n }\r\n\r\n const config = this.resolveMetadataConfig(this.options.metadataAlerts, selector) || {};\r\n const element = options.element || document.querySelector(selector);\r\n\r\n if (!element) {\r\n if (this.options.debug) {\r\n this.log('[Metadata] Alert element not found:', selector);\r\n }\r\n return;\r\n }\r\n\r\n if (this.options.debug) {\r\n this.log('[Metadata] Handling alert', selector, { reason: options.reason, config });\r\n }\r\n\r\n this.cacheMetadataAlertContent(element, config);\r\n\r\n if (!element.dataset.vidplyAlertOriginalDisplay) {\r\n element.dataset.vidplyAlertOriginalDisplay = element.style.display || '';\r\n }\r\n\r\n if (!element.dataset.vidplyAlertDisplay) {\r\n element.dataset.vidplyAlertDisplay = config.display || 'block';\r\n }\r\n\r\n const shouldShow = options.show !== undefined ? options.show : (config.show !== false);\r\n if (shouldShow) {\r\n const displayValue = config.display || element.dataset.vidplyAlertDisplay || 'block';\r\n element.style.display = displayValue;\r\n element.hidden = false;\r\n element.removeAttribute('hidden');\r\n element.setAttribute('aria-hidden', 'false');\r\n element.setAttribute('data-vidply-alert-active', 'true');\r\n }\r\n\r\n const shouldReset = config.resetContent !== false && options.reason === 'focus';\r\n if (shouldReset) {\r\n this.restoreMetadataAlertContent(element, config);\r\n }\r\n\r\n const shouldFocus = options.focus !== undefined\r\n ? options.focus\r\n : (config.focusOnShow ?? (options.reason !== 'focus'));\r\n\r\n if (shouldShow && shouldFocus) {\r\n if (element.tabIndex === -1 && !element.hasAttribute('tabindex')) {\r\n element.setAttribute('tabindex', '-1');\r\n }\r\n element.focus();\r\n }\r\n\r\n if (shouldShow && config.autoScroll !== false && options.autoScroll !== false) {\r\n element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n }\r\n\r\n const continueSelector = config.continueButton;\r\n if (continueSelector) {\r\n let continueButton = null;\r\n if (continueSelector === 'self') {\r\n continueButton = element;\r\n } else if (element.matches(continueSelector)) {\r\n continueButton = element;\r\n } else {\r\n continueButton = element.querySelector(continueSelector) || document.querySelector(continueSelector);\r\n }\r\n\r\n if (continueButton && !this.metadataAlertHandlers.has(selector)) {\r\n const handler = () => {\r\n const hideOnContinue = config.hideOnContinue !== false;\r\n if (hideOnContinue) {\r\n const originalDisplay = element.dataset.vidplyAlertOriginalDisplay || '';\r\n element.style.display = config.hideDisplay || originalDisplay || 'none';\r\n element.setAttribute('aria-hidden', 'true');\r\n element.removeAttribute('data-vidply-alert-active');\r\n }\r\n\r\n if (config.resume !== false && this.state.paused) {\r\n this.play();\r\n }\r\n\r\n const focusTarget = config.focusTarget || 'playButton';\r\n this.setManagedTimeout(() => {\r\n this.focusMetadataTarget(focusTarget, element);\r\n }, config.focusDelay ?? 100);\r\n };\r\n\r\n continueButton.addEventListener('click', handler);\r\n this.metadataAlertHandlers.set(selector, { button: continueButton, handler });\r\n }\r\n }\r\n\r\n return element;\r\n }\r\n\r\n handleMetadataHashtags(hashtags) {\r\n if (!Array.isArray(hashtags) || hashtags.length === 0) {\r\n return;\r\n }\r\n\r\n const configMap = this.options.metadataHashtags;\r\n if (!configMap) {\r\n return;\r\n }\r\n\r\n hashtags.forEach(tag => {\r\n const config = this.resolveMetadataConfig(configMap, tag);\r\n if (!config) {\r\n return;\r\n }\r\n\r\n const selector = this.normalizeMetadataSelector(config.alert || config.selector || config.target);\r\n if (!selector) {\r\n return;\r\n }\r\n\r\n const element = document.querySelector(selector);\r\n if (!element) {\r\n if (this.options.debug) {\r\n this.log('[Metadata] Hashtag target not found:', selector);\r\n }\r\n return;\r\n }\r\n\r\n if (this.options.debug) {\r\n this.log('[Metadata] Handling hashtag', tag, { selector, config });\r\n }\r\n\r\n this.cacheMetadataAlertContent(element, config);\r\n\r\n if (config.title) {\r\n const titleSelector = config.titleSelector || '[data-vidply-alert-title], h3, header';\r\n const titleEl = element.querySelector(titleSelector);\r\n if (titleEl) {\r\n titleEl.textContent = config.title;\r\n }\r\n }\r\n\r\n if (config.message) {\r\n const messageSelector = config.messageSelector || '[data-vidply-alert-message], p';\r\n const messageEl = element.querySelector(messageSelector);\r\n if (messageEl) {\r\n messageEl.textContent = config.message;\r\n }\r\n }\r\n\r\n const show = config.show !== false;\r\n const focus = config.focus !== undefined ? config.focus : false;\r\n\r\n this.handleMetadataAlert(selector, {\r\n element,\r\n show,\r\n focus,\r\n autoScroll: config.autoScroll,\r\n reason: 'hashtag'\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Handle individual metadata cues\r\n * Parses metadata text and emits events or triggers actions\r\n */\r\n handleMetadataCue(cue) {\r\n const text = cue.text.trim();\r\n \r\n // Debug logging\r\n if (this.options.debug) {\r\n this.log('[Metadata] Processing cue:', {\r\n time: cue.startTime,\r\n text: text\r\n });\r\n }\r\n \r\n // Emit a generic metadata event that developers can listen to\r\n this.emit('metadata', {\r\n time: cue.startTime,\r\n endTime: cue.endTime,\r\n text: text,\r\n cue: cue\r\n });\r\n\r\n // Parse for specific commands (examples based on wwa_meta.vtt format)\r\n if (text.includes('PAUSE')) {\r\n // Automatically pause the video\r\n if (!this.state.paused) {\r\n if (this.options.debug) {\r\n this.log('[Metadata] Pausing video at', cue.startTime);\r\n }\r\n this.pause();\r\n }\r\n // Also emit event for developers who want to listen\r\n this.emit('metadata:pause', { time: cue.startTime, text: text });\r\n }\r\n\r\n // Parse for focus directives\r\n const focusMatch = text.match(/FOCUS:([\\w#-]+)/);\r\n if (focusMatch) {\r\n const targetSelector = focusMatch[1];\r\n const normalizedSelector = this.normalizeMetadataSelector(targetSelector);\r\n // Automatically focus the target element\r\n const targetElement = normalizedSelector ? document.querySelector(normalizedSelector) : null;\r\n if (targetElement) {\r\n if (this.options.debug) {\r\n this.log('[Metadata] Focusing element:', normalizedSelector);\r\n }\r\n // Make element focusable if it isn't already\r\n if (targetElement.tabIndex === -1 && !targetElement.hasAttribute('tabindex')) {\r\n targetElement.setAttribute('tabindex', '-1');\r\n }\r\n // Use setTimeout to ensure DOM is ready\r\n this.setManagedTimeout(() => {\r\n targetElement.focus();\r\n // Scroll element into view if needed\r\n targetElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n }, 10);\r\n } else if (this.options.debug) {\r\n this.log('[Metadata] Element not found:', normalizedSelector || targetSelector);\r\n }\r\n // Also emit event for developers who want to listen\r\n this.emit('metadata:focus', { \r\n time: cue.startTime, \r\n target: targetSelector,\r\n selector: normalizedSelector,\r\n element: targetElement,\r\n text: text \r\n });\r\n\r\n if (normalizedSelector) {\r\n this.handleMetadataAlert(normalizedSelector, {\r\n element: targetElement,\r\n reason: 'focus'\r\n });\r\n }\r\n }\r\n\r\n // Parse for hashtag references\r\n const hashtags = text.match(/#[\\w-]+/g);\r\n if (hashtags) {\r\n if (this.options.debug) {\r\n this.log('[Metadata] Hashtags found:', hashtags);\r\n }\r\n this.emit('metadata:hashtags', {\r\n time: cue.startTime,\r\n hashtags: hashtags,\r\n text: text\r\n });\r\n\r\n this.handleMetadataHashtags(hashtags);\r\n }\r\n }\r\n}\r\n\r\n// Static instances tracker for pause others functionality\r\nPlayer.instances = [];\r\n\r\n", "/**\r\n * YouTube Renderer\r\n */\r\n\r\nexport class YouTubeRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.youtube = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL\r\n this.videoId = this.extractVideoId(this.player.element.src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid YouTube URL');\r\n }\r\n\r\n // Load YouTube IFrame API\r\n await this.loadYouTubeAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/)([^&\\s]+)/,\r\n /youtube\\.com\\/embed\\/([^&\\s]+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadYouTubeAPI() {\r\n // Check if API is already loaded\r\n if (window.YT && window.YT.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n // Check if script is already being loaded\r\n if (window.onYouTubeIframeAPIReady) {\r\n const originalCallback = window.onYouTubeIframeAPIReady;\r\n window.onYouTubeIframeAPIReady = () => {\r\n originalCallback();\r\n resolve();\r\n };\r\n return;\r\n }\r\n\r\n // Load the API script\r\n const tag = document.createElement('script');\r\n tag.src = 'https://www.youtube.com/iframe_api';\r\n \r\n window.onYouTubeIframeAPIReady = () => {\r\n resolve();\r\n };\r\n\r\n tag.onerror = () => reject(new Error('Failed to load YouTube API'));\r\n \r\n const firstScriptTag = document.getElementsByTagName('script')[0];\r\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `youtube-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.height = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n return new Promise((resolve) => {\r\n this.youtube = new window.YT.Player(this.iframe.id, {\r\n videoId: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n playerVars: {\r\n controls: 0,\r\n disablekb: 1,\r\n fs: 0,\r\n modestbranding: 1,\r\n rel: 0,\r\n showinfo: 0,\r\n iv_load_policy: 3,\r\n autoplay: this.player.options.autoplay ? 1 : 0,\r\n mute: this.player.options.muted ? 1 : 0,\r\n start: this.player.options.startTime || 0\r\n },\r\n events: {\r\n onReady: (event) => {\r\n this.isReady = true;\r\n this.attachEvents();\r\n resolve();\r\n },\r\n onStateChange: (event) => this.handleStateChange(event),\r\n onError: (event) => this.handleError(event)\r\n }\r\n });\r\n });\r\n }\r\n\r\n attachEvents() {\r\n // Set up polling for time updates (YouTube doesn't provide timeupdate events)\r\n this.timeUpdateInterval = setInterval(() => {\r\n if (this.isReady && this.youtube) {\r\n const currentTime = this.youtube.getCurrentTime();\r\n const duration = this.youtube.getDuration();\r\n \r\n this.player.state.currentTime = currentTime;\r\n this.player.state.duration = duration;\r\n \r\n this.player.emit('timeupdate', currentTime);\r\n }\r\n }, 250);\r\n\r\n // Initial metadata\r\n if (this.youtube.getDuration) {\r\n this.player.state.duration = this.youtube.getDuration();\r\n this.player.emit('loadedmetadata');\r\n }\r\n }\r\n\r\n handleStateChange(event) {\r\n const states = window.YT.PlayerState;\r\n\r\n switch (event.data) {\r\n case states.PLAYING:\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.state.buffering = false;\r\n this.player.emit('play');\r\n this.player.emit('playing');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n break;\r\n\r\n case states.PAUSED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n break;\r\n\r\n case states.ENDED:\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.youtube.seekTo(0);\r\n this.youtube.playVideo();\r\n }\r\n break;\r\n\r\n case states.BUFFERING:\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n break;\r\n\r\n case states.CUED:\r\n this.player.emit('loadedmetadata');\r\n break;\r\n }\r\n }\r\n\r\n handleError(event) {\r\n const errors = {\r\n 2: 'Invalid video ID',\r\n 5: 'HTML5 player error',\r\n 100: 'Video not found',\r\n 101: 'Video not allowed to be played in embedded players',\r\n 150: 'Video not allowed to be played in embedded players'\r\n };\r\n\r\n const error = new Error(errors[event.data] || 'YouTube player error');\r\n this.player.handleError(error);\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.playVideo();\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.pauseVideo();\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.seekTo(time, true);\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setVolume(volume * 100);\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.youtube) {\r\n if (muted) {\r\n this.youtube.mute();\r\n } else {\r\n this.youtube.unMute();\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.youtube) {\r\n this.youtube.setPlaybackRate(speed);\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.timeUpdateInterval) {\r\n clearInterval(this.timeUpdateInterval);\r\n }\r\n\r\n if (this.youtube && this.youtube.destroy) {\r\n this.youtube.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * Vimeo Renderer\r\n */\r\n\r\nexport class VimeoRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.vimeo = null;\r\n this.videoId = null;\r\n this.isReady = false;\r\n this.iframe = null;\r\n }\r\n\r\n async init() {\r\n // Extract video ID from URL\r\n this.videoId = this.extractVideoId(this.player.element.src);\r\n \r\n if (!this.videoId) {\r\n throw new Error('Invalid Vimeo URL');\r\n }\r\n\r\n // Load Vimeo Player API\r\n await this.loadVimeoAPI();\r\n\r\n // Create iframe\r\n this.createIframe();\r\n\r\n // Initialize player\r\n await this.initializePlayer();\r\n }\r\n\r\n extractVideoId(url) {\r\n const patterns = [\r\n /vimeo\\.com\\/(\\d+)/,\r\n /vimeo\\.com\\/video\\/(\\d+)/,\r\n /player\\.vimeo\\.com\\/video\\/(\\d+)/\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = url.match(pattern);\r\n if (match && match[1]) {\r\n return match[1];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n async loadVimeoAPI() {\r\n // Check if API is already loaded\r\n if (window.Vimeo && window.Vimeo.Player) {\r\n return Promise.resolve();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://player.vimeo.com/api/player.js';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load Vimeo API'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n createIframe() {\r\n // Hide original element\r\n this.player.element.style.display = 'none';\r\n\r\n // Create container for iframe\r\n this.iframe = document.createElement('div');\r\n this.iframe.id = `vimeo-player-${Math.random().toString(36).substr(2, 9)}`;\r\n this.iframe.style.width = '100%';\r\n this.iframe.style.height = '100%';\r\n \r\n this.player.element.parentNode.insertBefore(this.iframe, this.player.element);\r\n }\r\n\r\n async initializePlayer() {\r\n const options = {\r\n id: this.videoId,\r\n width: '100%',\r\n height: '100%',\r\n controls: false,\r\n autoplay: this.player.options.autoplay,\r\n muted: this.player.options.muted,\r\n loop: this.player.options.loop,\r\n keyboard: false\r\n };\r\n\r\n if (this.player.options.startTime > 0) {\r\n options.startTime = this.player.options.startTime;\r\n }\r\n\r\n this.vimeo = new window.Vimeo.Player(this.iframe.id, options);\r\n\r\n // Wait for player to be ready\r\n await this.vimeo.ready();\r\n this.isReady = true;\r\n\r\n this.attachEvents();\r\n\r\n // Get initial duration\r\n try {\r\n const duration = await this.vimeo.getDuration();\r\n this.player.state.duration = duration;\r\n this.player.emit('loadedmetadata');\r\n } catch (error) {\r\n this.player.log('Error getting duration:', error, 'warn');\r\n }\r\n }\r\n\r\n attachEvents() {\r\n this.vimeo.on('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n });\r\n\r\n this.vimeo.on('timeupdate', (data) => {\r\n this.player.state.currentTime = data.seconds;\r\n this.player.state.duration = data.duration;\r\n this.player.emit('timeupdate', data.seconds);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, data.seconds);\r\n }\r\n });\r\n\r\n this.vimeo.on('volumechange', (data) => {\r\n this.player.state.volume = data.volume;\r\n this.player.emit('volumechange', data.volume);\r\n });\r\n\r\n this.vimeo.on('bufferstart', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.vimeo.on('bufferend', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.vimeo.on('seeking', () => {\r\n this.player.state.seeking = true;\r\n this.player.emit('seeking');\r\n });\r\n\r\n this.vimeo.on('seeked', () => {\r\n this.player.state.seeking = false;\r\n this.player.emit('seeked');\r\n });\r\n\r\n this.vimeo.on('playbackratechange', (data) => {\r\n this.player.state.playbackSpeed = data.playbackRate;\r\n this.player.emit('ratechange', data.playbackRate);\r\n });\r\n\r\n this.vimeo.on('error', (error) => {\r\n this.player.handleError(new Error(`Vimeo error: ${error.message}`));\r\n });\r\n }\r\n\r\n play() {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.play().catch(error => {\r\n this.player.log('Play error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.pause().catch(error => {\r\n this.player.log('Pause error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n seek(time) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setCurrentTime(time).catch(error => {\r\n this.player.log('Seek error:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n setVolume(volume) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setVolume(volume).catch(error => {\r\n this.player.log('Volume error:', error, 'warn');\r\n });\r\n this.player.state.volume = volume;\r\n }\r\n }\r\n\r\n setMuted(muted) {\r\n if (this.isReady && this.vimeo) {\r\n if (muted) {\r\n this.vimeo.setVolume(0);\r\n } else {\r\n this.vimeo.setVolume(this.player.state.volume);\r\n }\r\n this.player.state.muted = muted;\r\n }\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n if (this.isReady && this.vimeo) {\r\n this.vimeo.setPlaybackRate(speed).catch(error => {\r\n this.player.log('Playback rate error:', error, 'warn');\r\n });\r\n this.player.state.playbackSpeed = speed;\r\n }\r\n }\r\n\r\n destroy() {\r\n if (this.vimeo && this.vimeo.destroy) {\r\n this.vimeo.destroy();\r\n }\r\n\r\n if (this.iframe && this.iframe.parentNode) {\r\n this.iframe.parentNode.removeChild(this.iframe);\r\n }\r\n\r\n // Show original element\r\n if (this.player.element) {\r\n this.player.element.style.display = '';\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * HLS Streaming Renderer\r\n * Uses hls.js for browsers that don't natively support HLS\r\n */\r\n\r\nexport class HLSRenderer {\r\n constructor(player) {\r\n this.player = player;\r\n this.media = player.element;\r\n this.hls = null;\r\n }\r\n\r\n async init() {\r\n // Check if browser natively supports HLS (Safari)\r\n if (this.canPlayNatively()) {\r\n this.player.log('Using native HLS support');\r\n await this.initNative();\r\n } else {\r\n this.player.log('Using hls.js for HLS support');\r\n await this.initHlsJs();\r\n }\r\n }\r\n\r\n canPlayNatively() {\r\n const video = document.createElement('video');\r\n return video.canPlayType('application/vnd.apple.mpegurl') !== '';\r\n }\r\n\r\n async initNative() {\r\n // Use HTML5 renderer for native HLS support\r\n const HTML5Renderer = (await import('./HTML5Renderer.js')).HTML5Renderer;\r\n const renderer = new HTML5Renderer(this.player);\r\n await renderer.init();\r\n \r\n // Copy methods\r\n Object.getOwnPropertyNames(Object.getPrototypeOf(renderer)).forEach(method => {\r\n if (method !== 'constructor' && typeof renderer[method] === 'function') {\r\n this[method] = renderer[method].bind(renderer);\r\n }\r\n });\r\n }\r\n\r\n async initHlsJs() {\r\n // Hide native controls\r\n this.media.controls = false;\r\n this.media.removeAttribute('controls');\r\n \r\n // Load hls.js if not already loaded\r\n if (!window.Hls) {\r\n await this.loadHlsJs();\r\n }\r\n\r\n if (!window.Hls.isSupported()) {\r\n throw new Error('HLS is not supported in this browser');\r\n }\r\n\r\n // Create hls.js instance with better error recovery\r\n this.hls = new window.Hls({\r\n debug: this.player.options.debug,\r\n enableWorker: true,\r\n lowLatencyMode: false,\r\n backBufferLength: 90,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n maxBufferSize: 60 * 1000 * 1000,\r\n maxBufferHole: 0.5,\r\n // Network retry settings\r\n manifestLoadingTimeOut: 10000,\r\n manifestLoadingMaxRetry: 4,\r\n manifestLoadingRetryDelay: 1000,\r\n manifestLoadingMaxRetryTimeout: 64000,\r\n levelLoadingTimeOut: 10000,\r\n levelLoadingMaxRetry: 4,\r\n levelLoadingRetryDelay: 1000,\r\n levelLoadingMaxRetryTimeout: 64000,\r\n fragLoadingTimeOut: 20000,\r\n fragLoadingMaxRetry: 6,\r\n fragLoadingRetryDelay: 1000,\r\n fragLoadingMaxRetryTimeout: 64000\r\n });\r\n\r\n // Attach media element\r\n this.hls.attachMedia(this.media);\r\n\r\n // Load source - Get from attribute to avoid blob URL conversion\r\n let src;\r\n const sourceElement = this.player.element.querySelector('source');\r\n if (sourceElement) {\r\n // Use getAttribute to get the original URL, not the blob-converted one\r\n src = sourceElement.getAttribute('src');\r\n } else {\r\n // Fallback to element's src attribute\r\n src = this.player.element.getAttribute('src') || this.player.element.src;\r\n }\r\n \r\n this.player.log(`Loading HLS source: ${src}`, 'log');\r\n \r\n if (!src) {\r\n throw new Error('No HLS source found');\r\n }\r\n \r\n this.hls.loadSource(src);\r\n\r\n // Attach events\r\n this.attachHlsEvents();\r\n this.attachMediaEvents();\r\n }\r\n\r\n async loadHlsJs() {\r\n return new Promise((resolve, reject) => {\r\n const script = document.createElement('script');\r\n script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';\r\n script.onload = () => resolve();\r\n script.onerror = () => reject(new Error('Failed to load hls.js'));\r\n document.head.appendChild(script);\r\n });\r\n }\r\n\r\n attachHlsEvents() {\r\n this.hls.on(window.Hls.Events.MANIFEST_PARSED, (event, data) => {\r\n this.player.log('HLS manifest loaded, found ' + data.levels.length + ' quality levels');\r\n this.player.emit('hlsmanifestparsed', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.LEVEL_SWITCHED, (event, data) => {\r\n this.player.log('HLS level switched to ' + data.level);\r\n this.player.emit('hlslevelswitched', data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.ERROR, (event, data) => {\r\n this.handleHlsError(data);\r\n });\r\n\r\n this.hls.on(window.Hls.Events.FRAG_BUFFERED, () => {\r\n this.player.state.buffering = false;\r\n });\r\n }\r\n\r\n attachMediaEvents() {\r\n // Use same events as HTML5 renderer\r\n this.media.addEventListener('loadedmetadata', () => {\r\n this.player.state.duration = this.media.duration;\r\n this.player.emit('loadedmetadata');\r\n });\r\n\r\n this.media.addEventListener('play', () => {\r\n this.player.state.playing = true;\r\n this.player.state.paused = false;\r\n this.player.state.ended = false;\r\n this.player.emit('play');\r\n \r\n if (this.player.options.onPlay) {\r\n this.player.options.onPlay.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('pause', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.emit('pause');\r\n \r\n if (this.player.options.onPause) {\r\n this.player.options.onPause.call(this.player);\r\n }\r\n });\r\n\r\n this.media.addEventListener('ended', () => {\r\n this.player.state.playing = false;\r\n this.player.state.paused = true;\r\n this.player.state.ended = true;\r\n this.player.emit('ended');\r\n \r\n if (this.player.options.onEnded) {\r\n this.player.options.onEnded.call(this.player);\r\n }\r\n \r\n if (this.player.options.loop) {\r\n this.player.seek(0);\r\n this.player.play();\r\n }\r\n });\r\n\r\n this.media.addEventListener('timeupdate', () => {\r\n this.player.state.currentTime = this.media.currentTime;\r\n this.player.emit('timeupdate', this.media.currentTime);\r\n \r\n if (this.player.options.onTimeUpdate) {\r\n this.player.options.onTimeUpdate.call(this.player, this.media.currentTime);\r\n }\r\n });\r\n\r\n this.media.addEventListener('volumechange', () => {\r\n this.player.state.volume = this.media.volume;\r\n this.player.state.muted = this.media.muted;\r\n this.player.emit('volumechange', this.media.volume);\r\n });\r\n\r\n this.media.addEventListener('waiting', () => {\r\n this.player.state.buffering = true;\r\n this.player.emit('waiting');\r\n });\r\n\r\n this.media.addEventListener('canplay', () => {\r\n this.player.state.buffering = false;\r\n this.player.emit('canplay');\r\n });\r\n\r\n this.media.addEventListener('error', () => {\r\n this.player.handleError(this.media.error);\r\n });\r\n }\r\n\r\n handleHlsError(data) {\r\n // Log detailed error info\r\n this.player.log(`HLS Error - Type: ${data.type}, Details: ${data.details}, Fatal: ${data.fatal}`, 'warn');\r\n if (data.response) {\r\n this.player.log(`Response code: ${data.response.code}, URL: ${data.response.url}`, 'warn');\r\n }\r\n \r\n if (data.fatal) {\r\n switch (data.type) {\r\n case window.Hls.ErrorTypes.NETWORK_ERROR:\r\n this.player.log('Fatal network error, trying to recover...', 'error');\r\n this.player.log(`Network error details: ${data.details}`, 'error');\r\n setTimeout(() => {\r\n this.hls.startLoad();\r\n }, 1000);\r\n break;\r\n \r\n case window.Hls.ErrorTypes.MEDIA_ERROR:\r\n this.player.log('Fatal media error, trying to recover...', 'error');\r\n this.hls.recoverMediaError();\r\n break;\r\n \r\n default:\r\n this.player.log('Fatal error, cannot recover', 'error');\r\n this.player.handleError(new Error(`HLS Error: ${data.type} - ${data.details}`));\r\n this.hls.destroy();\r\n break;\r\n }\r\n } else {\r\n this.player.log('Non-fatal HLS error: ' + data.details, 'warn');\r\n }\r\n }\r\n\r\n play() {\r\n const promise = this.media.play();\r\n \r\n if (promise !== undefined) {\r\n promise.catch(error => {\r\n this.player.log('Play failed:', error, 'warn');\r\n });\r\n }\r\n }\r\n\r\n pause() {\r\n this.media.pause();\r\n }\r\n\r\n seek(time) {\r\n this.media.currentTime = time;\r\n }\r\n\r\n setVolume(volume) {\r\n this.media.volume = volume;\r\n }\r\n\r\n setMuted(muted) {\r\n this.media.muted = muted;\r\n }\r\n\r\n setPlaybackSpeed(speed) {\r\n this.media.playbackRate = speed;\r\n }\r\n\r\n switchQuality(levelIndex) {\r\n if (this.hls) {\r\n this.hls.currentLevel = levelIndex;\r\n }\r\n }\r\n\r\n getQualities() {\r\n if (this.hls && this.hls.levels) {\r\n return this.hls.levels.map((level, index) => ({\r\n index,\r\n height: level.height,\r\n width: level.width,\r\n bitrate: level.bitrate,\r\n name: `${level.height}p`\r\n }));\r\n }\r\n return [];\r\n }\r\n\r\n destroy() {\r\n if (this.hls) {\r\n this.hls.destroy();\r\n this.hls = null;\r\n }\r\n }\r\n}\r\n\r\n", "/**\r\n * VidPly Playlist Manager\r\n * Manages playlists for audio and video content\r\n */\r\n\r\nimport { DOMUtils } from '../utils/DOMUtils.js';\r\nimport { createIconElement } from '../icons/Icons.js';\r\n\r\nexport class PlaylistManager {\r\n constructor(player, options = {}) {\r\n this.player = player;\r\n this.tracks = [];\r\n this.currentIndex = -1;\r\n \r\n // Options\r\n this.options = {\r\n autoAdvance: options.autoAdvance !== false, // Default true\r\n loop: options.loop || false,\r\n showPanel: options.showPanel !== false, // Default true\r\n ...options\r\n };\r\n \r\n // UI elements\r\n this.container = null;\r\n this.playlistPanel = null;\r\n this.trackInfoElement = null;\r\n \r\n // Bind methods\r\n this.handleTrackEnd = this.handleTrackEnd.bind(this);\r\n this.handleTrackError = this.handleTrackError.bind(this);\r\n \r\n // Register this playlist manager with the player\r\n this.player.playlistManager = this;\r\n \r\n // Initialize\r\n this.init();\r\n \r\n // Update controls to add playlist buttons\r\n this.updatePlayerControls();\r\n }\r\n \r\n init() {\r\n // Listen for track end\r\n this.player.on('ended', this.handleTrackEnd);\r\n this.player.on('error', this.handleTrackError);\r\n \r\n // Create UI if needed\r\n if (this.options.showPanel) {\r\n this.createUI();\r\n }\r\n }\r\n \r\n /**\r\n * Update player controls to add playlist navigation buttons\r\n */\r\n updatePlayerControls() {\r\n if (!this.player.controlBar) return;\r\n \r\n const controlBar = this.player.controlBar;\r\n \r\n // Clear existing controls content (except the element itself)\r\n controlBar.element.innerHTML = '';\r\n \r\n // Recreate controls with playlist buttons now available\r\n controlBar.createControls();\r\n \r\n // Reattach events for the new controls\r\n controlBar.attachEvents();\r\n controlBar.setupAutoHide();\r\n }\r\n \r\n /**\r\n * Load a playlist\r\n * @param {Array} tracks - Array of track objects\r\n */\r\n loadPlaylist(tracks) {\r\n this.tracks = tracks;\r\n this.currentIndex = -1;\r\n \r\n // Add playlist class to container\r\n if (this.container) {\r\n this.container.classList.add('vidply-has-playlist');\r\n }\r\n \r\n // Update UI\r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n \r\n // Auto-play first track\r\n if (tracks.length > 0) {\r\n this.play(0);\r\n }\r\n }\r\n \r\n /**\r\n * Play a specific track\r\n * @param {number} index - Track index\r\n * @param {boolean} userInitiated - Whether this was triggered by user action (default: false)\r\n */\r\n play(index, userInitiated = false) {\r\n if (index < 0 || index >= this.tracks.length) {\r\n console.warn('VidPly Playlist: Invalid track index', index);\r\n return;\r\n }\r\n \r\n const track = this.tracks[index];\r\n \r\n // Update current index\r\n this.currentIndex = index;\r\n \r\n // Load track into player\r\n this.player.load({\r\n src: track.src,\r\n type: track.type,\r\n poster: track.poster,\r\n tracks: track.tracks || []\r\n });\r\n \r\n // Update UI\r\n this.updateTrackInfo(track);\r\n this.updatePlaylistUI();\r\n \r\n // Emit event\r\n this.player.emit('playlisttrackchange', {\r\n index: index,\r\n item: track,\r\n total: this.tracks.length\r\n });\r\n \r\n // Return focus to player for keyboard navigation (only on user action)\r\n if (userInitiated && this.player.container) {\r\n this.player.container.focus();\r\n }\r\n \r\n // Auto-play\r\n setTimeout(() => {\r\n this.player.play();\r\n }, 100);\r\n }\r\n \r\n /**\r\n * Play next track\r\n */\r\n next() {\r\n let nextIndex = this.currentIndex + 1;\r\n \r\n if (nextIndex >= this.tracks.length) {\r\n if (this.options.loop) {\r\n nextIndex = 0;\r\n } else {\r\n return;\r\n }\r\n }\r\n \r\n this.play(nextIndex);\r\n }\r\n \r\n /**\r\n * Play previous track\r\n */\r\n previous() {\r\n let prevIndex = this.currentIndex - 1;\r\n \r\n if (prevIndex < 0) {\r\n if (this.options.loop) {\r\n prevIndex = this.tracks.length - 1;\r\n } else {\r\n return;\r\n }\r\n }\r\n \r\n this.play(prevIndex);\r\n }\r\n \r\n /**\r\n * Handle track end\r\n */\r\n handleTrackEnd() {\r\n if (this.options.autoAdvance) {\r\n this.next();\r\n }\r\n }\r\n \r\n /**\r\n * Handle track error\r\n */\r\n handleTrackError(e) {\r\n console.error('VidPly Playlist: Track error', e);\r\n \r\n // Try next track\r\n if (this.options.autoAdvance) {\r\n setTimeout(() => {\r\n this.next();\r\n }, 1000);\r\n }\r\n }\r\n \r\n /**\r\n * Create playlist UI\r\n */\r\n createUI() {\r\n // Find player container\r\n this.container = this.player.container;\r\n \r\n if (!this.container) {\r\n console.warn('VidPly Playlist: No container found');\r\n return;\r\n }\r\n \r\n // Create track info element (shows current track)\r\n this.trackInfoElement = DOMUtils.createElement('div', {\r\n className: 'vidply-track-info',\r\n role: 'status',\r\n 'aria-live': 'polite',\r\n 'aria-atomic': 'true'\r\n });\r\n this.trackInfoElement.style.display = 'none';\r\n \r\n this.container.appendChild(this.trackInfoElement);\r\n \r\n // Create playlist panel with proper landmark\r\n this.playlistPanel = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-panel',\r\n role: 'region',\r\n 'aria-label': 'Media playlist'\r\n });\r\n this.playlistPanel.style.display = 'none';\r\n \r\n this.container.appendChild(this.playlistPanel);\r\n }\r\n \r\n /**\r\n * Update track info display\r\n */\r\n updateTrackInfo(track) {\r\n if (!this.trackInfoElement) return;\r\n \r\n const trackNumber = this.currentIndex + 1;\r\n const totalTracks = this.tracks.length;\r\n const trackTitle = track.title || 'Untitled';\r\n const trackArtist = track.artist || '';\r\n \r\n // Screen reader announcement\r\n const announcement = `Now playing: Track ${trackNumber} of ${totalTracks}. ${trackTitle}${trackArtist ? ' by ' + trackArtist : ''}`;\r\n \r\n this.trackInfoElement.innerHTML = `\r\n <span class=\"vidply-sr-only\">${DOMUtils.escapeHTML(announcement)}</span>\r\n <div class=\"vidply-track-number\" aria-hidden=\"true\">Track ${trackNumber} of ${totalTracks}</div>\r\n <div class=\"vidply-track-title\" aria-hidden=\"true\">${DOMUtils.escapeHTML(trackTitle)}</div>\r\n ${trackArtist ? `<div class=\"vidply-track-artist\" aria-hidden=\"true\">${DOMUtils.escapeHTML(trackArtist)}</div>` : ''}\r\n `;\r\n \r\n this.trackInfoElement.style.display = 'block';\r\n }\r\n \r\n /**\r\n * Render playlist\r\n */\r\n renderPlaylist() {\r\n if (!this.playlistPanel) return;\r\n \r\n // Clear existing\r\n this.playlistPanel.innerHTML = '';\r\n \r\n // Create header\r\n const header = DOMUtils.createElement('h2', {\r\n className: 'vidply-playlist-header',\r\n id: 'vidply-playlist-heading'\r\n });\r\n header.textContent = `Playlist (${this.tracks.length})`;\r\n this.playlistPanel.appendChild(header);\r\n \r\n // Add keyboard instructions (visually hidden)\r\n const instructions = DOMUtils.createElement('div', {\r\n className: 'vidply-sr-only',\r\n 'aria-hidden': 'false'\r\n });\r\n instructions.textContent = 'Use arrow keys to navigate between tracks. Press Enter or Space to play a track. Press Home or End to jump to first or last track.';\r\n this.playlistPanel.appendChild(instructions);\r\n \r\n // Create list (proper ul element)\r\n const list = DOMUtils.createElement('ul', {\r\n className: 'vidply-playlist-list',\r\n 'aria-labelledby': 'vidply-playlist-heading',\r\n 'aria-describedby': 'vidply-playlist-instructions'\r\n });\r\n \r\n // Add list description\r\n const listDescription = DOMUtils.createElement('div', {\r\n className: 'vidply-sr-only',\r\n id: 'vidply-playlist-instructions'\r\n });\r\n listDescription.textContent = `Playlist with ${this.tracks.length} ${this.tracks.length === 1 ? 'track' : 'tracks'}`;\r\n this.playlistPanel.appendChild(listDescription);\r\n \r\n this.tracks.forEach((track, index) => {\r\n const item = this.createPlaylistItem(track, index);\r\n list.appendChild(item);\r\n });\r\n \r\n this.playlistPanel.appendChild(list);\r\n this.playlistPanel.style.display = 'block';\r\n }\r\n \r\n /**\r\n * Create playlist item element\r\n */\r\n createPlaylistItem(track, index) {\r\n const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;\r\n const trackTitle = track.title || `Track ${index + 1}`;\r\n const trackArtist = track.artist ? ` by ${track.artist}` : '';\r\n const isActive = index === this.currentIndex;\r\n const statusText = isActive ? 'Currently playing' : 'Not playing';\r\n const actionText = isActive ? 'Press Enter to restart' : 'Press Enter to play';\r\n \r\n const item = DOMUtils.createElement('li', {\r\n className: 'vidply-playlist-item',\r\n tabIndex: index === 0 ? 0 : -1, // Only first item is in tab order initially\r\n 'aria-label': `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`,\r\n 'aria-posinset': index + 1,\r\n 'aria-setsize': this.tracks.length,\r\n 'data-playlist-index': index\r\n });\r\n \r\n // Add active class if current\r\n if (isActive) {\r\n item.classList.add('vidply-playlist-item-active');\r\n item.setAttribute('aria-current', 'true');\r\n item.setAttribute('tabIndex', '0'); // Active item should always be tabbable\r\n }\r\n \r\n // Add screen reader only position info\r\n const positionInfo = DOMUtils.createElement('span', {\r\n className: 'vidply-sr-only'\r\n });\r\n positionInfo.textContent = `${trackPosition}: `;\r\n item.appendChild(positionInfo);\r\n \r\n // Thumbnail or icon\r\n const thumbnail = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-thumbnail',\r\n 'aria-hidden': 'true'\r\n });\r\n \r\n if (track.poster) {\r\n thumbnail.style.backgroundImage = `url(${track.poster})`;\r\n thumbnail.setAttribute('role', 'img');\r\n thumbnail.setAttribute('aria-label', `${trackTitle} thumbnail`);\r\n } else {\r\n // Show music/speaker icon for audio tracks\r\n const icon = createIconElement('music');\r\n icon.classList.add('vidply-playlist-thumbnail-icon');\r\n thumbnail.appendChild(icon);\r\n }\r\n \r\n item.appendChild(thumbnail);\r\n \r\n // Info\r\n const info = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-info',\r\n 'aria-hidden': 'true'\r\n });\r\n \r\n const title = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-title'\r\n });\r\n title.textContent = trackTitle;\r\n info.appendChild(title);\r\n \r\n if (track.artist) {\r\n const artist = DOMUtils.createElement('div', {\r\n className: 'vidply-playlist-item-artist'\r\n });\r\n artist.textContent = track.artist;\r\n info.appendChild(artist);\r\n }\r\n \r\n item.appendChild(info);\r\n \r\n // Status indicator for screen readers\r\n if (isActive) {\r\n const statusIndicator = DOMUtils.createElement('span', {\r\n className: 'vidply-sr-only'\r\n });\r\n statusIndicator.textContent = ' (Currently playing)';\r\n item.appendChild(statusIndicator);\r\n }\r\n \r\n // Play icon\r\n const playIcon = createIconElement('play');\r\n playIcon.classList.add('vidply-playlist-item-icon');\r\n playIcon.setAttribute('aria-hidden', 'true');\r\n item.appendChild(playIcon);\r\n \r\n // Click handler\r\n item.addEventListener('click', () => {\r\n this.play(index, true); // User-initiated\r\n });\r\n \r\n // Keyboard handler\r\n item.addEventListener('keydown', (e) => {\r\n this.handlePlaylistItemKeydown(e, index);\r\n });\r\n \r\n return item;\r\n }\r\n \r\n /**\r\n * Handle keyboard navigation in playlist items\r\n */\r\n handlePlaylistItemKeydown(e, index) {\r\n const items = Array.from(this.playlistPanel.querySelectorAll('.vidply-playlist-item'));\r\n let newIndex = -1;\r\n \r\n switch(e.key) {\r\n case 'Enter':\r\n case ' ':\r\n e.preventDefault();\r\n this.play(index, true); // User-initiated\r\n break;\r\n \r\n case 'ArrowDown':\r\n e.preventDefault();\r\n // Move to next item\r\n if (index < items.length - 1) {\r\n newIndex = index + 1;\r\n }\r\n break;\r\n \r\n case 'ArrowUp':\r\n e.preventDefault();\r\n // Move to previous item\r\n if (index > 0) {\r\n newIndex = index - 1;\r\n }\r\n break;\r\n \r\n case 'Home':\r\n e.preventDefault();\r\n // Move to first item\r\n newIndex = 0;\r\n break;\r\n \r\n case 'End':\r\n e.preventDefault();\r\n // Move to last item\r\n newIndex = items.length - 1;\r\n break;\r\n }\r\n \r\n // Update tab indices for roving tabindex pattern\r\n if (newIndex !== -1 && newIndex !== index) {\r\n items[index].setAttribute('tabIndex', '-1');\r\n items[newIndex].setAttribute('tabIndex', '0');\r\n items[newIndex].focus();\r\n }\r\n }\r\n \r\n /**\r\n * Update playlist UI (highlight current track)\r\n */\r\n updatePlaylistUI() {\r\n if (!this.playlistPanel) return;\r\n \r\n const items = this.playlistPanel.querySelectorAll('.vidply-playlist-item');\r\n \r\n items.forEach((item, index) => {\r\n const track = this.tracks[index];\r\n const trackPosition = `Track ${index + 1} of ${this.tracks.length}`;\r\n const trackTitle = track.title || `Track ${index + 1}`;\r\n const trackArtist = track.artist ? ` by ${track.artist}` : '';\r\n \r\n if (index === this.currentIndex) {\r\n item.classList.add('vidply-playlist-item-active');\r\n item.setAttribute('aria-current', 'true');\r\n item.setAttribute('tabIndex', '0'); // Active item should be tabbable\r\n \r\n const statusText = 'Currently playing';\r\n const actionText = 'Press Enter to restart';\r\n item.setAttribute('aria-label', `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`);\r\n \r\n // Scroll into view\r\n item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\r\n } else {\r\n item.classList.remove('vidply-playlist-item-active');\r\n item.removeAttribute('aria-current');\r\n item.setAttribute('tabIndex', '-1'); // Remove from tab order (use arrow keys)\r\n \r\n const statusText = 'Not playing';\r\n const actionText = 'Press Enter to play';\r\n item.setAttribute('aria-label', `${trackPosition}. ${trackTitle}${trackArtist}. ${statusText}. ${actionText}.`);\r\n }\r\n });\r\n }\r\n \r\n /**\r\n * Get current track\r\n */\r\n getCurrentTrack() {\r\n return this.tracks[this.currentIndex] || null;\r\n }\r\n \r\n /**\r\n * Get playlist info\r\n */\r\n getPlaylistInfo() {\r\n return {\r\n currentIndex: this.currentIndex,\r\n totalTracks: this.tracks.length,\r\n currentTrack: this.getCurrentTrack(),\r\n hasNext: this.hasNext(),\r\n hasPrevious: this.hasPrevious()\r\n };\r\n }\r\n \r\n /**\r\n * Check if there is a next track\r\n */\r\n hasNext() {\r\n if (this.options.loop) return true;\r\n return this.currentIndex < this.tracks.length - 1;\r\n }\r\n \r\n /**\r\n * Check if there is a previous track\r\n */\r\n hasPrevious() {\r\n if (this.options.loop) return true;\r\n return this.currentIndex > 0;\r\n }\r\n \r\n /**\r\n * Add track to playlist\r\n */\r\n addTrack(track) {\r\n this.tracks.push(track);\r\n \r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n }\r\n \r\n /**\r\n * Remove track from playlist\r\n */\r\n removeTrack(index) {\r\n if (index < 0 || index >= this.tracks.length) return;\r\n \r\n this.tracks.splice(index, 1);\r\n \r\n // Adjust current index if needed\r\n if (index < this.currentIndex) {\r\n this.currentIndex--;\r\n } else if (index === this.currentIndex) {\r\n // Current track was removed, play next or stop\r\n if (this.currentIndex >= this.tracks.length) {\r\n this.currentIndex = this.tracks.length - 1;\r\n }\r\n \r\n if (this.currentIndex >= 0) {\r\n this.play(this.currentIndex);\r\n }\r\n }\r\n \r\n if (this.playlistPanel) {\r\n this.renderPlaylist();\r\n }\r\n }\r\n \r\n /**\r\n * Clear playlist\r\n */\r\n clear() {\r\n this.tracks = [];\r\n this.currentIndex = -1;\r\n \r\n if (this.playlistPanel) {\r\n this.playlistPanel.innerHTML = '';\r\n this.playlistPanel.style.display = 'none';\r\n }\r\n \r\n if (this.trackInfoElement) {\r\n this.trackInfoElement.innerHTML = '';\r\n this.trackInfoElement.style.display = 'none';\r\n }\r\n }\r\n \r\n /**\r\n * Destroy playlist manager\r\n */\r\n destroy() {\r\n // Remove event listeners\r\n this.player.off('ended', this.handleTrackEnd);\r\n this.player.off('error', this.handleTrackError);\r\n \r\n // Remove UI\r\n if (this.trackInfoElement) {\r\n this.trackInfoElement.remove();\r\n }\r\n \r\n if (this.playlistPanel) {\r\n this.playlistPanel.remove();\r\n }\r\n \r\n // Clear data\r\n this.clear();\r\n }\r\n}\r\n\r\nexport default PlaylistManager;\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["translations", "HTML5Renderer", "currentSrc", "hasSourceElementsWithDesc", "allTextTracks"]
7
7
  }