Search code examples
javascripthtmlaudioplayback

Stop all other <audio> onclick? (also some FontAwesome stuff)


Long-time lurker, first-time question-asker; my thanks to SO for all its help so far!

What I want: User clicks on one of thirty-ish buttons and hears the appropriate audio track. Clicking on another button plays another track, and stops any already-playing track. Super simple.

What happens: Bugger all.

I'm also changing a play/pause FontAwesome class (which also doesn't work) but I'll figure that one out later:

<audio id="song1"><source src="sample/1.mp3" type="audio/mpeg"></audio>
<audio id="song2"><source src="sample/2.mp3" type="audio/mpeg"></audio>
<audio id="song3"><source src="sample/3.mp3" type="audio/mpeg"></audio>

<button onclick="letsBoogie(song1);"><i class="fa fa-play-circle"></i></button>
<button onclick="letsBoogie(song2);"><i class="fa fa-play-circle"></i></button>
<button onclick="letsBoogie(song3);"><i class="fa fa-play-circle"></i></button>

<script>
var setList = document.getElementsByTagName('audio');

function letsBoogie(sample);
for(var i = 0, len = setList.length; i < len;i++){
    if(setList[i] != sample.target){
        setList[i].pause();
        setList[i].currentTime = 0;
        $(this).find('i').className = "fa fa-play-circle";
    } else {
    setList[i].play();
    $(this).find('i').className = "fa fa-pause-circle-o";
    }
}
}, true);
</script>

I've been tearing my hair out over this for days. Any help would be super-duper appreciated.


EDIT: For anyone who stumbles on this, here's the final working code. First, identify all audio:

<!-- this can be anywhere in body -->
<audio id="song1"><source src="sample/1.mp3" type="audio/mpeg"></audio>
<audio id="song2"><source src="sample/2.mp3" type="audio/mpeg"></audio>
<audio id="song3"><source src="sample/3.mp3" type="audio/mpeg"></audio>
...

Then place your icons (or buttons or links or whatever):

<i class="fa fa-play-circle" onclick="letsBoogie(song1,this)"></i>
<i class="fa fa-play-circle" onclick="letsBoogie(song2,this)"></i>
<i class="fa fa-play-circle" onclick="letsBoogie(song3,this)"></i>
...

Finally, shove this beauty in your JS:

var setList = $('audio');
function letsBoogie(tune, that) {
  if (tune.paused) {
  $.each(setList, function(index, alltunes) { // pause and reset all audio
    alltunes.pause();
    alltunes.currentTime = 0;
  });
    tune.play(); // then toggle play/pause targeted audio
  } else {
    tune.pause();
}
  tune.onplaying = function() { // change icon if playing
  $(that).attr('class', 'fa fa-pause-circle-o');
  }
  tune.onpause = function() { // change icon and reset if paused
  $(that).attr('class', 'fa fa-play-circle');
  sample.currentTime = 0;
  }
  tune.onended = function() { // change icon when finished
  $(that).attr('class', 'fa fa-play-circle');
  };
}

Solution

  • You need to .attr('class', to set the class than className as it is method of DOM api.

    Try this:

    var setList = $('audio');
    
    function letsBoogie(sample, that) {
      $.each(setList, function(index, elem) {
        elem.pause();
        elem.currentTime = 0;
      });
      $('button i').attr('class', 'fa fa-play-circle');
      sample.play();
      $(that).find('i').attr('class', 'fa fa-pause-circle');
    }
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <audio id="song1">
      <source src="sample/1.mp3" type="audio/mpeg">
        <source src="sample/1.ogg" type="audio/ogg">
    </audio>
    <audio id="song2">
      <source src="sample/2.mp3" type="audio/mpeg">
        <source src="sample/2.ogg" type="audio/ogg">
    </audio>
    <audio id="song3">
      <source src="sample/3.mp3" type="audio/mpeg">
        <source src="sample/3.ogg" type="audio/ogg">
    </audio>
    
    <ul>
      <li>Song 1</li>
      <li>
        <button onclick="letsBoogie(song1,this);"><i class="fa fa-play-circle"></i>
        </button>
      </li>
    </ul>
    <ul>
      <li>Song 2</li>
      <li>
        <button onclick="letsBoogie(song2,this);"><i class="fa fa-play-circle"></i>
        </button>
      </li>
    </ul>
    <ul>
      <li>Song 3</li>
      <li>
        <button onclick="letsBoogie(song3,this);"><i class="fa fa-play-circle"></i>
        </button>
      </li>
    </ul>

    Edit: I suggest you not to pass id attribute values as arguments(without quotes(")) as JavaScript will look for global variables having name as mentioned argument. If you have any other global variable having same name then your code will not work as expected. I will also suggest using JavaScript event binding than inline event binding.