/*Copyright 2005. RealBird Inc. All rights reserved. */
function ZoomPan(anchordiv, minscale, maxscale, initscale) {
	this.max_scale = maxscale;
	this.min_scale = minscale;	
	this.current_pos = initscale;  //current scale value of the control
	//control setup
	this.zoom_plus_minus_auto = true;	//true - clicking +/- automatically inc/decr position
										//false - only onZoomMinus/onZoomPlus events generated
										
	this.max_on_top = false;			//true - maximum is at top of scrool bar
										//false - maximum is at bottom of scrool bar
										
	this.scale_inc = 10;				//numerical amount between scale values
	//following two values must equal the height of theimages used
	//for zoompan_tick.png and zoompan_tracker.png.  Fixes opera issue of
	//when the JSCript runs before images are loaded
	this.tick_height = 3;				
	this.tracker_height = 9;
	//Height to use for the scoll bar area
	this.tracker_bar_height = 150;
	
	
	if ((initscale < minscale) || (initscale > maxscale)) {
		initscale=40;
	} 
	//function for creating temp ids
	function create_tmp_id() {
		var tmpid = "";
		var i;
		var chars = new Array('a','b','c','d','e','f','g','h','i','j','k','l','m','n');
		for (i = 0; i < 5; i++) {
			tmpid += chars[Math.floor(13*Math.random() + 0.5)];
		}
		while (document.getElementById(tmpid) != null) {
			tmpid += chars[Math.floor(13*Math.random() + 0.5)];
		}
		return tmpid;	
	}	
	
	var tempids = new Array(9);
	var i;
	//create 9 temp ids
	for (i = 0; i < tempids.length; i++) {
		tempids[i] = create_tmp_id();
	}
	//create the control pieces
	//	this.main_div is the div which contains all of the pieces
	this.main_div = document.createElement("div");
	var table_div = document.createElement("div");
	//use innerHTML and temp ids  to generate the table.  Reduces the headache
	//associated with cross-broswer table DOM implementations
	var table_src = '<table style="background-color:transparent;" cellpadding="2" border="0"><tr><td></td><td><img id="' + tempids[0] + '" src="javascript/zb/zoompan_up.png" style="cursor:pointer;cursor:hand;"></td></tr>';
	table_src += '<tr><td><img id="' + tempids[1] + '" src="javascript/zb/zoompan_left.png" style="cursor:pointer;cursor:hand;"></td><td><img id="' + tempids[2] + '" src="javascript/zb/zoompan_reset.png" style="cursor:pointer;cursor:hand;"></td><td><img id="' + tempids[3] + '" src="javascript/zb/zoompan_right.png" style="cursor:pointer;cursor:hand;"></td></tr>';
	table_src += '<tr><td></td><td><img id="' + tempids[4] + '" src="javascript/zb/zoompan_down.png" style="cursor:pointer;cursor:hand;"></td></tr>';
	table_src += '<tr><td></td><td><img id="' + tempids[5] + '" src="javascript/zb/zoompan_plus.png" style="cursor:pointer;cursor:hand;"></td></tr>';
	table_src += '<tr><td></td><td><div style="position:relative;cursor:pointer;cursor:hand;"><img id="' + tempids[6] + '" src="javascript/zb/zoompan_tracker.png" style="position:absolute;top:0px;left:0px;" width="17"><div id="' + tempids[7] + '" style="height:' + this.tracker_bar_height + 'px;"></div></div></td></tr>';
	table_src += '<tr><td></td><td><img id="' + tempids[8] + '" src="javascript/zb/zoompan_minus.png" style="cursor:pointer;cursor:hand;"></td></tr>';
	table_src += '</table>';	
	//add main_div to the document
	this.main_div = anchordiv.appendChild(this.main_div);
	//add table div to main div
	table_div = this.main_div.appendChild(table_div);
	//have to do this in this order, else IE on mac has issues
	table_div.innerHTML = table_src;																																											

	this.main_table = this.main_div.childNodes.item(0);
	this.main_table.This = this;
	
	
	//set the properties for each UI piece
	this.pan_up = document.getElementById(tempids[0]);
	this.pan_left = document.getElementById(tempids[1]);
	this.pan_reset =  document.getElementById(tempids[2]);
	this.pan_right = document.getElementById(tempids[3]);
	this.pan_down = document.getElementById(tempids[4]);
	this.zoom_plus = document.getElementById(tempids[5]);
	this.tracker = document.getElementById(tempids[6]);
	this.tracker_bar = document.getElementById(tempids[7]);
	this.zoom_minus = document.getElementById(tempids[8]);
	
	//link each piece back to this
	this.tracker.This = this;
	this.pan_left.This = this;
	this.pan_right.This = this;
	this.pan_up.This = this;
	this.pan_down.This = this;
	this.pan_reset.This = this;
	this.zoom_plus.This = this;
	this.zoom_minus.This = this;
	this.tracker_bar.This = this;
	this.tracker_bar.style.width = this.tracker.width;
	//-----------------------------------------------
	//private methods
	//-----------------------------------------------
	//
	//this.trackbarclick
	//	Event handler used by each graphical piece of the scroll/tracker bar
	this.trackbarclick = function Zoombar_TrackbarClick() {
		if (this.tracker_position == null) {
			return;
		}
		if (this.tracker_position == this.This.current_pos) {
			return;
		}
		this.This.set_tracker_pos(this.tracker_position);
		this.This.eventDispatcher("onScaleChanged", this.This.current_pos);		
	}
	
	//this.filltrackerbar
	//	builds the scroll/tracking bar
	//	The scroll tracker bar consitis of four images, layed out as
	//		zoompan_top
	//		zoompan_spacer
	//		zoompan_spacer
	//		zoompan_tick
	//		zoompan_spacer
	//		zoompan_spacer
	//			...
	//		zoompan_bottom
	this.filltrackerbar = function Zoombar_FillTracker() {
		var positions = new Array(); // array which matches image to position value
		var new_html = '<table style="background-color:transparent" border="0" cellspacing="0" cellpadding="0"><tr><td><img src="javascript/zb/zoompan_top.png"></td></tr>';
		var tot_height = this.tracker_bar_height - this.tracker_height;
		var tot_steps = Math.floor((this.max_scale-this.min_scale) / this.scale_inc);
		var height_filled = this.tick_height;						
		var step_size = (tot_height) / tot_steps;	
		var cur_height, half_height;
		var img_pos;	//value to assign to the current image
		if (this.max_on_top) {
			img_pos = this.max_scale;
		}
		else {
			img_pos= this.min_scale;
		}
		positions[0] = img_pos; //set the first image to top value
		for (i = 0; i < tot_steps - 1; i++) {
			//figure out the height of this step and tick
			cur_height = Math.floor((step_size * (i+ 1)) + 0.5) - height_filled;
			//the space between each tick consists of two space images
			//top has the previous value
			//bottom has the next value
			half_height = Math.floor(cur_height / 2);
			if (half_height > 0) {
				new_html += '<tr><td><img src="javascript/zb/zoompan_spacer.png" height="' + half_height + '" width="17"></td></tr>';
				positions[positions.length] = img_pos;
			}
			if (this.max_on_top) {
				img_pos -= this.scale_inc;
			}
			else {
				img_pos += this.scale_inc;
			}
			half_height = Math.ceil(cur_height / 2);
			if (half_height > 0) {
				new_html += '<tr><td><img src="javascript/zb/zoompan_spacer.png" height="' + half_height + '" width="17"></td></tr>';
				positions[positions.length] = img_pos;
			}
			positions[positions.length] = img_pos;
			new_html += '<tr><td><img src="javascript/zb/zoompan_tick.png"></td></tr>';
			height_filled += cur_height + this.tick_height;
		}
		//add the spacers between last tick ans the bottom value
		if (height_filled < tot_height) {
			cur_height = tot_height-height_filled;
			half_height = Math.floor(cur_height / 2);
			if (half_height > 0) {
				new_html += '<tr><td><img src="javascript/zb/zoompan_spacer.png" height="' + half_height + '" width="17"></td></tr>';
				positions[positions.length] = img_pos;
			}
			if (this.max_on_top) {
				img_pos -= this.scale_inc;
			}
			else {
				img_pos += this.scale_inc;
			}
			half_height = Math.ceil(cur_height / 2);
			if (half_height > 0) {
				new_html += '<tr><td><img src="javascript/zb/zoompan_spacer.png" height="' + half_height + '" width="17"></td></tr>';
				positions[positions.length] = img_pos;
			}
		}
		if (this.max_on_top) {
			positions[positions.length] = this.min_scale;
		}
		else {
			positions[positions.length] = this.max_scale;
		}
		new_html += '<tr><td><img src="javascript/zb/zoompan_bottom.png"></td></tr></table>';
		this.tracker_bar.innerHTML = new_html;
		//attach event handler to each image
		var images = this.tracker_bar.getElementsByTagName("img");
		for (i = 0; i < images.length; i++) {
			images.item(i).onclick = this.trackbarclick;
			images.item(i).This = this;
			images.item(i).tracker_position = positions[i];
		}		
		//set all tds in the control to have transparent background
		var tds = this.main_table.getElementsByTagName("td");
		for (i = 0; i < tds.length; i++) {
			tds.item(i).style.backgroundColor = "transparent";
		}			
	}
	//
	//this.trackermousedown
	//	Event handler for onmousedown of the scroller tracker
	this.trackermousedown = function Zoombar_TrackerMouseDown(e) {
		var ie = false;
		if (e == null) {
			e = window.event;
			ie = true;
		}
		else {
			e.preventDefault();
		}

		this.tracking = true;
		this.original_pos = this.This.current_pos;
		//use e.screenY, since this is the only 
		//mouse position available across all browsers
		//this value is used to compute the mouse y-delta
		this.downpos = e.screenY;
		this.offsetdownpos = this.offsetTop;
		this.onmousemove = null;
		this.onmousemove = this.This.trackermousemove;
		//if win IE then just call setCapture			
		if ((ie) && (this.setCapture)) {
			this.setCapture();
		}
		else {
			//otherwise send all mousemove/mouseup in the control to the tracker
			this.This.main_table.onmousemove = function a(e) {
				this.This.tracker.onmousemove(e);
			}
			this.This.main_table.onmouseup = function a(e) {
				this.This.tracker.onmouseup(e);
			}
		}
	}
	//
	//this.trackermousemove
	//	Event handler for onmousemove of the scroller tracker				
	this.trackermousemove = function Zoombar_TrackerMouseMove(e) {
		var ie = false;
		var tracker_height = this.clientHeight;
		var tracker_y;
		if (e == null) {
			e = window.event;
			ie = true;
		}
		//compute the new y pos by adding the mouse y-delta to the original offset position	
		tracker_y = this.offsetdownpos + (e.screenY - this.downpos);
		if (tracker_y < 0) {
			tracker_y = 0;
		}
			
		var range = this.nextSibling.clientHeight - tracker_height;
		if (tracker_y > range) {
			tracker_y = range;
		}
		//set new position
		this.style.top = tracker_y + "px";
		//compute to new value
		var temp_pos = Math.floor(((tracker_y / (1.0 * range)) * (this.This.max_scale - this.This.min_scale) + this.This.min_scale + 0.5));
		temp_pos = Math.floor((temp_pos/(this.This.scale_inc * 1.0)) + 0.5) * this.This.scale_inc;
		if (this.This.max_on_top) {
			temp_pos = (this.This.max_scale - temp_pos) + this.This.min_scale;
		}
		//if value changed, raise onDrag event
		if (temp_pos != this.This.current_pos) {						
			this.This.current_pos = temp_pos;
			this.This.eventDispatcher("onDrag", this.This.current_pos);
		}
	}		
		
	//
	//this.trackermouseup
	//	Event handler for onmouseup of the scroller tracker		
	this.trackermouseup = function Zoombar_TrackerMouseUp(e) {
		if (!this.tracking) {
			return;
		}
		var ie = false;
		if (e == null) {
			e = window.event;
			ie = true;
		}
		this.tracking = false;
		this.onmousemove = null;
		if ((ie) && (this.releaseCapture)) {
			this.releaseCapture();				
		}
		this.This.main_table.onmousemove = null;
		//move the tracker to current position for value
		this.This.set_tracker_pos(this.This.current_pos);
		//if value changed due to move, raise onScaleChanged event
		if (this.This.current_pos != this.original_pos) {
			this.This.eventDispatcher("onScaleChanged", this.This.current_pos);
		}			
	}
	//Attach event handlers to tracker
	this.tracker.onmousedown = this.trackermousedown;
	this.tracker.onmouseup = this.trackermouseup;
	
	//
	//this.set_tracker_pos
	//	sets this.current_pos = pos
	//	sets the tracker to the correct position for pos
	this.set_tracker_pos = function ZoomPan_SetTrackerPos(pos) {
		this.current_pos = pos;
		var tracker_range = this.tracker_bar_height - this.tracker_height;
		if (this.max_on_top) {
			pos = (this.max_scale - pos) + this.min_scale;
		}
		this.tracker.style.top = Math.floor(((pos - this.min_scale) / (1.0*(this.max_scale - this.min_scale))) * tracker_range + 0.5) + "px";
	}
	//
	//add the event handlers for the buttom images
	this.pan_left.onclick = function ZoomPan_PanLeftClick() {
		this.This.eventDispatcher("onPanLeft");
	}
	this.pan_right.onclick = function ZoomPan_PanRightClick() {
		this.This.eventDispatcher("onPanRight");
	}
	this.pan_up.onclick = function ZoomPan_PanUpClick() {
		this.This.eventDispatcher("onPanUp");
	}
	this.pan_down.onclick = function ZoomPan_PanDownClick() {
		this.This.eventDispatcher("onPanDown");
	}
	this.pan_reset.onclick = function ZoomPan_ResetClick() {
		this.This.eventDispatcher("onReset");
	}
	this.zoom_plus.onclick = function ZoomPan_ZoomPlus() {
		if (this.This.zoom_plus_minus_auto) {
			if (this.This.max_on_top) {
					if (this.This.current_pos < this.This.max_scale) {		
					this.This.current_pos += this.This.scale_inc;
					if (this.This.current_pos >  this.This.max_scale) {
						this.This.current_pos =  this.This.max_scale
					}
					this.This.set_tracker_pos(this.This.current_pos);
					this.This.eventDispatcher("onScaleChanged", this.This.current_pos);
				}			
			}
			else {
				if (this.This.current_pos > this.This.min_scale) {		
					this.This.current_pos -= this.This.scale_inc;
					if (this.This.current_pos <  this.This.min_scale) {
						this.This.current_pos =  this.This.min_scale
					}
					this.This.set_tracker_pos(this.This.current_pos);
					this.This.eventDispatcher("onScaleChanged", this.This.current_pos);
				}
			}
		}
		this.This.eventDispatcher("onZoomPlus");
	}
	this.zoom_minus.onclick = function ZoomPan_ZoomMinus() {
		if (this.This.zoom_plus_minus_auto) {
			if (this.This.max_on_top) {
				if (this.This.current_pos > this.This.min_scale) {		
					this.This.current_pos -= this.This.scale_inc;
					if (this.This.current_pos <  this.This.min_scale) {
						this.This.current_pos =  this.This.min_scale
					}
					this.This.set_tracker_pos(this.This.current_pos);
					this.This.eventDispatcher("onScaleChanged", this.This.current_pos);
				}			
			}
			else {
				if (this.This.current_pos < this.This.max_scale) {		
					this.This.current_pos += this.This.scale_inc;
					if (this.This.current_pos >  this.This.max_scale) {
						this.This.current_pos =  this.This.max_scale
					}
					this.This.set_tracker_pos(this.This.current_pos);
					this.This.eventDispatcher("onScaleChanged", this.This.current_pos);
				}
			}
		}
		this.This.eventDispatcher("onZoomMinus");
	}
	
	this.event_lookup = new Array();	//event handler lookup array
	
	//
	//this.eventDispatcher
	//	dispatches events to the subscribed handlers
	this.eventDispatcher = function ZoomPan_EventDispatcher(ename,p1,p2) {
		var idx = ename.toLowerCase();
		var callbacks = this.event_lookup[idx];
		if (callbacks == null) {
			return;
		}
		var i;
		for (i = 0; i < callbacks.length; i++) {
			callbacks[i](p1,p2);		
		}	
	}
	//-----------------------------------------------
	//end private methods
	//-----------------------------------------------
	//Finish initialization
	//fill in the scale
	this.filltrackerbar();
	//initialize pos
	this.set_tracker_pos(this.current_pos);
	//-----------------------------------------------
	//API functions
	//-----------------------------------------------
	this.AddEventListener = function ZoomPan_AddEventListener(ename, func) {
		var idx = ename.toLowerCase();
		if (this.event_lookup[idx] == null) {
			this.event_lookup[idx] = new Array();
		}
		this.event_lookup[idx][this.event_lookup[idx].length] = func;	
	}
	
	this.GetCurrentScale = function ZoomPan_GetCurrentScale() {
		return this.current_pos;	
	}
	
	this.SetCurrentScale = function ZoomPan_SetCurrentScale(pos) {
		if ((pos > this.max_scale) || (pos < this.min_scale)) {
			throw "ZoomPan:scale not in scale range";
		}
		this.set_tracker_pos(pos);
	}
	
	this.SetMinScale = function ZoomPan_SetMinScale(minscale) {
		if (minscale > this.max_scale) {
			throw "ZoomPan:minimum scale greater than maximum scale";
		}
		this.min_scale = minscale;
		this.filltrackerbar();
		if (this.current_pos < this.min_scale) {
			this.set_tracker_pos(this.min_scale);
		}
		else {
			this.set_tracker_pos(this.current_pos);
		}
	}
	this.SetMaxScale = function ZoomPan_SetMaxScale(maxscale) {
		if (maxscale < this.min_scale) {
			throw "ZoomPan:maximum scale less than minimum scale";
		}
		this.max_scale = maxscale;
		this.filltrackerbar();
		if (this.current_pos > this.max_scale) {
			this.set_tracker_pos(this.max_scale);
		}
		else {
			this.set_tracker_pos(this.current_pos);
		}
	}	
}