// STABLE 

function hopJSGallery(containerID, xmlImageSource) {
	this.imageArray = [ ];
  this.thumbArray = [ ];
	this.containerID = containerID;
  this.containerObj = document.getElementById(this.containerID);
  this.containerObj.unselectable = true; 
  this.containerObj.style.MozUserSelect = "none";
	this.containerObj.style.KhtmlUserSelect = "none";
  this.containerObj.style.cursor = "default";
  this.containerObj.style.position = "relative";
  this.imageBaseUrl = "http://www.jessicajones.co.nz/media/images/gallery/";
	//this.imageBaseUrl = "http://gavin/~paul/jessica/media/gallery";
  this.ajaxLoaderHref = this.imageBaseUrl + "ajax-loader.gif";
  this.xmlBaseUrl = "http://www.jessicajones.co.nz/galleryxml.php/weddings/gallery/xml/attr/gallery4/";
  //this.xmlBaseUrl = "file:///C:/Users/Jones/Documents/Jessica%20Jones%20Photography%20Ltd/Website/media/xml/";
	//this.xmlBaseUrl = "http://gavin/~paul/jessica/galleryxml.php/weddings/gallery/xml/attr/gallery4/";
  this.scrollbarImagesObj = null;
  this.scrollbarObj = null;
  this.viewportObj = null;
  
	// depreciate
	this.mainImageImgObj = null;
	this.loadImageArray = [ ];
	this.imageObjArray = [ ];
	this.imagePositionArray = {"left":0, "centre":1, "right":2};
  this.imageCoordinates = {"left": {"x" : 0, "y" : 0}, "centre": {"x" : 0, "y" : 0}, "right": {"x" : 0, "y" : 0} };
  this.imageTransitionDefault = "cubic-bezier(0.15,0,0,1) 500ms";
  this.imageTransitionTime = 200;
  this.SBTransitionDefault = "ease 250ms";
			
  this.loadingDivObj = null;
	this.diagTextObj = null;
  this.mainImageCache = [ ];
  this.xmlImageSource = this.xmlBaseUrl + xmlImageSource + "/gallery.xml";
  this.nextImg = null;
  this.imageNo = -1;
  this.loadScrollbarImageNo = -1;
  this.loadSBImg = null;
  this.loadCacheImg = new Image();
	var self = this;
	this.loadCacheImg.onload = function() { self.cacheImageLoaded(this); };
  
  this.SBImages = new Array();
  this.CachedImages = new Array();
  this.cacheImageNo = 0;
  this.nextSBLeft = 0;
  this.imageFadeValue = 50;
  this.imageNotLoadedFadeValue = 20;
  this.scrollbarWidth = 0;
  this.scrollbarRight = 0;
  this.scrollSwipeStartX = 0;
  this.leftArrow = null;
  this.rightArrow = null;
	this.lastDragX = 0;
	this.lastDragTime = 0;
  this.loadingImage = null;
  this.pauseDisplay = false;

  // Set Item Sizes
	this.scrollbarHeight = 60;
  this.viewportHeight =  this.containerObj.offsetHeight - this.scrollbarHeight - 20 - this.stripPX(this.containerObj.style.borderTopWidth);
  this.viewportWidth = this.containerObj.offsetWidth - this.stripPX(this.containerObj.style.borderRightWidth) - this.stripPX(this.containerObj.style.borderLeftWidth);
} 

hopJSGallery.prototype.stripPX = function(str) {
	return new Number(str.replace("px", ""));
}

hopJSGallery.prototype.build = function() {
	if(document.getElementById(this.containerID)) {
	
		// Diagnostic Textbox Build	
 	  /*this.diagTextObj = document.createElement("input");
		this.diagTextObj.style.top = (this.viewportHeight - 5) + "px";
		this.diagTextObj.style.left = ((this.viewportWidth/2) - 150) + "px"
		this.diagTextObj.style.width = "300px";
		this.diagTextObj.style.height = "15px";
    this.diagTextObj.style.borderWidth = "1px";
    this.diagTextObj.style.borderColor = "#000000";
    this.diagTextObj.style.borderStyle = "solid";
		this.diagTextObj.style.textAlign = "right";
		this.diagTextObj.value = "test";
		this.diagTextObj.id = "hopGalleryDiagText";
	*/
  	this.viewportObj = document.createElement("div");
    this.viewportObj.id = "hopGalleryViewport";
    this.viewportObj.style.height = (this.viewportHeight) + "px";
    this.viewportObj.style.width = (this.viewportWidth) + "px"; 
    this.viewportObj.style.borderWidth = "0px";
    this.viewportObj.style.borderColor = "#000000";
    this.viewportObj.style.borderStyle = "solid";
		this.viewportObj.style.position = "relative";
    this.viewportObj.style.overflow = "hidden";
    
		// Create main Images Array
		for(var i=0; i<3; i++) {
				this.imageObjArray[i] = document.createElement("img");
				this.imageObjArray[i].id = "hopGalleryMainImage" + i;
				this.imageObjArray[i].webkitTransition = "all 0";
				this.imageObjArray[i].loadedImageNo = -1;
				this.imageObjArray[i].currentImageNo = -1;
        this.imageObjArray[i].objectNo = i;
				this.imageObjArray[i].style.position = "absolute";
				this.imageObjArray[i].style.webkitTransition = "left 0";
				this.viewportObj.appendChild(this.imageObjArray[i]);
		}
    
		// Add Image Viewport to Main Gallery Container
    this.containerObj.appendChild(this.viewportObj);
		
		// Diagnostic Textbox Append
		//this.containerObj.appendChild(this.diagTextObj);
		
    var self = this;
    this.viewportObj.onmousedown = function(e) { if(self.isRightClick(e)) {self.previous(true); }else{self.next(true);} return false; };
    this.viewportObj.oncontextmenu = function() { return false; };  
    
    // Build Scrollbar Container
    this.scrollbarObj = document.createElement("div");
    this.scrollbarObj.id = "hopGalleryScrollbar";
    this.scrollbarObj.style.width = (this.viewportWidth - (36 * 2)) + "px";
    this.scrollbarObj.style.left = "36px";
    this.scrollbarObj.style.height = this.scrollbarHeight + "px";;
    this.scrollbarObj.style.overflow = "hidden";
    this.scrollbarObj.style.position = "absolute";
    this.scrollbarObj.style.top = (this.viewportHeight + 15) + "px";
    this.scrollbarWidth = this.viewportWidth - (36 * 2);
		
    // Build Scrollbar Images Container
    this.scrollbarImagesObj = document.createElement("div");
    this.scrollbarImagesObj.id = "hopGalleryScrollbarImages";
    this.scrollbarImagesObj.style.height = this.scrollbarHeight + "px";
    this.scrollbarImagesObj.style.width = "5000px";
    this.scrollbarImagesObj.style.position = "absolute";
    this.scrollbarImagesObj.style.left = "0px";
		this.scrollbarImagesObj.style.webkitTransition = "all 0";
		this.scrollbarImagesObj.className = "scroll";
		
    this.scrollbarObj.appendChild(this.scrollbarImagesObj);
		
		// Add Scrollbar to Main Gallery Container
    this.containerObj.appendChild(this.scrollbarObj);
	

	  var self = this;
    
		// Create Scrollbar Arrows
    this.leftArrow = document.createElement("img");
    this.leftArrow.src = this.imageBaseUrl + 'scrollbar_left.jpg';
    this.leftArrow.style.position = "absolute";
    this.leftArrow.style.top = (this.viewportHeight + 15) + "px";
    this.leftArrow.style.left = "0px";
    this.leftArrow.style.display = "none";    
    this.leftArrow.id = "hopGalleryLeftArrow";
  	this.leftArrow.onclick = function() { self.scrollLeft();};
    
    this.rightArrow = document.createElement("img");
    this.rightArrow.src = this.imageBaseUrl + 'scrollbar_right.jpg';
    this.rightArrow.style.position = "absolute";
    this.rightArrow.style.top = (this.viewportHeight + 15) + "px";
    this.rightArrow.style.left = (this.viewportWidth - 31) + "px";    
    this.rightArrow.style.display = "none";
    this.rightArrow.id = "hopGalleryRightArrow";    
  	this.rightArrow.onclick = function() { self.scrollRight();};
    
    // Build Loading Image
    this.loadingImage = document.createElement("img");
    this.loadingImage.src = this.ajaxLoaderHref; 
    this.loadingImage.style.position = "absolute";
    this.loadingImage.style.left = "16px";
    this.loadingImage.style.top = "7px";
    
    this.loadingDivObj = document.createElement("div");
    this.loadingDivObj.id = "hopGalleryLoadingDiv";
    this.loadingDivObj.style.position = "absolute";
    this.loadingDivObj.style.top = "0px";
    this.loadingDivObj.style.width = "64px";
    this.loadingDivObj.style.height = "64px";  
    this.loadingDivObj.style.left = parseInt(this.viewportWidth/2 - 16) + "px";
    this.loadingDivObj.style.top = parseInt(this.viewportHeight/2 - 16) + "px";  
    this.loadingDivObj.style.borderRadius = "10px";
    this.loadingDivObj.style.backgroundColor = "white";
    //loadingDiv.style.display = "none";
    
    
    var loadingSubDiv = document.createElement("div");
    loadingSubDiv.style.position = "absolute";
    loadingSubDiv.style.width = "64px";
    loadingSubDiv.style.height = "64px";   
    
    var loadingText = document.createTextNode("Loading...");
    
    var loadingTextSpan = document.createElement("span");
    loadingTextSpan.style.position = "absolute";
    loadingTextSpan.style.top = "46px";
    loadingTextSpan.style.left = "14px";
    loadingTextSpan.style.fontFamily = "Arial, Helvetica, sans-serif"; 
    loadingTextSpan.style.fontSize = "9px";
    
    loadingTextSpan.appendChild(loadingText);
    this.loadingDivObj.appendChild( loadingSubDiv );
    this.loadingDivObj.appendChild( this.loadingImage );
    this.loadingDivObj.appendChild( loadingTextSpan);
    
    this.containerObj.appendChild(this.loadingDivObj);
    this.containerObj.appendChild(this.leftArrow);
    this.containerObj.appendChild(this.rightArrow); 
		   
    //this.loadingDivObj = document.getElementById("hopGalleryLoadingDiv");
    
    this.loadImageXML();
		this.assignImageNoToImages(0);
		
    //this.next();
    this.loadScrollbarImages();
	if (/iPhone|iPod|iPad/i.test(navigator.userAgent)) {
		this.enableiPad();
	}
	var self = this;
    var startCache = function() { self.cacheNextImage(); };
 
    // Execute the function with time-out
    window.setTimeout(startCache, 500);
  }
}

hopJSGallery.prototype.dragScrollbar = function(x,y) {
	this.moveScrollbar(-x);
}

hopJSGallery.prototype.setAllImagesNoTransition = function() {
	for (x in this.imagePositionArray) {
		this.imageObjArray[this.imagePositionArray[x]].style.webkitTransition = "none";
	} 
}

hopJSGallery.prototype.setAllImagesEaseTransition = function() {
	for (x in this.imagePositionArray) {
		this.imageObjArray[this.imagePositionArray[x]].style.webkitTransition = this.imageTransitionDefault;
	} 
}

hopJSGallery.prototype.enableiPad = function() {
		var self = this;
		iPT = new hopJSiPadTouch(this.viewportObj);
    iPT.minLength = this.viewportWidth/2;
		iPT.initialize();
		iPT.dragObj = function(x,y) { self.dragImage(x,0); }; //self.diagTextObj.value = Math.round(this.lastDragSpeedX) + " px/sec";
		iPT.swipeStart = function(x,y) { self.setAllImagesNoTransition(); };
		iPT.swipeLeft = function() { self.next(); };
		iPT.swipeRight = function() { self.previous(); };
		iPT.swipeCancelled = function() { self.setAllImagesEaseTransition(); self.dragImage(0,0); };
		iPT.tap = function() { self.next(true); };
		
		iPTSB = new hopJSiPadTouch(this.scrollbarObj);
		iPTSB.initialize();
		iPTSB.swipeStart = function(x,y) { self.setSBEase(false); self.scrollSwipeStartX = self.stripPX(self.scrollbarImagesObj.style.left); };
		iPTSB.dragObj = function(x,y) { self.dragScrollbar(self.scrollSwipeStartX + x,0); };
		iPTSB.swipeLeft = function() { self.scrollRight(); };
		iPTSB.swipeRight = function() { self.scrollLeft(); };
		iPTSB.tap = function() { self.scrollbarTap(iPTSB.clientX); };
}

hopJSGallery.prototype.loadImageXML = function() {
  if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
    }
  else
    {// code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
  //alert(this.xmlImageSource);
  xmlhttp.open("GET",this.xmlImageSource,false);
  xmlhttp.send();
  xmlDoc=xmlhttp.responseXML;
  //alert('here');
  //alert(xmlDoc.getElementsByTagName("image")[1].childNodes[1].textContent);
  imageNodes = xmlDoc.getElementsByTagName("image");
  for(i=0;i<imageNodes.length;i++) {
  	this.imageArray[i] = imageNodes[i].childNodes[0].textContent;
    this.thumbArray[i] = imageNodes[i].childNodes[1].textContent;
  }
}

hopJSGallery.prototype.scrollbarImageLoaded = function(newSBImg) {
  var prevHeight = newSBImg.height;
  var prevWidth = newSBImg.width;
  newSBImg.style.height = this.scrollbarHeight + "px";
  newSBImg.style.width = parseInt(((this.scrollbarHeight/prevHeight) * prevWidth)) + "px";
  newSBImg.style.position = "absolute";
  newSBImg.style.left = this.nextSBLeft  + "px";
  this.scrollbarRight = this.nextSBLeft + this.stripPX(newSBImg.style.width);
  newSBImg.sbImageNo = this.loadScrollbarImageNo;
  var self = this;
  newSBImg.onclick = function() { self.goto(this.sbImageNo);};
  if(this.loadScrollbarImageNo != this.imageNo) {
  	if(!this.SBImages[newSBImg.sbImageNo]) {
    		this.changeOpacity(newSBImg, this.imageNotLoadedFadeValue);
  	}
  	else {
  		this.changeOpacity(newSBImg, this.imageFadeValue);
  	}
  }
  if(this.nextSBLeft > this.scrollbarWidth && this.leftArrow.style.display == "none") {
  	this.leftArrow.style.display = "block";
  	this.rightArrow.style.display = "block";    
  }
  this.nextSBLeft += this.stripPX(newSBImg.style.width) + 4;
  this.scrollbarImagesObj.appendChild(newSBImg);
  this.SBImages.push(newSBImg);
  this.loadScrollbarImages();
}


hopJSGallery.prototype.loadScrollbarImages = function() {
	this.loadScrollbarImageNo = this.loadScrollbarImageNo + 1;
	if(this.loadScrollbarImageNo < this.imageArray.length) {
		var self = this;
		var newSBImg = document.createElement("img");
		newSBImg.onload = function() { self.scrollbarImageLoaded(this); };
   	newSBImg.src = this.thumbArray[this.loadScrollbarImageNo];
 	}
}

hopJSGallery.prototype.changeOpacity = function(imageobject, opacity) {
    var object = imageobject.style;
    object.opacity = ( opacity / 100 );
    object.MozOpacity = ( opacity / 100 );
    object.KhtmlOpacity = ( opacity / 100 );
    object.filter = "alpha(opacity=" + opacity + ")";
}

hopJSGallery.prototype.dragImage = function(x,y) {
	this.imageObjArray[this.imagePositionArray.centre].style.webkitTransform = "translate3d(" + (this.imageCoordinates.centre.x + x) + "px, " + this.imageCoordinates.centre.y + "px, 0)";
  if(x <= 20) {
  	this.imageObjArray[this.imagePositionArray.right].style.webkitTransform = "translate3d(" + (this.imageCoordinates.right.x + x) + "px, " + this.imageCoordinates.right.y + "px, 0)";
  }
  if(x >= -20) {
  	this.imageObjArray[this.imagePositionArray.left].style.webkitTransform = "translate3d(" + (this.imageCoordinates.left.x + x) + "px, " + this.imageCoordinates.left.y + "px, 0)";
  }
  var theTransform = this.imageObjArray[this.imagePositionArray.left].style.webkitTransform;
   
}

hopJSGallery.prototype.moveToCentre = function(imageArrayNo,instant) {
	if(!instant) instant = false;
	var self = this;
  if(!instant) this.imageObjArray[this.imagePositionArray.centre].style.webkitTransition = this.imageTransitionDefault;
  else this.imageObjArray[this.imagePositionArray.centre].style.webkitTransition = "none";
  if(imageArrayNo == this.imagePositionArray.right) {
	  this.imageObjArray[this.imagePositionArray.left].style.webkitTransition = "none";
	  if(!instant) this.imageObjArray[this.imagePositionArray.right].style.webkitTransition = this.imageTransitionDefault;
    else this.imageObjArray[this.imagePositionArray.right].style.webkitTransition = "none";
    
    //this.assignCoordinates(this.imageObjArray[this.imagePositionArray.left],this.imageObjArray[this.imagePositionArray.centre],this.imagePositionArray.left);
    this.assignCoordinates(this.imageObjArray[this.imagePositionArray.centre],this.imageObjArray[this.imagePositionArray.centre],this.imagePositionArray.left);
    this.assignCoordinates(this.imageObjArray[this.imagePositionArray.right],this.imageObjArray[this.imagePositionArray.right],this.imagePositionArray.centre);
    
    if(!instant) this.pauseDisplay = true;
	  this.updatePosition(this.imageObjArray[this.imagePositionArray.centre]);
    this.updatePosition(this.imageObjArray[this.imagePositionArray.right]);
    if(!instant) setTimeout(function() { self.pauseDisplay = false; }, this.imageTransitionTime);
    
		var oldCentre = this.imagePositionArray.centre;
		this.imagePositionArray.centre = this.imagePositionArray.right;
		this.imagePositionArray.right = this.imagePositionArray.left;
		this.imagePositionArray.left = oldCentre;
	}
	else if(imageArrayNo == this.imagePositionArray.left) {
	  if(!instant) this.imageObjArray[this.imagePositionArray.left].style.webkitTransition = this.imageTransitionDefault;
    else this.imageObjArray[this.imagePositionArray.left].style.webkitTransition = "none";
	  this.imageObjArray[this.imagePositionArray.right].style.webkitTransition = "none";

    this.assignCoordinates(this.imageObjArray[this.imagePositionArray.centre],this.imageObjArray[this.imagePositionArray.centre],this.imagePositionArray.right);
    this.assignCoordinates(this.imageObjArray[this.imagePositionArray.left],this.imageObjArray[this.imagePositionArray.left],this.imagePositionArray.centre);

    if(!instant) this.pauseDisplay = true;
 	  this.updatePosition(this.imageObjArray[this.imagePositionArray.centre]);
    this.updatePosition(this.imageObjArray[this.imagePositionArray.left]);
    if(!instant) setTimeout(function() { self.pauseDisplay = false; }, this.imageTransitionTime);

	  //this.updatePosition([ this.imageObjArray[this.imagePositionArray.centre], this.imageObjArray[this.imagePositionArray.left] ]);
    
		var oldCentre = this.imagePositionArray.centre;
		this.imagePositionArray.centre = this.imagePositionArray.left;
		this.imagePositionArray.left = this.imagePositionArray.right;
		this.imagePositionArray.right = oldCentre;
	}
  
}

hopJSGallery.prototype.goto = function(imageNo) {
	if(imageNo != this.imageNo) {
		this.assignImageNoToImages(imageNo);
  }
}

hopJSGallery.prototype.next = function(instant) {
	if (!instant) instant = false;
  	this.moveToCentre(this.imagePositionArray.right, instant);
    var self = this;
    setTimeout(function() { self.assignImageNoToImages(self.imageNo + 1); }, this.imageTransitionTime);
}

hopJSGallery.prototype.previous = function(instant) {
	if (!instant) instant = false;
  this.moveToCentre(this.imagePositionArray.left, instant);
 	var self = this;
 	setTimeout(function() { self.assignImageNoToImages(self.imageNo - 1); }, this.imageTransitionTime);
}

hopJSGallery.prototype.assignImageNoToImages = function(centreImageNo) {
    centreImageNo = this.checkImageNumber(centreImageNo);
		this.imageObjArray[this.imagePositionArray.centre].currentImageNo = this.checkImageNumber(centreImageNo);
		this.imageObjArray[this.imagePositionArray.right].currentImageNo = this.checkImageNumber(centreImageNo+1);
		this.imageObjArray[this.imagePositionArray.left].currentImageNo = this.checkImageNumber(centreImageNo-1)
  	this.fadeSBImg(this.imageNo);
		this.imageNo = centreImageNo;
   	this.highlightSBImage(this.imageNo);
    this.populateImageObjects();
}

hopJSGallery.prototype.populateImageObjects = function() {
  if(this.imageObjArray[this.imagePositionArray.centre].currentImageNo != this.imageObjArray[this.imagePositionArray.centre].loadedImageNo) {
    this.initLoad(this.imageObjArray[this.imagePositionArray.centre].currentImageNo,this.imagePositionArray.centre,1);
  }
	if(this.imageObjArray[this.imagePositionArray.right].currentImageNo != this.imageObjArray[this.imagePositionArray.right].loadedImageNo) {
    this.initLoad(this.imageObjArray[this.imagePositionArray.right].currentImageNo,this.imagePositionArray.right,2);
	}
	if(this.imageObjArray[this.imagePositionArray.left].currentImageNo != this.imageObjArray[this.imagePositionArray.left].loadedImageNo) {
    this.initLoad(this.imageObjArray[this.imagePositionArray.left].currentImageNo,this.imagePositionArray.left,3);
	}
}

hopJSGallery.prototype.cacheImageLoaded = function( loadedImage ) {
  if(!this.mainImageCache[loadedImage.imageNo]) {
  	this.mainImageCache[loadedImage.imageNo] = loadedImage;
  }
  this.setSBImageLoaded(loadedImage.imageNo);
  loadedImage.onload = null;
  //loadedImage.src = null;
  //loadedImage = null;
  var self = this;
  setTimeout(function() { self.cacheNextImage(); }, 200);
}

hopJSGallery.prototype.setSBImageLoaded = function( imageNo ) {
	if(this.SBImages[imageNo]) {
		this.changeOpacity( this.SBImages[imageNo], this.imageFadeValue);
	}
}

hopJSGallery.prototype.cacheNextImage = function() {
	this.cacheImageNo = this.cacheImageNo + 1;
	if(this.cacheImageNo < this.imageArray.length) {
	  if(!this.mainImageCache[this.cacheImageNo]) {
      //this.loadCacheImg = null;
  		var cacheImage = new Image();
      cacheImage.imageNo = this.cacheImageNo;
			var self = this;
			cacheImage.onload = function() { self.cacheImageLoaded(this); };
      cacheImage.src = this.imageArray[this.cacheImageNo];
    }
    else {
		  this.setSBImageLoaded(this.cacheImageNo);
    	this.cacheNextImage();
    }
	}
}

hopJSGallery.prototype.initLoad = function(imageNumberToLoad, positionToPopulate, imageArrayNo) {
	var self = this;

  if(!this.mainImageCache[imageNumberToLoad]) {
  	// Display preloading Image
    var imgObj = this.imageObjArray[positionToPopulate];
  	imgObj.src = this.loadingImage.src;
    this.assignCoordinates(imgObj, this.loadingImage, positionToPopulate);
  	imgObj.style.webkitTransition = "none";
	 	this.updatePosition(imgObj);
    
    // Load New Image
  	var loadImage = new Image();
  	loadImage.onload = function() { self.displayImage(this); };
  	loadImage.imageNo = imageNumberToLoad;
  	loadImage.populateObjNum = positionToPopulate;
  	loadImage.src = this.imageArray[imageNumberToLoad];
  }
	else {
  	var preloadedImg = this.mainImageCache[imageNumberToLoad];
    preloadedImg.populateObjNum = positionToPopulate;
  	this.displayImage(preloadedImg);
  }  
}

hopJSGallery.prototype.displayImage = function(loadedImage) {
	var self = this;
	if(!this.mainImageCache[loadedImage.imageNo]) {
  		this.mainImageCache[loadedImage.imageNo] = loadedImage;
	}
  if(this.pauseDisplay == true) {
  	setTimeout(function() { self.displayImage(loadedImage); }, this.imageTransitionTime);
    return;
	}
  var positionToPopulate = -1;
 	var load = true;
	if(this.imageObjArray[loadedImage.populateObjNum].currentImageNo == loadedImage.imageNo) {
  	positionToPopulate = loadedImage.populateObjNum;
  }
  else {
    load = false;
  	for(var i=0; i<this.imageObjArray.length; i++) {
    	if(this.imageObjArray[i].currentImageNo == loadedImage.imageNo) {
  			positionToPopulate = i;
        load = true;
  		}
    }
  }
  
	if(load) {
	 	var imgObj = this.imageObjArray[positionToPopulate];
  	imgObj.loadedImageNo = loadedImage.imageNo;
  	imgObj.src = loadedImage.src;
  	imgObj.style.position = "absolute";
    imgObj.nextPosition = null;
	  this.assignCoordinates(imgObj, loadedImage, positionToPopulate);
  	imgObj.style.webkitTransition = "none";
 		this.updatePosition(imgObj);
  }
  loadedImage.onload = null;
	//loadedImage.src = null;
  //loadedImage = null;
	this.loadingDivObj.style.display = "none";
	this.populateImageObjects();
}

hopJSGallery.prototype.assignCoordinates = function(imgObj, imgSizeObj, moveToPosition) {
	var left = 0;
  var top = (this.viewportHeight/2) - (imgSizeObj.height/2);
  if(moveToPosition == this.imagePositionArray.centre) {
		left = parseInt((this.viewportWidth/2) - (imgSizeObj.width/2));
  	this.imageCoordinates.centre.x = left;
  	this.imageCoordinates.centre.y = top;
    imgObj.nextPosition = this.imageCoordinates.centre;
  }
	else if(moveToPosition == this.imagePositionArray.left) {
		left = 0-parseInt((this.viewportWidth/2) + (imgSizeObj.width/2)) - 10;
  	this.imageCoordinates.left.x = left;
  	this.imageCoordinates.left.y = top;
    imgObj.nextPosition = this.imageCoordinates.left;
	}
	else if(moveToPosition == this.imagePositionArray.right) {
		left = this.viewportWidth + parseInt((this.viewportWidth/2) - (imgSizeObj.width/2)) + 10;
  	this.imageCoordinates.right.x = left;
  	this.imageCoordinates.right.y = top;
    imgObj.nextPosition = this.imageCoordinates.right;
	}	
}

hopJSGallery.prototype.updatePosition = function(imgObj) {
	imgObj.style.webkitTransform = "translate3d(" + imgObj.nextPosition.x + "px, "+ imgObj.nextPosition.y + "px, 0)";
}

hopJSGallery.prototype.isRightClick = function(e) {
	var rightclick;
	if (!e) var e = window.event;
	if (e.which) rightclick = (e.which == 3);
	else if (e.button) rightclick = (e.button == 2);
	//alert('Rightclick: ' + rightclick); // true or false
  return rightclick;
}


hopJSGallery.prototype.checkImageNumber = function(num) {
	if(num < 0) num = this.imageArray.length + num;
  if(num > this.imageArray.length-1) num = num-this.imageArray.length;
  return num;
}

hopJSGallery.prototype.fadeSBImg = function(imageNo) {
	if(this.SBImages[imageNo]) {
		this.changeOpacity( this.SBImages[imageNo], this.imageFadeValue);
  }
}

hopJSGallery.prototype.highlightSBImage = function(imageNo) {
	if(this.SBImages[imageNo]) {
		this.changeOpacity( this.SBImages[imageNo], 100);
	}
	this.focusScrollbar();  
}

hopJSGallery.prototype.focusScrollbar = function() {
	this.setSBEase(true);
	if(this.SBImages[this.imageNo]) {
  	//if(this.stripPX(this.SBImages[this.imageNo].style.left) > -this.stripPX(this.scrollbarImagesObj.style.left) + this.scrollbarWidth - 100) {
	if(this.stripPX(this.SBImages[this.imageNo].style.left) + this.stripPX(this.SBImages[this.imageNo].style.width)  > -this.stripPX(this.scrollbarImagesObj.style.left) + this.scrollbarWidth - 100) {
    	this.moveScrollbar(this.stripPX(this.SBImages[this.imageNo].style.left) - 150);
    }
    else if(this.stripPX(this.SBImages[this.imageNo].style.left) < -this.stripPX(this.scrollbarImagesObj.style.left) + 100) {
    	this.moveScrollbar(this.stripPX(this.SBImages[this.imageNo].style.left) - this.scrollbarWidth + this.stripPX(this.SBImages[this.imageNo].style.width) + 150);    
    }
  }
}

hopJSGallery.prototype.setSBEase = function(setOn) {
	switch(setOn) {
  	case true:
	  	this.scrollbarImagesObj.style.webkitTransition = this.SBTransitionDefault; 
    	break;
    case false:
	  	this.scrollbarImagesObj.style.webkitTransition = "all 0";
      break 
 	}
}

hopJSGallery.prototype.scrollLeft = function() {
	this.setSBEase(true);
	this.moveScrollbar(-this.stripPX(this.scrollbarImagesObj.style.left) - this.scrollbarWidth + 50);
}

hopJSGallery.prototype.scrollRight = function() {
	this.setSBEase(true);
	this.moveScrollbar(-this.stripPX(this.scrollbarImagesObj.style.left) + this.scrollbarWidth - 50);
}

hopJSGallery.prototype.findPos = function(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		do {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		} while (obj = obj.offsetParent);
		return [curleft,curtop];
	}		
}

hopJSGallery.prototype.scrollbarTap = function(x) {
	var SBObjPos = this.findPos(this.scrollbarObj);
	var SBClickX = x - SBObjPos[0] - this.stripPX(this.scrollbarImagesObj.style.left);
	for(var i=0; i<this.SBImages.length; i++) {
		var lTest = this.stripPX(this.SBImages[i].style.left);
		var wTest = this.stripPX(this.SBImages[i].style.width);
		if(lTest+wTest > SBClickX && lTest < SBClickX) {
			this.goto(this.SBImages[i].sbImageNo);
			break;
		}
	}
}

hopJSGallery.prototype.moveScrollbar = function(left) {
	if(left < 0) left = 0;
  if(left + this.scrollbarWidth > this.scrollbarRight) {
  	left = this.scrollbarRight - this.scrollbarWidth;
  }
	if(this.scrollbarImagesObj.style.webkitTransform) {
		this.scrollbarImagesObj.style.webkitTransform = "translate3d(" + -left + "px, 0, 0)";
	}
	else {
		this.scrollbarImagesObj.style.left = -left + "px";
	}
}







function hopJSiPadTouch(containerObj) {

	this.triggerElementID = null; // this variable is used to identity the triggering element
	this.fingerCount = 0;
	this.startX = 0;
	this.startY = 0;
	this.clientX = 0;
	this.clientY = 0;
	this.curX = 0;
	this.curY = 0;
	this.deltaX = 0;
	this.deltaY = 0;
	this.horzDiff = 0;
	this.vertDiff = 0;
	this.minLength = 400; // the shortest distance the user may swipe
	this.swipeLength = 0;
	this.swipeAngle = null;
	this.swipeDirection = null;
	this.swipeLeft = new Function();
	this.swipeRight = new Function();
	this.swipeUp = new Function();
	this.swipeDown = new Function();
	this.tap = new Function();
	this.dragObj = new Function();
	this.swipeStart = new Function();
	this.swipeReset = new Function();
	this.swipeCancelled = new Function();
	this.cID = containerObj.id;
	this.cIDObj = containerObj;	
	this.touchStartedAt = 0;
	this.lastDrag = 0;
	this.lastDragTime = 0;
  this.dragDirection = "left";
	this.lastDragX = 0;
	this.lastDragY = 0;
	this.lastDragSpeedX = 0;
	this.lastDragSpeedY = 0;
	this.detectSwipeSpeed = 1500; // minimum swipe speed for a touch to be detected as a swipe
}

hopJSiPadTouch.prototype.initialize = function() {
	var self = this;
	this.cIDObj.ontouchstart = function(e) { self.touchStart(e,self.cID); };
	this.cIDObj.ontouchend = function(e) { self.touchEnd(e); };
	this.cIDObj.ontouchmove = function(e) { self.touchMove(e); };
	this.cIDObj.ontouchcancel = function(e) { self.touchCancel(e); };
	//this.cIDObj.onmousedown = function(e) { self.touchStart(e,self.cID); };
}

hopJSiPadTouch.prototype.resetDragSpeedDetect = function(x,y) {
	var dt = new Date();
  this.lastDragTime = dt.getTime();
  this.lastDragX = x;
  this.lastDragY = y;
	this.lastDragSpeedX = 0;
	this.lastDragSpeedY = 0;
}

hopJSiPadTouch.prototype.detectDragSpeed = function(x,y) {
  var dt = new Date();
  var now = dt.getTime();
	
	var timeDiff = this.lastDragTime - now;
	var posDiffX = this.lastDragX - x;
	var posDiffY = this.lastDragY - y;
  
  if(posDiffX > 0) {
		this.swipeDirection = 'left';
	}
  else {
  	this.swipeDirection = 'right';
  }
  
  this.lastDragSpeedX = Math.abs(posDiffX/timeDiff*1000);
	this.lastDragSpeedY = Math.abs(posDiffY/timeDiff*1000);
	
	this.lastDragX = x;
	this.lastDragY = y;
	this.lastDragTime = now;
}

// The 4 Touch Event Handlers

// NOTE: the touchStart handler should also receive the ID of the triggering element
// make sure its ID is passed in the event call placed in the element declaration, like:
// <div id="picture-frame" ontouchstart="touchStart(event,'picture-frame');"  ontouchend="touchEnd(event);" ontouchmove="touchMove(event);" ontouchcancel="touchCancel(event);">

hopJSiPadTouch.prototype.touchStart = function(event,passedName) {
	// disable the standard ability to select the touched object
	event.preventDefault();
	// get the total number of fingers touching the screen
	this.fingerCount = event.touches.length;
	// since we're looking for a swipe (single finger) and not a gesture (multiple fingers),
	// check that only one finger was used
	if ( this.fingerCount == 1 ) {
		// get the coordinates of the touch
		var dt = new Date();
		this.touchStartedAt = dt.getTime(); 
		this.lastDrag = this.touchStartedAt;
		this.startX = event.touches[0].pageX;
		this.startY = event.touches[0].pageY;
		this.resetDragSpeedDetect(this.startX, this.startY);
		this.clientX = event.touches[0].clientX;
		this.clientY = event.touches[0].clientY;
		this.swipeStart(this.startX,this.startY);
		// store the triggering element ID
		this.triggerElementID = passedName;
	} else {
		// more than one finger touched so cancel
		this.touchCancel(event);
	}
}

hopJSiPadTouch.prototype.touchMove = function(event) {
	event.preventDefault();
	if ( event.touches.length == 1 ) {
		this.curX = event.touches[0].pageX;
		this.curY = event.touches[0].pageY;
	  this.dragObj(this.curX - this.startX,this.curY - this.startY);
  	this.detectDragSpeed(this.curX, this.curY);
	} else {
		this.touchCancel(event);
	}
}

hopJSiPadTouch.prototype.touchEnd = function(event) {
	event.preventDefault();
	// check to see if more than one finger was used and that there is an ending coordinate
	if ( this.fingerCount == 1) {
		if ( this.curX != 0 ) {
				  if(this.lastDragSpeedX > this.detectSwipeSpeed || this.lastDragSpeedY > this.detectSwipeSpeed) {
  				  //this.caluculateAngle();
  				  //this.determineSwipeDirection();
  				  this.processingRoutine();
  				  this.touchCancel(event); // reset the variables
					}
          else if(Math.abs(this.curX - this.startX) > this.minLength) {
            if(this.curX - this.startX < 0) {
          		this.swipeDirection = 'left';
          	}
            else {
            	this.swipeDirection = 'right';
            }
  				  this.processingRoutine();
            this.touchCancel(event);
          }
					else {
						this.swipeCancelled();
					  this.touchCancel(event);
					}
		}
		else {
			this.tap();
			this.touchCancel(event);
		}
	} 
	else {
	  this.swipeCancelled();
		this.touchCancel(event);
	}
}

hopJSiPadTouch.prototype.touchCancel = function(event) {
	// reset the variables back to default values
	this.fingerCount = 0;
	this.startX = 0;
	this.startY = 0;
	this.curX = 0;
	this.curY = 0;
	this.deltaX = 0;
	this.deltaY = 0;
	this.horzDiff = 0;
	this.vertDiff = 0;
	this.swipeLength = 0;
	this.swipeAngle = null;
	this.swipeDirection = null;
	this.triggerElementID = null;
	this.swipeReset();
}

hopJSiPadTouch.prototype.caluculateAngle = function() {
	var X = this.startX-this.curX;
	var Y = this.curY-this.startY;
	var Z = Math.round(Math.sqrt(Math.pow(X,2)+Math.pow(Y,2))); //the distance - rounded - in pixels
	var r = Math.atan2(Y,X); //angle in radians (Cartesian system)
	this.swipeAngle = Math.round(r*180/Math.PI); //angle in degrees
	if ( this.swipeAngle < 0 ) { this.swipeAngle =  360 - Math.abs(this.swipeAngle); }
}

hopJSiPadTouch.prototype.determineSwipeDirection = function() {
	if ( (this.swipeAngle <= 45) && (this.swipeAngle >= 0) ) {
		this.swipeDirection = 'left';
	} else if ( (this.swipeAngle <= 360) && (this.swipeAngle >= 315) ) {
		this.swipeDirection = 'left';
	} else if ( (this.swipeAngle >= 135) && (this.swipeAngle <= 225) ) {
		this.swipeDirection = 'right';
	} else if ( (this.swipeAngle > 45) && (this.swipeAngle < 135) ) {
		this.swipeDirection = 'down';
	} else {
		this.swipeDirection = 'up';
	}
}

hopJSiPadTouch.prototype.processingRoutine = function() {
	//var swipedElement = document.getElementById(this.triggerElementID);
	
	if ( this.swipeDirection == 'left' ) {
		this.swipeLeft();
	} else if ( this.swipeDirection == 'right' ) {
		this.swipeRight();
	} else if ( this.swipeDirection == 'up' ) {
		this.swipeUp();
	} else if ( this.swipeDirection == 'down' ) {
		this.swipeDown();
	}
}

