/********************************************************************************************
   Creates the popup image with callout object and optional text

   Requires the following to be defined on the page:
---------------------------------------
<!-- For Internet Explorer Include the VML behavior
		  and Declare the VML namespace -->
	<!--[if IE]>
    	<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
        <style>v\:shape,
    		v\:roundrect,
    		v\:fill,
    		v\:textbox
    		{ behavior:url(#default#VML);display:inline-block }
        </style>
	<![endif]-->
----------------------------------------

	Requires a mapped image
   <img id='map_image' usemap="#map1" border="0" src="images/kiana_layout.jpg" width="300" height="106">
    <MAP NAME="map1">
     <AREA SHAPE=POLYGON COORDS="37,15,69,8,68,99,34,91,37,15" onmouseover="callout.mouseIn(0)" onmouseout="callout.mouseOut()">
     <AREA SHAPE=POLYGON COORDS="207,50,238,56,238,86,208,93,207,50" onmouseover="callout.mouseIn(1)" onmouseout="callout.mouseOut()">
    </MAP>

   The object is created and the images loaded after the page has rendered
   by placing the following immediately before the </body> tag
   <script>
    var callout = new galCallout('map_image');
    callout.setImage(0,"images/kiana_stern_cabin.JPG", 'some optional text');
    callout.setImage(1,"images/kiana_forward_cabin.JPG");
   </script>
   </body>
   
   To apply style to the objects use the setID method and CSS
   eg.  callout.setID('image_container', 'text_container', 'text_div');
   #image_container{border:1px solid #000000}
   #text_container{border:2px solid #000000}
   #text_div{font-size:9pt}
   
   To change the fill and stroke color for the callout use the setCalloutStyle(fillcolour, strokecolor) method
   eg. callout.setCalloutStyle('#000000', '#000000') 

*****************************************************************************************************/

function galCallout(map_id){
	// constants
	this.imageTopOffset = -200;
	this.textTopOffset = 10;
	var image_class = "";
	var text_class = "";
	var text_id = "";
	this.calloutBaseWidth = 12;
	this.calloutBaseYoffset = 5;
	this.cursorYoffset = 10;
	this.calloutZindex = 10;
	this.popupZindex = 12;
	
	//alert('galCallout'); // Create a container for all our elements 
	this.myCalloutContainer = document.createElement('div'); 
	this.myCalloutContainer.style.position = 'absolute'; 
	this.myCalloutContainer.style.visibility = 'visible'; //This needs to be visible for Safari 
	this.myCalloutContainer.style.display = 'block'; 
	this.myCalloutContainer.style.zIndex = this.popupZindex; 
	document.body.insertBefore(this.myCalloutContainer, 
	document.body.firstChild);
	
	// Create the callout VML
	if (document.all){
		//alert('IE');
		//document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', "#default#VML");
		this.myCallout = document.createElement('v:shape');
		this.myCalloutContainer.appendChild(this.myCallout);
		this.myCallout.fillcolor = '#FFFFCC';
		this.myCallout.strokecolor = '#000000';
		this.myCallout.style.position = 'absolute';
		this.myCallout.style.visibility = 'hidden';
		this.myCallout.style.display = 'block';
    	this.myCallout.style.left = '0px';
    	this.myCallout.style.top = '0px';
    	this.myCallout.style.width = '600px'; // set to view port width??
    	this.myCallout.style.height = '10px';
    	this.myCallout.style.zIndex = this.calloutZindex;
    	this.myCallout.coordsize = '600 10';
	}
	else{
		//alert('firefox');
	}

	// Create the image element
	if (document.all){
		this.myImgRect = document.createElement('v:roundrect');
		this.myCalloutContainer.appendChild(this.myImgRect);
		this.myImgRect.fillcolor = '#FFFFFF';
		this.myImgRect.strokecolor = '#CC3300';
		this.myImgRect.strokeweight = '2pt';
		this.myImgRect.coordsize = '21600 21600';
		//this.myImgRect.arcSize = '10%';
		
		this.myImage = document.createElement('v:fill');
		this.myImgRect.appendChild(this.myImage);
		this.myImage.type = 'frame';
	}
	else{
		this.myImgRect = document.createElement('div');
		this.myCalloutContainer.appendChild(this.myImgRect);
		this.myImgRect.className = image_class;
		this.myImgRect.style.border = '2pt solid #CC3300';
		this.myImage = document.createElement('img');
		this.myImgRect.appendChild(this.myImage);		
	}
	this.myImgRect.style.position = 'absolute';
	this.myImgRect.style.visibility = 'hidden'; 
	this.myImgRect.style.height = '150px';
	this.myImgRect.style.width = '150px';
	this.myImgRect.className = image_class;
	this.myImgRect.style.zIndex = this.popupZindex;
	this.myImgRect.style.display = 'block';

	// Create the text element
	if (document.all){
		this.myTxtRect = document.createElement('v:roundrect');
		this.myCalloutContainer.appendChild(this.myTxtRect);
		this.myTxtRect.fillcolor = '#FFFFFF';
		this.myTxtRect.strokecolor = '#CC3300';
		this.myTxtRect.strokeweight = '2pt';
		this.myTxtRect.coordsize = '21600 21600';
		//this.myTxtRect.arcSize = '10%';
		this.myTxtRect.style.verticalAlign = 'middle';
		
		this.myTextBox = document.createElement('v:textbox');
		this.myTxtRect.appendChild(this.myTextBox);

		this.myTextBox.innerHTML = '<div></div>';
		var tempDiv = this.myTextBox.firstChild;		
		var tempTable = document.createElement('table');
		tempTable.style.borderCollapse = 'collapse';
		tempTable.style.border = '0px none #000000';
		tempTable.style.width = '100%';
		tempTable.style.height = '100%';
		tempDiv.appendChild(tempTable);
		var tempTbody = document.createElement('tbody');
		tempTable.appendChild(tempTbody);
		var tempTr = document.createElement('tr');
		tempTbody.appendChild(tempTr);
		var tempTd = document.createElement('td');
		tempTr.appendChild(tempTd);
		
		this.myTextDiv = document.createElement('div');
		tempTd.appendChild(this.myTextDiv);
	}
	else{
		this.myTxtRect = document.createElement('div');
		this.myCalloutContainer.appendChild(this.myTxtRect);
		this.myTxtRect.className = text_class;
		this.myTxtRect.style.backgroundColor = '#FFFFFF';
		this.myTxtRect.style.border = '2pt solid #CC3300';
		this.myTextDiv = document.createElement('div');
		this.myTxtRect.appendChild(this.myTextDiv);	
		this.myTextDiv.id = text_id;
	}
	this.myTxtRect.style.position = 'absolute';
	this.myTxtRect.style.visibility = 'hidden';
	this.myTxtRect.style.height = '100px';
	this.myTxtRect.style.width = '250px';
	this.myTxtRect.className = text_class;
	this.myTxtRect.style.zIndex = this.popupZindex;
	this.myTxtRect.style.display = 'block';

	// Mapped image
	this.map_id = map_id;
	this.myMap = new galGetObj(map_id);
	if (typeof(this.myMap.obj)=='undefined') alert('galCallout: Mapped image is not defined');
	this.map_top = (new findPos(this.myMap.obj)).top;

	this.mouseOut_timer = false;
	this.images = new Array();
	this.active_ix = -1;
	
	//======= end constructor ===============
	
	// this method is used to set the id's of elements so styles can be applied with CSS
	this.setID = function(image_container_id, text_container_id, text_div_id){
		if (image_container_id) this.myImgRect.id = image_container_id;
		if (text_container_id) this.myTxtRect.id = text_container_id;
		if (text_div_id) this.myTextDiv.id =text_div_id;
	}
	
	// this method is used to set the callout colors
	this.setCalloutStyle = function(fillcolor, strokecolor){
		if (document.all){
			this.myCallout.fillcolor = fillcolor;
			this.myCallout.strokecolor = strokecolor;
		}
	}
	
	// this function is used to register an image
	// ix is the image index used to call the image on the mouseover event
	// src is the imgae source file name
	this.setImage = function(ix, src, text){
		this.images[ix] = new Object();
		this.images[ix].img = new Image();
		this.images[ix].img.src = src;
		this.images[ix].text = "";
		if (text){
			this.images[ix].text = text;
		}
	}
	// this method is called to preload the images in IE
	// the normal preload doesn't work becuase we are use VML
	//  to display the image rather than the <img> tag
	this.forcePreload = function(img){
		if (document.all){
			for (var i=0; i<this.images.length; i++){
				var vml = document.createElement('v:roundrect');
				var fill = document.createElement('v:fill');
				fill.type = 'frame';
				fill.src = this.images[i].img.src;
				vml.appendChild(fill);
				this.myCalloutContainer.appendChild(this.myImgRect);
				document.body.appendChild(vml);	
			}
		}
	}

	// called when the mouseover event occurs
	// ix is the index of the image to show
    this.mouseIn = function(e, ix){
    	if (ix < 0){
        	// We have rolled into the base image
    	    this._hide_callout(this);
    	    return;
    	}
    	if (ix >= this.images.length){
    		alert('Invalid image index('+ix+')');
    		return;
    	}
   		window.clearTimeout(this.mouseOut_timer);
    	// if we are currently active check if the same target
    	if (this.active_ix >= 0) if (this.active_ix == ix) return;

    	// A new target has been activated
    	if (this.active_ix >= 0) this._hide_callout(this);
		this.active_ix = ix;
		this._position_elements();
		this.myMap.style.cursor = 'pointer';
		
		// set up the image source
		this.myImage.src = this.images[ix].img.src;
		this.myImgRect.style.visibility = 'visible';

		// set up the text it there is any
		if (this.images[ix].text.length > 0){
			this.myTextDiv.innerHTML = this.images[ix].text;
	        this.myTxtRect.style.visibility="visible";
		}
		else{
			this.myTextDiv.innerHTML = '';
	        this.myTxtRect.style.visibility="hidden";
		}
	
        document.onmousemove = this.registerOnMouseMove(this);
        return true;
    }

	this.mouseOut = function(e){
		if ((typeof(e.toElement)=='object')&&(e.toElement)&&(typeof(e.toElement.tagName)!='undefined'))
			if (e.toElement.tagName == 'shape') return;
		this.mouseOut_timer = window.setTimeout(this.timeoutCallback(this),1);
	}
	this.timeoutCallback = function(context){
		return function(){
			context._hide_callout(context);
		}
	}
	this._hide_callout = function(context){
    	context.active_ix = -1;
		context.myMap.style.cursor = '';
        context.myImgRect.style.visibility = 'hidden';
	    if (this.myTxtRect) this.myTxtRect.style.visibility = 'hidden';
    	if (document.all){
			context.myCallout.path="";
			context.myCallout.style.visibility = 'hidden';
		}
        document.onmousemove = "";
        return true;
    }

	this._getmouseposition = function(ev, context){
	    if (!document.all) return;
		ev = event;
		if (document.documentElement && document.documentElement.scrollTop){
		// IE6 +4.01 
        	var scrollX = document.documentElement.scrollLeft;
        	var scrollY = document.documentElement.scrollTop;
		}
		else{
			var scrollX = document.body.scrollLeft;
			var scrollY = document.body.scrollTop;
		}
		
        var x = ev.clientX + scrollX;
        var y = ev.clientY + scrollY;		
		//window.status = "x="+x+", y="+y+", scrollX="+scrollX+", scrollY="+scrollY;
		
        if (y < context.map_top){
        	context._hide_callout(context);
        	return;
        }
    	context.myCallout.style.visibility = 'visible';
		
		// start at the cursor position
		var myCalloutPos = new findPos(context.myCallout);
		var mX = x - myCalloutPos.left + context.myCallout.offsetLeft;
		var mY = y - myCalloutPos.top + context.myCallout.offsetTop - context.cursorYoffset;
		
		// first point at bottom of image (left)
		var x1 = context.callout_base_x[0] - myCalloutPos.left + context.myCallout.offsetLeft;
		var y1 = context.callout_base_y[0] - myCalloutPos.top + context.myCallout.offsetTop - context.calloutBaseYoffset;
		
		// first point at bottom of image (right)
		var x2 = context.callout_base_x[1] - myCalloutPos.left + context.myCallout.offsetLeft;
		var y2 = context.callout_base_y[1] - myCalloutPos.top + context.myCallout.offsetTop - context.calloutBaseYoffset;
		
		path = "m "+mX+","+mY+" l "+x1+","+y1+" "+x2+","+y2+ "x e";
		context.myCallout.path = path;
	}

	// creates an object with the style postions to move an element to an anchor
	this.newPos = function(anchr, elem){
		var aPos = new findPos(anchr);
		var ePos = new findPos(elem);
		this.left = aPos.left - ePos.left + elem.offsetLeft; 
		this.top = aPos.top - ePos.top + elem.offsetTop; 
	}

	this._position_elements = function(){
		// the image and text rects are postioned relative to the image map
		var mapPos = new findPos(this.myMap.obj);
		var imgPos = new findPos(this.myImgRect);
		var txtPos = new findPos(this.myTxtRect);
		// left/top to move to image map postion
		var imgNewPos = new this.newPos(this.myMap.obj, this.myImgRect);
		var txtNewPos = new this.newPos(this.myMap.obj, this.myTxtRect);
		// the center of each elelemt is aligned with the center of the map
		// so move left 1/2 the width of map less 1/2 width of the image
		var imgLeftOffset = parseInt(this.myMap.obj.offsetWidth/2 - this.myImgRect.offsetWidth/2);
		var textLeftOffset = parseInt(this.myMap.obj.offsetWidth/2 - this.myTxtRect.offsetWidth/2);
		var imgTopOffset = this.imageTopOffset;
		var textTopOffset = this.textTopOffset + this.myMap.obj.offsetHeight;
		
		// Position the two elements
		this.myImgRect.style.left = (imgNewPos.left + imgLeftOffset) + 'px';
		this.myImgRect.style.top  = (imgNewPos.top + imgTopOffset) + 'px';
		this.myTxtRect.style.left = (txtNewPos.left + textLeftOffset) + 'px';
		this.myTxtRect.style.top  = (txtNewPos.top + textTopOffset) + 'px';

		// now do the callout
		if (document.all){
			var w = this.calloutBaseWidth; 
	
			// find the new cordinates of the picture bottom
			var pic_pos = new findPos(this.myImgRect);
			var bLeftX = pic_pos.left;
			var bLeftY = pic_pos.top + this.myImgRect.offsetHeight;
			var bRightX = pic_pos.left + this.myImgRect.offsetWidth;
			var bRightY = pic_pos.top + this.myImgRect.offsetHeight;
			
			// origin is always the centre of the picure
			var ctr = parseInt((bRightX - bLeftX)/2);
			var myRightX = bLeftX + ctr + w;
			var myLeftX = bLeftX + ctr - w;
	
			this.callout_base_x = new Array(myLeftX, myRightX);
			this.callout_base_y = new Array(bLeftY, bRightY);
			//alert('baseX:'+this.callout_base_x[0]+':'+this.callout_base_x[1]+', baseY:'+this.callout_base_y[0]+':'+this.callout_base_y[1]);
		}
    }
	
	this.registerOnMouseMove = function(context){
    	return function(event){context._getmouseposition(event, context)}
    }
}

