eventListener to alter between two elements - javascript

What I want is whenever I mouseover on an element for it to set the style of video to display: none; and then the img to display: block;
Here's my code:
Javascript
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("container").addEventListener("mouseenter", function(event) {
alternate(event);
});
document.getElementById("container").addEventListener("mouseout", function(event) {
alternate(event);
});
function alternate(e) {
var target = e.target || e.srcElement;
if (target) {
if (target.nodeName == "IMG") {
target.querySelector(".video").style.display = "block";
target.querySelector(".img").style.display = "none";
} else if (target.nodeName == "VIDEO") {
target.querySelector(".video").style.display = "none";
target.querySelector(".img").style.display = "block";
}
}
}
});
HTML
<div id="container">
<li>
<div>
<video class="video" src="./test.mp4" type="video/mp4" muted autoplay></video>
<img class="img" src="./test.jpg"></img>
</div>
</li>
<li>
<div>
<video class="video" src="./test.mp4" type="video/mp4" muted autoplay></video>
<img class="img" src="./test.jpg"></img>
</div>
</li>
</div>
Essentially what I am trying to achieve is whenever I mouseout from the video, put the image back and then back from. video: hidden, image:shown to video:shown, image:hidden.
I did manage to get something working by using the target.previousSibling technique but it didn't work 100%,
Hopefully I formatted this question right, thank you for reading. Any help is really appreciated.

You could achieve this with pure CSS. A very simple approach would be:
.hover-toggle {
position: relative;
}
.hover-toggle .video {
/* Use absolute positioning to place video along-side image */
position: absolute;
top: 0;
left: 0;
/* Set video to be transparent by default */
opacity: 0;
}
/* When hovering the transparent video, cause it to become opaque */
.hover-toggle .video:hover {
opacity: 1;
}
<div class="hover-toggle">
<video class="video" src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" muted autoplay></video>
<img class="img" src="https://via.placeholder.com/320x176" />
</div>
<div class="hover-toggle">
<video class="video" src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" muted autoplay></video>
<img class="img" src="https://via.placeholder.com/320x176" />
</div>

mouseenter and mouseleave are the proper events to use.
If you use <li> then you must use <ol> or <ul> as the parent.
Register the events to each <li>
const items = document.querySelectorAll('li');
for (let item of items) {
item.addEventListener('mouseenter', alternate);
item.addEventListener('mouseleave', alternate);
}
Define the event handler using e.target and .matches('li') to insure that the events only apply to <li>. Then use e.type to insure that only mouseenter and mouseleave` events apply.
const tgt = e.target;
const evt = e.type;
if (tgt.matches('li')) {
if (evt === 'mouseenter') {
...
else if (evt === 'mouseleave') {
...
}
The reason why target.previousSibling worked some of the time is because display: none removes elements from the flow thereby not being recognized as a sibling. Try assigning a class that has visibility and z-index properties and alternate that class between events.
tgt.children[0].classList.add('on');
tgt.children[1].classList.remove('on');
// and vice versa
BTW <img> tags are void elements (no end tag </img>)
const items = document.querySelectorAll('li');
for (let item of items) {
item.addEventListener('mouseenter', alternate);
item.addEventListener('mouseleave', alternate);
}
function alternate(e) {
const tgt = e.target;
const evt = e.type;
if (tgt.matches('li')) {
if (evt === 'mouseenter') {
tgt.children[0].classList.add('on');
tgt.children[1].classList.remove('on');
} else if (evt === 'mouseleave') {
tgt.children[1].classList.add('on');
tgt.children[0].classList.remove('on');
} else {
return false;
}
}
return false;
}
li {
position: relative;
height: 135px;
}
li * {
visibility: hidden;
position: absolute;
z-index: -1;
top: 0;
left: 0;
}
.on {
visibility: visible;
z-index: 1;
}
<ul>
<li>
<video src='https://storage04.dropshots.com/photos6000/photos/1381926/20170326/005610.mp4' muted autoplay loop width='240' height='135'></video>
<img class='on' src='https://branditprintit.com/wp-content/uploads/2017/04/logo-degin-logo-design-design-art-free.png' width='240' height='135'>
</li>
<li>
<video src='https://storage04.dropshots.com/photos6000/photos/1381926/20170326/005609.mp4' muted autoplay loop width='240' height='135'></video>
<img class='on' src='https://branditprintit.com/wp-content/uploads/2017/04/logo-degin-logo-design-design-art-free.png' width='240' height='135'>
</li>
</ul>

Related

How to perform jquery script only once?

I use the isInViewport script to play the video on scroll, but it doesn't look very good because it happens multiple times. Please tell how to limit the triggering of animation or video playback to literally once. Tried to add with one() and true/false but the code didn't work (I still green in jquery).
<div class="block"><span>Video below</span></div>
<div class="block video-block">
<video class="video" loop="loop" width="640" controls="controls" muted>
<source src="http://denis-creative.com/wp-content/uploads/2018/01/video.mp4" type="video/mp4" />
<source src="http://denis-creative.com/wp-content/uploads/2018/01/video.ogv" type="video/ogv" />
<source src="http://denis-creative.com/wp-content/uploads/2018/01/video.webm" type="video/webm" />
</video>
</div>
<div class="block"><span>Video above</span></div>
.block{
height: 100vh;
font-size: 60px;
text-align: center;
display: flex;
}
.block > *{
margin: auto;
display: inline-block;
max-width: 100%;
}
// Plugin isInViewport
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("jquery"),require("window")):"function"==typeof define&&define.amd?define("isInViewport",["jquery","window"],n):n(e.$,e.window)}(this,function(e,n){"use strict";function t(n){var t=this;if(1===arguments.length&&"function"==typeof n&&(n=[n]),!(n instanceof Array))throw new SyntaxError("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions");return n.forEach(function(n){"function"!=typeof n?(console.warn("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions"),console.warn("isInViewport: Ignoring non-function values in array and moving on")):[].slice.call(t).forEach(function(t){return n.call(e(t))})}),this}function o(n){var t=e("<div></div>").css({width:"100%"});n.append(t);var o=n.width()-t.width();return t.remove(),o}function r(t,i){var a=t.getBoundingClientRect(),u=a.top,c=a.bottom,f=a.left,l=a.right,d=e.extend({tolerance:0,viewport:n},i),s=!1,p=d.viewport.jquery?d.viewport:e(d.viewport);p.length||(console.warn("isInViewport: The viewport selector you have provided matches no element on page."),console.warn("isInViewport: Defaulting to viewport as window"),p=e(n));var w=p.height(),h=p.width(),v=p[0].toString();if(p[0]!==n&&"[object Window]"!==v&&"[object DOMWindow]"!==v){var g=p[0].getBoundingClientRect();u-=g.top,c-=g.top,f-=g.left,l-=g.left,r.scrollBarWidth=r.scrollBarWidth||o(p),h-=r.scrollBarWidth}return d.tolerance=~~Math.round(parseFloat(d.tolerance)),d.tolerance<0&&(d.tolerance=w+d.tolerance),l<=0||f>=h?s:s=d.tolerance?u<=d.tolerance&&c>=d.tolerance:c>0&&u<=w}function i(n){if(n){var t=n.split(",");return 1===t.length&&isNaN(t[0])&&(t[1]=t[0],t[0]=void 0),{tolerance:t[0]?t[0].trim():void 0,viewport:t[1]?e(t[1].trim()):void 0}}return{}}e="default"in e?e.default:e,n="default"in n?n.default:n,/**
* #author Mudit Ameta
* #license https://github.com/zeusdeux/isInViewport/blob/master/license.md MIT
*/
e.extend(e.expr[":"],{"in-viewport":e.expr.createPseudo?e.expr.createPseudo(function(e){return function(n){return r(n,i(e))}}):function(e,n,t){return r(e,i(t[3]))}}),e.fn.isInViewport=function(e){return this.filter(function(n,t){return r(t,e)})},e.fn.run=t});
//# isInViewport
// Play Video
$(function() {
var $video = $('.video');
var $window = $(window);
$window.scroll(function() {
if ($video.is(":in-viewport")) {
$video[0].play();
} else {
$video[0].pause();
}
});
});
You could add a var to check if the video is still playing (for example is_playing) and check it with an inner if:
$(function() {
var $video = $('.video');
var $window = $(window);
var is_playing = false;
$window.scroll(function() {
if ($video.is(":in-viewport")) {
if (!is_playing) {
is_playing = true;
$video[0].play();
}
} else {
$video[0].pause();
}
});
});

HTML5 video full screen not populate on android browser on mobile view

I am trying to open a video in full screen on a mobile browser.
The video is showing just fine, but when I click the "full screen" button on the video, only the sound is playing, without the video nor the controls showing.
Could anyone please help me ?
You can find my HTML code below :
<div class = "container">
<div class = "row">
<div class = "col-md-12">
<p class="new-txt-styl-mob">Video Title</p>
<video class = "ved-sttng-mob" controls id = "control1" src = "video1.mp4" type="video/mp4" >
</div>
</div>
</div>
Here is my JavaScript code :
var myVideo;
window.onload = function()
{
myVideo = document.getElementById("control1");
myVideo.load();
myVideo.addEventListener("webkitfullscreenchange", setFullScreenMode);
}
function setFullScreenMode()
{
if(myVideo.requestFullscreen) {
myVideo.requestFullscreen();
} else if (myVideo.webkitRequestFullscreen) {
myVideo.webkitRequestFullscreen();
} else if (myVideo.msRequestFullscreen) {
myVideo.msRequestFullscreen();
} else if (myVideo.mozRequestFullScreen) {
myVideo.mozRequestFullScreen();
}
}
And, finally, my CSS code :
.ved-sttng-mob {
width: 100%;
height: auto;
}
.ved-sttng-mob:-webkit-full-screen {
width: 100%;
height: auto;
}
You could try to use allowfullscreen like this
<video class = "ved-sttng-mob" controls id = "control1" src = "video1.mp4" type="video/mp4" allowfullcreen="true">

Slow video down to a stop gradually

I'm working on a project where a video plays in the background and events need to be fired at certain points in the video. At these points, the video needs to gradually slow down and stop before the event displays.
So far I have made this happen by getting the frame rate and the more it goes up the slower the video playback is, however, it is quite stuttery and jumps into slowing down very fast I would like something smoother. Also currently when you then want to replay the video it falls within the slow down to a stop area of the frames and starts to slow down before starting to play again. I've put in a different video to my actual video as for demo purposes so there is only one event which actually fires in this due to the video being small but there's need to be multiple events at different points in the video.
var currentFrame = $('#currentFrame');
var video = VideoFrame({
id: 'video',
frameRate: 29.97,
callback: function(frame) {
currentFrame.html(frame);
if ((frame > 60) && (frame < 135) || (frame > 875) && (frame < 952) || (frame > 1700) && (frame < 1798)) {
decrease_rate(frame);
} else {
reset_frames_rate();
}
}
});
$('#play-pause').click(function() {
ChangeButtonText();
});
window.decrease_rate = decrease_rate;
var frame_on_start = 0,
frame_rate_dif,
new_speed;
function decrease_rate(frame) {
if (frame_on_start == 0) {
console.log("frame rate reset");
frame_on_start = frame;
} else {
frame_rate_dif = frame - frame_on_start;
new_speed = 1 - (frame_rate_dif / 100);
document.querySelector('video').playbackRate = new_speed;
if (frame_rate_dif > 65) {
reset_frames_rate();
video.video.pause();
video.stopListen();
$("#play-pause").html('Play');
show_event();
}
}
}
window.show_event = show_event;
function show_event() {
$('.event1').removeClass('hide_event');
}
window.reset_frames_rate = reset_frames_rate;
function reset_frames_rate() {
frame_on_start = 0;
frame_rate_dif = 0;
document.querySelector('video').playbackRate = 1;
}
function ChangeButtonText() {
if (video.video.paused) {
video.video.play();
video.listen('frame');
$("#play-pause").html('Pause');
$('.event1').addClass('hide_event');
} else {
video.video.pause();
video.stopListen();
$("#play-pause").html('Play');
}
}
#container {
position: relative;
}
.hide_event {
display: none;
}
.event1 {
position: absolute;
top: 40%;
left: 0px;
background-color: white;
width: 100%;
text-align: center;
}
<script src="https://rawgit.com/allensarkisyan/VideoFrame/master/VideoFrame.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<video height="180" width="100%" id="video">
<source src="http://www.w3schools.com/html/mov_bbb.mp4"></source>
</video>
<div id="event1" class="event1 hide_event">
<p>Display event</p>
</div>
</div>
<div class="frame">
<span id="currentFrame">0</span>
</div>
<div id="controls">
<button id="play-pause">Play</button>
</div>

Change video of video tag on scroll

I have a video tag say
<div class="phone" align="center">
<div class="phone-inner">
<video width="100%" height="100%" autoplay="" loop="" muted id="phonevideo">
<source src="vid/1.mp4" type="video/mp4">
</video>
</div>
</div>
I want to change the video when page scrolls and each time div changes like fueled.com. Say I have six divisions like
<div id="first></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>
<div id="five"></div>
<div id="six"></div>
When div 2 comes into view the video should change and when div 3 or 4 comes into view video should change again to something else. Here is my code which needs to be modified according to it.
$(window).scroll(function() {
var topDivHeight = $("#first").height();
var DivTop = $("#sixth").position().top;
var viewPortSize = $(window).height();
var triggerAt = 450;
var triggerHeight = (topDivHeight - viewPortSize) + triggerAt;
var test1 = (topDivHeight - viewPortSize) + 650;
var count = 0;
var number = jQuery.grep(mainTops, function(n, i) {
if (n < $(window).scrollTop())
{
count++;
}
});
$('.nav ul li a').css("color", "#fff");
$('.nav ul li a#nav'+count ).css("color", "#f60");
if($(window).scrollTop() >= triggerHeight && $(window).scrollTop() < DivTop) {
$('.phone').css('visibility', 'visible').fadeIn();
if($(window).scrollTop() >= test1){
$('#phonevideo').html('<source src="vid/2.mp4" type="video/mp4">'); // tried using this method but its not working here. Some other method needed here.
}
} else {
$('.phone').fadeOut();
}
});
Try this code:
$('#phonevideo').find("source").attr("src", "https://www.w3schools.com/tags/movie.mp4");
$('#phonevideo').get(0).load();
You can change source attribute like $('#phonevideo').find("source").attr("src","videosource")
and after changing source you need to load video $('#phonevideo').get(0).load()
You cannot directly replace the HTML as you do using function .html(), accordingly to the HTML specification
Dynamically modifying a source element and its attribute when the
element is already inserted in a video or audio element will have no
effect.
But what you can try as suggested by the document is to change what is playing, just use the src attribute on the media element directly and use function .load();
A working example below:
var btn = document.getElementById('btn'),
player = document.getElementById('phonevideo'),
source = document.getElementById('src');
btn.addEventListener('click', function(event) {
player.pause();
source.src = 'http://html5demos.com/assets/dizzy.mp4'; // change video
player.load(); // load it
});
<div class="phone" align="center">
<div class="phone-inner">
<video width="100%" height="100%" autoplay="" loop="" muted id="phonevideo">
<source id="src" src="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4" type="video/mp4">
</video>
</div>
</div>
<button id="btn" type="button">Change Video!</button>
Using jQuery as on your example (not tested):
var player = $('#phonevideo');
player.find("source").attr("src", "http://html5demos.com/assets/dizzy.mp4");
player[0].load();
I've optimized your code. I have added a class to your divs and used the data attribute. Here is a working jsfiddle.
<div class="phone" align="center">
<div class="phone-inner">
<video width="100%" height="100%" autoplay="" loop="" muted id="phonevideo">
<source src="vid/1.mp4" type="video/mp4">
</video>
</div>
</div>
<div id="first" class="view" data-vid-src="vid/1.mp4"></div>
<div id="two" class="view" data-vid-src="vid/2.mp4"></div>
<div id="three" class="view" data-vid-src="vid/3.mp4"></div>
<div id="four" class="view" data-vid-src="vid/4.mp4"></div>
<div id="five" class="view" data-vid-src="vid/5.mp4"></div>
<div id="six" class="view" data-vid-src="vid/6.mp4"></div>
To see some result I have added some css:
.phone {
position: fixed;
height: 200px;
width: 120px;
background: white;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -60px;
}
.view {
height: 500px;
}
#first {
background: red;
}
#two {
background: yellow;
}
#three {
background: green;
}
#four {
background: blue;
}
#five {
background: pink;
}
#six {
background: black;
}
And now the jQuery part.
function getCurrentElement(pos) {
var len = $('.view').length;
var i = 0;
var old_pos;
var ele_pos;
var old_ele;
var return_ele;
$('.view').each(function(){
i++;
offset = $(this).offset();
ele_pos = offset.top;
if(pos == ele_pos) {
return_ele = $(this);
return;
}
else if(ele_pos > pos && old_pos < pos) {
return_ele = old_ele;
return;
}
else if(ele_pos < pos && i == len) {
return_ele = $(this);
return;
}
old_pos = ele_pos;
old_ele = $(this);
});
return return_ele;
}
var old_ele = null;
$(window).scroll(function() {
var cur_pos = $(window).scrollTop();
current_element = getCurrentElement(cur_pos);
if(old_ele != null) {
if(current_element.attr('id') != old_ele.attr('id')) {
$('#phonevideo source').attr('src',current_element.attr('data-vid-src'))
}
}
old_ele = current_element;
});
I hope this code will help you. :)

JavaScript Toggle with button

So i have a button that what it does it toggles and displays a video. If clicked again it will hide it and on and on. It works fine the only problem is that when the first time you click it you have to click it twice for some reason i can't seem to figure it out.
function togglevid() {
var e = document.getElementById("movie");
if (e.style.display == 'none') e.style.display = 'block';
else e.style.display = 'none';
if (e.pause == false) e.pause()
else e.pause()
}
#movie {
position:absolute;
top:158px;
left:470px;
display:none;
z-index:10
}
<video controls="" height="400" id="movie" oncontextmenu="return false;"
width="960">
<source src="" type="video/mp4">
Your browser does not support HTML5 video.</video>
<input id="mcodebtn" onclick="togglevid()" type="button" value=
"">
I believe the reason for this error is the fact i have the video set to display: none; by default.
Try below code, style property should be set to display:none.
The problem is that you are trying to access style property and then access display value. But the first time you run it, video tag does not have any style attribute set.
function togglevid() {
var s = document.getElementById("newcode");
var e = document.getElementById("movie");
if (e.style.display == 'none') e.style.display = 'block';
else e.style.display = 'none';
if (s.style.display == 'none') s.style.display = 'block';
else s.style.display = 'none';
if (e.pause == false) e.pause()
else e.pause()
}
#movie {
position:absolute;
top:158px;
left:470px;
display:none;
z-index:10
}
<video controls=""
height="400"
id="movie"
oncontextmenu="return false;"
width="960"
style="display:none;"><!-- Here we set a default value for style attr-->
<source src="" type="video/mp4">
Your browser does not support HTML5 video.</video>
<input id="mcodebtn" onclick="togglevid()" type="button" value=
"">
Try substituting window.getComputedStyle() for e.style.display
function togglevid() {
var e = document.getElementById("movie");
e.style.display = window.getComputedStyle(e, null)
.getPropertyValue("display") === "none"
? "block" : "none";
}
#movie {
position: absolute;
top: 158px;
left: 470px;
display: none;
z-index: 10
}
<video controls="" height="400" id="movie" oncontextmenu="return false;" width="960">
<source src="" type="video/mp4">
Your browser does not support HTML5 video.</video>
<input id="mcodebtn" onclick="togglevid()" type="button" value="toggle">

Categories

Resources