1document.addEventListener('DOMContentLoaded', () => { 2 const tracks = document.querySelectorAll('.audio-track'); 3 let currentlyPlaying = null; 4 5 tracks.forEach(track => { 6 const audio = track.querySelector('.native-audio'); 7 const btnPlay = track.querySelector('.btn-play'); 8 const progressBar = track.querySelector('.track-progress'); 9 const progressContainer = track.querySelector('.track-progress-container'); 10 const durationDisplay = track.querySelector('.track-duration'); 11 let isInitialized = false; 12 13 // Formatear tiempo (Segundos a MM:SS) 14 const formatTime = (secs) => { 15 const mins = Math.floor(secs / 60); 16 const seconds = Math.floor(secs % 60); 17 return `${mins}:${seconds.toString().padStart(2, '0')}`; 18 }; 19 20 const loadAndPlay = () => { 21 if (!isInitialized) { 22 audio.src = track.dataset.src; 23 isInitialized = true; 24 audio.load(); 25 } 26 }; 27 28 const playTrack = () => { 29 // Pausar la pista que se está reproduciendo actualmente 30 if (currentlyPlaying && currentlyPlaying !== track) { 31 currentlyPlaying.querySelector('.native-audio').pause(); 32 currentlyPlaying.classList.remove('is-playing'); 33 currentlyPlaying.querySelector('.btn-play i').className = 'fas fa-play'; 34 currentlyPlaying.querySelector('.btn-play').style.marginLeft = '2px'; 35 currentlyPlaying.querySelector('.track-progress').style.width = '0%'; 36 } 37 38 loadAndPlay(); 39 audio.play(); 40 track.classList.add('is-playing'); 41 btnPlay.innerHTML = '<i class="fas fa-pause"></i>'; 42 btnPlay.style.marginLeft = '0'; 43 currentlyPlaying = track; 44 }; 45 46 const pauseTrack = () => { 47 audio.pause(); 48 track.classList.remove('is-playing'); 49 btnPlay.innerHTML = '<i class="fas fa-play" style="margin-left: 2px;"></i>'; 50 if (currentlyPlaying === track) currentlyPlaying = null; 51 }; 52 53 // Eventos de Click 54 btnPlay.addEventListener('click', (e) => { 55 e.stopPropagation(); 56 if (track.classList.contains('is-playing')) { 57 pauseTrack(); 58 } else { 59 playTrack(); 60 } 61 }); 62 63 // Permitir hacer clic en toda la fila para reproducir 64 track.addEventListener('click', () => { 65 if (!track.classList.contains('is-playing')) playTrack(); 66 }); 67 68 // Click en la barra de progreso para saltar 69 progressContainer.addEventListener('click', (e) => { 70 if (!isInitialized) return; 71 const rect = progressContainer.getBoundingClientRect(); 72 const percent = (e.clientX - rect.left) / rect.width; 73 audio.currentTime = percent * audio.duration; 74 }); 75 76 // Actualizar UI cuando el audio se carga y reproduce 77 audio.addEventListener('loadedmetadata', () => { 78 durationDisplay.textContent = formatTime(audio.duration); 79 }); 80 81 audio.addEventListener('timeupdate', () => { 82 if (audio.duration) { 83 const percent = (audio.currentTime / audio.duration) * 100; 84 progressBar.style.width = `${percent}%`; 85 } 86 }); 87 88 audio.addEventListener('ended', () => { 89 pauseTrack(); 90 progressBar.style.width = '0%'; // Reiniciar barra al terminar 91 }); 92 }); 93 });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.