I have an html with a bunch of audio links. I am trying to make all of my audio links play/pause on click and I have tried the solution here. This is exactly what I am after, except that I am now stuck modifying this function to apply to all audio links in my code (since I cannot define one function per link). Ideas on how to do this?
Example:
<script type="text/javascript">
function loadAudio(source) {
currentSource = source;
audioSource.src = source;
audio.load();
}
var audio = document.getElementById('audio');
var audioSource = document.getElementById('audioSource');
var currentSource;
document.querySelectorAll('.play-audio').forEach(function(link) {
link.addEventListener('click', function() {
var linkSource = this.dataset.audio;
if (currentSource === linkSource) {
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
} else {
loadAudio(linkSource);
audio.play();
}
});
});
</script>
<audio id="audio">
<source id="audioSource" src=""></source>
Your browser does not support the audio format.
</audio>
<table>
<tr>
<td>Play 1</td>
</tr>
<tr>
<td>Play 2</td>
</tr>
</table>
If you want to play the audio one at a time. You can play them all through the same audio element by changing the source based on what link has been clicked:
function loadAudio(source) {
currentSource = source;
audioSource.src = source;
audio.load();
}
var audio = document.getElementById('audio');
var audioSource = document.getElementById('audioSource');
var currentSource;
document.querySelectorAll('.play-audio').forEach(function(link) {
link.addEventListener('click', function() {
var linkSource = this.dataset.audio;
if (currentSource === linkSource) {
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
} else {
loadAudio(linkSource);
audio.play();
}
});
});
<audio id="audio">
<source id="audioSource" src=""></source>
Your browser does not support the audio format.
</audio>
Click here to hear 1.
Click here to hear 2.
Click here to hear 3.
You can use a selector to find and pause/play your player.
Let's say you have 4 <audio> tags
<div class='audio-container'>
<audio id="audio1" src="/Demo1.mp3"></audio>
<a class='audio-play'>Click here to hear 1.</a>
</div>
<div class='audio-container'>
<audio id="audio2" src="/Demo2.mp3"></audio>
<a class='audio-play'>Click here to hear 2.</a>
</div>
<div class='audio-container'>
<audio id="audio3" src="/Demo3.mp3"></audio>
<a class='audio-play'>Click here to hear 3.</a>
</div>
<div class='audio-container'>
<audio id="audio4" src="/Demo4.mp3"></audio>
<a class='audio-play'>Click here to hear 4.</a>
</div>
Using JQuery:
$(".audio-container .audio-play").off("click").on("click", function() {
// $(this) -> ref to the currently clicked <a/>
//get the [0] element of the FIND query, because a TAG selector returns an array of found elements
var audio = $(this).parent().find("audio")[0];
var hasNotStarted = audio.paused && audio.currentTime == 0 && !audio.ended;
var hasEnded = audio.paused && audio.currentTime > 0 && audio.ended;
var isPaused = audio.paused && audio.currentTime > 0 && !audio.ended;
if(hasNotStarted || hasEnded || isPaused)
audio.play()
else
audio.pause();
});
Plain JS
//in plain JS, you will have to add a click event listener, on each element
var audioElems = document.querySelectorAll(".audio-container .audio-play");
for (var i = 0; i < audioElems.length; i++) {
audioElems[i].addEventListener("click", function() {
var audio = this.parentNode.children[0]
var hasNotStarted = audio.paused && audio.currentTime == 0 && !audio.ended;
var hasEnded = audio.paused && audio.currentTime > 0 && audio.ended;
var isPaused = audio.paused && audio.currentTime > 0 && !audio.ended;
if(hasNotStarted || hasEnded || isPaused)
audio.play()
else
audio.pause();
});
}
Related
I have 2 function which play the same video but with different timing.
I can't play make the function to work properly.
Looks like the function doesn't reset the other function
I tried to change variables names but still change the timing on click.
var video = document.getElementById('videoElm');
function playShortVideo() {
var starttime = 0; // start at 0 seconds
var endtime = 2; // stop at 2 seconds
video.addEventListener("timeupdate", function() {
if (this.currentTime >= endtime) {
this.currentTime = 0; // change time index here
}
}, false);
video.load();
video.play();
}
function playFullVideo() {
var starttime = 0; // start at 0 seconds
var endtime = 24; // stop at 2 seconds
video.addEventListener("timeupdate", function() {
if (this.currentTime >= endtime) {
this.currentTime = 0; // change time index here
}
}, false);
video.load();
video.play();
}
//play short video by default
playShortVideo();
//CLICK events
var btnshort = $('.shortvideo');
var btnfull = $('.fullvideo');
btnshort.click(function() {
playShortVideo();
});
btnfull.click(function() {
playFullVideo();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<video id="videoElm" autoplay muted controls loop>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/webm">
</video>
</div>
<button class="shortvideo">play 2 secs only</a><br>
<button class="fullvideo">loop full video</button>
That's because the listener is still there, you need to remove it.
Remember, in order to remove it, you can't use anonymous function as callback so I turned it into defined function.
var video = document.getElementById('videoElm');
const playShort = function() {
if (this.currentTime >= 2) {
this.currentTime = 0; // change time index here
}
};
const playFull = function() {
if (this.currentTime >= 24) {
this.currentTime = 0; // change time index here
}
};
function playShortVideo() {
video.removeEventListener("timeupdate", playFull, false)
video.addEventListener("timeupdate", playShort, false);
video.load();
video.play();
}
function playFullVideo() {
video.removeEventListener("timeupdate", playShort, false)
video.addEventListener("timeupdate", playFull, false);
video.load();
video.play();
}
//play short video by default
playShortVideo();
//CLICK events
var btnshort = $('.shortvideo');
var btnfull = $('.fullvideo');
btnshort.click(function() {
playShortVideo();
});
btnfull.click(function() {
playFullVideo();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<video id="videoElm" autoplay muted controls loop>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/webm">
</video>
</div>
<button class="shortvideo">play 2 secs only</a><br>
<button class="fullvideo">loop full video</button>
And here is the approach for starting the video at 49 sec (60 > 49 + 10)
const shortStartTime = 49;
const shortDuration = 10;
var video = document.getElementById('videoElm');
const playShort = function() {
if (this.currentTime > (shortStartTime + shortDuration)) {
this.currentTime = shortStartTime; // change time index here
}
};
const playFull = function() {
if (this.currentTime >= 24) {
this.currentTime = 0; // change time index here
}
};
function playShortVideo() {
video.removeEventListener("timeupdate", playFull, false)
video.addEventListener("timeupdate", playShort, false);
video.load();
video.currentTime = shortStartTime;
video.play();
}
function playFullVideo() {
video.removeEventListener("timeupdate", playShort, false)
video.addEventListener("timeupdate", playFull, false);
video.load();
video.play();
}
//play short video by default
playShortVideo();
//CLICK events
var btnshort = $('.shortvideo');
var btnfull = $('.fullvideo');
btnshort.click(function() {
playShortVideo();
});
btnfull.click(function() {
playFullVideo();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<video id="videoElm" autoplay muted controls loop>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/webm">
</video>
</div>
<button class="shortvideo">play 2 secs only</a><br>
<button class="fullvideo">loop full video</button>
That happens because you're attaching a timeUpdate event listener multiple times.
You either need to use one-only or delete it before attaching a new one.
var video = document.getElementById('videoElm');
var listener;
var starttime = 0;
var endtime = 2;
function updateVideo(e) {
if (e.target.currentTime >= endtime) {
e.target.currentTime = 0; // change time index here
}
}
function playShortVideo() {
starttime = 0; // start at 0 seconds
endtime = 2; // stop at 2 seconds
if (!listener) {
listener = video.addEventListener("timeupdate", updateVideo, false);
}
video.load();
video.play();
}
function playFullVideo() {
starttime = 0; // start at 0 seconds
endtime = 24; // stop at 2 seconds
if (!listener) {
listener = video.addEventListener("timeupdate", updateVideo, false);
}
video.load();
video.play();
}
//play short video by default
playShortVideo();
//CLICK events
var btnshort = $('.shortvideo');
var btnfull = $('.fullvideo');
btnshort.click(function() {
playShortVideo();
});
btnfull.click(function() {
playFullVideo();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<video id="videoElm" autoplay muted controls loop>
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/webm">
</video>
</div>
<button class="shortvideo">play 2 secs only</a><br>
<button class="fullvideo">loop full video</button>
I'm working on a web app in meteor and I'm trying to use the HTML5, CSS and Javascript audio playlist in my app:
var audio;
var playlist;
var tracks;
var current;
init();
function init(){
current = 0;
audio = $('audio');
playlist = $('#playlist');
tracks = playlist.find('li a');
len = tracks.length - 1;
audio[0].volume = .10;
playlist.find('a').click(function(e){
e.preventDefault();
link = $(this);
current = link.parent().index();
run(link, audio[0]);
});
audio[0].addEventListener('ended',function(e){
current++;
if(current == len){
current = 0;
link = playlist.find('a')[0];
}else{
link = playlist.find('a')[current];
}
run($(link),audio[0]);
});
}
function run(link, player){
player.src = link.attr('href');
par = link.parent();
par.addClass('active').siblings().removeClass('active');
audio[0].load();
audio[0].play();
}
#playlist,audio{background:#666;width:400px;padding:20px;}
.active a{color:#5DB0E6;text-decoration:none;}
li a{color:#eeeedd;background:#333;padding:5px;display:block;}
li a:hover{text-decoration:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<audio id="audio" preload="auto" tabindex="0" controls="" type="audio/mpeg">
<source type="audio/mp3" src="http://www.archive.org/download/bolero_69/Bolero.mp3">
Sorry, your browser does not support HTML5 audio.
</audio>
<ul id="playlist">
<li class="active">Ravel Bolero</li>
<li>Moonlight Sonata - Beethoven</li>
<li>Canon in D Pachabel</li>
<li>patrikbkarl chamber symph</li>
</ul>
When I try to click on the li to play a song it opens the file up in a new tab with the audio in white and a black background.
I was wondering if anyone knew how to fix this as I've been stuck on this issue for almost three days now.
Thanks,
Dillon Davis
.I've just loaded jQuery in the snippet you've provided, and that worked fine. No other changes were required.
Check below snippet:
var audio;
var playlist;
var tracks;
var current;
init();
function init(){
current = 0;
audio = $('audio');
playlist = $('#playlist');
tracks = playlist.find('li a');
len = tracks.length - 1;
audio[0].volume = .10;
playlist.find('a').click(function(e){
e.preventDefault();
link = $(this);
current = link.parent().index();
run(link, audio[0]);
});
audio[0].addEventListener('ended',function(e){
current++;
if(current == len){
current = 0;
link = playlist.find('a')[0];
}else{
link = playlist.find('a')[current];
}
run($(link),audio[0]);
});
audio[ 0 ].addEventListener( 'canplay', function( e ) {
this.play();
}, false );
}
function run(link, player){
player.src = link.attr('href');
par = link.parent();
par.addClass('active').siblings().removeClass('active');
}
#playlist,audio{background:#666;width:400px;padding:20px;}
.active a{color:#5DB0E6;text-decoration:none;}
li a{color:#eeeedd;background:#333;padding:5px;display:block;}
li a:hover{text-decoration:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<audio id="audio" preload="auto" tabindex="0" controls="" type="audio/mpeg">
<source type="audio/mp3" src="http://www.archive.org/download/bolero_69/Bolero.mp3">
Sorry, your browser does not support HTML5 audio.
</audio>
<ul id="playlist">
<li class="active">Ravel Bolero</li>
<li>Moonlight Sonata - Beethoven</li>
<li>Canon in D Pachabel</li>
<li>patrikbkarl chamber symph</li>
</ul>
Update: I've added play() method after player loaded audio
Update 2: I've moved .play() to canplay event.
I'm designing a landing page with video background. I'd like to auto-play a series of background video clips (looping back to #1 when the sequence runs out, although I haven't tried to integrate this wrinkle yet). I pulled some sample code off a reputable webdev blog and adapted it, but currently to no effect (my initial video plays once with the desired effect, but gives way to its poster image, rather than the next clip). Relevant html and js below. Help much appreciated!
<div id="video-box">
<video class="landing-video" autoplay muted poster="./resources/media/images/Two-Swimmers.jpg">
<source src="./resources/media/video/Two-Swimmers.mp4" type="video/mp4" />
</video>
<div class="video-playlist">
</div>
</div>
<script type="text/javascript" src="video.js"></script>
video.js code:
( function() {
var videoPlayer = document.getElementById( 'video-box' ),
video = videoPlayer.getElementsByClassName( 'landing-video' )[0],
playlist = videoPlayer.getElementsByClassName( 'video-playlist' )[0],
source = video.getElementsByTagName( 'source' ),
linkList = [],
videoDirectory = './resources/media/video/',
currentVideo = 0,
allLinks = playlist.children,
linkNumber = allLinks.length,
i, filename;
function playVideo( index ) {
allLinks[index].classList.add( 'current-video' );
currentVideo = index;
source[0].src = videoDirectory + linkList[index] + '.mp4';
video.load();
video.play();
}
for ( i = 0; i < linkNumber; i++ ) {
filename = allLinks[i].href;
linkList[i] = filename.match( /([^\/]+)(?=\.\w+$)/ )[0];
}
video.addEventListener( 'ended', function () {
allLinks[currentVideo].classList.remove( 'current-video' );
nextVideo = currentVideo + 1;
if ( nextVideo >= linkNumber ) {
nextVideo = 0;
}
playVideo( nextVideo );
} );
} () );
I changed video to have a src attribute, and I used setAttribute in the ended event handler.
var video = document.querySelector('video');
var links = document.querySelectorAll('.video-playlist > a');
var i = 0;
video.addEventListener('ended', function() {
i++;
if (i >= links.length) {
current = 0;
}
var a = links.item(i);
a.className = 'current-video';
video.setAttribute('src', a.href);
video.play();
});
<div id="video-box">
<video class="landing-video" autoplay muted src="https://www.w3schools.com/html/mov_bbb.mp4">
</video>
<div class="video-playlist">
</div>
</div>
I don't have your CSS so you can't see the <a> tags or the current-video class. I also don't have your video files so I grabbed some public videos for demonstration purposes.
I'm creating a personal small website and I want to play some songs on it. What I've tried to do is the following:
<script type="text/javascript">
var i=1;
var nextSong= "";
var audioPlayer = document.getElementById('audio');
audioPlayer.onended = function(){
i++
nextSong = "Music/"+i+".mp3";
audioPlayer.src = nextSong;
audioPLayer.load();
audioPlayer.play();
if(i == 37) // this is the end of the songs.
{
i = 1;
}
}
</script>
<audio id="audio" src="Music/1.mp3"controls="controls" autoplay="autoplay" align=""> </audio>
However, I can't get this to work. It just plays the first song and doesn't execute the JS. I've tried alerting the state of i for example but it doesn't do anything.
Try this:
<script type="text/javascript">
var i=1;
var nextSong= "";
function setup() {
document.getElementById('audio').addEventListener('ended', function(){
i++;
nextSong = "Music/"+i+".mp3";
audioPlayer = document.getElementById('audio');
audioPlayer.src = nextSong;
audioPLayer.load();
audioPlayer.play();
if(i == 37) // this is the end of the songs.
{
i = 1;
}
}, false);
}
</script>
<body onLoad="setup();">
<audio id="audio" src="Music/1.mp3"controls="controls" autoplay="autoplay" align=""> </audio>
</body>
Amendment needed on this answer. You need to also identify the audio player, otherwise this won't work...
<script type="text/javascript">
function setup() {
var i=1;
var nextSong= "";
audioPlayer = document.getElementById('audio');
document.getElementById('audio').addEventListener('ended', function(){
i=i+1;
nextSong = "m"+i+".mp3";
audioPlayer.src = nextSong;
audioPlayer.load();
audioPlayer.play();
}, false);
}
</script>
<body onLoad="setup();">
<audio id="audio" src="m1.mp3" controls="controls" autoplay="autoplay" align=""> </audio>
</body>
var i=1; var nextSong= ""; function setup() { document.getElementById('audio').addEventListener('ended', function(){ i++; nextSong = "Music/"+i+".mp3"; audioPlayer = document.getElementById('audio'); audioPlayer.src = nextSong; audioPLayer.load(); audioPlayer.play(); if(i == 37) // this is the end of the songs. { i = 1; } }, false); }
I have found a nice tutorial on how to build a playlist using HTML5 and JavaScript in blog post HTML5 Audio and Video and how to make a playlist. I followed the instructions, but I did not get the correct outcome.
This code SHOULD play all three audio files in order and stop when the last song has ended, but it what it actually does is autoplay the first file then stops when the first file is completed. What did I do wrong?
<html>
<body>
<ul id="playlist">
<li class="active">
<a href="http://www.codenamejupiterx.com/song/soundtest.mp3">
soundtest
</a>
</li>
<li>
<a href="http://www.codenamejupiterx.com/song/soundtest2.mp3">
soundtest2
</a>
</li>
<li>
<a href="http://www.codenamejupiterx.com/song/soundtest3.mp3">
soundtest3
</a>
</li>
</ul>
<script>
var audio;
var playlist;
var tracks;
var current;
init();
function init(){
current = 0;
audio = $('#audio');
playlist = $('#playlist');
tracks = playlist.find('li a');
len = tracks.length - 1;
audio[0].volume = .10;
audio[0].play();
playlist.find('a').click(function(e){
e.preventDefault();
link = $(this);
current = link.parent().index();
run(link, audio[0]);
});
audio[0].addEventListener('ended',function(e){
current++;
if(current == len){
current = 0;
link = playlist.find('a')[0];
}
else{
link = playlist.find('a')[current];
}
run($(link),audio[0]);
});
}
function run(link, player){
player.src = link.attr('href');
par = link.parent();
par.addClass('active').siblings().removeClass('active');
audio[0].load();
audio[0].play();
}
</script>
</body>
</html>
1) JavaScript code is using jQuery (those $(...) statements), so it must be imported:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
</head>
<body>
...
2) The audio HTML element (the real "player") is missed:
<body>
<audio id="audio" preload="auto" tabindex="0" controls="" >
<source src="http://www.codenamejupiterx.com/song/soundtest.mp3">
</audio>
...
3) The code play only TWO songs. To play THREE:
...
len = tracks.length; //"-1" removed
...
4) The code play again and again the three songs. To stop it:
audio[0].addEventListener('ended',function(e){
current++;
if(current < len){
link = playlist.find('a')[current];
run($(link),audio[0]);
}
});
Using jQuery I do have achieved this by using the following control.
Add the audio Control tag with following parameters:
<audio id="audio1" controls="controls" autoplay="autoplay"> </audio>
And in JavaScript:
jQuery(function($) {
var supportsAudio = !!document.createElement('audio').canPlayType;
if (supportsAudio) {
url = URL.baseUrl + Books + authors + "/" + subject + "/data.json";
$.getJSON(url, function(data){
console.log("ddd"+JSON.stringify(data));
var index = 0,
trackCount = data.URL.length,
npAction = $('#npAction'),
npTitle = $('#npTitle'),
audioid = $('#audio1').bind('play', function() {
}).bind('ended', function() {
if((index + 1) < trackCount) {
index++;
loadTrack(index);
audioid.play();
}
else {
audioid.pause();
index = 0;
loadTrack(index);
}
}).get(0),
loadTrack = function(id) {
index = id;
audioid.src = data.URL[index].ayah;
};
loadTrack(index);
});
}
});