// by Mark Williams (mwp@mwp.id.au) for Crystalfontz America Inc.
// Copyright Crystalfontz America Inc, 2008.

function zi_show_help(div_name)
{
	document.getElementById(div_name).style.display = "inline";
}
function zi_hide_help(div_name)
{
	document.getElementById(div_name).style.display = "none";
}

function zi_download(zi_obj, table)
{
    if(table != "document") table = "photo";
    else table = "document";
	window.open("/zimage/zidownload.php?name="+zi_obj.image_id+"&type="+table);
}

function zi_select_border(id, image_id)
{
	var res = getElementsByClassName("zimage_select_image");
	for (var i=0; i < res.length; i++)
		res[i].style.border = "3px solid transparent";
	
	var select = document.getElementById("zis_"+id+"_"+image_id);
	select.style.border = "3px double blue";
	select.scrollIntoView(true); // true scrolles thumb to top of page. false scrolls it to bottom of page
    // if thumbs are above zoom and you say false, then thumb will be at bottom of page and bump zoom out of view
}

function zi_set_description(id, view, comment)
{
	var box = document.getElementById("ziid_"+id);
	var pview = document.getElementById("ziid_"+id+"_view");
	var pdesc = document.getElementById("ziid_"+id+"_desc");

	if (!view && !comment)
	{
		box.style.display = "none"
		return;
	}
	box.style.display = "block";
	if (view && (view!="Misc"))
	{
		pview.innerHTML = view;
		pview.style.display = "block";
	}
	else
		pview.style.display = "none";

	if (comment)
	{
		pdesc.innerHTML = comment;
		pdesc.style.display = "block";
	}
	else
		pdesc.style.display = "none";
}


function zi_new(id, image_id,
	tile_size_x, tile_size_y,
	full_size_x, full_size_y,
	start_zoom, zoom_pcts, dbtable)
	//start_zoom = -1 for autofit or 0->levels
	// dbtable is what db table tiles should get from: photo or document
{
	//keep correct scope
	var self = this;

	//bowser interaction vars
	this.browser = new get_browser;
	this.id = id;
	this.image_id = image_id;
	this.zi_div = null;
	this.image_div = null;
	this.controls_div = null;
	this.container_div = null;
	this.zoom_bar = null;
	this.zoom_bar_pos = null;
	this.div_width = 0;
	this.div_height = 0;
	this.start_zoom = start_zoom;
	
	if ((dbtable != 'photo') && (dbtable != 'document'))
		this.dbtable = 'photo';
	else
		this.dbtable = dbtable;

	//image handling vars
	this.zoom_level = 0;
	this.zoom_pcts = zoom_pcts;
	this.tile_size_x = tile_size_x;
	this.tile_size_y = tile_size_y;
	this.pos_x = 0;
	this.pos_y = 0;
	this.before_drag_x = 0;
	this.before_drag_y = 0;
	this.mouse_start_x = 0;
	this.mouse_start_y = 0;
	this.last_start_tile_x = 0;
	this.last_start_tile_y = 0;
	this.last_end_tile_x = 0;
	this.last_end_tile_y = 0;
	this.last_zoom_level = -999;
	this.zoom_bar_pos_x = 0;
	this.zoom_bar_positions = new Array();

	//misc
	this.tiles_x = 0;
	this.tiles_y = 0;
	this.size_x = 0;
	this.size_y = 0;
	this.start_tile_x = 0;
	this.start_tile_y = 0;
	this.end_tile_x = 0;
	this.end_tile_y = 0;

	//calc zoom tile areas from zoom levels
	this.zoom_tiles = new Array();
	for (var i=0; i < this.zoom_pcts.length; i++)
	{
		pct = this.zoom_pcts[i];
		if (pct < 1)
		{
			//resize to new zoom level
			zx = Math.floor(full_size_x * pct);
			zy = Math.floor(full_size_y * pct);
			//upsize to tile multiple
			bx = Math.ceil(zx / this.tile_size_x);
			by = Math.ceil(zy / this.tile_size_y);
		}
		else
		{
			//image already at size upsize to tile multiple
			bx = Math.ceil(full_size_x / this.tile_size_x);
			by = Math.ceil(full_size_y / this.tile_size_y);
		}
		this.zoom_tiles[i] = new Array();
		this.zoom_tiles[i][0] = bx;
		this.zoom_tiles[i][1] = by;
	}

	//run on page dom load
	this.zi_init = function()
	{
		//get correct scope
		if (this != self)
			return zi_init.apply(self, arguments);

		//get dom info
		this.zi_div = document.getElementById("zi_" + this.id);
		this.image_div = document.getElementById("zim_" + this.id);
		this.controls_div = document.getElementById("zic_" + this.id);
		this.container_div = document.getElementById("zii_" + this.id);
		this.zoom_bar = document.getElementById("zic_" + this.id + "_bar");
		this.zoom_bar_pos = document.getElementById("zic_" + this.id + "_pos");

		//initial resize
		this.zi_update_size();

		//do first update
		if (this.start_zoom == -1)
			this.zi_zoom_fit();
		else
			this.zoom_level = this.start_zoom;
		this.zi_do_zoom();
		this.zi_update_image(true);

		//mouse cursor
		this.container_div.style.cursor = "url(/zimage/openhand.cur), pointer";
		this.zoom_bar.style.cursor = "url(/zimage/openhand.cur), pointer";
		this.zoom_bar_pos.style.cursor = "url(/zimage/openhand.cur), pointer";

		//events
		if (this.browser.isIE)
		{
			//is IEx
			this.container_div.attachEvent("onmousedown", this.zi_mouse_down);

//			this.container_div.attachEvent("DOMMouseScroll", this.zi_mouse_wheel);
//			this.container_div.attachEvent("onmousewheel", this.zi_mouse_wheel);

			this.zoom_bar.attachEvent("onmousedown", this.zi_mouse_down_zoom);
			this.zoom_bar_pos.attachEvent("onmousedown", this.zi_mouse_down_zoom);

			window.attachEvent("onresize", this.zi_update_size);

			document.getElementById("zic_"+this.id+"_out").attachEvent("onclick", this.zi_control_out);
			document.getElementById("zic_"+this.id+"_in").attachEvent("onclick", this.zi_control_in);
			document.getElementById("zic_"+this.id+"_fit").attachEvent("onclick", this.zi_control_fit);
		}
		else
		{
			//not IEx
			if (this.browser.isiPhone)
				this.container_div.addEventListener("touchstart", this.zi_touch_down, false);
			else
			{
				this.container_div.addEventListener("mousedown", this.zi_mouse_down, false);
//				this.container_div.addEventListener("DOMMouseScroll", this.zi_mouse_wheel, false);
//				this.container_div.addEventListener("mousewheel", this.zi_mouse_wheel, false);
			}

			this.zoom_bar.addEventListener("mousedown", this.zi_mouse_down_zoom, false);
			this.zoom_bar_pos.addEventListener("mousedown", this.zi_mouse_down_zoom, false);

			window.addEventListener("resize", this.zi_update_size, false);

			document.getElementById("zic_"+this.id+"_out").addEventListener("click", this.zi_control_out, false);
			document.getElementById("zic_"+this.id+"_in").addEventListener("click", this.zi_control_in, false);
			document.getElementById("zic_"+this.id+"_fit").addEventListener("click", this.zi_control_fit, false);

		}

		//and again (IE needs)
		this.zi_update_size();
	}

	//run before removal
	this.zi_uninit = function zi_uninit()
	{
		//clean up
		//get correct scope
		if (this != self)
			return zi_uninit.apply(self, arguments);

		//events
		if (this.browser.isIE)
		{
			//is IEx
			this.container_div.detachEvent("onmousedown", this.zi_mouse_down);

//			this.container_div.detachEvent("DOMMouseScroll", this.zi_mouse_wheel);
//			this.container_div.detachEvent("onmousewheel", this.zi_mouse_wheel);

			this.zoom_bar.detachEvent("onmousedown", this.zi_mouse_down_zoom);
			this.zoom_bar_pos.detachEvent("onmousedown", this.zi_mouse_down_zoom);

			window.detachEvent("onresize", this.zi_update_size);

			document.getElementById("zic_"+this.id+"_out").detachEvent("onclick", this.zi_control_out);
			document.getElementById("zic_"+this.id+"_in").detachEvent("onclick", this.zi_control_in);
			document.getElementById("zic_"+this.id+"_fit").detachEvent("onclick", this.zi_control_fit);

			this.container_div.detachEvent("onmouseup", this.zi_mouse_up);
			this.container_div.detachEvent("onmousemove", this.zi_mouse_move);
		}
		else
		{
			//not IEx
			if (this.browser.isiPhone)
				this.container_div.removeEventListener("touchstart", this.zi_touch_down, false);
			else
			{
				this.container_div.removeEventListener("mousedown", this.zi_mouse_down, false);
//				this.container_div.removeEventListener("DOMMouseScroll", this.zi_mouse_wheel, false);
//				this.container_div.removeEventListener("mousewheel", this.zi_mouse_wheel, false);
			}

			this.zoom_bar.removeEventListener("mousedown", this.zi_mouse_down_zoom, false);
			this.zoom_bar_pos.removeEventListener("mousedown", this.zi_mouse_down_zoom, false);

			window.removeEventListener("resize", this.zi_update_size, false);

			document.getElementById("zic_"+this.id+"_out").removeEventListener("click", this.zi_control_out, false);
			document.getElementById("zic_"+this.id+"_in").removeEventListener("click", this.zi_control_in, false);
			document.getElementById("zic_"+this.id+"_fit").removeEventListener("click", this.zi_control_fit, false);

			this.container_div.removeEventListener("mouseup", this.zi_mouse_up, true);
			this.container_div.removeEventListener("mousemove", this.zi_mouse_move, true);
		}
	}

	//update div sizes
	this.zi_update_size = function zi_update_size()
	{
		//get correct scope
		if (this != self)
			return zi_update_size.apply(self, arguments);

		if (this.browser.isIE)
			window.detachEvent("onresize", this.zi_update_size);

		//resize
		if (this.browser.isIE)
		{
			this.div_width = document.documentElement.clientWidth - find_pos_x(this.zi_div) - 120;
			//this.div_height = document.documentElement.clientHeight - find_pos_y(this.zi_div) - 80;
			this.div_height =  document.documentElement.clientHeight - 100;
		}
		else
		{
			this.div_width = window.innerWidth - this.zi_div.offsetLeft - 120;
			//this.div_height = window.innerHeight - this.zi_div.offsetTop - 80;
			this.div_height = window.innerHeight - 100;
		}
		if (this.div_width < 600) this.div_width = 600;
		if (this.div_height <  400) this.div_height = 400;

		this.zi_div.style.width = this.div_width+"px";
		this.zi_div.style.height = this.div_height+"px";
		this.container_div.style.width = this.div_width+"px";
		this.container_div.style.height = (this.div_height-30)+"px";
		this.controls_div.style.width = this.div_width+"px";
		this.controls_div.style.height = "30px";

		//calc zoom bar positions
		var bar_x = find_pos_x(this.zoom_bar);
		var bar_width = this.zoom_bar.width;
		var pos_width = this.zoom_bar_pos.width;
		var temp = 0;
		for (var i = 0; i < this.zoom_tiles.length; i++)
		{
			temp = Math.round(((bar_width - 20) / (this.zoom_tiles.length-1)) * (this.zoom_tiles.length-1 - i)) - Math.round(pos_width/2); i
			this.zoom_bar_positions[i] = temp + bar_x + 10;
		}

		//position help box
		var help_img = document.getElementById("zic_"+ this.id + "_help");
		var help_box = document.getElementById("zic_"+ this.id + "_help_box");
		help_box.style.left = "0px";
		help_box.style.top = "0px";

		if (this.browser.isIE)
			window.detachEvent("onresize", this.zi_update_size);

		//update image
		this.zi_do_zoom();
	}

	//update image
	this.zi_update_image = function zi_update_image(full_update)
	{
		//get correct scope
		if (this != self)
			return zi_update_image.apply(self, arguments);

		//for overzoom
		var tile_width = this.tile_size_x;
		var tile_height = this.tile_size_y;
		var pct = this.zoom_pcts[this.zoom_level];
		if (pct > 1.00)
		{
			//do overzoom
			tile_width = tile_width * pct;
			tile_height = tile_height * pct;
		}

		this.start_tile_x = Math.floor(this.pos_x / tile_width) -1;
		if (this.start_tile_x < 0) this.start_tile_x = 0;
		this.start_tile_y = Math.floor(this.pos_y / tile_height) -1;
		if (this.start_tile_y < 0) this.start_tile_y = 0;

		this.end_tile_x = Math.ceil((this.pos_x + this.div_width) / tile_width) +1;
		if (this.end_tile_x > this.tiles_x) this.end_tile_x = this.tiles_x;
		this.end_tile_y = Math.ceil((this.pos_y + this.div_height) / tile_height) +1;
		if (this.end_tile_y > this.tiles_y) this.end_tile_y = this.tiles_y;

		//update html img tags
		if (
			(this.last_start_tile_x != this.start_tile_x) ||
			(this.last_start_tile_y != this.start_tile_y) ||
			(this.last_end_tile_x != this.end_tile_x) ||
			(this.last_end_tile_y != this.end_tile_y) ||
			(full_update == true))
		{
			//image tiles are changing
			var emit = '';
			
			//loading image place holders
			for (var tx = this.start_tile_x; tx < this.end_tile_x; tx++)
				for (var ty = this.start_tile_y; ty < this.end_tile_y; ty++)
				{
/*					var tile_pos_x = tx * this.tile_size_x;
					var tile_pos_y = ty * this.tile_size_y; 
*/
					var tile_pos_x = tx * tile_width;
					var tile_pos_y = ty * tile_height;

					emit += '<img src="/zimage/loading'+this.tile_size_x+this.tile_size_y+'.jpg" style="left:'+
					        tile_pos_x+'px;top:'+tile_pos_y+'px;width:'+tile_width+'px;height:'+tile_height+'px;z-index:1;';

					if (this.browser.isNS)
						emit += '-moz-user-select:none;';
					
					emit += '" />';
				}

			//update new images
			for (var tx = this.start_tile_x; tx < this.end_tile_x; tx++)
				for (var ty = this.start_tile_y; ty < this.end_tile_y; ty++)
				{
/*					var tile_pos_x = tx * this.tile_size_x;
					var tile_pos_y = ty * this.tile_size_y; 
*/
					var tile_pos_x = tx * tile_width;
					var tile_pos_y = ty * tile_height; 

/*					emit += '<img src="/zimage/zitile.php?name='+this.image_id+'&z='+this.zoom_level+'&bx='+
					        tx+'&by='+ty+'&type='+this.dbtable+'" style="left:'+tile_pos_x+'px;top:'+tile_pos_y+
					        'px;width:'+tile_width+'px;height:'+tile_height+'px;z-index:2;'; */


					//when using htaccess
					emit += '<img src="/zimage/tile/i'+this.image_id+'z'+this.zoom_level+'x'+
					        tx+'y'+ty+'t'+this.dbtable+'" style="left:'+tile_pos_x+'px;top:'+tile_pos_y+
					        'px;width:'+tile_width+'px;height:'+tile_height+'px;z-index:2;'; 

					
					if (this.browser.isNS)
						emit += '-moz-user-select:none;';
                    
                    emit += '" />';

				}
			this.image_div.innerHTML = emit;

			this.last_start_tile_x = this.start_tile_x;
			this.last_start_tile_y = this.start_tile_y;
			this.last_end_tile_x = this.end_tile_x;
			this.last_end_tile_y = this.end_tile_y;
		}

		//update div position
		this.image_div.style.left = (0-this.pos_x)+"px";
		this.image_div.style.top = (0-this.pos_y)+"px";
	}


	//do zoom change
	this.zi_do_zoom = function zi_do_zoom()
	{
		//get correct scope
		if (this != self)
			return zi_do_zoom.apply(self, arguments);

		if (this.browser.isIE)
			window.detachEvent("onresize", this.zi_update_size);

		//check zoom range
		if (this.zoom_level < 0)
			this.zoom_level = 0;
		if (this.zoom_level > this.zoom_tiles.length-1)
			this.zoom_level = this.zoom_tiles.length-1;

		//for overzoom
		var tile_width = this.tile_size_x;
		var tile_height = this.tile_size_y;
		var pct = this.zoom_pcts[this.zoom_level];
		if (pct > 1.00)
		{
			//do overzoom
			tile_width = tile_width * pct;
			tile_height = tile_height * pct;
		}

		//save prev info for pos calc
		var last_tiles_x = this.tiles_x;
		var last_tiles_y = this.tiles_y;
		var last_size_x = this.size_x;
		var last_size_y = this.size_y;

		//update tile infos
		this.tiles_x = this.zoom_tiles[this.zoom_level][0];
		this.tiles_y = this.zoom_tiles[this.zoom_level][1];
		this.size_x = this.tiles_x * tile_width;
		this.size_y = this.tiles_y * tile_height;

		//update image div size
		this.image_div.style.width = this.size_x + "px";
		this.image_div.style.height = this.size_y + "px";

/*		//fix browser offsets
		this.zoom_bar_pos_x = this.zoom_bar_positions[this.zoom_level];
		if (this.browser.isNS) this.zoom_bar_pos_x -= 8;
		if (this.browser.isIE) this.zoom_bar_pos_x -= 12;
		if (this.browser.isSafari) this.zoom_bar_pos_x += 1;
		if (this.browser.isOpera) this.zoom_bar_pos_x -= 8;
		//update zoom bar
		this.zoom_bar_pos.style.left = this.zoom_bar_pos_x + "px";
		this.zoom_bar_pos.style.display = "block";
		this.zoom_bar_pos.style.top = "0px";
		//this.zoom_bar_pos.style.top = find_pos_y(this.zoom_bar) + "px";
	*/

		//update zoom bar
		this.zoom_bar_pos_x = this.zoom_bar_positions[this.zoom_level];
		this.zoom_bar_pos.style.left = this.zoom_bar_pos_x + "px";
		this.zoom_bar_pos.style.display = "block";
		var ret = find_offset_from_parents(this.zoom_bar).top;
		if (this.browser.isIE) ret += 5;
		this.zoom_bar_pos.style.top = ret+"px";

		if (this.browser.isIE)
			window.attachEvent("onresize", this.zi_update_size);

		//return if no zoom (only var updates)
		if (this.last_zoom_level == this.zoom_level)
		{
			//do re-center if smaller than viewing area (for resize)
			var do_update = false;
			if ((this.size_x <= this.div_width) || (this.last_zoom_level == -999))
			{
				//center x
				this.pos_x = 0 - Math.round((this.div_width - this.size_x) / 2);
				do_update = true;
			}
			if ((this.size_y <= this.div_height) || (this.last_zoom_level == -999))
			{
				//center y
				this.pos_y = 0 - Math.round((this.div_height - this.size_y) / 2);
				do_update = true;
			}
			if (do_update)
			{
				this.last_zoom_level = this.zoom_level;
				this.zi_update_image(true);
			}
			return;
		}

		//do positioning updates
		var half_width = Math.round(this.div_width/2);
		var half_height = Math.round(this.div_height/2);
		if ((this.size_x <= this.div_width) || (this.last_zoom_level == -999))
			//center x
			this.pos_x = 0 - Math.round((this.div_width - this.size_x) / 2);
		else
		{
			//use prev zoom x loc to reposition
			var last_center_x = this.pos_x + half_width;
			var pct_x = last_center_x / last_size_x;
			var new_center_x = Math.round(this.size_x * pct_x);
			this.pos_x = 0 - (half_width - new_center_x);
		}
		if ((this.size_y <= this.div_height) || (this.last_zoom_level == -999))
			//center y
			this.pos_y = 0 - Math.round((this.div_height - this.size_y) / 2);
		else
		{
			//use prev zoom y loc to reposition
			var last_center_y = this.pos_y + half_height;
			var pct_y = last_center_y / last_size_y;
			var new_center_y = Math.round(this.size_y * pct_y);
			this.pos_y = 0 - (half_height - new_center_y);
		}

		//save last zoom
		this.last_zoom_level = this.zoom_level;

		//do update
		this.zi_update_image(true);

	}

	//calc fitting zoom level
	this.zi_zoom_fit = function zi_zoom_fit()
	{
		//get correct scope
		if (this != self)
			return zi_zoom_fit.apply(self, arguments);

		//step through zoom sizes until fit is found
		for (var l = 0; l < this.zoom_tiles.length; l++)
		{
			if (this.zoom_pcts[l] > 1)
				continue;
			if (((this.zoom_tiles[l][0] * this.tile_size_x) <= this.div_width) &&
				((this.zoom_tiles[l][1] * this.tile_size_y) <= this.div_height))
			{
				//found the correct size
				this.zoom_level = l;
				break;
			}
		}
	}

	//zoom delta
	this.zi_zoom_delta = function zi_zoom_delta(delta)
	{
		//get correct scope
		if (this != self)
			return zi_zoom_delta.apply(self, arguments);

		//change zoom level
		this.zoom_level -= delta;

		//do zoom
		this.zi_do_zoom();
	}

	//on mouse start drag
	this.zi_mouse_down = function zi_mouse_down(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_down.apply(self, arguments);

		//get starting locations
		this.before_drag_x = this.pos_x;
		this.before_drag_y = this.pos_y;
		this.mouse_start_x = this.zi_mouse_x(event);
		this.mouse_start_y = this.zi_mouse_y(event);

		//mouse cursor
		this.container_div.style.cursor = "url(/zimage/closedhand.cur), pointer";
		
		//add drag events
		if (this.browser.isIE)
		{
			this.container_div.attachEvent("onmouseup", this.zi_mouse_up);
			this.container_div.attachEvent("onmousemove", this.zi_mouse_move);
			if (event)
			{
				event.cancelBubble = true;
				event.returnValue = false;
			}
		}
		else
		{
			this.container_div.addEventListener("mouseup", this.zi_mouse_up, true);
			this.container_div.addEventListener("mousemove", this.zi_mouse_move, true);
			if (event.preventDefault)
				event.preventDefault();
		}
	}

	//on mouse stop drag
	this.zi_mouse_up = function zi_mouse_up(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_up.apply(self, arguments);

		//mouse cursor
		this.container_div.style.cursor = "url(/zimage/openhand.cur), pointer";

		//remove drag events
		if (this.browser.isIE)
		{
			this.container_div.detachEvent("onmousemove", this.zi_mouse_move);
			this.container_div.detachEvent("onmouseup", this.zi_mouse_up);
			if (event)
			{
				event.cancelBubble = true;
				event.returnValue = false;
			}
		}
		else
		{
			this.container_div.removeEventListener("mousemove", this.zi_mouse_move, true);
			this.container_div.removeEventListener("mouseup", this.zi_mouse_up, true);
			if (event.preventDefault)
				event.preventDefault();
		}
	}

	//on drag move
	this.zi_mouse_move = function zi_mouse_move(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_move.apply(self, arguments);

		//check for leaving the containing div
		var mx = this.zi_mouse_x(event);
		var my = this.zi_mouse_y(event);
		var loc = find_offset_from_parents(this.container_div);
		var contx = loc.left;
		var conty = loc.top;
		if (
			(mx <= (contx+2)) || (my <= (conty+2)) ||
			(mx >= (this.div_width+contx-2)) || (my >= (this.div_height+conty-2)) 
			)
		{
			//mouse cursor
			this.container_div.style.cursor = "url(/zimage/openhand.cur), pointer";

			//cancel drag action
			if (this.browser.isIE)
			{
				this.container_div.detachEvent("onmousemove", this.zi_mouse_move);
				this.container_div.detachEvent("onmouseup", this.zi_mouse_up);
			}
			else
			{
				this.container_div.removeEventListener("mousemove", this.zi_mouse_move, true);
				this.container_div.removeEventListener("mouseup", this.zi_mouse_up, true);
			}
		}

		//update image location
		this.pos_x = this.before_drag_x - (mx - this.mouse_start_x);
		this.pos_y = this.before_drag_y - (my - this.mouse_start_y);

		//check image bounds in container (dont let move outside)
		var half_width = Math.round(this.div_width/2);
		var half_height = Math.round(this.div_height/2);
		if ((0-this.pos_x) > half_width)
			this.pos_x = (0-half_width);
		if ((0-this.pos_y) > half_height)
			this.pos_y = (0-half_height);
		if (((0-this.pos_x) + this.size_x) < half_width)
			this.pos_x = 0 - (half_width - this.size_x);
		if (((0-this.pos_y) + this.size_y) < half_height)
			this.pos_y = 0 - (half_height - this.size_y);

		//do update
		this.zi_update_image(false);

		//stop default actions
		if (this.browser.isIE && event)
		{
			event.cancelBubble = true;
			event.returnValue = false;
		}
	}

	//on iPhone start drag
	this.zi_touch_down = function zi_touch_down(event)
	{
		//get correct scope
		if (this != self)
			return zi_touch_down.apply(self, arguments);

		// only deal with one finger
		if (event.touches.length != 1)
			return;

		//get starting locations
		this.before_drag_x = this.pos_x;
		this.before_drag_y = this.pos_y;
		this.mouse_start_x = event.touches[0].pageX;
		this.mouse_start_y = event.touches[0].pageY;

		//add drag events
		this.container_div.addEventListener("touchend", this.zi_touch_up, true);
		this.container_div.addEventListener("touchmove", this.zi_touch_move, true);
		if (event.preventDefault)
			event.preventDefault();
	}

	//on iPhone stop drag
	this.zi_touch_up = function zi_touch_up(event)
	{
		//get correct scope
		if (this != self)
			return zi_touch_up.apply(self, arguments);

		//remove drag events
		this.container_div.removeEventListener("touchmove", this.zi_touch_move, true);
		this.container_div.removeEventListener("touchend", this.zi_touch_up, true);
		if (event.preventDefault)
			event.preventDefault();
	}

	//on iPhone drag move
	this.zi_touch_move = function zi_touch_move(event)
	{
		//get correct scope
		if (this != self)
			return zi_touch_move.apply(self, arguments);

		//check for leaving the containing div
		var mx = event.touches[0].pageX;
		var my = event.touches[0].pageY;
		var contx = find_pos_x(this.container_div);
		var conty = find_pos_y(this.container_div);
		if (
			(mx <= (contx+2)) || (my <= (conty+2)) ||
			(mx >= (this.div_width+contx-2)) || (my >= (this.div_height+conty-2)) 
			)
		{
			//cancel drag action
			this.container_div.removeEventListener("touchmove", this.zi_touch_move, true);
			this.container_div.removeEventListener("touchstop", this.zi_touch_up, true);
		}

		//update image location
		this.pos_x = this.before_drag_x - (mx - this.mouse_start_x);
		this.pos_y = this.before_drag_y - (my - this.mouse_start_y);

		//check image bounds in container (dont let move outside)
		var half_width = Math.round(this.div_width/2);
		var half_height = Math.round(this.div_height/2);
		if ((0-this.pos_x) > half_width)
			this.pos_x = (0-half_width);
		if ((0-this.pos_y) > half_height)
			this.pos_y = (0-half_height);
		if (((0-this.pos_x) + this.size_x) < half_width)
			this.pos_x = 0 - (half_width - this.size_x);
		if (((0-this.pos_y) + this.size_y) < half_height)
			this.pos_y = 0 - (half_height - this.size_y);

		//do update
		this.zi_update_image(false);
	}

/*
    Scroll wheel is a pain when scrolling a page and mouse happens over the zoomer and your scroller
    is hijacked by the zoomer
    
	//scroll wheel handler
	this.zi_mouse_wheel = function zi_mouse_wheel(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_wheel.apply(self, arguments);

		var delta = 0;
		if (!event)
			event = window.event;
		if (event.wheelDelta)
		{
			delta = event.wheelDelta / 120; 
		}
		else if (event.detail)
		{
			delta = -event.detail / 3;
		}

		//have delta value, do zoom in/out
		this.zi_zoom_delta(delta);

		if (event.preventDefault)
			event.preventDefault();
		event.returnValue = false;
	}
*/
    
	//control icons clicked
	this.zi_control_out = function zi_control_out(event)
	{
		//get correct scope
		if (this != self)
			return zi_control_out.apply(self,arguments);
		this.zi_zoom_delta(-1);
	}
	this.zi_control_in = function zi_control_in(event)
	{
		//get correct scope
		if (this != self)
			return zi_control_in.apply(self,arguments);
		this.zi_zoom_delta(1);
	}
	this.zi_control_fit = function zi_control_fit(event)
	{
		//get correct scope
		if (this != self)
			return zi_control_fit.apply(self,arguments);
		this.zi_zoom_fit();
		this.zi_do_zoom();
	}

	//on mouse start drag on zoomer
	this.zi_mouse_down_zoom = function zi_mouse_down_zoom(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_down_zoom.apply(self, arguments);

		//get starting locations
		this.mouse_start_x = this.zi_mouse_x(event);

		//move the position bar
		this.zi_move_bar_pos(this.mouse_start_x);

		//mouse cursor
		this.zoom_bar.style.cursor = "url(/zimage/closedhand.cur), pointer";
		this.zoom_bar_pos.style.cursor = "url(/zimage/closedhand.cur), pointer";

		//add drag events
		if (this.browser.isIE)
		{
			this.zoom_bar.attachEvent("onmouseup", this.zi_mouse_up_zoom);
			this.zoom_bar.attachEvent("onmousemove", this.zi_mouse_move_zoom);
			this.zoom_bar_pos.attachEvent("onmouseup", this.zi_mouse_up_zoom);
			this.zoom_bar_pos.attachEvent("onmousemove", this.zi_mouse_move_zoom);
			event.cancelBubble = true;
			event.returnValue = false;
		}
		else
		{
			this.zoom_bar.addEventListener("mouseup", this.zi_mouse_up_zoom, false);
			this.zoom_bar.addEventListener("mousemove", this.zi_mouse_move_zoom, false);
			this.zoom_bar_pos.addEventListener("mouseup", this.zi_mouse_up_zoom, false);
			this.zoom_bar_pos.addEventListener("mousemove", this.zi_mouse_move_zoom, false);
			if (event.preventDefault)
				event.preventDefault();
		}
	}

	//on mouse stop drag on zoomer
	this.zi_mouse_up_zoom = function zi_mouse_up_zoom(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_up_zoom.apply(self, arguments);

		//done drag, snap to closest zoom location
		var closest_delta = 9999;
		var closest_zoom = 0;
		var delta = 0;
		for (var i = 0; i < this.zoom_tiles.length; i++)
		{
			delta = Math.abs(this.zoom_bar_pos_x - this.zoom_bar_positions[i]);
			if (delta < closest_delta)
			{
				closest_delta = delta;
				closest_zoom = i;
			}
		}
		this.zoom_level = closest_zoom;
		this.zi_do_zoom();

		//mouse cursor
		this.zoom_bar.style.cursor = "url(/zimage/openhand.cur), pointer";
		this.zoom_bar_pos.style.cursor = "url(/zimage/openhand.cur), pointer";

		//remove drag events
		if (this.browser.isIE)
		{
			this.zoom_bar.detachEvent("onmousemove", this.zi_mouse_move_zoom);
			this.zoom_bar.detachEvent("onmouseup", this.zi_mouse_up_zoom);
			this.zoom_bar_pos.detachEvent("onmousemove", this.zi_mouse_move_zoom);
			this.zoom_bar_pos.detachEvent("onmouseup", this.zi_mouse_up_zoom);
			if (event)
			{
				event.cancelBubble = true;
				event.returnValue = false;
			}
		}
		else
		{
			this.zoom_bar.removeEventListener("mousemove", this.zi_mouse_move_zoom, false);
			this.zoom_bar.removeEventListener("mouseup", this.zi_mouse_up_zoom, false);
			this.zoom_bar_pos.removeEventListener("mousemove", this.zi_mouse_move_zoom, false);
			this.zoom_bar_pos.removeEventListener("mouseup", this.zi_mouse_up_zoom, false);
			if (event)
				if (event.preventDefault)
					event.preventDefault();
		}
	}

	//on drag move on zoomer
	this.zi_mouse_move_zoom = function zi_mouse_move_zoom(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_move_zoom.apply(self, arguments);

		//move the position bar
		var mx = this.zi_mouse_x(event);
		this.zi_move_bar_pos(mx);
	}

	//set a new zoom bar position
	this.zi_move_bar_pos = function zi_move_bar_pos(new_x)
	{
		//get correct scope
		if (this != self)
			return zi_move_bar_pos.apply(self, arguments);

		var new_pos = new_x - Math.round(this.zoom_bar_pos.width/2);
		var max_limit = find_pos_x(this.zoom_bar) + this.zoom_bar.width - 7 - this.zoom_bar_pos.width;
		var min_limit = find_pos_x(this.zoom_bar) + 7;
		if (new_pos <= min_limit)
		{
			//out of bounds, cancel zoom
			this.zoom_bar_pos_x = min_limit;
			this.zoom_bar_pos.style.left = min_limit + "px";
			this.zi_mouse_up_zoom(null);
			return;
		}
		if (new_pos >= max_limit)
		{
			//out of bounds, cancel zoom
			this.zoom_bar_pos_x = max_limit;
			this.zoom_bar_pos.style.left = max_limit + "px";
			this.zi_mouse_up_zoom(null);
			return;
		}

		//set new position
		this.zoom_bar_pos_x = new_pos;
		this.zoom_bar_pos.style.left = new_pos + "px";
	}

	//get X mouse location
	this.zi_mouse_x = function zi_mouse_x(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_x.apply(self, arguments);

		if (event.pageX)
			return event.pageX;
		else
			if (event.clientX)
				return event.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft);
			else
				return null;

/*		if (this.browser.isIE)
			return (window.event.clientX + document.documentElement.scrollLeft +
				document.body.scrollLeft);
		else
			return (event.clientX + window.scrollX); */
	}

	//get Y mouse location
	this.zi_mouse_y = function zi_mouse_y(event)
	{
		//get correct scope
		if (this != self)
			return zi_mouse_y.apply(self, arguments);

		if (event.pageY)
			return event.pageY;
		else
			if (event.clientY)
				return event.clientY + (document.documentElement.scrollTop ?  document.documentElement.scrollTop : document.body.scrollTop);
			else
				return null;


/*		if (this.browser.isIE)
			return (window.event.clientY + document.documentElement.scrollTop +
				document.body.scrollTop);
		else
			return (event.clientY + window.scrollY); */
	}
}
