34

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,476
  • 2
  • 11
  • 14

8 Answers8

116

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,754
  • 4
  • 40
  • 41
12

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
  • 12,710
  • 6
  • 41
  • 61
  • 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
6

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,986
  • 3
  • 32
  • 45
  • 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
  • 3,455
  • 2
  • 21
  • 17
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
1

Best solution rewritten regarding ECMA 2022:

  document.addEventListener('play', (event) => {
    const audios = [...document.getElementsByTagName('audio')];
    
    audios.forEach((audio) => audio !== event.target && audio.pause());
  }, true);
legoghetto
  • 11
  • 2
  • `...document`, is this a thing? What are `...` for? – Sam Sirry Jul 31 '22 at 18:48
  • `document.getElementsByTagName('audio')` is a thing :) A collection of DOM nodes to be exact. And we use `...` aka spread operator to make an array of it. – legoghetto Aug 01 '22 at 13:44
  • It's the first time I come across the three-dot notation. I see; it seems like the call returns a `NodeList` or `HTMLCollection` (I don't care), and then it is turned into an Array. – Sam Sirry Aug 04 '22 at 22:10
  • 1
    Exactly! A collection has very similar structure to an array: it's indexed just the same and can be iterated with a for loop. But to use array methods like forEach it needs to be converted into an array first. – legoghetto Aug 17 '22 at 09:50
0

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

var previousAudio;
document.addEventListener('play', function(e){
    if(previousAudio && previousAudio != e.target){
        previousAudio.pause();
    }
    previousAudio = e.target;
}, true);
Yurié
  • 2,148
  • 3
  • 23
  • 40
  • 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
})


}