Multiple HTML audio players with play/pause toggle text buttons - javascript

I'm an absolute newbie when it comes to javascript, but I'm trying to implement multiple audio players with separate songs on a page where the buttons toggles between the text "Listen" and "Pause" when clicked.
With the following code (EDITED) the text toggle and the play function works, but it only restarts the songs instead of pausing when clicked again.
<a class="audioButton" data-audio="song1.mp3">Listen</a><br>
<a class="audioButton" data-audio="song2.mp3">Listen</a><br>
(() => {
const AUD = new Audio(),
BTNS = document.querySelectorAll("[data-audio]");
function playPause() {
const src = this.dataset.audio;
if (AUD.src != src) AUD.src = src;
AUD[AUD.paused ? "play" : "pause"]();
BTNS.forEach(el => el.classList.remove("pause"));
this.classList.toggle("pause", !AUD.paused);
}
AUD.addEventListener("ended", playPause);
BTNS.forEach(el => el.addEventListener("click", playPause));
})();
$('.audioButton').on('click', function(e) {
$(this).text(function(i, s) {
return s === 'Pause' ? 'Listen' : 'Pause';
});
});

Related

How to prevent click function from running on double click?

I am new to Jquery and Javascript. I want my code to play a sound when clicking anywhere in the document, and a different sound when double clicking on a .marker.
It works right now, but when I double click the marker it plays the .click function twice along with the double click function.
How do I prevent the .click from playing when I double click?
Here is my Jquery code:
$(document).ready(function () {
$(document).click(function () {
setTimeout(function () {
let audio = document.createElement("audio");
audio.src = "audio/click-audio.wav";
audio.play();
}, 700);
});
$('.marker').dblclick(function () {
let audio = document.createElement("audio");
audio.src = "audio/page-audio.wav";
audio.play();
});
});
Just check whether clicked element is .marker :
$(document).click(function(event) {
if($(event.target).is(".marker")) return ;
setTimeout(function() {
let audio = document.createElement("audio");
audio.src = "audio/click-audio.wav";
audio.play();}, 700);
});
Using event properties, you could achieve
$('marker').click(function(event) {
if(!event.detail || event.detail == 1){
// code here.
// It will execute only once on multiple clicks
}
});
The stopPropagation() method stops the bubbling of an event to parent elements, preventing any parent handlers from being notified of the event.
$(document).click(function () {
setTimeout(function() {
let audio = document.createElement("audio");
audio.src = "audio/click-audio.wav";
audio.play();}, 700);
});
$('.marker').click(function (event) {
let audio = document.createElement("audio");
audio.src = "audio/page-audio.wav";
audio.play();
event.stopPropagation();
});
});
hope it will help you

AudioContext does not have a pause property?

I have used javascript Audio() before, but now I need to add some reverb effect in the audio and I am using reverb.js which uses the AudioContext api. I have the start property available, but no pause property? How do I pause or stop the audio??
Here is my code:
<script src="http://reverbjs.org/reverb.js"></script>
<script>
// 1) Setup your audio context (once) and extend with Reverb.js.
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
reverbjs.extend(audioContext);
// 2) Load the impulse response; upon load, connect it to the audio output.
var reverbUrl = "http://reverbjs.org/Library/SaintLawrenceChurchMolenbeekWersbeekBelgium.m4a";
var reverbNode = audioContext.createReverbFromUrl(reverbUrl, function() {
reverbNode.connect(audioContext.destination);
});
// 3) Load a test sound; upon load, connect it to the reverb node.
var sourceUrl = "./sample.mp3";
var sourceNode = audioContext.createSourceFromUrl(sourceUrl, function() {
sourceNode.connect(reverbNode);
});
</script>
Play
Stop
Also, I tried using stop(), and it works, but when I fire start() after clicking on stop, the start() doesn't work. Can you you help me out with a solution??
You can use the suspend() and resume() methods of AudioContext to pause and resume your audio: https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/suspend
One way to implement this with a single button for play/pause/resume, would be to add a function that controls the player state. For example:
let started = false;
function pauseOrResume() {
if (!started) {
sourceNode.start();
started = true;
document.getElementById("pauseButton").innerHTML = 'Pause';
} else if (audioContext.state === 'running') {
audioContext.suspend().then(function () {
document.getElementById("pauseButton").innerHTML = 'Resume';
});
} else if (audioContext.state === 'suspended') {
audioContext.resume().then(function () {
document.getElementById("pauseButton").innerHTML = 'Pause';
});
}
}
And replace your existing "Play" button with:
<a id="pauseButton" href="javascript:pauseOrResume()">Play</a>
This does the following:
If the audio hasn't yet been started, the link will say "Play".
If the user clicks "Play", the audio will start playing and the text of the link will change to "Pause".
If the user clicks "Pause" while the audio is playing, it will be paused, and the text of the link will change to "Resume".

Javascript pause sound when image is clicked

I'm using code that plays sound whn image is loaded (i'm using this as a play button on music player). But I have a problem, you can't stop sound when image is clicked (play button). So, do you know how can I make on this code, so sound pause when image is clicked.
My code:
<script type="text/javascript">
//Create new function that will update the image source on click.
function updateImage(el, soundfile) {
//Determine if music is playing or paused then adjust image
source accordingly.
if(soundfile.mp3.paused) {
el.src =
"imageurl.com";
} else {
el.src = "secondimageurl.com";
}
};
function playSound(el,soundfile) {
if (el.mp3) {
if(el.mp3.paused) el.mp3.play();
else el.mp3.pause();
} else {
el.mp3 = new Audio(soundfile);
el.mp3.play();
}
//Call new function made whenever the sound is toggled.
updateImage(document.getElementById("Bottom-1"), el);
};
</script>
<body onload="playSound(this, 'soundsource.mp3');">
<img src="buttonimage.html" name="Bottom-1" width="50" height="45"
border="0" id="Bottom-1"/>
</span>
</body>
Use SoundPlayer.js.
// Initialize
const player = new SoundPlayer();
// Load the sound
const sound = player.load('Sound.mp3');
// Play the sound
sound.play();
// load & play in one line
const sound = player.load('Sound.mp3').play();
And bind the image onclick event
image.onclick = function () {
sound[ sound.isPlaying ? 'pause' : 'play' ]();
image.src = sound.isPlaying ? 'isPlaying.jpg' : 'isPaused.jpg';
}
Full fiddle: https://jsfiddle.net/GustavGenberg/dxgph924/

Add code into JS with button click

So I have these buttons that when pressed play a sound, and I wanted to make a button that when pressed would allow these sounds to loop. I dont know how to explain this correctly, so ill just show the code
function aud1play() {
aud1.src = "aud1.mp3";
aud1.play();
}
document.getElementById('aud1button').addEventListener('click', aud1play);
function aud2play() {
aud2.src = "aud2.mp3";
aud2.play();
}
document.getElementById('aud2button').addEventListener('click', aud2play);
function aud3play() {
aud3.src = "aud3.mp3";
aud3.play();
}
document.getElementById('aud3button').addEventListener('click', aud3play);
is there a way to take the names (aud1, aud2, aud3) and put (name).loop; under each of the functions with a button press without having to actually write the (name).loop; for every one?
Try this
JS:
function play(){
var audio = document.getElementById("audio");
audio.play();
}
HTML5:
<audio controls loop id="audio">
<source src="horse.mp3" type="audio/mpeg">
</audio>
You should look at the bind method: https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/
function playAudio(type) {
aud.src = (type === '1') ?
"aud1.mp3" :
(type === "2") ?
"aud2.mp3" :
"aud3.mp3";
aud.play();
}
document.getElementById('aud1button').addEventListener('click', playAudio.bind("1"));
document.getElementById('aud2button').addEventListener('click', playAudio.bind("2"));
document.getElementById('aud3button').addEventListener('click', playAudio.bind("3"));
You could do something like this:
// create an object containing all audio objects
var audios = (function () {
var names = ['aud1.mp3', 'aud2.mp3', 'aud3.mp3'];
var audios = {};
for (var index in names) {
var audio = audios[names[index]] = new Audio();
audio.src = names[index];
}
return audios;
})();
function toggleAudioPlay () {
// "this" refers to the button that was clicked
var name = this.getAttribute('data-audio-src'); // read the button's "data-audio-src" attribute
if (!audios.hasOwnProperty(name)) {
// audio doesn't exist
return;
}
var audio = audios[name];
audio.src = name;
// toggle the play state
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
}
function toggleAudioLoop () {
var name = this.getAttribute('data-audio-src');
if (!audios.hasOwnProperty(name)) {
// audio doesn't exist
return;
}
var audio = audios[name];
audio.loop = !audio.loop;
}
document.querySelector('.audio-button-toggle-play').forEach(function (button) {
button.addEventListener('click', toggleAudioPlay);
});
document.querySelector('.audio-button-toggle-loop').forEach(function (button) {
button.addEventListener('click', toggleAudioLoop);
});
Now, you could have the following HTML:
<button class="audio-button-toggle-play" data-audio-src="aud1.mp3">Play/Pause the first audio</button>
<button class="audio-button-toggle-play" data-audio-src="aud2.mp3">Play/Pause the second audio</button>
<button class="audio-button-toggle-play" data-audio-src="aud3.mp3">Play/Pause the third audio</button>
<button class="audio-button-toggle-loop" data-audio-src="aud1.mp3">Enable/Disable looping of the first audio</button>
<button class="audio-button-toggle-loop" data-audio-src="aud2.mp3">Enable/Disable looping of the second audio</button>
<button class="audio-button-toggle-loop" data-audio-src="aud3.mp3">Enable/Disable looping of the third audio</button>
That way, you don't have to create a new function for each audio. Just add a new audio file to the "names" array and add a button with a special class (audio-button-toggle-play in order to toggle the play state of an audio) and a data-audio-src attribute containing the location of the audio file.

How to make multiple mp3 files play one after another on the click of a button using javascript or jquery?

I have the following html and script to play/pause an audio by clicking a button.
<audio id="testAudio" hidden src="sample.mp3" type="audio/mpeg">
</audio>
<button id="playAudio">Play</button>
<script>
document.getElementById("playAudio").addEventListener("click", function(){
var audio = document.getElementById('testAudio');
if(this.className == 'is-playing'){
this.className = "";
this.innerHTML = "Play"
audio.pause();
}else{
this.className = "is-playing";
this.innerHTML = "Pause";
audio.play();
}
});
</script>
I need to edit it in such a way as to play multiple mp3 files one by one in a defined order and stop only when the last audio has played.
I just don't know how to make that work. Can anyone help?
You can register an event handler for the audio tag, that first when the current file has finished;
document.getElementById("testAudio").addEventListener("ended",function(e) {
// Play next track
});
If you have a list of tracks to play in an array, then simply play the next one after the current track has finished. Using the setTimeout function you can put in a delay between the tracks. A simple example is as follows;
<script>
var playlist= [
'https://api.twilio.com/cowbell.mp3',
'https://demo.twilio.com/hellomonkey/monkey.mp3'
];
var currentTrackIndex = 0;
var delayBetweenTracks = 2000;
document.getElementById("playAudio").addEventListener("click", function(){
var audio = document.getElementById('testAudio');
if(this.className == 'is-playing'){
this.className = "";
this.innerHTML = "Play"
audio.pause();
}else{
this.className = "is-playing";
this.innerHTML = "Pause";
audio.play();
}
});
document.getElementById("testAudio").addEventListener("ended",function(e) {
var audio = document.getElementById('testAudio');
setTimeout(function() {
currentTrackIndex++;
if (currentTrackIndex < playlist.length) {
audio.src = playlist[currentTrackIndex];
audio.play();
}
}, delayBetweenTracks);
});
</script>
Note that cowbell track is 52 seconds long, so if your testing the above (for your own sanity) set the controls property to the audio tag so you can skip through most of it.

Categories