skip to Main Content

We create buttons dynamically in Javascript or code-behind for all buttons in a web application… thousands of them throughout the application. Part of that build is the onclick=somefunction() part. I’d like to play an audio sound (click) before the onclick function specified is called. So, rather than building the string like this:

s = '<input type="button" onclick="somefunction()"...

I would build it like:

s = '<input type="button" onclick="playSystemSound(link); somefunction()"...
$('btnX').innerHTML = s;

However, some of the called functions have an alert in them and this stops the paying of the sound until the alert is cleared. I obviously can’t put the call to playSystemSound in the called functions, there’s way too many. So, I thought I could use an async function and await it before the "somefunction()" is called, but it still waits for the alert to be cleared. Using the sample above to call both functions, my code looks like this:

async function playSystemSound(link) {
    const audio = new Audio(link)
    await playSystemSoundEx(audio);
}

function playSystemSoundEx(audio) {
    return new Promise(res=>{
        audio.play()
        audio.onended = res
    })
}

So, given I must add a function before the existing function, my question is: How can I play the sound before continuing to the next function?

EDIT:
I should have added that I tried the set timeout first because that usually works for this sort of thing. That code looked like:

function playSystemSound(link) {
    setTimeout('playSystemSoundEx("' + link + '")', 50);
}

function playSystemSoundEx(link) {
    const audio = new Audio(link)
    audio.play();
}

2

Answers


  1. You can call the second function after you played the sound. In the example I use the ended event, but there could be other events. This trick kind of requires that you can turn the name of the second function into a function call. Here I use an object with the named functions.

    const functions = {
      func1: e => {
        alert('Alert from func1');
      },
      func2: e => {
        alert('Alert from func2');
      }
    };
    
    document.querySelectorAll('button').forEach(button => {
      button.addEventListener('click', playSystemSoundEx, true);
    });
    
    function playSystemSoundEx(clickevent) {
      let secondFunc = functions[clickevent.target.dataset.func];
      const audio = new Audio('https://cdn.pixabay.com/audio/2022/03/24/audio_719bb3b0e5.mp3');
      audio.addEventListener('ended', endevent => {
        //call second function
        secondFunc();
      });
      audio.play();
    }
    <button data-func="func1">Button 1</button>
    <button data-func="func2">Button 2</button>
    <button data-func="func1">Button 3</button>
    <button data-func="func2">Button 4</button>
    Login or Signup to reply.
  2. You should make sure the sound is loaded first, before you alert.
    You can use loadeddata event.

    function soundThenAlert() {
      const audio = new Audio('https://sofona.co.il/cors/firstblood.mp3');
      audio.addEventListener('loadeddata', () => {
        audio.play(); // Play after fully loaded
        alert(12)
      });
    }
    <button onclick="soundThenAlert()">click</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search