Reputation: 111
I am trying to make a generalized routine which will play a sound before redirecting to the specified href of a link. I'm trying to keep this as dynamic as possible to avoid having to add onclick events to each link manually, etc.
From other code on stackoverflow and elsewhere, I've managed to find almost exactly what I'm looking for.
document.querySelector('.playsound').onclick = function (evt) {
evt = evt || window.event;
playThenRedirectTo('sndButton', this.href);
// prevent the link from being followed, until we want to later on
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
}
function play_single_sound(target) {
document.getElementById(target).play();
}
function newPage(url) {
location.href = url;
}
function playThenRedirectTo(audioTarget, url) {
var time = 0;
play_single_sound(audioTarget);
setInterval(function () {
var end = document.getElementById(audioTarget).played.end(0);
if (end > time) {
time = end;
} else {
newPage(url);
}
}, 250);
}
This works for the first element on the page. The sound file is played prior to redirection. However I'm not sure how to make this apply to all elements with css class matching playsound as right now it only applies to the first.
I'm assuming querySelectorAll and some sort of forEach will be required, but I don't know what the syntax would be to use it. Any suggestions would be much appreciated!
Upvotes: 2
Views: 92
Reputation: 371193
While you could use querySelectorAll
to add a listener to every <a>
on the page, you might consider event delegation instead: add a single click listener to the document, and when something is clicked, check if the target is an a
. If so, call playThenRedirectTo
:
document.addEventListener('click', (e) => {
if (!e.target.matches('a')) return;
// if you only want `.playSound` `a`s to trigger this behavior, instead use
// if (!e.target.matches('a.playSound')) return;
playThenRedirectTo('sndButton', e.target.href);
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
});
The querySelectorAll
version involves using forEach
to iterate over all elements, and attaching a listener to each:
Array.prototype.forEach.call(
document.querySelectorAll('a.playsound'), // or whatever selector you want
playsound => playsound.onclick = e => {
playThenRedirectTo('sndButton', playsound.href);
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
);
(although on newer browsers, you can forEach
directly over a NodeList
, such as returned by querySelectorAll
, for that to work reliably for website visitors, you'd need a polyfill, thus the call
of the Array
method)
Upvotes: 1