/* -------------------------------------------------------------------- */
/* -------- Core Javascript Library ----------------------------------- */
/* -------------------------------------------------------------------- */
/* -------- Heikki Gruner ---- 10 September, 2008 --------------------- */
/* -------------------------------------------------------------------- */

function GetAbsolutePosition( elementReference ) {
	if( elementReference == undefined || elementReference == null ) return { x : 0, y : 0 };
	var offsetX = elementReference.offsetLeft;
	var offsetY = elementReference.offsetTop;
	var offsetHandle = elementReference.offsetParent;
	
	while( offsetHandle ) {
		offsetX += offsetHandle.offsetLeft;
		offsetY += offsetHandle.offsetTop;
		offsetHandle = offsetHandle.offsetParent;
	}
	
	return { x : offsetX, y : offsetY };
}
function GetBoundingBox( elementReference ) {
	var position = GetAbsolutePosition( elementReference );
	return { left : position.x, right : position.x + elementReference.offsetWidth, top : position.y, bottom : position.y + elementReference.offsetHeight };
}

function GetMousePosition( mouseMoveEvent ) {
	if( ! mouseMoveEvent ) {
		return { x : window.event.clientX + document.documentElement.scrollLeft, y : window.event.clientY + document.documentElement.scrollTop }; 
	} else {
		return { x : mouseMoveEvent.pageX, y : mouseMoveEvent.pageY };
	}
}


function AppendClassName( reference, className ) { reference.className = reference.className + " " + className; }
function RemoveClassName( reference, className ) {
	var classElements = reference.className.split( " " );
	var targetElements = new Array();
	for( index in classElements ) {
		if( classElements[ index ] != className ) {
			targetElements.push( classElements[ index ] );
		}
	}
	reference.className = targetElements.join( " " );
}
function HasClassName( reference, className ) {
	var classElements = reference.className.split( " " );
	for( index in classElements )
		if( classElements[ index ] == className ) return true;
	return false;
}


function GetTransparency( reference ) {
	if( reference.filters ) {
		var filter = reference.style.filter;
		if( filter.search( "opacity" ) < 0 ) return 1;
		var matches = filter.match( "opacity[ ]*=[ ]*[^ )]+" );
		if( matches.length < 1 ) return 1;
		var matchParts = matches[ 0 ].split( "=" );
		var matchParsed = new Number( matchParts[ 1 ] );
		return matchParsed.valueOf() / 100;
	} else {
		return ( isNaN( parseFloat( reference.style.opacity ) ) ? 1.0 : parseFloat( reference.style.opacity ) );
	}
}
function SetTransparency( reference, value ) {
	reference.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + value * 100 + ")";
	reference.style.opacity = value;
	//reference.style.filter = "alpha( opacity=" + value * 100 + ")";
}


function ValueExists( value, collection ) {
	for( var index in collection ) if( collection[ index ] == value ) return true; return false;
}

function RoundFloat( value, places ) {
	value = parseFloat( value );
	if( isNaN( value ) ) throw "Invalid argument. Must be float.";
	return Math.round( value * Math.pow( 10.0, places ) ) / Math.pow( 10.0, places );
}

function GetMethodReference( instance, methodName ) {
	return ( function() { return instance[ methodName ](); } );
}




function FadeElement( elementReference ) {
	this.element = elementReference;
	this.alpha = GetTransparency( this.element );
	this.visible = ( this.alpha > 0 );
	this.display = ( this.element.style.display == "none" ? "" : this.element.style.display );
	this.timer = null;
	this.shift = 0;
	this.increment = 0;
	
	
	this.FadeTo = function( time, target ) {
		// If a fade operation is already in effect, cancel it.
		if( this.timer !== null ) {
			window.clearInterval( this.timer );
			this.timer = null;
		}
		
		// Compute the shift required to achieve the target fade level.
		this.shift = target - this.alpha;
		
		// Compute the shift rate (amount to shift per second).
		this.increment = this.shift / time;
		
		// Initiate the 20 millisecond timer.
		this.timer = window.setInterval( GetMethodReference( this, "FadeFrame" ), 20 );
	}
	
	
	this.FadeFrame = function() {
		// Compute the amount of change in this frame. (20 millisecond interval assumed.)
		var frame = this.increment * 0.02;
		
		// Check to see if we are in striking distance of the target.
		if( Math.abs( frame ) > Math.abs( this.shift ) ) {
			this.alpha = parseFloat( this.alpha ) + this.shift;
			window.clearInterval( this.timer );
			this.timer = null;
			this.shift = 0;
			this.increment = 0;
		} else {
			this.shift -= frame;
			this.alpha = parseFloat( this.alpha ) + frame;
		}
		
		// Set the transparency to the approriate value for this frame.
		SetTransparency( this.element, this.alpha );
	}
}



/* ----------------------------------------------- */
/* ---- Collection --------- Class Definition ---- */
/* ----------------------------------------------- */
function Collection( owner ) {
	// Properties
	this.owner = owner;
	this.list = new Array();
	
	// Methods
	this.Count = function() { return this.list.length; };
	this.Add = function( item ) {
		this.list.push( item );
		if( this.list.length == 1 && this.onemptystatechange != null ) this.onemptystatechange( ( this.owner != null ? this.owner : this ), false );
	}
	
	this.Insert = function( index, item ) {
		if( index < 0 || index >= this.list.length ) throw "Index out of range.";
		this.list.splice( index, 0, item );
		if( this.list.length == 1 && this.onemptystatechange != null ) this.onemptystatechange( ( this.owner != null ? this.owner : this ), false );
	}
	
	this.Remove = function( item ) {
		for( index in this.list ) {
			if( this.list[ index ] == item ) {
				this.list.splice( index, 1 );
				if( this.list.length == 0 && this.onemptystatechange != null ) this.onemptystatechange( ( this.owner != null ? this.owner : this ), true );
				return;
			}
		}
	}
	
	this.RemoveAt = function( index ) {
		if( index < 0 || index >= this.list.length ) throw "Index out of range.";
		this.list.splice( index, 1 );
		if( this.list.length == 0 && this.onemptystatechange != null ) this.onemptystatechange( ( this.owner != null ? this.owner : this ), true );
	}
	
	// Events
	this.onemptystatechange = null;
}
