/*

Author: Scott Doxey
Author: Mark Connolly
Version: 1
Version Date: 10.24.09
Release: 0
Release Date: ? 7.30.09 ?
 
*/
 

// Class Constructor



function Slider (keyhole_div, sliding_div, keyhole_size, requestedSlideIndex, direction, animationSpeed, deepLink) {
	

	/*     definable Objects via constructor     */
	
	this.keyhole_div = this.checkObject(keyhole_div, 'string');
	
	this.sliding_div = this.checkObject(sliding_div, 'string');
	this.keyhole_size = keyhole_size;
	this.requestedSlideIndex = requestedSlideIndex;
	this.direction = direction;
	this.animationSpeed = animationSpeed;
	this.deepLink = deepLink;


	/*     predefined Objects     */
		
	this.currentSlideIndex = 0;
	
	
	/*     calculated Objects     */
	
	this.slideTimes;
	this.moduleWidth;
	this.moduleHeight;
	this.width;
	this.height;

	/*  initialization (one-time) calls  */
	
	this.scrubWhiteSpace(this.keyhole_div);
	
	// Check if any definable Objects are incorrectly or not defined.

	if (!this.sliding_div) {
		this.sliding_div = this.keyhole_div.childNodes[0];
	}

	if ((this.direction != 'horizontal' && this.direction != 'vertical') || !this.direction) {
		this.direction = 'horizontal';
	}

	if (!this.animationSpeed) {
		this.animationSpeed = 20;
	}

	if (!this.requestedSlideIndex) {
		this.requestedSlideIndex = this.currentSlideIndex;
	}
}

Slider.prototype.checkObject = function (obj, type) {
	if (obj) {
		if (typeof(obj) == type) {
			obj = document.getElementById(obj);
		}
		
		return obj;
	}
}



Slider.prototype.scrubWhiteSpace = function (obj) {

	for (var x = 0; x < obj.childNodes.length; x++) {
		if (obj.childNodes[x].nodeType > 1) {
			obj.removeChild(obj.childNodes[x]);
			x--;
		}
	}
}


Slider.prototype.getRealMeasure = function (obj, measure) {

	var realMeasure = 0;
	
	if (measure == 'width') {
		var attributes = Array('width', 'padding-left', 'padding-right', 'border-left-width', 'border-right-width', 'margin-left', 'margin-right');
	} else {
		var attributes = Array('height', 'padding-top', 'padding-bottom', 'border-top-width', 'border-bottom-width', 'margin-top', 'margin-bottom');
	}
	
	for (var i = 0; i < attributes.length; i++) {
		realMeasure += Number(this.getStyle(obj, attributes[i]));
	}
	
	return realMeasure;	
}


Slider.prototype.getStyle = function (obj, name) {

	// the function checks first for Opera, IE, Everything else DOM compliant, and then everything else NOT DOM compliant

	var output;

	if (obj.currentStyle) { 
		output = obj.currentStyle[this.camelize(name)];
		
	} else if (obj.style && obj.style[this.camelize(name)]) { 
		output = obj.style[this.camelize(name)];
		
	} else if (window.getComputedStyle) {
		output = document.defaultView.getComputedStyle(obj, null).getPropertyValue(name); 
		
	} else { 
		return false;
	}

	if (String(output).match(/^[0-9]+px$/)) { 
		return Number(String(output).match(/[0-9]+/)[0]);
	} else { 
		return 0;
	}
}


Slider.prototype.camelize = function (name) {
	return name.replace(/-([a-z])/g, function(str) { 
		return String(str.match(/[a-z]/)).toUpperCase(); }
	);
}




Slider.prototype.initializeVariables = function () {
	
	this.scrubWhiteSpace(this.sliding_div);	
	
	if (this.keyhole_div.childNodes.length > 1) {
	
		for (var x = 0; x < this.keyhole_div.childNodes.length; x++) {
			if (this.keyhole_div.childNodes[x] == this.sliding_div) {
				this.keyhole_div.childNodes[x].style.display = 'block';
			} else {
				this.keyhole_div.childNodes[x].style.display = 'none';
			}
		}
	}
		
	if (window.event) {
		this.width = 0;
		this.height = 0;
		this.moduleWidth = 0;
		this.moduleHeight = 0;
		this.slideTimes = null;
		this.currentIndex = 0;
		this.requestedIndex = 0;
		if (this.sliding_div.interval) {
			clearInterval(this.sliding_div.interval);
		}
	}
		
	var sideToCheck;
	this.direction == 'horizontal' ? sideToCheck = this.getRealMeasure(this.keyhole_div, 'width') : sideToCheck = this.getRealMeasure(this.keyhole_div, 'height');
					
	if (!this.keyhole_size) { var tempKeyhole = 1; }
	
	for (var x = 0; x < this.sliding_div.childNodes.length; x++) {	
		if (this.getStyle(this.sliding_div.childNodes[x], 'display') != 'none') { 
	
			var tempWidth = this.getRealMeasure(this.sliding_div.childNodes[x], 'width');
			var tempHeight = this.getRealMeasure(this.sliding_div.childNodes[x], 'height');
	
			if (!this.width) {
				this.width = tempWidth;
			} else {
				this.width += tempWidth;
			}
			
			if (!this.height) {
				this.height = tempHeight;
			} else {
				this.height += tempHeight;
			}
				
			if (x == 0) {
				this.moduleWidth = this.width;
				this.moduleHeight = this.height;
			}			
			
			this.moduleWidth = Math.max(tempWidth, this.moduleWidth);
			this.moduleHeight = Math.max(tempHeight, this.moduleHeight);
			
			if (!this.keyhole_size) {
				if ((this.direction == 'horizontal' && this.width < sideToCheck) || (this.direction == 'vertical' && this.height < sideToCheck)) {
					tempKeyhole++;
				}
			}
		}
	}
	
	if (!this.keyhole_size) {
		this.keyhole_size = tempKeyhole;
	}
	
		
	this.slideTimes = this.sliding_div.childNodes.length / this.keyhole_size;
	
	
	if (this.requestedSlideIndex > Math.ceil(this.slideTimes)) {
		this.requestedSlideIndex = 0;
	}
}


Slider.prototype.setLayout = function () {
	
	/*
	
	This function sets the keyhole_div and sliding_div width and height.
	This function is called on initialize, but also on collapse (when expand is initialized).

	*/
		
	this.keyhole_div.style.overflow = 'hidden';
	this.keyhole_div.style.position = 'relative';
			
	this.sliding_div.style.position = 'absolute';
	
	if (this.direction == 'horizontal') {
		this.sliding_div.style.left = '-' + this.currentSlideIndex * this.keyhole_size * this.moduleWidth + 'px';
		this.sliding_div.style.top = '0px';
		this.sliding_div.style.width = this.width + 'px';
		this.sliding_div.style.height = this.moduleHeight + 'px';
		
		this.keyhole_div.style.height = this.moduleHeight + 'px';
		this.keyhole_div.style.width = this.moduleWidth * this.keyhole_size + 'px';

	} else {
	
		this.sliding_div.style.left = '0px';
		this.sliding_div.style.top = this.currentSlideIndex * this.keyhole_size * this.moduleHeight + 'px';
		this.sliding_div.style.width = this.moduleWidth + 'px';
		this.sliding_div.style.height = this.height + 'px';
		
		this.keyhole_div.style.width = this.moduleWidth + 'px';
		this.keyhole_div.style.height = this.keyhole_size * this.moduleHeight + 'px';
	}
}	
	
Slider.prototype.sliderLogic = function (event) {
		
	setEventTargets(event);
	var startPosition, endposition, moduleSize;
	var targetSlider = eTarget.targetSlider;
		
	if (eTarget == targetSlider.arrow2 || eTarget == targetSlider.arrow1) {
	
		if (eTarget == targetSlider.arrow2) {
	
			var num = Math.ceil(targetSlider.slideTimes);
			num--;
		
			num != targetSlider.currentSlideIndex ? targetSlider.requestedSlideIndex = targetSlider.currentSlideIndex + 1 : targetSlider.requestedSlideIndex = targetSlider.currentSlideIndex;
		
		} else {
		
			targetSlider.currentSlideIndex == 0 ? targetSlider.requestedSlideIndex = targetSlider.currentSlideIndex : targetSlider.requestedSlideIndex = targetSlider.currentSlideIndex - 1;
		}		
	} else {
		
		targetSlider.requestedSlideIndex = eTarget.requestedIndex;
	
	}
		
	var result = targetSlider.currentSlideIndex - targetSlider.requestedSlideIndex;
	targetSlider.direction == 'horizontal' ? startPosition = targetSlider.sliding_div.style.left : startPosition = targetSlider.sliding_div.style.top;
	startPosition = parseInt(startPosition.replace('px', ''));
	startPosition = -startPosition;
				
	targetSlider.direction == 'horizontal' ? moduleSize = targetSlider.moduleWidth : moduleSize = targetSlider.moduleHeight;
			
	if (result != 0) {
	
		endPosition = targetSlider.keyhole_size * moduleSize * targetSlider.requestedSlideIndex;
		
		if (result < 0) {
		
			// move left
			var alreadySeen = (targetSlider.currentSlideIndex + 1) * targetSlider.keyhole_size;
			
			if (alreadySeen != targetSlider.sliding_div.childNodes.length) {
			
				if ((((targetSlider.requestedSlideIndex) * targetSlider.keyhole_size) + targetSlider.keyhole_size) > targetSlider.sliding_div.childNodes.length) {
				
					endPosition = ((targetSlider.keyhole_size * moduleSize * targetSlider.slideTimes) - (targetSlider.keyhole_size * moduleSize));
						
				} 
			}
		} 
								
		targetSlider.currentSlideIndex = targetSlider.requestedSlideIndex;
		
		// Set arrow images
		
		if (targetSlider.arrow1) {
			targetSlider.initializeArrows();
		}
		
		if (targetSlider.pageContainer) {
			targetSlider.initializePagination();
		}
		
		if (targetSlider.offerContainerArray) {
			targetSlider.initializeDealNumber();
		}
		
		targetSlider.move(startPosition, endPosition);
		
	}
	
}


Slider.prototype.move = function (start, end, targetSlider) {

	if (!targetSlider) {
		targetSlider = this;
	}
	
	if (targetSlider.sliding_div.interval) { clearInterval(targetSlider.sliding_div.interval); }
	
	var time = 0;
	var change = -(start - end);

	
	function tween () {
	
		time++;
		
		// Robert Penner Equation slightly modified		
		
		function easeOutCirc (time, startValue, change, duration) {
			return -(change * Math.sqrt(1 - (time=time/duration-1)*time) + startValue);
		}
		
		if (time > targetSlider.animationSpeed) {
			clearInterval(targetSlider.sliding_div.interval);
		} else {
			var newLocation = easeOutCirc(time, start, change, targetSlider.animationSpeed);
			targetSlider.direction == 'horizontal' ? targetSlider.sliding_div.style.left = newLocation + 'px' : targetSlider.sliding_div.style.top = newLocation + 'px';
		}
	}
	
	
	targetSlider.sliding_div.interval = setInterval(tween, targetSlider.animationSpeed);
	
}



Slider.prototype.initializeArrows = function (arrow1, arrow2) {

	/*
	
	Object arrow1 should always be either the left arrow or the down arrow. These arrows are turned off
	by default when the slider is initialized because if they were active, the resulting slide
	would create an empty keyhole.
	
	When first run, the function will always have the arguments passed. We embed the class into the arrows as a sub-object
	called arrowX.slider.
	
	If the function is called subsequently, we can reference the sub-object. As a result, we can have more than one
	slider on a page. As a result of the dual use, we reference "this" (the class) as targetSlider.
	
	*/
	
	var targetSlider;
	
	if (arguments.length) {
		this.arrow1 = this.checkObject(arrow1, 'string');
		this.arrow2 = this.checkObject(arrow2, 'string');
		
		this.arrow1.targetSlider = this;
		this.arrow2.targetSlider = this;
		
		targetSlider = this;
		
		addListener(this.arrow1, 'click', targetSlider.sliderLogic, false);
		addListener(this.arrow2, 'click', targetSlider.sliderLogic, false);
		
	} else {
	
		targetSlider = eTarget.targetSlider;
	}
	

			
	function setDisabledArrow (obj) {
	
		if (obj.nodeName == 'IMG') {
			var currentSrc = obj.getAttribute('src');
			var str;
			
			currentSrc.match('over.') ? str = 'over.' : str = 'normal.';
			if (str == 'over.') { obj.removeAttribute('style'); }	
		
			obj.setAttribute('src', obj.getAttribute('src').replace(str, 'disabled.'));
			removeListener(obj, 'mouseover', swapImageLogic, false);
			removeListener(obj, 'mouseout', swapImageLogic, false);
		
		}
	}
	
	function setNormalArrow(obj) {
	
		if (obj.nodeName == 'IMG') {
		
			currentSrc = obj.getAttribute('src');
			var result = currentSrc.match('disabled.');
			
			if (result) {
				
				addListener(obj, 'mouseover', swapImageLogic, false);
				addListener(obj, 'mouseout', swapImageLogic, false);
				obj.setAttribute('src', obj.getAttribute('src').replace('disabled.', 'normal.'));
			
			}
		}
	}
	
	
	if (this.slideTimes > 1) {
		
		if (this.arrow1.style.display == 'none') {
		
			this.arrow1.style.display = 'block';
			this.arrow2.style.display = 'block';
		
		}
	
	
		if (this.currentSlideIndex != 0) {
			setNormalArrow(this.arrow1)
		}
		
		if (this.currentSlideIndex == 0 && !arguments.length) {
			setDisabledArrow(this.arrow1);
		}
		
		if (this.currentSlideIndex < Math.ceil(this.slideTimes) - 1) {
			setNormalArrow(this.arrow2)
		}
		
		if (!arguments.length && this.requestedSlideIndex == Math.ceil(this.slideTimes) - 1) {
			setDisabledArrow(this.arrow2);
		}
	} else {
	
		this.arrow1.style.display = 'none';
		this.arrow2.style.display = 'none';
	
	}
				
}


Slider.prototype.initializeTabs = function (array, searchTerm) {

	// needs to be changed to handle text based tabs

	
	var targetSlider;
	
	if (arguments.length && !event) {
		this.tabArray = array;
		targetSlider = this;
	}
	
	
	if (event) {
		if (event.type == 'click' || event.type == 'onclick') {
			setEventTargets(event);
			targetSlider = eTarget.targetSlider;
			
			if (targetSlider.sliding_div.interval) {
				clearInterval(targetSlider.sliding_div.interval);
			}
			
			
			
			targetSlider.sliding_div = eTarget.targetDiv;
			searchTerm = targetSlider.sliding_div.getAttribute('id');
		}
	}
	
		
	for (var x = 0; x < targetSlider.tabArray.length; x++) {

		var result, pattern;
		var img = targetSlider.tabArray[x].getElementsByTagName('IMG')[0];
		
		if (arguments.length && !event && !targetSlider.deepLink) {
			addListener(img, 'click', this.initializeTabs, false);
			img.targetSlider = this;
			img.targetDiv = this.checkObject(navArray[x], 'string');
		}
		
		if (arguments.length) {
			addListener(img, 'mouseover', swapImageLogic, false);
			addListener(img, 'mouseout', swapImageLogic, false);
		}
		
		if (searchTerm == navArray[x]) {
		
			if (event) {
				img.setAttribute('src', img.getAttribute('src').replace('_over.', '_disabled.'));
			} else {
				img.setAttribute('src', img.getAttribute('src').replace('_normal.', '_disabled.'));
			}
			
		} else if (event && searchTerm != navArray[x]) {
			img.setAttribute('src', img.getAttribute('src').replace('_disabled.', '_normal.'));
		
		}
	}
	
	
	/* 
	
	If deep linking is not enabled, this function should effect the layout of the page.
	
	Other than the initial call, this is the ONLY function that should effect a change this drastic.
	
	*/

	if (event && !targetSlider.deepLink) {
	
		targetSlider.currentSlideIndex = 0;
		targetSlider.requestedSlideIndex = 0;
	
		targetSlider.initializeVariables();
		targetSlider.setLayout();
		
		if (targetSlider.sliding_div.interval) { 
			clearInterval(targetSlider.sliding_div.interval);
		}
	
		if (targetSlider.arrow1) {
			targetSlider.initializeArrows();
		}
		
		if (targetSlider.pageContainer) {
			targetSlider.initializePagination();
		}
		
		if (targetSlider.expandButton) {
			targetSlider.expandAndCollapse();
		}
		
		if (targetSlider.offerContainerArray) {
			targetSlider.initializeDealNumber();
		}
	}	
}


Slider.prototype.initializePagination = function (obj) {

	/*
	
	When coding the page, obj should always be a block level element.
	It should also always be the master container for the elements you want to effect.
	
	Images or text can be used to represent the page number.
	
	If a text based structure is used, please be sure to contain the node within a LI.
	The LIs should be siblings to eachother in the UL - which must be the master container (obj).
	The proper structure is: UL > LI > #text
	
	Image based structures must keep the images in the same master containter (obj).
	They should all be inline and siblings. Do not structurally separate the images.
	The proper structure is: Block Level Element > IMG
		
	Regardless of a text or image based structure, do not contain the IMG or Text in an A tag.
	
	*/

	var targetSlider;
	var childType;
	var sourcePath;
	
	if (arguments.length) {
		targetSlider = this;
		targetSlider.pageContainer = this.checkObject(obj, 'string');
		
		if (arguments.length > 0) {
			targetSlider.paginationImgSource = arguments[1];
			if (arguments[2]) {
				targetSlider.paginationImgExt = arguments[2];
			}
			if (arguments[3]) {
				targetSlider.paginationImgSize = arguments[3];
			}
			
		}
		
		if (!targetSlider.deepLink) {
			addListener(targetSlider.pageContainer, 'click', stopEvents, false);
		}
		
	} else {
		targetSlider = eTarget.targetSlider;		
	}
	

	if (targetSlider.slideTimes > 1) {

		if (targetSlider.pageContainer.style.display == 'none') {
			targetSlider.pageContainer.style.display = 'block';
		}


		while (targetSlider.pageContainer.firstChild) {
			targetSlider.pageContainer.removeChild(targetSlider.pageContainer.firstChild);
		}
		
		if (targetSlider.pageContainer.nodeName == 'UL') {
			childType = 'LI'
		} else {
			childType = 'IMG';
			if (targetSlider.paginationImgSource == undefined) {
				targetSlider.paginationImgSource = 'images/';
			}
			if (targetSlider.paginationImgExt == undefined) {
				targetSlider.paginationImgExt = '.gif';
			}
			
			if (targetSlider.paginationImgSize == undefined) {
				targetSlider.paginationImgSize = new Array(17, 17);
			}
		}
		
		
		for (var x = 0, y = 1; x < Math.ceil(targetSlider.slideTimes); x++, y++) {
		
			var newChild = document.createElement(childType);
			
			if (newChild.nodeName == 'IMG') {
			
				var modifier = 'normal';
			
				if (x == Math.ceil(targetSlider.currentSlideIndex)) {
					modifier = 'selected';
				} else {
				
					addListener(newChild, 'mouseover', swapImageLogic, false);
					addListener(newChild, 'mouseout', swapImageLogic, false);
				
				}
				
				newChild.setAttribute('src', targetSlider.paginationImgSource + 'button_page_' + y + '_' + modifier + targetSlider.paginationImgExt);
				newChild.setAttribute('width', targetSlider.paginationImgSize[0] + 'px');
				newChild.setAttribute('height', targetSlider.paginationImgSize[1] + 'px');
				newChild.setAttribute('alt', 'Page ' + y);
			
			} else {
				
				var eText = document.createTextNode(y);
				newChild.appendChild(eText);
				
				if (x == targetSlider.currentSlideIndex) {
					newChild.hasAttribute ? newChild.setAttribute('class', 'selected') : newChild.className = 'selected';
				} else {
					addListener(newChild, 'mouseover', slider_changeTextBg, false);
					addListener(newChild, 'mouseout', slider_changeTextBg, false);
				}		
			}
	
			newChild.targetSlider = this;
			newChild.requestedIndex = x;
			
			addListener(newChild, 'click', targetSlider.sliderLogic, false);
			targetSlider.pageContainer.appendChild(newChild);
		
		}
	} else {
	
		targetSlider.pageContainer.style.display = 'none';
	
	}
}





Slider.prototype.expandAndCollapse = function (event) {

	if (event) {
		setEventTargets(event);
		targetSlider = eTarget.targetSlider;
	}


	if (targetSlider.sliding_div.interval) { 
		clearInterval(targetSlider.sliding_div.interval);
	}
	
	if (targetSlider.keyhole_div.style.height != 'auto') {
	
		// this part of the if/else expands the content
	
		targetSlider.keyhole_div.style.height = 'auto';
		targetSlider.sliding_div.style.position = 'relative';
		targetSlider.sliding_div.style.width = 'auto';
		targetSlider.sliding_div.style.height = Math.ceil(targetSlider.slideTimes) * targetSlider.moduleHeight + 'px';
		targetSlider.sliding_div.style.left = '0px';
		targetSlider.sliding_div.style.top = '0px';
		targetSlider.arrow1.style.display = 'none';
		targetSlider.arrow2.style.display = 'none';
		
		if (targetSlider.pageContainer) {
			while (targetSlider.pageContainer.firstChild) {
				targetSlider.pageContainer.removeChild(targetSlider.pageContainer.firstChild);
			}
		}
		
		if (targetSlider.offerContainerArray) {
		
			for (var x = 0; x < targetSlider.offerContainerArray.length; x++) {
			
				while (targetSlider.offerContainerArray[x].firstChild) {
					targetSlider.offerContainerArray[x].removeChild(targetSlider.offerContainerArray[x].firstChild);
				}
			}
		}
		
		
		if (targetSlider.expandButton.nodeName == 'IMG') {
			targetSlider.expandButton.setAttribute('src', targetSlider.expandButton.getAttribute('src').replace('_expand_', '_collapse_'));
		} else {
			targetSlider.expandButton.originalText = targetSlider.expandButton.firstChild.nodeValue;
			targetSlider.expandButton.firstChild.nodeValue = 'Collapse to slide';
		}
		
	} else {
	
		targetSlider.keyhole_div.style.height = targetSlider.moduleHeight + 'px';
		targetSlider.sliding_div.style.position = 'absolute';
		
		if (targetSlider.direction == 'horizontal') {
			targetSlider.sliding_div.style.width = targetSlider.width + 'px';
			targetSlider.sliding_div.style.height = targetSlider.moduleHeight + 'px';
			targetSlider.sliding_div.style.left = - targetSlider.currentSlideIndex * targetSlider.moduleWidth * targetSlider.keyhole_size + 'px';
			
			if (targetSlider.slideTimes.toString().match('.') && targetSlider.currentSlideIndex == Math.floor(targetSlider.slideTimes)) {
				targetSlider.sliding_div.style.left = -((targetSlider.keyhole_size * targetSlider.moduleWidth * targetSlider.slideTimes) - (targetSlider.keyhole_size * targetSlider.moduleWidth)) + 'px';
			}
			
			
		} else {
			targetSlider.sliding_div.style.width = targetSlider.moduleWidth + 'px';
			targetSlider.sliding_div.style.height = targetSlider.height + 'px';
			targetSlider.sliding_div.style.top = targetSlider.currentSlideIndex * (targetSlider.moduleHeight * targetSlider.keyhole_size) + 'px';
		}
		
		if (targetSlider.expandButton.nodeName == 'IMG') {
			targetSlider.expandButton.setAttribute('src', targetSlider.expandButton.getAttribute('src').replace('_collapse_', '_expand_'));
		
		} else {
			targetSlider.expandButton.firstChild.nodeValue = targetSlider.expandButton.originalText;
		}
		
		targetSlider.arrow1.style.display = 'inline';
		targetSlider.arrow2.style.display = 'inline';

		
		if (targetSlider.pageContainer) {
			targetSlider.initializePagination();
		}
		
		if (targetSlider.offerContainerArray) {
			targetSlider.initializeDealNumber();
		}
	}
}		



Slider.prototype.initializeExpandButton = function (obj) {

	obj = this.checkObject(obj, 'string')
	obj.targetSlider = this;
	this.expandButton = obj;

	addListener(obj, 'click', this.expandAndCollapse, false);
	
	if (obj.nodeName == 'IMG') {
		addListener(obj, 'mouseover', swapImageLogic, false);
		addListener(obj, 'mouseout', swapImageLogic, false);
	
	}
}


Slider.prototype.initializeDealNumber = function (array, str, layout, targetOfferNode, targetOfferClass, targetPaneNode, targetPaneClass) {

	/*
	
	array is either one or many objects that we want to write the xx of xx into. For example,
	as of this writing, the Saving Center has the xx of xx in two places while CPC Special deals
	has it in ony one.
	
	str represents what the "offer" is. In one case the offer might be xx of xx deals, in another xx of xx results or xx of xx offers.
	
	layout dictates the placement of str. NULL is the default value - which is after the xx of xx. Anything other than NULL will result
	in final rendered text that reads str xx of xx. For example, the CPC Special Offers page reads Offer 1 of 4 while Savings Center
	reads 1-5 of 50 Deals.
	
	Most sliders will only need to define the first 3 arguments.
	
	this.keyhole_size determines whether or not the string will read "xx of xx" or "xx - xx of xx". If the keyhole size is greater than one
	the latter will be used. This basic logic has a major problem when dealing with complex layout sliders like the Savings Center, in which
	the keyhole_size is 1, but 5 or 6 offers are displayed at a time. Consequently, we use the concept of a pane.
	
	Conceptually, a pane is a group of offers that cannot be expressed with simple page structure. Most sliders, like CPC Special Deals,
	OXO, Staples brand shredder microsite, and the Back To School retail page structurally rely upon each offer being a sibling to the next.
	
	A slider like the Savings Center slider does not fit that mold. Instead, the offers are deeply nested within divs. There is no structural
	affinity to rely upon. Consequently, panes must be used to describe how many offers and which set of offers are visible.
	
	Panes may need to be used when a developer needs to make one offer look different than several others, but display them all at once. 
	Or, a developer may need to stack offers on top of eachother, like in the Saving Center slider. 
	Or, a developer may need to vary the amount of offers displayed between tabs. 
	Again, the best example	of all three situations (and all at once) is the Saving Center Slider as it was written in June, 2009.
	
	This script accounts for several different types of structure. One assumes each child of the sliding_div is an offer.
	Another assumes that a developer might only need to target a particular type of element. 
		
	Because the script can handle many different types of layout, targetOfferNode and targetOfferClass are optional. If structure cannot be used
	to create affinity of offers, targetOfferNode can be defined. It should always be a block level element and passed as a string. 
	targetOfferNode can be used independantly of targetOfferClass. For example, all of the product names in a particular slider
	might contained as text nodes in H3 tags. If the H3 tags are unique in the structure (meaning, they only appear in a div and are only used to describe the product name) 
	the structure of a nodeList can be relied upon. A node list is what the script will define if targetOfferNode is defined.
	
	If further clarification is needed, targetOfferClass should be defined.
	For example, if a div with a class of "productName" has nested or sibling divs, the script can find focus by looking for the class which should have
	been used uniquely withing each offer module.
	
	As mentioned above, targetPaneNode accomodates a very complex slider like Savings Center which has a different layouts between sliders.
	As of this writing, the Featured Weekly Deals tab displays 5 deals at a time while the Clearance Center displays 6 deals at a time.
	targetPaneNode is used to identify all of the panes. Once found, the script examines each pane to find the maximum offers shown. This technique
	anticipates varying quantities in each pane and maintains consistency when describing xx - xx of xx offers.
	
	Much like targetOfferClass, targetPaneClass is also optional. It is used by the script just like targetOfferClass when further clarification is needed.
	
	*/

	var targetSlider;
	var	totalOffers = 0;
	var currentOffers;
	var list;
	var xxOfxxStr;


	if (event) {
		targetSlider = eTarget.targetSlider
	} else {
		targetSlider = this;
	}
	
	
	if (arguments.length) {
	
		if (typeof(array) == 'string') {
			array = new Array(targetSlider.checkObject(array, 'string'));
		} 
		
		targetSlider.offerContainerArray = array;
		
		if (targetOfferNode) {
			targetSlider.targetOfferNode = targetOfferNode;
		}
		
		if (targetOfferClass) {
			targetSlider.targetOfferClass = targetOfferClass;
		}
		
		if (targetPaneNode) {
			targetSlider.targetPaneNode = targetPaneNode;
		}
		
		if (targetPaneClass) {
			targetSlider.targetPaneClass = targetPaneClass;
		}
		
		targetSlider.offerText = str;
		targetSlider.offerLayout = layout;
		
	}
	
	
	if (targetSlider.slideTimes > 1) {
	
		if (targetSlider.offerContainerArray[0].style.display == 'none') {
		
			for (var x = 0; x < targetSlider.offerContainerArray.length; x++) {
				targetSlider.offerContainerArray[x].style.display = 'block';
			
			}
		}
	
		// determine total number of offers in the sliding_div
		
		if (targetSlider.targetOfferNode) {
		
			var list = targetSlider.sliding_div.getElementsByTagName(targetSlider.targetOfferNode.toUpperCase());
			
			if (targetSlider.targetOfferClass) {
			
				for (var x = 0; x < list.length; x++) {
					if (list[x].className && list[x].className == targetSlider.targetOfferClass) {
						totalOffers++;
					}
				}
			} else {
				totalOffers = list.length;
			}	
		} else {
			totalOffers = targetSlider.sliding_div.childNodes.length;
		
		}	
		
		
		
	
		// determine what offers we are looking at
		
		
		if (!targetSlider.targetPaneNode) {
		
			if (targetSlider.keyhole_size == 1) {
		
				xxOfxxStr = (targetSlider.currentSlideIndex + 1) + ' of ' + totalOffers;
	
			} else {
			
				var tempList, currentOffer, endRangeOffer;
			
				if (targetSlider.targetOfferNode) {
					tempList = document.getElementsByTagName(targetSlider.targetOfferNode.toUpperCase());
					
				} else {
					tempList = targetSlider.sliding_div.childNodes.length;
				}
											
				endRangeOffer = (targetSlider.currentSlideIndex + 1) * targetSlider.keyhole_size;
				
				if (endRangeOffer > totalOffers) {
					endRangeOffer = totalOffers;
				}
				currentOffer = endRangeOffer - (targetSlider.keyhole_size - 1);
				
				//xxOfxxStr = currentOffer + ' - ' + endOffer + ' of ' + totalOffers;
				xxOfxxStr = currentOffer + ' - ' + endRangeOffer + ' of ' + totalOffers;
								
			}
					
		} else {
		
			var paneList, currentOffer, endRangeOffer;
	
			paneList = targetSlider.sliding_div.getElementsByTagName(targetSlider.targetPaneNode);
					
			if (targetSlider.targetPaneClass) {
			
				var tempList = new Array();
				
				for (var x = 0; x < paneList.length; x++) {
				
					if (paneList[x].className && paneList[x].className == targetSlider.targetPaneClass) {
						tempList.push(paneList[x]);
					
					}
				}
				
				paneList = tempList;
			
			} 		
			
			// determine the largest amount of offers being shown in one pane.
			// also determine how many total offers (including the ones visible) we have seen
			
			var offerCount = 0;
			var currentViewable = 0;
			
			for (var x = 0; x < paneList.length; x++) {
			
				var offerList = paneList[x].getElementsByTagName(targetSlider.targetOfferNode);
				var offersInThisPane = 0;
	
				if (targetSlider.targetOfferClass) {
				
					offersInThisPane = 0;
				
					for (var y = 0; y < offerList.length; y++) {
					
						if (offerList[y].className && offerList[y].className == targetSlider.targetOfferClass) {
							offersInThisPane++;
						}
					}
					
				} else {
				
					offersInThisPane = offerList.length
				}
									
				if (x <= targetSlider.currentSlideIndex) {
					offerCount += offersInThisPane;
					
					if (x == targetSlider.currentSlideIndex){
						currentViewable = offersInThisPane;
					}
				}
			}
					
			endRangeOffer = offerCount;
			currentOffer = offerCount - currentViewable + 1;
			
			xxOfxxStr = currentOffer + ' - ' + endRangeOffer + ' of ' + totalOffers;
			
		}
		
		for (var x = 0; x < targetSlider.offerContainerArray.length; x++) {
			
			while (targetSlider.offerContainerArray[x].firstChild) {
				targetSlider.offerContainerArray[x].removeChild(targetSlider.offerContainerArray[x].firstChild);
			}
			
			var text;
			
			if (targetSlider.offerLayout != null) {
				text = document.createTextNode(targetSlider.offerText + ' ' + xxOfxxStr);
			
			} else {
				text = document.createTextNode(xxOfxxStr + ' ' + targetSlider.offerText);
			}
		
			targetSlider.offerContainerArray[x].appendChild(text);
		}
		
	} else {
	
		for (var x = 0; x < targetSlider.offerContainerArray.length; x++) {
		
			targetSlider.offerContainerArray[x].style.display = 'none';
		
		}
	}
}




function slider_changeTextBg (event) {

	setEventTargets(event);
	
	if (event.type == 'mouseover' || event.type == 'onmouseover') {
		eTarget.hasAttribute ? eTarget.setAttribute('class', 'requested') :  eTarget.setAttribute('className', 'requested');
	} else {
		eTarget.hasAttribute ? eTarget.removeAttribute('class') :  eTarget.removeAttribute('className');
	}

}


/*     Runtime     */

// event Keyword fix for FireFox

if (navigator.userAgent.match(/firefox/gi)) {
	event = window.event;
}
