// Fader.js
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// History Log
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// 2009-03-14 : Vincent (http://www.vlamoureux.com/)
//				Original scripting
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Public properties
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
//    speed:Number     [default=50]   : Animation iteration in milliseconds
//    increment:Number [default=.1]   : Opacity increment for each iteration (number from 0 to 1)
//    maxOpacity       [default=1]    : Final opacity of fade in (number from 0 to 1)
//    minOpacity       [default=0]    : Final opacity of fade out (number from 0 to 1)
//    startOpacity     [default=0]    : Starting opacity (number from 0 to 1)
//    listener         [default=null] : Listener function for dispatched Fader events



// Fader object creation
function Fader(element, options) {
	
	// Public properties
	this.options = options ? options : new Object();
	
	// Private properties
	this.element = element;
	this.fadeInterval = null;
	this.fadeType = null;
	this.currentOpacity = null;
	
	
	// Public methods
	this.fadeIn        = Fader_FadeIn;
	this.fadeOut       = Fader_FadeOut;
	this.stopFade      = Fader_StopFade;
	
	// Private methods
	this.startFade     = Fader_StartFade;
	this.fade          = Fader_Fade;
	this.setOpacity    = Fader_SetOpacity;
	this.stopInterval  = Fader_StopInterval;
	this.setOptions    = Fader_SetOptions;
	this.dispatchEvent = Fader_DispatchEvent;
	
	
	// Checks if the elements exists to continue
	if (this.element) {
		this.setOptions();
		this.setOpacity(this.options.startOpacity);
	} else {
		delete this;
		alert("Element '" + element + "' could not be found in DOM tree.");
	}
}



// Starts fade in
function Fader_FadeIn() {
	this.startFade("FADE_IN");
}



// Starts fade out
function Fader_FadeOut() {
	this.startFade("FADE_OUT");
}



// Stops fading
function Fader_StopFade() {
	if ( this.fadeType )
		this.dispatchEvent(this.fadeType + "_STOP");
	this.stopInterval();
}



// Starts element's fading in and out (called by 'fadeIn' and 'fadeOut' methods)
function Fader_StartFade(fadeType) {
	if ( fadeType != this.fadeType ) {
		this.fadeType ? this.dispatchEvent(fadeType + "_CHANGE") : this.dispatchEvent(fadeType + "_START");
		this.stopInterval();
		this.fadeType = fadeType;
		
		if ( this.fadeType == "FADE_IN" && this.currentOpacity == this.options.maxOpacity ) {
			this.dispatchEvent(fadeType + "_COMPLETE");
			this.fadeType = null;
		} else if ( this.fadeType == "FADE_OUT" && this.currentOpacity == this.options.minOpacity ) {
			this.dispatchEvent(fadeType + "_COMPLETE");
			this.fadeType = null;
		} else {
			var refObject = this;
			this.fadeInterval = setInterval(function() { refObject.fade(); }, this.options.speed);
		}
	}
}



// Fades the element (animation)
function Fader_Fade() {
	var nextOpacity;
	var stopFade;
	
	switch (this.fadeType) {
		case "FADE_IN":
			if ( this.currentOpacity + this.options.increment < this.options.maxOpacity)
				nextOpacity = Math.round((this.currentOpacity + this.options.increment) * 100) / 100;
			else {
				nextOpacity = this.options.maxOpacity;
				stopFade = true;
			}
			break;
			
		case "FADE_OUT":
			if ( this.currentOpacity - this.options.increment > this.options.minOpacity)
				nextOpacity = Math.round((this.currentOpacity - this.options.increment) * 100) / 100;
			else {
				nextOpacity = this.options.minOpacity;
				stopFade = true;	
			}
			break;
			
		default:
			nextOpacity = this.currentOpacity;
			stopFade = true;
			break;
	}
	
	this.setOpacity(nextOpacity);
		
	if ( stopFade ) {
		this.dispatchEvent(this.fadeType + "_COMPLETE");
		this.stopInterval();
	}
}



// Sets the element's opacity
function Fader_SetOpacity(opacity) {
	this.element.style.opacity = String(opacity);
	this.element.style.filter = "alpha(opacity=" + String(opacity * 100) + ")";
	
	this.currentOpacity = opacity;
}



// Clears Fader interval
function Fader_StopInterval() {
	if ( this.fadeInterval ) {
		clearInterval(this.fadeInterval);
		this.fadeInterval = null;
		this.fadeType = null;
	}
}



// Sets Fader options and default options
function Fader_SetOptions() {
	var defaultOptions = new Object();
		defaultOptions.speed        = 50;
		defaultOptions.increment    = .1;
		defaultOptions.maxOpacity   = 1;
		defaultOptions.minOpacity   = 0;
		var opacity;
		if ( typeof(this.element.style.opacity) != "undefined" )
			defaultOptions.startOpacity = this.element.style.opacity ? parseFloat(this.element.style.opacity) : minOpacity;
		else {
			var filterString = this.element.style.filter;
				filterString
			defaultOptions.startOpacity = filterString ? parseFloat(filterString.substring(filterString.indexOf("pacity=") + 7)) : minOpacity;
		}
		
	
	for ( var prop in defaultOptions ) {
		if ( this.options[prop] == null )
			this.options[prop] = defaultOptions[prop];
	}
}



// Dispatches a Fader event to the listener function property
function Fader_DispatchEvent(eventType) {
	if (this.options.listener)
		this.options.listener(eventType, this.element);
}

