
// ------------------------------------------------------------
// Dihedrals Webascent Simple Slide Show.
// (c) 2007 by Dihedrals. All rights reserved. www.dihedrals.com
// ------------------------------------------------------------
/*
	SimpleSlideShow
	Controls a simple slide show.
*/

// Requires YUI Base + Dom + Event
/*----------------------- Constructor --------------------------
/ 
/ -------------------------------------------------------------*/
function SimpleSlideShow( pConfig ) {
	
	
	// Configs.
	this._baseImgEl = pConfig.baseImgEl || null;
	this._ssImagesList = pConfig.imageList || [];
	this._ssLoop = pConfig.loop || false;
	this._ssInterval = pConfig.interval || 10 * 1000;					
	this._ssTransitionTimer = pConfig.transitionInterval || 2 * 1000;	
	
	// Properties.
	this._currentSSImgIndex = 0;
	this._firstRun = true;
	this._ssIntervalID = null;
	this._isPaused = false;
	this._slideCounter = 0;
	
	this._transitionPlugin = null;
	
	this._preloadImageObj = new Image();
	this._areAllImagesLoaded = false;
	
	// Plugin Transition architecture?
	var config = {
		baseImgDomEl:		this._baseImgEl
	}
	this._transitionPlugin = new Blender( config );
	
	// Base Image's image src. Used to reset the slide show.
	this._baseImgElsImgPath = this._baseImgEl.attributes.src.nodeValue;
	
	
} // end constructor

	/*--------------------------- Getter ---------------------------*/
	SimpleSlideShow.prototype.getCurrentSlideIndex = function() {
		return this._slideCounter ;
	};
	
	/*--------------------------- Getter ---------------------------*/
	SimpleSlideShow.prototype.isPaused = function() {
		return this._isPaused;
	};
	
	/*--------------------------- Setter ---------------------------*/
	SimpleSlideShow.prototype.setImageList = function( pImageList ) {
		this._ssImagesList = pImageList;
		//console.log("Set Image List to: " + this._ssImagesList );
	};
	
	
	/*--------------------------- Setter ---------------------------*/
	SimpleSlideShow.prototype.setTransitionTime = function( pInterval ) { 
		if ( typeof( pInterval ) != "number" ) { 
			throw "Invalid value passed to SimpleSlideShow.setTransitionTime -> must be a Number. Passed: " + pInterval;
			return; 
		}
		this._ssTransitionTimer = pInterval;
		//console.log("Set Transition Time to: " + this._ssTransitionTimer );
	};
	
	/*--------------------------- Setter ---------------------------*/
	SimpleSlideShow.prototype.setInterval = function( pInterval ) { 
		if ( typeof( pInterval ) != "number" ) { 
			throw "Invalid value passed to SimpleSlideShow.setInterval -> must be a Number. Passed: " + pInterval;
			return; 
		}
		this._ssInterval = pInterval;
		//console.log("Set Slide Show Interval to: " + this._ssInterval );
	};
	
	/*--------------------------- Setter ---------------------------*/
	SimpleSlideShow.prototype.setLoop = function( pBool ) { 
		if ( typeof( pBool ) != "boolean" ) { 
			throw "Invalid value passed to SimpleSlideShow.setLoop -> must be a boolean. Passed: " + pBool;
			return; 
		}
		this._ssLoop = pBool;
		//console.log("Set Loop to: " + this._ssLoop );
	};
	
	/*--------------------------- Method ---------------------------
	/ Returns true if the SS is showing the final slide of the loop.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype.isLastSlide = function() {
		
		if ( this._currentSSImgIndex >= this._ssImagesList.length ) {
			return true;
		} else {
			return false;
		}
		
	};
	
	/*--------------------------- Method ---------------------------
	/ Starts the timer for the slide show. After the amount of time set
	/ via SSDelay, the next slide will be shown.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype.start = function() {
		this._isPaused = false;
		
		//this._reset();
		this._currentSSImgIndex = 0;
		this._slideCounter = 1;				// First slide is visible (the default 'Base' image)
		if ( this._firstRun !== true ) {
			//console.log( "Show Slide: 0. Looped to start, showing default Image." );
			this._transitionPlugin.doTransition( this._ssTransitionTimer, this._baseImgElsImgPath );
		}
		
		
		// Need to adjust the slide interval depending on wether or not
		// the Slide Show loops. 
		// The first slide will show for interval, afterwards the interval
		// needs to also have the transitionTimer added, otherwise they will
		// skew the timing of the Slide Show (consider a 2 second slide interval
		// with a 4 second transition timer...)
		var timeout = this._ssInterval;
		if ( this._firstRun !== true ) {
			timeout = this._ssInterval + this._ssTransitionTimer;
		}
		
		//alert( "Slide delay timer: " + timeout + ". (milliseconds)" );
		
		// Need to wrap setTimeout into an anonymous function to be able
		// to handle the passing 'this' scope issues with IE.
		var self = this;
		this._ssIntervalID = window.setTimeout( function() {
			self._cycle( self );
		}, timeout ); 
		
		// Preload 2nd Image.
		this._preloadNextImage();
		
		if ( this.evPlay ) { this.evPlay.fire(); }
	};
	
	
	/*--------------------------- Method ---------------------------
	/ Moves the slide show counter back to the start.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype.rewind = function() {
		this._reset();
	};
	
	/*--------------------------- Method ---------------------------
	/ Pauses the Slide Show at its current position.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype.pause = function() {
		this._isPaused = true;
		clearTimeout( this._ssIntervalID );
		if ( this.evPause ) { this.evPause.fire(); }
	};
	/*--------------------------- Method ---------------------------
	/ Pauses the Slide Show at its current position. 
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype.play = function() {
		if ( this._isPaused === true ) {
			this._isPaused = false;
			// Need to wrap setTimeout into an anonymous function to be able
			// to handle the passing 'this' scope issues with IE.
			var self = this;
			this._ssIntervalID = window.setTimeout( function() {
				self._cycle( self );
			}, this._ssInterval ); 
			if ( this.evPlay ) { this.evPlay.fire(); }
		}
	};
	
	
	/*--------------------------- Method ---------------------------
	/ Called each time the Slide Show starts by displaying the default image.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype._reset = function() {
		this._currentSSImgIndex = 0;
		this._slideCounter = 1;				// First slide is visible (the default 'Base' image)
		
		//if ( this._firstRun !== true ) {
			//console.log( "Show Slide: 0. Looped to start, showing default Image." );
			this._transitionPlugin.doTransition( this._ssTransitionTimer, this._baseImgElsImgPath );
		//}
		
	};
	

	/*--------------------------- Method ---------------------------
	/ Starts the timer for the slide show. After the amount of time set
	/ via SSDelay, the next slide will be shown.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype._cycle = function( me ) {
		
		// Check to see if we're at the end of the list of SlideShow images,
		// and if yes, either stop the slide show, or have it loop back to the
		// begining again.
		//alert("IE bug hunt. -> Before bug. me._currentSSImgIndex: " + this );
		if ( me._currentSSImgIndex >= me._ssImagesList.length ) {
			// At end of Image list.
			if ( me._ssLoop ) {
				me._currentSSImgIndex = 0;
				//console.log( " -> Loop Slide show to first image again." );
				me.start();
				return;
			} else {
				//console.log( " -> ! Stop Slide show." );
				me._isPaused = false;
				me._firstRun = true;
				me._currentSSImgIndex = 0;
				if ( me.evStop ) { me.evStop.fire(); }
				return;
			}
		}
		//alert("IE bug hunt.");
		
		me._firstRun = false;
		var timeout = me._ssInterval + me._ssTransitionTimer;
		// Add the transition time to the slide change interval, to keep them
		// from overlapping.
		// Need to wrap setTimeout into an anonymous function to be able
		// to handle the passing 'this' scope issues with IE.
		var self = me;
		me._ssIntervalID = window.setTimeout( function() {
			self._cycle( self );
		}, timeout );
		
		me._slideCounter++;
		me._transition();
		me._currentSSImgIndex++;
		
		// Preload next image.
		me._preloadNextImage();
		
	};

	/*--------------------------- Method ---------------------------
	/ Runs a timer that does the actual Transition of the slides (blend, etc.)
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype._transition = function() {
		this._transitionPlugin.doTransition( this._ssTransitionTimer, this._ssImagesList[this._currentSSImgIndex] );
	};
	
	
	/*--------------------------- Method ---------------------------
	/ Pre-fetch the next slide show image.
	/ -------------------------------------------------------------*/
	SimpleSlideShow.prototype._preloadNextImage = function() {
		
		if ( this._areAllImagesLoaded === true ) { return; }
		
		// Make sure we don't try and grab an image past the end of the images list.
		if ( this._currentSSImgIndex < this._ssImagesList.length ) {
			var nextImgPath = this._ssImagesList[this._currentSSImgIndex];
			var host = window.location.href;
			var host = host.replace( /\/$/,"" );    // Remove trailing '/' if any.
			// Todo: Check if we really need 'host' or if a relative path is ok...
			this._preloadImageObj.src = host + nextImgPath;
			//console.log( "Preload image: " + nextImgPath );
		} else {
			this._areAllImagesLoaded = true;
			//console.log( " -> All images Preloaded." );
		}
		
	};
	
	
	
	
	
	
	
	
	
	
/*
	SimpleSlideShow
	Transition Plugin :: Blender
	Console.log causes IE to fail silently -- careful!
*/
/*----------------------- Constructor --------------------------
/ 
/ -------------------------------------------------------------*/
function Blender ( pConfig ) {
	
	//var Dom = YAHOO.util.Dom;
	
	// *** Configs ***
	// Base Slide Show Image.
	this._baseImgDomElObj = pConfig.baseImgDomEl
	if ( ! this._baseImgDomElObj ) { 
		throw "'baseImgDomElName' config must point to a DOM object on the page: " + _baseImgDomElObj;
		return; 
	}
	
	
	// Properties.
	this._transitionIntervalMilliSecs = 0;	
	this._transToImagePath = '';
	this._dateObj = new Date();
	this._transStartTime = 0;
	this._transElapsedTime = 0;
	this._transFPS = 30;						// FPS is fixed at the moment (would be good to offer for an Advanced Slide Show setting)
	this._targetMilliS = 0;
	
	this._totalTransSteps = 0;
	this._currTransStep = 0;
	this._transTimerID = 0;
	
	this.tmpStartTime = 0;
	
	// Create the temporary 'Cover' elements that hold the actual slide
	// show images being switched back and forth.
	this._tmpTOPCoverEl = document.createElement( 'div' );
	this._tmpBASECoverEl = document.createElement( 'div' );
	if (document.all) { // IE Hack
		this._tmpTOPCoverEl.className = 'dwa-simpleSlideShowTransitionCover dwa-noPublish TOP';
		this._tmpBASECoverEl.className = 'dwa-simpleSlideShowTransitionCover dwa-noPublish BASE';
	} else {			// Rest of world.
		this._tmpTOPCoverEl.setAttribute( 'class', 'dwa-simpleSlideShowTransitionCover dwa-noPublish TOP' );
		this._tmpBASECoverEl.setAttribute( 'class', 'dwa-simpleSlideShowTransitionCover dwa-noPublish BASE' );
	}
	
	/**	Bug fix.
	*	The temp blend cover should match the Slide Show's image size.
	ssW = this._baseImgDomElObj.width;
	ssH = this._baseImgDomElObj.height;
	this._tmpBASECoverEl.setAttribute( 'width', ssW + 'px' );
	this._tmpBASECoverEl.setAttribute( 'width', ssH + 'px' );
	*/
	
	var parent = this._baseImgDomElObj.parentNode;
    if ( parent.lastChild == this._baseImgDomElObj ) {
        parent.appendChild( this._tmpTOPCoverEl );
    } else {
        parent.insertBefore( this._tmpTOPCoverEl, this._baseImgDomElObj.nextSibling );
    }
    parent.insertBefore( this._tmpBASECoverEl, this._tmpTOPCoverEl );
    
	//this._baseImgDomElObj.parentNode.insertBefore( this._tmpBASECoverEl, this._baseImgDomElObj );
	//this._baseImgDomElObj.parentNode.insertBefore( this._tmpTOPCoverEl, this._baseImgDomElObj );
	
} // end constructor

	/*--------------------------- Method ---------------------------
	/ Triggers the start of the Transition Timer (loop)
	/ -------------------------------------------------------------*/
	//Blender.prototype.doTransition = function( pSlideShowObj, pTransMilliSecs, pImageToTransTo ) {
	Blender.prototype.doTransition = function( pTransMilliSecs, pImageToTransTo ) {
		
		if ( typeof( pTransMilliSecs ) != "number" ) { 
			throw "Invalid value passed to Blender.doTransition -> must be a Number. Passed: " + pTransMilliSecs;
			return; 
		}
		this._transitionIntervalMilliSecs = pTransMilliSecs;
		this._transToImagePath = pImageToTransTo;
		//console.log("Starting Transition for slide: " + this._transToImagePath + ". Transition Seconds: " + (this._transitionIntervalMilliSecs / 1000) );
		
		
		// Set up the Transition.
		// Creates a 'Cover' element that overlays the Base Image.
		// Does anything else that needs to be set before starting the transition.
		this._setupTransition();
		
		// Need to wrap setTimeout into an anonymous function to be able
		// to handle the passing 'this' scope issues with IE.
		
		var self = this;
		this._transTimerID  = window.setTimeout( function() {
			self._transStep( self );
		}, this._targetMilliS ); 
		//console.log( "MilliS for Trans Timer: " + this._targetMilliS );
		
	};
	
	/*--------------------------- Method ---------------------------
	/ Set up the Transition.
	/ Add the next image to the Cover element.
	/ -------------------------------------------------------------*/
	Blender.prototype._setupTransition = function() {
		
		//console.log( " ++> Trans Startup <++ " );
		
		this._currTransStep = 0;
		
		// Check timing of actual transition.
		//this.tmpStartTime = Date.now();		// FF only -- IE yakks.
		
		
		// Calculate the number of individual steps for this transition. 
		// ( transSeconds x FPS )
		this._totalTransSteps = Math.ceil(( this._transitionIntervalMilliSecs / 1000 ) * this._transFPS );
		/**
		* Firefox Bug.
		* Flickering image when the number of steps exceeds 100 (opacity related, am guessing.)
		* Fix: Limit the number of steps for opacity based transitions to max 99.
		* Opacity only allows for a max of 100 steps, so this doesn't damage anything for
		* this type of transition.
		*/
		this._targetMilliS = ( 1000 / this._transFPS );
		if ( this._totalTransSteps > 99 ) {
			// also need to adjust this._transitionIntervalMilliSecs as we've changed the number of
			// steps for this transition. For example a 10 sec transition at 30fps gives us a total
			// of 300 individual trans steps. If we cap the steps at 99 (0-99 == 100 steps), then
			// we'll be missing 200 steps and the transition will only run for 3.33 seconds instead 
			// of the desired 10.
			var milliMuliplier = this._totalTransSteps / 100;		// 100 is the capped number of steps.
			this._targetMilliS = Math.ceil( this._targetMilliS * milliMuliplier );
			//console.log( "Target MilliS *WITH* capping: " + this._targetMilliS );
			this._totalTransSteps = 99;								// 100 -> Zero based.
		} else {
			// standard transition milliS value (no capping at 100 steps)
			this._targetMilliS = parseInt( 1000 / this._transFPS );
			//console.log( "Target MilliS *NO* capping: " + this._targetMilliS );
		}
		
		// Copy the component's saved html image to the Base SS Cover.
		// This lets us avoid any issues when Publishing a modified DWA
		// EditBox with a running slide show in it (as the temp Top/Base
		// Cover elements are marked with 'dwa-noPublish' which stops 
		// them from being saved.)
		//var innerImg = '<img src="' + this._baseImgDomElObj.attributes.src.nodeValue + '" alt=""/>';
		this._tmpBASECoverEl.innerHTML = this._tmpTOPCoverEl.innerHTML;
		
		// Set Top Cover to transparent, and update its image to the next (2nd)
		// image of the slide show.
		this._setOpacity( this._tmpTOPCoverEl, 0 );
		var innerImg = '<img src="' + this._transToImagePath + '" alt=""/>';
		this._tmpTOPCoverEl.innerHTML = innerImg;
		
		// Finally *hide* the SS's actual html base image, as its not being updated
		// by the slide show animation, and is only displayed when the page is first
		// loaded.
		
		
		//console.log( "**** Trans Setup completed ****. BASE cover path: " + this._baseImgDomElObj.attributes.src.nodeValue );
	}
	
	
	/*--------------------------- Method ---------------------------
	/ Do a single step of the image transition.
	/ -------------------------------------------------------------*/
	Blender.prototype._transStep = function( me ) {
		
		me._currTransStep++;
		
		// Do the actual Image transition stuff here (a single step)
		if ( me._currTransStep <= me._totalTransSteps ) {
			
			//console.log( " --> Trans Step <-- Nr:" + me._currTransStep );
			
			var opacityPerStep = 0;
			if ( this._totalTransSteps > 0 ) { 
				opacityPerStep = 100 / this._totalTransSteps;
			}
			var newOpacity = opacityPerStep * me._currTransStep;
			me._setOpacity( me._tmpTOPCoverEl, newOpacity );

			var self = me;
			me._transTimerID = window.setTimeout( function() {
				self._transStep( self );
			}, me._targetMilliS );
		} else {
			me._cleanupTransition();
		}
		
		
		
	};
	
	/*--------------------------- Method ---------------------------
	/ Clean up the Transition at its end. 
	/ Move the displayed image to the base image and hide the cover.
	/ -------------------------------------------------------------*/
	Blender.prototype._cleanupTransition = function() {
	
		//console.log( " **> Trans Cleanup <** " );
		
		//console.log( " TOTAL Trans time taken: " + ( Date.now() - this.tmpStartTime ) );		// FF only -- IE yakks.
		
		// 0 is transparent, 1 is opaque
		this._setOpacity( this._tmpTOPCoverEl, 0 );
		clearTimeout( this._transTimerID );
		
		//var innerImg = '<img src="' + this._transToImagePath + '" alt=""/>';
		this._tmpBASECoverEl.innerHTML = this._tmpTOPCoverEl.innerHTML;
		
		//console.log( " -> Trans completed. BASE cover path: " + this._tmpTOPCoverEl.innerHTML );
	}
	
	
	/*--------------------------- Method ---------------------------
	/ Do a single step of the image transition.
	/ -------------------------------------------------------------*/
	Blender.prototype._setOpacity = function( pEl, pOpacity ) {
	
		if ( !document.getElementById ) { return; }
		num = parseFloat( pOpacity );
		var el = pEl;
		
		if ( !el || !el.style || isNaN(num) || ( num < 0 ) ) { return; }
		while( num > 1 ) { num = num / 100; }
		
		//if ( num == 1.0 ) { num = 0.99; }
		//if ( num === 0 ) { num = 0.01; }
		//console.log( "Op: " + num );
		
		el.style.MozOpacity = num;										// Gecko browsers including Netscape 6+ and Firefox
		el.style.KhtmlOpacity = num;									// Safari 1.1+, I think
		el.style.opacity = num;											// Netscape 7.2+, Firefox, Opera 9
		if (( el.style.filter != null )&&( el.style.filter != 'undefined' ) ) {	// IE5.5+/Win
			el.style.zoom = "1";
			el.style.filter = "alpha(opacity=" + ( num * 100 ) + ")";
		}
		
	};

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
//*************************************************************************************************************************************
/*
	SimpleSlideController
	The Controller is responsible for setting up the SlideShow object
	so that it runs properly in normal circumstances, as well as being
	in charge of the SS's model (Admin Panel), so that the user's inputs
	are handled and saved properly when the model's DWA EditBox is saved
	during a Publish event.
	
	This class is specific to the SimpleSlideShow model.
	
	Controller is a Toolbox only Class and as such is allowed to use YUI
	elements, whereas the Simple Slide Show and the Transition Plugins need
	to work in IE and older browsers, so need to hand code those the hard way!
	
*/

/*----------------------- Constructor --------------------------
/ 
/ -------------------------------------------------------------*/
function SimpleSlideController( pModelID ) {
	
	// Properties.
	this._modelBoxID = pModelID;
	this._slideShowBaseDomImgID = this._modelBoxID.replace( /-model/, "" );
	this._imgList = [];
	this._slideShowObj = null;
	
	this.areAdminControlsInited = false;
	
	// Add an init() method to the model box, so we can set up the 
	// model properly when it is displayed by the Toolbox.
	this._modelBoxObj = document.getElementById( this._modelBoxID );
	//alert(modelBoxObj);
	
	// Create and register the custom event that the Toolbox is calling
	// when the user clicks on the *Admin...* button for this component.
	window.evAddonInit = new YAHOO.util.CustomEvent( "addonInit", this); 
	window.evAddonInit.subscribe( this.initAddon, this );
	
	this._runSlideShow();		// inits the Slide Show object.
	
	
} // end constructor
	
	/*--------------------------- Method ---------------------------
	/ Need to trap the 'Publish' event from the Toolbox and make sure that
	/ there are no artifacts from the slide show published. 
	Example: if the user changes the main SS image and then hits Publish,
	they will often end up with the SS temp cover image and cruft being 
	saved along with the proper SS component in the SS's DWA EditBox.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._onPublishSlideShow = function() {
		
		
	};
		
		
	/*--------------------------- Method ---------------------------
	/ Parses the SlideShow information that is stored in the 'model' box
	/ and starts up the SlideShow.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._runSlideShow = function() {
		
		// Get the DOM Image object that acts as the Slide Show's Base Image.
		// The Slide Show Base Image DOM object is the 'first' img tag located
		// within the DWA Slide Show Component.
		var baseImgEl = null;
		var dwaSSDomObj = document.getElementById( this._slideShowBaseDomImgID );
		var domChildren = dwaSSDomObj.childNodes;
		var len = domChildren.length;
		for ( var x = 0; x < len; x++ ){
			if ( domChildren[x].nodeName.toLowerCase() === 'img' ) {
				baseImgEl = domChildren[x];
				break;
			}
		}
		if ( baseImgEl === null ) { 
			throw "Not able to find a Base Image for this Slide Show Component. Must have an 'img' tag to show slides in...";
			return; 
		}
		
		
		// Read in the images used in this slide show.
		this._buildImagesList();
		
		
		// Get Slide Interval & Transition Interval.
		var adminLoopObj = document.getElementById( "loop" );
		var loopFlag = false;
		if ( adminLoopObj.value.toLowerCase() == 'on' ) {
			loopFlag = true;
		}
		var adminSlideTimeObj = document.getElementById( "slideInterval" );
		var slideInterval = parseFloat( adminSlideTimeObj.value );
		//alert( "SS Init -> slideInterval: " + slideInterval );
		var adminTransTimeObj = document.getElementById( "transitionInterval" );
		var transInterval = parseFloat( adminTransTimeObj.value );
		//alert( "SS Init -> transInterval: " + transInterval );
		
		
		// Build the SS config.
        var ssConfig = {
        	baseImgEl:			baseImgEl,
            imageList:			this._imgList,
            loop:				loopFlag,
            interval:			slideInterval*1000,				// 2 seconds
            transitionInterval:	transInterval*1000				// 1 second
        };
		
		// Start the slide show.
		this._slideShowObj = new SimpleSlideShow( ssConfig );
		this._slideShowObj.start();
		
	};


	/*--------------------------- Method ---------------------------
	/ Called when the Slide Show 'Stops'.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._playAgain = function( ev, args ) {
		//console.log("Set PlayPause button to: " + pPlayPause );
		var playPauseBtn = document.getElementById( 'playPauseBtn' );
		playPauseBtn.value = 'Play';
		// Rewind the Slide Show.
		this._slideShowObj.rewind();
	};
	
	/*--------------------------- Method ---------------------------
	/ Handle the custom event from the Toolbox when the user clicks on the Admin... button 
	// Need to change each element's html so that the chosen values are stored
	// properly on Publish.
	// Also need to send the value changes to the slide show, so the user
	// can immediately see their changes.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype.initAddon = function( ev, args ) {
		//alert( "Init() called on model box!" );
		
		Dom = YAHOO.util.Dom;
		Ev = YAHOO.util.Event;
		
		/**
			Set up a listener that marks the Model DWAEditBox as 'dirty' every time
			the user changes something in the Edit Box.
		*/
		var toolboxCompEditorObj = args[0];
		Ev.purgeElement( this._modelBoxObj );					// remove any previous listeners.
		Ev.addListener( this._modelBoxObj, "change", function( anEv, me ){
			// Let the Toolbox know that something's been changed in the SShow's Admin box.
			toolboxCompEditorObj._toolboxRef.currentDWAEditBox.setIsModified( true );
			// Try and restart the slide show?
			//me._runSlideShow();
		}, this );
		
		
		
		
		// Loop Checkbox Control
		var loopControl = document.getElementById( 'loop' );
		// Update Control so it shows correct underlying html value (often doesn't on reload).
		//console.log("Loop Control: " + loopControl.checked );
		// Set Event Listeners on Control.
		Ev.purgeElement( loopControl );					// remove any previous listeners.
		// Sets the html value of the checkbox (generic for any checkbox)
		Ev.addListener( loopControl, "change", this._setChkbox, this );
		// closure that passes the changed checkbox's value to the Slide Show. Specific to this component.
		Ev.addListener( loopControl, "change", function( anEv, me ) { 
			me._slideShowObj.setLoop( loopControl.checked );
		}, this );
		
		// Slide Display Time drop menu
		var slideTimeControl = document.getElementById( 'slideInterval' );
		// Update Control so it shows correct underlying html value (often doesn't on reload).
		var startTimeVal = slideTimeControl.options[slideTimeControl.selectedIndex].value;
		this._slideShowObj.setInterval( parseFloat( startTimeVal ) * 1000 );
		//console.log("Initial Time val: " + startTimeVal );
		// Set Event Listeners on Control.
		Ev.purgeElement( slideTimeControl ); 						// remove any previous listeners.
		// Sets the html value of the Drop Menu (generic for any Select)
		Ev.addListener( slideTimeControl, "change", this._setSelectOption, this );
		// closure that passes the changed Select Box value to the Slide Show. Specific to this component.
		Ev.addListener( slideTimeControl, "change", function( anEv, me ) { 
			var millisecs = parseFloat( this.value ) * 1000;
			me._slideShowObj.setInterval( parseFloat( millisecs ) );
		}, this );
		
		// Slide Transition Time drop menu
		var slideTransitionIntervalControl = document.getElementById( 'transitionInterval' );
		// Update Control so it shows correct underlying html value (often doesn't on reload).
		var setTransitionTime = slideTransitionIntervalControl.options[slideTransitionIntervalControl.selectedIndex].value;
		this._slideShowObj.setTransitionTime( parseFloat( setTransitionTime ) * 1000 );
		//console.log("Initial Time val: " + startTimeVal );
		// Set Event Listeners on Control.
		Ev.purgeElement( slideTransitionIntervalControl ); 						// remove any previous listeners.
		// Sets the html value of the Drop Menu (generic for any Select)
		Ev.addListener( slideTransitionIntervalControl, "change", this._setSelectOption, this );
		// closure that passes the changed Select Box value to the Slide Show. Specific to this component.
		Ev.addListener( slideTransitionIntervalControl, "change", function( anEv, me ) { 
			var millisecs = parseFloat( this.value ) * 1000;
			me._slideShowObj.setTransitionTime( parseFloat( millisecs ) );
		}, this );
		
		
		// Pause/Play button.
		var playPauseBtn = document.getElementById( 'playPauseBtn' );
		Ev.purgeElement( playPauseBtn ); 						// remove any previous listeners.
		Ev.addListener( playPauseBtn, "click", function( ev, me ) {
			console.log(this.value);
			if ( this.value.toLowerCase() == "pause" ) {
				this.value = "Play";
				me._slideShowObj.pause();
			} else {
				this.value = "Pause";
				// If the SS is playing, then pause it, otherwise Start it again.
				if ( me._slideShowObj.isPaused() === true && me._slideShowObj.isLastSlide() === false ) {
					me._slideShowObj.play();
					console.log(" *** Played ***" );
				} else {
					me._slideShowObj.rewind();
					me._slideShowObj.start();
					console.log(" *** Started ***" );
				}
			}
		}, this );
		
		// Rewind button.
		var rewindBtn = document.getElementById( 'rewindBtn' );
		Ev.purgeElement( rewindBtn ); 						// remove any previous listeners.
		Ev.addListener( rewindBtn, "click", function( ev, me ) {
			console.log(this.value);
			me._slideShowObj.rewind();
		}, this );
		
		
		// Only the Addon Controller can use YUI events, so they need to 
		// be set up here and injected into the Slide Show. (This is to
		// keep the Slide Show 'old browser proof')
		// Slide Show Events.
		this._slideShowObj.evPlay = new YAHOO.util.CustomEvent( "play", this._slideShowObj ); 
		this._slideShowObj.evPause = new YAHOO.util.CustomEvent( "pause", this._slideShowObj ); 
		this._slideShowObj.evStop = new YAHOO.util.CustomEvent( "stop", this._slideShowObj ); 
		
		// Listen for Slide Show Events.
		this._slideShowObj.evStop.subscribe( this._playAgain, this );
		//this._slideShowObj.evStop.subscribe( function(){ 
		//	alert("Got the Stop Ev.");
		//}, this );
		
	};
	
	/*--------------------------- Method ---------------------------
	/ Force updates to the browser DOM for this Checkbox, so when the
	/ DWA Edit Box that contains it is saved, it remembers the correct value.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._setChkbox = function( ev, me ) {
		
		if ( this.checked ) {
			//alert("The checkbox has been checked. Adding 'Checked' attribute...");
			this.setAttribute( 'checked', 'checked' );
			this.setAttribute( 'value', 'on' );
			return true;
		} else {
			//alert("The checkbox has been Un-checked. Killing 'Checked' attribute...");
			// Unchecked, remove the "checked='checked'" attribute from the checkbox.
			this.removeAttribute( 'checked' );
			this.setAttribute( 'value', 'off' );
			return false;
		}
		
	};
	
	
	/*--------------------------- Method ---------------------------
	/ Force updates to the browser DOM for this Select Box's Option element, so when the
	/ DWA Edit Box that contains it is saved, it remembers the correct value.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._setSelectOption = function( ev, me ) {
		
		//alert("Select changed. Value: " + this.value );
		
		var userSelVal = this.value;
		
		// clear the previous selected='selected' attribute on the options.
		var len = this.options.length;
		for ( var y = 0; y < len; y++ ){
			this.options[y].removeAttribute( 'selected' );
		}
		
		// loop through each of the option values and set 
		// seletected on the first match.
		for ( var x = 0; x < len; x++ ){
			if ( this.options[x].value === userSelVal ) {
				this.options[x].setAttribute( 'selected', 'selected' );
			}
		}
		
	};
	
	/*--------------------------- Method ---------------------------
	/ Get the image paths used by the slide show.
	/ -------------------------------------------------------------*/
	SimpleSlideController.prototype._buildImagesList = function() {
		
		Dom = YAHOO.util.Dom;
		
		// Grab all of the SS Images in the model. They use the css class 'dwa-SlideShowImage'
		var slidesArray = Dom.getElementsByClassName( 'dwa-SlideShowImage', 'div', this._modelBoxID )
		// Pull out each SS Image's path and add to the ss list.
		var len = slidesArray.length;
		for ( var x = 0; x < len; x++ ){
			// Loop through this element's children and grab the first image found (slide)
			var children = slidesArray[x].childNodes;
			var childrenLen = children.length;
			for ( var y = 0; y < childrenLen; y++ ){
				var node = children[y].nodeName;
				if ( node.toLowerCase() == "img" ) {
					// Add this img's path to the list.
					var path = children[y].attributes.src.nodeValue;
					this._imgList.push( path );
				}
			}
		}
	};
	
	
	
	