29

I have 10 audio players with simple html audio tags on a html5 page. No jquery, no special audio js plugins, etc...

Does anyone has a simple script in js to pause all other players when the current player is playing ?

I don't want to use js plugins because i want to keep a simple audio html code.

hedi
  • 1,266
  • 2
  • 10
  • 14

8 Answers8

103

you can use event delegation. Simply listen to the play event in the capturing phase and then pause all video file, but not the target one:

document.addEventListener('play', function(e){
    var audios = document.getElementsByTagName('audio');
    for(var i = 0, len = audios.length; i < len;i++){
        if(audios[i] != e.target){
            audios[i].pause();
        }
    }
}, true);
alexander farkas
  • 13,108
  • 4
  • 39
  • 41
11

Instead of looping over all audio tags on a page and pausing them, you can store a reference to the currently playing element, and have only that one pause when playing another.

document.addEventListener("play", function(evt) {
    if(this.$AudioPlaying && this.$AudioPlaying !== evt.target) {
        this.$AudioPlaying.pause();
    }
    this.$AudioPlaying = evt.target;
}, true);
bryc
  • 9,635
  • 6
  • 36
  • 58
  • 3
    I've fixed just one thing to prevent the same audio element to get caught into a bad working loop because you must skip the current one with `if(window.$_currentlyPlaying && window.$_currentlyPlaying != evt.target)`. Thank you, i've created that based on this and other questions related on [this gist.](http://erm3nda.github.io/blog/2016/06/02/javascript-html5-audio-swapper-and-remember-me-function) – m3nda Jun 14 '16 at 21:21
  • Changed to a better version that doesn't use global variable, and fixes the bug @m3nda mentions (Thanks). – bryc Jul 04 '21 at 08:45
5

Mixing both previous answers that didn't work, i've used that. I just added && window.$_currentlyPlaying != evt.target and all is working. Also i've created a gist with this and other goodies for audio tags. javascript-audio-tags

window.addEventListener("play", function(evt)
{
    if(window.$_currentlyPlaying && window.$_currentlyPlaying != evt.target)
    {
        window.$_currentlyPlaying.pause();
    } 
    window.$_currentlyPlaying = evt.target;
}, true);
m3nda
  • 1,832
  • 3
  • 32
  • 44
  • This one worked for me without any hitch. I just popped it at the bottom of the page where I have a similar audio script running. – abtecas Jul 06 '16 at 15:37
3
$("audio").on("play", function() {
    var id = $(this).attr('id');

    $("audio").not(this).each(function(index, audio) {
        audio.pause();
    });
});

$("video").on("play", function() {
    var id = $(this).attr('id');

    $("video").not(this).each(function(index, video) {
        video.pause();
    });
});
Canaan Etai
  • 2,844
  • 2
  • 19
  • 16
1

I don't know if it is because of Chrome updates, but the previous answers did not work for me. I modified a bit of the code here and came up with this:

document.addEventListener("play", function(evt)
{
    if(window.$_currentlyPlaying && window.$_currentlyPlaying != evt.target)
    {
        window.$_currentlyPlaying.pause();
    } 
    window.$_currentlyPlaying = evt.target;
}, true);

I don't know why, but the widow.addEventListener was not working for me, but I liked the idea of having the currentPlaying variable stored in the window element instead of having to create it outside of the listener prior to using it.

Boyd Cyr
  • 191
  • 1
  • 6
0

You can even try this solution, if you don't want to loop through

var previuosAudio;
document.addEventListener('play', function(e){
    if(previousAudio && previousAudio != e.target){
        previousAudio.pause();
    }
    previousAudio = e.target;
}, true);
  • The only difference between my code and this is the `document.xxx` instead of `window.xxxxx`, so, using Ajax or iframes would break the usage, i guess. – m3nda Jul 10 '16 at 13:08
  • tried to edit the first misspelled 'previous' but edits need to be at least 6 characters so I couldn't. – dijon Aug 13 '16 at 18:41
  • @dijon add "Hope it works" to the end of the answer :-) – m3nda Feb 25 '21 at 18:54
0

I made a player at the bottom and changed the src every time the user clicks on play this is just one way of doing it

HTML

<audio src="tracks/track1.mp3" type="audio/mp3" class='audios'></audio>
  <i class='fas fa-play'></i>
  <i class='far fa-pause-circle'></i>
  <i class='fas fa-stop'></i>
<audio src="tracks/track2.mp3" type="audio/mp3" class='audios'></audio>
  <i class='fas fa-play'></i>
  <i class='far fa-pause-circle'></i>
  <i class='fas fa-stop'></i>
<audio src="tracks/track3.mp3" type="audio/mp3" class='audios'></audio>
  <i class='fas fa-play'></i>
  <i class='far fa-pause-circle'></i>
  <i class='fas fa-stop'></i>

  <audio class='main-audio' controls>
     <source src="#" type="audio/mp3">
  </audio>

JavaScript

const audios_with_src = document.querySelectorAll('.audios')
const play = document.querySelectorAll('.fa-play')
const pause = document.querySelectorAll('.fa-pause-circle')
const stop = document.querySelectorAll('.fa-stop')
const main_player = document.querySelector('.main-audio')

for(let i =0; i < audios_with_src.length; i++) {
 play[i].addEventListener('click', (e) => {
    main_player.src = audios_with_src[i].src;
    main_player.play()   
    })

pause[i].addEventListener('click', () => {
    main_player.pause()
})

stop[i].addEventListener('click', () => {
    main_player.pause()
    main_player.currentTime = 0;  // there is no stop() function so had to do this
})


}

0

Best solution rewritten regarding ECMA 2022:

  document.addEventListener('play', (event) => {
    const audios = [...document.getElementsByTagName('audio')];
    
    audios.forEach((audio) => audio !== event.target && audio.pause());
  }, true);