In a previous article I demonstrated how to make a simple responsive video playlist using three links and just one <video>
element. One of the limitations of the code was that each video did not automatically advance to the next when it finished playing. In this article, I’ll show how to solve that problem.
This example will use a similar markup structure as the earlier one: I would recommend reading that article if the code is unfamiliar to you.
<figure id="video_player">
<div id="video_container">
<video controls poster="vid-glacier.jpg">
<source src="glacier.webm" type="video/webm">
<source src="glacier.mp4" type="video/mp4">
</video>
</div>
<figcaption>
<a href="glacier.mp4" class="currentvid">
<img src="glacier.jpg" alt="Athabasca Glacier">
</a>
<a href="lake.mp4">
<img src="lake.jpg" alt="Athabasca Lake">
</a>
<a href="mountain.mp4">
<img src="mountain.jpg" alt="Mountain">
</a>
</figcaption>
</figure>
There is an extra <div>
around the <video>
in this example to deal with iOS (which will not scale video correctly without a little guidance). The CSS is also very similar to the earlier example:
#video_player {
display: table;
line-height: 0;
font-size: 0;
background: #000;
max-width: 1000px;
margin: 0 auto;
}
#video_container {
position: relative;
}
#video_player div,
#video_player figcaption {
display: table-cell;
vertical-align: top;
}
#video_container video {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
}
#video_player figcaption {
width: 25%;
}
#video_player figcaption a {
display: block;
}
#video_player figcaption a {
opacity: .5;
transition: 1s opacity;
}
#video_player figcaption a img,
figure video {
width: 100%;
height: auto;
}
#video_player figcaption a.currentvid,
#video_player figcaption a:hover,
#video_player figcaption a:focus {
opacity: 1;
}
@media (max-width: 700px) {
#video_player video,
#video_player figcaption {
display: table-row;
}
#video_container {
padding-top: 56.25%;
}
#video_player figcaption a {
display: inline-block;
width: 33.33%;
}
}
The .currentvid
class highlights the video that is currently playing.
The JavaScript
The first few lines of JavaScript, placed at the end of the page, are the same as the previous version:
var video_player = document.getElementById("video_player");
video = video_player.getElementsByTagName("video")[0],
video_links = video_player.getElementsByTagName("figcaption")[0],
source = video.getElementsByTagName("source"),
link_list = [],
path = '',
currentVid = 0,
allLnks = video_links.children,
lnkNum = allLnks.length;
video.removeAttribute("controls");
video.removeAttribute("poster");
The only additions are link_list
, currentVid
. allLnks
and lnkNum
variables, all relevant to the creation of the playlist. path
is the location of the videos, which is unused in this case: the code assumes that all files are in the same location.
Playing a video is now contained in the playVid
function, which is wrapped in a closure, together with a for
loop that fills the link_list
array:
(function() {
function playVid(index) {
video_links.children[index].classList.add("currentvid");
source[0].src = path + link_list[index] + ".mp4";
source[1].src = path + link_list[index] + ".webm";
currentVid = index;
video.load();
video.play();
}
for (var i=0; i<lnkNum; i++) {
var filename = allLnks[i].href;
link_list[i] = filename.match(/([^\/]+)(?=\.\w+$)/)[0];
(function(index){
allLnks[i].onclick = function(i){
i.preventDefault();
for (var i=0; i<lnkNum; i++) {
allLnks[i].classList.remove("currentvid");
}
playVid(index);
}
})(i);
}
The link_list
uses a more efficient regular expression to get the filename from each link. Every video link is then connected to the playVid
function, to which it carries the index
of the clicked link. Each link is also prevented from opening a video in a fresh browser window.
Next, we need to look for a video ending, remove the currentvid
class from all other links, then play the next logical video:
video.addEventListener('ended', function () {
allLnks[currentVid].classList.remove("currentvid");
if ((currentVid + 1) >= lnkNum) {
nextVid = 0;
} else {
nextVid = currentVid+1;
}
playVid(nextVid);
})
The last version of this code didn’t allow the user to control individual videos as they play: we’ll correct that with some event listeners:
video.addEventListener('mouseenter',
function() {
video.setAttribute("controls","true");
})
video.addEventListener('mouseleave', function() {
video.removeAttribute("controls");
})
That’s it. You may note enhanced accessibility in the example: once you click on a video thumbnail, you can navigate the list using cursor keys, and use return to start the selected video. I’ll cover this technique in a future article.
Video segments by Alexander Kondratskiy, licensed under Creative Commons.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/vnedg