I'm trying to make it so that when you click on a separate element it pauses the current song playing from a different element. In addition I had previously made it so when you click on the same element after it started playing audio it would pause that audio, but when you click on a different element with the same function it breaks.
var paused = true;
var song;
var songPlaying;
function playSong(x) {
song = x;
if(songPlaying != song){
document.getElementById(songPlaying).pause();
}
if(paused == true){
document.getElementById(song).play();
paused = false;
songPlaying = song;
} else {
document.getElementById(song).pause();
paused = true;
}
}
Is there anyway I can fix this? Will I have to make a different function for every song?
EDIT 1: Here the HTML my for the sections I'm using as well, each audio file has an ID that is called as a parameter in the function inside onclick
<div class="album">
<img src="assets/BattalionsOfFear.png" onclick="playSong('bofSong')">
<h1>Battalions of Fear</h1>
<p>Released in 1988</p>
</div>
<div class="album">
<img src="assets/FollowTheBlind.png" onclick="playSong('bfsSong')">
<h1>Follow the Blind</h1>
<p>Released in 1989</p>
</div>
<!--- Audio -->
<audio id="bofSong">
<source src="assets/BattalionsOfFear.mp3">
</audio>
<audio id="bfsSong">
<source src="assets/BanishFromSanctuary.mp3">
</audio>
EDIT 2:
In attempting Laif's solution
I have tried adding the 'song' class to my HTML img elements and linked it to my audio element with the 'song1' class yet it still is not working. Am I doing the classes wrong or is it something with the way I have put them down?
<div class="album">
<img src="assets/BattalionsOfFear.png" class="song song1">
<h1>Battalions of Fear</h1>
<p>Released in 1988</p>
</div>
<audio id="bofSong" class="song1">
<source src="assets/BattalionsOfFear.mp3">
</audio>
Each song should share the same class so that you can do something like this:
<html>
<div class="song"></div>
<div class="song"></div>
</html>
var songs = document.querySelectorAll(".song");
function playSong(e) {
songs.forEach(el => {
el.style.play();
});
e.currentTarget.pause();
};
songs.forEach(el => {
el.addEventListener("click", playSong);
});
Related
i want to build a image button, that plays an audio.
My Version works but when I want to use it more than once on a site, it only play one mp3, not the other ones.
My Code:
<audio loop="false" src="audio_01.mp3"> </audio>
<p><img alt="" class="hover_pic" src="image.png" style="width: 40%;cursor:pointer" /></p>
<script>
var aud = document.getElementById("ASong").children[0];
var isPlaying = false;
aud.pause();
function playPause() {
if (isPlaying) {
aud.pause();
} else {
aud.play();
}
isPlaying = !isPlaying;
}
</script></div>
and
<div id="BSong" onclick="playPause()" type="button">
<audio loop="false" src="audio_02.mp3"> </audio>
<p><img alt="" class="hover_pic" src="image.png" style="width: 40%;cursor:pointer" /></p>
<script>
var aud = document.getElementById("BSong").children[0];
var isPlaying = false;
aud.pause();
function playPause() {
if (isPlaying) {
aud.pause();
} else {
aud.play();
}
isPlaying = !isPlaying;
}
</script></div>
So you have an idea what the problem is that the button only play one of them on the website?
You are using the same variable names multiple times like aud, isPlayig, etc..
To solve this issue, you should declare only once the whole script and form the onclick="playPause()" send the id of the song you want to play.
Be aware if there is already some music which is playing.
It's hard to tell how your two current code snippets are arranged with respect to each other, but duplicating the code over and over every time you want to add another track is going to be unmaintainable. As it stands, the variables for isPlaying and aud probably overwrite each other, depending on how they're laid out, even if they're in different scripts. Using const or let instead of var and use strict; at the top of your script can help detect these aliases.
You could add closures around each one to keep them distinct, but a better approach is to write a loop (which also acts as a scoping closure) and dynamically add the listener to each element. For example:
const trackEls = [...document.querySelectorAll(".track")];
for (const trackEl of trackEls) {
const audioEl = trackEl.querySelector("audio");
trackEl.addEventListener("click", () => {
audioEl.paused ? audioEl.play() : audioEl.pause();
});
}
<div class="tracks">
<div type="button" class="track">
<audio src="https://upload.wikimedia.org/wikipedia/commons/d/d8/Bourne_woods_2020-11-18_0732.mp3"></audio>
<img alt="play track icon" src="http://placekitten.com/50/50" class="track-icon">
</div>
<div type="button" class="track">
<audio src="https://upload.wikimedia.org/wikipedia/commons/e/ea/Rapid-Acoustic-Survey-for-Biodiversity-Appraisal-pone.0004065.s017.ogg"></audio>
<img alt="play track icon" src="http://placekitten.com/50/50" class="track-icon">
</div>
</div>
Note that the above code lets multiple audio files play at once. If you want to stop all other audio elements when a new one is clicked and reset their time, you can do that with a loop or an extra variable that keeps track of the currently-playing track. For example:
const trackEls = [...document.querySelectorAll(".track")];
let currentTrack;
for (const trackEl of trackEls) {
const audioEl = trackEl.querySelector("audio");
trackEl.addEventListener("click", () => {
if (audioEl !== currentTrack) {
if (currentTrack) {
currentTrack.pause();
currentTrack.currentTime = 0;
}
currentTrack = audioEl;
}
audioEl.paused ? audioEl.play() : audioEl.pause();
});
}
<div class="tracks">
<div type="button" class="track">
<audio src="https://upload.wikimedia.org/wikipedia/commons/d/d8/Bourne_woods_2020-11-18_0732.mp3"></audio>
<img alt="play track icon" src="http://placekitten.com/50/50" class="track-icon">
</div>
<div type="button" class="track">
<audio src="https://upload.wikimedia.org/wikipedia/commons/e/ea/Rapid-Acoustic-Survey-for-Biodiversity-Appraisal-pone.0004065.s017.ogg"></audio>
<img alt="play track icon" src="http://placekitten.com/50/50" class="track-icon">
</div>
</div>
A few remarks on your code:
There's no need for isPlaying variables since audio elements already track their playing/paused state with audioElement.paused. If you track it in external state, you add further complication and room for bugs if your variable and the the audio element's state go out of sync.
Avoid putting a <script> in a <div>. <script> is usually a child of <body> or <head> (probably <body> in this case), after all of the HTML tags are closed.
onclick on an HTML element is generally poor practice. HTML should be structural, not behavioral. Similarly, style="width: 40%;cursor:pointer" should be moved to an external stylesheet and applied to a class.
.children[0]; is a brittle way to select the audio element in a track. If you wind up rearranging elements in the div, this code is liable to break. document.querySelector("#BSong audio") is more precise and robust to refactors, although using classes instead of ids enables easier dynamism so you don't have to type each track out by hand.
CSS classes are usually kebab-case, so hover_pic would be hover-pic.
I just put together this code to play audio on hover.. on a test page, trying to incorporate it into the rest of the site, but the jQuery is clashing with other jQuery, and noconflict mode at this point is a pretty huge job. Is it possible to do the following using only javascript ?
<audio id="whiterose" preload="auto">
<source src="//sarahboulton.co.uk/audio/white-rose.mp3"></source>
<source src="//sarahboulton.co.uk/audio/white-rose.ogg"></source>
</audio>
<div class="whiterose">
white rose?
</div>
<script>
//change audio 1 to audio 2.. 3 .. etc
var audioOne = $("#whiterose")[0];
$(".whiterose a")
.mouseenter(function() {
audioOne.play();
});
</script>
http://sarahboulton.co.uk/audio.html#
Thanks !
<audio id="audio" preload="auto" src="http://sarahboulton.co.uk/audio/white-rose.mp3"></audio>
<div id="test" style="background-color:red;" class="whiterose">
white rose?
</div>
<script>
var test = document.getElementById("test");
test.addEventListener("mouseover", function( event ) {
var audio = document.getElementById("audio");
audio.play();
}, false);
</script>
SCRIPT AND HTML CODE: When i click on a button, the other buttons are working. I've one class for buttons so how can i use multiple this button ?
Shall i add data_id for each button ?
Is this what you need?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio controls>
<source src="http://www.noiseaddicts.com/samples_1w72b820/4160.mp3" id="audio" type="audio/ogg">
Your browser does not support the audio element.
</audio>
Try adding a new class to the tag. And get the element on your JQuery by the new class, like this:
function play() {
var audio = document.getElementById('audio');
if (audio.paused) {
audio.play();
$('.play-button').addClass('icon-control-pause')
$('.play-button').removeClass('icon-control-play')
}else{
audio.pause();
$('.play-button').addClass('icon-control-play')
$('.play-button').removeClass('icon-control-pause')
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio src="audio.mp3" id="audio"></audio>
<i class="play-button icon-control-play i-2x" id="play" onclick="play()"></i>
I was hoping for some assistance with this. I have 3 audio instances on a single page. Handling the audio to play and pause isn't an issue. The issue is when audio is playing and I click play on another, I can't get the other audio instance to stop playing. So in the end I have these tracks all playing and I have to manual hit stop on each of them. My code below so far.
Honestly I am not sure how to go about doing the checks for this. First time doing something like this.
Any help would be appreciated :) thanks
HTML:
<div class="voting-artist">
<audio class="audio">
<source src="{{ song.url }}" type="audio/mpeg">
</audio>
<audio class="audio">
<source src="{{ song.url }}" type="audio/mpeg">
</audio>
<audio class="audio">
<source src="{{ song.url }}" type="audio/mpeg">
</audio>
</div>
jQuery/JavaScript:
$votingArtist.each(function(i, value) {
var $this = $(this);
var thisAudioPlayBtn = $this.find('.play-btn', $this);
var thisAudioStopBtn = $this.find('.stop-btn', $this);
var thisSelectionCont = $this.find('.selection--play-btn', $this);
var thisAudio = $this.find('.audio', $this);
thisAudioPlayBtn.on('click', function(e) {
thisAudio[0].play();
thisAudioPlayBtn.hide()
thisAudioStopBtn.show();
thisSelectionCont.addClass('is-playing');
});
thisAudioStopBtn.on('click', function() {
thisAudio[0].pause();
thisAudioPlayBtn.show()
thisAudioStopBtn.hide();
thisSelectionCont.removeClass('is-playing');
});
});
Just pause() them all!
thisAudioPlayBtn.on('click', function(e) {
$("audio").pause(); // Add this to pause them all.
$(".selection--play-btn").removeClass("is-playing"); // And remove the playing class everywhere too!
$(".play-btn").hide(); // Reset play/pause button
$(".stop-btn").show();
thisAudio[0].play();
thisAudioPlayBtn.hide()
thisAudioStopBtn.show();
thisSelectionCont.addClass('is-playing');
});
I have some divs that I use jQuery's fade in/out to bring onto the page when a link is clicked. Each page has an associated html5 audio element that also fades in/out accordingly.
$('.link').on('click', function(e){
var targetpage = $($(this).attr("href"));
$('.pagecontainer>div').fadeOut(0); //fade out currently displayed page
targetpage.fadeIn(); //fade in page associated with link
if (targetpage.children().hasClass('backgroundmusic')) {
$('audio').animate({volume: 0}, 1000); //fade out currently playing audio
alert('audio faded out');
$.each($('audio'), function () { //stop all audio
this.currentTime=0;
this.pause();
alert('audio stopped');
});
alert('stop function executed');
}
});
$('.sound').on('play', function () { //since volume was faded out, reset volume when click play button
$('audio').animate({volume: 1}, 100);
});
HTML:
Audio 1
Audio 2
Audio 3
<div class="pagecontainer">
<div id="page1"> //all three audio elements are in exact same spot
//clicking page link fades in current audio and fades in new one
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music1.mp3"/>
<source src="../../site/music/music1.ogg"/>
</audio>
</div>
</div>
<div id="page2">
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music2.mp3"/>
<source src="../../site/music/music2.ogg"/>
</audio>
</div>
</div>
<div id="page3">
<div class="backgroundmusic">
<audio controls loop class="sound" preload="none">
<source src="../../site/music/music3.mp3"/>
<source src="../../site/music/music3.ogg"/>
</audio>
</div>
</div>
</div>
The "alert('audio faded out')" will execute, but the "alert('audio stopped')" does not execute as it's not running the "$.each($('audio'), function" script at all, neither does "alert('stop function executed')". I have to use this "each" script as $('audio').currentTime=0 does not work, neither does $('audio').pause(), as I have multiple audio instances on my page.
Does anyone know why this is not working?
Thanks.
You pass in e to your function but don't use it. Probably want to prevent default action from that click event.
e.preventDefault(); //Put this at the top of the callback
This should fix your .each() problems. Also you should be using the console instead of alerts as to not freeze your page.
console.log('audio faded out'); //Use console instead of alerts
$('audio').each(function () { //Do it this way.
this.currentTime=0;
this.pause();
console.log('audio stopped');
});
console.log('stop function executed');