When I pause an Audio and set it’s currentTime, it does something weird. when I press a button that controls the .paused
state of the Audio, it seems to click again automatically, preventing the audio from playing. Why?
Additionally, if I set the currentTime again, it decides to stop clicking the play button twice. this happens on and off every time I set the currentTime. it can be demonstrated with this code. (slowed audio is only because the example audio is too short).
<!doctype html><html><body>
<button id="play" disabled>play</button>
<button id="idk">load audio</button>
<script>
var clicks = 0; console.clear();
idk = document.getElementById("idk");
idk.addEventListener("click", async ()=>{
aud = new Audio("https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3")
aud.addEventListener('canplaythrough', init);
}, {once: true});
function init(){
/**/aud.playbackRate = 0.25;//only to lengthen the audio to give you time.
playButton = document.getElementById("play");
playButton.disabled = false;
idk.innerText = "pause and set time to 1";
playButton.addEventListener("click", e=>{
if(aud.paused){
aud.play();
playButton.innerText = "pause";
}else{
aud.pause();
playButton.innerText = "play";
}
//Nothing different between duplicate click events, logging it takes up space
console.log(clicks++, aud.paused, /*e*/);//clicks++ to tell apart logs.
});
idk.addEventListener("click", e=>{
console.log("Rightmost element clicked");
if(!aud.paused){ aud.pause(); playButton.innerText = "play"; }
aud.currentTime = 1;
});
}
</script>
</body></html>
See live example (removed event logging due to pollution of console)
simply click load audio
, then click play
once permitted, and finally click on pause and set time to 1
.
after such, the click event will be fired twice per actual click (as seen in the log), preventing the audio from playing. the only way to fix it is to click pause and set time to 1
again, and attempt clicking play
. You will be successful, but if you click the right button again, you will face this issue again.
I also noticed that the double-clicking turns into quadruple-clicking when modified slightly, still causing the issue, as 4 clicks is an even number.
<!doctype html><html><body>
<button id="play">play</button>
Control+Click to pause the audio and change it's currentTime value
<script>
var clicks = 0; console.clear();
playButton = document.getElementById("play");
playButton.addEventListener("click", async ()=>{
/**/window.aud = new Audio("https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3");
aud.addEventListener('canplaythrough', ()=>{
playButton.style.color = "#080";
/**/aud.playbackRate = 0.25;//only to lengthen the audio to give you time.
playButton.addEventListener("click", e=>{
if(e.ctrlKey){
if(!aud.paused){ aud.pause(); playButton.innerText = "play"; }
aud.currentTime = 1;
return;
}
if(aud.paused){
aud.play();
playButton.innerText = "pause";
}else{
aud.pause();
playButton.innerText = "play";
}
//Nothing different between duplicate click events, logging it takes up space
console.log(clicks++, aud.paused, /*e*/);//clicks++ to tell apart logs.
});
});
}, {once: true});
</script>
</body></html>
See live example (removed event logging due to pollution of console)
to use the second example, use CTRL+Click as the pause and set time to 1
button.
in both examples, running aud.play();
in the console seems to work, but still doesn’t allow the play/pause button to act and double clicks them. Setting aud.currentTime
in the console (after it has been set an even number of times) has no effect, and neither does having the code set aud.currentTime
twice in succession. The user has to click it and then click it again.
This occurs on Chrome Beta 127.0.6533.94 on ChromeOS, as well as Chrome 127.0.6533.85 and Firefox 129.0 on Android 14. I Can’t get it to work at all on non-EU iOS.
HOWEVER…
Safari 17.3 on MacOS Sonoma (via Browserling, if any difference made) appears to work as expected.
Sorry in advance, if that’s insufficient testing, or I made a really obvious mistake
2
Answers
To solve your problem, you have a few points to consider:
Event Listener Duplication : Each time you click the
play
button, a new event listener is added. This can cause multiple event listeners to be triggered, leading to the double-click behavior. To fix this, ensure that the event listener is added only once.Browser Differences: Different browsers, like in Google Chrome, handle the
currentTime
property differently, as told in this StackOverflow question, and in the MDN Docs: BaseAudioContext: currentTime property.Your problem, in this case, is that you triggered multiple times the
click
event on theplay
button, due to event duplication. Here’s the code:This ensures that the
togglePlayPause
function is called only once per click, preventing the multiple event listener issue.Here’s a much cleaner approach:
"click"
). One way is to use{once: true}
as the Event options (third argument) – but that adds complexity to the code and it’s hard to reason about and debug.const
,let
) to prevent polluting the global scopeconst aud = new Audio();
immediately in your variables. You’ll add.source
laterload()
(with the specific pause + time thing),toggle()
to toggle play/pause, andupdateUI()
which only job is to take care of the UI depending on theaud.paused
andaud.readyState
states"canplaythrough"
,"play"
and"pause"
Events in order to call thechangeUI
load()
andtoggle()
functions