/*
Sky.Tooltip 
copyright by MySign AG (http://www.mysign.ch), Christian Troller
depencies: Prototype 1.6.0.2
           Scriptaculous effects 1.8.1
*/

// creating namespace
var Sky;
if ( !Sky ) Sky = {};

Sky.Tooltip = Class.create();

Sky.Tooltip.currMouseX = 0;
Sky.Tooltip.currMouseY = 0;

Sky.Tooltip._REQUIRED_PROTOTYPE = '1.6.0.2';
Sky.Tooltip._REQUIRED_SCRIPTACULOUS_EFFECTS = '1.8.1';

Event.observe( window, 'load', function () {
	Event.observe( document, "mousemove", function( event ) {
										Sky.Tooltip.currMouseX = Event.pointerX( event );
										Sky.Tooltip.currMouseY = Event.pointerY( event );
									} );
} );

Sky.Tooltip.prototype = {
	initialize: function( opts )
	{
		// checking Sky.PrototypeExtensions
		if( Object.isUndefined( Sky.PrototypeExtensions ) )
		{
			throw( "Sky.Tooltip requires the Sky.PrototypeExtensions JavaScript framework" );
		}
		// checking Prototype
		if( !Sky.PrototypeExtensions.isPrototypeLoaded( Sky.Tooltip._REQUIRED_PROTOTYPE ) )
		{
			throw( "Sky.Tooltip requires the Prototype JavaScript framework >= " + Sky.Tooltip._REQUIRED_PROTOTYPE );
		}
		// checking script.aculo.us effects
		if( !Sky.PrototypeExtensions.isScriptaculousEffectsLoaded( Sky.Tooltip._REQUIRED_SCRIPTACULOUS_EFFECTS ) )
		{
			throw( "Sky.Tooltip requires the script.aculo.us effects JavaScript framework >= " + Sky.Tooltip._REQUIRED_SCRIPTACULOUS_EFFECTS );
		}
		
		this.options = {
			className:				"myTooltip",	// Class name of the tooltip layer
			offsetX:				5,				// x-Offset from the mouse pointer to the layer
			offsetY:				5,				// y-Offset from the mouse pointer to the layer
			zindex:					99999,			// z-index of the layer
			fade:					true,			// Defines if the layer should fade and appear
			fadeSpeed:				.5,				// Fade/Appear speed
			fixedPosition:			false,			// Defines if the layer should have a fixed position
			useCustomPosition:		false,			// Defines if you want to use a custom position for the layer to appear. See the next 2 options for x/y coordinate definition
			customX:				0,				// Custom X-Position. Enable "useCustomPosition" to use this value.
			customY:				0,				// Custom Y-Position. Enable "useCustomPosition" to use this value.
			appearDelay:			.25,			// Defines the time in seconds until the tooltip is displayed after you call the show()-method
			elIdForCheckMousePos:	null			// Hide tooltip if mouse leaving this element.
		};
		
		Object.extend( this.options, opts || {} );
		
		this.initialized = false;
		this.boundMovementListener = this._adjustPositionOnMovement.bindAsEventListener( this );
		this.boundCheckMousePos = this._checkMousePosition.bind( this );
		
		this.text = "";
		
		this.runningEffect = null;
		this.isHiding = false;
	},
	
	show: function( text, options )
	{
		this.text = text;
		if( !Object.isUndefined( options ) )
		{
			if( this.initialized )
			{
				// delete old options
				this.tooltip.removeClassName( this.options.className );
			}
			
			Object.extend( this.options, options || {} );
		}
		
		window.setTimeout( this._show.bind( this ), ( this.options.appearDelay * 1000 ) );
	},
	
	_show: function()
	{
		this.isHiding = false;
		
		if( !this.initialized )
		{
			this.tooltip = new Element( "div" );
			this.tooltip.addClassName( this.options.className );
			this.tooltip.setStyle( { "position": "absolute", zIndex: this.options.zindex } );
			this.tooltip.hide();
			$(document.body).insert( { "top": this.tooltip } );
			
			this.initialized = true;
		}
		else
		{
			this.tooltip.addClassName( this.options.className ).setStyle( { zIndex: this.options.zindex } ).hide().absolutize();
		}
		
		this.tooltip.update( this.text );
		
		if( this.options.useCustomPosition )
		{
			var x, y;
			x = this.options.customX;
			y = this.options.customY;
			
			this.tooltip.setStyle( { top: y + "px", left: x + "px" } );
		}
		else
		{
			this._adjustPositionOnMovement();
		}
		
		if( this.options.fade )
		{
			this.tooltip.setOpacity( 0 );
			this.tooltip.show();
			if ( this.runningEffect != null )
			{
				this.runningEffect.cancel();
				this.runningEffect = null;
			}
			
			this.runningEffect = new Effect.Appear( this.tooltip, {
				duration: this.options.fadeSpeed,
				afterFinish: function()
								{
									this.runningEffect = null;
								}.bind( this )
			} );
		}
		else
		{
			this.tooltip.show();
		}
		
		if( !this.options.fixedPosition )
		{
			Event.observe( document, "mousemove", this.boundMovementListener );
		}
		
		if( this.options.elIdForCheckMousePos != null )
		{
			Event.observe( document, 'mousemove', this.boundCheckMousePos );
		}
		else
		{
			Event.stopObserving( document, 'mousemove', this.boundCheckMousePos );
		}
	},
	
	hide: function()
	{
		if( !this.options.fixedPosition )
		{
			Event.stopObserving( document, "mousemove", this.boundMovementListener );
		}
		Event.stopObserving( document, 'mousemove', this.boundCheckMousePos );
		
		if( !this.isHiding )
		{
			this.isHiding = true;
			
			if( this.options.fade )
			{
				if ( this.runningEffect != null )
				{
					this.runningEffect.cancel();
					this.runningEffect = null;
				}
				
				this.runningEffect = new Effect.Fade( this.tooltip, {
					duration: this.options.fadeSpeed,
					afterFinish: function()
									{
										this.runningEffect = null;
										this.tooltip.hide();
									}.bind( this )
				} );
			}
			else
			{
				this.tooltip.hide();
			}
		}
	},
	
	_getWindowWidth: function()
	{
		return (window.innerWidth + window.pageXOffset || document.documentElement.clientWidth + document.documentElement.scrollLeft || document.body.clientWidth + document.body.scrollLeft || 0);
	},
	
	_getWindowHeight: function()
	{
		return (window.innerHeight + window.pageYOffset ||  document.documentElement.clientHeight + document.documentElement.scrollTop || document.body.clientHeight + document.body.scrollTop || 0);
	},
	
	_adjustPositionOnMovement: function( event )
	{
		var mouseX = Sky.Tooltip.currMouseX;
		var mouseY = Sky.Tooltip.currMouseY;
		
		var tempX = mouseX, tempY = mouseY;
		if( !Object.isUndefined( this.tooltip ) && $(this.tooltip) )
		{
			if( ( mouseX + this.tooltip.getWidth() + 17 ) > this._getWindowWidth() )
			{
				tempX = mouseX - this.tooltip.getWidth() - 17;
				tempX += -(this.options.offsetX);
			}
			else
			{
				tempX += this.options.offsetX;
			}

			if( ( mouseY + this.tooltip.getHeight() + 17 ) > this._getWindowHeight() )
			{
				tempY = mouseY - this.tooltip.getHeight() - 17;
				tempY += -(this.options.offsetY);
			}		
			else
			{
				tempY += this.options.offsetY;
			}
			
			if( tempX < 0 )
			{
				tempX = 0;
			}
			
			if( tempY < 0 )
			{
				tempY = 0;
			}
			
			this.tooltip.setStyle( { top: tempY + "px", left: tempX + "px" } );
		}
	},
	
	_checkMousePosition: function ()
	{
		if( this.options.elIdForCheckMousePos != null && $(this.options.elIdForCheckMousePos) && !this.isHiding )
		{
			var containerViewportOffset = $(this.options.elIdForCheckMousePos).cumulativeOffset();
			var containerLeft = containerViewportOffset[0];
			var containerTop = containerViewportOffset[1];
			
			var horizontalPosition = Sky.Tooltip.currMouseX - containerLeft;
			var verticalPosition = Sky.Tooltip.currMouseY - containerTop;
			
			var containerDimensions = $(this.options.elIdForCheckMousePos).getDimensions();
			var containerHeight   = containerDimensions.height;
			var containerWidth = containerDimensions.width;
			
			if( horizontalPosition < 0 || verticalPosition < 0 || Sky.Tooltip.currMouseX > (containerWidth + containerLeft) || Sky.Tooltip.currMouseY > (containerHeight + containerTop) )
			{
				this.hide();
			}
		}
	}
};

// For compatibility reasons
var My;
if( !My ) My = {};
My.Tooltip = Sky.Tooltip;