/* part of dean edwards IE scripts */
function addClass(element, className) {
if (!hasClass(element, className)) {
	if (element.className) element.className += " " + className;
 	else element.className = className;
 	}
};

function removeClass(element, className) {
  var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)");
  element.className = element.className.replace(regexp, "$2");
};

function hasClass(element, className) {
  var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)");
  return regexp.test(element.className);
};

// array has function.
Array.prototype.has = function(t) {
	/*@cc_on
	 /*@if(@_jscript_version <= 5.1)
	   if(typeof(this.t) === undefined) {return false;}
	 @else @*/
	   if(!(t in this)) { return false;}
	 /*@end
	 @*/
	 return true;
}

/* prevent IE memory leaks.  i think i might want to run this on safari to.. the vm is a little scary */
function purge(d) {
	if(!d) { return; }
	// prevent IE memory leaks.
	var a,i,l,n;
	var at = true;
	
	/*@cc_on
	  /*@if(@_jscript_version <= 5.1)
		if(typeof(d.attributes) === undefined) {at=false;}
	  @else @*/
	  	if(!("attributes" in d)) {at = false;}
	  /*@end
	@*/
	
	if(at){a = d.attributes, i, l, n;}

    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    
   var cn = true;
   
   /*@cc_on
	  /*@if(@_jscript_version <= 5.1)
		if(typeof(d.childNodes) === undefined) {cn=false;}
	  @else @*/
	  	if(!("childNodes" in d)) {cn = false;}
	  /*@end
	@*/

    if(cn){a = d.childNodes;}
    
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            purge(d.childNodes[i]);
        }
    }
}
					

//console.log('purge parsed');

/* cross platform . query */
function getElementsByClass(searchClass,node,tag) {
	
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	
	/* IE 5 support */
	
	var els = node.getElementsByTagName(tag);
	if(tag=='*' && (!els || !els.length)) {els = node.all;}
		
	var elsLen = els.length;
	var pattern = searchClass;
	if(typeof(searchClass) == 'string')
		{
		pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
		}
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	var endTime = new Date().getTime();
	return classElements;
}

//console.log('events and styles');


/* cross platform get computed style function */
function getStyle(oElm, strCssRule){
	var strValue = "";
	if(document.defaultView && document.defaultView.getComputedStyle){
		strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
	}
	else if(oElm.currentStyle){
		if(DEF_IE_VERSION < 5.5)
			{
			var matches = strCssRule.split(/\-/g);
			strCssRule = matches[0];
			for(var i=1;i<matches.length;i++)
				{
				var upCase = matches[i].substr(0,1)
				strCssRule += upCase.toUpperCase();
				strCssRule += matches[i].substr(1);
				}
			}
		else
			{
				strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
			return p1.toUpperCase();});
			}
		strValue = oElm.currentStyle[strCssRule];
	}
	return strValue;
}


//console.log('finished utils');
/* AG_Carousel
/ Class definition for AG_Carousel
*/

var storedEvent = null; //fix an ie event bug where it loses track of the event

function AG_Carousel(myname,mytagID,mynumber)
	{
	
	// fisrt make sure we're able to even do this...
	
	if(DEF_IE_VERSION < 5.5) // doesn't work in IE5
		{
		baseDiv = document.getElementById(mytagID);
		addClass(baseDiv,'inactive');
		this.active = false;
		return false;
		}
		
	
	
	//carousel class variables
	// identification and set up..
	this.active = true;
	this.thename = myname; // unique name fo the carousel
	this.tagID = mytagID; // the tag which is converted into a carousel
	this.thenumber = mynumber;  // a guess at the number of items in the carousel
	this.currentlyShown = 0; // item currently shown
	this.oldShown = 0; // last item shown
	
	// user addressable - change these outside the script to adjust the behavior
	this.animSpeed = .05;  // the animation speed.
	this.slowAnimSpeed = .35; // the animation speed for the slow, automatic turn;

	// variables used to control the animation
	this.inAnimate = false;
	
	this.animTimer = null; // timer hold for movement animation
	this.autoTimer = null; // timer hold for auto animation
	this.autoStopper = null; // stop delay for snap too
	this.counter = 0; // animation counter
	this.animDistance = 0;
	this.snapDistance = 0;
	this.snapSpeed = .2; // animation speed for snap to
	this.currentDistance = 0;
	this.autoAnimate = false; // currently in slow spin?
	this.direction = null; // direction of travel
	this.distance = null; // number of NODES to travel
	this.nearestNode = false; // snap to destination
	this.storedCommand = null; // command which excutes after snap too.
		
	// internals, inited by the activate routine
	this.items = new Array(mynumber);
	this.baseDiv = null;
	this.parade = null;
	this.navDiv = null;
	this.navElements = new Array();
	
	// whether we wait a small amount of time before popping the last item
	// of the array.
	this.delayPop = false; // don't wait by default
	
	this.oldSaf = false; // older versions of safari?  they've got needs
		
	var node= this;  // keep a reference to ourselves since this is not always equal to us when we're called through an event.
	
	this.animSpeedOld = node.animSpeed;  // hang onto this in two places for the auto animate.
	
	
	/* activate
	/  call this on your carousel after you have created it to assign events to the navigation controls and to double check
	/  the number of items in your carousel.
	*/

	this.activate = function() { with (this) {
	
	
	if(/WebKit/i.test(navigator.userAgent))
		{ 
			 var webKitFields = RegExp("( AppleWebKit/)([^ ]+)").exec(navigator.userAgent);
   			 var version = parseFloat(webKitFields[2]);
			 if(version <= 412)
				{
				oldSaf = true;
				}
		}
	
	// find all the parts to the carousel
	baseDiv = document.getElementById(tagID);
	// debugger;
	var parades = getElementsByClass("carousel_parade",baseDiv,'div');
	var navDivs = getElementsByClass("carousel_nav",baseDiv,'div');
	parades[0].id = myname+'_parade_main';
	navDivs[0].id = myname+'_nav_main';
	
	parade=document.getElementById(myname+'_parade_main');
	navDiv=document.getElementById(myname+'_nav_main');
	
	if(!navDiv || !parade) { return false;} // die if we're not set up right.
	
	items = getElementsByClass("carousel_item",baseDiv,'div');
	
	for(var i=0;i<items.length;i++)
		{
		items[i].id = myname+'_element_'+i;
		}
	// i wonder if the user told us right?  assume not.	
	
	thenumber = items.length;	
	
	// set up the navigation controls.  navLinks won't hang around for long - we just
	// use it here to tidy up the logic a bit.	
	var navLinks = navDiv.getElementsByTagName('A');

		for(var i = 0;i<navLinks.length;i++)
			{
				if(hasClass(navLinks[i],'left_arrow'))
					{
						addEvent(navLinks[i],'click',function(e){node.navigate(e);});
					}
				if(hasClass(navLinks[i],'right_arrow'))
					{
						addEvent(navLinks[i],'click',function(e){node.navigate(e);});
					}
				if(hasClass(navLinks[i],'auto'))
					{
						addEvent(navLinks[i],'click',function(e){node.navigate(e);});
						autoNode = navLinks[i];
					}
				if(navLinks[i].className == '') // only if it's blank right...
					{
					navElements[navElements.length] = navLinks[i];
					}
			}		
	
	if(navElements.length != items.length)
			{
				// match the number of navigational items to the number of carousel items.
				var shortfall;
				shortfall = (navElements.length - items.length);
				var navArea = navElements[0].parentNode;
				var currentLength = navElements.length;
				
				if(navElements.length < items.length)
					{	
					shortfall = Math.abs(shortfall);
					for(var i = 0;i<shortfall;i++)
						{
							// DOM magic.
							var newNode = document.createElement('a'); // create a new nav item;
							newNode.innerHTML = currentLength+1+i+'';
							newNode.setAttribute('href','');
							navArea.insertBefore(newNode,navElements[navElements.length-1].nextSibling);
							navElements[navElements.length] = newNode;
						}	
					}
				else if(navElements.length > items.length)
					{
					for(var i = 0;i<shortfall;i++)
						{
						var anyLeft = navArea.removeChild(navElements.pop()); // and then the fo'real last node;
						if(navElements.length == 0)
							{
								baseDiv.style.display = 'none';  // hide the carousel if it doesn't have anything in it.
								return false;
							}
						}
					}		
			}
	
	// here's the important bit.  attach controls to the function.	
	for(var i=0;i<navElements.length;i++)
		{
			addEvent(navElements[i],'click',function(e){node.navigate(e);});
			navElements[i].name = i;
		}	
	
	//console.log('sniff the kit');
	//console.log(navigator.userAgent);
	
	if(oldSaf || (DEF_IE_VERSION != DEF_NOT_IE))
		{
		// ie looks here first, so put some stoppers in the href for it too.
		addEvent(document,'scroll',function() {parade.innerHTML += '';});
				for(var i=0;i<navLinks.length;i++)
					{
					navLinks[i].setAttribute("href","javascript:return false;");
					}
					
		}
		
	

	// mark the current node and we're ready to rock.
	addClass(navElements[currentlyShown],'current');
	//	navElements[currentlyShown].className = 'current';
	
	return true;
	
	}};
	
	/* highlight
	/  handle the class change on the controls to indicate the current item
	*/
	this.highlight = function() { with (this) {
		////console.log('highlight '+currentlyShown);
		removeClass(navElements[oldShown],'current');
		addClass(navElements[currentlyShown],'current');
	}};
	
	/* popItem, pushItem
	/ these function do exactly what you think they'd do given the names.
	/ push or pop items off one end of the carousel.
	*/
	this.popItem = function () { with (this) {
		var firstNode = parade.firstChild;
		while(!hasClass(firstNode,'carousel_item'))
			{
				firstNode = firstNode.nextSibling;
			}
		firstNode = parade.removeChild(firstNode);
		return parade.insertBefore(firstNode,this.lastItem().nextSibling);
	}};
	
	this.pushItem = function () {with (this) {
		var lastNode = parade.lastChild;
		while(!hasClass(lastNode,'carousel_item'))
			{
				lastNode = lastNode.previousSibling;
			}
		lastNode = parade.removeChild(lastNode);
		return parade.insertBefore(lastNode,this.firstItem());
		
	}};
	/* firstItem, lastItem
	/ i'm actually not sure these are in use any more
	/
	*/
	this.firstItem = function () {with (this) {
		var firstNode = parade.firstChild;
		while(!hasClass(firstNode,'carousel_item'))
			{
				firstNode = firstNode.nextSibling;
			}
		return firstNode;
	}};
	
	this.lastItem = function () {with (this) {
		var lastNode = parade.lastChild;
		while(!hasClass(lastNode,'carousel_item'))
			{
				lastNode=lastNode.previousSibling;
			}
		return lastNode;
	}};
	
	/* nextItem, prevItem
	/ functions that find the next item and the previous item in the carousel parade, respectively.
	*/
	this.nextItem = function() { with (this) {
		var theNextItem = (currentlyShown + 1) > thenumber ? (currentlyShown+1)-(thenumber+1) : currentlyShown + 1;
		return theNextItem;
	}};
	
	this.prevItem = function() { with (this) {
		var thePrevItem = (currentlyShown - 1) < 0 ? (currentlyShown-1)+(thenumber+1): currentlyShown - 1;
		return thePrevItem;
	}};
	
	/* animate (item, d)
	/   item - the destination of the animation in 0 start distance from the front.
	/   d - a delayed action.  since animate is used to perform the snap to, the optional d argument executes after
	/	   the animation is complete.
	/	
	/  the main work function. this one handles moving the items around in the dom, as well as changing the positioning
	/  of them.
	*/
	
	this.animate = function(item,d) { with (this) {
		
		// item = item || currentlyShown; // nulls in item are BAD news.
		d = d || false;  // make sure the delayed action flag is set to true.
			
				
		var cP = Math.pow(Math.sin(Math.PI * counter / 2), 0.75); // ease function
		
		// //console.log('in animate');
		
		////console.log("run setup");
		inAnimate = true;
		/* begin setup for animation */
				
		if(snapDistance != 0 && counter == 0) { 	item = node.findPosition(); }
		
		// find the shortest route...
		
		var distanceFromBack = (thenumber) - currentlyShown;
		var distanceFromFront = currentlyShown;
		
		var distanceRight;
		var distanceLeft;
		
		var targetDistanceFromFront = item;
		var targetDistanceFromBack = (thenumber) - item;
		
		if(targetDistanceFromFront > distanceFromFront)
			{
			distanceRight = targetDistanceFromFront - distanceFromFront;
			distanceLeft = distanceFromFront + targetDistanceFromBack;
			}
		else if (targetDistanceFromFront < distanceFromFront)
			{
			distanceLeft = distanceFromFront - targetDistanceFromFront;
			distanceRight = distanceFromBack + targetDistanceFromFront;
			}
		else
			{
			if(!autoAnimate && nearestNode != 2)
				{
				clearInterval(animTimer);
				animTimer = setInterval(function() { with(this){
					inAnimate = true;
					if(navElements[currentlyShown].style.color != 'rgb(255, 0, 0)' && navElements[currentlyShown].style.color != '#ff0000')
						{
							navElements[currentlyShown].style.color = '#FF0000';
						}
					else
						{
							navElements[currentlyShown].style.color = '#000000';
						}
					return;
				}}, 50);
				setTimeout(function() { with(this){
					clearInterval(animTimer);
					navElements[currentlyShown].style.color = '';
					inAnimate = false;}},325);
				return; // now quit with this stuff...
				}
			}
								
		direction = (distanceLeft < distanceRight) ? 'left':'right';
		distance = (distanceLeft < distanceRight) ? (distanceLeft)*-1:distanceRight;
		
		if(distance > 1) { delayPop = true; }
		else { delayPop = false;}
		
		
		if(counter == 0)
			{		
				/* if(currentlyShown+distance < 0) { nextItem = thenumber + (currentlyShown+distance);}
				if(currentlyShown+distance >= thenumber) {nextItem = thenumber - Math.abs(currentlyShown+distance);} */
				
				if(direction == 'left') // if we're going to the left pull items off the end so it doesn't look like crap...
				{
				var offset = 0;
					for(var i=0;i<Math.abs(distance);i++)
								{
									var opNode = pushItem();
									offset += opNode.offsetWidth;
								}
				parade.style.left = '-'+offset+'px';
				currentDistance = offset*(-1);
				}
				
				if(snapDistance !=0)
				{
					currentDistance = snapDistance;
				}
								
			/*//console.log('target node '+item);
			//console.log('distance left'+distanceLeft);
			//console.log('distance right'+distanceRight);*/
			}
			
	
		 
		if(!animDistance)
			{							
				var t = 0;
				
				if(snapDistance != 0)
					{
						if(item==currentlyShown) 
							{
							animDistance = snapDistance;
							direction = 'left';
							}
						else
							{
							animDistance = document.getElementById(myname+'_element_'+currentlyShown).offsetWidth;
							animDistance += snapDistance;
							direction = 'left';
							}
					}
				else
					{
					while(t != distance)
						{
												
						var oldt = t;
												
						t = (direction == 'left') ? t-1:t;			
							
						var getNode = currentlyShown + t;
								
						if(getNode < 0) {getNode = thenumber + getNode;}
						if(getNode >= thenumber) {getNode = getNode-thenumber;}
						
						
						animDistance += document.getElementById(myname+'_element_'+(getNode)).offsetWidth;
											
						
						t = (t == oldt) ? t+1: t;
						
						}
						
						animDistance = (direction == 'right') ? animDistance + 12: animDistance;
						
						if(snapDistance != 0)
							{
								if(item == currentlyShown)
						
						animDistance += snapDistance;
						}
					}
			}
			
		if(nearestNode == true)
			{
			////console.log("stop issued");
			snapDistance = parseInt(parade.style.left); //determine how far left or right we need to go.
			animDistance = 0;
			nearestNode = 2; // if you snap, you may do something else as soon as you're done.
			if(counter < 1) {d = false;} // don't let the secondary fire until we've arrived there.
			counter = 0;
			oldAnimSpeed = animSpeed;
			animSpeed = snapSpeed;
			inAnimate = false;
			return; // nothing more to do here.
			}	
		else if(nearestNode == 2 && snapDistance != 0)
			{
				if(counter >= 1) { d=true;} // set this to fire on the end of the snap;
			}
		
		inAnimate = true;	
		/* end setup for animation */
		
				
		if(counter < 1)
			{
				/* the heart of the matter. move it around then. */
				////console.log(animDistance);
				
				if(autoAnimate)
					{
					currentDistance += 5*animSpeed;
					parade.style.left = '-'+currentDistance+'px';
					}
				else
					{
					if(direction == 'right')
						{
						parade.style.left = currentDistance - ((animDistance * cP))+'px';
						}
					else if (direction == 'left')
						{
						parade.style.left = currentDistance + ((animDistance * cP))+'px';
						}
					}
				if(autoAnimate) { counter = currentDistance / animDistance;}
				else {counter += animSpeed;}
			}
				
		if(counter >= 1)
			{	
				clearInterval(animTimer);
				counter=0;
				oldShown = currentlyShown;
				
				if(nearestNode == 2) { distance = 0;}
				if(nearestNode == 2 && animDistance > 0) { distance = 1;}
										
				currentlyShown = currentlyShown + distance;
				
				
				// //console.log(distance);
				
				if(direction == 'left')
					{		
					parade.style.left = '0px';
					}
				
				if(direction == 'right')
					{
							if(delayPop)
									{
									setTimeout( function () {
										for(var i=0;i<Math.abs(distance);i++)
											{
												popItem();
											}
										},10);
									}
							else {
									for(var i=0;i<Math.abs(distance);i++)
									{
										popItem();
									}
							}	
					
					parade.style.left = '0px';
					
					}
				
				if(currentlyShown < 0)
						{
							currentlyShown = thenumber + currentlyShown;
						}
				if(currentlyShown >= thenumber)
						{
							currentlyShown = Math.abs(currentlyShown) - thenumber;
						}	
					
				currentDistance = 0;
				animDistance = 0;
				snapDistance = 0;
				inAnimate = false;
				
				highlight();
				if(autoAnimate == false)
					{
						clearInterval(autoTimer);
					}
				
				if(nearestNode == 2)
					{
					animSpeed = oldAnimSpeed;
					}
				
				if(d || nearestNode) {
					nearestNode = false;
					node.storedCommand();
				} // run the stored command}
			}		
	}};
	
	/* seizeControl(e)
	/  e - event to drop
	/  prevent the default action on events which are assigned to this carousel.
	*/
	this.seizeControl = function(e) { with (this) {
		// stop the normal course of events which i intercept...
		//console.log('event seized');
		
		e = e||event;
		
		// a special IE only dispensation of a storedEvent. Since "this" refers to window in timer
		// functions - the dispatched stop of the snap too contains no event.  therefore we need
		// to save the event until the autotimer finishes.  it's < 40ms - so i doubt there's
		// any real danger of a separate event being replaced with the stored one.
		
		if(DEF_IE_VERSION != DEF_NOT_IE)
			{
			if(!storedEvent)
				{
				storedEvent = document.createEventObject(e);
				}
			if(typeof(e.cancelBubble) == "unknown")  // really just checking to see if it exists.
				{
				e = document.createEventObject(storedEvent);
				storedEvent = null;
				}
			}
		
		
		e.preventDefault ? e.preventDefault() : e.returnValue = false;
		return e;
	}};
	
	/* navigate(evt)
	/  evt - user event which called this function
	/  interprets and passes out user control events.
	*/
	this.navigate = function(evt) { with (this) {	
		// first we grab the event out of the normal flow.
		var stop = 1;
			
		evt = node.seizeControl(evt);
		
		// let us learn about who called us.
		var elem = (evt.target) ? evt.target : evt.srcElement; // now we have our culprit
		
		// if we're already animating, drop the event into wherever uncaught events go....
		if(inAnimate && !autoAnimate) { return false;}
		if(autoAnimate && !(hasClass(elem,'auto'))) { node.stopSpin(function() {node.navigate(evt);}); } // stop it once we recieve an event, even if it's not from the control
				
		
		var toNode; // what's the heading, scotty?
		var testClass = elem.className; // get them all if we have multiples.
		var classes = testClass.match(/(left_arrow|right_arrow|auto)/g);
		if(classes != null && classes.length > 1) { alert('The carousel is poorly constructed.'); }
		if(classes != null){testClass = classes[0];}
		else {testClass = null;} // gotta equal something...
		
		switch(testClass)
			{
				case 'left_arrow':
					toNode = node.currentlyShown-1;
					toNode = (toNode < 0) ? thenumber+toNode : toNode;
					break;
				case 'right_arrow':
					toNode = node.currentlyShown+1; // works liks this... check this in animate...
					break;
				case 'auto':
					if(autoAnimate) {node.stopSpin();}
					else {node.slowSpin();}
					return; // nothing else to do in this situation.  go home.
					break;
				default: // okay, it's one of the "per element" navigators
					toNode = parseInt(elem.name);
					if(oldSaf)  // how i hate you old safari returning a #text.
						{
						toNode = parseInt(elem.data);
						}
					//console.log(elem.nodeName);
					break;
			}
			
		// set the timeer and go home
		//console.log('go to node: '+toNode);
		function returnFunction () {node.animate(toNode); return false;};
		animTimer = setInterval(returnFunction, 40);
				
		return false; // just in case
	}};
	
	/* slowSpin
	/ function activates an automatic animation of the caruousel.
	/ it also changes the style on the auto control element.
	*/
	this.slowSpin = function() { with (this) {
		if(!autoAnimate) {autoNode.style.textDecoration = 'none';}
		autoAnimate = true;
		animSpeed = slowAnimSpeed;
		function autoReturnFunction() {node.animate(node.currentlyShown+1);}
		autoTimer = setInterval(autoReturnFunction,40);
		autoStopper = setTimeout(function() { node.stopSpin();},60000); // because it eats processor, we'll stop the auto spin after a minute.
								
	}};
	
	
	/* findPosition
	/ function determines whether to go forward or backward in the carousel
	/ depending on position.
	*/
	this.findPosition = function() { with (this) {
		var spot = parseInt(parade.style.left);
	 	var width = document.getElementById(myname+'_element_'+(currentlyShown)).offsetWidth;		   
		var pos = Math.abs(spot)/width;
		if(pos > .5) { return nextItem(); }
		if(pos <= .5) { return currentlyShown; }
	}};
	
	/* stopSpin
	/  f - a function to execute after the snapto is complete.
	/  
	/  stops the automatic spin and resets the appropriate counters
	*/
	
	this.stopSpin = function(f) { with (this) {
			
		window.clearTimeout(autoStopper); // no need to stop it automatically now...
		
		var f = f || function() {;}; //sometimes we go somewhere else once we're stopped.
			
		node.storedCommand = f;
		node.animSpeed = node.animSpeedOld;
		node.autoAnimate = false;
		node.counter = 1;
		node.nearestNode = true;
		autoNode.style.textDecoration = 'line-through'; 
	}};
	
	}
	
/* other functions */
//console.log('finished carousel');
/* credit card verifier */
function agr_validate_cc(area)
{
	// get every form field whose label contains a "*" for required.  sneaky me.
	var payment_info = document.getElementById(area);
	var labelFields = payment_info.getElementsByTagName('label');
	var emptyFields = new Array();
	var warn = document.getElementById('required_field_warning');
	for(var i=0;i<labelFields.length;i++)
		{
		var label = labelFields[i];
		var labelText = label.innerHTML;
		if(labelText.match(/\*/))
			{		
			// stupid internet explorer.  have to look for htmlFor?  what FOR??
			var fieldName = (label.getAttribute('for')) ? label.getAttribute('for') : label.getAttribute('htmlFor');
			var reqField = document.getElementById(fieldName);
			reqField.style.backgroundColor = ''; // clear this out
			if(reqField.value == "")
				{
				emptyFields[emptyFields.length] = reqField;
				}
			}
		}
		
	if(area=='register_now')
		{
			if(document.getElementById('new_pass').value != document.getElementById('new_pass_conf').value)
				{
				document.getElementById('new_pass').style.backgroundColor = '#FFAAAA';
				document.getElementById('new_pass_conf').style.backgroundColor = '#FFAAAA';
				document.getElementById('required_field_warning').innerHTML = "<h3 id=\"field_missing\"> The passwords do not match. </h3";
				warn.style.display = 'block';
				return false;
				}
		}
		
	if(emptyFields.length > 0)
		{
		warn.style.display = 'block';
		for(var i=0;i<emptyFields.length;i++)
			{
			emptyFields[i].style.backgroundColor = "#FFAAAA";
			}
		if(document.getElementById('luhn_error'))
			{
			document.getElementById('luhn_error').style.display='none';
			}
		document.getElementById('required_field_warning').innerHTML = "<h3 id=\"field_missing\"> A Required Field is Missing. </h3>";
		return false;
		}
	
	if(payment_info.id != 'payment_info') 
		{
		// skip the credit card stuff if we're validating addresses.
		return true;
		}
		
	if(document.getElementById('card_name').value.match(/[0-9]/))
	{
		// names normally don't include numbers.... unles you're like... from the future.  or something.
		warn.style.display = 'block';
		document.getElementById('field_missing').innerHTML = "A Required field has an incorrect entry.";
		document.getElementById('card_name').style.backgroundColor = '#FFAAAA';
		return false;
	}
	
	var today = new Date();
	var ccey;
	var ccem;
	if((ccey = document.getElementById('exp_year').value) && (ccem = document.getElementById('exp_date').value))
		{
		var exp_error;
		if(ccey < today.getFullYear()) { exp_error = true;} /* definitely wrong */
		if(ccey == today.getFullYear() && ccem < today.getMonth() + 1) {exp_error = true;}
		if(exp_error)
			{
				warn.style.display = 'block';
				document.getElementById('field_missing').innerHTML = "Credit card has expired.";
				document.getElementById('exp_date').style.backgroundColor = '#FFAAAA';
				document.getElementById('exp_year').style.backgroundColor = '#FFAAAA';
				return false;
			}
		}
		
	// now lets check the credit card number
	var error = "";
	var cc;
	if(cc = document.getElementById('card_number').value)
		{
		var ct = document.getElementById('cc_type').value;
		if(ct == ccType(cc))
			{
			if(ccLuhn(cc))
				{
				return true;
				}
			else
				{
				error = "Your credit card number appears to be invalid. Please check the number and try again. ";
				error = error + "<br/> If you are sure you entered it correctly, please contact customer service.<br/>";
				}
			}
		else
			{
			error = error + "Your credit card number does not match the type of credit card you selected.<br/>";
			}
		}
	else
		{
			error = "Form validation error.  Please contact customer service.";
		}
	
	var badCC = document.getElementById('luhn_error');
	document.getElementById('field_missing').innerHTML = "Invalid Credit Card or Wrong Card Type."
	
	if(!badCC)
		{
		badCC = document.createElement("p");
		if(DEF_IE_VERSION < 6)
			{
			badCC.id = "luhn_error";
			}
		else
			{
			var id = document.createAttribute("id");
			id.nodeValue = "luhn_error";
			badCC.setAttributeNode(id);
			}	
		warn.appendChild(badCC);
		}
	badCC.innerHTML = error;
	badCC.style.display = 'block';
	warn.style.display = 'block';
	
	
	
	return false;
}
	
/* credit card verifier routines.  from typical programmer */

function ccType(cc)
{
    // regular expressions to match common card types
    // delete or comment out cards not accepted
    // see: www.merriampark.com/anatomycc.htm
    var cardpatterns = {
        'VI'       : /^(4\d{12})|(4\d{15})$/,
        'MC'	   : /^5[1-5]\d{14}$/,
        'DI'	   : /^6011\d{12}$/,
        'AE'       : /^3[47]\d{13}$/};

    // return type of credit card
    // or 'unknown' if no match
    // remove non-digits
    cc = cc.replace(/[^\d]/g, '');

    for (var type in cardpatterns)
    {
        if (cardpatterns[type].test(cc))
            return type;
    }
    return 'unknown';
}

function ccLuhn(cc)
{
    // digits 0-9 doubled with nines cast out
    var doubled = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];

    // remove non-digit characters
    cc = cc.replace(/[^\d]/g, '');
    var digits = cc.split('');

    // alternate between summing the digits
    // or the result of doubling the digits and
    // casting out nines (see Luhn description)
    var alt = false;
    var total = 0;
    for(var i = digits.length - 1;i >= 0; i--)
    	{
        var d = Number(digits[i]);
        total += (alt ? doubled[d] : d);
        alt = !alt;
        }
    return total % 10 == 0;
}

/* button "press" behavior */
function agr_button(evt)
	{
	var element = (evt.target) ? evt.target : evt.srcElement;
	var op;
	// its a little different in IE - of course
	if(DEF_IE_VERSION < 7)
		{
		// since we only need the dual class name for this function
		// and have avoided them scruplously besideds this,
		// we don't really care what the IE7 assigned "special class name"
		// is.
		// get only the first class name
		element.className = element.className.split(/\s/g)[0];
		op = true;
		}
	 
	if(evt.type == 'mouseout' || evt.type =='dragleave')
		{
		
		// element.className = element.className.replace(/pressed/,"");
		if(op) 
			{ 
			element.className = element.className.replace(/pressed/g,''); 
			// ain't gonna being hovering now more either, so clear that for the hover behavior.
			element.className = element.className.replace(/onhover|onunknown/g,'');
			}
		else removeClass(element,"pressed");
		return;
		}
	
	if(evt.type == 'mousedown' || evt.type == 'mouseup')
		{
		// sedebugger;
		if(element.className=="")
			{
			addClass(element,"pressed");
			// element.className="pressed";
			return;
			// i'm not strictly sure this isn't duplicate logic
			}
		else if(!(hasClass(element,"pressed")))
			{
			if(op) {
				if(DEF_IE_VERSION < 7 && element.className == 'onhover')
					{
						element.className = "pressed";
					}
				else
					{
					element.className = element.className+" pressed";
					}
			}
			else addClass(element,"pressed");
			// element.className=element.className+" pressed";
			return;
			}
		else 
			{
			if(op) element.className = element.className.split(/pressed/)[0];
			else removeClass(element,"pressed");
			// element.className = element.className.replace(/pressed/,"");
			return;
			}
		}
	}
	
//console.log('finished cc');

function agr_button_attach(elements)
{
//console.log(elements.length);
for(var i=0;i<elements.length;i++)
	{
	var element = elements[i];
	if(element)
		{
		addEvent(element,'mousedown',function(evt){agr_button(evt);});
		addEvent(element,'mouseup',function(evt){agr_button(evt);});
		// since the button function is unloaded before the event handlers are done firing
		// it's possible to raise an exception by doing a mouseout while the page is unloading.
		// in order to avoid the error message - we catch the error and drop it into the abyss.
		addEvent(element,'mouseout',function(evt){try{agr_button(evt);} catch(e){;/*noop*/}});
		if(DEF_IE_VERSION < 7 && element.tagName == 'INPUT');
			{
			addEvent(element,'dragleave',function(evt){try{;agr_button(evt);}catch(e){;}});
			}
		}
	}
}

/* auto populate addresses */

function agr_populate(src,dst,src_search,dst_search,type, evt)
{
	
var elem;

if(evt != 'auto')
	{
	elem = (evt.target) ? evt.target : evt.srcElement; // now we have our culprit
	if(elem.checked == false) { 
		type="clear";
		}
	}
var srcstring = src;
var dststring = dst;
var src = new RegExp(src);
var dst = new RegExp(dst);

var srcElements = getElementsByClass(src,document.getElementById(src_search),'*');
var dstElements = getElementsByClass(dst,document.getElementById(dst_search),'*');

var i,x;
for(i=0;i<srcElements.length;i++)
	{
	var matchClass = srcElements[i].className; // this still works since anything with this class name should still be matched

	var classes = matchClass.split(/\s/g);
	for(var j=0;j<classes.length;j++)
		{
		if(src.test(classes[j]))
			{
			matchClass = classes[j].replace(src,''); 
			// sort out the ones with src regex in them in them;
			}
		}
	var matched = null;
	x = 0;
	while(!matched && x < dstElements.length)
		{
		// we don't need to pull the class out of multiply classed elements,
		// because we just have to find it in the overall string.
		var inQuestion = dstElements[x].className;
		if(dst.test(inQuestion)) // is it something we're interestin in replacing?
			{
			matched = inQuestion.match(matchClass); // does it match our current string?
			}
		x++;
		}
	if(matched) { 
		switch(type)
			{
			case 'html2val':
					dstElements[x-1].value = srcElements[i].innerHTML; 
					break;
			case 'val2html':
					dstElements[x-1].innerHTML = srcElements[i].value;
					break;
			case 'val2val':
					dstElements[x-1].value = srcElements[i].value;
					break;
			case 'clear':
					dstElements[x-1].value = '';
					break;
			}
			}
	}

/* now keep them synced */
var src_element = document.getElementById(src_search);
if(evt != 'auto') {
	if(elem.checked == true) {
		// auto call has to be a global variable or you get exceptions in firefox.
		// that ain't good.
		autoCall = function() {agr_populate(srcstring,dststring,src_search,dst_search,type,'auto');};
		if(DEF_IE_VERSION != DEF_NOT_IE)
			{
			if(DEF_IE_VERSION < 5.5)	
				{
				// god how I hate IE.
				var inputs = src_element.getElementsByTagName('input');
				for(var i=0;i<inputs.length;i++) 
					{
					inputs[i].attachEvent('onblur',autoCall);
					}
				}
			else
				{			
				addEvent(src_element,'deactivate',autoCall);
				}
			// gotta get the actual form element to add the submit event.
			src_element = document.getElementById(src_search);
			var theform = src_element.getElementsByTagName('form');
			for(var i = 0;i<theform.length;i++)
				{
				addEvent(theform[i],'submit',autoCall);
				}
			}
		else
			{	
			addEvent(src_element,'submit',autoCall);
			addEvent(src_element,'change',autoCall);
			}
		
		}
	else
		{
		if(DEF_IE_VERSION != DEF_NOT_IE)
			{
			if(DEF_IE_VERSION < 5.5)	
				{
				// god how I hate IE.
				var inputs = src_element.getElementsByTagName('input');
				for(var i=0;i<inputs.length;i++) 
					{
					inputs[i].detachEvent('onblur',autoCall);
					}
				}
			else
				{
				removeEvent(src_element,'deactivate',autoCall);
				}
			src_element = document.getElementById(src_search);
			var theform = src_element.getElementsByTagName('form');
			for(var i = 0;i<theform.length;i++)
				{
				removeEvent(theform[i],'submit',autoCall);
				}
			}
		else
			{
			// for some reason this raises an exception in firefox. it still works though... 
			removeEvent(src_element,'change',autoCall);
			removeEvent(src_element,'submit',autoCall);
			}
		}
	}
}


function agr_hidestyle(c,o) {
	var hi = getElementsByClass(c)
	for(var i = 0;i<hi.length;i++)
		{
		 	hi[i].style.display = hi[i].style.display == 'none' ? '':'none';
		 	if(DEF_IE_VERSION != DEF_NOT_IE)
		 		{
		 			if(hasClass(document.body,'search') || hasClass(document.body,'category'))
		 				{
		 				var searchClass = (c == 'product_small_image') ? 'product_short_description' : 'product_small_image';
		 				var searchEl = hi[i].parentElement;
		 				while(searchEl.className != 'product_listing') {searchEl = searchEl.parentElement; if(searchEl == document.body) {return;}}
		 				var listing = getElementsByClass(searchClass,searchEl,'div');
		 				var element = listing[0];
		 				element.runtimeStyle.marginTop = ((element.parentElement.offsetHeight - element.offsetHeight)/2)+'px'; 
		 				}
		 		}
		}
	o.innerHTML = o.innerHTML.match(/Hide/) ? o.innerHTML.replace(/Hide/,"Show") : o.innerHTML.replace(/Show/,"Hide");	
}

function agr_class_reset(o, c, r) {
	// o = the object in question
	// c = the new class
	// r = the class to remove if it exists.		
	for(var i in o)
		{
			if(i=='push' || i=='pop' || i=='has') {continue;} // skip known member functions
			if(o[i])
				{
				removeClass(o[i],r);
				addClass(o[i],c);
				// o[i].className = c;
				}
		}
	}



function agr_disable_fixed(noReload) {

	if(DEF_DISABLE_FIXED)
		{
		agr_class_reset(fixedElements,'bottom','fixed');
		}
	else 
		{
		var height = 0;
		var cmH;
		if(pagetype == 'category')
				{
				var hasMessage = document.getElementById('category_message') ? true : false;
				cmH = hasMessage ? document.getElementById('category_message').offsetHeight : 0;
				if(!(hasMessage))
					{
					fixedElements["header"].style.backgroundColor="rgb(255,255,255)";
					}
				}
			if(pagetype == 'checkout' || pagetype == 'article' || pagetype == 'cart' || pagetype == 'search')
				{
					fixedElements["header"].style.backgroundColor="rgb(255,255,255)";
					var ca = document.getElementById('checkout_area');
				}
			if(window.innerHeight) { height = window.innerHeight;}
			else if (document.documentElement && document.documentElement.clientHeight) { height = document.documentElement.clientHeight;}
			else if (document.body && document.body.clientHeight) { height = document.body.clientHeight;}	
					
		if(height <= 600)
			{
				agr_class_reset(fixedElements,'bottom','fixed');
				if (/WebKit/i.test(navigator.userAgent)) {
					if(pagetype == 'product') {fixedElements["end_feature_wrap"].style='';}
				}
				if(pagetype=='category') {
						document.getElementById('category_list').style.marginTop = '-13px';
						}
				if(pagetype=='search') {
						document.getElementById('category_list').style.marginTop = '0px';
				}
			}
		else if(height >= 601 && height <= 900)
			{
				agr_class_reset(fixedElements,'bottom','fixed');
				if (/WebKit/i.test(navigator.userAgent)) {
					if(pagetype == 'product') {fixedElements["end_feature_wrap"].style='';}
				}
				
				 if(pagetype=='category') {
						document.getElementById('category_list').style.marginTop = '-13px';
						}
				 if(pagetype=='search') {
						document.getElementById('category_list').style.marginTop = '0px';
				  }
			}
		else if(height >= 901)
			{
				agr_class_reset(fixedElements,'fixed','bottom');
				if (/WebKit/i.test(navigator.userAgent)) {
					/*yuck.. safari bug keeps causing me grief. */
					 var webKitFields = RegExp("( AppleWebKit/)([^ ]+)").exec(navigator.userAgent);
					 var version = parseFloat(webKitFields[2]);
					
					if(pagetype == 'product' && version < 420) {fixedElements["end_feature_wrap"].style.marginTop='105px';}
					if(pagetype == 'category' || pagetype == 'checkout' || pagetype == 'article' || pagetype == 'cart' || pagetype == 'search') {fixedElements["header"].style.marginTop='-9px';}
				}
				
				 if(pagetype=='category') {
						document.getElementById('category_list').style.marginTop = cmH+25+'px';
					}
				  if(pagetype=='search') {
						document.getElementById('category_list').style.marginTop = '32px';
				  }
			}
		}
		
	var cw = document.getElementById('copy_wrap');
	if(cw)
		{
		if(cw.clientWidth < cw.scrollWidth)
			{
			cw.style.overflow = 'hidden'; // prevents an extraneous scroll bar in opera.
			}
		}
}

function agr_switchmenu(e)	{

	// //debugger;
	
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	targ = (targ.nodeType == 3) ? targ.parentNode : targ;
	var actualTarget = targ;
	var menu_regex = /(menu_)/
	
	var menu_id = targ.id.replace('menu_','');
		
	var menu = document.getElementById(menu_id);
	
	if(menu)
		{
		if(e.type == 'mouseover') 
				{
				topMenu.show(menu_id);
				}
		if(e.type == 'mouseout')
			    {
			   	topMenu.hide(menu_id);
			   	}
		}
	}

function agr_popup(e,ptype,dest) {
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	while(targ.tagName != 'A' && targ.tagName != 'BODY') {targ = targ.parentNode;}
	if(e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { return true; }
	else {
		 if(dest == null) {dest = targ.getAttribute('href');}
		 var img;
		 if(ptype == 'image') {
		 	do{	img = targ.firstChild; } while(img.tagName != 'IMG')
			var w = img.width;
		 	var h = img.height;
		 	if(img.className == 'detail') { w = (w/.35)+100; h = (h/.35)+170;}
			else { w = (w/.75)+100; h= (h/.75)+170; }
		 	var nw = window.open('/pop_article.asp?ai=171&file='+dest,'image_pop','width='+w+',height='+h+',location=1,resizable=1,scrollbars=1');
		 }
		 else
		 {
		 	var nw = window.open(dest,'text_pop','width=626,height=600,location=0,resizable=1,scrollbars=1');
		 }
	}
	if(nw.opener == null) {nw.opener = self;}
	nw.focus();
	e.preventDefault ? e.preventDefault() : e.returnValue = false;
	return e;
}

function agr_setpopups() {
	var l = document.getElementsByTagName('a');
	for(var i = 0; i<l.length;i++)
		{
		if(l[i].rel == 'popup') {
			if(l[i].firstChild.tagName == 'IMG' && l[i].lastChild == l[i].firstChild)
				 {addEvent(l[i],'click',function(e) {agr_popup(e,'image');});}
			else {addEvent(l[i],'click',function(e) {agr_popup(e,'page');});}
			}
		}
}

function agr_quick_order_validate(e) {
	var val = document.getElementById('quick_order_input').value
	var fail = false;
	if(val == '') 
		{
		fail = true;
		}
	else if (val.length > 13 || val.match(/\S+\s/)) 
		{
		document.getElementById('left_search_entry').value = val;
		document.forms['left_search'].submit();
		fail = true;
		}
	if(!fail) { return true; }
	e.preventDefault ? e.preventDefault() : e.returnValue = false; 
	return false;
}

function agr_search_validate(e) {
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	while(targ.tagName != 'FORM') {targ = targ.parentNode;}
	var ss = targ.elements['ss'];
	if(ss.value == '') { e.preventDefault ? e.preventDefault() : e.returnValue = false; return false;}
	return true;
}

function agr_special_focus(e) {
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	while(targ.tagName != 'FORM') {targ = targ.parentNode;}
	var email = targ.elements['email'];
	if(DEF_IE_VERSION < 8)
		{
		email.style.fontSize = '11px';
		email.style.color = 'black';
		email.style.textAlign = 'left';
		}
	email.value = '';
}

function agr_special_blur(e) {
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	while(targ.tagName != 'FORM') {targ = targ.parentNode;}
	if(DEF_IE_VERSION < 8)
	{
		email.style.fontSize = '';
		email.style.color = '';
		email.style.textAlign = '';
	}
	if(email.value == '') {email.value = 'your email';}
}

function agr_parseuri(uri_string)
{
	uri_string = uri_string ? uri_string : window.location.search
	var list = new Object;
	var list_array = uri_string.split(/[?&=]/);
	var start_index = DEF_NOT_IE ? 1 : 0;
	for(var i=1;i<=list_array.length;i+=2)
		{
			list[list_array[i]]=list_array[i+1];
		}
       return list;
}


function agr_clear_error(delay) {
	setTimeout(function() {document.getElementById('required_field_warning').style.display = 'none';},delay);
}
	
function agr_show_error(msg) { 
	document.getElementById('required_field_warning').innerHTML = "<h3 id=\"field_missing\">"+msg+"</h3>";
	document.getElementById('required_field_warning').style.display = 'block';
	agr_clear_error(10000);
}
	

function agr_special_validate(e) {
	var e = (e) ? e : ((window.event) ? window.event : "")
	var targ = (e.target) ? e.target : e.srcElement;
	while(targ.tagName != 'FORM') {targ = targ.parentNode;}
	var email = targ.elements['email'];
	var emailadd = email.value
	var valid = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(emailadd);
	if(!valid) { e.preventDefault ? e.preventDefault() : e.returnValue = false; 
				 email.focus();
				 email.select();
				 agr_show_error('Please Enter A Valid Email Address'); 
				 return false;}
	// okay, we open the popup window.
	agr_popup(e,'page','/pop_catalog_request.asp?rt=oo&email='+email.value);
	var lefter = targ.parentNode;
	lefter.removeChild(targ);
	var ws_link = document.createElement('DIV');
	ws_link.innerHTML = '<hr/><a class="sign_up" href="/Weekly_Special/c/130">View our newest<br/>Weekly Special</a>';
	lefter.appendChild(ws_link);
	// we need to cookie people in here.
	return true;
}
	

//console.log('finished behavior');

/* FSMENU Animation Functions */

/* animations for the menu */

FSMenu.animSlideDown = function(ref,counter,show)
{
	var cP = Math.pow(Math.sin(Math.PI * counter / 2), 0.75);
	
	if(counter == 1 || (counter < 0.01 && !show) || (counter+.2 >= 1))
		{
			if(window.opera || navigator.userAgent.indexOf('KHTML') > -1)
				{
					ref.style.clip = '';
				}
			else
				{
					ref.style.clip = 'rect(auto auto auto auto)';
				}
		}
	else
		{
			ref.style.clip = 'rect(0px '+ref.offsetWidth+'px '+ (ref.offsetHeight * cP) + 'px 0px)';
		}
}


FSMenu.animClipSide = function(ref, counter, show)
{

	var cP = Math.pow(Math.sin(Math.PI * counter / 2), 0.75);
	
	
	if(counter == 1 || (counter < 0.01 && !show) || (counter+.2 >= 1))
		{
			if(window.opera || navigator.userAgent.indexOf('KHTML') > -1)
				{
					ref.style.clip = '';
				}
			else
				{
					ref.style.clip = 'rect(auto auto auto auto)';
				}
		}
	else
		{
			ref.style.clip = 'rect(0px '+(ref.offsetWidth*cP)+'px '+ref.offsetHeight+'px 0px)';
		}
}

FSMenu.prototype.ieSelBoxFixShow = function(mN) { with (this)
{m
 var m = menus[mN];
 if (!isIE || !window.createPopup) return;
 if (navigator.userAgent.match(/MSIE ([\d\.]+)/) && parseFloat(RegExp.$1) > 6.5)
  return;
 // Create a new transparent IFRAME if needed, and insert under the menu.
 if (!m.ifr)
 {
  m.ifr = document.createElement('iframe');
  m.ifr.src = 'about:blank';
  with (m.ifr.style)
  {
   position = 'absolute';
   border = 'none';
   filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
  }
  m.lyr.ref.parentNode.insertBefore(m.ifr, m.lyr.ref);
 }
 // Position and show it on each call.
 with (m.ifr.style)
 {
  left = m.lyr.ref.offsetLeft + 'px';
  top = m.lyr.ref.offsetTop + 'px';
  width = m.lyr.ref.offsetWidth + 'px';
  height = m.lyr.ref.offsetHeight + 'px';
  visibility = 'visible';
 }
}};
FSMenu.prototype.ieSelBoxFixHide = function(mN) { with (this)
{
 if (!isIE || !window.createPopup) return;
 var m = menus[mN];
 if (m.ifr) m.ifr.style.visibility = 'hidden';
}};

FSMenu.prototype.toggleElements = function(show)
{
 // CONFIGURATION: Here's a list of tags that will be hidden by menus. Modify to fit your site.
 var tags = ['select', 'iframe'];

 if (!isDOM) return;

 for (var t in tags)
 {
  var elms = document.getElementsByTagName(tags[t]);
  for (var e = 0; e < elms.length; e++) elms[e].style.visibility = show ? 'visible' : 'hidden';
 }
};
	
