Reputation: 9521
I'm using AJAX to load some rows from my database, among all data the most important is a path to audio file, for example uploads/song.mp3
.
I clear the content div with $('#content').html('');
and then loop (with jQuery.each) through data - creating containers with text and <audio>
element, that have song path loaded into src
attribute.
The problem is that not all songs play - on first load some of them do and some don't; then on next AJAX request, when I get new data and remove everything from #content
- not a single <audio>
element plays a song.
Here's some of the code:
$.ajax({
type: 'POST',
url: 'xxx.php',
data: {fr : fraza, ajax : true},
dataType: 'json'
}).success(function(retData) {
//console.log(retData);
$('#container').html('');
$.each(retData, function(index, value) {
var unos = value;
$('#glavni').append('<div class="pesma-item" id="pesma-id-'+ unos.id +'"><h2>' + unos.naziv + '</h2><img src="' + unos.note + '" alt="" /><div><p><pre>' + unos.temp + '</pre></p><br style="clear: both" /><audio controls preload="auto"><source src="' + unos.audio + '" type="audio/mpeg"></audio></div><br style="clear:both" /></div>');
$('#pesma-id-' + unos.id + ' audio')[0].load();
});
});
How can I force every audio
element to reload the file, so it can be playable?
Upvotes: 2
Views: 8554
Reputation: 6366
I believe there are a few issues that could be sorted out. For starters, I believe at least some of your issue is related to garbage collection. The Mozilla Docs suggest a method that first calls the pause()
method on the <audio>
element in question, then set the src
to an empty string. What I think is going on is that because preload="auto"
is set — which instructs (Read: suggests) the browser to load the entire stream on page load—this process continues, even though you've wiped out the <audio>
elements by emptying out your container $('#container').html('')
I've reworked a bit of your code to do a few things. The first being a loop to first pause()
all <audio>
elements, then set their src
to an empty string:
...
$('audio').each(function(){
$(this).pause().attr('src', '');
});
$('#container').empty();
...
The next thing I did was reformat the markup that you append to $("#glavni")
(main), mostly for my own sanity, but more importantly I removed the <source>
tag from your <audio>
element. With the src
property back on the <audio>
element, we can be sure which source is playing, as well as knowing our pause()
method is being called directly on the element in question.
$.ajax({
type: 'POST',
url: 'xxx.php',
data: {
fr: fraza,
ajax: true
},
dataType: 'json'
}).success(function (retData) {
//console.log(retData);
$('audio').each(function(){
$(this).pause().attr('src', '');
});
$('#container').html('');
$.each(retData, function (index, value) {
var unos = value, markup;
markup += '<div class="pesma-item" id="pesma-id-' + unos.id + '">';
markup += '<h2>' + unos.naziv + '</h2>';
markup += '<img src="' + unos.note + '" alt="" />';
markup += '<div>';
markup += '<p>';
markup += '<pre>' + unos.temp + '</pre>';
markup += '</p>';
markup += '<br style="clear: both" />';
markup += '<audio controls preload="auto" src="' + unos.audio + '">';
markup += '</audio>';
markup += '</div>';
markup += '<br style="clear:both" />';
markup += '</div>';
$('#glavni').append(markup);
// $('#pesma-id-' + unos.id + ' audio')[0].load();
});
});
One other thing — I commented out your load()
method.
The load() method is used to update the audio/video element after changing the source or other settings - Source
This was more of a precaution than anything—in theory, it shouldn't hurt you, but since the issues described are related to load/unload woes, I thought it best to remove it.
In the comments on your question, I mentioned the possibility of using one <audio>
element that is basically a recyclable object, reworked on-the-fly. If you continue to have issues, this approach may be worth exploring as its much easier to debug the behavior of one instance—not to mention it's less markup, which [if you ask me] is pretty much always a good thing.
Upvotes: 8
Reputation: 6888
Maybe try this..
HTML:
<div id="audio_player_container">
</div>
JS :
$.ajax({
type: 'POST',
url: 'xxx.php',
data: {fr : fraza, ajax : true},
dataType: 'json'
}).success(function(retData) {
//$('#container').html('');
// Maybe instead of removing html from #container you should do this
$('#glavni').empty();
$.each(retData, function(index, value) {
// store audio source in anchor href
var unos = value, markup;
markup += '<div class="pesma-item" id="pesma-id-' + unos.id + '">';
markup += '<h2>' + unos.naziv + '</h2>';
markup += '<img src="' + unos.note + '" alt="" />';
markup += '<div>';
markup += '<p>';
markup += '<pre>' + unos.temp + '</pre>';
markup += '</p>';
markup += '<br style="clear: both" />';
markup += '<a class="trigger" href="' + unos.audio + '">Play This';
markup += '</a>';
markup += '</div>';
markup += '<br style="clear:both" />';
markup += '</div>';
$('#glavni').append(markup);
});
});
$(".trigger").on("click", function(e) {
e.preventDefault();
var sourceUrl = $(this).attr("href"), audio_markup;
audio_markup += '<audio id="audio_player" controls preload="auto">';
audio_markup += '<source id="audio_src" src="' + sourceUrl + '" type="audio/mpeg">';
audio_markup += '</audio>';
$("#audio_player_container").html(audio_markup);
var player = $("#audio_player");
// maybe then do something
player[0].load();
player[0].play();
});
Upvotes: 1