(function(){

	/* "Noisy events" demo | YUI 2.7 + SoundManager 2 */

	// first, make some sound parameter objects.

	var noises = [
	  {
	    id: 'click0',
	    url: '10884-batchku-doyng-1.mp3'
	  },{
	    id: 'click1',
	    url: '13658__LS__camera_click-1.mp3'
	  },{
	    id: 'click2',
	    url: '13658__LS__camera_click-2.mp3'
	  },{
	    id: 'man0',
	    url: '74472__qubodup__slightscream_source-1.mp3'
	  },{
	    id: 'man1',
	    url: '74472__qubodup__slightscream_source-2.mp3'
	  },{
	    id: 'man2',
	    url:	'74472__qubodup__slightscream_source-3.mp3'
	  },{
	    id: 'moving',
	    url: '35801__offthesky__chair_squeek.mp3',
	    volume: 75,
	    multiShot: false
	  },{
	    id: 'dragging',
	    url: 'brown_noise.mp3',
	    volume: 33,
	    multiShot: false
	  },{
	    id: 'drop',
	    url: '43603__FreqMan__object_falls_5_.mp3'
	  },{
	    id: 'type0',
	    url: '18625__Walter_Odington__type_writer-0.mp3'	
	  },{
	    id: 'type1',
	    url: '18625__Walter_Odington__type_writer-1.mp3'
	  },{
	    id: 'type2',
	    url: '18625__Walter_Odington__type_writer-2.mp3'
	  },{
	    id: 'type3',
	    url: '18625__Walter_Odington__type_writer-3.mp3'
	  },{
	    id: 'type4',
	    url: '18625__Walter_Odington__type_writer-4.mp3'
	  },{
	    id: 'type5',
	    url: '18625__Walter_Odington__type_writer-5.mp3'
	  },{
	    id: 'ding',
	    url: '18625__Walter_Odington__type_writer-ding.mp3'
	  },{
	    id: 'popHigh',
	    url: 'pop-high.mp3'
	  },{
	    id: 'popLow',
	    url: 'pop-low.mp3'
	  }
	];

	// lazy-add pre-pitch-bent sounds
	for (var i=1; i<11; i++) {
	  noises.push ({
	    id: 'pop'+i,
	    url: 'pop'+i+'.mp3'
	  });
	}

	var sounds = [];
	var draggables = [];
	var windowX = null;
	var windowX2 = null;

	function getPan(e) {
	  var x = YAHOO.util.Event.getXY(e)[0];
	  var pan = (x<windowX2?(windowX2-x)/windowX2*-100:(x-windowX2)/windowX2*100);
	  return pan;
	}

	function Draggable(oSounds,elementID) {

	  // Drag/drop box, sounds including pan effects	

	  var self = this;
	  this.sounds = oSounds;
	  this.o = document.getElementById(elementID);
	  this.dd = new YAHOO.util.DD(this.o);
	  this.timer = null;
	  this.isDragging = false;
	  this.css = {
	    dragging: 'is_dragging'	
	  }
	  this.x = null;

	  this.onMouseDown = function(e) {
		var s = self.sounds['man'+parseInt(Math.random()*3)];
		self.isDragging = true;
	    s.play({
		  pan:getPan(e)
		});
	    YAHOO.util.Dom.addClass(self.o,self.css.dragging);
	  }

	  this.onMouseOver = function() {
		if (!self.isDragging) {
	      sounds.click0.play();	
	    }
	  }

	  this.onMouseMove = function() {
	    if (self.timer) {
	      window.clearTimeout(self.timer);
	    }
	    var nPan = getPan({
		  clientX:YAHOO.util.Dom.getX(self.o),
		  clientY:0
		}); // hack as "e" is undefined here? Odd?
	    if (self.sounds.dragging.playState == 0) {
	      self.sounds.dragging.play({pan:nPan});
	    } else {
		  self.sounds.dragging.setPan(nPan);
	      if (self.sounds.dragging.paused) {
		    self.sounds.dragging.resume();
		  }
	    }
	    self.timer = window.setTimeout(self.stopSound,200);
	  }

	  this.stopSound = function() {
	    if (self.timer) {
	      window.clearTimeout(self.timer);
	      self.timer = null;
	    }
	    self.sounds.dragging.pause();
	  }

	  this.onMouseUp = function(e) {
	    self.stopSound();
	    self.sounds.drop.play({
		  pan: getPan({
		    clientX:YAHOO.util.Dom.getX(self.o),
			clientY:0
		  }) // hack as "e" is undefined here? Odd?
		});
	    YAHOO.util.Dom.removeClass(self.o,self.css.dragging);
		self.isDragging = false;
	  };

	  YAHOO.util.Event.addListener(this.o,'mouseover',this.onMouseOver);
	  this.dd.on('mouseDownEvent',this.onMouseDown);
	  this.dd.on('dragEvent',this.onMouseMove,self,true);
	  this.dd.on('mouseUpEvent',this.onMouseUp);

	}

	function ScrollHandler(oObj,oSound) {
	
	  // a rusty-sounding scrollable element.
	
	  var self = this;
	  this.timer = null;
	  this.timerInterval = (navigator.platform.match(/win32/i)?250:100); // windows needs more time.
	  this.o = oObj;
	  this.sound = oSound;

	  this.doScroll = function() {
	    if (self.timer) {
	      window.clearTimeout(self.timer);
	    }
	    if (self.sound.playState == 0) {
	      self.sound.play();
	    }
	    if (self.sound.paused) {
	      self.sound.resume();
	    }
	    self.timer = window.setTimeout(self.stopSound,self.timerInterval);
	  }

	  this.stopSound = function() {
	    self.sound.pause();
	    self.timer = null;
	  }

	  YAHOO.util.Event.addListener(this.o,'scroll',this.doScroll);

	}

	function start() {
	
		// general init, common stuff

	    windowX = YAHOO.util.Dom.getDocumentWidth();
	    windowX2 = parseInt(windowX/2);

		for (var i=0, j=noises.length; i<j; i++) {
		  sounds[noises[i].id] = soundManager.createSound(noises[i]);
		};
	
		draggables.push(
		  new Draggable(sounds,'dragdrop')
		);
	
		var s = new ScrollHandler(document.getElementById('noisy-textarea'),sounds.moving);
	
		// assign handlers to some of the form elements
	
		var f = document.getElementById('a-form');

		YAHOO.util.Event.addListener(f,'mousedown',function(e) {
		  var o = YAHOO.util.Event.getTarget(e);
		  if (o.nodeName.toLowerCase() == 'input' && o.type == 'button') {
			// noise only for buttons
		    sounds.click0.play();
		  }
		});

		YAHOO.util.Event.addListener(f,'click',function(e) {
		  var o = YAHOO.util.Event.getTarget(e);
		  // noise for buttons and checkboxes
		  if (o.nodeName.toLowerCase() == 'input') {
			if (o.type == 'button') {
		      sounds.click1.play();
		    } else if (o.type == 'checkbox') {
			  if (o.checked) {
			    sounds.popHigh.play();	
			  } else {
				sounds.popLow.play();
			  }
		    }
		  }
		});
	
		function makeType(e) {
		  // random keyboard sounds!
		  if (e.keyCode == 13) {
		    sounds.ding.play();	
		  } else {
		    sounds['type'+parseInt(Math.random()*6)].play();	
		  }
		}
	
		YAHOO.util.Event.addListener('noisy-textarea','keydown',makeType);

	}

	(function(){
		// YUI slider example, from http://developer.yahoo.com/yui/examples/slider/slider-ticks.html

		var Event = YAHOO.util.Event,
		    Dom   = YAHOO.util.Dom,
		    lang  = YAHOO.lang,
		    slider, 
		    bg="slider-bg", thumb="slider-thumb"

		// The slider can move 0 pixels up
		var topConstraint = 0;

		// The slider can move 200 pixels down
		var bottomConstraint = 200;

		// Custom scale factor for converting the pixel offset into a real value
		var scaleFactor = 0.5;

		// The amount the slider moves when the value is changed with the arrow keys
		var keyIncrement = 20;

		var tickSize = 20;

		Event.onDOMReady(function() {

		    slider = YAHOO.widget.Slider.getHorizSlider(bg, 
		                     thumb, topConstraint, bottomConstraint, 20);

		    // Sliders with ticks can be animated without YAHOO.util.Anim
		    slider.animate = true;

		    slider.getRealValue = function() {
		        return Math.round(this.getValue() * scaleFactor);
		    }

		    slider.subscribe("change", function(offsetFromStart) {

		        // use the scale factor to convert the pixel offset into a real value
		        var actualValue = slider.getRealValue();

		        // Update the title attribute on the background.  This helps assistive
		        // technology to communicate the state change
		        Dom.get(bg).title = "slider value = " + actualValue;
	
			    var i = actualValue/10;
			    sounds['pop'+(i==0?'Low':i)].play({pan:(actualValue<50?(50-actualValue)/50*-100:(actualValue-50)/50*100)});

		    });

		    slider.subscribe("slideStart", function() {
		            YAHOO.log("slideStart fired", "warn");
		        });

		    slider.subscribe("slideEnd", function() {
		            YAHOO.log("slideEnd fired", "warn");
		        });

		    // Listen for keystrokes on the form field that displays the
		    // control's value.  While not provided by default, having a
		    // form field with the slider is a good way to help keep your
		    // application accessible.
		    Event.on(textfield, "keydown", function(e) {

		        // set the value when the 'return' key is detected
		        if (Event.getCharCode(e) === 13) {
		            var v = parseFloat(this.value, 10);
		            v = (lang.isNumber(v)) ? v : 0;

		            // convert the real value into a pixel offset
		            slider.setValue(Math.round(v/scaleFactor));
		        }
		    });
    
		    // Use setValue to reset the value to white:
		    Event.on("putval", "click", function(e) {
		        slider.setValue(100, false); //false here means to animate if possible
		    });
    
		    // Use the "get" method to get the current offset from the slider's start
		    // position in pixels.  By applying the scale factor, we can translate this
		    // into a "real value
		    Event.on("getval", "click", function(e) {
		        YAHOO.log("Current value: "   + slider.getValue() + "\n" + 
		                  "Converted value: " + slider.getRealValue(), "info", "example"); 
		    });

		});

	})();


	// -------------------------------------------------------
	// soundManager (JS/Flash sound API) configuration

	soundManager.flashVersion = 9;
	soundManager.useHighPerformance = true;
	soundManager.debugMode = false; // disable or enable debug output
	soundManager.url = '../'; // path to directory containing SM2 SWF
	soundManager.defaultOptions.autoLoad = true;
	soundManager.defaultOptions.multiShot = true;

	soundManager.onload = function() {
	  // soundManager.createSound() etc. may now be called
	  setTimeout(start,1);
	}

})();
