var Core =
{
	getEventElement: function(pEvt)
	{
		pEvt = (pEvt) ? pEvt : window.event;
		return (pEvt.target) ? pEvt.target : pEvt.srcElement;
	},
	mouseY: function(evt)
	{
		if (evt.pageY) return evt.pageY;
		else if (evt.clientY)
		   return evt.clientY + (document.documentElement.scrollTop ?
		   document.documentElement.scrollTop :
		   document.body.scrollTop);
		else return null;
	},

	mouseX: function(evt)
	{
		if (evt.pageX) return evt.pageX;
		else if (evt.clientX)
		   return evt.clientX + (document.documentElement.scrollLeft ?
		   document.documentElement.scrollLeft :
		   document.body.scrollLeft);
		else return null;
	},

    addSpan: function(pContainer, pText)
    {
        var el = this.addElement(pContainer, "span");
        if (pText)
        {
            this.addText(el, pText);
        }
        return el;
    },

    addDiv: function(pContainer, pText)
    {
        var el = this.addElement(pContainer, "div");
        if (pText)
        {
            this.addText(el, pText);
        }
        return el;
    },

    addElement: function(pContainer, pTagName)
    {
        var el = document.createElement(pTagName);
        if (pContainer != null)
        {
            pContainer.appendChild(el);
        }
        return el;
    },

    removeClass: function(el, pClassName)
    {
        if (!(el && el.className))
        {
            return;
        }
        var cls = el.className.split(" ");
        var ar = new Array();
        for (var i = cls.length; i > 0;)
        {
            if (cls[--i] != pClassName)
            {
                ar[ar.length] = cls[i];
            }
        }
        el.className = ar.join(" ");
    },

    addClass: function(el, pClassName)
    {
        this.removeClass(el, pClassName);
        if (!el.className || el.className.length == 0)
        {
            el.className = pClassName;
        }
        else
        {
            el.className += " " + pClassName;
        }
    },

    addClasses: function(el, pClassNames)
    {
        if (!el)
        {
            return;
        }
        if (!el.className)
        {
            el.className = pClassNames;
            return;
        }
        var cls = pClassNames.split(" ");
        for (var i = cls.length; i > 0;)
        {
            if (cls[--i] != "")
            {
                this.addClass(el, cls[i]);
            }
        }
    },
    
    
		getBoundingRect: function (element) {
			var coords = { x: 0, y: 0, width: element.offsetWidth, height: element.offsetHeight };
			while (element) {
				coords.x += element.offsetLeft;
				coords.y += element.offsetTop;
				element = element.offsetParent;
			}
			return coords;
		}
};

var Balloon =
{
	TIP_WIDTH: 20,
	TIP_HEIGHT: 27,
	TIP_XOFFSET: 27,
	TIP_YOFFSET: 6,
        prevBalContParent: null,
        currentEvent: null,
        currentElement: null,
        timeOutId: 0,
        currentSRC: null,
        currentX: null,
        
    buildBalloon: function(pContainer)
    {
		var balloon = document.getElementById('balloon_tooltip');
		if (balloon == null)
		{
			balloon = Core.addDiv(pContainer);
			balloon.id = "balloon_tooltip";
			Core.addClasses(balloon, "balloon");

			var innerDiv1 = Core.addDiv(balloon);
			Core.addClasses(innerDiv1, "balloon-top");
			Core.addSpan(innerDiv1);//we need content

			var innerDiv2 = Core.addDiv(balloon);
			Core.addClasses(innerDiv2, "balloon-middle");
			innerDiv2.id = "balloon_middle";

			Core.addClasses(Core.addDiv(balloon), "balloon-bottom");
		}
		return balloon;
	},

    buildTip: function(pContainer)
    {
    	var balloonTip = document.getElementById('balloonTip');
    	if (balloonTip == null)
    	{
			balloonTip = Core.addDiv(pContainer);
			balloonTip.id = "balloonTip";
		}
		return balloonTip;
	},
    

	showCode: function(src, x, contentElement)
	{

		//var st = Math.max(document.body.scrollTop,document.documentElement.scrollTop);		
		var srcRect = Core.getBoundingRect(src);
		var container = document.body;

		var balloon = this.buildBalloon(container);
		var balloonTip = this.buildTip(container);
		var contentContainer = document.getElementById('balloon_middle');
		prevBalContParent = contentElement.parentNode;
		var currentContent = contentContainer.firstChild
		if (currentContent) {
			currentContent.style.display = "none";
			prevBalContParent.appendChild(currentContent)
		}
		contentContainer.appendChild(contentElement);
		contentElement.style.display = 'block';
		balloon.style.display = 'block';

//		var balloonRect = balloon.getBoundingClientRect();
//		var balloonHeight = balloonRect.bottom - balloonRect.top;
		var balloonRect = Core.getBoundingRect(balloon);
		var balloonHeight = balloonRect.height;
		var leftPos = x - this.TIP_XOFFSET;
//		var topPos = srcRect.top - balloonHeight - this.TIP_HEIGHT;
		var topPos = srcRect.y - balloonHeight - this.TIP_HEIGHT;
		if (topPos > 0)
		{
			Core.removeClass(balloonTip, "balloon-tip-top");
			Core.addClasses(balloonTip, "balloon-tip");
			balloonTip.style.display = 'block';
			balloon.style.left = leftPos + 'px';
			balloon.style.top = topPos + 'px';
//			balloonTip.style.top = srcRect.top - this.TIP_HEIGHT - this.TIP_YOFFSET + 'px';
			balloonTip.style.top = srcRect.y - this.TIP_HEIGHT - this.TIP_YOFFSET + 'px';
			balloonTip.style.left = leftPos + this.TIP_XOFFSET + 'px';
		}
		else
		{
//			topPos = srcRect.bottom + this.TIP_HEIGHT;
			topPos = (srcRect.y + srcRect.height) + this.TIP_HEIGHT;
			Core.removeClass(balloonTip, "balloon-tip");
			Core.addClasses(balloonTip, "balloon-tip-top");
			balloonTip.style.display = 'block';
			balloon.style.left = leftPos + 'px';
			balloon.style.top = topPos + 'px';
//			balloonTip.style.top = srcRect.bottom + 2 + 'px';
			balloonTip.style.top = (srcRect.y + srcRect.height) + 2 + 'px';
			balloonTip.style.left = leftPos + this.TIP_XOFFSET + 'px';
		}
		this.showSelects(false);
	},

        showBalloon: function() 
        {
            this.showCode(this.currentSRC,this.currentX,this.currentElement);
            this.timeOutId = 0;
        },
        
	show: function(pEvent, contentElement)
	{
	    if ( this.timeOutId != 0 ) 
	       return;
	       
	    if(document.all)pEvent = event;
	    this.currentEvent = pEvent;
	    this.currentElement = contentElement;
            this.currentSRC = Core.getEventElement(pEvent);
            this.currentX = Core.mouseX(pEvent);
	    this.timeOutId = setTimeout("Balloon.showBalloon()",600);
        },
        
 	hide: function()
	{
	    if ( this.timeOutId != 0 ) {
	        clearTimeout(this.timeOutId);
	        this.timeOutId = 0;
	        return;
	    }
		this.showSelects(true);
		document.getElementById('balloon_tooltip').style.display = 'none';
		document.getElementById('balloonTip').style.display = 'none';
		var contentContainer = document.getElementById('balloon_middle');
		contentContainer.firstChild.style.display = 'none';
		prevBalContParent.appendChild(contentContainer.firstChild);
	},

	showSelects: function(pShow)
	{
	    var el = document.getElementById('balloon_tooltip');
		var p = this.getAbsolutePos(el);
		var EX1 = p.x;
		var EX2 = el.offsetWidth + EX1;
		var EY1 = p.y;
		var EY2 = el.offsetHeight + EY1;
		var ar = document.getElementsByTagName("select");
		for (var i = ar.length; i > 0;) {
			var cc = ar[--i];

			p = this.getAbsolutePos(cc);
			var CX1 = p.x;
			var CX2 = cc.offsetWidth + CX1;
			var CY1 = p.y;
			var CY2 = cc.offsetHeight + CY1;

			if (!((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)))
			{
				cc.style.visibility = pShow ? "" : "hidden";
			}
		}
	},

    getAbsolutePos: function(el)
    {
    	var SL = 0, ST = 0;
    	var is_div = /^div$/i.test(el.tagName);
    	if (is_div && el.scrollLeft)
    		SL = el.scrollLeft;
    	if (is_div && el.scrollTop)
    		ST = el.scrollTop;
    	var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
    	if (el.offsetParent) {
    		var tmp = this.getAbsolutePos(el.offsetParent);
    		r.x += tmp.x;
    		r.y += tmp.y;
    	}
    	return r;
    }

};