Turn these several blocks of code into a loop?

Hi,

I have PHP writing out some jQuery to configure a script on a per-object basis. The jQuery works, but it’s ridiculous-looking under the hood, so I’m hoping someone can show me how to pare this down into the 2 tiny loops I’m thinking it can be. I do have the IDs (ie, sound0, sound1, sound2, …) ahead of time (in PHP) if that makes any difference.

Here’s my output:


		jQuery("a#sound0-play").click(function(){soundManager.pauseAll();sound0.play();});
		jQuery("a#sound0-pause").click(function(){sound0.pause();});
		jQuery("a#sound0-stop").click(function(){sound0.stop();});
		jQuery("a#sound0-volume-0").click(function(){sound0.setVolume(0);});
		jQuery("a#sound0-volume-1").click(function(){sound0.setVolume(10);});
		jQuery("a#sound0-volume-2").click(function(){sound0.setVolume(20);});
		jQuery("a#sound0-volume-3").click(function(){sound0.setVolume(30);});
		jQuery("a#sound0-volume-4").click(function(){sound0.setVolume(40);});
		jQuery("a#sound0-volume-5").click(function(){sound0.setVolume(50);});
		jQuery("a#sound0-volume-6").click(function(){sound0.setVolume(60);});
		jQuery("a#sound0-volume-7").click(function(){sound0.setVolume(70);});
		jQuery("a#sound0-volume-8").click(function(){sound0.setVolume(80);});
		jQuery("a#sound0-volume-9").click(function(){sound0.setVolume(90);});
		jQuery("a#sound0-volume-10").click(function(){sound0.setVolume(100);});

		jQuery("a#sound1-play").click(function(){soundManager.pauseAll();sound1.play();});
		jQuery("a#sound1-pause").click(function(){sound1.pause();});
		jQuery("a#sound1-stop").click(function(){sound1.stop();});
		jQuery("a#sound1-volume-0").click(function(){sound1.setVolume(0);});
		jQuery("a#sound1-volume-1").click(function(){sound1.setVolume(10);});
		jQuery("a#sound1-volume-2").click(function(){sound1.setVolume(20);});
		jQuery("a#sound1-volume-3").click(function(){sound1.setVolume(30);});
		jQuery("a#sound1-volume-4").click(function(){sound1.setVolume(40);});
		jQuery("a#sound1-volume-5").click(function(){sound1.setVolume(50);});
		jQuery("a#sound1-volume-6").click(function(){sound1.setVolume(60);});
		jQuery("a#sound1-volume-7").click(function(){sound1.setVolume(70);});
		jQuery("a#sound1-volume-8").click(function(){sound1.setVolume(80);});
		jQuery("a#sound1-volume-9").click(function(){sound1.setVolume(90);});
		jQuery("a#sound1-volume-10").click(function(){sound1.setVolume(100);});

		jQuery("a#sound2-play").click(function(){soundManager.pauseAll();sound2.play();});
		jQuery("a#sound2-pause").click(function(){sound2.pause();});
		jQuery("a#sound2-stop").click(function(){sound2.stop();});
		jQuery("a#sound2-volume-0").click(function(){sound2.setVolume(0);});
		jQuery("a#sound2-volume-1").click(function(){sound2.setVolume(10);});
		jQuery("a#sound2-volume-2").click(function(){sound2.setVolume(20);});
		jQuery("a#sound2-volume-3").click(function(){sound2.setVolume(30);});
		jQuery("a#sound2-volume-4").click(function(){sound2.setVolume(40);});
		jQuery("a#sound2-volume-5").click(function(){sound2.setVolume(50);});
		jQuery("a#sound2-volume-6").click(function(){sound2.setVolume(60);});
		jQuery("a#sound2-volume-7").click(function(){sound2.setVolume(70);});
		jQuery("a#sound2-volume-8").click(function(){sound2.setVolume(80);});
		jQuery("a#sound2-volume-9").click(function(){sound2.setVolume(90);});
		jQuery("a#sound2-volume-10").click(function(){sound2.setVolume(100);});

Obviously, this is pretty amateurish. But these blocks of code do exactly what I need, so I’m hoping it can be pared down into a javascript loop and not have to all be written out by-hand (well, with PHP) in this long-hand format.

Your wisdom is greatly appreciated!

Here is the code with 2 tiny loops.

		for(i = 0; i <= 2; i++) {
			jQuery("a#sound"+i+"-play").click(function(){soundManager.pauseAll(); eval("sound"+i).play();});
			jQuery("a#sound"+i+"-pause").click(function(){eval("sound"+i).pause();});
			jQuery("a#sound"+i+"-stop").click(function(){eval("sound"+i).stop();});
			for(vol = 0; vol <= 10; vol++) {
				jQuery("a#sound"+i+"-volume-"+vol).click(function(){eval("sound"+i).setVolume(vol * 10);});
			}
		}

Thanks a lot for the assist! This code doesn’t do the same thing as when I echo out all the statements manually (via PHP). No error is produced in the error console with your loops, so I’m at a loss as to what exactly to look at.

I’m linking directly to mp3 files, so if the click wasn’t being handled, it would serve them up as a download. This isn’t happening (nor do I want it to,) and I only mention it because that would seem to indicate that indeed the click was being handled in some way (ie, when clicked, nothing happens.)

Is there a particular panel in Firebug that would allow me to view exactly what the browser is seeing/interpreting (ie, the long-hand version of these functions), after parsing these loops?

Is it correct that all these functions made in these loops can all exist in memory at runtime (ie, the DOM), rather than procedurally in the source? I just want to be sure I’m understanding this properly and not merely finding a solution.

Anything you can add would be greatly appreciate, thanks again!

Very similar to the previous response but a little more structured and more maintainable.

for (var i = 0; i <= 2; i++) {
    // Define the name for this sound collection
    var name = 'a#sound' + i,
        call = window[name.substring(2)];

    // Setup all the click events
    jQuery(name + '-play, ' + name + '-pause, ' + name + '-pause').on('click', function() {
        switch (this.id.replace(new RegExp(name + '\\-'), '')) {
            // Play
            case 'play':
                soundManager.pauseAll();
                call.play();
            break;

            // Pause
            case 'pause':
                call.pause();
            break;

            // Stop
            case 'stop':
                call.stop();
            break;
        }
    });

    // Volume buttons
    for (var j = 0; j <= 10; j++) {
        jQuery(name + '-volume-' + j).on('click', function() {
            call.setVolume(j * 10);
        });
    }
}

tamilsuresh, I wanted to mention that your code did work once I got it in the right spot; I had it outside the (PHP) loop it needed to be in. Thanks again.

chris.upjohn, thanks, that is a rather elegant solution! I also like that it doesn’t use the eval function since there could be any number of sounds on a given page. I’m eager to give that a try!

I should mention that the sound IDs don’t necessarily stop at “sound2”; that was just for the sake of brevity in the original post. There can be any number of sounds from page to page. I know a foreach loop is going to cost more, but if I have all the ids available in an array ahead of this loop (and there’s not, say, more than 20-25 sounds per page), would that be a viable solution, or would so many iterations add a ton of overhead?

The soundManager API doesn’t contain any methods to see the number of instances created but what you can do is create a variable call num or something to that effect and simply increment the total starting from 0, so it works properly increment it before you run the soundManager setup method.

Once you have that working simply switch the static 2 over to the variable and your set.

Thanks for that. You obviously know what library I’m working with. While I have to admit that I don’t really understand what you just said, I do appreciate your follow-up. Actually, we can learn the number of instances and iterate over them as such (taken from the SM2 forum), though a ton of variations on these loops also didn’t produce the correct result:

for (var i=soundManager.soundIDs.length; i++;) {
    soundManager.setVolume(soundManager.soundIDs[i], 50);
}

…or…

for(var i in soundManager.sounds) {
     soundManager.getSoundById(i).setVolume(g);
}

It would be extremely helpful if I could see exactly what’s being interpreted by the browser, so I can better wrap my mind around what is going on under the hood. Coming from a PHP background, my mind tells me to just dump the variables I need to inspect to the screen and I’ve used both the alert function and Firebug to try and do that, but using alert will only tell me something is an object, not what it contains, and when using the console, I think I’m just not using the right view in spite of the fact that (I think) I’ve tried every last view there is. It’s easy to isolate a variable/array/object and learn about it if you know what you’re doing and what you’re looking for. Wish I did. Thanks again for your extended time and effort, but I probably shouldn’t take any more of your time on this; it’s just a pet project and I’m the one who cared about it anyway. :slight_smile:

Based on what you have above all you would need is

for (var i = 0, m = soundManager.soundIDs.length; i < m; i++) {
    // jQuery and soundManager code here...
}

I appreciate that; thanks again for your assistance. It’s painfully clear that I need to take a proper course in JS to get a better handle on the syntax. All I can say is “d’oh!” … well, and thanks. :slight_smile: