Home>

You need to insert several videos on one page with your own control design.

HTML:

<div class="video-holder">      <video class="video" src="video.mp4"></video>      <div class="controls">         <div class="play-button">            <button id="play-pause"></button>         </div>         <div class="progress bar">            <div class="timeBar"></div>         </div>      </div>   </div>

JavaScript for displaying playback progress works for multiple players:

const video= document.querySelectorAll('.video');
const progbar= document.querySelectorAll('.progressBar');
video.forEach(video=> video.addEventListener('timeupdate',
function(e) {
   const videoWrap= e.currentTarget.closest('.video-holder'),
   video= videoWrap.querySelector('video');
   videoWrap.querySelector('.timeBar').style.width=
   (video.currentTime /video.duration * 100) + "%";
}));

There is a clickable progress code that only works for one video per page:

var updatebar= function(x) {
varprogress= $('.progressBar');
varmaxduration= video.duration;
var position= x -progress.offset().left;
var percentage= 100 * position/progress.width();
if(percentage > one hundred) {
    percentage= 100;
}
if(percentage< 0) {
    percentage= 0;
}
$('.timeBar').css('width', percentage+'%');
video.currentTime= maxduration * percentage /100;
};
var timeDrag= false;
$('.progressBar').mousedown(function(e) {
timeDrag= true;
updatebar(e.pageX);
});
$(document).mouseup(function(e) {
if(timeDrag) {
    timeDrag=false;
    updatebar(e.pageX);
}
});
$(document).mousemove(function(e) {
if(timeDrag) {
    updatebar(e.pageX);
}
});

How to rewrite it so that it works with any number of videos?

  • Answer # 1

    This option worked:

    const video= document.querySelectorAll('.video');
    const progbar= document.querySelectorAll('.progressBar');
    /* Display the playback progress bar */
    video.forEach(video=> video.addEventListener('timeupdate',
    function(e) {
    e.currentTarget.closest('.video-
    holder').querySelector('.timeBar').style.width=
    (e.currentTarget.currentTime /e.currentTarget.duration * 100) + "%";
    }));
    /* Display the playback progress bar */
    /* Set CurrentTime to click point */
    progbar.forEach(progbar=> progbar.addEventListener('click',
    function(e) {
    var x= e.offsetX==undefined?e.layerX:e.offsetX;
    var getvideoholder= e.currentTarget.closest('.video-holder');
    var wdth= getvideoholder.querySelector('.progressBar').offsetWidth;
    var viddur= getvideoholder.querySelector('video').duration;
    getvideoholder.querySelector('video').currentTime= x*viddur/wdth;
    }));
    /* Set CurrentTime to click point */
    

    Overall not bad, but could be improved a bit. The timeupdate event happens on video, so we can get it e.currentTarget. And in the second handler, you should cache e.currentTarget.closest('.video-holder') in the variable so as not to perform the same 'slow' one several times

    onovikov2022-01-27 21:01:25

    Corrected, yes, it's much cleaner.

    Andrey2022-01-27 21:01:25
  • Answer # 2

    This option worked:

    const video= document.querySelectorAll('.video');
    const progbar= document.querySelectorAll('.progressBar');
    /* Display the playback progress bar */
    video.forEach(video=> video.addEventListener('timeupdate',
    function(e) {
    e.currentTarget.closest('.video-
    holder').querySelector('.timeBar').style.width=
    (e.currentTarget.currentTime /e.currentTarget.duration * 100) + "%";
    }));
    /* Display the playback progress bar */
    /* Set CurrentTime to click point */
    progbar.forEach(progbar=> progbar.addEventListener('click',
    function(e) {
    var x= e.offsetX==undefined?e.layerX:e.offsetX;
    var getvideoholder= e.currentTarget.closest('.video-holder');
    var wdth= getvideoholder.querySelector('.progressBar').offsetWidth;
    var viddur= getvideoholder.querySelector('video').duration;
    getvideoholder.querySelector('video').currentTime= x*viddur/wdth;
    }));
    /* Set CurrentTime to click point */
    

    Overall not bad, but could be improved a bit. The timeupdate event happens on video, so we can get it e.currentTarget. And in the second handler, you should cache e.currentTarget.closest('.video-holder') in the variable so as not to perform the same 'slow' one several times

    onovikov2022-01-27 21:01:25

    Corrected, yes, it's much cleaner.

    Andrey2022-01-27 21:01:25
  • Answer # 3

    Alternatively, into a functionupdateBartransfer not the coordinate, but the entire event object. And based on it, calculate the current element for work. Maybe so:

    var updatebar= function(e) {
        var progress= $(e.currentTarget).closest('.video-container').find('.progressBar');
        var video= $(e.currentTarget).closest('.video-container').find('video').get(0);
        varmaxduration= video.duration;
        var position= e.pageX -progress.offset().left;
        var percentage= 100 * position/progress.width();
        if(percentage > one hundred) {
            percentage= 100;
        }
        if(percentage< 0) {
            percentage= 0;
        }
        $(e.currentTarget).closest('.video-container').find('.timeBar').css('width', percentage+'%');
        video.currentTime= maxduration * percentage /100;
    };
    

    Inupdatebar(e);pass the entire event.

    In my opinion it is wrong to mix pure js with js written in jQuery. Write in the same style, so there is less chance of making a mistake.

    Yes, I just used this solution, thanks! All controls work for each video individually. But I want to add clickability to the playback progress bar (so that there is a transition to the corresponding point in the video).

    Andrey2022-01-27 21:01:25

    Added some code to the answer

    onovikov2022-01-27 21:01:25

    Thanks! I'll try this option.

    Andrey2022-01-27 21:01:25

    Clarified the answer a little.

    onovikov2022-01-27 21:01:25

    Thanks for the reply, but I didn't manage to figure this out. Lack of knowledge in javascript. Wrote another version.

    Andrey2022-01-27 21:01:25