badjuju badjuju - 14 days ago 6
Ajax Question

trigger functions no longer working after implement ajax scroll pagination

This is a pretty big question so bare with me.

I have developed an audio platform similar to Soundcloud and it all works(ed) perfectly! Until I decided to create an Ajax scroll pagination.

Both the pagination and Ajax work fine. However, I have noticed some JavaScript that used to work before implementing Ajax, which no longer does.

The script has a pretty simple duty; play a track when the user clicks the play button (or pause when the user clicks on it again). Then, once the track has finished, move on to the next track until it finally reaches the end.

What happens now is, when the page first loads up (along with the 10 tracks that load with the page), the

script
will work as it is supposed to. But, when the user scrolls down to get more results to load, if the user clicks on one of the newly loaded tracks play button, the track either won't play, or it will play over the other track which is supposed to pause (and then all the buttons just completely stop working).

Here is all of the
feed.js
(removed as much bloat code as possible, and placed comments):

$(document).ready(function(){ // on page load
var tp = 1; // set track page equal to one
loadTracks(tp); // then load all of the tracks

jQuery(function($) {
$('.f-outer-container').on('scroll', function() { // when the user scrolls to the bottom of the page load more tracks
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
tp++;
loadTracks(tp);
}
});
});
function loadTracks(track_page){
$.post('/spectrum-rr/core/_func/functions/loadTrack.php', {'page': tp}, function(data){ // get send and get data from loadTrack.php
$("#f-ap__aj").append(data); // append those tracks in the feed

// player functions
$(".track-w__trigger").click(function(){ // when the play button is clicked
var tid = $(this).attr('aria-trackid'), // get its track id
tiW = 'w' + tid + 'w',
tiW = eval(tiW); // set the waveform object

playPauseButton(this, tiW, tid);
});
});
}
});

// player functionality
function playPauseButton(button, wave, trackID){ // once the function has been called
pausePrevious(button); // pause the previous track (this doesn't work when more ajax results are loaded)
var button = $(button);

if(wave.isPlaying()){ // if the wave is playing; stop it
button.removeClass("playing");
wave.pause();
} else { // vice versa
button.addClass("playing");
wave.play();
}
var waveDuration = wave.getDuration();
var nextTrack = ++trackID;

var checkAudioFinished = setInterval(function(){ // check if the audio has finished playing every second
if(wave.getCurrentTime() >= waveDuration){ // if it has
button.removeClass("playing"); // remove it's buttons "playing" class
$('#w' + nextTrack + 'w-trigger').trigger('click'); // play the next song on the playlist by incrementing the id
clearInterval(checkAudioFinished);
}
}, 1000);
}
function pausePrevious(b){
$(".playing").not(b).each(function(){ // when this function is triggered
$(".playing").trigger('click'); // pause all of the other tracks (by simulating the click of their pause buttons
$(".playing").removeClass("playing"); // remove it's class too
});
}


I feel these problems are occurring due to the use of
$(document).ready();
. Forcing these functions to only be available to those tracks that were already loaded. However, I am not sure.

Here is the HTML that gets sent back from each request (in 10s):

<div class="f-wave-send f-waveform-container">
<div aria-trackid="1" class="track-w__trigger" id="w1w-trigger"></div> <!-- the "1" is generated by PHP. it is incremented for every div !-->
<div class="f-waveform-outer-container">
<div aria-trackid="1" class="track-w__waveform" id="w1-w"></div>
<script>
var w1w = WaveSurfer.create({ // wavesurfer script (this is the "wave" object that is being triggered inside the playPauseButton() function !-->
container: '#w1-w',
barWidth: 2,
});
w1w.load('./player/audio/sampleaudio.mp3');
</script>
</div>
</div>


If anyone could give me insight as to what might be going on (or any tips in improving my code for that matter), it would be greatly appreciated!

Answer

Try this,

You should not bind an click event each time load happens and it should be moved out of your loadTracks, instead you shuold apply event delegation.

           // player functions
            $(document).on('click', '.track-w__trigger', function(){ // when the play button is clicked
                var tid = $(this).attr('aria-trackid'), // get its track id
                    tiW = 'w' + tid + 'w',
                    tiW = eval(tiW); // set the waveform object

                playPauseButton(this, tiW, tid); 
            });