I am using videojs as the framework for a JavaScript video player page I am working on, its working great & I have customised the playback controls which are inside a div to match the spec I wanted (hide controls on load & then only show when the user has clicked play and has hovered etc).
I am now trying to make sure that the video player works when there is multiple instances on 1 page i.e if I add 4 or 5 videos to a page. the basic video.js functionality features seems to work fine but the additional control functionality which I have implemented will only work on the first instance of the video on the page (& thats because its just standard JS looking for that class & theres no unique ID per video player).
Here is what I have for the HTML:
<div class="cb-article-media__container padding-top-sm padding-bottom-sm">
<div class="cb-article-media__video-block">
<div class="c-video-container">
<video id="videoPlayer" class="video-js vjs-default-skin video-cover" width="100%" height="100%" controls preload="none" poster="<?php echo esc_url($video_thumbnail_url); ?>"
data-setup='{}'>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type='video/mp4'/>
</video>
</div>
</div>
</div>
<div class="cb-article-media__container padding-top-sm padding-bottom-sm">
<div class="cb-article-media__video-block">
<div class="c-video-container">
<video id="videoPlayer" class="video-js vjs-default-skin video-cover" width="100%" height="100%" controls preload="none" poster="<?php echo esc_url($video_thumbnail_url); ?>"
data-setup='{}'>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type='video/mp4'/>
</video>
</div>
</div>
</div>
and here is the JS:
var videoContainer = document.querySelector('#videoPlayer');
var videoControl = document.querySelector('.vjs-control');
var timeDivider = document.querySelector('.vjs-time-divider');
var timeDur = document.querySelector('.vjs-duration');
var fullScrControl = document.querySelector('.vjs-fullscreen-control');
$(document.body).on('click', '.vjs-fullscreen-control' , function(){
if (videoContainer && videoContainer.classList.contains('vjs-fullscreen') ) {
fullScrControl.className += " exit-full-screen";
} else {
fullScrControl.classList.remove("exit-full-screen");
}
});
$(document.body).on('click', '.vjs-big-play-button' ,function(){
// if (videoContainer.hasClass('vjs-playing')) {
videoContainer.className += " show-controls";
// }
});
How would I be able to make this JS/Jquery above work per instance of video player on the page (to show and hide the controls per player)? At present it only works for the first video player on the page.
Any help would be really appreciated.
Here is a codepen to the same issue:
https://codepen.io/nolimit966/pen/LYVyVzz
Thank you
Your HTML is incorrect - you have multiple elements with the same ID - videoPlayer. Each ID must be unique in its home subtree (document).
To fix this issue give each player a unique id, e.g.
<video id="videoPlayer1" ...
<video id="videoPlayer2" ...
In JS you just need make sure that you are controlling the correct player. To do this you probably just need to get the elements based on the control that was clicked rather than hard coding them.
You don't show the actual page markup - so this is a guess - but you want something like the following using "closest".
$(document.body).on('click', '.vjs-fullscreen-control' , function(){
// note this is a guess, it could be $(this).parent, is the player you want.
var player = $(this).closest('.video-js')
if(player.classList.contains('vjs-fullscreen')) {
player.closest('.vjs-fullscreen-control').className += " exit-full-screen";
} else {
player.closest('.vjs-fullscreen-control').classList.remove("exit-full-screen");
}
});
In any case the principal remains the same - remove your hardcoded selectors and target the elements relative to the target of the click handler. If this doesn't work then please provide the full mark-up of a video player showing all the elements such as '.vjs-control' and '.vjs-fullscreen-control'
Related
I have used a slide show on my web site. There are a couple of images and a video. I have not enabled any shadow elements or controls for this video, however there is a custom button to open it externally and I cannot disable it in any ways.
I have tried different JS scripts to attach a shadow and set the mode on closed, but I get the error that this video element cannot have an attached shadow.
Here's the button I am talking about
An example script that I have used:
function makeShadowTree(shadowClose) {
var root = shadowClose.attachShadow({mode: 'closed'});
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.slides--i').forEach(makeShadowTree);
});
<div class="slides">
<div class="slides--i" id="slide--1"></div>
<div class="slides--i" id="slide--2"></div>
<video autoplay muted loop class="slides--i" id="slide--video">
<source src="img/slides/slide-03-video.mp4" type="video/mp4">
</video>
</div>
What I am trying to do is to get popcorn.js to jump to a point in the video when a link is clicked. I tried using the below function, currentTime() but am unable to add the on click button to trigger the function.
http://popcornjs.org/popcorn-docs/media-methods/#currentTime
For the html side this is what I have.
<video height="180" width="300" id="video" controls>
<source src="http://videos.mozilla.org/serv/webmademovies/popcornplug.mp4"> </source>
<source src="http://videos.mozilla.org/serv/webmademovies/popcornplug.ogv"> </source>
<source src="http://videos.mozilla.org/serv/webmademovies/popcornplug.webm"></source>
</video>
<div id="footnotediv"></div>
<p id="click">Click me.</p>
This is what I have tried for the .js side
// create a popcorn instance
var $pop = Popcorn("#video");
// on click , switch the time back to 3 second
$pop.exec( document.getElementById("click").onclick, function() {
this.currentTime( 3 );
});
// play the video
$pop.play();
Can anyone help me point to what am I doing wrong? I am still trying to find my feet with this.
I think this is a syntax problem try this:
// create a popcorn instance
var $pop = Popcorn("#video");
// on click , switch the time back to 3 second
$pop.exec( document.getElementById("click").onclick, function() {
$pop.currentTime = 3;
});
// play the video
$pop.play();
I'm currently working on a page for playing different videos when you click an element. While it works beautifully on the computer, of iOS devices it does not. The problem is that when the element, in this case a button, is clicked, it shows the video but does not start playing, as it should. The script is
$(document).ready(function(){
$('#video_1, #video_2').hide();
$('.icon_1').click(function(){
$('#video_2').fadeOut(function(){
$('#video_1').fadeIn();
});
});
$('.icon_2').click(function(){
$('#video_1').fadeOut(function(){
$('#video_2').fadeIn();
});
});
$('.icon_1').click(function(){
$('.video_2').get(0).pause();
$('.video_2').get(0).currentTime = 0;
$('.video_1').get(0).play();
});
$('.icon_2').click(function(){
$('.video_1').get(0).pause();
$('.video_1').get(0).currentTime = 0;
$('.video_2').get(0).play();
});
});
and the html is
<button><div class="icon_1" id="mediaplayer" onclick="play">cadillac</div></button>
<button><div class="icon_2" id="mediaplayer2" onclick="play">nike</div></button>
<div id="video_1">
<video class="video_1" width="50%" height="50%" controls poster="http://www.birds.com/wp-content/uploads/home/bird.jpg" >
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type="video/mp4" />
</video>
</div>
<div id="video_2">
<video class="video_2" width="50%" height="50%" controls poster="images/BKG_JohnGT.png">
<source src="images/01.mp4" type="video/mp4" />
</video>
</div>
It anyone could give me a function that could mak this happen, tht would be great
iOS does not support more than one video element in a page at one time. It doesn't even give you an error message - it will merely display the poster image (or first frame) and then fail to play, just as you describe.
Unfortunately, you can't do a true cross-fade, but you can come close. Start with only one video element attached to the DOM. When switching from one video to another, you can fade the current video out, and then when it's done, remove it and add the second video. Apple has provided some details and code samples on how to do this.
In theory, you should be able to grab a snapshot of the video frame in a canvas and swap that in for the video and fade the canvas out, but iOS doesn't support capturing video frames in a canvas either.
These and some other non-standard behaviors are described well in this article.
I've got a gallery of sorts with 10 or so thumbnails that each represent one song. To control the playback of each, I've set a play button to fades in via jQuery. After some digging around Apple's Dev Center I found some native JavaScript to control audio. It works beautifully, but is written for control of one object at a time. What I'd like to do is rewrite it as one function that dynamically controls the playback/pause of the thumbnail you're selecting.
Below is the code that I found.. works, but it'd be a lot of unnecessary code to write it 10 times.
Thanks for your help and advice, always!
HTML:
<div class="thumbnail" id="paparazzixxx">
<a href="javascript:playPause();">
<img id="play" src="../images/icons/35.png" />
</a>
<audio id="paparazzi">
<source src="../audio/fernando_garibay_paparazzisnlmix.ogg" type="audio/ogg" />
<source src="../audio/fernando_garibay_paparazzisnlmix.mp3" type="audio/mpeg" />
Your browser does not support HTML5 audio.
</audio>
</div>
JavaScript:
<script type="text/javascript">
function playPause() {
var song = document.getElementsByTagName('audio')[0];
if (song.paused)
song.play();
else
song.pause();
}
</script>
jQuery is awesome for this sort of thing. It gives you the ability to easily manipulate elements based on their relationship to other elements in the DOM tree. In your example you want to be able to make the <a> elements only affect the <audio> elements that are right next to them when clicked.
The problem with your current Javascript code is that it is actually just grabbing only the first audio element on the entire page.
Here's how you can change your code to support an unlimited number of <a> & <audio> pairs.
Add a class to the <a> tag ('playback' in my example)
Replace the href attribute with a '#'
Then use jQuery to attach a handler to the click event for elements with that class.
HTML
<div class="thumbnail" id="paparazzixxx">
<a class="playback" href="#">
<img id="play" src="../images/icons/35.png" />
</a>
<audio id="paparazzi">
<source src="../audio/fernando_garibay_paparazzisnlmix.ogg" type="audio/ogg" />
<source src="../audio/fernando_garibay_paparazzisnlmix.mp3" type="audio/mpeg" />
Your browser does not support HTML5 audio.
</audio>
</div>
Javascript
<script type="text/javascript">
$(function() {
$(".playback").click(function(e) {
e.preventDefault();
// This next line will get the audio element
// that is adjacent to the link that was clicked.
var song = $(this).next('audio').get(0);
if (song.paused)
song.play();
else
song.pause();
});
});
</script>
I'm trying to create multiple links that when clicked, will change the source of the video being played on the player.
So far I have something that does ALMOST what I want to achieve:
HTML:
<video id="videoclip" width="640" height="480" controls preload="none">
<source id="mp4video" src="myvideo.mp4?dl=1">
</video>
<p>first video</p>
<p>second video</p>
<p>third video</p>
<p>fourth video</p>
Javascript:
videocontainer = document.getElementById('videoclip');
videosource = document.getElementById('mp4video');
newmp4 = 'newvideo.mp4?dl=1';
videobutton = document.getElementById("videolink1");
videobutton.addEventListener("click", function(event) {
videocontainer.pause();
videosource.setAttribute('src', newmp4);
videocontainer.load();
videocontainer.play();
}, false);
This works great. The problem is, the way the code is written, it will only allow me to change the first video into the second one and that's it. I want to be able to click the other links (videolink2, videolink3, etc) and change what video is being played to something else.
I already spend many hours looking at many other questions here but wasn't able to achieve my goal.
You need to think dynamic in situations like this. What you did to get one working is a good first stepping stone.
Each video link now has a data- attribute that holds the new source for that link.
Each video link also has the same class that way we can group them together using document.getElementsByClassName("videolink") which returns an array of elements with the classname videolink
Then run a loop over the returned array (which is a link element with the classname videolink) and add a click event on each one that calls the changeVideo function
this inside changeVideo refers to the element that was clicked. So we grab the data-videolink value using dataset property on the link element that was just clicked
Finally change the source of the video to that value.
var videocontainer = document.getElementById('videoclip');
var videosource = document.getElementById('mp4video');
var videoButtons = document.getElementsByClassName("videolink");
for (var i = 0; i < videoButtons.length; i++) {
videoButtons[i].addEventListener("click", changeVideo, false);
}
function changeVideo() {
var newLink = this.dataset.videolink;
console.log("Changing video to source: " + newLink);
//videocontainer.pause();
//videosource.setAttribute('src', newLink);
//videocontainer.load();
//videocontainer.play();
}
<video id="videoclip" width="640" height="480" controls preload="none">
<source id="mp4video" src="myvideo.mp4?dl=1">
</video>
<p>first video</p>
<p>second video</p>
<p>third video</p>
<p>fourth video</p>