/*//========================================
ImageViewer v0.9.7 [TEST RELEASE]
Author: Aractain
Copyright 2008
Last Updated: 17/10/2008




TODO:####

BUG: data box dosn't fade in (resolved - 13/10/2008 14:41)
BUG: image sometimes flashes before it annimates the image box (resolved - 13/10/2008 14:52)
BUG: flickering when reapidly click next/prev buttons (resolved - 14/10/2008 15:38)
BUG: solve resize bug when changing from image to same size image (resolved - 09/10/2008 14:34)
BUG: sometimes when pressing next/prev etc it moves the page to the top of the page (resolved - 14/10/2008 18:36 - was default action of <a> tag)
INVESTIGATE: it seems to hang for a while when change image (seemed to go away - 14/10/2008 16:20) (was casued by large text in a text box - 15/10/2008 17:23)
BUG: if click in fade stage of data box, flickering happens - need to hide box sooner (resolved - 15/10/2008 17:23)
BUG: when moveing from bigger to smaller image, data box has a 'trail' of 'disruption' to the underlying graphics (?)
BUG: IE dosn't update background if page incrases in size (resolved - 19/10/2008 17:10 - "documentelement" instead of "body" was needed to get values)
BUG: some buttons don't grey out - caused by stupid IE standard with opacity only on "layout" content (resolved - 19/10/2008 14:46)
BUG: flickering content (probably unset alpha settings) (resolved - 19/10/2008 15:04)
BUG: keys are fireing multiple events per keydown event, only in IE though (resolved - 19/10/2008 18:43 - added delay to enabling keyboard event after a change)



make sure keybaord event disable is done in stop function (done - 14/10/2008 15:38)
background - need it to fade out even if code stops before an image loads (resolved with S_CLOSE var - 10/10/2008 14:43)
add set number to image data area (done - 13/10/2008 14:02)
code to find element that was clicked (to feed into details/image update code) - PRIORITY (done - 13/10/2008 10:44)
change image code (done - 10/10/2008 12:04)
show/hide elements when nessesary (done - 10/10/2008 14:44)
sort array code (or smarter set prev/next checking) - (looking like chooseing smarter code) - (done - 11/10/2008 16:32)
show next/prev hover images even if not part of set - put in configurable switch so can switch off (done - 10/10/2008 14:44)
code to move from set to set (done - 13/10/2008 14:02)
keyboard code, need P and left arrow plus right arrow and N to work on the keyboard to navigate the image, [ and ] to navigate sets (done - 14/10/2008 12:56)
Page size info function (done - 15/10/2008 15:28)
Redesign resize function to complie with better standards (done - 15/10/2008 15:36)
initilisation on load (done - 16/10/2008 09:45)
framework code to run everything (done - 18/10/2008 10:44)
need a min width (done - 19/10/2008 15:01)

added a close to clicking the image with any mouse button (done - 27/04/2009 01:32)
added hideing of set buttons if theres only one or no sets (done - 30/04/2009 07:05)

hide flash objects and the like since they display on top and various bad things
inject HTML into the page instead of having it already there
more tag generation options

full testing!!




*///========================================

// config vars
var S_ALWAYS_NAV = true; // toggles nav buttons on/off within sets (true means they will move to the next image in the array, false mwans they wont display)
var S_SHADE_OPACITY = .50; // how much the background page shade should be transparent
var S_RESIZE_SPEED = 10;
var S_BORDER_SIZE = 10;
var S_BOLD_IMAGE_STRING = true; // switches on/off bold font for the numbers in the "image 1 of 3" display
var S_SHOW_SET_NAMES = true;

// image array and index
var imagesArray = [];
var currentImage = 0;

// const values
var S_UPDATES_PER_SECOND = 30; // Set resize FPS here
var S_MAX_INCR = 25;
var S_MIN_INCR = 3;
var S_SLOW_SCALE = 10;
var S_FADEOUT_TIME = 25;
var S_OPACITY_INCR = .10;
var S_FULL_OPACITY = 1;
var S_HEIGHT_SETUP = 400;
var S_WIDTH_SETUP = 400;
var S_MIN_WIDTH = 400;

var S_RESIZE_HEIGHT = 0;
var S_RESIZE_WIDTH = 1;

var S_IMAGEFLAG = 0;
var S_INFOFLAG = 1;
var S_SHADEFLAG = 2;

var S_PREV = 0;
var S_NEXT = 1;
var S_PREV_SET = 2;
var S_NEXT_SET = 3;
var S_FIRST = 4;
var S_LAST = 5;

// setup time/order checking vars
var S_H_RESIZE_FIN = true;
var S_W_RESIZE_FIN = true;
var S_CLOSE = false; // if set to true the imageViewer wants to close the image/background etc
var S_HEIGHT_CLOSE = false; // these tell the resize code to stop imediately and not to do anything before they finish
var S_WIDTH_CLOSE = false;

// fade in/out type flags
var S_IMAGE_IN = false;
var S_INFO_IN = false;
var S_SHADE_IN = false;

var S_IMAGE_OUT = false;
var S_INFO_OUT = false;
var S_SHADE_OUT = false;

// timeout vars
var S_HEIGHT_RESIZE_TIMEOUT;
var S_WIDTH_RESIZE_TIMEOUT;
var S_FADE_IN_TIMEOUT;
var S_FADE_OUT_TIMEOUT;

// image info class
function ImageInfo(href, rel, title, set) {
	this.href = href;
	this.rel = rel;
	this.title = title;
	this.set = set;
}


// HTML box

var htmlInject = '<div id="ImageViewer">' +
	'<div id="imageBorder">' +
    '<div id="imageBox">' +
	    '<img id="imageHandle" />' +
	    '<div id="loading">' +
	      '<a href="#" id="loadingImage" title="Loading: Click to close Image Viewer"><img src="images/controls/loading.gif" /></a>' +
		  '</div>' +
	  '</div>' +
	'</div>' +
	'<div id="infoBox">' +
	  '<div id="controlBox">' +
  		'<div id="imageNavigation">' +
  			'<a href="#" id="prevImage" title="Previous Image"><img src="images/controls/previmage.jpg" alt="Previous Image" /></a>' +
  			'<a href="#" id="nextImage" title="Next Image"><img src="images/controls/nextimage.jpg" alt="Next Image" /></a>' +
  			'<div id="imageTransNavigation">' +
  				'<a href="#" id="prevSet" title="Previous Set"><img src="images/controls/prevset.jpg" alt="Previous Set" /></a>' +
	    		'<a href="#" id="nextSet" title="Next Set"><img src="images/controls/nextset.jpg" alt="Next Set" /></a>' +
  			'</div>' +
      '</div>' +
	    '<div id="imageText">' +
	      '<span id="titleText"></span>' +
	      '<span id="setInfo"></span>' +
	    '</div>' +
	    '<div id="closeControl">' +
	    	'<table id="closeControlTable">' +
	    		'<tr>' +
	    			'<td><a href="#" id="firstImage" title="First Image"><img src="images/controls/firstimage.jpg" alt="First Image" /></a></td>' +
	    			'<td><a href="#" id="lastImage" title="Last Image"><img src="images/controls/lastimage.jpg" alt="Last Image" /></a></td>' +
	        	'<td><a href="#" id="imageViewerClose" title="Close Image Viewer"><img src="images/controls/close.jpg" alt="Close Image Viewer" /></a></td>' +
	        '</tr>' +
		    '</table>' +
	    '</div>' +
    '</div>' +
	'</div>' +
'</div>';


/*var htmlInject = '<div id="ImageViewer"><div id="imageBorder"><div id="imageBox"><img id="imageHandle" /><div id="loading"><a href="#" id="loadingImage" title="Loading: Click to close Image Viewer"><img src="images/controls/loading.gif" /></a></div></div></div><div id="infoBox"><div id="controlBox"><div id="imageNavigation"><a href="#" id="prevImage" title="Previous Image"><img src="images/controls/previmage.jpg" alt="Previous Image" /></a><a href="#" id="nextImage" title="Next Image"><img src="images/controls/nextimage.jpg" alt="Next Image" /></a><div id="imageTransNavigation"><a href="#" id="prevSet" title="Previous Set"><img src="images/controls/prevset.jpg" alt="Previous Set" /></a><a href="#" id="nextSet" title="Next Set"><img src="images/controls/nextset.jpg" alt="Next Set" /></a></div></div><div id="imageText"><span id="titleText"></span><span id="setInfo"></span></div><div id="closeControl"><table id="closeControlTable"><tr><td><a href="#" id="firstImage" title="First Image"><img src="images/controls/firstimage.jpg" alt="First Image" /></a></td><td><a href="#" id="lastImage" title="Last Image"><img src="images/controls/lastimage.jpg" alt="Last Image" /></a></td><td><a href="#" id="imageViewerClose" title="Close Image Viewer"><img src="images/controls/close.jpg" alt="Close Image Viewer" /></a></td></tr></table></div></div></div></div>';
*/


// Setup initilisation event
//document.write("lol1");
AddEvent('DOMContentLoaded', function () { initialiseImageViewer(); }, document); // starts imageviewer on load
//document.write("lol7");
// support ie's lack of standards
document.write('<script defer src="//:" id="IDonLoadDOMContent"><\/script>');
document.getElementById("IDonLoadDOMContent").onreadystatechange = function() {
  if (document.getElementById("IDonLoadDOMContent").readyState == "complete") {
    document.getElementById("IDonLoadDOMContent").onreadystatechange = null;
    initialiseImageViewer();
  } };
  
  
  


///// FUNCTION initialise() - sets up event listners and hides stuff not ment to be seen
function initialiseImageViewer() {
	// inject the HTML
	
	//var divElement = document.createElement('div');
	//divElement.id = "testdiv";
	//divElement.className = "blah";
	
	var newTag = GenerateTag("div", "backgroundShade", "none");

	//var body = document.getElementById('mainBody');
	var body = document.getElementsByTagName('body')[0];
	//newTag.id = "backgroundShade";
	body.appendChild(newTag);
	//document.body.appendChild(divElement);
	
	
	var newTag2 = GenerateTag("div", "ImageViewerWrapper", "");
	var body = document.getElementsByTagName('body')[0];
	body.appendChild(newTag2);
	
	
	var newTag3 = GenerateTag("div", "ImageViewer", "");

	//var body = document.getElementById('mainBody');
	//var body = document.getElementById('ImageViewer');
	//body.appendChild(newTag3);
	// add in the html text in this wrapper tag
	document.getElementById('ImageViewerWrapper').innerHTML = htmlInject;
	//document.getElementById('ImageViewer').innerHTML = "HIHIHIHIHIHIIH";
	//document.getElementById('testdiv').innerHTML = "HIHIHIHIHIHIIH";
	//document.getElementById("backgroundShade").style.display = 'none';
	
	// end of HTML injection
	
	// hide the imageViwer and background
	document.getElementById("ImageViewer").style.display = 'none';
	document.getElementById("backgroundShade").style.display = 'none';
	
	// setup basic imageViwer size
	document.getElementById("imageBorder").style.height = S_HEIGHT_SETUP + "px";
	document.getElementById("imageBorder").style.width = S_WIDTH_SETUP + "px";
	
	var linkNode;
	// start up all the event listeners
	AddEvent('click', function(event) { StopAction(event); StopViwer(); }, document.getElementById("backgroundShade"));
	AddEvent('click', function(event) { StopAction(event); if(eventTarget(event).id == 'ImageViewer') { StopViwer(); }}, document.getElementById("ImageViewer"));
	AddEvent('click', function(event) { StopAction(event); StopViwer(); }, document.getElementById("imageViewerClose"));
	AddEvent('mouseup', function(event) { StopAction(event); if(eventTarget(event).id == 'imageHandle') { StopViwer(); }}, document.getElementById("imageHandle"));
	AddEvent('click', function(event) { StopAction(event); StopViwer(); }, document.getElementById("loadingImage"));
	AddEvent('click', function(event) { StopAction(event); if(FindImage(S_PREV) == true) { updateImage(); } }, document.getElementById("prevImage"));
	AddEvent('click', function(event) { StopAction(event); if(FindImage(S_NEXT) == true) { updateImage(); } }, document.getElementById("nextImage"));
	AddEvent('click', function(event) { StopAction(event); if(FindImage(S_FIRST) == true) { updateImage(); } }, document.getElementById("firstImage"));
	AddEvent('click', function(event) { StopAction(event); if(FindImage(S_LAST) == true) { updateImage(); } }, document.getElementById("lastImage"));
	AddEvent('click', function(event) { StopAction(event); if(FindSet(S_PREV_SET) == true) { updateImage(); } }, document.getElementById("prevSet"));
	AddEvent('click', function(event) { StopAction(event); if(FindSet(S_NEXT_SET) == true) { updateImage(); } }, document.getElementById("nextSet"));
	AddEvent('click', function(event) { linkNode = GetEventLinkNode(eventTarget(event)); if(linkNode) { StopAction(event); updateArray(linkNode); } }, document);
}

///// FUNCTION eventTarget() - returns browser specific event target
function eventTarget(event) {
	if(event.target) {
		return event.target;
	}
	else {
		return event.srcElement;
	}
}

///// FUNCTION updateArray(element(an <a> tag)) - called on every click to a ImageViewer link, it fills the image array and displays the viewer box
function updateArray(imgInfo) {
	//KeybaordNavigationOn();
	S_CLOSE = false; // reset the close check just in case
	
	updateBackground();
	S_SHADE_IN = true;
	FadeIn(document.getElementById("backgroundShade"), S_SHADEFLAG, S_SHADE_OPACITY);
	
	
	imagesArray = []; // reset array
	
	var imageHref, imageRel, imageTitle;
	var sets;
	sets = 1; // primed for adding a set
	var setFound;
	setFound = false;
	imageHref = imgInfo.href;
	imageRel = imgInfo.rel;
	imageTitle = imgInfo.title;
	
	allElements = FindElementsRel("ImageViewer");
		
	imageHref = allElements[0].href;
  imageRel = allElements[0].rel;
  imageTitle = allElements[0].title;
	
	var imageIndex;
	imageIndex = 0;
	for(k=0;k < allElements.length;k++) {
		imageHref = allElements[k].href;
	  imageRel = allElements[k].rel;
	  imageTitle = allElements[k].title;
	  if(imageRel == 'ImageViewer') { // striaght image, no set name
	  	// add image source and title to an array with the set of 0
	  	imagesArray.push(new ImageInfo(imageHref, imageRel, imageTitle, 0));
	  }
	  else { // image is part of a set name so check for which set its part off
	  	var i;
	  	
	  	var staticLength = imagesArray.length;
	  	for(i=0;i < staticLength;i++) {
	  		if(imagesArray[i].set == 0) {
	  			// skip this image
	  		}
	  		else if(imageRel == imagesArray[i].rel) {
	  			// part of same set
	  			imagesArray.push(new ImageInfo(imageHref, imageRel, imageTitle, imagesArray[i].set));
	  			setFound = true;
	  			break;
	  		}
	  	}
	  	if(setFound == false) { // no matching set, add to array with new set
	 			imagesArray.push(new ImageInfo(imageHref, imageRel, imageTitle, sets));
	 			sets++;
	  	}
	  	setFound = false; // reprime the check
	  }
	}

	// sort the array
	ImgArraySortAsc();

	// initialise current image index
	for(i=0;i < imagesArray.length; i++) {
		if(imagesArray[i].href == imgInfo.href && imagesArray[i].rel == imgInfo.rel && imagesArray[i].title == imgInfo.title) {
			currentImage = i;
		}
	}

	imageViewerLocation = GetPageOffsets();

	document.getElementById("ImageViewer").style.top = imageViewerLocation[0] + (imageViewerLocation[2] / 30) + 'px'; // small gap at the top
	document.getElementById("ImageViewer").style.left = imageViewerLocation[1] + 'px'; // put viwer at scroll position if horizontal scroll is on
	document.getElementById("ImageViewer").style.display = '';
	
	updateImage();
}


///// FUNCTION updateImage() - loads and shows the current image (which should have been changed before this was called)
function updateImage() {
	// if close is set for resize then clear the timeout and reset the checks
	if(S_HEIGHT_CLOSE = true || S_WIDTH_CLOSE == true) {
		clearTimeout(S_HEIGHT_RESIZE_TIMEOUT);
		clearTimeout(S_WIDTH_RESIZE_TIMEOUT);
		clearTimeout(S_FADE_IN_TIMEOUT);
		clearTimeout(S_FADE_OUT_TIMEOUT);
		// stop animation of the box
    S_HEIGHT_CLOSE = false;
		S_WIDTH_CLOSE = false;
	}
  
  // show imageBox and the loading annimation but hide rest while it annimates
  document.getElementById("loading").style.display = '';
  document.getElementById("imageHandle").style.display = 'none';
  document.getElementById("infoBox").style.display = 'none';
  document.getElementById("setInfo").style.display = 'none';
  
  // bug: infoBox is not being hidden fast enough, try this
  //document.getElementById("infoBox").style.opacity = 0;
  setOpacity(document.getElementById("infoBox"), 0);

	// load up the img and resize background when its done
	var preLoadImg = new Image();
  preLoadImg.onload = function() {
    document.getElementById("imageHandle").style.opacity = 0; // solve flicker of image before annimation bug 
    document.getElementById("imageHandle").style.filter = "alpha(opacity=" + 0 + ")";
    document.getElementById("imageHandle").src = imagesArray[currentImage].href;
    resizeImageBox(preLoadImg.width, preLoadImg.height); };
  preLoadImg.src = imagesArray[currentImage].href;
}

///// FUNCTION resizeImageBox(int, int) - starts the resize animation
// this could easily go inside resizeImageViewer
function resizeImageBox(imageWidth, imageHeight) {
	var dimsArray = FindDimensions(document.getElementById("imageBorder"));
	var currentHeight = dimsArray[0];
	var currentWidth = dimsArray[1];

	if(!currentHeight) { // if the image box has bad data, reset to default
		currentHeight = S_HEIGHT_SETUP;
	}
	if(!currentWidth) {
		currentWidth = S_WIDTH_SETUP;
	}
	
	var newHeight = imageHeight + (S_BORDER_SIZE * 2);
	var newWidth = imageWidth + (S_BORDER_SIZE * 2);
	
	var heightDiff = currentHeight - newHeight;
	var widthDiff = currentWidth - newWidth;
	
	if(heightDiff != 0) {
		resizeImageViewer(document.getElementById("imageBorder"), heightDiff, S_RESIZE_SPEED, S_RESIZE_HEIGHT);
	}
	if(widthDiff != 0) {
		resizeImageViewer(document.getElementById("imageBorder"), widthDiff, S_RESIZE_SPEED, S_RESIZE_WIDTH);
	}
	
	
	if(newWidth < S_MIN_WIDTH) {
		document.getElementById("infoBox").style.width = S_MIN_WIDTH + "px";
	}
	else {
		document.getElementById("infoBox").style.width = newWidth + "px";
	}
  
  S_IMAGE_IN = true;
  // prime opacity to zero for the fade
  document.getElementById("imageHandle").style.opacity = 0;
  document.getElementById("imageHandle").style.filter = "alpha(opacity=" + 0 + ")";
  FadeIn(document.getElementById("imageHandle"), S_IMAGEFLAG, S_FULL_OPACITY);
  updateInfo();
  preLoadImages();
}
    
  

///// FUNCTION updateInfo() - updates set and title information
function updateInfo() {
	var imageHref, imageTitle; // temp vars that would have current image data in them
	imageHref = imagesArray[currentImage].href;
	imageRel = imagesArray[currentImage].rel;
	imageTitle = imagesArray[currentImage].title;
	setNum = imagesArray[currentImage].set;
	// show title string if it exists
	
	document.getElementById("titleText").innerHTML = ''; // clear html
	document.getElementById("setInfo").innerHTML = ''; // clear html
	
	if(imageTitle != "" && imageTitle) {
		document.getElementById("titleText").innerHTML = imageTitle;
		document.getElementById("titleText").style.display = '';
	}
	
	// this could be designed better to say the least...
	var setOrder;
	setOrder = 1;
	var setTotal;
	setTotal = 1;
	var tempOrder;
	tempOrder = 1;
	var setString;
	var stringEnd;
	var imageString;
	var span = "</span>";
	var boldStart = '<span class="boldSpan">';
	
	var i;
	for(i in imagesArray) {
  	if(imagesArray[i].href == imageHref && imagesArray[i].rel == imageRel && imagesArray[i].title == imageTitle) {
  		setOrder = tempOrder;
  	}
		else if(imagesArray[i].set == setNum) { // increase the nums if find a matching set
			tempOrder++;
			setTotal++;
		}
  }
	 
	// display set info: "Image 3 of 5 in Image Set 2" etc
	if(setNum > 0) { // in a real set
		imageString = " in Set ";
		
		// in case we want to see the set names
		if(S_SHOW_SET_NAMES == true) {
			stringEnd = imagesArray[currentImage].rel.substring(12, (imagesArray[currentImage].rel.length - 1));
			// if browser does this diffrently take off trialing bracket
			//document.write(stringEnd.substring(7, 8));
			//document.write(stringEnd.length);
			//document.write(stringEnd.substring(stringEnd.length - 1, stringEnd.length));
			var pos = stringEnd.lastIndexOf("]")
			if(pos != -1) {
				stringEnd = stringEnd.substring(0, pos);
			}
			/*if(stringEnd.substring(imagesArray[currentImage].rel.length - 1, imagesArray[currentImage].rel.length) == "]") {
				stringEnd = stringEnd.substring(12, (imagesArray[currentImage].rel.length - 1));
			}*/
		}
		else {
			stringEnd = setNum;
		}
		
	}
	else {
		imageString = "";
		stringEnd = " unrelated images";
		boldStart = "";
		span = "";
	}
	
	if(S_BOLD_IMAGE_STRING == true) {
		setString = 'Image <span class="boldSpan">' + setOrder + '</span> of <span class="boldSpan">' + setTotal + '</span>' + imageString + boldStart + stringEnd + span;
	}
	else {
		setString = "Image " + setOrder + " of " + setTotal + imageString + stringEnd;
	}
	
	document.getElementById("setInfo").innerHTML = setString;
	document.getElementById("setInfo").style.display = '';
	
	// fade in the data box
	S_INFO_IN = true;
	// prime opacity to zero for the fade
	document.getElementById("infoBox").style.opacity = 0;
	document.getElementById("infoBox").style.filter = "alpha(opacity=" + 0 + ")";
	FadeIn(document.getElementById("infoBox"), S_INFOFLAG, S_FULL_OPACITY);
	updateBackground();
  updateNavigationState();
}
    
    

///// FUNCTION updateNavigationState() - makes prev/next buttons grey or normal if they can be used or not
function updateNavigationState() {
	setData = FindSetOrder(); // 0 = set order, 1 = number in that set, 2 = max number of sets
	// vars to make it easier to read above set order array
	var setOrder = 0;
	var setTotal = 1;
	var setMax = 2;
	var setZero = 3;

	if(currentImage > 0) { // nothing before this image
		if(setData[setOrder] > 1 || S_ALWAYS_NAV == true) { // part of a set or nav always on
			setOpacity(document.getElementById("prevImage"), 1);
			setOpacity(document.getElementById("firstImage"), 1);
			//document.getElementById("prevImage").style.opacity = 1;
			//document.getElementById("firstImage").style.opacity = 1;
			//document.getElementById("text").value += "1.\n"
		}
	}
	else {
		setOpacity(document.getElementById("prevImage"), 0.2);
		setOpacity(document.getElementById("firstImage"), 0.2);
		//document.getElementById("firstImage").style.filter = "alpha(opacity=" + 20 + ")";
		//document.getElementById("prevImage").style.opacity = 0.2;
		//document.getElementById("firstImage").style.opacity = 0.2;
		//document.getElementById("text").value += "2.\n"
	}
	if(currentImage < imagesArray.length - 1) {
		if(setData[setOrder] < setData[setTotal] || S_ALWAYS_NAV == true) { // part of a set or nav always on
			setOpacity(document.getElementById("nextImage"), 1);
			setOpacity(document.getElementById("lastImage"), 1);
			//document.getElementById("nextImage").style.opacity = 1;
			//document.getElementById("lastImage").style.opacity = 1;
			//document.getElementById("text").value += "3.\n"
		}
	}
	else {
		setOpacity(document.getElementById("nextImage"), 0.2);
		setOpacity(document.getElementById("lastImage"), 0.2);
		//document.getElementById("nextImage").style.opacity = 0.2;
		//document.getElementById("lastImage").style.opacity = 0.2;
		//document.getElementById("text").value += "4.\n"
	}
	if(imagesArray[currentImage].set <= 0 || setData[setZero] == false) { // first 'set' so grey out previous set link
		setOpacity(document.getElementById("prevSet"), 0.2);
		//document.getElementById("prevSet").style.opacity = 0.2;
		//document.getElementById("text").value += "5.\n"
	}
	else {
		setOpacity(document.getElementById("prevSet"), 1);
		//document.getElementById("prevSet").style.opacity = 1;
		//document.getElementById("text").value += "6.\n"
	}
	if(imagesArray[currentImage].set >= setData[setMax] && imagesArray[currentImage].set != 0) { // last set so grey out next set link
		setOpacity(document.getElementById("nextSet"), 0.2);
		//document.getElementById("nextSet").style.opacity = 0.2;
		//document.getElementById("text").value += "7.\n"
	}
	else {
		setOpacity(document.getElementById("nextSet"), 1);
		//document.getElementById("nextSet").style.opacity = 1;
		//document.getElementById("text").value += "8.\n"
	}
	// hide set buttons if less than two sets
	if(setData[setMax] < 2) { // last set so grey out next set link
		document.getElementById('nextSet').style.display = 'none';
		document.getElementById('prevSet').style.display = 'none';
	}
	else {
		document.getElementById('nextSet').style.display = '';
		document.getElementById('prevSet').style.display = '';
	}
	
  //KeybaordNavigationOn();
  var t = setTimeout(function() {KeybaordNavigationOn();}, 500) // wait half a second then start keyboard event listener
}

///// FUNCTION setOpacity(element, int) - set the transparancy of passed element, browser specific
function setOpacity(DOMElement, value) {
	DOMElement.style.opacity = value;
	value = Math.round(value * 100);
	if(value > 100) {
		value = 100;
	}
	if(value < 0) {
		value = 0;
	}
	DOMElement.style.filter = "alpha(opacity=" + value + ")";
	/*document.getElementById("text").value += "ID: " + DOMElement.id + "\n";
	document.getElementById("text").value += value + "\n";
	document.getElementById("text").value += DOMElement.style.filter + "\n";
	document.getElementById("text").value += "\n";*/
}


///// FUNCTION keyboardHandler(event) - checks what key was pressed and sends appropriate actions
function keyboardHandler(event) {
	/*keyCodes:
	< = 188
	> = 190
	[ = 219
	] = 221
	left arrow = 37
	right arrow = 39
	escape = 27
	*/
	
  var keyCodeId = event.keyCode;
  var escapeCodeId;
  var keyString;
  
	if(event.DOM_VK_ESCAPE) { // are we useing flashy new standards?
		escapeCodeId = event.DOM_VK_ESCAPE;
	}
	else { // no we are probably using IE...
		escapeCodeId = 27;
	}
		
	// this dosn't work for non letters/numbers most of the time so have to rely on codes for them
  keyString = String.fromCharCode(keyCodeId).toLowerCase();
  if(keyString == "x" || keyCodeId == escapeCodeId) { // close imageviewer
    StopAction(event);
    StopViwer();
  } 
  else if(keyString == 'p' || keyCodeId == 37) { // prev image
    if(FindImage(S_PREV) == true) {
      StopAction(event);
      KeybaordNavigationOff();
      updateImage();
      //document.getElementById("text").value += "1\n";
      //KeybaordNavigationOn();
    }
  } 
  else if(keyString == 'n' || keyCodeId == 39) { // next image
    if(FindImage(S_NEXT) == true) {
      StopAction(event);
      KeybaordNavigationOff();
      updateImage();
       //document.getElementById("text").value += "2\n";
       //KeybaordNavigationOn();
    }
  }
	else if(keyCodeId == 219 || keyCodeId == 188) { // prev set
  	if(FindSet(S_PREV_SET) == true) {
  		StopAction(event);
  		KeybaordNavigationOff();
  		updateImage();
  		 //document.getElementById("text").value += "3\n";
  		 //KeybaordNavigationOn();
  	}
  }
  else if(keyCodeId == 221 || keyCodeId == 190) { // next set
  	if(FindSet(S_NEXT_SET) == true) {
  		StopAction(event);
  		KeybaordNavigationOff();
  		updateImage();
  		 //document.getElementById("text").value += "4\n";
  		 //KeybaordNavigationOn();
  		 
  	}
  }
}

///// FUNCTION preLoadImages() - preloads one image forward and behind the current image as the most likely action
function preLoadImages() {
	var preLoadPrevImg;
	var preLoadNextImg;
	
	if(currentImage > 0) { // prev image exists
		preLoadPrevImg = new Image();
		preLoadPrevImg.src = imagesArray[currentImage - 1].href;
	}
	if(currentImage < imagesArray.length - 1) { // next image exists
		preLoadNextImg = new Image();
		preLoadNextImg.src = imagesArray[currentImage + 1].href;
	}
}


///// FUNCTION resizeContainer(element, int, int, flag(int)) - initialises and sets up for calling the repeating resize code
function resizeImageViewer(DOMelement, diffrence, resizeRate, dim) {
	// resizing state
	if(dim <= 0) { // height
		S_H_RESIZE_FIN = false;
	}
	if(dim > 0) { // width
		S_W_RESIZE_FIN = false;
	}
	
	var amount;
	amount = diffrence * -1; // reverse the sign on the number
	
	var scale = 1000; // thousand miliseconds, one second
	var interval = scale / S_UPDATES_PER_SECOND;
	
	var newSize;
	if(dim <= 0) { // height
		newSize = parseFloat(DOMelement.style.height);
	}
	if(dim > 0) { // width
		newSize = parseFloat(DOMelement.style.width);
	}
	var targetSize;
	targetSize = newSize + amount;
	
	
	
	var down;
	down = true; // default direction
	if(targetSize < newSize) {
		down = false; // set direction
	}
	
	if(targetSize < S_MIN_WIDTH && dim > 0) {
		targetSize = S_MIN_WIDTH;
	}
	
	var increment;
	if(amount < 0) {
		increment = Math.round((amount * -1) * (resizeRate / 100)); //((amount * -1) / updates).round();
	}
	else {
		increment = Math.round(amount * (resizeRate / 100));
	}

	if(increment > S_MAX_INCR) {
		increment = S_MAX_INCR; // don't allow over max increment
	}
	if(increment < S_MIN_INCR) {
		increment = S_MIN_INCR; // don't allow less than min increment
	}

	if(dim <= 0) { // height
		S_HEIGHT_RESIZE_TIMEOUT = setTimeout(function() {resize(DOMelement, interval, increment, targetSize, down, dim);}, interval)
	}
	if(dim > 0) { // width
		S_WIDTH_RESIZE_TIMEOUT = setTimeout(function() {resize(DOMelement, interval, increment, targetSize, down, dim);}, interval)
	}
}


///// FUNCTION resize(element, int, int, int, bool, flag(int)) - resizes the passed in element
function resize(DOMelement, interval, increment, targetSize, down, dim) {
	// absolute stop check	
	if(dim <= 0) { // height
		if(S_HEIGHT_CLOSE == true) {
			S_HEIGHT_CLOSE = false;
			return;
		}
	}
	else if(dim > 0) { // width
		if(S_WIDTH_CLOSE == true) {
			S_WIDTH_CLOSE = false;
			return;
		}
	}
	
	// get new size
	if(dim <= 0) { // height
		size = parseFloat(DOMelement.style.height);
	}
	else if(dim > 0) { // width
		size = parseFloat(DOMelement.style.width);
	}
	
	// stop if the next update will go over the target
	if(size >= targetSize && down == true) { // down check
		if(dim <= 0) { // height
			DOMelement.style.height = targetSize + 'px';
			S_H_RESIZE_FIN = true;
		}
		else if(dim > 0) { // width
			DOMelement.style.width = targetSize + 'px';
			S_W_RESIZE_FIN = true;
		}
		return;
	}
	if(size <= targetSize && down == false) { // up check
		if(dim <= 0) { // height
			DOMelement.style.height = targetSize + 'px';
			S_H_RESIZE_FIN = true;
		}
		else if(dim > 0) { // width
			DOMelement.style.width = targetSize + 'px';
			S_W_RESIZE_FIN = true;
		}
		return;
	}
	
	increment = slow(targetSize, size, increment);
	
	
	var newSize;
	if(down == true) {
		newSize = size + increment;
	}
	if(down == false) {
		newSize = size - increment;
	}
	if(dim <= 0) { // height
		DOMelement.style.height = newSize + 'px';
	}
	else if(dim > 0) { // width
		DOMelement.style.width = newSize + 'px';
	}
	
	updateBackground();
	
	if(dim <= 0) { // height
		S_HEIGHT_RESIZE_TIMEOUT = setTimeout(function() {resize(DOMelement, interval, increment, targetSize, down, dim);}, interval)
	}
	if(dim > 0) { // width
		S_WIDTH_RESIZE_TIMEOUT = setTimeout(function() {resize(DOMelement, interval, increment, targetSize, down, dim);}, interval)
	}
}


///// FUNCTION slow(int, int, int) - reduce increment size to slow down the animation speed of the resize, its called every 'frame'
function slow(target, size, incra) {
	var x;
	var y;
	
	y = target - size;
	
	if(y < 0) {
		y = y * -1;
	}
	
	x = y / incra;
	x = x / S_SLOW_SCALE;
	
	x = x * incra;
	if(x < S_MIN_INCR) {
		x = S_MIN_INCR;
	}
	if(x > incra) {
		x = incra
	}
	x = Math.round(x);
	return x;
}


///// FUNCTION FadeIn(element, flag(int), float(0-1)) - fades in the selected element, you can pass in a value as a final value
function FadeIn(DOMelement, flag, finalValue) {
	if((flag == S_IMAGEFLAG && S_IMAGE_IN == false) || (flag == S_INFOFLAG && S_INFO_IN == false) || (flag == S_SHADEFLAG && S_SHADE_IN == false)) {
		return; // the fade is complete so run no more code
	}
	if((S_H_RESIZE_FIN == false || S_W_RESIZE_FIN == false) && flag != S_SHADEFLAG) {
		if(flag == S_SHADEFLAG) { // the background is a special case
			S_FADE_IN_TIMEOUT_BACK = setTimeout(function() {FadeIn(DOMelement, flag, finalValue);}, 50)
		}
		else { 
			S_FADE_IN_TIMEOUT = setTimeout(function() {FadeIn(DOMelement, flag, finalValue);}, 50)
		}
		return;
	}

	var newOpacity;
	newOpacity = parseFloat(DOMelement.style.opacity) + S_OPACITY_INCR;
	if(!newOpacity && newOpacity != 0) { // try again with filter for IE
		newOpacity = (parseFloat(DOMelement.style.filter) / 100) + S_OPACITY_INCR;
	}
	if(!newOpacity && newOpacity != 0) {
		newOpacity = 0;
	}
	
	// hide the loading animation
	if(flag == S_IMAGEFLAG) {
		document.getElementById('loading').style.display = 'none';
	}

	// update images opacity THEN show it (prevent flicker in this order)
	//DOMelement.style.opacity = newOpacity;
	//DOMelement.style.filter = "alpha(opacity=" + newOpacity + ")";
	setOpacity(DOMelement, newOpacity);
	DOMelement.style.display = '';
	
	updateBackground();
	if(S_CLOSE == true) {
		// emergency close
		return;
	}
	
	if(newOpacity >= 0.99 || newOpacity == finalValue) { // max visability reahed, stop the loop
		//DOMelement.style.opacity = finalValue;
		setOpacity(DOMelement, finalValue);
		switch (flag) {
		case S_IMAGEFLAG:
			S_IMAGE_IN = false;
			break;
		case S_INFOFLAG:
			S_INFO_IN = false;
			break;
		case S_SHADEFLAG:
			S_SHADE_IN = false;
			break;
		}
		return;
	}
	if(flag == S_SHADEFLAG) { // the background is a special case
		S_FADE_IN_TIMEOUT_BACK = setTimeout(function() {FadeIn(DOMelement, flag, finalValue);}, 50)
	}
	else { 
		S_FADE_IN_TIMEOUT = setTimeout(function() {FadeIn(DOMelement, flag, finalValue);}, 50)
	}
}


///// FUNCTION FadeOut(element, flag(int)) - Fades out the passed in element
function FadeOut(DOMelement, flag) {
	if((flag == S_IMAGEFLAG && S_IMAGE_OUT == false) ||	(flag == S_INFOFLAG && S_INFO_OUT == false) || (flag == S_SHADEFLAG && S_SHADE_OUT == false)) {
		return; // the fade is complete so run no more code
	}

	var newOpacity;
	newOpacity = parseFloat(DOMelement.style.opacity) - S_OPACITY_INCR;
	if(!newOpacity && newOpacity != 0) { // try again with filter for IE
		newOpacity = (parseFloat(DOMelement.style.filter) / 100) + S_OPACITY_INCR;
	}
	
	if(!newOpacity && newOpacity != 0) {
		newOpacity = 1.0;
	}
	
	if(newOpacity < 0) {
		newOpacity = 0.0;
	}
	
	if(newOpacity <= 0.0) { // image is invisable, stop the loop
		//DOMelement.style.opacity = 0.0;
		setOpacity(DOMelement, 0);
		DOMelement.style.display = 'none';
		switch (flag) {
		case S_IMAGEFLAG:
			S_IMAGE_OUT = false;
			break;
		case S_INFOFLAG:
			S_INFO_OUT = false;
			break;
		case S_SHADEFLAG:
			S_SHADE_OUT = false;
			break;
		}
		return;
	}
	
	//DOMelement.style.opacity = newOpacity;
	setOpacity(DOMelement, newOpacity);
	S_FADE_OUT_TIMEOUT = setTimeout(function() {FadeOut(DOMelement, flag);}, S_FADEOUT_TIME)
}


///// FUNCTION updateBackground() - resizes the background shading to make sure its still reflects the page size
function updateBackground() {
	var backgroundSize = GetBackgroundSize();
	document.getElementById("backgroundShade").style.height = backgroundSize[0] + 'px';
	document.getElementById("backgroundShade").style.width = backgroundSize[1] + 'px';
}


///// FUNCTION FindElementsRel(string) - looks for any link (a, area) elements with the proper rel (which is passed in)
function FindElementsRel(rel){
	var aElements = [];
  aElements = document.getElementsByTagName("a");
  areaElements = document.getElementsByTagName("area");
  matchedRel = [];
  
  var imageHref;
	var imageRel;
	var imageTitle;
  var i;
  var elRel;
  for (i in aElements) {
    if (aElements[i].rel != null && aElements[i].rel != "") {
    	elRel = aElements[i].rel.toLowerCase();
    	
    	if (elRel.match(rel.toLowerCase()) != null) {
    		imageHref = aElements[i].href;
		  	imageRel = aElements[i].rel;
		  	imageTitle = aElements[i].title;
		  		
        matchedRel.push(new ImageInfo(imageHref, imageRel, imageTitle, 0));
    	}
    }
  }
  for (i in areaElements) {
    if (areaElements[i].rel != null && areaElements[i].rel != "") {
    	elRel = areaElements[i].rel.toLowerCase();
    	
    	if (elRel.match(rel.toLowerCase()) != null) {
    		imageHref = areaElements[i].href;
		  	imageRel = areaElements[i].rel;
		  	imageTitle = areaElements[i].title;
		  		
        matchedRel.push(new ImageInfo(imageHref, imageRel, imageTitle, 0));
    	}
    }
  }
	return matchedRel;
}


///// FUNCTION FindSetOrder() - retuns an array with 3 elements, 1st the current array set, 2nd the number of images in that set and the 3rd the total number of sets
function FindSetOrder() {
	var imageHref, imageRel, imageTitle, setNum; // temp vars that would have current image data in them
	imageHref = imagesArray[currentImage].href;
	imageRel = imagesArray[currentImage].rel;
	imageTitle = imagesArray[currentImage].title;
	setNum = imagesArray[currentImage].set;
    	
	var maxSets;
	maxSets = 0;
	var setOrder;
	setOrder = 1;
	var setTotal;
	setTotal = 1;
	var tempOrder;
	tempOrder = 1;
	var setZeroDetected;
	setZeroDetected = false;
	var results = [];
	
	
	// show the set string
  if(setNum > 0) { // set exists
  	var i;
  	for(i=0; i < imagesArray.length; i++) {
    	if(imagesArray[i].href == imageHref && imagesArray[i].rel == imageRel && imagesArray[i].title == imageTitle) { // assign the set order of the curernt image
    		setOrder = tempOrder;
    	}
  		else if(imagesArray[i].set == setNum && setNum != 0) { // increase the nums if find a matching set
  			tempOrder++;
  			setTotal++;
  		}
  		if(imagesArray[i].set > maxSets) { // find total number of sets
  			maxSets = imagesArray[i].set;
  		}
  		if(imagesArray[i].set == 0) { // there is images with no set in the array
  			setZeroDetected = true;
  		}
    }
  }
  results[0] = setOrder;
  results[1] = setTotal;
  results[2] = maxSets;
  results[3] = setZeroDetected;
  return results;
}


///// FUNCTION FindImage(int) - int is a flag for prev, next, first and last
function FindImage(flag) {
	oldIndex = currentImage; // setup testing varaible
	if(currentImage > 0 && flag == S_PREV) { // prev
		if(imagesArray[currentImage].set > 0) { // part of a set
			// search for prev image in array with the same set from the current index
			for(i=currentImage-1; i >= 0; i--) {
				if(imagesArray[i].set == imagesArray[currentImage].set) { // match found
					currentImage = i;
					return true;
				}
			}
		}
		if(oldIndex == currentImage) { // nothing was changed so do default action
			currentImage -= 1;
			return true;
		}
	}
	else if(currentImage < imagesArray.length - 1 && flag == S_NEXT) {
		if(imagesArray[currentImage].set > 0) { // part of a set
			// search for prev image in array with the same set from the current index
			for(i=currentImage+1; i < imagesArray.length; i++) {
				if(imagesArray[i].set == imagesArray[currentImage].set) { // match found
					currentImage = i;
					return true;
				}
			}
		}
		if(oldIndex == currentImage) { // nothing was changed so do default action
			currentImage += 1;
			return true;
		}
	}
	else if(currentImage > 0 && flag == S_FIRST) {
		currentImage = 0;
		return true;
	}
	else if(currentImage < imagesArray.length - 1 && flag == S_LAST) {
		currentImage = imagesArray.length - 1;
		return true;
	}
	return false;
}


///// FUNCTION FindSet(int) - find the first instance of a set forward or backwards depending on passed int flag
function FindSet(flag) {
	oldSet = imagesArray[currentImage].set; // setup testing varaible
	if(flag == S_PREV_SET) { // prev set
		for(i=0; i < imagesArray.length; i++) {
			if(oldSet - 1 == imagesArray[i].set) { // found match
				currentImage = i;
				return true;
			}
		}
	}
	else if(flag == S_NEXT_SET) {
		for(i=0; i < imagesArray.length; i++) {
			if(oldSet + 1 == imagesArray[i].set) { // found match
				currentImage = i;
				return true;
			}
		}
	}
	return false;
}

		
///// FUNCTION ImgArraySortAsc() - sorts the image array in asscending order in relation to the set value
function ImgArraySortAsc() {
	var count = imagesArray.length;
	var a, b;
	var t;
	
	for(a=0; a < count; a++) {
		for(b=0; b < count-1; b++) {
			if(imagesArray[b].set > imagesArray[b+1].set) {
				t = imagesArray[b];
				imagesArray[b] = imagesArray[b+1];
				imagesArray[b+1] = t;
			}
			/*else { // can't go any further
				break;
			}*/
		}
	}
}


///// FUNCTION GetEventLinkNode(element) - check all the parent nodes of passed event element to find the one that we need (a/area)
function GetEventLinkNode(eventElement) {
	 while(eventElement.parentNode) {
		if(eventElement.rel && eventElement.nodeType == 1 && (eventElement.tagName == "A" || eventElement.tagName == "AREA")) {
			if(eventElement.rel != null && eventElement.rel != "") {
				elRel = eventElement.rel.toLowerCase();
				rel = "ImageViewer";
				if(elRel.match(rel.toLowerCase()) != null) { // click was an image link
					return eventElement;
				}
			}
		}
		eventElement = eventElement.parentNode;
	}
	return false;
}


// FUNCTION GetBackgroundSize() - returns the size of the page for the background (array with two values)
function GetBackgroundSize() {
	var heightOffset;
	var widthOffset;
	var winWidth;
	var winHeight;
	var backgroundHeight;
	var backgroundWidth;
	
	//document.getElementById("text").value += "getBackgroundsize caleed" + "\n";
	    
	// find window dimensions using standard values
	if(window.innerWidth) {
		winHeight = window.innerHeight;
		if(document.documentElement.clientWidth) { // make sure this works
			winWidth = document.documentElement.clientWidth;
		}
		else {
			winWidth = window.innerWidth;
		}
	}
	else if(document.documentElement && document.documentElement.clientHeight) {
		winHeight = document.documentElement.clientHeight;
		winWidth = document.documentElement.clientWidth;
	}
	else if(document.body) {
		winHeight = document.body.clientHeight;
		winWidth = document.body.clientWidth;
	}
	
	
	// find window dimensions using scroll values
	if(window.scrollMaxY && window.innerHeight) { // check basic version works
		heightOffset = window.scrollMaxY + window.innerHeight;
		widthOffset = window.scrollMaxX + window.innerWidth;
	}
	else if(document.documentElement.scrollHeight > document.documentElement.offsetHeight) {
		heightOffset = document.documentElement.scrollHeight;
		widthOffset = document.documentElement.scrollWidth;
	}
	else if(document.body.scrollHeight > document.body.offsetHeight) {
		heightOffset = document.body.scrollHeight;
		widthOffset = document.body.scrollWidth;
	}
	else { // every other case
		heightOffset = document.body.offsetHeight;
		widthOffset = document.body.offsetWidth;
	}
	
	/*if(heightOffset >= document.body.clientHeight || heightOffset >= document.documentElement.clientHeight) {
		heightOffset += document.body.scrollTop; // support browsers who don't return entire document height
	}*/
	
	//document.getElementById("text").value += "scoll offset - top: " + document.body.scrollTop + "\n";
	
	//document.getElementById("text").value += "winvalues - innerHeight: " + window.innerHeight + " clientHeight: " + document.documentElement.clientHeight + " body.clientHeight " + document.body.clientHeight + "\n";
	
	//document.getElementById("text").value += "scrollvalues - scrooly: " + window.scrollMaxY + " body.scrollHeight: " + document.body.scrollHeight + " body.offsetHeight " + document.body.offsetHeight + "\n";
	
	// find the biggest height so that it covers the whole page
	if(winHeight > heightOffset) {
		backgroundHeight = winHeight;
	}
	else {
		backgroundHeight = heightOffset;
	}
	
	// find the smallest width to avoid the horizontal scroll bar popping up on some pages
	if(winWidth > widthOffset) {
		backgroundWidth = widthOffset;
	}
	else {
		backgroundWidth	= winWidth;
	}
	
	//document.getElementById("text").value += "New values - Height: " + backgroundHeight + " Width: " + backgroundWidth + "\n";
	return [backgroundHeight, backgroundWidth];
}


///// FUNCTION GetPageOffsets() - returns the top and left offsets as well as width and height
function GetPageOffsets() {
	var top;
	var left;
	var heigth;
	var width;
	
	if(window.pageYOffset) {
		top = window.pageYOffset;
		left = window.pageXOffset;
	}
	else if(document.documentElement.scrollTop) {
		top = document.documentElement.scrollTop;
		left =  document.documentElement.scrollLeft;
	}
	else {
		top = document.body.scrollTop;
		left = document.body.scrollLeft;		
	}

	heigth = document.body.offsetHeight;
	width = document.body.offsetWidth;
	
	return [top, left, heigth, width];//{top: top, left: left, heigth: heigth, width: width};
}


///// FUNCTION FindDimensions(element) - gets the width and height of passed element. Returns array, first is height second is width.
function FindDimensions(DOMelement) {
	// temp vars
	var vis = DOMelement.style.visibility;
	var pos = DOMelement.style.position;
	var dis = DOMelement.style.display;
	
	DOMelement.style.visibility = "hidden";
	DOMelement.style.position = "absolute";
	DOMelement.style.display = "block";
	
	var height = DOMelement.clientHeight;
	var width = DOMelement.clientWidth;
	
	DOMelement.style.visibility = vis;
	DOMelement.style.position = pos;
	DOMelement.style.display = dis;
	
	return [height, width];
}


///// FUNCTION AddEvent(string, function, element) - adds an event listener to the element passed in that calls the function passed in
function AddEvent(eventType, actions, DOMelement) {
	// if no actions then return false
	if(!actions) {
		return false;
	}
	
	// check if new event listner is supported, otherwise use old one
  if(DOMelement.addEventListener) {
    DOMelement.addEventListener(eventType, actions, false);
  }
  else {
  	if(eventType == "DOMContentLoaded") { // other browser support
			eventType = "load";
		}
    DOMelement.attachEvent("on" + eventType, actions);
  }
}


///// FUNCTION RemoveEvent(string, function, element) - removes an event listener on the element passed in
function RemoveEvent(eventType, actions, DOMelement) {
	if(DOMelement.removeEventListener) {
    DOMelement.removeEventListener(eventType, actions, false);
  }
  else {
    DOMelement.detachEvent("on" + eventType, actions);
  }
}


///// FUNCTION StopPropagate(event) - stop event going further combined with stop action
/*function StopPropagate(ourEvent) {
	if(ourEvent && ourEvent.stopPropogation) {
		ourEvent.stopPropogation();
	}
	else if(window.event && window.event.cancelBubble) {
		window.event.cancelBubble = true;
	}
}*/


///// FUNCTION StopAction(event) - stop event doing what it wants to (like following a link)
function StopAction(ourEvent) {
	if(ourEvent && ourEvent.preventDefault) {
		ourEvent.preventDefault();
	}
	else if(window.event) {
		window.event.returnValue = false;
	}
	if(ourEvent && ourEvent.stopPropogation) {
		ourEvent.stopPropogation();
	}
	else if(window.event) {
		window.event.cancelBubble = true;
	}
}


///// FUNCTION KeybaordNavigationOn() - start looking for keybaord input
function KeybaordNavigationOn() {
	AddEvent("keydown", keyboardHandler, document);
}


///// FUNCTION KeybaordNavigationOff() - stop accepting keyboard input
function KeybaordNavigationOff() {
	RemoveEvent("keydown", keyboardHandler, document);
}


///// FUNCTION StopViwer() - stops the imageviwer and makes everything disapear
function StopViwer() {
	//hide the ImageViwer
	document.getElementById("ImageViewer").style.display = 'none';
	KeybaordNavigationOff();
	// close any fade in etc
  S_CLOSE = true;
  S_HEIGHT_CLOSE = true;
  S_WIDTH_CLOSE = true;
  
  
  // stop any cued actions
  clearTimeout(S_HEIGHT_RESIZE_TIMEOUT);
	clearTimeout(S_WIDTH_RESIZE_TIMEOUT);
	clearTimeout(S_FADE_IN_TIMEOUT);
	clearTimeout(S_FADE_OUT_TIMEOUT);
	
	// fade out the background
	S_SHADE_OUT = true;
  FadeOut(document.getElementById("backgroundShade"), S_SHADEFLAG);
}

///// FUNCTION GenerateTag(string, string array) - stops the imageviwer and makes everything disapear
function GenerateTag(genTagName, idName, displayState) {
  var tagParent = document.createElement(genTagName);
  
  // use a try block instead
  try {
    tagParent.innerHTML = '<' + genTagName + '></' + genTagName + '>';
  } 
  catch(exception) {
  }
  var finalTag = tagParent.firstChild || null;
  
  // if we created a tag but browser put another set around them (names will be diffrent)
  // always use lower case, otherwise it thinks its diffrent sometimes
  if(finalTag && (finalTag.tagName.toLowerCase() != genTagName)) {
  	// tag should exist so just get it from the page
    finalTag = element.getElementsByTagName(genTagName)[0];
  }
  
  // if it still dosn't work then use the createElement method alone, works in some places
  if(!finalTag) {
  	finalTag = document.createElement(genTagName);
  }
  
  // return nothing if it didn't work, probably will generate an excepetion when it uses it though - add a try block to that?
  if(!finalTag) {
  	return;
  }
  
  
  // add the id
  if(idName) {
  	finalTag.id = idName;
	}
	
	// set up the visability
	if(displayState) {
  	finalTag.style.display = displayState;
	}
	
  return finalTag;
}