JS newbie here. I'm in a situation where I need each video in a set to play on mouseover and pause on mouseout. I use a forEach loop to give this functionality to all of them, but now I need to "move" this functionality to div containers for each video, not the videos themselves.
Here's what I'm starting with:
HTML
<video src="/path-to-video" loop></video>
<video src="/path-to-video" loop></video>
<video src="/path-to-video" loop></video>
<video src="/path-to-video" loop></video>
JS
const videos = document.querySelectorAll('video');
videos.forEach(video => {
video.addEventListener('mouseover', function () {
this.play();
});
video.addEventListener('mouseout', function () {
this.pause();
});
});
I need to "transfer" the functionality of the above to a div container for each video. So, when I hover over the video, it is the div container that is actually playing the video, and when I hover away, it is the div container that is pausing the video. So NOT the video itself like it is above.
The HTML would now look like this (essentially):
<div class="item">
<video src="/path-to-video" loop></video>
</div>
<div class="item">
<video src="/path-to-video" loop></video>
</div>
<div class="item">
<video src="/path-to-video" loop></video>
</div>
<div class="item">
<video src="/path-to-video" loop></video>
</div>
I tried this JS:
const items = document.querySelectorAll('.item');
items.forEach(item => {
const video = document.querySelectorAll('video');
item.addEventListener('mouseover', function () {
video.play();
});
item.addEventListener('mouseout', function () {
video.pause();
});
});
This did nothing; none of the videos played on hover.
I also tried:
document.querySelector('.item').addEventListener('mouseover', function () {
const video = document.querySelector('video');
video.play();
});
document.querySelector('.item').addEventListener('mouseout', function () {
const video = document.querySelector('video');
video.pause();
});
This worked as intended on the first video, but not any of the others, and using querySelectorAll made none of them work. Using getElementsByClassName makes none of them work.
I'd prefer to keep the forEach approach but just have each div play and pause its video child using mouseover and mouseout. How could this be achieved? I'm probably not doing something obvious.
items is a NodeList, so you are looping over all of the elements with the "item" class. You can use the querySelector method on the elements you're iterating over to get that element's child video element. Then, you can call play() on that video element.
Basically, you had the right idea, you just need to use querySelector on the item instead of document.
Example:
const items = document.querySelectorAll('.item');
items.forEach(item => {
// see change below
const video = item.querySelector('video');
item.addEventListener('mouseover', function() {
video.play();
});
item.addEventListener('mouseout', function() {
video.pause();
});
});
.item {
width: 300px;
}
video {
width: 300px;
}
<div class="item">
<video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" loop></video>
</div>
<div class="item">
<video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" loop></video>
</div>
<div class="item">
<video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" loop></video>
</div>
<div class="item">
<video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4" loop></video>
</div>
Related
I'm designing a page where i want the video for each post to play when the user hovers the post. I've set it up like this:
<div class="project-link-block">
<div class="video-cover">
<video class="playonhover"height="100%" width="100%" muted playsinline loop data-object-fit="cover">
<source src="https://player.vimeo.com/progressive_redirect/playback/671122426/rendition/720p?loc=external&signature=e1562e4b2a73a9f37492359547fef09f8a3ed47a9d12fd77089930fc656a7d8e" type="video/mp4">
Your browser doesn't support HTML5 video tag.
</video>
</div>
</div>
<script>
$(document).ready(function() {
$(".playonhover").on("mouseover", function(event) {
this.play();
}).on('mouseout', function(event) {
this.pause();
});
})
</script>
This works, but I actually want the video to play when the top div (class .project-link-block) is hovered, not the video itself. Is there any way to do this? Switching the class in the JS didn't work. Using Webflow for this, in case it's relevant.
Did you also change this when you switched the class? Once you switch the class, the video element is no longer this.
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<div class="project-link-block">
<div class="video-cover">
<video class="playonhover" height="100%" width="100%" muted playsinline loop data-object-fit="cover">
<source
src="https://player.vimeo.com/progressive_redirect/playback/671122426/rendition/720p?loc=external&signature=e1562e4b2a73a9f37492359547fef09f8a3ed47a9d12fd77089930fc656a7d8e"
type="video/mp4">
Your browser doesn't support HTML5 video tag.
</video>
</div>
</div>
<script>
$(document).ready(function () {
$(".video-cover").on("mouseover", function (event) {
$(".playonhover").get(0).play();
}).on('mouseout', function (event) {
$(".playonhover").get(0).pause();
});
})
</script>
See if this code below achieves your expected result. Then convert to JQuery (if required).
<!DOCTYPE html>
<html>
<body>
<div class="project-link-block">
<div class="video-cover">
<video class="playonhover"height="100%" width="100%" muted playsinline loop data-object-fit="cover">
<!-- <source src="https://www.w3schools.com/tags/movie.mp4" type="video/mp4"> -->
<source type="video/mp4"
src="https://player.vimeo.com/progressive_redirect/playback/671122426/rendition/720p?loc=external&signature=e1562e4b2a73a9f37492359547fef09f8a3ed47a9d12fd77089930fc656a7d8e"
>
Your browser doesn't support HTML5 video tag.
</video>
</div>
</div>
<script>
window.addEventListener( "load", on_documentReady );
function on_documentReady()
{
//const myTargets = document.getElementsByClassName("playonhover");
const myTargets = document.getElementsByClassName("project-link-block");
for (var i = 0; i < myTargets.length; i++)
{
myTargets[i].onmouseover = handle_mouseOver;
myTargets[i].onmouseout = handle_mouseOut;
}
}
function handle_mouseOver( evt )
{
//alert( "## was rolled over" );
evt.target.play();
}
function handle_mouseOut( evt )
{
//alert( "## was rolled out" );
evt.target.pause();
}
</script>
</body>
</html>
I'm struggling trying to set a mouseenter and mouseleave event in several videos. Everything seems that work perfectly, the video plays when I mouseenter and stop when mouseleave.
However, when I add more than one video, just play the first video. I am trying to figure out what it's missing what I don't find the way to do it.
Here is the link to codepen: https://codepen.io/felixgonzalo/pen/poJoXRW
My code is:
<div class="main-wrapper">
<div class="video-container">
<video id="video" class="video" controls class="border" controls="false" muted loop>
<source src="https://www.errorerror.studio/wp-content/uploads/2020/01/ee.st-honesty-clip-00.mp4" preload="auto" type="video/mp4" autoplay />
</video>
<div class="overlay"></div>
</div>
<div class="video-container">
<video id="video-2" class="video" controls class="border" controls="false" muted loop>
<source src="https://www.errorerror.studio/wp-content/uploads/2020/01/ee.st-honesty-clip-00.mp4" preload="auto" type="video/mp4" autoplay />
</video>
<div class="overlay"></div>
</div>
</div>
jQuery
$('.video').prop('currentTime', 0)
function Play() {
$('.video').get(0).play();
}
function Stop() {
$('.video').prop('currentTime', 0).get(0).pause();
}
$(document).ready(function(){
$('.video-container').mouseenter(function(){
$('.overlay', this).addClass("hide")
Play();
}).mouseleave(function(){
$('.overlay', this).removeClass("hide")
Stop();
});
});
I also tried to make it in JS but didn't work out:
var container = document.querySelector('.video-container');
container.addEventListener('mouseleave', function() {
this.querySelector('.overlay').classList.remove('hide');
Stop();
});
container.addEventListener('mouseenter', function() {
this.querySelector('.overlay').classList.add('hide');
Play()
});
Really appreciate any help
Your function play gets only the first video because you specified the 0 index. You need to pass the current video index you're hovering to trigger the playback.
EDIT: Working code.
I made your functions taking an argument, which I'm setting to the first video element children of the element triggering the mouse events.
$('.video').prop('currentTime', 0)
$(document).ready(function() {
$('.video-container').mouseenter(function() {
$('.overlay', this).addClass("hide")
$(this).children('.video')[0].play();
}).mouseleave(function() {
$('.overlay', this).removeClass("hide")
$($(this).children('.video')[0]).prop('currentTime', 0)
$(this).children('.video')[0].pause();
});
});
I am trying to fade in an icon when video finish, but nothing.
Html
<video>
<source src="">
</video>
<div class="icon"></div>
First Try
$("video").on("ended", function() {
$(".icon").fadeIn;
});
Second try
$('video').parent().on("ended", function() {
if($(this).children("video").get(0).paused) {
$(this).children(".icon").fadeIn();
}
});
Actually has onclick event working fine
$("video").parent().on("click", function() {
$(this).children(".icon").fadeToggle();
});
You can try this way:
<video id="myVideo">
<source src="">
</video>
<div class="icon"></div>
var vid = document.getElementById("myVideo");
vid.onended = function() {
alert("The video has ended"); //Just to verify if the event is trapped
$(".icon").fadeIn();
};
You can achieve it in this way
document.getElementById('video').addEventListener('ended',function() {
$(".icon").fadeIn();
},false);
You've all been so great in helping me in the past and I'm hoping we can solve this next problem as well.
I am building a slideshow of sorts using videos as backgrounds instead of images. Everything is working perfectly except that the timing of the videos is off because even though my divs are hidden the videos are all playing at the same time.
So, what I need is a JS/jQuery solution to stop (not pause) and play the videos as the divs are hidden/shown. Here's my code so far:
jsfiddle: http://jsfiddle.net/Z2Nq8/1/
JS:
$(function () {
var counter = 0,
divs = $('#video1, #video2, #video3');
function showDiv () {
divs.hide()
.filter(function (index) { return index == counter % 3; }) // figure out correct div to show
.show();
counter++;
};
showDiv();
setInterval(function () {
showDiv();
}, 7 * 1000);
});
HTML:
`<div id="videocont">
<div id="video1" class="display">
<video autoplay loop poster="PHI.png" id="bgvid">
<source src="URL/video.mp4" type="video/mp4">
</video>
<div id="title">Headline text.
</div>
</div>
<div id="video2" class="display">
<video autoplay loop poster="PHI.png" id="bgvid">
<source src="URL/video.mp4" type="video/mp4">
</video>
<div id="title">Headline text.
</div>
</div>
<div id="video3" class="display">
<video autoplay loop poster="PHI.png" id="bgvid">
<source src="URL/video.mp4" type="video/mp4">
</video>
<div id="title">Headline text.
</div>
</div>
</div>`
Thanks!
You have auto play on all of the videos.
Set auto play on the first element, then when you're going through the videos use:
VideoElement.play()
And
VideoElement.pause()
If you want to then reset the video you can do:
VideoElement.currentTime = 0;
To manage the videos playing.
Working Fiddle
I have some divs that I use jQuery's fade in/out to bring onto the page when a link is clicked. Each page has an associated html5 audio element that also fades in/out accordingly.
$('.link').on('click', function(e){
var targetpage = $($(this).attr("href"));
$('.pagecontainer>div').fadeOut(0); //fade out currently displayed page
targetpage.fadeIn(); //fade in page associated with link
if (targetpage.children().hasClass('backgroundmusic')) {
$('audio').animate({volume: 0}, 1000); //fade out currently playing audio
alert('audio faded out');
$.each($('audio'), function () { //stop all audio
this.currentTime=0;
this.pause();
alert('audio stopped');
});
alert('stop function executed');
}
});
$('.sound').on('play', function () { //since volume was faded out, reset volume when click play button
$('audio').animate({volume: 1}, 100);
});
HTML:
Audio 1
Audio 2
Audio 3
<div class="pagecontainer">
<div id="page1"> //all three audio elements are in exact same spot
//clicking page link fades in current audio and fades in new one
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music1.mp3"/>
<source src="../../site/music/music1.ogg"/>
</audio>
</div>
</div>
<div id="page2">
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music2.mp3"/>
<source src="../../site/music/music2.ogg"/>
</audio>
</div>
</div>
<div id="page3">
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music3.mp3"/>
<source src="../../site/music/music3.ogg"/>
</audio>
</div>
</div>
</div>
The "alert('audio faded out')" will execute, but the "alert('audio stopped')" does not execute as it's not running the "$.each($('audio'), function" script at all, neither does "alert('stop function executed')". I have to use this "each" script as $('audio').currentTime=0 does not work, neither does $('audio').pause(), as I have multiple audio instances on my page.
Does anyone know why this is not working?
Thanks.
You pass in e to your function but don't use it. Probably want to prevent default action from that click event.
e.preventDefault(); //Put this at the top of the callback
This should fix your .each() problems. Also you should be using the console instead of alerts as to not freeze your page.
console.log('audio faded out'); //Use console instead of alerts
$('audio').each(function () { //Do it this way.
this.currentTime=0;
this.pause();
console.log('audio stopped');
});
console.log('stop function executed');