(function($){

/*----------------------------------------------------------------------------------

Class: FloatObject

-------------------------------------------------------------------------------------*/

	function FloatObject(jqObj, params)

	{

		this.jqObj = jqObj;

		

		switch(params.speed)

		{

			case 'fast': this.steps = 5; break;

			case 'normal': this.steps = 10; break;

			case 'slow': this.steps = 20; break;

			default: this.steps = 10;

		};

		

		var offset = this.jqObj.offset();

		this.currentX = offset.left;

		this.currentY = offset.top;

		this.width = this.jqObj.width();

		this.height = this.jqObj.height();

		this.alwaysVisible = params.alwaysVisible;

		this.alwaysTop = params.alwaysTop;

		

		

		this.origX = typeof(params.x) == "string" ?  this.currentX : params.x;

		this.origY = typeof(params.y) == "string" ?  this.currentY : params.y;

				

				

		if ($(window).scrollTop() > this.origY ) {

this.updatedY = $(window).scrollTop();

} else {

this.updatedY = this.origY+10;

}		

		

		//now we make sure the object is in absolute positions.

		this.jqObj.css({'position':'absolute' , 'top':this.currentY ,'left':this.currentX,'z-index':'1000'});

	}

	

	FloatObject.prototype.updateLocation = function()

	{

		this.updatedX = $(window).scrollLeft() + this.origX;

		

		if( this.alwaysTop == false ){

			this.updatedY = $(window).scrollTop()+ this.origY;

			

			if( this.alwaysVisible ){

				if( this.origX + this.width > this.windowWidth() ) 

					this.updatedX = this.windowWidth() - this.width + $(window).scrollLeft();

				if( this.origY + this.height > this.windowHeight() ) 

				{

					this.updatedY = $(window).scrollTop() + this.windowHeight() - this.height;

					if( this.updatedY < this.origY ) this.updatedY = this.origY;

				}				

			}

		}

		else

		{



			if( $(window).scrollTop() > this.origY )

			{

				this.updatedY = $(window).scrollTop() + 5;

			}

			else

			{

				this.updatedY = this.origY + 5;

			}

		}

		this.dx = Math.abs(this.updatedX - this.currentX );

		this.dy = Math.abs(this.updatedY - this.currentY );

		

		return this.dx || this.dy;

	}

	

	FloatObject.prototype.windowHeight = function()

	{

		var de = document.documentElement;

		

		return self.innerHeight ||

			(de && de.clientHeight) ||

			document.body.clientHeight;

	}

	

	FloatObject.prototype.windowWidth = function()

	{

		var de = document.documentElement;

		

		return self.innerWidth ||

			(de && de.clientWidth) ||

			document.body.clientWidth;

	}

	

	

	FloatObject.prototype.move = function()

	{

		if( this.jqObj.css("position") != "absolute" ) return;

		var cx = 0;

		var cy = 0;

		

		if( this.dx > 0 )

		{			

			if( this.dx < this.steps / 2 )

				cx = (this.dx >= 1) ? 1 : 0;

			else

				cx = Math.round(this.dx/this.steps);

			

			if( this.currentX < this.updatedX )

				this.currentX += cx;

			else

				this.currentX -= cx;

		}

		

		if( this.dy > 0 )

		{

			if( this.dy < this.steps / 2 )

				cy = (this.dy >= 1) ? 1 : 0;

			else

				cy = Math.round(this.dy/this.steps);

			

			if( this.currentY < this.updatedY )

				this.currentY += cy;

			else

				this.currentY -= cy;

		}

		

		this.jqObj.css({'left':this.currentX, 'top': this.currentY });			

	}



	

	

/*----------------------------------------------------------------------------------

Object: floatMgr

-------------------------------------------------------------------------------------*/		

	$.floatMgr = {

		

		FOArray: new Array() ,

		

		timer: null ,

		

		initializeFO: function(jqObj,params) 

		{

			var settings =  $.extend({

				x: 0 ,

				y: 0 ,

				speed: 'fast'	,

				alwaysVisible: false ,

				alwaysTop: false},params||{});

			var newFO = new FloatObject(jqObj,settings);

			

			$.floatMgr.FOArray.push(newFO);

			

			if( !$.floatMgr.timer ) $.floatMgr.adjustFO();

			

			//now making sure we are registered to all required window events

			if( !$.floatMgr.registeredEvents ) 

			{

					$(window).bind("resize", $.floatMgr.onChange);

					$(window).bind("scroll", $.floatMgr.onChange);

					$.floatMgr.registeredEvents = true;

			}		

		} , 

		

		adjustFO: function() 

		{

			$.floatMgr.timer = null;

			

			var moveFO = false;

			

			for( var i = 0 ; i < $.floatMgr.FOArray.length ; i++ )

			{

				 FO = $.floatMgr.FOArray[i];

				 if( FO.updateLocation() )  moveFO = true;

			}

			

			if( moveFO )

			{

				for( var i = 0 ; i < $.floatMgr.FOArray.length ; i++ )

				{

					FO = $.floatMgr.FOArray[i];

					FO.move();

				}

				

				if( !$.floatMgr.timer ) $.floatMgr.timer = setTimeout($.floatMgr.adjustFO,50);

			}

		}	,

		

		stopFloatChk: false ,

		

		onChange: function()

		{

			if( !$.floatMgr.timer && !$.floatMgr.stopFloatChk ) $.floatMgr.adjustFO();

		} 		

	};

	

/*----------------------------------------------------------------------------------

Function: makeFloat

-------------------------------------------------------------------------------------*/		

	$.fn.makeFloat = function(params) {

		var obj = this.eq(0); //we only operate on the first selected object;

		$.floatMgr.initializeFO(obj,params); 

		if( $.floatMgr.timer == null ) $.floatMgr.adjustFO();

		return obj;

	};

	$.fn.stopFloat = function(params) {

		$.floatMgr.stopFloatChk = true;

	};

	

	$.fn.restartFloat = function(params) {

		$.floatMgr.stopFloatChk = false;

	};

})(jQuery);
