JS Audio – update to scriptaculous sound

I’ve made a fork of scriptaculous at github and put in an important edit to sounds.js. The pull request is in but if you don’t want to wait, you can grab the updated sound.js below .

Problem

While working on a website for design firm, they noticed the problem. When navigating to another page then back, lots of sounds would fire off. Weird!

In my original JS Audio Engine I was killing the element that played the sound after a set amount of time. That cleaned up the page. However when it was folded into scriptaculous so long ago, that code was removed/changed. So it made perfect sense that when you leave the page and come back, the browser sees all those elements and plays them. I’ve never noticed it because I’ve only used sounds in one-load-websites (ajax). There was never any web page navigation involved.

Solution

Not to undo any work done when incorporated into scripty, I came up with a self cleaning solution. When the js file is loaded it creates a random number ID:

randID = 'scriptaculous-soundboard-'+Math.floor(Math.random()*1000000000);

I know there is a way to create a UUID with prototype, but I don’t know it. Anyway… upon the first sound being played a hidden div with an ID of that random number is created:

// Is the soundboard created yet?
if (!$(randID)) {
	$$('body')[0].insert(
		new Element('div',{
			id: randID,
			style: 'visibility:hidden;'
		})
	);
	// All sounds will play from this soundboard
}

All sounds are now created within that div, instead of at the end of the BODY. When the page is left (onbeforeunload) that div is removed.

// Remove the soundboard when leaving
window.onbeforeunload = function() {
	if ($(randID)) {
		document.body.removeChild($(randID));
	}
}

So when you navigate back, no sounds play.

Download sound.js.zip
Follow github project

5 Replies to “JS Audio – update to scriptaculous sound”

  1. hello veteran,

    i like your scriptaculous used audio workaround making it not necessary using flash for only short sound snippets.
    while trying around i had problems to make a simple afterFinish / afterPlay Callback, maybe there are solutions depending on the used embed tag? or maybe a js sided way to make it more compatible?

    Could you give me a tip?

    thank you.

  2. @david
    Unfortunately there is no pure way to do this. The way I do it is by preloading the audio file, preload the plugin, then use a timer. Like so:
    1) Preload your audio using image tags. Yes, really 🙂

    <img src='myAudio.mp3' alt='' style='display:none;'>

    2) After the page is loaded, play a silent 1 second clip. That will ‘warm up’ whichever plugin the user’s system is set to play audio files.

    Event.observe(window,'load', function(){
    	Sound.play('blank.mp3');
    });

    3) Then play the file normally, of which you’ll know it’s length, let’s say 1 second for example.

    Sound.play('myAudio.mp3');

    4) Simply use…

    setTimeout("doSomethingElse();", 1010);
  3. Okay, thank you.

    By trying to fix this I used a timer with the duration of the audio file allready,
    but the preloading with an image-tag is a nice idea!

    I thought also to use an ajax-loader, for preloading the file binary, to get the duration in the header of the file.
    Maybe I’ll build a class someday, handling the preloading that way, I will post it here 😀

  4. @david
    You can do that… but you’ll still not definitely know when the file has finished playing. You’ll be using a timer just the same. Preloading the file and warming up the player would still be required for near-zero latency.

Comments are closed.