0

I'm trying to count how many times an HTML5 Audio object(audioPlayer) has played, by adding an 'ended' event, and using the played property which returns a Timesrange Object. Nevertheless, this approach only works
ok until the 1st complete listen, ie, when it ends I get a Timesrangeobject with all the partial listens. For further listens, it just "forgets" the 1st listen.

Here is my code

const audioPlayer = document.getElementById('soundPlayer');
audioPlayer.addEventListener(
    'ended',
    function() {
      const timesPlayed = audioPlayer.played;
      let totalTimePlayed = 0;
      for (let i = 0; i < timesPlayed.length; i += 1) {
        totalTimePlayed += timesPlayed.end(i) - timesPlayed.start(i);
      }
      const ratioPlayed = totalTimePlayed / audioPlayer.duration;
    },
    true
  ); 

A second question is: how do I force an ended event if the user leaves page while the audio is playing (ie, without having ended)? (This experiment is a multi-page webapp "survey" with an HTML5 Audio Element in each page, that the user listens to, then by pressing a button goes to the next page.

I'm trying to use the onbeforeunload, but I can't trigger the "ended" event.

function preventNavigatingAway() {
  window.onbeforeunload = function() {
    $('#soundPlayer').trigger('ended');
  };
}

Additional comment: I'm not sure if the order for which I'm calling the events is correct, so here is my full code:

function initAudio(audioPlayer) {

  audioPlayer.addEventListener(
    'ended',
    function() {
      const ratioPlayedInput = $("input:text[name='input-ratioPlayed']").val() || '0';
      let ratioPlayed = parseFloat(ratioPlayedInput);
      let timesPlayed = $("input:text[name='input-timesPlayed']").val();
      timesPlayed = parseInt(timesPlayed, 10) || 0;
      const currTimesPlayed = audioPlayer.played;
      let totalTimePlayed = 0;
      for (let i = 0; i < currTimesPlayed.length; i += 1) {
        totalTimePlayed += currTimesPlayed.end(i) - currTimesPlayed.start(i);
      }
      ratioPlayed += totalTimePlayed / audioPlayer.duration;
      ratioPlayed = parseFloat(ratioPlayed.toFixed(2));
      timesPlayed += currTimesPlayed.length;

      $("input:text[name='input-ratioPlayed']").val(ratioPlayed);
      $("input:text[name='input-timesPlayed']").val(timesPlayed);
    },
    true
  );
  return true;
}

function preventNavigatingAway() {
  console.log('preventNavigatingAway');
  window.onbeforeunload = function() {
    $('#soundPlayer').trigger('ended');
    console.log('in window.beforeunload()');
  };
}

document.addEventListener('DOMContentLoaded', function() {
  console.log('DOMContentLoaded!');
  const audioPlayer = document.getElementById('soundPlayer');
  initAudio(audioPlayer);
  preventNavigatingAway();
});
MrT77
  • 811
  • 6
  • 25
  • 1
    make the totalTimePlayed a global variable. Currently everytime the audio ends the totalTimePlayed is initialized to 0. – A Rogue Otaku May 04 '19 at 14:46
  • @Amit Das: thanks, that solved. What about the 2nd question: "how do I force an ended event if the user leaves page while the audio is playing (ie, without having ended)?". Do you have any idea on that? – MrT77 May 04 '19 at 15:01
  • What exactly do you mean by leaving the page? Like going to another tab? Minimizing the browser or just closing the browser? Try the `onbeforeunload` event for browser close and https://stackoverflow.com/questions/2720658/how-to-detect-when-a-tab-is-focused-or-not-in-chrome-with-javascript for tab change. – A Rogue Otaku May 04 '19 at 15:07
  • @AmitDas: I edited my question to answer you. – MrT77 May 04 '19 at 15:49

0 Answers0