/*##############################################################################
#    ____________________________________________________________________
#   /                                                                    \
#  |               ____  __      ___          _____  /     ___    ___     |
#  |     ____       /  \/  \  ' /   \      / /      /__   /   \  /   \    |
#  |    / _  \     /   /   / / /    /  ___/  \__   /     /____/ /    /    |
#  |   / |_  /    /   /   / / /    / /   /      \ /     /      /____/     |
#  |   \____/    /   /    \/_/    /  \__/  _____/ \__/  \___/ /           |
#  |                                                         /            |
#  |                                                                      |
#  |   Copyright (c) 1999-2004, MindStep Corporation. All rights reserved |
#  |                                                                      |
#  |      www.mindstep.com                              www.mjswin.com    |
#  |   info-oss@mindstep.com                           mjswin@mjswin.com  |
#   \____________________________________________________________________/
#
#  [This product is distributed under a BSD-like license]
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#
#     2. Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in
#        the documentation and/or other materials provided with the
#        distribution.
#
#  THIS SOFTWARE IS PROVIDED BY THE MINDSTEP CORP PROJECT ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MINDSTEP CORP OR CONTRIBUTORS
#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
#  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
#  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
#  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#  The views and conclusions contained in the software and documentation
#  are those of the authors and should not be interpreted as representing
#  official policies, either expressed or implied, of MindStep Corp.
#
################################################################################
#
#	The trick to make the bubble appear on top of form elements on IE>=5.5 was
#	taken from: http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx
#
#  	This module uses a few <if browser X> tricks, but there is no really
#  	alternative, sadly :-(
#
##############################################################################*/

var gTTP_divId       = "ttp_toolTipContainer";
var gTTP_shadowId    = "ttp_toolTipContainerShadow";
var gTTP_frameId     = "ttp_toolTipContainerFrame";

var gTTP_divStyle    = "position:absolute;visibility:hidden;z-index:1000;"+
                       "color:#666;background-color:#ccc;padding:0px;margin:2px;font-size:11px;border:0px";

var gTTP_divHtml     = "<div id=" + gTTP_divId + " style='" + gTTP_divStyle + "'></div>";

var gTTP_iframeHtml  = "<iframe id="+gTTP_frameId+" "+
                       "frameborder=0 scrolling=no src='' width=200 height=100 "+
					   "style='visibility:hidden;position:absolute;z-index:998;filter:alpha(opacity=0);'></iframe>";

var gTTP_shadowHtml  = "<div id='"+gTTP_shadowId+"' "+
                       "style='background-color:#808080;visibility:hidden;position:absolute;z-index:999;"+
					   "filter:alpha(opacity=50);'></div>";

var gTTP_maxWidth    = null;
var gTTP_div         = null;
var gTTP_iframe      = null;

var gTTP_showDelay      = 300;
var gTTP_showFocusDelay = 1000;
var gTTP_hideDelay      = 300;

var gTTP_shadow         = null;
var gTTP_shadowSz       = 0;

var gTTP_curel       = null;
var gTTP_visible     = false;
var gTTP_locked      = false;
var gTTP_mousex      = 0;
var gTTP_mousey      = 0;
var gTTP_dflMode     = "mouse";
var gTTP_dflClass    = "";


function mjs_showToolTip(el,mode)
{
	var x,y,dx,dy;
	var winDx=mjs_documentWidth();
	var winDy=mjs_documentHeight();

	mjs_cancelTimedCall("ttpDelayedClose");
	mjs_cancelTimedCall("ttpDelayedOpen");
	mjs_hideToolTip();

	gTTP_visible=true;

	// Restore "auto sizing"
	mjs_resize(gTTP_div,"","");

	// Loads the tooltip content
	gTTP_div.innerHTML=el.mjstooltip;

	// Deals with maximum width
	var maxWidth=mjs_inheritAttrDfl(el,"mjstooltipmaxwidth",gTTP_maxWidth);
	if(mjs_valued(maxWidth) && mjs_width(gTTP_div)>maxWidth)
	{
		mjs_resize(gTTP_div,maxWidth,null);
	}
	else
	{
		maxWidth=null;
	}

	dx=mjs_width(gTTP_div);
	dy=mjs_height(gTTP_div);

	if(mode=="focus")
	{
		// The tooltip is related to a form element which has focus
		// => arranges things so that the tip does not cover the content
		x=mjs_x(el);
		y=mjs_y(el)-mjs_height(gTTP_div)-1-gTTP_shadowSz;
		if(y<0)
		{
			// Does not fit at the top ? Tries on the left side
			x=mjs_x(el)-mjs_width(gTTP_div)-1-gTTP_shadowSz;
			y=mjs_y(el);
		}
	}
	else
	{
		x=gTTP_mousex+5;
		y=gTTP_mousey+10;
	}

	if((x+dx+gTTP_shadowSz)>winDx)
	{
		x=winDx-dx-gTTP_shadowSz;
	}
	if((y+dy+gTTP_shadowSz)>winDy)
	{
		y=winDy-dy-gTTP_shadowSz;
	}

	x = (x<0)?0:x;
	y = (y<0)?0:y;

	if(mjs_valued(gTTP_iframe))
	{
		mjs_moveTo(gTTP_iframe,x,y);
		mjs_resize(gTTP_iframe,dx+gTTP_shadowSz,dy+gTTP_shadowSz);
		mjs_show(gTTP_iframe);
	}

	if(mjs_isie55 || mjs_ismoz)
	{
		// Manually setting the size of the DIV avoid its resizing when
		// resizing the document window. Only works on moz and IE though.
		mjs_resize(gTTP_div,dx,dy);
	}

	mjs_show(gTTP_div);
	mjs_moveTo(gTTP_div,x,y);

	if(gTTP_shadowSz>0)
	{
		dx=mjs_width(gTTP_div);
		dy=mjs_height(gTTP_div);
		mjs_moveTo(gTTP_shadow,x+gTTP_shadowSz,y+gTTP_shadowSz);
		mjs_resize(gTTP_shadow,dx,dy);
		mjs_show(gTTP_shadow);
	}

	gTTP_curel=el;
}

function mjs_hideToolTip()
{
	gTTP_visible=false;
	if(mjs_ismoz)
	{
		// This hack avoid the flickering effects in moz
		mjs_moveTo(gTTP_div,0,-1000);
	}
	mjs_hide(gTTP_div);
	mjs_hide(gTTP_iframe);
	if(mjs_ismoz)
	{
		// Anti-flickering again
		mjs_moveTo(gTTP_shadow,0,-1000);
		mjs_resize(gTTP_shadow,1,1);
	}
	mjs_hide(gTTP_shadow);
}

function _ttp_mouseOver(el,ev)
{
	gTTP_mousex=mjs_eventMousex(ev);
	gTTP_mousey=mjs_eventMousey(ev);

	if(!gTTP_locked)
	{
		if(!gTTP_visible)
		{
			if(el.mjsttonfocus)
			{
				mjs_timedCall(gTTP_showFocusDelay,"ttpDelayedOpen",mjs_showToolTip,el);
			}
			else
			{
				mjs_timedCall(gTTP_showDelay,"ttpDelayedOpen",mjs_showToolTip,el);
			}
		}
		else
		{
			mjs_cancelTimedCall("ttpDelayedClose");
			if(gTTP_curel !== el)
			{
				// We went on another element with tooltip => show it now
				mjs_timedCall(0,"ttpDelayedOpen",mjs_showToolTip,el);
			}
		}
	}
	return true;
}

function _ttp_mouseOut(el)
{
	if(!gTTP_locked)
	{
		if(!gTTP_visible)
		{
			mjs_cancelTimedCall("ttpDelayedOpen");
		}
		else
		{
			mjs_timedCall(gTTP_hideDelay,"ttpDelayedClose",mjs_hideToolTip,el);
		}
	}
	return true;
}

function _ttp_mouseMove(el,ev)
{
	gTTP_mousex=mjs_eventMousex(ev);
	gTTP_mousey=mjs_eventMousey(ev);
	return true;
}

function _ttp_gainFocus(el)
{
	gTTP_locked=true;
	mjs_showToolTip(el,"focus");
	return true;
}

function _ttp_loseFocus(el)
{
	mjs_hideToolTip();
	gTTP_locked=false;
	return true;
}

function parentDissalowed(ref)
{
	ok=0; // it's just to start the loop, we don't use it to get out.
	while (!ok)
	{
	ref = ref.parentNode;
	if (ref.nodeType==1) //check that the node is a tag, not text (type=3)
		{
		if (String(ref.id)=="art_scroll")
			{
			return true;
			}
		if (String(ref.nodeName)=="BODY")
			{
			return false;
			}
		}
	}
}

function _ttp_initialize()
{

	function _ttp_initTitle(el,text)
	{

		if (parentDissalowed(el))
		{
			return;
		}

		var caption,a,html="";
		var mode=mjs_inheritAttrDfl(el,"mjstooltipmode",gTTP_dflMode);
		var cssClass=mjs_inheritAttrDfl(el,"mjstooltipclass",gTTP_dflClass);
		var id,content;




		a=text.split("|",2);
		if(a.length>1)
		{
			// There is a caption
			caption=a[0];
			text=a[1];
		}

		if(id=text.match(/^#(.*)/))
		{
			id=id[1];
			if(!mjs_valued(content=document.getElementById(id)))
			{
				LOGERROR("cannot find title element id=#%s",id);
				return false;
			}
			mjs_hide(content); // In case author forgot
			text=content.innerHTML;
		}

		if(cssClass !== "")
		{
			html += "<div class='" + cssClass + "'>";
		}
		else
		{
			html += "<div style='border:0px solid black;'>";
		}

		if(mjs_valued(caption))
		{
			if(cssClass !== "")
			{
				// Uses the <class>_caption style for tooltip title
				html += "<div class='" + cssClass + "_caption'>"+caption+"</div>";
			}
			else
			{
				html += "<div style='padding:1px;background-color:black;color:white;'><b>"+caption+"</b></div>";
			}
		}

		if(cssClass !== "")
		{
			// Uses the <class> style for tooltip body
			html += "<div class='" + cssClass + "_body'>" + text + "</div>";
		}
		else
		{
			html += "<div style='padding:4px;'>" + text + "</div>";
		}
		html += "</span>";

		// Stores it for later use
		el.mjstooltip=html;
		el.mjsttonfocus=false;

		// Hooks relevant callbacks
		if(mode == "focus")
		{
			el.mjsttonfocus=true;
			if(mjs_isFormField(el))
			{
				mjs_setEventCallback("blur","ttplosefocus",el,_ttp_loseFocus);
				mjs_setEventCallback("focus","ttpgainfocus",el,_ttp_gainFocus);
				if(mjs_isCombo(el))
				{
					// Hide the tooltip after changing a combo value
					mjs_setEventCallback("change","ttpgainfocus",el,_ttp_loseFocus);
				}
			}
			else
			{
				LOGERROR("cannot set 'focus' tooltip mode on tag %s",el.tagName);
			}
		}
		else if(mode != "mouse")
		{
			LOGERROR("unknown tooltip mode '%s' on tag %s",mode,el.tagName);
			return false;
		}

		mjs_setEventCallback("mouseover","ttpover",el,_ttp_mouseOver);
		mjs_setEventCallback("mouseout","ttpout",el,_ttp_mouseOut);
		mjs_setEventCallback("mousemove","ttpmove",el,_ttp_mouseMove);
	}

	function _ttp_parse(el)
	{




		var i,l=el.childNodes,attr;

		for(i=0;i<l.length;i++)
		{
			var child=l[i];

			if(child.getAttribute != void(0))
			{
				if(attr=child.getAttribute("title"))
				{


					if (!parentDissalowed(child))
					{
						mjs_setAttr(child,"title","");
						_ttp_initTitle(child,attr);
					}


				}
			}
			_ttp_parse(child);
		}
	}

	// Creates a container for tooltips
	var el=document.createElement('span');
	el.innerHTML=gTTP_divHtml;
	document.body.appendChild(el);
	gTTP_div=document.getElementById(gTTP_divId);

	// Creates the IE iframe trick
	if(mjs_isie55)
	{
		var el=document.createElement('span');
		el.innerHTML=gTTP_iframeHtml;
		document.body.appendChild(el);
		gTTP_iframe=document.getElementById(gTTP_frameId);
	}

	// Creates a layer for the shadow
	var el=document.createElement('span');
	el.innerHTML=gTTP_shadowHtml;
	document.body.appendChild(el);
	gTTP_shadow=document.getElementById(gTTP_shadowId);

	// Parses the document tree in the search for tooltip related stuff
	_ttp_parse(document.body);
}

mjs_registerModule("tooltip",_ttp_initialize);


//--------------------------------------------------------------------------------
//
//	Public javascript API
//
//--------------------------------------------------------------------------------

function mjs_setTooltipClass(className)
{
	gTTP_dflClass=className;
}

function mjs_setTooltipShadowSize(sz)
{
	gTTP_shadowSz=sz;
}

function mjs_setTooltipMaxWidth(sz)
{
	gTTP_maxWidth=sz;
}

