Reputation: 33
I'm trying to make html5 audio player to play list of songs but it plays only two first ones and stops there.
I'm using this to make it play next song after one ends:
$(audio).on("ended", function() {
audio.pause();
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio(next);
audio.play();
showDuration();
});
Can't find out what is the problem here.
EDIT
Whole code:
JS
var audio;
$('#pause').hide();
initAudio($('#playlist li:first-child'));
function initAudio(element){
var song = element.attr('song');
var title = element.attr('songtitle');
var artist = element.attr('artist');
audio = new Audio('audio/' + song);
if(!audio.currentTime){
$('#duration').html('0:00');
}
$('#audio-player .title').text(title);
$('#audio-player .artist').text(artist);
$('#playlist li').removeClass('active');
element.addClass('active');
}
$('#play').click(function(){
audio.play();
$('#play').hide();
$('#pause').show();
showDuration();
});
$('#pause').click(function(){
audio.pause();
$('#pause').hide();
$('#play').show();
});
$(audio).on("ended", function() {
audio.pause();
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio(next);
audio.play();
showDuration();
});
HTML
<div id="audio-player">
<button id="play"></button>
<button id="pause"></button>
<ul id="playlist">
<li song="song1.wav" songtitle="Song1" artist="Artist1"></li>
<li song="song2.wav" songtitle="Song2" artist="Artist2"></li>
<li song="song3.wav" songtitle="Song3" artist="Artist3"></li>
<li song="song4.wav" songtitle="Song4" artist="Artist4"></li>
</ul>
<div id="audio-info">
<span class="artist"></span> <span class="title"></span>
</div>
</div>
Upvotes: 1
Views: 2942
Reputation: 566
Move this code:
$(audio).on("ended", function() {
audio.pause();
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio(next);
audio.play();
showDuration();
});
inside the initAudio
function, like this:
function initAudio(element){
var song = element.attr('song');
var title = element.attr('songtitle');
var artist = element.attr('artist');
audio = new Audio('audio/' + song);
if(!audio.currentTime){
$('#duration').html('0:00');
}
$('#audio-player .title').text(title);
$('#audio-player .artist').text(artist);
$('#playlist li').removeClass('active');
element.addClass('active');
$(audio).on("ended", function() {
audio.pause();
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio(next);
audio.play();
showDuration();
});
}
This will ensure the ended
call will be triggered for all the audio
elements, not only for the first one.
Currently, the ended
event is only fired once. So, the code plays the first song, triggers the ended
event, plays the second one and then doesn’t trigger ended
anymore.
This is because $(audio)
refers to the audio element that is destroyed and re-created when you do initAudio
. The line:
audio = new Audio('audio/' + song);
creates a new audio
element when you call initAudio. This new audio
element will not have the same callback attached to it.
$(audio).on("ended", ...);
is only attached one time, and if the code creates new elements of the same type, it won’t be re-attached to them. So, you need to re-attach your event callback each time the audio element is re-created, and this can be done in initAudio
. If you used selectors, a common method is to use $(document).on("ended", selector, ...);
for this, but it won’t work in your example, since audio
is not a selector.
Upvotes: 3