/*
######################################################################################
######                                                                        #######
######     GENERIC SCRIPTS			                                         #######
######                                                                      #######
##################################################################################
*/

	var Generic = new Object();

/********************************************************************************/
/***** CONTENT SUPPORT FUNCTIONS ***********************************************/
/******************************************************************************/
	
	var genericTransition 		= 'off';	// Records the state of the transition. On = running, off = ready
	var genericLinkElement;					// Records the element that was clicked to call the action. Used to reset INPUTs
	
	Generic.Core = {

/***** HUB FOR THE TRANSITIONS *****/

		Switcher: function() {
		// Extract the variables
			var Opener 		= $(arguments[0]);
			var Closer 		= $(arguments[1]);
			var Container 	= $(arguments[2]);
			var options		= !arguments[3] ?  new Object() : arguments[3];

			var duration 	= !options.duration ? 0.7 : options.duration;
			var transition 	= !options.transition ? 'switcher' : options.transition;
			var linkElement = !$(options.linkElement) ? null : $(options.linkElement);

		// Activate the links
			if(linkElement != null) { Generic.Links(linkElement, transition); }

		// Get all of the DIVs styles set for the transition
			Container.setStyle({
				height: Closer.getHeight() + 'px',
				width: Closer.getWidth() + 'px',
				position: 'relative',
				overflow: 'hidden'
			});
			Generic.Core.Layout(Opener,Closer);
		
		// Specify transition effects
			var transition1 = new Effect.Fade(Closer, { sync: true });
			var transition2 = new Effect.Appear(Opener, { sync: true });
			var transition3 = new Effect.Morph(Container, { style: { height: Opener.getHeight() + 'px' }, sync: true });
		
		// If the opening and closing DIVs have the same height, DON'T use the morph effect (var transition3)
			if(Opener.getHeight() != Closer.getHeight()) {
				var effectList	= [transition1,transition2,transition3];
			} else {
				var effectList	= [transition1,transition2];
			}

		// The content transition itself (fade out the active DIV, fade in the next)
			new Effect.Parallel(effectList, { duration: duration,  beforeStart: function() {
					genericTransition = 'on';
				}, afterFinish: function() {
					genericTransition = 'off';
					Generic.inputReset();

				// Change the DIVs back to normal positioning. Set the container height to auto for closing
					Opener.style.position 	= '';
					Closer.style.position 	= '';
					Container.style.overflow = 'visible';
					Container.style.height 	= 'auto';
				}
			})
		},

/***** DOM CHANGER FOR ALL DIVS IN PLAY *****/

		Layout: function() {
		// Extract the variables
			var Opener 		= $(arguments[0]);
			var Closer 		= $(arguments[1]);

		// Prepare the Closing DIV
			Closer.setStyle({ position: 'absolute', left: '0', top: '0' });

		// Prepare the Opening DIV
			Opener.show();
			Opener.setStyle({
				visibility: 'hidden',
				position: 	'absolute',
				left: 		'0',
				top: 		'0',
				visibility: 'visible'
			})
		
		// Re-hide the opening DIV for the transition
			Opener.hide();
		},

/***** OPEN THE DIV FOR THE FIRST TIME *****/

		Open: function() {
		// Extract the variables
			var divElement	= $(arguments[0]);
			var options		= !arguments[1] ?  new Object() : arguments[1];
			var duration 	= !options.duration ? 0.7 : options.duration;
			var transition 	= !options.transition ? 'switcher' : options.transition;
			var linkElement = !$(options.linkElement) ? null : $(options.linkElement);

		// Activate the links
			if(linkElement != null) { Generic.Links(linkElement, transition); }

		// Specify transition effects
			var transition1 = new Effect.BlindDown(divElement, { sync: true });
			var transition2 = new Effect.Appear(divElement, { sync: true });
			var effectList	= [transition1,transition2];
		
		// Opening transition
			new Effect.Parallel(effectList, { duration: duration, beforeStart: function() {
					genericTransition = 'on';
				}, afterFinish: function() {
					genericTransition = 'off';
					Generic.inputReset();
				}
			})
		},

/***** CLOSE THE DIV AND RESET VARIABLES *****/

		Close: function() {
		// Extract the variables
			var divElement	= $(arguments[0]);
			var options		= !arguments[1] ?  new Object() : arguments[1];
			var duration 	= !options.duration ? 0.7 : options.duration;
			var transition 	= !options.transition ? 'switcher' : options.transition;
			var linkElement = !$(options.linkElement) ? null : $(options.linkElement);

		// Activate the links
			if(linkElement != null) { Generic.Links(linkElement, transition); }

		// Specify transition effects
			var transition1 = new Effect.Fade(divElement, { sync: true });
			var transition2 = new Effect.BlindUp(divElement, { sync: true });
			var effectList	= [transition1,transition2];

		// Closing transition
			new Effect.Parallel(effectList, { duration: 0.7, beforeStart: function() {
					genericTransition = 'on'
				}, afterFinish: function() {
					genericTransition = 'off';
					Generic.inputReset();
				}
			});
		}
	}


/********************************************************************************/
/***** ACTIVE LINK MANAGER *****************************************************/
/******************************************************************************/

/*
This function will allow you to manage active links in a menu. It can be run alongside virtually any
other script when specified in an event handler.
It works by targetting to container and seeing how many links are within it. It then removes the active
class from all before assigning the active state to the link that was clicked.

Has been scripted to support A tags and INPUTS as activators.
*/

	Generic.Links = function() {
		linkElement 		= $(arguments[0]);
		transition	 		= arguments[1];
		genericLinkElement 	= linkElement;

		
/***** IDENTIFY LINK ACTIVATOR TYPE *****/

		switch(linkElement.tagName) {
		// INPUT
			case 'INPUT':
				switch(linkElement.type) {
					case 'checkbox':
					case 'radio':
					// Disable the INPUT while the transition runs
						linkElement.disabled = false;
						if(genericTransition == 'on') { linkElement.disabled = true; }
					break;
				}
			break;

		// A
			case 'A':
				linkElement.blur();

			// Find out the navigation element structure
				if(linkElement.up().tagName == 'LI') {
					var Container = linkElement.up().up();
				} else {
					var Container = linkElement.up();
				}
				var linkList = $(Container).getElementsByTagName('a');
			
			// If there is only 1 link
				if(linkList.length == 1) {
					if(linkElement.className == 'active') {
						linkElement.className = '';
					} else {
						linkElement.className = 'active';
					}
				} else {

			// If there is more then 1 link
					if(transition == 'closer') {
					// Closer
						if(linkElement.className == 'active') {
							for(var i = 0; i < linkList.length; i++) { linkList[i].className = ''; }
						} else {
							for(var i = 0; i < linkList.length; i++) { linkList[i].className = ''; }
							linkElement.className = 'active';
						}
					} else {
					// Switcher
						if(linkElement.className != 'active') {
							for(var i = 0; i < linkList.length; i++) { linkList[i].className = ''; }
							linkElement.className = 'active';
						}
					}
				}
			break;
		}
	}


/***** INPUT RESET *****/

/*
If the activator is a CHECKBOX or RADIO the above script will disable them so they
cant be clicked over and over during the transition.
This script reenables the button.
It is called once the transition has completed
*/

	Generic.inputReset = function() {
		if(genericLinkElement) {
			if(genericLinkElement.tagName == 'INPUT') {
				switch(genericLinkElement.type) {
					case 'checkbox':
					case 'radio':
						genericLinkElement.disabled = false;
					break;
				}
			}
			genericLinkElement = '';
		}
	}
	

/********************************************************************************/
/***** CONTENT SWITCHING FUNCTIONS *********************************************/
/******************************************************************************/

/***** CONTENT SWITCHER WHICH ALLOWS THE ACTIVE DIV TO BE CLOSED *****/

/*
This function will allow you to switch between different DIVs that are associated through
a specified containing DIV. This script also allows you to close the active DIV when actioned.
A variation of this script, Generic.SwitcherOnly(), functions in the same way but will prevent the
active DIV from closing when actioned.
*/

	Generic.Switcher = function() {
	// Extract the variables
		var divElement	= $(arguments[0]);
		var options		= !arguments[1] ?  new Object() : arguments[1];
		var duration 	= !options.duration ? 0.7 : options.duration;
		var transition 	= !options.transition ? 'switcher' : options.transition;
		var linkElement = !$(options.linkElement) ? null : $(options.linkElement);

	// Determine the action
		if(genericTransition == 'off') {
			genericTransition = 'on';
			var Container = $(divElement.up());
			var ContainerChildren = Container.childElements();
			var status = '';
		
		// Search the content DIVs to find the closer
			for(var i = 0; i < ContainerChildren.length; i++) {
			// Find the correct DIVs by their class name
				if(ContainerChildren[i].className == 'div_cell') {
				// Only the open DIV can be closed
					if(ContainerChildren[i].style.display != 'none') {
						var Closer		= ContainerChildren[i];
					// If the
						if(ContainerChildren[i] == divElement) {
							if(transition == 'closer') {
								status = 'closing';
							} else {
								genericTransition = 'off';
							}
						} else {
							var divActive = ContainerChildren[i];
							status = 'switching';
						}
						break;
					} else {
						if(transition == 'closer') {
							status = 'opening';
						}
					}
				}
			}

			switch(status) {
				case 'opening':
					Generic.Core.Open(divElement,options);
				break;
				case 'closing':
					Generic.Core.Close(divElement,options);
				break;
				case 'switching':
					Opener = divElement;
					Closer = divActive;
					Generic.Core.Switcher(Opener,Closer,Container,options);
				break;
			}
		}
	}


/********************************************************************************/
/***** SIMPLE OPENER / CLOSER **************************************************/
/******************************************************************************/

/*
This script will allow you to open and close a single DIV and its contents. It isnt
designed for multiple DIV content.
*/

	Generic.OpenerCloser = function() {
	// Extract the variables
		var divElement	= $(arguments[0]);
		var options		= !arguments[1] ?  new Object() : arguments[1];
		var duration 	= !options.duration ? 0.7 : options.duration;
		var transition 	= !options.transition ? 'switcher' : options.transition;
		var linkElement = !$(options.linkElement) ? null : $(options.linkElement);

	// Determine the action
		if(genericTransition == 'off') {
			genericTransition = 'on';

		// Set the activator and div states
			if(divElement.style.display == 'none') {
				Generic.Core.Open(divElement,options);
			} else {
				Generic.Core.Close(divElement,options);
			}
		}
	}



/********************************************************************************/
/***** VERTICAL / HORIZONTAL SLIDER ********************************************/
/******************************************************************************/
	
	var sliderChanger = new Array();
	
/***** GET THE FUNCTIONS STARTED *****/

	Generic.Slider = function(element,options) {
		element = $(element);
		Generic.Slider.Run(element,options);
	}

	/***** RUN THE SLIDER *****/
	
		Generic.Slider.Run = function(element,options) {
			element = $(element);
		// Prepare the containing DIV
			element.setStyle({ position: 'relative', overflow: 'hidden' });

		// Create the scrolling element
			var elementContent = element.innerHTML;
			if($(element.id + '_scroller') != null) {
				elementContent = $(element.id + '_scroller').innerHTML
				$(element.id + '_scroller').remove();
			}
			var scroller = new Element('div', { id: element.id + '_scroller' });
			scroller = $(scroller);
			scroller.setStyle({ position: 'absolute', paddingRight: '20px' });
		
		// Transfer the content into the new inner DIV
			element.innerHTML	= '';
			element.appendChild(scroller);
			scroller.innerHTML = elementContent;

		// Get heights / ratio for the DIVs
			if(options.axis == 'vertical') {
				var elementLayout 	= element.getHeight();
				var scrollerLayout 	= scroller.getHeight();
			} else {
				var elementLayout 	= element.getWidth();
				var scrollerLayout 	= getOffsetWidth(scroller);
			}


			var layoutRatioLge	= (scrollerLayout / elementLayout);
			var layoutRatioSml	= (elementLayout / scrollerLayout);
		
		// Set the height or width of the handle
			var handleLayout	= (elementLayout * layoutRatioSml);
	
		// If the scroller content is bigger then the container, set the scroller
			if(scrollerLayout > elementLayout) {
				Event.observe(element, 'DOMMouseScroll', function(event) { Generic.Slider.Wheel(event,element) }); 	// mozilla
				Event.observe(element, 'mousewheel', function(event) { Generic.Slider.Wheel(event,element) }); 		// IE/Opera
			
			// Create the slider and append it to the container
				var slider 	= new Element('div');
				slider.className = options.slider;
				element.appendChild(slider);
			
			// Create the handle and append it to the slider
				var handle 	= new Element('div');
				handle.className = options.handle;
				slider.appendChild(handle);
			
			// if Dynamic, set the width or height based on height differences. Else, CSS
				if(options.handleSize == 'dynamic') {
					if(options.axis == 'vertical') {
						handle.setStyle({ height: handleLayout + 'px' });
					} else {
						handle.setStyle({ width: handleLayout + 'px' });
					}
				}

			// Get the height difference between the container and scroller
				var layoutDiff		= (scrollerLayout - elementLayout);
			
			// Create the event handler for the slider
				sliderChanger[element.id] = new Control.Slider(handle,slider, {
					axis: options.axis,
					onSlide: function(value) {
						if(options.axis == 'vertical') {
							scroller.style.top = (-1 * value * layoutDiff) + 'px';
						} else {
							scroller.style.left = (-1 * value * layoutDiff) + 'px';
						}
					},
					onChange: function(value) {
						if(options.axis == 'vertical') {
							scroller.style.top = (-1 * value * layoutDiff) + 'px';
						} else {
							scroller.style.left = (-1 * value * layoutDiff) + 'px';
						}
					}
				});
			}
		}
	
	/***** CHANGE SLIDER BY MOUSEWHEEL MOVEMENT *****/
	
		Generic.Slider.Handle = function(delta,element) {
			delta = (delta / 15);
			sliderChanger[element.id].setValueBy(-delta);
		}
	
	/***** MOUSEWHEEL FUNCTION *****/
	
		Generic.Slider.Wheel = function(event,element){
			var delta = 0;
			if(!event) event = window.event;
			if(event.wheelDelta) {
				delta = event.wheelDelta/120;
				if (window.opera) { delta = -delta; }
			} else if(event.detail) {
				delta = -event.detail / 3;
			}
			if (delta) Generic.Slider.Handle(delta,element);
			if (event.preventDefault) event.preventDefault();
			event.returnValue = false;
		}


/********************************************************************************/
/***** HORIZONTAL CAROUSEL SLIDER **********************************************/
/******************************************************************************/

	var mouse = { x: 0, y: 0, maxL: 0, maxR: 0, xPercent: 0, xPos: 1, sector: 5, startL: 0,
	endL: 0, startR: 0, endR: 0, speedValue: 0, startV: 0, endV: 0 };
	
/***** GET THE FUNCTIONS STARTED *****/

	Generic.Carousel = function (Shell,Inner) {
	// Establish the correct width of the slider
		var subNavOuter = $(Shell);
		var subNavOuterWidth = getOffsetWidth(subNavOuter);
		var subNavShell = $(Inner);
		subNavOuter.style.width = '150000px';
		subNavShell.style.position = 'absolute';
		var subShellWidth = getOffsetWidth(subNavShell);
		subNavShell.style.position = 'relative';
		subNavOuter.style.width = subNavOuterWidth + 'px';
		subNavShell.style.width = subShellWidth + 'px';
	
	// Make the slider react to the mouse
		Event.observe($('carousel_shell'), 'mousemove', function(e) { Generic.CarouselShifter(e,Shell,Inner); });
	
	//Collection.speedFreak();
		setInterval('Generic.CarouselRun(\'' + Shell + '\',\'' + Inner + '\')', 20);
	}


/***** SET PARAMETERS FOR MOUSE MOVEMENTS AND REACTIONS / SPEEDS *****/

	var newDir = '';
	var speedFreak;

	Generic.CarouselShifter = function(e,Shell,Inner) {
		mouse.maxL	= 0;
		mouse.maxR	= getOffsetWidth($(Inner)) - getOffsetWidth($(Shell));
		mouse.xPercent	= getOffsetWidth($(Shell)) / 100;

	// Get mouse coordinates on the screen
		mouse.x	= getMousePositionX(e) - getMouseOffsetX($(Shell));
		mouse.y	= getMousePositionY(e) - getMouseOffsetY($(Shell));

	// Start and finish values for the x position of the 2 halves of the screen
		mouse.startL	= 0;
		mouse.endL		= (mouse.xPercent * 50);
		mouse.startR	= mouse.endL + 1;
		mouse.endR		= getWindowWidth();
	
	// y position delimiters
		mouse.startV	= 0;
		mouse.endV		= getOffsetHeight($(Shell));

	// Left hand area sectors
		if(mouse.x > 0 && mouse.x <= (mouse.xPercent * 10)) 						mouse.sector = 1;
		if(mouse.x > (mouse.xPercent * 10) && mouse.x <= (mouse.xPercent * 20)) 	mouse.sector = 2;
		if(mouse.x > (mouse.xPercent * 20) && mouse.x <= (mouse.xPercent * 30)) 	mouse.sector = 3;
		if(mouse.x > (mouse.xPercent * 30) && mouse.x <= (mouse.xPercent * 40)) 	mouse.sector = 4;
		if(mouse.x > (mouse.xPercent * 40) && mouse.x <= mouse.endL) 				mouse.sector = 5;
		
	// Right hand area sectors
		if(mouse.x > mouse.startR && mouse.x <= (mouse.xPercent * 60)) 				mouse.sector = 5;
		if(mouse.x > (mouse.xPercent * 60) && mouse.x <= (mouse.xPercent * 70)) 	mouse.sector = 4;
		if(mouse.x > (mouse.xPercent * 70) && mouse.x <= (mouse.xPercent * 80)) 	mouse.sector = 3;
		if(mouse.x > (mouse.xPercent * 80) && mouse.x <= (mouse.xPercent * 90)) 	mouse.sector = 2;
		if(mouse.x > (mouse.xPercent * 90) && mouse.x <= mouse.endR) 				mouse.sector = 1;
		
	// Set which is the left and right halves of the screen
		if(mouse.x > mouse.startL && mouse.x <= mouse.endL)	newDir = 'left';
		if(mouse.x > mouse.startR && mouse.x <= mouse.endR)	newDir = 'right';

		switch(mouse.sector) {
			case 1: mouse.speedValue = 40;  break;
      case 2: mouse.speedValue = 30;  break;
      case 3: mouse.speedValue = 20;  break;
      case 4: mouse.speedValue = 10;  break;
      case 5: mouse.speedValue = 0; break;
		}
	}


/***** DYNAMICALLY SET AND UPDATE THE SLIDER POSITION *****/

	Generic.CarouselRun = function(Shell,Inner) {
	// Determine the increment of the pixel value
		if(newDir == 'right')	{ xPos = mouse.xPos + mouse.speedValue; }
		if(newDir == 'left')	{ xPos = mouse.xPos - mouse.speedValue; }

	// If too far to the left or right
		if(xPos < mouse.maxL) {
			xPos = 0;
			}
		if(xPos > mouse.maxR) {
			xPos = mouse.maxR - 1;
			}
		if(mouse.maxR < 0) {
			xPos = 0;
		}
		
	// Set the actual pixel position value
		$(Inner).style.left = (-1 * xPos) + 'px';
	
	// Update the global position variable
		mouse.xPos = xPos;
	}