/*
 *
 *           _________________
 *          /                /\     klof  |  innovative web technologies
 *         /  /\/|          /  \
 *        /   \  |         /   /    most rights reserved 2002-2004, klof
 *       /    /__|        /   /     certainly not free for commercial use
 *      /        /\/|    /   /
 *     /         \  |   /   /         script       :  dynobject.js
 *    /          /__|  /   /          date         :  November 14th 2002 - March 17th 2004
 *   /                /   /           author       :  Rogier Spieker
 *  /________________/   /            purpose      :  Provide easy construction of DHTML objects
 *  \                \  /             dependencies :  /
 *   \________________\/              history      :  03.10.2003 - Added a workaround for doctype
 *                                                                 dependency bug in Safari
 *                                                    11.02.2004 - Extracted the method from the
 *                                                                 constructor function and prototype
 *                                                                 the method into the dynamicElement
 *                                                    17.03.2004 - Removed the prototyped methods and
 *                                                                 made them inline again, this due to
 *                                                                 strange problems with methods being
 *                                                                 unrecognised.
 *                                                    03.11.2004 - Implemented a workaround for Opera
 *                                                                 (7.1+) which is confused about doctype
 *                                                                 and standards compliat mode (add "px"
 *                                                                 to values)
 *
 *
 */

/*
 *  Function : dynamicElement
 *  Purpose  : Construct an object which enables easy access to dynamic elements
 *  Synopsis : object dynamicElement( string layer [, string parentlayer ] );
 */
function dynamicElement( sElement, sContainer )
{
	// If we are coding properly and use a doctype, we are required to specify the units
	// In case we are dealing with Safari on OSX 10.2, we have the unique situation in which the type of the doctype is object but the value is null
	// we use this as the base for our workaround which adds the 'px' unit to the amount in case of resizing an element.
	this.docTypePosAppend  = document.doctype && typeof window.opera != "object" ? "px" : 0;
	this.docTypeSizeAppend = ( document.doctype == null && typeof document.doctype == "object" ) ? "px" : this.docTypePosAppend;

	// Assign properties
	this._object = document.all ? document.all[ sElement ] : document.getElementById ? document.getElementById( sElement ) : document.layers ? eval( ( sContainer != "" && sContainer != null ? "document." + sContainer + "." : "" ) + "document." + sElement ) : 0;
	this._style  = this._object.style || this._object;
	this._refer  = this._style.document || document;
	this._x      = this._left = parseInt( this._style.left ) || this._style.pixelLeft || this._object.offsetLeft || 0;
	this._y      = this._top  = parseInt( this._style.top )  || this._style.pixelTop  || this._object.offsetTop  || 0;
	this._width  = this._object.offsetWidth || this._refer.width || this._style.pixelWidth ||this._style.clip.width || 0;
	this._height = this._object.offsetHeight ||this._refer.height || this._style.pixelHeight || this._style.clip.height || 0;
	this._right  = this._left + this._width;
	this._bottom = this._top + this._height;

	// Assign methods

	/*
	 *  Method   : move
	 *  Purpose  : Move an object to a specified location
	 *  Synopsis : void object.move( int x, int y )
	 */
	this.move = function( x, y )
	{
		if ( typeof x == "number" && !isNaN( x ) )
			this._x = parseInt( this._style.posLeft = this._style.left = x + this.docTypePosAppend );
		if ( typeof y == "number" && !isNaN( y ) )
			this._y = parseInt( this._style.posTop  = this._style.top  = y + this.docTypePosAppend );
		this._right  = this._left + this._width;
		this._bottom = this._top + this._height;
	}


	/*
	 *  Method   : resize
	 *  Purpose  : Set the dimensions of an object
	 *  Synopsis : void object.resize( int width, int height )
	 *  Note     : Resizing has to be supported by the browser in order to work.
	 */
	this.resize = function( nWidth, nHeight )
	{
		this._width  = parseInt( this._style.width  = nWidth + this.docTypeSizeAppend );
		this._height = parseInt( this._style.height = nHeight + this.docTypeSizeAppend );
		this._right  = this._left + this._width;
		this._bottom = this._top + this._height;
	}

	/*
	 *  Method   : show
	 *  Purpose  : make an object visible
	 *  Synopsis : void object.show()
	 */
	this.show = function()
	{
		this._style.visibility = "visible";
		this._visible          = true;
	}

	/*
	 *  Method   : hide
	 *  Purpose  : make an object invisible
	 *  Synopsis : void object.hide()
	 */
	this.hide = function()
	{
		this._style.visibility = "hidden";
		this._visible          = false;
	}

	/*
	 *  Method   : clip
	 *  Purpose  : Clip a specific visible part (rectangle) from an object
	 *  Synopsis : void object.clip( int top, int right, int bottom, int left )
	 *  Note     : Clipping has to be supported by the browser in order to work.
	 */
	this.clip = function( nTop, nRight, nBottom, nLeft )
	{
		if ( this._style.clip.width )
		{
			this._width  = this._style.clip.width  = ( nRight - nLeft );
			this._height = this._style.clip.height = ( nBottom - nTop );
		}
		else
		{
			this._style.clip = "rect( " + nTop + "px " + nRight + "px " + nBottom + "px " + nLeft + "px )";
			this._width  = ( nRight - nLeft );
			this._height = ( nBottom - nTop );
		}
	}

	/*
	 *  Method   : setMethod
	 *  Purpose  : Assign a method to an object
	 *  Synopsis : void object.setMethod( string function )
	 */
	this.setMethod = function( sFunctionName, oFunction )
	{
		this[ sFunctionName ] = typeof oFunction != "undefined" ? oFunction : sFunctionName;
	}

	/*
	 *  Method   : clearMethod
	 *  Purpose  : Remove a method from an object
	 *  Synopsis : void object.clearMethod( string function )
	 */
	this.clearMethod = function( sFunctionName )
	{
		this[ sFunctionName ] = null;
	}

	/*
	 *  Method   : setHandler
	 *  Purpose  : Bind an event handler to an object specific event
	 *  Synopsis : void object.setHandler( string event, string function )
	 */
	this.setHandler = function( sEvent, sMethod )
	{
		if ( this._object.captureEvents )
			this._object.captureEvents( eval( "Event." + sEvent.toUpperCase() ) );
		eval( "this._object.on" + sEvent.toLowerCase() + "= new Function( \"evt\", \"return " + this._self + "." + sMethod +"( evt );\" )" );
	}

	/*
	 *  Method   : clearHandler
	 *  Purpose  : Remove an eventhandler from an object
	 *  Synopsis : void object.clearMethod( string event )
	 */
	this.clearHandler = function( sEvent )
	{
		if ( this._object.releaseEvents )
			this._object.releaseEvents( eval( "Event." + sEvent.toUpperCase() ) );
		eval( "this._object.on" + sEvent.toLowerCase() + "=null" );
	}

	// Return the proper reference to the dynamicElement
	this._self = sElement + "object";
	eval( this._self + "=this" );
	return this;
}
