Pause video when clicking an overlay element - javascript

I am working on a video where during some seconds, an overlay element appears to promote a product.
I would like to know if is possible to pause the video when someone clicks the overlay element and at the same time this will display a window showing the product details. So:
Video plays and displays an overlay element
User clicks the overlay element so:
2.1: Video pauses on the background
2.2: Overlay element opens a window over the paused video to show the product details.
This is my code where the video shows the overlay element for a few seconds during the video:
<video id="myVideo" controls>
<source id='mp4' src="video.mp4" type='video/mp4'>
</video>
<div id="overlay">
Something
</div>
<script>
//Shows link between seconds 5 and 10
var overlay = document.getElementById('overlay');
var video = document.getElementById('myVideo');
video.addEventListener('timeupdate', function() {
console.log( video.currentTime );
var show = video.currentTime >= 5 && video.currentTime < 10;
overlay.style.opacity = show ? '1' : '0';
}, false);
</script>

some sample code:
overlay.addEventListener('click', function() { video.pause() })
You should proably add in something that would play the video once the overlay is clicked again - but i think you get the idea.
Have a look here for the documentation on what is available on the video element:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video

Video can be paused using video.pause()
https://www.w3schools.com/tags/ref_av_dom.asp
You can attach an click event listener to your overlay,
and call the video pause function when the user click on the overlay.
Instead of using opacity on your overlay,
you can perhaps try using display: none instead.
So that, you won't need to handle the situation where the overlay
is always blocking in front of your elements.
See demo: https://jsfiddle.net/amoshydra/pan306jt/
//Shows link between seconds 5 and 10
var overlay = document.getElementById('overlay');
var video = document.getElementById('myVideo');
video.addEventListener('timeupdate', function() {
console.log( video.currentTime );
var show = video.currentTime >= 5 && video.currentTime < 10;
// Try using display style?
overlay.style.display = show ? 'block' : 'none';
}, false);
overlay.addEventListener('click', function() {
var urlToOpen = 'http://stackoverflow.com/questions/14132122/open-url-in-new-window-with-javascript';
window.open(urlToOpen, '_blank');
// Pause video using the video API
video.pause();
});

Related

flickity.js play/pause video based on current cell

I am using Flickity to create a slider of images and videos. When changing slides, I want to play the video on the current slide (which has a class of .is-selected), and then pause again once I move to the next slide.
The code below manages to find any videos within the slider, but plays them on any slide change, rather than specifically for the slide they are within. Any help would be much appreciated.
// Init Flickity
var $carousel = $('.carousel');
$carousel.flickity();
// On slide change
$carousel.on('change.flickity', function() {
// Find videos
var currentSlide = $(this).find('.is-selected');
var video = $(this).find('video');
// Play videos
video[0].play();
});
What you want to do is pause all videos on every slide change and only play the one on the selected slide. I did something similar (without jQuery):
var carousel = document.querySelector(".carousel");
var flkty = new Flickity(carousel, {
// ..
});
flkty.on("change", function() {
console.log("Flickity active slide: " + flkty.selectedIndex);
flkty.cells.forEach(function(cell, i) {
if (cell.element == flkty.selectedElement) {
// play video if active slide contains one
// use <video playsinline ..> in your html to assure it works on ios devices
var video = cell.element.querySelector("video");
if (video) {
console.log("playing video " + i);
video.play();
}
return;
}
// pause all other videos
var video = cell.element.querySelector("video");
if (video) {
console.log("pausing video " + i);
video.pause();
}
});
});
As I stated in the comment, you might wanna use the "playsinline" attribute for your videos, otherwise you'll run into problems on iOS.
Also: using the "settle" event instead of "change" allows you to start playing once the active slide settled at its end position.

How to buffer / preload html5 videos using javascript

I am running the following code which changes the source of an html5 video at the end of each video, so that it constantly plays one video after another. After the first video finishes, it runs the second, then the third and eventually starts again from the beginning, resulting in an endless cycle. It also chooses a random starting point, but that is not important for my question.
In the code below you will only find two video sources but the final code would use around ten or so.
My problem is that there is a small pause between the end of a video and the beginning of the next one. I have made the background-color of the video tag red so that you will be able to see a red flash between the playback of each video.
I'm guessing that this could be solved by preloading all videos specified inside the javascript code. So what I would like to achieve is to preload only the next video in the list specified inside the javascript code when the current video is playing. So when video nr. 5 is playing, it should preload video nr. 6 etc..
Or is this not something that could be solved by effective buffering / preloading? I'm happy about any other suggestions as well..
var vidElement = document.getElementById('video');
var vidSources = [
"http://www.w3schools.com/html/mov_bbb.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
var activeVideo = Math.floor((Math.random() * vidSources.length));
vidElement.src = vidSources[activeVideo];
vidElement.addEventListener('ended', function(e) {
// update the active video index
activeVideo = (++activeVideo) % vidSources.length;
if(activeVideo === vidSources.length){
activeVideo = 0;
}
// update the video source and play
vidElement.src = vidSources[activeVideo];
vidElement.play();
});
video { background-color: red }
<video src="http://www.w3schools.com/html/mov_bbb.mp4" id="video" autoplay muted playsinline></video>
<p>(each video is just ~ 10 seconds)</p>
You can create video elements with preload attribute and add it to div containar like follows:
function initVideoElement(videoEl)
{
videoEl.playsinline = true;
videoEl.muted = false;
videoEl.preload = 'auto'; //but do not set autoplay, because it deletes preload
//loadedmetadata is wrong because if we use it then we get endless loop
videoEl.onplaying = function(e)
{
if(++nextActiveVideo == 2)
nextActiveVideo = 0;
//replace the video elements against each other:
if(this.inx == 0)
nextVideoElement = videoElements[1];
else
nextVideoElement = videoElements[0];
nextVideoElement.src = vidSources[nextActiveVideo];
nextVideoElement.pause();
};
videoEl.onended = function(e)
{
this.style.display = 'none';
nextVideoElement.style.display = 'block';
nextVideoElement.play();
};
}
var videoContainer = document.getElementById('videoContainer'),
nextActiveVideo = 0,
nextVideoElement,
videoElements =
[
document.createElement('video'),
document.createElement('video')
],
vidSources =
[
"http://www.w3schools.com/html/mov_bbb.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
videoElements[0].inx = 0; //set index
videoElements[1].inx = 1;
initVideoElement(videoElements[0]);
initVideoElement(videoElements[1]);
videoElements[0].autoplay = true;
videoElements[0].src = vidSources[0];
videoContainer.appendChild(videoElements[0]);
videoElements[1].style.display = 'none';
videoContainer.appendChild(videoElements[1]);
video{background-color: red}
<div id="videoContainer"></div>

Workaround for Autoplay on Iframe for Phones and Tablets

Is there any CSS (or anything) I can add to my media queries that would recognize what the device the video is playing on? I am looking to have a play button appear on my site when the video attempts to play on any device that does not allow auto play. Let me know your thoughts, my site is live and published at http://www.rosemont.edu/admissionstest
Javascript to hide button:
var supports_video_autoplay = function(callback) {
var v = document.createElement("video");
v.paused = true;
var p = "play" in v && v.play();
typeof callback === "function" && callback(!v.paused || "Promise" in window && p instanceof Promise);
};
// usage
supports_video_autoplay(function(supported) {
if (supported) {
// video autoplay supported!
document.getElementById("Playing1").style.display = "none";
} else {
// no video autoplay support :(
document.getElementById("playing1")
}
});
I don't think there is a clean css solution for this. There is a related question here
Maybe you could display the play button by default and hide it when the media element's playing event(not the play event, but playing) is triggered? If you add transitions to it it won't blink for devices that has auto-play support.
Something like
var video = document.getElementsByTagName("video")[0];
video.addEventListener("playing", function() {
// Hide or fade out the initial play button
});

Optimised Javascript for HTML5 Video player

I have a HTML5 video player on my site with three videos. The code I found only supported one video per webpage but I managed to do a hack to make it work with multiple videos per page. The hack is pretty inefficient and I am sure there is a more elegant way to implement this. Here is how my code looks:
// Video
var video = document.getElementById("video");
var video2 = document.getElementById("video2");
var video3 = document.getElementById("video3");
// Buttons
var playButton = document.getElementById("play-pause");
var playButton2 = document.getElementById("play-pause2");
var playButton3 = document.getElementById("play-pause3");
// Event listener for the play/pause button 1
playButton.addEventListener("click", function () {
if (video.paused == true) {
// Play the video
video.play();
// Update the button text to 'Pause'
document.getElementById("play-pause").className = "pause";
} else {
// Pause the video
video.pause();
// Update the button text to 'Play'
document.getElementById("play-pause").className = "play";
}
});
// Event listener for the play/pause button 2
playButton2.addEventListener("click", function () {
if (video2.paused == true) {
// Play the video
video2.play();
// Update the button text to 'Pause'
document.getElementById("play-pause2").className = "pause";
} else {
// Pause the video
video2.pause();
// Update the button text to 'Play'
document.getElementById("play-pause2").className = "play";
}
});
// Event listener for the play/pause button 3
playButton3.addEventListener("click", function () {
if (video3.paused == true) {
// Play the video
video3.play();
// Update the button text to 'Pause'
document.getElementById("play-pause3").className = "pause";
} else {
// Pause the video
video3.pause();
// Update the button text to 'Play'
document.getElementById("play-pause3").className = "play";
}
});
}
As you can see I went down the route of simply duplicating the event listener and creating new variables. There must be a way to select the target based on the specific Div selected, maybe through specifying the path of the class? I.e. .container .video1 .play?
The second problem I am having is reverting the pause button and poster image back to the original state after the video has finished playing.
Here is the site where the code and content is placed:
http://www.glowdigital.net/index.php?page=snap-inspire
Any help would be much appreciated!
Thank you
There must be a way to select the target based on the specific Div selected, maybe through specifying the path of the class?
Yes there are better ways of event handling a group of elements.
Event delegation is when the event listener is registered on an ancestor element that the target elements have in common.
Arrays can be used by keeping track of an index number.
The following demo will address the latter.
The second problem I am having is reverting the pause button and poster image back to the original state after the video has finished playing.
Many ways to handle that. The demo demonstrates the use of the CSS ::after pseudo-element and add/removeClass() methods.
I also added exclusive playback capabilities as well. If a player is playing and
another player starts to play, the player that was playing will stop playing.
Details are commented in demo
Demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<title>HTML5 Video Player Group - Exclusive Playback</title>
<style>
button {
color: rgba(66, 200, 150, 1);
background: none;
border: 0;
font: 400 24px/1 Verdana;
outline: 0;
cursor: pointer;
}
button:hover,
button:active,
button:focus {
color: #0F3
}
.play.toPause::after {
content: '⏸';
font: inherit;
}
.play.toPlay::after {
content: '▶';
font: inherit;
}
.stop::after {
content: '⏹';
font: inherit;
}
</style>
</head>
<body>
<header> </header>
<main id="media">
<figure class="vSection">
<video id="v0" width="320" height="auto" poster="http://www.glowdigital.net/images/projects/snap-inspire-1.jpg">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-1.webm" type="video/webm">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-1.mp4" type="video/mp4">
</video>
<figcaption class="controls">
<button type="button" class="play toPlay"></button>
<button type="button" class="stop"></button>
</figcaption>
</figure>
<figure class="vSection">
<video id="v1" width="320" height="auto" poster="http://www.glowdigital.net/images/projects/snap-inspire-2.jpg">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-2.webm" type="video/webm">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-2.mp4" type="video/mp4">
</video>
<figcaption class="controls">
<button type="button" class="play toPlay"></button>
<button type="button" class="stop"></button>
</figcaption>
</figure>
<figure class="vSection">
<video id="v2" width="320" height="auto" poster="http://www.glowdigital.net/images/projects/snap-inspire-3.jpg">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-3.webm" type="video/webm">
<source src="http://www.glowdigital.net/images/projects/snap-inspire-3.mp4" type="video/mp4">
</video>
<figcaption class="controls">
<button type="button" class="play toPlay"></button>
<button type="button" class="stop"></button>
</figcaption>
</figure>
</main>
<footer> </footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
// Gather all <video> into a NodeList then convert it into an array
var videos = Array.from(document.querySelectorAll('video'));
/* map() through array assigning an id to each <video>
|| vArray is returned; an array of <video id='..'>
*/
var vArray = videos.map(function(vid, idx) {
var player = document.getElementById(vid.id);
return player;
});
// When a button.play is clicked...
$('.play').on('click', function(e) {
// Get it's index number
var idx = $('.play').index(this);
/* Invoke functiom excPlay passing the vArray and idx
|| It stops any player if it's playing and the prepares
|| the specified player to play. See bottom of source
|| for details
*/
var player = excPlay(vArray, idx);
// If paused or ended...
if (player.paused || player.ended) {
// Play video
player.play();
// Switch the classes for the all buttons to the paused state
$('.play').removeClass('toPause').addClass('toPlay');
// Switch this button to the playing state
$(e.target).addClass('toPause').removeClass('toPlay');
}
//...Otherwise...
else {
// Pause the video
player.pause();
// Switch all buttons to the paused state
$('.play').removeClass('toPause').addClass('toPlay');
}
// Click thebutton.stop...
$('.stop').on('click', function(e) {
// Get index number
var index = $('.stop').index(this);
// See line 73
var player = excPlay(vArray, index);
// Pause the video
player.pause();
// Set video's time back to 0
player.currentTime = 0;
});
// If a video ends...
$('video').on('ended', function() {
// Reset the time
this.currentTime = 0;
// Get its poster value...
var image = this.poster;
// ,,,then set it
this.poster = image;
// Set all buttons to pause state
$('.play').removeClass('toPause').addClass('toPlay');
});
/* Pass in an array of video objects and the index number of
|| thevideo you want to play.
*/
function excPlay(array, exclude) {
// map() the array of videos; on each loop...
array.map(function(video, index) {
// If the video isn't the video you want to play...
if (index != exclude) {
// Get the video's poster
var image = video.poster;
// Set the time back to the beginning
video.currentTime = 0;
// Pauase video
video.pause();
// Reset the poster image
video.poster = image;
}
});
// Toggle the classes on the play button
$('.play').removeClass('toPause').addClass('toPlay');
// Return the selected player or nothing
return array[exclude] || null;
}
});
</script>
</body>
</html>

Is it possible to embed actions in html5 video?

Is there any way to play a video in html5, stop and execute javascript at known points within the video?
Yes, try this. You have to use the currentTime property. Start with that and start your javascript functions from there. Is that what you're looking for?
var vid = document.getElementById("video");
//Add a timeupdate listener
video.addEventListener("timeupdate", function(){
//Check for video properties from within the function
if (this.currentTime == 5)
this.pause();
//cal javascript
}
}
Looking at the accepted answer over here it looks like it is possible.
To pause the video you just do this:
var mediaElement = document.getElementById("video"); // create a reference to your HTML5 video
mediaElement.pause(); // pauses the video
If you want to play the video, do this:
mediaElement.play(); // plays the video
To get the current time in the video, do this:
mediaElement.currentTime; // gets the current time
Here's an example linking them all up:
var mediaElement = document.getElementById("video");
if(mediaElement.currentTime == 35){
mediaElement.pause();
// do whatever else you would like
mediaElement.play();
}
The MDL documentation is here, there are plenty of other properties you might find helpful.
Hope this helps!
Yes, by doing like this you can.
Note that you have to look for a time using bigger than > bigger than (as the chance to match an exact millisecond is almost zero), and have a variable in one way or the other to know which ones is done.
window.addEventListener('load', function() {
var cur = document.querySelector('#cur'),
vid = document.querySelector('#vid')
})
var appDone = {"done7":false,"done4":false}
vid.addEventListener('timeupdate', function(e) {
if (e.target.currentTime > 7 && !appDone.done7) {
appDone.done7 = true;
e.target.pause();
//do something
cur.textContent += ", " + "done7 once";
e.target.play();
}
if (e.target.currentTime > 4 && !appDone.done4) {
appDone.done4 = true;
e.target.pause();
//do something
cur.textContent += ", " + "done4 once";
e.target.play();
}
})
<video id="vid" width="320" height="176" controls>
<source src="http://www.w3schools.com/tags/mov_bbb.mp4" type="video/mp4">
<source src="http://www.w3schools.com/tags/mov_bbb.ogg" type="video/ogg">
Your browser does not support HTML5 video.
</video>
<p id="cur"></p>

Categories