EDIT: I have found the solution, posted and marked as the best answer below.
I’m coding a portfolio website for myself using HTML, CSS and JS and I need to add multiple videos on a lot of pages.
I followed some tutorials to learn how to customize the video player, but it only works for one specific video on the page. If I were to add more videos, I’d need to have one .js custom player file for each video and manually select them on the website.
How can I apply this single .js custom video player to all of my videos using purely javascript?
I have found similar topics about the subject here, but all of them uses jQuery and I’m struggling to make it work with javascript.
My HTML for the video player:
<section class="videoplayer"> <div class="c-video"> <div id="video_player"> <video src="./media/portfolio/videos/Show-Reel-2021.mp4" id="main-video"></video> <div class="progressAreaTime">00:00</div> <div class="controls"> <div class="progress-area"> <div class="progress-bar"> <span></span> </div> <div class="buffered-progress-bar"></div> </div> <div class="controls-list"> <div class="controls-left"> <span class="icon"> <i class="material-icons fast-rewind" title="Retroceder 10 segundos">first_page</i> </span> <span class="icon"> <i class="material-icons play_pause" title="Reproduzir">play_arrow</i> </span> <span class="icon"> <i class="material-icons fast-forward" title="Avançar 10 segundos">last_page</i> </span> <span class="icon"> <i class="material-icons volume" title="Sem áudio">volume_up</i> <input type="range" min="0" max="100" class="volume_range"> </span> <div class="timer"> <span class="current">00:00</span> / <span class="duration">0:00</span> </div> </div> <div class="controls-right"> <span class="icon"> <i class="material-icons auto-play" title="A repetição automática está desativada"></i> </span> <span class="icon"> <i class="material-icons settingsBtn" title="Detalhes">settings</i> </span> <span class="icon"> <i class="material-icons picture_in_picture" title="Miniplayer">picture_in_picture_alt</i> </span> <span class="icon"> <i class="material-icons fullscreen" title="Tela inteira">fullscreen</i> </span> </div> </div> </div> <div id="settings"> <div class="playback"> <span>Velocidade da Reprodução</span> <ul> <li data-speed="0.25">0.25</li> <li data-speed="0.5">0.5</li> <li data-speed="0.75">0.75</li> <li data-speed="1" class="active">Normal</li> <li data-speed="1.25">1.25</li> <li data-speed="1.5">1.5</li> <li data-speed="1.75">1.75</li> <li data-speed="2">2</li> </ul> </div> </div> </div> </div>
My JavaScript for the video player:
// Select elements const vidsrc = document.querySelector('#main-video').src; const video_player = document.querySelector('#video_player'), mainVideo = video_player.querySelector('#main-video'), progressAreaTime = video_player.querySelector('.progressAreaTime'), controls = video_player.querySelector('.controls'), progressArea = video_player.querySelector('.progress-area'), progress_Bar = video_player.querySelector('.progress-bar'), buffered_Bar = video_player.querySelector('.buffered-progress-bar'), fast_rewind = video_player.querySelector('.fast-rewind'), play_pause = video_player.querySelector('.play_pause'), fast_forward = video_player.querySelector('.fast-forward'), volume = video_player.querySelector('.volume'), volume_range = video_player.querySelector('.volume_range'), current = video_player.querySelector('.current'), totalDuration = video_player.querySelector('.duration'), auto_play = video_player.querySelector('.auto-play'), settingsBtn = video_player.querySelector('.settingsBtn'), picture_in_picture = video_player.querySelector('.picture_in_picture'), fullscreen = video_player.querySelector('.fullscreen'), settings = video_player.querySelector('#settings'), playback = video_player.querySelectorAll('.playback li'); mainVideo.addEventListener('loadeddata',()=>{ setInterval(() => { let bufferedTime = mainVideo.buffered.end(0); let duration = mainVideo.duration; let width = (bufferedTime / duration) * 100; buffered_Bar.style.width = `${width}%` }, 500); }) // Play function playVideo() { play_pause.innerHTML = "pause"; play_pause.title = "Pausar"; video_player.classList.add('paused') mainVideo.play(); } // Pause function pauseVideo() { play_pause.innerHTML = "play_arrow"; play_pause.title = "Reproduzir"; video_player.classList.remove('paused') mainVideo.pause(); } play_pause.addEventListener('click',()=>{ const isVideoPaused = video_player.classList.contains('paused'); isVideoPaused ? pauseVideo() : playVideo(); }) mainVideo.addEventListener('play',()=>{ playVideo(); }) mainVideo.addEventListener('pause',()=>{ pauseVideo(); }) // Rewind fast_rewind.addEventListener('click',()=>{ mainVideo.currentTime -= 10; }) // Forward fast_forward.addEventListener('click',()=>{ mainVideo.currentTime += 10; }) // Total duration mainVideo.addEventListener("loadeddata",(e)=>{ let videoDuration = e.target.duration; let totalMin = Math.floor(videoDuration / 60); let totalSec = Math.floor(videoDuration % 60); // Complete with zero at beggining totalSec < 10 ? totalSec = "0"+totalSec:totalSec; totalMin < 10 ? totalMin = "0"+totalMin:totalMin; totalDuration.innerHTML = `${totalMin}:${totalSec}`; }) // Current duration mainVideo.addEventListener('timeupdate',(e)=>{ let currentVideoTime = e.target.currentTime; let currentMin = Math.floor(currentVideoTime / 60); let currentSec = Math.floor(currentVideoTime % 60); // Complete with zero at beggining currentSec < 10 ? currentSec = "0"+currentSec:currentSec; currentMin < 10 ? currentMin = "0"+currentMin:currentMin; current.innerHTML = `${currentMin}:${currentSec}`; let videoDuration = e.target.duration // Seek bar let progressWidth = (currentVideoTime / videoDuration) * 100; progress_Bar.style.width = `${progressWidth}%`; }) // Update current duration progressArea.addEventListener('click',(e)=>{ let videoDuration = mainVideo.duration; let progressWidthval = progressArea.clientWidth; let ClickOffsetX = e.offsetX; mainVideo.currentTime = (ClickOffsetX / progressWidthval) * videoDuration; }) // Volume function changeVolume() { mainVideo.volume = volume_range.value / 100; if (volume_range.value == 0) { volume.innerHTML = "volume_off"; }else if(volume_range.value < 40){ volume.innerHTML = "volume_down"; }else{ volume.innerHTML = "volume_up"; } } function muteVolume() { if (volume_range.value == 0) { volume_range.value = 80; mainVideo.volume = 0.8; volume.innerHTML = "volume_up"; volume.title = "Sem áudio"; }else{ volume_range.value = 0; mainVideo.volume = 0; volume.innerHTML = "volume_off"; volume.title = "Reativar o som"; } } volume_range.addEventListener('change',()=>{ changeVolume(); }) volume.addEventListener('click',()=>{ muteVolume(); }) // Update on mouse move progressArea.addEventListener('mousemove',(e)=>{ let progressWidthval = progressArea.clientWidth; let x = e.offsetX; progressAreaTime.style.setProperty('--x',`${x}px`); progressAreaTime.style.display = "block"; let videoDuration = mainVideo.duration; let progressTime = Math.floor((x/progressWidthval)*videoDuration); let currentMin = Math.floor(progressTime / 60); let currentSec = Math.floor(progressTime % 60); // Complete with zero at beggining currentSec < 10 ? currentSec = "0"+currentSec:currentSec; currentMin < 10 ? currentMin = "0"+currentMin:currentMin; progressAreaTime.innerHTML = `${currentMin}:${currentSec}`; }) progressArea.addEventListener('mouseleave',()=>{ progressAreaTime.style.display = "none"; }) // Loop auto_play.addEventListener('click',()=>{ auto_play.classList.toggle('active') if(auto_play.classList.contains('active')){ auto_play.title = "A repetição automática está ativada"; }else{ auto_play.title = "A repetição automática está desativada"; } }); mainVideo.addEventListener("ended",()=>{ if (auto_play.classList.contains('active')) { playVideo(); }else{ play_pause.innerHTML = "replay"; play_pause.title = "Reproduzir novamente"; } }); // Picture in picture picture_in_picture.addEventListener('click',()=>{ mainVideo.requestPictureInPicture(); }) // Full screen fullscreen.addEventListener('click',()=>{ if (!video_player.classList.contains('openFullScreen')) { video_player.classList.add('openFullScreen'); fullscreen.innerHTML = "fullscreen_exit"; fullscreen.title = "Sair da tela inteira"; video_player.requestFullscreen(); }else{ video_player.classList.remove('openFullScreen'); fullscreen.innerHTML = "fullscreen"; fullscreen.title = "Tela inteira"; document.exitFullscreen(); } }); // Settings settingsBtn.addEventListener('click',()=>{ settings.classList.toggle('active'); settingsBtn.classList.toggle('active'); }) // Speed playback.forEach((event)=>{ event.addEventListener('click',()=>{ removeActiveClasses(); event.classList.add('active'); let speed = event.getAttribute('data-speed'); mainVideo.playbackRate = speed; }) }) function removeActiveClasses() { playback.forEach(event => { event.classList.remove('active') }); } // Get URL let xhr = new XMLHttpRequest(); xhr.open("GET",vidsrc); xhr.responseType = "arraybuffer"; xhr.onload = (e)=>{ let blob = new Blob([xhr.response]); let url = URL.createObjectURL(blob); mainVideo.src = url; } xhr.send(); // Store duration window.addEventListener('unload',()=>{ let setDuration = localStorage.setItem('duration',`${mainVideo.currentTime}`); let setSrc = localStorage.setItem('src',`${mainVideo.getAttribute('src')}`); }) window.addEventListener('load',()=>{ let getDuration = localStorage.getItem('duration'); let getSrc = localStorage.getItem('src'); if (getSrc) { mainVideo.src = getSrc; mainVideo.currentTime = getDuration; } }) mainVideo.addEventListener('contextmenu',(e)=>{ e.preventDefault(); }) // Hide and show controls (mouse) video_player.addEventListener('mouseover',()=>{ controls.classList.add('active'); }) video_player.addEventListener('mouseleave',()=>{ if (video_player.classList.contains('paused')) { if (settingsBtn.classList.contains('active')) { controls.classList.add('active'); }else{ controls.classList.remove('active') } }else{ controls.classList.add('active') } }) if (video_player.classList.contains('paused')) { if (settingsBtn.classList.contains('active')) { controls.classList.add('active'); }else{ controls.classList.remove('active') } }else{ controls.classList.add('active') } // Hide and show controls (mobile) video_player.addEventListener('touchstart',()=>{ controls.classList.add('active'); setTimeout(() => { controls.classList.remove('active') }, 8000); }) video_player.addEventListener('touchmove',()=>{ if (video_player.classList.contains('paused')) { controls.classList.remove('active') }else{ controls.classList.add('active') } })
Advertisement
Answer
I HAVE FOUND THE SOLUTION
For anyone in the future seeking for the same solution, I was able to make it work by first selecting every videoplayer div:
const videoContainers = document.querySelectorAll(".video-container")
Then using the .forEach()
function so that the code will generate a button for every individual videoplayer:
videoContainers.forEach((container) => { let playPauseBtn = container.querySelector(".play-pause-btn"); let theaterBtn = container.querySelector(".theater-btn"); let fullScreenBtn = container.querySelector(".full-screen-btn"); ... // The entire code for one videoplayer }
You can reference “container” for the individual videoplayer or “document” for every videoplayer at once. It just works like magic!