Dynamically control HTML5 audio with JavaScript - javascript

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>

Related

Quality selection with 1 source file in HTML/JS [duplicate]

Goal:
I am trying to implement a control with as little code clutter as possible that will allow the change of quality of a video.
Preferences:
The following is what I am given, and I would rather work around it. I am open to using pre-built plugins or a javascript/jquery hack, but would rather not go for a solution that involves reinventing (me or you) the wheel (require the building of a custom video control scheme), but would take it as a last result.
EDIT:
Sorry. Did not mean to have that correlation, as the urls did not reflect any sort of pattern. I oversimplified it, not assuming people would look at the urls for a pattern. But thank you for that start, as I can probably work with that. Sorry again. I will change the urls to not have any pattern.
<video controls preload>
<source label="fullHD" src="http://v.com/lorem.mp4" type="video/mp4">
<source label="720p" src="http://v.com/ipsum.mp4" type="video/mp4" >
<source label="360p" src="http://v.com/dolor.mp4" type="video/mp4">
</video>
Thank you in advance for anybody who can give some insight.
Sorry for asking. Turns out I was able to solve it pretty much all by myself. Hate those moments. Here is the solution I came up with, which just involves copying the <source> I need based on the label attribute, deleting it, and prepending it into the <video> element:
HTML
<div class='vidcontainer'>
<select class='qualitypick' autocomplete='off'>
<option selected>fullHD</option>
<option>720p</option>
<option>360p</option>
</select>
<video controls preload>
<source label="fullHD" src="http://v.com/lorem.mp4" type="video/mp4">
<source label="720p" src="http://v.com/ipsum.mp4" type="video/mp4" >
<source label="360p" src="http://v.com/dolor.mp4" type="video/mp4">
</video>
</div>
JQUERY
$(document).ready(function(){
$('.qualitypick').change(function(){
//Have several videos in file, so have to navigate directly
video = $(this).parent().find("video");
//Need access to DOM element for some functionality
videoDOM = video.get(0);
curtime = videoDOM.currentTime; //Get Current Time of Video
source = video.find("source[label=" + $(this).textContent + "]"); //Copy Source
source.remove(); //Remove the source from select
video.prepend(source); //Prepend source on top of options
video.load(); //Reload Video
videoDOM.currentTime = curtime; //Continue from video's stop
videoDOM.play(); //Resume video
})
})
Although this was not my intention, I hope my answer is of some use. Sorry again for asking before thinking it through.
You don't need many source tags. One is enough, however, you need to change the value of the source attribute, which is src.
var map={'fullHD':'1080p','720p':'720p','360p':'360p'};
function changeQ(quality){
$('source','video#player').attr('src','http://v.com/'+map[quality]);
$('span#pp').html(map[quality]);
console.log($('source','video#player').attr('src'))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Quality
(<span id="pp"></span>)</button>
<ul class="dropdown-menu">
<li>FullHD</li>
<li>720p</li>
<li>360p</li>
</ul>
</div>
<video id="player" width="400" controls>
<source src="http://v.com/1080p" type="video/mp4">
</video>

Having multiple instances of video.js javascript video player

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'

How can I remove this shadow-root custom button from an HTML video?

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>

Change data-src to src via jquery

Im using a flexslider that has audio files for each slide, but I don't want to load countless audio files right away on the page. So im trying to get the data-src to become the src after each slide
the slides are currently as follows:
<div class="flexslider carousel">
<ul class="slides">
<li>
<img src="http://www.quinnmedical.com/skin/frontend/gigasavvy/quinn/ppt/Slide01.jpg" />
<audio id="demo" controls>
<source src="/skin/frontend/gigasavvy/quinn/audio/Slide1.mp3" type="audio/mpeg" />
</audio>
</li>
<li>
<img src="http://www.quinnmedical.com/skin/frontend/gigasavvy/quinn/ppt/Slide03.jpg" />
<audio id="demo" controls>
<source data-src="/skin/frontend/gigasavvy/quinn/audio/Slide3.mp3" src="" type="audio/mpeg" />
</audio>
</li>
</ul>
</div>
In the after function i want to change data-src to src. Any help would be greatly appreciated as how to go from data-src to src
Renaming an attribute is not be possible. You can add new attribute and remove the old one.
Suppose there is a click event as in the following example:
$('#demo').on("click", "img", function () {
var t = this;
var source = $(t).children("source");
$source.attr({
src: $t.attr('data-src')
}).removeAttr('data-src');
}
Please modify the event according to your requirements.
Try this:
$('source').attr("src", $(this).data('src'));
$('source').removeAttr('data-src');
This should move the url from data-src to src, and then remove the data-src attribute.
Inside the after function get the currently visible slide and then get the auto on it and it's source. Next check to see if it already has a src attribute. If not then set it to it's own .data('src'). Add this into the flexslider object.
after: function(){
var $currentAudio = $('.flex-active-slide audio source');
if(!$currentAudio.attr('src')){
$currentAudio.attr('src', $currentAudio.data('src'));
}
}

Make multiple html5-video start on click for iOS5

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.

Categories