hedi
hedi

Reputation: 1636

multiple audio html : auto stop other when current is playing with javascript

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.

Upvotes: 38

Views: 34092

Answers (8)

bryc
bryc

Reputation: 15056

Instead of looping over all audio/video 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.$MediaActive && this.$MediaActive !== evt.target) {
        this.$MediaActive.pause();
    }
    this.$MediaActive = evt.target;
}, true);

Using the this keyword allows the $MediaActive variable to be scoped to the listener object itself. This works because the listener is instantiated only once, and whenever the play event is triggered, $MediaActive will reflect the previous element it was set to.

If external access is required, one may replace this with any object they require. For example, using window will store the variable in the global scope.

Upvotes: 16

Sony Choudhary
Sony Choudhary

Reputation: 35

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);

Upvotes: 0

legoghetto
legoghetto

Reputation: 11

Best solution rewritten regarding ECMA 2022:

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

Upvotes: 1

Joe Powell
Joe Powell

Reputation: 1

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
})


}

Upvotes: 0

Boyd Cyr
Boyd Cyr

Reputation: 201

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.

Upvotes: 1

Canaan Etai
Canaan Etai

Reputation: 3775

$("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();
    });
});

Upvotes: 3

m3nda
m3nda

Reputation: 2027

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);

Upvotes: 6

alexander farkas
alexander farkas

Reputation: 14154

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);

Upvotes: 122

Related Questions