/*
		File:			ViewLarger class
		Version:	0.9
		Desc:			This class builds the View Larger functionality on a product page.
		Requires:	/pages/v4/script/dhtml_lib.js
							/pages/v4/script/ProductHelper.js
							/pages/v4/script/AjaxHelper.js
		Use:			Auto-initialize by setting up a window load event to call AutoInit static member
							EventHelper.AddEvent(window, 'load', ViewLarger.AutoInit, false);
							This assumes you already have a link to the view larger page.
		Author:		Eric Shepherd
		Date:			December 2006
		Methods:	The following methods are in this class.
		
							init()
								If the large image link is present, calls activate()
								
									
			Version History:
				
				0.9		EBS		Development
				1.0		EBS		Production
*/

// Class ViewLarger
function ViewLarger(parent) 
{
	this._relAttribute = 'view-larger';
	this._imageCaptionId = 'product-caption';
	this._parent = parent;
}

// Public
ViewLarger.prototype.SetRelAttribute = function(value) {
	this._relAttribute = value;	
}

ViewLarger.prototype.SetImageCaptionId = function(value) {
	this._imageCaptionId = value;	
}

ViewLarger.prototype.SetParent = function(value) {
	this._parent = value;	
}




// Function: init()
// Calls activate() if the view larger link is present
// Returns:
// 	void
ViewLarger.prototype.init = function() 
{
	if (this.largeImageLink(this._parent) != null) {
		this.activate(this._parent);
	}
}



// Funtion: largeImageLink()
// Returns the large image link by querying the document to match the rel attribute "view-larger"
// Parameters:
// 	parent - the element in which to check for a view larger link
// Returns:
// 	the view larger link if present, else null
ViewLarger.prototype.largeImageLink = function(parent) 
{
	var theLinks = parent.getElementsByTagName('a');
	var theLink = null;
	for (i=0; i<theLinks.length; i++) {
		if (theLinks[i].getAttribute('rel') && theLinks[i].getAttribute('rel').match(this._relAttribute)) {
			theLink = theLinks[i];	
		}
	}
	return theLink;
}



// Function: activate()
// Adds the click event to trigger the view larger functionality
// Parameters:
// 	parent - the element which contains the current view larger scope
// Returns:
// 	void
ViewLarger.prototype.activate = function(parent)
{
	var theLink = this.largeImageLink(parent);
	var thisReference = this;
	EventHelper.AddEvent(theLink, 'click', ptr = function(e) { thisReference.showLarger(theLink, e); }, false);
}



// Function: showLarger()
// Builds the view larger modal window, or reactivates it as needed, then cancels the default action
// Parameters:
// 	theLink - the view larger link which was clicked to activate the view larger functionality
// 	e - the click event
// Returns:
// 	void
ViewLarger.prototype.showLarger = function(theLink, e)
{
			// here is where we actually build stuff
	if (document.getElementById('larger-image') == null) {
		var newDiv = document.createElement('div');
		newDiv.id = 'larger-image';
		newDiv.style.display = 'none';
		var theBody = document.getElementsByTagName('body')[0];
		theBody.appendChild(newDiv);
				// set overlay size
		this.overlay();
				// load the external page into the div
		var thisReference = this;
				// make the xmlhttprequest
		AjaxHelper.load(newDiv, theLink, function() { thisReference.setBehaviors(); });

	} else if (SupportTest.isIE) {	// ie has bugs when reactivating the hidden div - things vanish - so we need to make the ajax call again
				// delete div
		var div = document.getElementById('larger-image');
		div.parentNode.removeChild(div);
				// redo ajax call
		var newDiv = document.createElement('div');
		newDiv.id = 'larger-image';
		newDiv.style.display = 'none';
		var theBody = document.getElementsByTagName('body')[0];
		theBody.appendChild(newDiv);
		this.overlay();
		var thisReference = this;
		AjaxHelper.load(newDiv, theLink, function() { thisReference.setBehaviors(); });
		
	} else {	// good browsers can just reactivate the hidden div
				// restore the visibility of the previously hidden element
		$('larger-image').setStyle('display', 'block');
		$('viewlarger-scroll-frame').setStyle('display', 'block');
		$('viewlarger-close').setStyle('display', 'block');
		$('viewlarger-include').effect('opacity').custom(0,1);
				// we need to set the image display now, also
		this.fixImages(theLink);
		this.fixCaption();
				// run the effects for the mouseovers and close functionality
		this.setBehaviors();
	}
			// cancel the default action
	EventHelper.CancelDefault(e);
}



// Function: fixImages()
// Fixes all images after a new click reactivates since we don't instantiate a new scroller object 
// This is kind of ugly, but the scroller doesn't know what's inside it, 
// so we have to longhand compare the large image with the scroller items.
// Parameters:
// 	theLink - the link which was clicked to activate view larger
// Returns:
// 	void
ViewLarger.prototype.fixImages = function(theLink)
{
			// get a reference to the ViewLarger object stored as a reference in document
	var VLI = document.ViewLargerInstance;
			// get the large image
	var image = $('main-large-image').getElementsByTagName('img')[0];
			// Here we go...
			// get the old number image and the newly selected image number.
			// we can take the difference and jump by that number
	var theOldNumberArr = image.src.match(/_(\d{1,2})\./);
	var theOldNumber = theOldNumberArr.length > 0 ? theOldNumberArr[1] : 1;
			// get the new number
	var theNewNumberArr = theLink.href.match(/image=(\d+)/);
	var theNewNumber = theNewNumberArr.length > 0 ? theNewNumberArr[1] : 1;
			// set the new large image
	var newImage = document.createElement('img');
	newImage.src = image.src.replace(/_\d+.jpg/g, '_' + theNewNumber + '.jpg');
	newImage.onload = function() {
		image.src = newImage.src;
		newImage = null;
	}
			// get an array of the images
			// PROBLEM: IE places the script objects in the ViewLarger.aspx page out of scope, so we can't read from the instances
			// SOLUTION: Place a reference to the instance in the document object when it's created in ViewLarger.aspx
	var container = document.getElementById(VLI.scroller._itemId);
	var thumbnails = container.getElementsByTagName('img');
			// get the new number
	var str = '_' + theNewNumber + '.jpg';
	var imageSlot = 1;
			// assign imageSlot to index in array of that number's occurrence
			// and set the selected list item for use below
	var theNewLi;
	for (i=0; i<thumbnails.length; i++) {
		if (thumbnails[i].src.match(str)) {
			imageSlot = i;
			theNewLi = DomHelper.AscendDom(thumbnails[i], 'li');
		}
	}
	var oldTop = VLI.scroller._itemTop;
	var newTop = imageSlot * VLI.scroller._increment;
			// reset scroller to new position
	if (thumbnails.length > 6) {
		VLI.scroller._scrollerItem.style.top = (0 - newTop) + 'px';
		VLI.scroller._itemTop = parseInt(VLI.scroller._scrollerItem.style.top);
	}
			// change the active/inactive items
			// start with scroller buttons
	VLI.scroller.updateControls(0, VLI.scroller.canScrollBackward());
	VLI.scroller.updateControls(1, VLI.scroller.canScrollForward());
			// then do the image active states and links using the currently instantiated ProductHelper object
	var theListItems = container.getElementsByTagName('li');
	var activeEl;
	for (i=0; i<theListItems.length; i++) {
		if (!theListItems[i].getElementsByTagName('a').length > 0) {
			activeEl = theListItems[i];
			VLI.viewLargerPH._storage = DomHelper.DeactivateElement(activeEl, VLI.viewLargerPH._storage);
			VLI.viewLargerPH._storage = DomHelper.ActivateElement(theNewLi, VLI.viewLargerPH._storage);
		}
	}
}



// Function: fixCaption()
// Fix the caption after the modal window is reactivated 
// Returns:
// 	void
ViewLarger.prototype.fixCaption = function()
{
	var theCaptionNode = document.getElementById(this._imageCaptionId);
	var theCaption = theCaptionNode.firstChild ? theCaptionNode.firstChild.nodeValue : ' ';
	var theNewCaptionNode = document.getElementById('viewlarger-caption');
	theNewCaptionNode.innerHTML = theCaption;
}



// Function: setBehaviors()
// Callback after ajax call or reactivation of hidden elements. Sets the behavioral effects of the modal window
// Returns: 
// 	void
ViewLarger.prototype.setBehaviors = function()
{
	var thisReference = this;
	
	targetsLoaded = setInterval(setEffects, 300);
	
	function setEffects() {
		if (typeof $ != 'undefined') {
					// INIT: set the position before making visible
			thisReference.setPosition();
					// make visible
			$('larger-image').setStyle('display', 'block');
			$('viewlarger-scroll-frame').setStyle('display', 'block');
			$('viewlarger-close').setStyle('display', 'block');
					// EFFECT: sets the opacity of the entire modal window, including display none
					// after it fades out, so that it won't be present over the product page window
			viewLargerOpacityEffect = $('viewlarger-include').effect('opacity', { 
				onStart : function() {
				},
				onComplete: function() {
					$('larger-image').setStyle('display', 'none');
					$('viewlarger-scroll-frame').setStyle('display', 'none');
					$('viewlarger-close').setStyle('display', 'none');
				}
			});					
					// ACTION: make modal window draggable
			var dragOptions = {
				onStart : function() {
					$('viewlarger-include').setStyle('cursor', 'move');
				},
				onComplete : function() {
					$('viewlarger-include').setStyle('cursor', 'default');
				}
			}
			$('viewlarger-include').makeDraggable(dragOptions);
					// EVENT: click - ELEMENT: close button or window overlay - ACTION: close and hide modal window
			$('viewlarger-overlay').addEvent('click', function() { viewLargerOpacityEffect.custom(1,0); });
			$('viewlarger-close').addEvent('click', function() { viewLargerOpacityEffect.custom(1,0); });
					// EVENT: keypress - ESCAPE KEY - ACTION: close and hide modal window
			document.onkeydown = function(e){   
				if (e == null) { // ie
					keycode = event.keyCode;
				} else { // mozilla
					keycode = e.which;
				}
				if(keycode == 27){ // close
					viewLargerOpacityEffect.custom(1,0);
				}  
			}			
					// clear interval - TODO: add a try/catch to be sure the interval gets cleared?
			clearInterval(targetsLoaded);
		}
	}
}

// -----------------------
// HELPER METHODS
// -----------------------


// Function: overlay()
// Sets the size of the overlay div to match the height and width of the current window
// Returns: 
// 	void
ViewLarger.prototype.overlay = function() 
{
	if (window.innerHeight && window.scrollMaxY || window.innerWidth && window.scrollMaxX) {
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
		var doc = document.documentElement;
		var docw = (doc && doc.clientWidth) || document.body.clientWidth || window.innerWidth || self.innerWidth;
		var doch = (doc && doc.clientHeight) || document.body.clientHeight || window.innerHeight || self.innerHeight;
		xScroll -= (window.innerWidth - docw);
		yScroll -= (window.innerHeight - doch);
	} else if (document.body.scrollHeight > document.body.offsetHeight || document.body.scrollWidth > document.body.offsetWidth) {
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else {
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	$('larger-image').setStyles({
		'width' : xScroll + 'px',
		'height' : yScroll + 'px'
	});
}



// Function: getPageSizes()
// Returns an array containing the width and height of the current page
// Returns:
// 	array[width, height]
ViewLarger.prototype.getPageSizes = function()
{
	var doc = document.documentElement;
	var w = window.innerWidth || self.innerWidth || (doc && doc.clientWidth) || document.body.clientWidth;
	var h = window.innerHeight || self.innerHeight || (doc && doc.clientHeight) || document.body.clientHeight;
	pageSizes = new Array(w, h);
	return pageSizes;
}



// Function: setPosition()
// Sets the left and top offsets of the view larger modal window
// Returns:
// 	void
ViewLarger.prototype.setPosition = function()
{
	var pageSizes = this.getPageSizes();
	var pageScrolls = this.getPageScrollTop();
	$('viewlarger-include').setStyles({ 
		'left' : pageScrolls[0] + ((pageSizes[0] - 590)/2) + 'px',
		'top' : (pageScrolls[1] + 25) + 'px'
	});
}



// Function: getPageScrollTop()
// Returns the amount the page has been scrolled
// Returns:
// 	array[left offset, top offset]
ViewLarger.prototype.getPageScrollTop = function()
{
	var xScrollLeft;
	var yScrollTop;
	if (self.pageYOffset || self.pageXOffset) {
		xScrollLeft = self.pageXOffset;
		yScrollTop = self.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop || document.documentElement.scrollLeft) {
		xScrollLeft = document.documentElement.scrollLeft;
		yScrollTop = document.documentElement.scrollTop;
	} else if (document.body) {
		xScrollLeft = document.body.scrollLeft;
		yScrollTop = document.body.scrollTop;
	}
	pageScrolls = new Array(xScrollLeft, yScrollTop);
	return pageScrolls;
}




// Function: AutoInit()
// Static member to create a standard application on a product page assuming we are targeting the "#product-shot" element
// Returns:
// 	void
ViewLarger.AutoInit = function() {
	var parent = document.getElementById('product-shot');
	var instance = new ViewLarger(parent);
	instance.init();
}
