/**
##########################################################################################

Part of COUNTRY START Teaser Slider

##########################################################################################
**/

/**
 * Teaser Slider
 * @author andreas.gehrig
 * 
 * Provides sliding effect for teasers on country-startpage
 * 
 * Needs a container div with id TEASER_CONTAINER_ID
 * Inside the container each 'slide' needs to have continuous id with prefix TEASER_ID_PREFIX
 * You can specify the delay between each slide with GLOBAL_WAIT
 * 
 * Manual interactions:
 * pause_slide() 				toggles play/pause mode
 * next_slide() 				pauses automatic sliding + moves one slide further
 * prev_slide() 				pauses automatic sliding + moves one slide back
 * goToSlide(int targetSlideNo)	pauses automatic sliding + moves to slide with specified ID (without prefix)
 * 
 * 
 * 
 * The following variables need to be defined on the page the slider is used
 * 
 * //text for pausing action
 * var MSG_PAUSE = 'pause';
 * //text for play action
 * var MSG_PLAY = 'play';
 * 
 */


/***** GLOBAL CONFIGURATION *****/
//configures time between each slide
var GLOBAL_WAIT = 5000;
//time to wait after user interaction
var GLOBAL_RESET_TIME = 20000;
//container div
var TEASER_CONTAINER_ID = "slide_container";
//prefix for slide divs
var TEASER_ID_PREFIX = "slide";
//width of slide (px)
var SLIDE_WIDTH = 304;
//status text ID
var MSG_ID = 'slide_status';
//img ID of play/pause button
var PAUSE_BTN_ID = 'button_pause';
//class of GOTO link
var LINK_ID = 'slideLink';
//GOTO link - container
var LINK_CONTAINER_ID = 'popupLinks';
//Prefix from surrounding forms etc.
var GLOBAL_ID_PREFIX = 'mf:';


/***** INTERNAL PARAMETERS *****/
//temporaryli stores current delay
var current_wait = GLOBAL_WAIT;
//pause flag
var pause = false;
//event queue
var queue = 0;
//number of slides to move on
var moveCount = 1;
//set to true if one running timer exists
var timerRunning = false;
//flag to reset delay time
var reset = false;
var resetTime = 0;

/***** START SLIDING *****/
document.observe("dom:loaded", init);


/***** INITIALIZES CONTAINER AND STARTS SLIDING *****/
function init() {
	// after combine all ..._slider.js to one script it throws an exception 
	// if div (TEASER_CONTAINER_ID) is missing
	if($(TEASER_CONTAINER_ID) == null) {
		return;	
	}
	
	// using 'toggleArrowPopup1' as name implies we can never use this in common
	// with a "site-pulldown navigation" as long as we don't take care that the
	// toggleArrowPopup<Number> do no collide, same must be considered for the "slide<Number>"-divs
	if($(GLOBAL_ID_PREFIX + 'toggleArrowPopup1') != null) {
		Event.observe(GLOBAL_ID_PREFIX + 'toggleArrowPopup1', 'click', function() {
			if (!this.slideInstance.isOpened && !pause)
				pause_slide();
		});
	}
	
	//only show content inside container
	$(TEASER_CONTAINER_ID).makeClipping();
	
	//get all slides
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	
//	alert("calcualte height on "+slides.length);
	
	// caluclate max height:
	calculateHeight(slides);
	
	// only start sliding if more than one slide exists
	if (slides.length > 1) {
		
		// make the first one visible
		slides[0].setStyle({left: '0px'});
		
		// hide all others
		for ( var i = 1; i < slides.length; i++) {
			slides[i].setStyle({left : SLIDE_WIDTH + 'px'});
		}
		
		// start the counter
		timer(GLOBAL_WAIT);
		
		// update popup links
		updateLinks();
	}
}

/* Sets the teaser box to the max. height over all subsequent children */
function calculateHeight(slides) {
	var height = 0;
	for (var i = 0; i < slides.length; i++) {
		var heightTmp = slides[i].getHeight();
		
		if (heightTmp > height) {
			height = heightTmp;
		}
	}
	$(TEASER_CONTAINER_ID).setStyle({'height': height+'px'});
}

/***** UPDATES LINKS IN POPUP MENU ACCORDING TO SLIDES *****/
function updateLinks() {
	
	// get all slides
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	
	//remove previously set span elements (they replaced links)
	var helpTexts = $(LINK_CONTAINER_ID).select('span.' + LINK_ID);
	helpTexts.each(function(helpSpan) {
		helpSpan.remove();
	});
	
	
	for (var i=0; i<slides.length; i++) {
		
		// get slide ID
		slideId = slides[i].id.replace(TEASER_ID_PREFIX, '');
		
		// make the first one only text
		if (i == 0) {
			// get all links according to current slide
			var links = $(LINK_CONTAINER_ID).select('a.' + LINK_ID + slideId);
			
			// for each link
			links.reverse().each(function(link) {
				// insert this link after element with ID 'current_links'
				$(GLOBAL_ID_PREFIX + 'popupLinksRepeat:0:current_links').insert({after: link});
				
				// create a new span element with text of the link
				var newSpan = document.createElement("span");
				var newSpanText = document.createTextNode(link.firstChild.data);
				newSpan.appendChild(newSpanText);
				
			 	// insert it after the link
				link.insert({after: newSpan});
				link.next().addClassName(LINK_ID);
				
				// make the link disappear
				link.setStyle({display: 'none'});
			});
		
		// all others remain links
		} else {
			// get all links according to current slide
			var links = $(LINK_CONTAINER_ID).select('a.' + LINK_ID + slideId);
			
			// for each link
			links.each(function(link) {
				// move this link to the bottom of the popup
				$('popupLinks').insert({bottom: link});
				// remove previously set styles
				link.setStyle({color: '', display: 'block'});
			});
			
		}
	}
}

/***** Counts down from WAIT to finally invoke SlideShow() *****/
function timer(wait, original) {
	// max. shrinking width of the timer-bar in pixels, must be identical to width set in country start
	// for element "h:panelGrid" holding the "#{countrystart_switchto}" -> "Switch to" text!
	var maxTimeoutWidth = 120;
	
	timerRunning = true;
	if (!pause) {
		if (wait > 0) {
			
			if (reset) {
				reset = false;
				if (resetTime != 0) {
					current_wait = resetTime;
					original = current_wait;
					resetTime = 0;
				} else {
					current_wait = GLOBAL_WAIT;
				}
			} else {
				current_wait = wait;
			}
			
			if (original == undefined) {
				original = current_wait;
			}
			
			current_wait = current_wait - 100;
			
			// limit to max width due to timer inaccuracies can cause size > 100%, f*ckin up the layout
			var newWidth = Math.min(maxTimeoutWidth, maxTimeoutWidth * (current_wait/original));
			
			$('slider_progress').setStyle({width: newWidth + 'px'});
			
			setTimeout("timer("+current_wait+", "+original+")", 100);
		} else {
			timerRunning = false;
			SlideShow('left');
			$('slider_progress').setStyle({width: maxTimeoutWidth + 'px'});
		}
	}
}

/* **** Removes first slide from the container and appends it on the end	*****
   ***** Gets called after each finished "Slide-To-The-Left" - effect		**** */
function moveBackwards() {
	
	//get all slides
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	
	//remove first one
	var remove = $(slides[0]).remove();
	//hide it from container
	remove.setStyle({left: SLIDE_WIDTH + 'px'});
	//insert it at the back
	$(TEASER_CONTAINER_ID).insert({bottom: remove});
	//signal that the sliding effect has finished
	stopProgress();
}


/* **** Slides by one into the given direction (left if none)	*****
  ***** and finally invokes timer()								**** */
function SlideShow(direction) {
	// get actual slides
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	
	// move backward
	if (direction == 'right') {
		// move last item to the front
		var remove = $(slides[slides.length - 1]).remove();
		remove.setStyle({left: -SLIDE_WIDTH + 'px'});
		$(TEASER_CONTAINER_ID).insert({top: remove});
		
	 	// get all items
		slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
		
		// move first and second item to the right
		new Effect.Move(slides[0],	{ duration: 0.6, mode: 'relative', x: SLIDE_WIDTH, transition: Effect.Transitions.sinoidal,
			beforeStart: startProgress, afterFinish: stopProgress });
		new Effect.Move(slides[1],	{ duration: 0.6, mode: 'relative', x: SLIDE_WIDTH, transition: Effect.Transitions.sinoidal,
			beforeStart: startProgress, afterFinish: stopProgress });
	} 
	// 'left' or nothing specified -> move forward
	else {
		// Effect.Fade(slides[0]);
		// move first and second item to the left
		// after effect finished, the first item will me moved to the back (afterFinish: moveBackwards)
		new Effect.Move(slides[0],	{ duration: 0.6, mode: 'relative', x: -SLIDE_WIDTH, transition: Effect.Transitions.sinoidal, 
			beforeStart: startProgress, afterFinish: moveBackwards });
		new Effect.Move(slides[1],	{ duration: 0.6, mode: 'relative', x: -SLIDE_WIDTH, transition: Effect.Transitions.sinoidal, 
			beforeStart: startProgress, afterFinish: stopProgress });
	}
	
	// if not in paused-mode, call timer againg
	if (!pause && !timerRunning) {
		
		timer(GLOBAL_WAIT);
		
	}
}


/* **** Toggles paused-mode and updates status text  **** */
function pause_slide() {
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	if (slides.length > 1) {
		if (!pause) {
			pause = true;
			$(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).src = $(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).src.replace('button_pause', 'button_play');
			$(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).writeAttribute('title', MSG_PLAY);
			// $(MSG_ID).update(MSG_PAUSED);
		} else {
			pause = false;
			$(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).src = $(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).src.replace('button_play', 'button_pause');
			$(GLOBAL_ID_PREFIX + PAUSE_BTN_ID).writeAttribute('title', MSG_PAUSE);
			var elements = $('slider_progress').select('div');
			elements.each(function(element) {
				element.setStyle({background: '#BFC5CE'});
			});
			if (reset) {
				reset = false;
				if (resetTime != 0) {
					timer(resetTime);
					resetTime = 0;
				} else {
					timer(GLOBAL_WAIT);
				}
			} else {
				timer(GLOBAL_WAIT);
			}
		}
	}
}


/* **** Turns over to the next slide **** */
function next_slide() {
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	if (slides.length > 1 && queue == 0) {
		if (!pause) {
			reset = true;
			resetTime = GLOBAL_RESET_TIME;
		}
		var elements = $('slider_progress').select('div');
		elements.each(function(element) {
			element.setStyle({background: '#BFC5CE'});
		});
		SlideShow('left');
	}
}


/* **** Turns over to the previous slide **** */
function prev_slide() {
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	if (slides.length > 1 && queue == 0) {
		if (!pause) {
			reset = true;
			resetTime = GLOBAL_RESET_TIME;
		}
		var elements = $('slider_progress').select('div');
		elements.each(function(element) {
			element.setStyle({background: '#BFC5CE'});
		});
		SlideShow('right');
	}
}



/* **** Turns over to the given slide ID	*****
  ***** Calculates direction internally	    **** */
function goToSlide(targetSlideId) {
	var slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
	if (slides.length > 1 && queue == 0) {
		if (!pause) {
			reset = true;
			resetTime = GLOBAL_RESET_TIME;
		}
		closeOpenPopups();
		
		var curSlideId = slides[0].id.replace(TEASER_ID_PREFIX, '');
		if (curSlideId != targetSlideId) {
			
			//calculate direction
			var moveTempForward = targetSlideId - curSlideId;
			if (moveTempForward < 0)
				moveTempForward = moveTempForward + slides.length;
			var moveTempBackward = curSlideId - targetSlideId;
			if (moveTempBackward < 0)
				moveTempBackward = moveTempBackward + slides.length;
			
			moveDirection = 'left';
			moveCount = moveTempForward;
			if (moveTempBackward < moveCount) {
				moveDirection = 'right';
				moveCount = moveTempBackward;
			}
			//var effectLength = 0.6 / moveCount;
			var effectLength = 0.6;
			
			var effect = Effect.Transitions.sinoidal;
			if (moveCount == 1)
				effect = Effect.Transitions.sinoidal;
				
			
			if (moveDirection == 'left') {
				for (var i = 0; i < moveCount; i++) {
					new Effect.Move(slides[i],		{ duration: effectLength, mode: 'relative', x: -SLIDE_WIDTH, transition: effect, 
						beforeStart: startProgress, afterFinish: moveBackwards, queue: {position: 'end', scope: 'scope' + i%2} });
					new Effect.Move(slides[i+1],	{ duration: effectLength, mode: 'relative', x: -SLIDE_WIDTH, transition: effect, 
						beforeStart: startProgress, afterFinish: stopProgress, queue: {position: 'end', scope: 'scope' + (i+1)%2} });
				}
			} else {
				for (var i = 0; i < moveCount; i++) {
					var remove = $(slides[slides.length - 1]).remove();
					remove.setStyle({left: -SLIDE_WIDTH + 'px'});
					$(TEASER_CONTAINER_ID).insert({top: remove});
					
					slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
				}
				slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX);
				for (var i = 0; i < moveCount; i++) {
					new Effect.Move(slides[moveCount - i],		{ duration: effectLength, mode: 'relative', x: SLIDE_WIDTH, transition: effect, 
						beforeStart: startProgress, afterFinish: stopProgress, queue: {position: 'end', scope: 'scope' + i%2} });
					new Effect.Move(slides[moveCount - i - 1],	{ duration: effectLength, mode: 'relative', x: SLIDE_WIDTH, transition: effect, 
						beforeStart: startProgress, afterFinish: stopProgress, queue: {position: 'end', scope: 'scope' + (i+1)%2} });
				}
			}
		}
		if (pause) {
			reset = true;
			resetTime = GLOBAL_RESET_TIME;
			pause_slide();
		}
	}
}


/***** Indicate that an effect is in progress *****/
function startProgress() {
	queue++;
}

/***** Indicate that one offect has finished *****/
function stopProgress() {
	queue--;
	// update popup links
	slides = $(TEASER_CONTAINER_ID).select('div.' + TEASER_ID_PREFIX); 
	var currSlide = slides[0].id.replace('slide', '');
	updateLinks();
}

/***** convert ms to seconds *****/
function toSec(wait) {
	return wait/1000;
}


/**
##########################################################################################

Part of Feature Slider
requires: prototype.js, scriptaculous.js, toolkit.js

##########################################################################################
**/

//Used for small feature-comparison boxes in the right content column, which offer
//to slide out key features of a product that is placed in the alternative cross navitgation.

//global var holding (css) class of toggle arrow to react on
var FEATURE_TOGGLE_CLASS = "toggleArrowFeature";
//id of the outer div which wraps the content of a single popup
var FEATURE_CONTAINER_ID = "featureBox";
//global var to hold popup trigger instances (with id='<OVERLAY_TOGGLE_CLASS>'+<number>)
var featureTriggers = [];

//global var to hold popup trigger instances (with id='<FEATURE_TOGGLE_CLASS>'+<number>)
Event.observe(window, 'load', initCompareFeatures);

/**
* Initializes event handling for all compare feature wrappers.
*/
function initCompareFeatures() {
// hold triggers globally available:
	
	// after combine all ..._slider.js to one script it throws an exception 
	// if div (bodyColumnRight) is missing
	if($('bodyColumnRight')==null)
	{return;}
	else { 
	featureTriggers = $('bodyColumnRight').select('img[class="'+FEATURE_TOGGLE_CLASS+'"]');
	}

// observe document click for closing rollover popups
Event.observe(document, 'click', function(event) {
 featureTriggers.each(function(trigger) {
   if ((trigger.slideInstance.isOpened) && (pointOutsideElement(event.clientX, event.clientY, trigger.slideInstance, 3))) {
     // click was outside popup, so close it
     closeFeature(trigger);
   }
 });
});

// set up popup events for trigger and slides:
setupFeatureEvents(featureTriggers);
} // end initCompareFeatures()


/**
* Sets the given elements image src to be the 'toggle arrow opened' image source.
*/
function showOpenFeatureArrow(element) {
replaceInFilePathAttribute(element, 'src', /closed/g, 'open');
} // end showOpenFeatureArrow(elementId)

/**
* Sets the given elements image src to be the 'toggle arrow closed' image source.
*/
function showClosedFeatureArrow(element) {
replaceInFilePathAttribute(element, 'src', /open/g, 'closed');
} // end showClosedFeatureArrow(elementId)	
	
/**
* Closes all currently opened popups.
* params:
*   keepOpenTrigger = optional parameter which specify to close 
*   all open popups EXCEPT that trigger's slide
*/
function closeOpenFeatures(keepOpenTrigger) {
featureTriggers.each(function(trigger) {
 if ((trigger.slideInstance.isOpened) && (trigger != keepOpenTrigger)) {
   closeFeature(trigger);
 }
});
} // end closeOpenFeatures()
	
/**
* Opens the popup of the given trigger.
* params:
*   trigger = the trigger node to open the slide of
*/
function openFeature(trigger) {
if (!trigger.slideInstance.isOpened) {
 closeOpenFeatures(trigger);
 showOpenFeatureArrow(trigger);
 applyBlindDown(trigger.slideInstance);

 // start mouse motion listening when being opened:
 trigger.slideInstance.observe('mousemove', function(event) {
   if (trigger.slideInstance.isOpened) {
     trigger.slideInstance.canBeClosed = true;
   }
 });
}
} // end openFeature(trigger)

/**
* Closes the given trigger's slide.
* params:
*   trigger = the trigger node whose slide shall be closed
*/
function closeFeature(trigger) {
if (trigger.slideInstance.isOpened) {
 // stop mouse move observation during close operation:
 trigger.slideInstance.stopObserving('mousemove');
 trigger.slideInstance.canBeClosed = false;

 showClosedFeatureArrow(trigger);
 applyBlindUp(trigger.slideInstance);
}
} // end closeFeature(trigger)	
	
/**
* Sets up the event handling for the popups.
*/
function setupFeatureEvents(triggerNodes) {
// specified in toolkit.js, creates index-information in the
// trigger/slide nodes and make trigger/slide nodes hold
// references to each other, so we don't need numerical indicies
setupTriggerSlides(triggerNodes, FEATURE_CONTAINER_ID);

// then, initialize events for each trigger and slide:
triggerNodes.each(function(trigger) {
 // initialize default state values:
 trigger.slideInstance.canBeClosed = false;
 trigger.slideInstance.isOpened = false;
 
 // prepare slide for slide effect:
 prepareBlind(trigger.slideInstance);

 // click opens and closes popup
 trigger.observe('click',function(event) {
   if (trigger.slideInstance.isOpened) {
     closeFeature(trigger);
		} else {
     closeOpenFeatures();
     openFeature(trigger);
   }
 });
});
} // end setupFeatureEvents(index)


/**
##########################################################################################

Part of Overlay Slider
requires: prototype.js, scriptaculous.js, toolkit.js

##########################################################################################
**/

//Used for product information overlays in product tables. Normally, you have
//a small toggle arrow in front of the product name, which slides out the additional info overlay.

//global var holding (css) class of toggle arrow to react on
var OVERLAY_TOGGLE_CLASS = "toggleArrowOverlay";
//id of the outer div which wraps the content of a single overlay
var OVERLAY_CONTAINER_ID = "productOverlay";
//global var to hold popup trigger instances (with id='<OVERLAY_TOGGLE_CLASS>'+<number>)
var overlayTriggers = [];

Event.observe(window, 'load', initOverlays);

/**
* Sets the given elements image src to be the 'toggle arrow opened' image source.
*/
function showOpenOverlayArrow(element) {
replaceInFilePathAttribute(element, 'src', /closed/g, 'open');
} // end showOpenOverlayArrow(elementId)

/**
* Sets the given elements image src to be the 'toggle arrow closed' image source.
*/
function showClosedOverlayArrow(element) {
replaceInFilePathAttribute(element, 'src', /open/g, 'closed');
} // end showClosedOverlayArrow(elementId)

/**
* Initializes event handling for all popup elements.
*/
function initOverlays() {
	// if the two following commented out method 'openTableOverlay(...)' should be used, 
	//the complete code of this method must be replaced with:
	// overlayTriggers = [];
	
	// hold triggers globally available:
	overlayTriggers = $('content').select('img[class="'+OVERLAY_TOGGLE_CLASS+'"]');

	// observe document click for closing rollover popups
	Event.observe(document, 'click', function(event) {
		overlayTriggers.each(function(trigger) {
			if ((trigger.slideInstance.isOpened) && (pointOutsideElement(event.clientX, event.clientY, trigger.slideInstance, 3))) {
				// click was outside popup, so close it
				closeOverlay(trigger);
			}
		});
	});

	// set up popup events for trigger and slides:
	setupOverlayEvents(overlayTriggers);
} // end initOverlays()


/** 
 * methods not used atm - was an experiment to show product table overlays by using ajax requests
 * 
function isOverlayOpen(tableIdentifier) {
	var slide = document.getElementById(OVERLAY_CONTAINER_ID+tableIdentifier+'0');
	if (slide != null) {
		//alert(slide.style.display);
	
		return slide.style.display != 'none';
	}
	return false;
}

function openTableOverlay(tableIdentifier, triggerId) {
	var trigger = document.getElementById(tableIdentifier+triggerId);
	var infoDiv = document.getElementById(tableIdentifier + 'wrapper');
	trigger.instanceIndex = 0;
	trigger.slideInstance = document.getElementById(OVERLAY_CONTAINER_ID+tableIdentifier+'0');
	trigger.slideInstance.instanceIndex = 0;
	trigger.slideInstance.triggerInstance = trigger;
	trigger.slideInstance.canBeClosed = false;
	trigger.slideInstance.isOpened = true;
	if (trigger.slideInstance.style.visibility == 'visible') {
		// click was outside popup, so close it
		closeOverlay(trigger);
		return;
	}
	// prepare slide for slide effect:
	prepareBlind(trigger.slideInstance);
	overlayTriggers = [trigger];
	Event.observe(document, 'click', function(event) {
		overlayTriggers.each(function(trigger) {
			if ((trigger.slideInstance.isOpened) && (pointOutsideElement(event.clientX, event.clientY, trigger.slideInstance, 3))) {
				// click was outside popup, so close it
				closeOverlay(trigger);
			}
		});
	});
	var pos = trigger.viewportOffset();
	var viewPos = document.viewport.getScrollOffsets();
	infoDiv.style.position = 'absolute';
	infoDiv.style.top = (pos.top+viewPos.top+24) + 'px';
	infoDiv.style.left = (pos.left+viewPos.left) + 'px';
	openOverlay(trigger);
} // end openTableOverlay()
*/

/**
* Closes all currently opened popups.
* params:
*   keepOpenTrigger = optional parameter which specify to close 
*   all open popups EXCEPT that trigger's slide
*/
function closeOpenOverlays(keepOpenTrigger) {
overlayTriggers.each(function(trigger) {
 if ((trigger.slideInstance.isOpened) && (trigger != keepOpenTrigger)) {
   closeOverlay(trigger);
 }
});
} // end closeOpenOverlays()

/**
* Opens the popup of the given trigger.
* params:
*   trigger = the trigger node to open the slide of
*/
function openOverlay(trigger) {
if (!trigger.slideInstance.isOpened) {
 closeOpenOverlays(trigger);
 showOpenOverlayArrow(trigger);
 applyBlindDown(trigger.slideInstance);

 // start mouse motion listening when being opened:
 trigger.slideInstance.observe('mousemove', function(event) {
   if (trigger.slideInstance.isOpened) {
     trigger.slideInstance.canBeClosed = true;
   }
 });
}
} // end openOverlay(trigger)

/**
* Closes the given trigger's slide.
* params:
*   trigger = the trigger node whose slide shall be closed
*/
function closeOverlay(trigger) {
if (trigger.slideInstance.isOpened) {
 // stop mouse move observation during close operation:
 trigger.slideInstance.stopObserving('mousemove');
 trigger.slideInstance.canBeClosed = false;

 showClosedOverlayArrow(trigger);
 applyBlindUp(trigger.slideInstance);
}
} // end closeOverlay(trigger)

/**
* Sets up the event handling for the popups.
*/
function setupOverlayEvents(triggerNodes) {
// specified in toolkit.js, creates index-information in the
// trigger/slide nodes and make trigger/slide nodes hold
// references to each other, so we don't need numerical indicies
setupTriggerSlides(triggerNodes, OVERLAY_CONTAINER_ID);

// then, initialize events for each trigger and slide:
triggerNodes.each(function(trigger) {
 // initialize default state values:
 trigger.slideInstance.canBeClosed = false;
 trigger.slideInstance.isOpened = false;
 
 // prepare slide for slide effect:
 prepareBlind(trigger.slideInstance);

 // click opens and closes popup
 trigger.observe('click',function(event) {
   if (trigger.slideInstance.isOpened) {
     closeOverlay(trigger);
		} else {
     closeOpenOverlays();
     openOverlay(trigger);
   }
 });
});
} // end setupOverlayEvents(index)


/**
##########################################################################################

Part of Popup Slider
requires: prototype.js, scriptaculous.js, toolkit.js

##########################################################################################
**/

//Used for popup-windows of pulldown boxes, normally navigation boxes which slide
//out using an toggle arrow.

//global var holding (css) class of toggle arrow to react on <img class="<POP_TOGGLE_CLASS>" ... />
var POPUP_TOGGLE_CLASS = "toggleArrowPopup";
//id of the outer div which wraps the content of a single popup
var POPUP_CONTAINER_ID = "popupBox";
//global var to hold popup trigger instances (with id='<POPUP_TOGGLE_CLASS>'+<number>)
var popupTriggers = [];

Event.observe(window, 'load', initPopups);

/**
* Sets the given elements image src to be the 'toggle arrow opened' image source.
*/
function showOpenPopupArrow(element) {
replaceInFilePathAttribute(element, 'src', /closed/g, 'open');
} // end showOpenPopupArrow(elementId)

/**
* Sets the given elements image src to be the 'toggle arrow closed' image source.
*/
function showClosedPopupArrow(element) {
replaceInFilePathAttribute(element, 'src', /open/g, 'closed');
} // end showClosedPopupArrow(elementId)

/**
* Initializes event handling for all popup elements.
*/
function initPopups() {
// hold triggers globally available:
	popupTriggers = $('content').select('img[class="'+POPUP_TOGGLE_CLASS+'"]');

// observe document click for closing rollover popups
Event.observe(document, 'click', function(event) {
 popupTriggers.each(function(trigger) {
   if ((trigger.slideInstance.isOpened) && (pointOutsideElement(event.clientX, event.clientY, trigger.slideInstance, 3))) {
     // click was outside popup, so close it
     closePopup(trigger);
   }
 });
});

// set up popup events for trigger and slides:
setupPopupEvents(popupTriggers);
} // end initPopups()

/**
* Closes all currently opened popups.
* params:
*   keepOpenTrigger = optional parameter which specify to close 
*   all open popups EXCEPT that trigger's slide
*/
function closeOpenPopups(keepOpenTrigger) {
popupTriggers.each(function(trigger) {
 if ((trigger.slideInstance.isOpened) && (trigger != keepOpenTrigger)) {
   closePopup(trigger);
 }
});
} // end closeOpenPopups()

/**
* Opens the popup of the given trigger.
* params:
*   trigger = the trigger node to open the slide of
*/
function openPopup(trigger) {
if (!trigger.slideInstance.isOpened) {
 closeOpenPopups(trigger);
 showOpenPopupArrow(trigger);
 applyBlindDown(trigger.slideInstance);

 // start mouse motion listening when being opened:
 trigger.slideInstance.observe('mousemove', function(event) {
   if (trigger.slideInstance.isOpened) {
     trigger.slideInstance.canBeClosed = true;
   }
 });
}
} // end openPopup(trigger)

/**
* Closes the given trigger's slide.
* params:
*   trigger = the trigger node whose slide shall be closed
*/
function closePopup(trigger) {
if (trigger.slideInstance.isOpened) {
 // stop mouse move observation during close operation:
 trigger.slideInstance.stopObserving('mousemove');
 trigger.slideInstance.canBeClosed = false;

 showClosedPopupArrow(trigger);
 applyBlindUp(trigger.slideInstance);
}
} // end closePopup(trigger)

/**
* Sets up the event handling for the popups.
*/
function setupPopupEvents(triggerNodes) {
// specified in toolkit.js, creates index-information in the
// trigger/slide nodes and make trigger/slide nodes hold
// references to each other, so we don't need numerical indicies
setupTriggerSlides(triggerNodes, POPUP_CONTAINER_ID);

// then, initialize events for each trigger and slide:
triggerNodes.each(function(trigger) {
 // initialize default state values:
 trigger.slideInstance.canBeClosed = false;
 trigger.slideInstance.isOpened = false;
 
 // prepare slide for slide effect:
 prepareBlind(trigger.slideInstance);

 // click opens and closes popup
 trigger.observe('click',function(event) {
   if (trigger.slideInstance.isOpened) {
     closePopup(trigger);
		} else {
     closeOpenPopups();
     openPopup(trigger);
   }
 });
});
} // end setupPopupEvents(index)