/****************************************************************
 ****************************************************************
 **
 ** Prototype Additions
 **
 ** Copyright (c) 2004 Nameless-UK
 **
 ****************************************************************
 ****************************************************************
 */

/****************************************************************
 * Math Prototypes
 ****************************************************************
 */
// Pre-calculate PI divided by two.
Math.PIby2 = Math.PI / 2;

// Simple harmonic motion
Math.SHM = function(iTimeIndex, iStart, iDelta, iDuration) {
	return( iStart + (iDelta * Math.sin( iTimeIndex / iDuration * Math.PIby2 ) ) );
}

// Return b bounded by a and c.
Math.bound = function(a, b, c) {
	return(Math.min(Math.max(a, b), c));
}

// Return whether b is with a and c.
Math.within = function(a, b, c) {
	return(b >= a && b <= c);
}


// Return the square of a number
Math.sqr = function(a) {
	return(Math.pow(a, 2));
}

/****************************************************************
 * Array Prototypes
 ****************************************************************
 */
// Add the ability to push something onto the end of an array
if(!Array.prototype.push) {
	Array.prototype.push = function( mNewEntry ) {
		this[ this.length++ ] = mNewEntry;
	}
}

// Add the ability to pop something off the end of an array
if(!Array.prototype.pop) {
	Array.prototype.pop = function() {
		var mReturnValue = false;
		if(this.length) {
			mReturnValue = this[ this.length - 1 ];
			this.length--;
		}
		return(mReturnValue);
	}
}

if(!Array.prototype.search) {
	Array.prototype.search = function(sTerm) {
		var iIndex = this.length;
		while(iIndex--) {
			if(this[ iIndex ] == sTerm) return(true);
		}
		return(false);
	}
}

if(!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(sTerm) {
		var iIndex = this.length;
		while(iIndex--) {
			if(this[ iIndex ] == sTerm) return(iIndex);
		}
		return(-1);
	}
}


/****************************************************************
 * Netscape Event Handler Object
 ****************************************************************
 */
function MungedNSEvent(oNSEvent) {

	// Which box model are we using :-/
	this.bIsNS = true;
	this.bIsIE = false;

	// Create a reference to the event
	this.oActualEvent = oNSEvent;

	// Button and event-type
	this.iButton    = oNSEvent.which;
	this.sEventType = oNSEvent.type;

	// Targets
	this.oElement   = oNSEvent.target;

	// Relative to the screen
	this.iScreenX   = oNSEvent.screenX;
	this.iScreenY   = oNSEvent.screenY;

	// Relative to the document
	// Relative to the window / frame
	this.iDocumentX = this.iWindowX = oNSEvent.pageX;
	this.iDocumentY = this.iWindowY = oNSEvent.pageY;

	// Relative to the layer / element
	this.iLayerX    = oNSEvent.layerX;
	this.iLayerY    = oNSEvent.layerY;

	// Scrollbar offsets
	this.iScrollX   = document.documentElement.scrollLeft;
	this.iScrollY   = document.documentElement.scrollTop;
}

// The function to stop event propagation
MungedNSEvent.prototype.stopPropagation = function() {
	this.oActualEvent.stopPropagation();
}

// The function to continue event propagation
MungedNSEvent.prototype.resumePropagation = function() {
	self.routeEvent(this.oActualEvent);
}

// The function to stop default action
MungedNSEvent.prototype.preventDefault = function() {
	this.oActualEvent.preventDefault();
}

MungedNSEvent.prototype.disableSelections = function() {}
MungedNSEvent.prototype.enableSelections = function() {}


/****************************************************************
 * IE Event Handler Object
 ****************************************************************
 */
function MungedIEEvent() {
	var oIEEvent = window.event;

	// Which box model are we using :-/
	this.bIsNS = false;
	this.bIsIE = true;

	// Create a reference to the event
	this.oActualEvent = window.event;

	// Button and event-type
	this.iButton    = oIEEvent.button;
	this.sEventType = oIEEvent.type;

	// Targets
	this.oElement   = oIEEvent.srcElement;

	// Relative to the screen
	this.iScreenX   = oIEEvent.screenX;
	this.iScreenY   = oIEEvent.screenY;

	// Relative to the window / frame
	this.iWindowX   = oIEEvent.clientX;
	this.iWindowY   = oIEEvent.clientY;

	// Relative to the layer / element
	this.iLayerX    = oIEEvent.offsetX;
	this.iLayerY    = oIEEvent.offsetY;

	// Scrollbar offsets
	this.iScrollX   = document.documentElement.scrollLeft || document.body.scrollLeft;
	this.iScrollY   = document.documentElement.scrollTop  || document.body.scrollTop;

	// Relative to the document
	this.iDocumentX = this.iWindowX + this.iScrollX;
	this.iDocumentY = this.iWindowY + this.iScrollY;

	// Take the image's offset into account
	if(oIEEvent.srcElement.tagName == 'IMG') {
		this.iDocumentX -= oIEEvent.srcElement.offsetLeft;
		this.iDocumentY -= oIEEvent.srcElement.offsetTop;
	}
}

// The function to stop event propagation
MungedIEEvent.prototype.stopPropagation = function() {
	this.oActualEvent.cancelBubble = true;
}

// The function to continue event propagation
MungedIEEvent.prototype.resumePropagation = function() {
	this.oActualEvent.cancelBubble = false;
}

// The function to stop default action
MungedIEEvent.prototype.preventDefault = function() {
	this.oActualEvent.returnValue = false;
}

MungedIEEvent.prototype.disableSelections = function() {
	if(document.selection && document.selection.empty) {
		document.selection.empty();
	}
	document.documentElement.onselectstart = document.body.onselectstart = function() {
		window.event.returnValue = false;
	}
}

MungedIEEvent.prototype.enableSelections = function() {
	document.documentElement.onselectstart = document.body.onselectstart = null;
}

/*
 * String.format() implementation. First argument must be the format string, the 
 * rest are the replacement parametres. Tokens for replacement are {n} where n
 * is the index of the zero-based replacement parameters.
 * 
 * Returns the formatted string.
 */
String.format = function()
{
	var formatString = arguments[0];

	for (var i = 1, len = arguments.length; i < len; i++)
	{
		formatString = formatString.replace('\{' + (i - 1) + '\}', arguments[i].toString());
	}

	return formatString;
}

