How can I play only one song on a page [duplicate] - 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.

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

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

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

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

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.

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

Best solution rewritten regarding ECMA 2022:
document.addEventListener('play', (event) => {
const audios = [...document.getElementsByTagName('audio')];
audios.forEach((audio) => audio !== event.target && audio.pause());
}, true);

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

Related

how can the audio going to play if the code given is correct on js

i am currently practicing my html and js skills and i have this code which is when i click the unlock button the audio will automatically play but the problem is even the unlock code is wrong the audio will still play this is my html on the button and on the audio
the audio tag:
<audio id="music" src="bgmusic.mp3" controls hidden loop></audio>
the button tag:
<button id="unlock" class="round pink" onclick="playAudio()">
Unlock
</button>
and here's my current js for the onlick event on the button
var x =
document.getElementById("music");
function playAudio() {
x.play();
}
that is my current syntax but what i want to happen is when the audio will only play if i enter the correct code
and here's the js function for the unlock code functionality:
var number = 0;
$('#unlock').on('click', function(event) {
event.preventDefault();
event.stopPropagation();
$('#textMachine').css('display', 'inline-block');
var code = '';
$.each($('.code'), function(i, v) {
code += $(v).val();
});
if(code == '30')
{
// success
var machine = $('#textMachine').slotMachine({
active: 0,
delay: 500,
randomize : function(activeElementIndex){
return 3;
}
});
machine.setRandomize(3);
machine.shuffle(5, function(){
answerCorrect();
});
} else {
if(number == 3) { number = 0; }
// fail
var machine = $('#textMachine').slotMachine({
active: 1,
delay: 500,
randomize : function(activeElementIndex){
return number;
}
});
machine.shuffle(5, function(){
number++;
});
}
});
var answerCorrect = function() {
$('.login-form').fadeOut();
$('.congratulation-text').fadeIn();
$('.success-area').css('display','block');
};
})();
well actually you can do this
function playSound () {
var audio = new Audio('audio_file.mp3');
audio.play();
}
and you can call it on your button or your function

Event Listener not firing if element is updated afterward

I wrote some custom audio controls in vanilla JS. Everything works as expected, except for one thing.
First, my method: I have a single audio element, and when a different song is selected, I pause the audio, update the audio element's sources, then run load() and play().
I have event listeners for the audio element as such:
audioElem.addEventListener('ended',updatePlayIcon);
audioElem.addEventListener('pause',updatePlayIcon);
audioElem.addEventListener('playing',updatePlayIcon);
I found that the pause event doesn't fire in the event that I am updating the audio element immediately afterward. I don't understand it at all.
It's probably best just to look at the site. http://joshblackburn-gregorythebold.rhcloud.com/albums
I had to add an explicit call to updatePlayIcon() in my function playTrack() because the pause method of the audo element isn't firing the event listener.
If it would be more helpful, I could write a minimal example showing the problem.
My question is this. Why isn't the event listener firing if I update the audio element after the pause() method?
Here is a more simple demo of the problem.
var tracks = ['https://upload.wikimedia.org/wikipedia/en/f/f8/Stipa_demo.ogg', 'https://upload.wikimedia.org/wikipedia/commons/c/c8/Example.ogg', 'https://upload.wikimedia.org/wikipedia/commons/f/f2/Median_test.ogg'];
audioContainer = document.getElementById('audio-container');
var audioElem = document.createElement('audio');
audioElem.controls = true;
audioElem.preload = "none";
var oggSource = document.createElement('source');
oggSource.type = "audio/ogg";
oggSource.src = tracks[0];
audioElem.appendChild(oggSource);
audioContainer.appendChild(audioElem);
var icon = document.getElementById('icon');
var getListItemByTrack = function(track) {
return document.querySelector('li a[data-track="' + track + '"]');
};
audioElem.addEventListener('pause', function() {
icon.innerHTML = "Paused";
console.log(audioElem.dataset.track);
getListItemByTrack(audioElem.dataset.track).className = "playLink paused";
});
audioElem.addEventListener('playing', function() {
icon.innerHTML = "Playing";
console.log(audioElem.dataset.track);
getListItemByTrack(audioElem.dataset.track).className = "playLink playing";
});
var togglePlayPause = function() {
var trackToPlay = this.dataset.track;
var trackPlaying = audioElem.dataset.track;
if (trackToPlay == trackPlaying) {
if (audioElem.paused) {
audioElem.play();
} else {
audioElem.pause();
}
} else {
audioElem.pause();
audioElem.dataset.track = this.dataset.track;
oggSource.src = tracks[parseInt(audioElem.dataset.track)]
audioElem.load();
audioElem.play();
}
};
var playLinks = document.getElementsByClassName("playLink");
for (var i = 0; i < playLinks.length; i++) {
playLinks[i].addEventListener('click', togglePlayPause);
};
.playLink {
cursor: pointer;
}
.playing::after {
content: " : playing";
}
.paused::after {
content: " : paused";
}
<div id="audio-container">
</div>
<div id="icon" class="material-icons">
Ready
</div>
<ol>
<li><a data-track="0" class="playLink">Play Track 1</a></li>
<li><a data-track="1" class="playLink">Play Track 2</a></li>
<li><a data-track="2" class="playLink">Play Track 3</a></li>
</ol>
If you click track 1 to play, you can keep clicking it to toggle play/pause and the pause event listener on the audio element fires, updating the list item's class (and therefor the :: after text).
However, if you click on Track 1, and while it's playing, click on track 2, it plays track 2, but track 1 never updates to paused, even though the pause() method is executed against the audio element. The event listener isn't firing!

Is there a way to do this in javascript?

All I want to do is to make the code below more compressed, because i have hundreds of words to vocalize.
<audio id="aufgabe" preload="auto">
<source src="../../../audio/aufgabe.mp3" type="audio/mpeg">Your browser does not support the audio element.</audio>
<button id="idj-play-button" class="btn btn-xs"><i class="glyphicon glyphicon-play"></i></button>
<button id="idj-pause-button" class="btn btn-xs hide"><i class="glyphicon glyphicon-pause"></i></button>
<script>
$('#idj-play-button').click(function() {
document.getElementById('aufgabe').play();
$('#idj-play-button').addClass('hide');
$('#idj-pause-button').removeClass('hide');
});
$('#idj-pause-button').click(function() {
document.getElementById('aufgabe').pause();
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
});
$('#aufgabe').on('ended', function() {
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
$('#aufgabe').load();
});
</script>
I have almost zero knowledge in javascript so I was wondering is there any way to make some kind of function, for example:
function vocalizeFile(aufgabe);
that leads to the other functions
<script>
$('#idj-play-button').click(function() {
document.getElementById('aufgabe').play();
$('#idj-play-button').addClass('hide');
$('#idj-pause-button').removeClass('hide');
});
$('#idj-pause-button').click(function() {
document.getElementById('aufgabe').pause();
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
});
$('#aufgabe').on('ended', function() {
$('#idj-pause-button').addClass('hide');
$('#idj-play-button').removeClass('hide');
$('#aufgabe').load();
});
</script>
so I dont have to make copy of this code everytime.
Thanks in advance!
You can trigger the event creating a custom data attribute and attaching a click event to it:
HTML:
<audio id="aufgabe" preload="auto">
<source src="../../../audio/aufgabe.mp3" type="audio/mpeg">Your browser does not support the audio element.
</audio>
<button id="idj-play-button" class="btn btn-xs" data-action="play" data-target="#aufgabe">
Play
</button>
<button id="idj-pause-button" class="btn btn-xs hide" data-action="pause" data-target="#aufgabe">
Pause
</button>
jQuery:
$('body').on('click','[data-action]',function() {
var action = $(this).data('action');
var target = $(this).data('target');
switch(action) {
case 'play':
$(target)[0].play();
break;
case 'pause':
$(target)[0].pause();
break;
}
console.log('Called action ',action,' on element ',target);
});
This way you just have to add data-action=[action-name] and data-target=#idOfTarget to each button and they'll work on any valid <audio> element with the specified id.
var $play = $('#idj-play-button');
var $pause = $('#idj-pause-button');
var $aufgabe = $('#aufgabe');
$play.click(playAudio);
$pause.click(pauseAudio);
$aufgabe.on('ended', onEnd);
var toggleButtons = function() {
$play.toggleClass('hide');
$pause.toggleClass('hide');
}
var playAudio = function() {
$aufgabe.play();
toggleButtons();
}
var pauseAudio = function() {
$aufgabe.pause();
toggleButtons()
}
var onEnd = function() {
$aufgabe.load();
toggleButtons();
}
I've just compressed your code and now it looks like this:
var $play = $('#idj-play-button');
var $pause = $('#idj-pause-button');
var $aufgabe = $('#aufgabe');
$play.on('click', function() {
playAudio();
toggleButtons();
});
$pause.on('click', function() {
pauseAudio();
toggleButtons();
});
$aufgabe.on('ended', function() {
loadAudio();
toggleButtons();
});
var toggleButtons = function() {
$play.toggleClass('hide');
$pause.toggleClass('hide');
}
var playAudio = function() {
$aufgabe.play();
}
var pauseAudio = function() {
$aufgabe.pause();
}
var loadAudtion = function() {
$aufgabe.load();
}
At first, I've cached all elements... If your variable contains an element, I recommend that you start it with $, because it says us that the variable is a jquery-element.
If you need to add class and then remove it, you should use toggleClass.
The code that manipulates with audio was divided by functions, because we need to maintain one level of abstructions.

How to play an audio file in a infinite loop using jQuery

Right now I have a piece of code (below) which allows me to play audio files on button click. However, I would like to have the file playing in a infinite loop until I click click the button "Stop" button.
How can I achieve that?
var audiotypes={
"mp3": "audio/mpeg",
"mp4": "audio/mp4",
"ogg": "audio/ogg",
"wav": "audio/wav"
}
function ss_soundbits(sound){
var audio_element = document.createElement('audio')
if (audio_element.canPlayType){
for (var i=0; i<arguments.length; i++){
var source_element = document.createElement('source')
source_element.setAttribute('src', arguments[i])
if (arguments[i].match(/\.(\w+)$/i))
source_element.setAttribute('type', audiotypes[RegExp.$1])
audio_element.appendChild(source_element)
}
audio_element.load()
audio_element.playclip=function(){
audio_element.pause()
audio_element.currentTime=0
audio_element.play()
}
return audio_element
}
}
var audio = ss_soundbits('audio/file.mp3');
var start_audio= function() {
audio.playclip();
};
Capture the ended event on the audio element, and then make it play again.
audio_element.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
This should be sufficient for you.
edit
As pointed out by #A. Wolff, I made an oversight wherein clicking stop would fire the ended event. Setting a global boolean flag will resolve this.
var stopped = false;
audio_element.addEventListener('ended', function() {
if(!stopped){
this.currentTime = 0;
this.play();
}
}, false);
var stop_button = document.getElementByID('stop');
stop.addEventListener('click', function(){
stopped = true
audio_element.stop();
});
Sorry for my comment - only addition: audio_element.play() may not work on mobile browsers without manual click

Ending a video in HTML using JavaScript events?

I am displaying a YouTube video on my html page using JavaScript.
How do I hide the video and retain the page that displayed the video using JavaScript?
I need to hide the video on a button click.
My code looks like this:
function addVideo(qId){
alert("a video");
var $videoComp = '<div class="vid" id="myytplayer"><iframe id="ifr" width="560" height="315" src="//www.youtube.com/embed/ac7KhViaVqc" allowfullscreen=""></iframe></div><div class ="main"><button class="btn btn-success" id="one" >Close video</button></div>';
$('.create-elem').append($videoComp);
$(".main").click(function(){
//$(".vid").hide();
//$("#one").hide();
function stopthevideo(){
var myPlayer = document.getElementById('myytplayer');
myPlayer.stopVideo();
}
});
This is what I do to identify end of video.
var myVideo = document.getElementById("video1");
myVideo.addEventListener('ended',onVideoEnded,false);
function onVideoEnded(e) {
if(!e) { e = window.event; }
// Make your things here
hideVideo = true;
}
Or you can always try work with https://developers.google.com/youtube/js_api_reference#Playback_status
Hope one of these will help you :)
The try to set video position at the ended event:
Save the start time and duration time to variable after loadedmetadata event.
var myVideo = document.getElementById("video1");
var videoStartTime = 0;
var videoEndTime = 0;
myVideo.addEventListener('loadedmetadata', function() {
videoStartTime = 2;
videoEndTime = 4;
this.currentTime = videoStartTime;
}, false);
If current time is greater than start time plus end of video time, pauses the video.
myVideo.addEventListener('timeupdate', function() {
if(this.currentTime > videoStartTime + videoEndTime ){
this.pause();
}
});

Categories

Resources