function XBalloon()
{
	//=========================================
	//Public variables
	//=========================================
	
	var self=this;
	
	//Properties
	self.id=null;
	
	self.width=200;
	self.imagesDir="";
	
	self.title=null;
	self.showCloseButton=true;
	self.contentHtml=null;
	self.contentDivID=null;
	
	self.posX=null;
	self.posY=null;
	self.direction=null;
	
	self.autoHide=false;
	self.autoAway=false;
	
	self.autoHideInterval=4000; // 4 sec
	
	//Transitions (for IE)
	self.transShow=false;
	self.transHide=false;
	self.transShowFilter='progid:DXImageTransform.Microsoft.Fade(Overlap=1.00)';
	self.transHideFilter='progid:DXImageTransform.Microsoft.Fade(Overlap=1.00)';
	
	//Used only if contentDivID was provided
	self.allowContentClone=true;
	
	//Events
	self.onClose=null;
	
	//Need timer as property to use on current object
	self.timerHide=null;
	
	
	//=========================================
	//Internal variables
	//=========================================
	
	var _isIE = document.all ? true : false;
	var _childID;
	var _balloonDiv;
	
	//=========================================
	//Public methods
	//=========================================
   
	self.isVisible = function()
	{
	    if (_balloonDiv && (_balloonDiv.style.visibility!='hidden'))
		   	return true;
		else
	        return false;
	}
	
	//private functions used in XBalloon.show
	function initBalloonDiv()
	{
		_balloonDiv= document.createElement("DIV");
	
		if (self.id)
		{
			var balloonDivID="balloonDiv_" + self.id;
	
			if (document.getElementById(balloonDivID))
				throw new Error ("XBalloon.initBalloonDiv div '" + balloonDivID + "' already exists");
	
			_balloonDiv.id=balloonDivID;
		}
		_balloonDiv.style.position="absolute";
		_balloonDiv.style.visibility="hidden";
		_balloonDiv.style.zIndex=3001;
		_balloonDiv.style.width=self.width + "px";
	
		_childID = document.forms[0].appendChild(_balloonDiv);
	
	}
		
	function preRenderBalloon()
	{
		// Assume SE
		if (!self.direction)
			self.direction = getBalloonDirection(); // get 'SE' or 'NE' etc
		
		genBalloonHtml();
		
		var left=parseInt(_balloonDiv.style.left);
		var top=parseInt(_balloonDiv.style.top);
		
		//East
		if (self.direction=="SE" || self.direction=="NE")
			_balloonDiv.style.left = (left - 18) + "px";
		
		//West  	
		if (self.direction=="SW" || self.direction=="NW")
			_balloonDiv.style.left = (left - _balloonDiv.offsetWidth + 15) + "px" ;
		
		//North
		if (self.direction=="NE" || self.direction=="NW")
			_balloonDiv.style.top = (top + _balloonDiv.offsetHeight) + "px";

                /*
		alert("direction "+self.direction);
                alert("left "+_balloonDiv.style.left);
                alert("top "+_balloonDiv.style.top);
		*/

	}	
	
	
	function showBalloon() {
		// Show balloon
		if(_isIE && self.transShow) {
			_balloonDiv.style.filter=self.transShowFilter;
		
			if(_balloonDiv.filters(0).status==2 || _balloonDiv.filters(0).status==1) {
				_balloonDiv.filters(0).Stop();
			}
			_balloonDiv.filters(0).Apply();
			_balloonDiv.style.visibility='visible';
			_balloonDiv.filters(0).Play();
		}
		else {
			_balloonDiv.style.visibility='visible';
		}
		
		// Init autohide if true
		if(self.autoHide) {
			clearTimeout(self.timerHide);
			self.timerHide=setTimeout(self.hide, self.autoHideInterval);
		}
		
		if(self.autoAway)
			_balloonDiv.onmouseover=self.hide;
		else
			_balloonDiv.onmouseover='';
		
	}
	
	self.show=function() {
		if(self.isVisible()) //to check _balloonDiv is visible or not
			throw new Error("XBalloon.showballoon'"+self.id+"'isalreadyvisible");
		
		if((!self.posX)||(!self.posY))
			throw new Error("XBalloon.showposXandposYpropertieswerenotspecified.");
		
		initBalloonDiv();
		
		preRenderBalloon();
		
		showBalloon();
		g_xBalloonManager.addBalloon(self);
	}
	
	self.hide =function() {
		if(!self.isVisible)
			throw new Error ("XBalloon.show  balloon '" + self.id  + "' is already hidden");
		
		if(_isIE && self.transHide) {
			_balloonDiv.style.filter=self.transHideFilter;
		
			if(_balloonDiv.filters(0).status==2 || _balloonDiv.filters(0).status==1) {
				_balloonDiv.filters(0).Stop();
			}
			_balloonDiv.filters(0).Apply();
			_balloonDiv.style.visibility='hidden';
			_balloonDiv.filters(0).Play();
		}
		else {
			_balloonDiv.style.visibility='hidden';
			_balloonDiv.innerHTML='';
			var tmp = document.forms[0].removeChild(_balloonDiv); //Added by Senthil P
		}	
		
		g_xBalloonManager.deleteBalloon(self);
	}
	
	self.onCloseButtonClick = function() {
		if (self.onClose!=null)
			self.onClose(self);
		self.hide();
	}
	
	//=========================================
	//Private methods
	//=========================================
	//Positioning functions
	function getLeft(obj) {
        	return(obj.offsetParent ? (getLeft(obj.offsetParent) + obj.offsetLeft) : obj.offsetLeft);
	}
			 
	function getTop(obj) {
		return(obj.offsetParent ? (getTop(obj.offsetParent) + obj.offsetTop) : obj.offsetTop); 
	}
		
	//Rendering functions
    	//Function gets called from show 
		    
	function getBalloonDirection() {
		genBalloonHtml("SE");
		var body = document.documentElement;
		
		//Account for scrolling
		var scrollTop = parseInt(body.scrollTop);
		var scrollLeft = parseInt(body.scrollLeft);
		
		var left=self.posX;
		var top=(self.posY - _balloonDiv.offsetHeight);
		
		_balloonDiv.style.left = left + "px";
		_balloonDiv.style.top =  top + "px";		
		
		//Take scrolling into account
		var isEast=true;
		
		if((document.body.offsetWidth + scrollLeft) < (left + _balloonDiv.offsetWidth + 20)) {		
			//Balloon doesn't fit to the right
			isEast=false;
		}
		
		var direction;
		
		if(parseInt(top) < scrollTop) {
			if(isEast)
				direction='NE';
			else
				direction='NW';
		}		
		else {
			if(isEast)
				direction='SE';
			else
				direction='SW';
		}
		
		return direction;
	}	
	

	function addContentHeader(content) {
		if ((self.title==null) && (!self.showCloseButton))
			return content;
		
		var newContent="";
		newContent=newContent + '<table cellpadding="0" cellspacing="0" border="0" width="100%">';
		newContent=newContent + '<tr>';
		
		var colspan=0;
		
		if (self.title!=null) {
			newContent=newContent + '<td style="padding-left:20px"><span>' +  self.title + '</span></td>';        
			colspan++;
		}
		
		if (self.showCloseButton) {
			var closeImage='<img id="imgClose" src="' + self.imagesDir + '/close.jpg"' +
			' onmouseover="this.src=\'' + self.imagesDir + '/closeActive.jpg\'"' +
			' onmouseout="this.src=\'' + self.imagesDir + '/close.jpg\'"' +
			' onmouseup="this.src=\''+ self.imagesDir + '/closeActive.jpg\'"'+
			' onmousedown="this.src=\'' + self.imagesDir + '/closeDown.jpg\'"' +
			' title="Close">';
		
			newContent=newContent + '<td align="right" valign="top">' +  closeImage + '</td>';        
			colspan++;
		}
		
		newContent=newContent + '</tr>';
		newContent=newContent + '<tr><td colspan="' + colspan + '">' +  content + '</td></tr>';       
		
		newContent=newContent + '</table>';
		return newContent;
	}
    

	function genBalloonHtml(direction) {
		if (!direction)
			direction=self.direction;
		
		var html="";
		var content="";
		var useContentDiv=((self.contentDivID!=null) && (self.contentDivID!=""))
		if (useContentDiv)
			content='<div id="divContentPlaceholder"></div>';
		else
			content='<div class="content" id="divContentHolder">' + self.contentHtml + '<div>';
		
		//Add title and close button
		//Body includes header and content
		var body;
		body=addContentHeader(content);
		
		switch(direction) {

		case 'SE':
		// South East	
			html ='<table class="XBalloon" border="0" cellpadding="0" cellspacing="0" >'+
			'  <tr>'+
			'    <td height="1" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftTop.gif" width="19" height="15"></td>'+
			'    <td height="7" class="south_border_top" >&nbsp;</td>'+
			'    <td height="7" class="south_border_top" >&nbsp;</td>'+
			'    <td height="7"  width="5%"><img border="0" src="' + self.imagesDir + '/cRightTop.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td valign=top colspan="4" class="body">'+
			body +
			'    </td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td width="5%" height="7">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftBottom.gif" width="19" height="15"></td>'+
			'    <td height="7" style="background-color: #E9F0F3" >&nbsp;</td>'+
			'    <td height="7" style="background-color: #E9F0F3" >&nbsp;</td>'+
			'    <td width="5%" height="7"><img border="0" src="' + self.imagesDir + '/cRightBottom.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td width="5%" height="10">&nbsp;</td>'+
			'    <td width="23%"><img border="0" src="'+ self.imagesDir + '/aSouthEast.gif" width="67" height="18"></td>'+
			'    <td height="10" class="south_border_bottom">&nbsp;</td>'+
			'    <td width="5%" height="10">&nbsp;</td>'+
			'  </tr>'+
			'</table>'
		break;
		
		case 'SW':					
		// South West
			html ='<table class="XBalloon" border="0" cellpadding="0" cellspacing="0">'+
			'  <tr>'+
			'    <td height="1" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftTop.gif" width="19" height="15"></td>'+
			'    <td height="7" class="south_border_top">&nbsp;</td>'+
			'    <td height="7" class="south_border_top">&nbsp;</td>'+
			'    <td height="7"  width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightTop.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td valign=top colspan="4" class="body">'+
			body +
			'    </td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td width="5%" height="7">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftBottom.gif" width="19" height="15"></td>'+
			'    <td height="7" style="background-color: #E9F0F3">&nbsp;</td>'+
			'    <td height="7" style="background-color: #E9F0F3">&nbsp;</td>'+
			'    <td width="5%" height="7">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightBottom.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td width="5%" height="10">&nbsp;</td>'+
			'    <td class="south_border_bottom" height="10">&nbsp;</td>'+
			'    <td width="23%">'+
			'    <img border="0" src="' + self.imagesDir + '/aSouthWest.gif" width="67" height="18"></td>'+
			'    <td width="5%" height="10">&nbsp;</td>'+
			'  </tr>'+
			'</table>'
		break;
		
		case 'NE':	
		// North East
			html ='<table class="XBalloon" border="0" cellpadding="0" cellspacing="0">'+
			'   <tr>'+
			'    <td width="5%" height="10"></td>'+
			'    <td width="23%">' +
			'    <img border="0" src=" '+ self.imagesDir + '/aNorthEast.gif" width="67" height="18"></td>'+
			'    <td height="10" class="north_border_top">&nbsp;</td>'+
			'    <td width="5%" height="10"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td height="7" width="5%">'+
			'    <img border="" src="' + self.imagesDir + '/cLeftTop.gif" width="19" height="15"></td>'+
			'    <td height="7" bgcolor="#E9F0F3">&nbsp;</td>'+
			'    <td height="7" bgcolor="#E9F0F3">&nbsp;</td>'+
			'    <td height="7" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightTop.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td valign=top colspan="4" class="body">'+
			body +
			'    </td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td height="1" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftBottom.gif" width="19" height="15"></td>'+
			'    <td height="7" class="north_border_bottom">&nbsp;</td>'+
			'    <td height="7" class="north_border_bottom">&nbsp;</td>'+
			'    <td width="5%" height="7">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightBottom.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'</table>'
		break;
		
		case 'NW':	
		// North West			
			html ='<table class="XBalloon" border="0" cellpadding="0" cellspacing="0">'+
			'  <tr>'+
			'    <td width="5%" height="10"></td>'+
			'    <td height="10" class="north_border_top">&nbsp;</td>'+
			'    <td width="23%">'+
			'    <img border="0" src="' + self.imagesDir + '/aNorthWest.gif" width="67" height="18"></td>'+
			'    <td width="5%" height="10"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td height="7" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftTop.gif" width="19" height="15"></td>'+
			'    <td height="7" bgcolor="#E9F0F3">&nbsp;</td>'+
			'    <td height="7" bgcolor="#E9F0F3">&nbsp;</td>'+
			'    <td height="7" width="5%">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightTop.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td valign=top colspan="4" class="body">' +
			body +
			'    </td>'+
			'  </tr>'+
			'  <tr>'+
			'    <td width="5%" height="1">'+
			'    <img border="0" src="' + self.imagesDir + '/cLeftBottom.gif" width="19" height="15"></td>'+
			'    <td height="7" class="north_border_bottom">&nbsp;</td>'+
			'    <td height="7" class="north_border_bottom">&nbsp;</td>'+
			'    <td width="5%" height="7">'+
			'    <img border="0" src="' + self.imagesDir + '/cRightBottom.gif" width="19" height="15"></td>'+
			'  </tr>'+
			'</table>'
		break;
		}
		
		if (useContentDiv) {
			var divContent=document.getElementById(self.contentDivID);
			if (divContent==null)
				throw new Error ("XBalloon.genBalloonHtml contentDiv '" + self.contentDivID  + "' does not exist.");
			if (!self.allowContentClone) {
				//Hide content and add it to body, otherwise it disappiars in IE
		
				divContent.style.display="none";
				document.forms[0].appendChild(divContent); 
			}
		
			_balloonDiv.innerHTML=html;
		
			replaceContentPlaceholder(divContent);
		} else {
			_balloonDiv.innerHTML=html;
		}
		
		if (self.showCloseButton) {
			var imgClose=findChildNode(_balloonDiv, "IMG", "imgClose");
			imgClose.onclick=self.onCloseButtonClick;
		}
	}
	
	
	function replaceContentPlaceholder(divContent) {
		var divContentPlaceholder=findChildNode(_balloonDiv, "DIV", "divContentPlaceholder");
		var parentNode=divContentPlaceholder.parentNode;
		
		parentNode.removeChild(divContentPlaceholder);
		
		if (self.allowContentClone) //Clone it
			divContent=divContent.cloneNode(true);
		
		divContent.style.display="block";
		parentNode.appendChild(divContent);
		
	}
	
	function findChildNode(parentNode, tagName, id) {
		var childNodes=parentNode.getElementsByTagName(tagName, id);
		
		var count;
		var node;
		
		for (count=0; count < childNodes.length; count++) {
			node=childNodes[count];
		
			if (node.id==id) {
				return node;
			}
		}
		
		return null;
	}
	
}

//===========================================
//Balloon manager
//
// -- Keeps track of all visible balloons.
//============================================

var g_xBalloonManager=new XBalloonManager();

function XBalloonManager() {
	//=========================================
	//Private attributes
	//=========================================
	
	var _balloons=new Array();
	var self=this;
	
	//=========================================
	//Public methods
	//=========================================
       
	self.addBalloon = function(balloon) {      
	        _balloons.push(balloon);
	}

	self.deleteBalloon = function(balloon) {
	        //array.indexOf is not supported in IE 6, so using my own
        	var index = getIndexOf(balloon);
       
	        if (index!=-1)
        		_balloons.splice(index, 1);
                
    	}

	self.hasBalloon = function(id) {
		var balloon;
		for (count=0; count < _balloons.length; count++) {
			balloon=_balloons[count];
			if (balloon.id==id)
				return true;
        	}
        	return false;
    	}

	function getIndexOf(balloon) {
        	for (count=0; count < _balloons.length; count++) {
			if (balloon==_balloons[count])
		                return count;
        	}
        
       		return -1;
    	}
}
