/* R6.1.0 FileID: $Id: objects_globals.js 890 2010-06-04 07:46:50Z enijmeijer@MIRABEAU.NL $ */

/*
 * Custom and extended OBJECTS, jQuery extensions and plugins
 */

/**
 * Easy namespacing setup for globals vars
 */
String.prototype.namespace = function(separator) {
	var ns = this.split(separator || '.'), p = window, i;
	for (i = 0; i < ns.length; i++) {
		p = p[ns[i]] = p[ns[i]] || {};
	}
};

/**
 * jQuery extensions and plugins
 */
jQuery.extend(jQuery.easing, {
	def : 'easeInOutQuad',
	easeInOutQuad : function(x, t, b, c, d) {
		if ((t /= d / 2) < 1)
			return c / 2 * t * t + b;
		return -c / 2 * ((--t) * (t - 2) - 1) + b;
	}
});

jQuery.fn.extend( {
	scrollTo : function(offset, speed, easing) {
		return this.each( function() {
			var targetOffset = $(this).offset().top + offset || 0;
			$('html,body').animate( {
				scrollTop : targetOffset
			}, speed, easing);
		});
	}
});
jQuery.extend( {
	/**
	 * return the height and width of the whole document
	 */
	getDocumentDimensions : function() {
		var maxWidth, maxHeight;
		if (isIE()) {
			maxWidth = document.documentElement.scrollWidth;
			maxHeight = document.documentElement.scrollHeight;
		} else {
			maxWidth = Math.max($('html').width(), $(window).width() - 30);
			maxHeight = Math.max($('html').height(), $(window).height() - 30);
		}
		return {
			width : maxWidth,
			height : maxHeight
		};
	}
});
jQuery.extend( {
	/**
	 * returns the height and width of the viewport, regardless of the document size
	 */
	getViewportDimensions : function() {
		var b = $(window);
		return {
			width : b.width(),
			height : b.height()
		};
	}
});

var count = 0;
jQuery.fn.extend( {
	/**
	 * combines the current classes into a merged form for IE6minus, removes any previously added combination
	 */
	combineClasses : function() {
		var merge = function(el) {
			$this = $(el);
			$this.data("merging", true);
			var currentClasses = el.className.split(" ");
			var prevClass = "";
			for ( var i = currentClasses.length - 1; i >= 0; i--) {
				if (currentClasses[i].indexOf("ZZ") >= 0 || currentClasses[i] == prevClass || currentClasses[i] == "") {
					currentClasses.splice(i, 1);
				} else {
					prevClass = currentClasses[i];
				}
			}
			currentClasses.sort(); // alphabetically sort to fix order of classes
			var cleanedClasses = ("" + currentClasses).replace(/,/g, " ");
			var mergedClasses = cleanedClasses.replace(/ /g, "ZZ");
			// clear out side-effects of strange and simulatenous merging
			mergedClasses = mergedClasses.replace(/ZZ$/, "");
			mergedClasses = mergedClasses.replace(/ZZ{2,}/, "ZZ");
			el.className = cleanedClasses + " " + mergedClasses;
			$this.removeData("merging");
			$this.dequeue();
		}

		if ($.browser.msie && $.browser.version < 7) {
			return this.each( function() {
				$this = $(this);
				var obj = this;
				var merging = $this.data("merging");
				if (!merging) {
					merge(obj);
				} else {
					alert("queued merging");
					$this.queue( function() {
						merge(obj)
					});
				}
			});
		}
	}
});

/**
 * Turns a set of list-items (with a specific markup) into a set of floating
 * panels
 *
 * @Author: Edo Nijmeijer
 */
( function($) {
	//
	// plugin object definition
	//
	var PanelFloater = function(element, opts) {

		// private variables
		var panels = new Array();
		element = $(element);
		var obj = this;
		var availHeight;
		var availWidth;
		var minPanelWidth;
		var maxPanelWidth;

		// establish options, falling back to defaults
		var options = $.extend( {}, $.fn.panelFloater.defaults, opts);

		this.getOptions = function() {
			// public method. Call by getting the object off the elements 'data' and calling it
			return options;
		};
		this.getAvailHeight = function() {
			return availHeight;
		}
		this.getMinPanelWidth = function() {
			return minPanelWidth;
		}
		this.getMaxPanelWidth = function() {
			return maxPanelWidth;
		}

		var privateMethod = function() {
			// this method can only be called from within the plugin
		};

		// hide scrollbars and remove padding that is used when JS does not initialise
		element.css( {
			"overflow" : "hidden",
			"padding" : (options.verPadding ? options.verPadding : 0) + "px "
					+ (options.horPadding ? options.horPadding : 0) + "px"
		});

		var $panels = $("li." + options.itemClass, element);

		// fix sitestat codes on homepage for links and clicks (setup later) within panels to add product
		var panelProductName = element[0].id.replace(/fp-/, "");
		//var $linksOut = $("a[onclick*=ns_onclick]", element);
		//$linksOut.each(function() {
		//	var orgOnClick = $(this).attr("onclick");
		//	var newOnClick = orgOnClick.replace(/click\.homepage\.drieluik/,"click.homepage.drieluik." + panelProductName);
		//	$(this).attr("onclick", newOnClick);
		//});
		var $panelClickConfigsItems = $("li[data-ns]", element);
		$panelClickConfigsItems.each( function() {
			var orgDataNS = $(this).attr("data-ns");
			var newDataNS = orgDataNS.replace(/click\.homepage\.drieluik/, "click.homepage.drieluik." + panelProductName);
			$(this).attr("data-ns", newDataNS);
		});

		/* determine measurements */
		availHeight = element.outerHeight() - options.verPadding * 2;
		availWidth = element.width();
		if ($panels.length > 1) {
			maxPanelWidth = availWidth * options.maxedPanelWidth;
			minPanelWidth = Math.floor((availWidth - maxPanelWidth + options.panelOverlap * ($panels.length - 1))
					/ ($panels.length - 1));
		} else {
			maxPanelWidth = availWidth;
			minPanelWidth = availWidth
		}

		/* store all panel items and components for manipulation later on. set widths, margin, event */
		var maxedPanelIndex = 999;
		$panels.each( function(index) {
			var $this = $(this);

			/* float panels */
			$this.css( {
				"float" : "left",
				"margin-right" : "0px",
				"margin-left" : "0px"
			});

			/* add horizontal overlap margins */
			if (index > 0) {
				$this.css( {
					"margin-left" : -1 * Math.round(options.panelOverlap) + "px"
				});
			}

			var panel = new Panel($this, $("." + options.minContentClass, $this), $("." + options.maxContentClass, $this),
					$("." + options.panelSideLClass, $this), $("." + options.panelSideRClass, $this));

			/* center panel itself vertically by adding margin */
			panel.centerVertically(availHeight);

			/* move any visuals in the maximized content to the background of the div (allows css rounded corners to work */
			var $vc = panel.$maxContent.find(".visual-container");
			if ($vc.length > 0) {
				var imgSrc = $("img", $vc).remove()[0].src;
				$vc.css( {
					backgroundImage : "url(" + imgSrc + ")",
					backgroundRepeat : "no-repeat"
				});
			}

			/* size panel horizontally, show correct contents, layer */
			if (panel.isMaximized(options.maxClass)) { /* passing in maxClass is unfortunately needed here since the data is not set on the parent yet */
				maxedPanelIndex = index;
				panel.$panel.animate( {
					width : maxPanelWidth
				}, 1000);
				// force sides to stay visible while animating (overrules jQuery behavior)
				panel.$panel.css("overflow", "visible");
				panel.$maxContent.show();
				panel.$minContent.hide();
				panel.$panel.css("z-index", options.baseZIndex + 100);

			} else {
				panel.$panel.animate( {
					width : minPanelWidth
				}, 1000);
				// force sides to stay visible while animating (overrules jQuery behavior)
				panel.$panel.css("overflow", "visible");
				panel.$minContent.show();
				/* center content vertically by adding margin */
				panel.centerContentVertically("." + options.minContentClass, options.minPanelHeaderHeight);
				panel.$maxContent.hide();
				panel.$panel.css("z-index", index < maxedPanelIndex ? options.baseZIndex - $panels.length + index
						: options.baseZIndex + maxedPanelIndex - index);

			}

			/* init panel sides at correct side */
			panel.$panelSideL.addClass(
					(index == 0 || index == maxedPanelIndex + 1) ? options.sideStraightClass : options.sidePointedClass)
					.combineClasses();
			panel.$panelSideR.addClass(index == $panels.length - 1 ? options.sideStraightClass : options.sidePointedClass)
					.combineClasses();

			/* click events on panel and button */
			panel.$panelSideR.add(panel.$panel).click( function() {
				if (!panel.isMaximized()) {
					// minimize current maxed
					panels[maxedPanelIndex].minimize();
					maxedPanelIndex = index;
					// manage panel sides positioning and symetrical z-indexing
					for ( var i = 0; i < panels.length; i++) {
						panels[i].$panel.removeClass(options.raisedClass).combineClasses();

						// panel sides
						panels[i].$panelSideL.add(panels[i].$panelSideR).removeClass(
								options.sidePointedClass + " " + options.sideStraightClass).combineClasses();
						panels[i].$panelSideL.addClass(
								(i == 0 || i == maxedPanelIndex + 1) ? options.sideStraightClass : options.sidePointedClass)
								.combineClasses();
						panels[i].$panelSideR.addClass(
								i == $panels.length - 1 ? options.sideStraightClass : options.sidePointedClass)
								.combineClasses();

						panels[i].$panel.css("z-index", i < maxedPanelIndex ? options.baseZIndex - panels.length + i
								: options.baseZIndex + maxedPanelIndex - i);
					}

					// init any non-initialized flash banner
					if (!panel.hasInitializedFlashBanner && panel.$panel.find(".flash-container").length > 0) {
						var flashObjectId = panel.$panel.find(".flash-container object").eq(0).attr("id");

						swfobject.switchOffAutoHideShow(); // fixed display issue with swfobject 2.2+

						swfobject.registerObject(flashObjectId, moneyou.globals.minFlashVersion);
						var flashObject = swfobject.getObjectById(flashObjectId);
						moneyou.globals.flashObjects.push(flashObject);

						// make sure this code only runs once per panel
						panel.hasInitializedFlashBanner = true;
					}

					// trigger tracking, if needed, if possible
					var trackingParam = panel.$panel.attr("data-ns");
					if (trackingParam && ns_onclick) {
						ns_onclick(panel.$panel[0], "", trackingParam, "clickin");
					}

					//max clicked panel
					panel.maximize();

				}
			});

			/* hover events on panel */
			panel.$panel.hover( function() {
				panel.raise();
			}, function() {
				panel.fallBack();
			}).combineClasses();

			/* finally, store */
			panels.push(panel);
		});

	};

	$.fn.extend( {
		panelFloater : function(options) {
			// iterate over all passed in objects
			return this.each( function() {
				var element = $(this)

				// do not allow double instantiation
					if (element.data("panelFloater"))
						return;

					// create instance
					var _panelFloater = new PanelFloater(this, options);
					// store object in element's data for later reference
					element.data("panelFloater", _panelFloater);
				});
		}
	});

	//
	// private variables shared between plugin instances
	//
	var privVar;

	//
	// private functions/objects shared between all plugin instances
	//
	var func = function(arg) {
	};
	var Panel = function($panel, $minContent, $maxContent, $panelSideL, $panelSideR) {
		this.$panel = $panel;
		this.$minContent = $minContent;
		this.$maxContent = $maxContent;
		this.$panelSideL = $panelSideL;
		this.$panelSideR = $panelSideR;
		this._pfContainer = undefined;
		this.hasInitializedFlashBanner = false;
	};

	Panel.prototype.getContainerPlugin = function() {
		if (!this._pfContainer)
			this._pfContainer = this.$panel.parent("ul").data("panelFloater");
		return this._pfContainer;
	};
	Panel.prototype.raise = function() {
		if (!this.isMaximized()) {
			var panel = this.$panel;
			var pfc = this.getContainerPlugin();
			panel.data("zBeforeRaise", panel.css("z-index"));
			panel.css("z-index", pfc.getOptions().baseZIndex + 102);
			panel.addClass(pfc.getOptions().raisedClass).combineClasses();
		}
	};
	Panel.prototype.maximize = function() {
		var panel = this.$panel;
		var pfc = this.getContainerPlugin();
		var panelObj = this;
		panel.css("z-index", pfc.getOptions().baseZIndex + 100);
		panelObj.$maxContent.hide();
		panelObj.hideContent("min");
		panelObj.centerVertically();
		panel.find(".warning-min").slideUp(500);
		panel.animate( {
			"width" : (pfc.getMaxPanelWidth() + "px")
		}, 500, function() {
			panelObj.showContent("max");
			panel.find(".warning-max").slideDown(300);
			panel.removeClass(pfc.getOptions().minClass).combineClasses();
			panel.addClass(pfc.getOptions().maxClass).combineClasses();
		});
		// force sides to stay visible while animating (overrules jQuery behavior)
		panel.css("overflow", "visible");
	};
	Panel.prototype.fallBack = function() {
		if (!this.isMaximized()) {
			var panel = this.$panel;
			var pfc = this.getContainerPlugin();
			panel.css("z-index", panel.data("zBeforeRaise"));
			panel.removeClass(pfc.getOptions().raisedClass).combineClasses();
		}
	};
	Panel.prototype.minimize = function() {
		var panel = this.$panel;
		var pfc = this.getContainerPlugin();
		var panelObj = this;
		panelObj.$minContent.hide();
		if (!panelObj.hasInitializedFlashBanner) {
			panelObj.hideContent("max");
		} else {
			panelObj.$maxContent.hide();

		}
		panelObj.centerVertically();
		panel.find(".warning-max").slideUp(500);
		panel.animate( {
			"width" : (pfc.getMinPanelWidth() + "px")
		}, 500, function() {
			panelObj.showContent("min");
			panel.find(".warning-min").slideDown(300);
			panel.removeClass(pfc.getOptions().maxClass).combineClasses();
			panel.addClass(pfc.getOptions().minClass).combineClasses();
		});
		// force sides to stay visible while animating (overrules jQuery behavior)
		panel.css("overflow", "visible");
	};
	Panel.prototype.isMaximized = function(maxClass) {
		var pfc = this.getContainerPlugin();
		maxClass = maxClass || pfc.getOptions().maxClass;
		return this.$panel.hasClass(maxClass);
	};
	Panel.prototype.centerVertically = function(availHeight) {
		var panel = this.$panel;
		var pfc = this.getContainerPlugin();
		var forInit = availHeight || false;
		availHeight = availHeight || pfc.getAvailHeight();
		panel.css( {
			"marginTop" : Math.floor((availHeight - panel.height()) / 2) + "px"
		});
	};
	Panel.prototype.centerContentVertically = function(contentTypeSelector, offset) {
		offset = offset || 0;
		var panelHeight = this.$panel.height() - offset;
		var $content = $(contentTypeSelector, this.$panel);
		var contentHeight = $content.outerHeight();
		var neededMargin = Math.floor((panelHeight - contentHeight) / 2) + offset;

		$content.css( {
			"marginTop" : neededMargin + "px"
		});
	};
	Panel.prototype.showContent = function(minMax) {
		var $toShow = this["$" + minMax + "Content"];
		var pfc = this.getContainerPlugin();
		var panelObj = this;
		if ($toShow.hasClass(pfc.getOptions().minContentClass)) {
			// quickly show and hide content to allow us align it
			$toShow.css( {
				"visibilty" : "hidden",
				"display" : "block"
			});
			panelObj.centerContentVertically("." + pfc.getOptions().minContentClass, pfc.getOptions().minPanelHeaderHeight);
			$toShow.css( {
				"visibility" : "visible"
			});
			$toShow.hide();
		}
		if (!isIE()) {
			$toShow.fadeIn(750);
		} else {
			$toShow.show();
		}
	}
	Panel.prototype.hideContent = function(minMax) {
		var $toHide = this["$" + minMax + "Content"];
		if (!isIE()) {
			$toHide.fadeOut(250);
		} else {
			$toHide.hide();
		}
	}
	Panel.prototype.hide = function() {
		var $toHide = this.$panel;
		if (!isIE()) {
			$toHide.fadeOut(500);
		} else {
			$toHide.hide();
		}
	}
	Panel.prototype.show = function(minMax) {
		var $toShow = this.$panel;
		if (!isIE()) {
			$toShow.fadeIn(500);
		} else {
			$toShow.show();
		}
	}

	//
	// defaults, ready to be overridden globally by for all new instances of the plugin
	//
	$.fn.panelFloater.defaults = {
		itemClass : "item",
		minClass : "minimized",
		maxClass : "maximized",
		raisedClass : "raised",
		minContentClass : "min-content",
		maxContentClass : "max-content",
		panelSideLClass : "panel-side-l",
		panelSideRClass : "panel-side-r",
		sidePointedClass : "pointed",
		sideStraightClass : "straight",
		maxedPanelWidth : 0.5,
		minPanelHeaderHeight : 28,
		verPadding : 5, /* 5px dropshadow zone results in 10px visual padding */
		horPadding : 23, /* -18 + 5 (dropshadow) overlap from panel sides results in 10px visual padding */
		panelOverlap : -31, /* end up being 5px distance between panels */
		baseZIndex : 200
	};

	//
	// end of closure
	//
})(jQuery);

/**
 * Pulls a menu together with a number of dedicated elements that act as a
 * fold-out menu for that item. Submenu items can be placed anywhere on the page
 * and will be positioned absolutely, near the original menu item
 *
 * @Author: Edo Nijmeijer
 */
( function($) {
	//
	// plugin helper object definition. source order matters!
	//
	var PopMenu = function(element, opts) {

		element = $(element);
		var obj = this;

		// establish options, falling back to defaults
		var options = $.extend( {}, $.fn.popMenu.defaults, opts);

		/* private vars */
		var hideTimer = undefined;
		var showTimer = undefined;
		var firstMousePassDetected = false;
		var verticalThreshold = element.offset().top + element.height();
		var $subMenuTriggers;
		var verticalPos;

		/* private methods */
		var hideMenuItem = function($menuItem) {
			$menuItem.hide();
		};
		var clearHideTimer = function() {
			if (hideTimer) {
				clearTimeout(hideTimer);
				hideTimer = undefined;
			}
		};
		var clearShowTimer = function() {
			if (showTimer) {
				clearTimeout(showTimer);
				showTimer = undefined;
			}
		};
		var hideMenus = function() {
			clearHideTimer();
			clearShowTimer();
			$subMenuTriggers.each( function() {
				var $this = $(this);
				var $menuItem = $($this.attr(options.linkAttrib));
				hideMenuItem($menuItem);
			});
		};
		var hideMenuDelayed = function($menuItem) {
			hideTimer = setTimeout( function() {
				hideMenuItem($menuItem);
				hideTimer = undefined;
			}, options.mouseOutHideDelay);
		};
		var addItemHover = function($menuItem) {
			$menuItem.unbind("mouseover").unbind("mouseout");
			$menuItem.bind("mouseover", function() {
				clearHideTimer();
			});
			$menuItem.bind("mouseout", function() {
				clearShowTimer();
				hideMenuDelayed($menuItem);
			});
		};
		var positionMenuAndBarWithTrigger = function($menuItem, $menuTrigger) {
			var triggerAbsOffset = $menuTrigger.offset().left;
			var triggerWidth = $menuTrigger.outerWidth();
			var menuAbsOffset = $menuItem.offset().left;
			var menuRelOffset = $menuItem.position().left;
			var menuAbsToRelCorrection = menuAbsOffset - menuRelOffset;

			// 0. measure
			var toggled = false;
			if (!$menuItem.is(":visible")) {
				toggled = true;
				$menuItem.toggle();
			}
			var menuInsideWidth = $menuItem.width();
			var availWidth = $.getDocumentDimensions().width;
			var menuWidth = $menuItem.outerWidth();
			if (toggled)
				$menuItem.toggle();

			// 1. fit columns to the available width (set on init, not css);
			if (options.popDirection == $.fn.popMenu.POPDIR_DOWN) {
				// rise-ups have their own width pre-set
				var $variableWidthItems = $(".links", $menuItem);
				var widthPerItem = Math.floor((menuInsideWidth - ($variableWidthItems.length) * (isIE6() ? 20 : 10))
						/ $variableWidthItems.length);
				$variableWidthItems.width(widthPerItem);
			}

			// 2. position everything, especially non-drop-down elements
			var $connBar = $("." + options.connectingBarClass, $menuItem);

			var newMenuOffset;
			var newConnOffset;
			var connOffsetForDropdown = (triggerAbsOffset - menuAbsToRelCorrection) - (isIE() ? 2 : 0);

			// horizontal
			if (triggerAbsOffset + menuWidth > availWidth) {
				// cannot extend to right: try to flip to the left instead of right
				if (triggerAbsOffset + triggerWidth - menuWidth < 0) {
					// cannot extend to left either: center
					newMenuOffset = (triggerAbsOffset + triggerWidth / 2) - menuWidth / 2 - menuAbsToRelCorrection;
					newConnOffset = menuWidth / 2 - triggerWidth / 2;

				} else {
					// can flip to left
					newMenuOffset = (triggerAbsOffset + triggerWidth) - menuWidth - menuAbsToRelCorrection;
					newConnOffset = menuWidth - triggerWidth;
					if (isIE()) {
						newConnOffset -= 4;
						newMenuOffset += 4;
					}
				}
			} else {
				// can stay to right
				newMenuOffset = triggerAbsOffset - menuAbsToRelCorrection;
				newConnOffset = 0;
			}

			// try to keep at least the left side in view: correct offset to 0 (+8)
			if (newMenuOffset + menuAbsToRelCorrection < 0) {
				// console.log("correcting neg offset after centering: from:" + newMenuOffset);
				var diff = -1 * (newMenuOffset + menuAbsToRelCorrection) + 8;
				newMenuOffset += diff;
				newConnOffset -= diff;
			}

			// vertical

			if (options.popDirection == $.fn.popMenu.POPDIR_UP) {
				if (isIE6()) {
					/* always recalc for IE (simulates fixed) */
					verticalPos = document.documentElement.clientHeight - 76 - $menuItem.height()
							+ document.documentElement.scrollTop;
					$menuItem.css( {
						top : verticalPos,
						bottom : ""
					});
				} else {
					$menuItem.css( {
						bottom : verticalPos,
						top : ""
					});
				}
			} else {
				$menuItem.css( {
					top : verticalPos,
					bottom : ""
				});
			}

			if (isIE67()) {
				newMenuOffset -= 2;
			}

			// horizontal
			if (options.popDirection != $.fn.popMenu.POPDIR_DOWN) {
				$menuItem.css( {
					left : newMenuOffset
				});
			}
			$connBar.css( {
				left : (options.popDirection != $.fn.popMenu.POPDIR_DOWN) ? newConnOffset : connOffsetForDropdown
			}).show();
			if (isIE67()) {
				// connbar sometimes needs the extra (odd) push to show itself in IE6/7
				$connBar.css("position", "relative").css("position", "absolute");
			}
		};
		var showMenuItemDelayed = function($menuItem, $menuTrigger) {
			showTimer = setTimeout( function() {
				showMenuItem($menuItem, $menuTrigger);
			}, firstMousePassDetected ? options.mouseInShowDelay : options.mouseFirstPassShowDelay);
		}
		var showMenuItem = function($menuItem, $menuTrigger) {
			hideMenus();
			addItemHover($menuItem);
			$menuItem.show();
			positionMenuAndBarWithTrigger($menuItem, $menuTrigger);
			firstMousePassDetected = true;
		};
		var handleFirstMousePass = function(e) {
			if (e.clientY >= verticalThreshold) {
				firstMousePassDetected = true;
				$(document).unbind("mousemove");
			}
		};

		// initialization
		$subMenuTriggers = $(options.menuItemElement + "." + options.subMenuIndicatorClass, element);

		$subMenuTriggers.each( function() {
			var $this = $(this);
			var linkRef = $this.attr(options.linkAttrib);

			if (linkRef != "") {
				var $menu = $(linkRef);
				var connBarHeight = $("." + options.connectingBarClass, $menu).height();

				/*position and size */
				if (options.popDirection == $.fn.popMenu.POPDIR_DOWN) {
					$menu.css("position", "absolute");

					var toggled = false;
					if (!$menu.is(":visible")) {
						toggled = true;
						$menu.toggle();
					}

					var normalAvailWidth = $(".about-moneyou", element).offset().left - element.offset().left; /* from Home to 'about' */
					if (isIE()) {
						normalAvailWidth += 4;
					}
					var neededWidthForBanners = 0; // adding banners can make menu too wide: measure
				$(".banners li", $menu).each( function() {
					neededWidthForBanners += $(this).outerWidth(true);
				});

				$menu
						.width((neededWidthForBanners > (normalAvailWidth - ($menu.outerWidth() - $menu.width()))) ? neededWidthForBanners
								: normalAvailWidth - ($menu.outerWidth() - $menu.width()));
				verticalPos = $this.offset().top + $this.outerHeight();
				$menu.css( {
					top : verticalPos,
					left : 0,
					bottom : ""
				});

				if (toggled)
					$menu.toggle();

				// click events for banners:
				$("a.banner-link", $menu).each( function() {
					$(this).parents(".banners>li").click( function(event) {
						var link = $("a.banner-link", $(this)).attr("href");
						window.location.href = link;
					});
				});
			} else if (options.popDirection == $.fn.popMenu.POPDIR_DOWN_SIMPLE) {
				$menu.css("position", "absolute");
				verticalPos = $this.offset().top + $this.outerHeight();
				$menu.css( {
					top : verticalPos,
					bottom : ""
				});
			} else {
				if (!isIE6()) {
					$menu.css("position", "fixed");
					verticalPos = $this.outerHeight();
				} else {
					$menu.css("position", "absolute");
				}
				$menu.css( {
					bottom : verticalPos,
					top : ""
				});
			}
			$menu.hide();
			positionMenuAndBarWithTrigger($menu, $this);

			// adapt width of the red connecting bar
			$("." + options.connectingBarClass, $menu).width($this.outerWidth());

			// hover events
			$this.hover( function() {
				clearShowTimer();
				showMenuItemDelayed($menu, $this);
			}, function() {
				clearShowTimer();
				hideMenuDelayed($menu);
			});

			// wire the close button, if present
			$("." + options.closeButtonClass, $menu).click( function() {
				hideMenus();
				return false;
			});
		}

	})	;

		// wire 'first pass event' for tab row
		if (options.popDirection == $.fn.popMenu.POPDIR_DOWN) {
			$(document).mousemove(handleFirstMousePass);
		} else {
			// no distinction between first and next passes
			firstMousePassDetected = true;
		}

	};

	/* actual plugin definition */
	$.fn.extend( {
		popMenu : function(options) {
			// iterate over all passed in objects
			return this.each( function() {
				var element = $(this);

				// do not allow double instantiation under the same dataelement name
					// strange construction needed because we call popMenu on ul#tabs twice for 2 types of submenus
					var dataIndex = 0;
					var dataName = "popMenu";
					while (element.data(dataName + dataIndex)) {
						dataIndex++;
					}

					// create instance
					var _popMenu = new PopMenu(this, options);
					// store object in element's data for later reference
					element.data(dataName + dataIndex, _popMenu);
				});
		}
	});

	//
	// private variables shared between plugin instances
	//
	var privVar;

	//
	// private functions shared between plugin instances
	//

	var func = function(arg) {
	};

	//
	// defaults, ready to be overridden globally for all new instances of the plugin
	//
	$.fn.popMenu.defaults = {
		mouseOutHideDelay : 500,
		mouseFirstPassShowDelay : 700,
		mouseInShowDelay : 250,
		menuItemElement : "a",
		subMenuIndicatorClass : "has-submenu",
		linkAttrib : "rel",
		connectingBarClass : "sm-con",
		popDirection : $.fn.popMenu.POPDIR_DOWN,
		closeButtonClass : "close"
	};
	$.fn.popMenu.POPDIR_UP = -1;
	$.fn.popMenu.POPDIR_DOWN = 1;
	$.fn.popMenu.POPDIR_DOWN_SIMPLE = 2;

	//
	// end of closure
	//
})(jQuery);

/**
 * Creates a set of collapsible items that can interact like an accordeon, or
 * not
 *
 * @Author: Edo Nijmeijer
 */
( function($) {
	//
	// plugin helper object definition
	//
	var CollapsibleSection = function(element, opts) {

		element = $(element);
		var obj = this;

		// establish options, falling back to defaults
		var options = $.extend( {}, $.fn.collapsibleSection.defaults, opts);

		/* private vars */
		var $triggers;
		var $sections;

		/* private methods */
		var collapseSection = function($section, callback) {

			//			if (!isIE67()) {
			//				$section.slideUp(options.collapseTiming, callback);
			//			} else {
			$section.hide();
			$section.css("display", "none");
			if (callback)
				callback();
			//			}
		};
		var showSection = function($section, callback) {
			if (!isIE67()) {
				$section.slideDown(options.extendTiming, callback);
			} else {
				$section.show();
				if (callback)
					callback();
			}
		};
		var hideAllSections = function() {
			collapseSection($sections);
		};

		// initialization

		// add .first and .last to respective section
		element.children(options.triggerAndSectionContainer + ":first").addClass("first-child");
		element.children(options.triggerAndSectionContainer + ":last").addClass("last-child");

		$triggers = $(options.triggerElement + "." + options.triggerClass, element);

		$triggers.each( function() {
			var $this = $(this);
			var $container = $this.parent("" + options.triggerAndSectionContainer);
			$container.data(options.dataItemOnTSContainer, obj);
			var $sectionsWithinContainer = $(options.sectionElement + "." + options.sectionClass, $container);
			if (!$sections || $sections.length == 0)
				$sections = $sectionsWithinContainer;
			else
				$sections = $sections.add($sectionsWithinContainer);

			/* cleanup up (backup?) href */
			if (options.triggerElement.indexOf("a") == 0)
				$this.attr("href", "javascript:void(0);");

			/* wire events */
			$this.click( function(event) {
				event = event || window.event;
				event.stopPropagation();
				event.cancelBubble = true;

				/* close other open items, if needed */
				var $otherOpenContainers;
				if (options.singleContainerPerElementOpen) {
					$openContainersThatNeedToBeClosed = $container.siblings("." + options.extendedContainerClass).not(
							$container[0]);
					if (options.singleContainerPerPageOpen) {
						var $openContainersThatCouldBeClosed = $("." + options.extendedContainerClass).not($container[0]);
						/* see if other container are part of a collapsiblesection element that is configured as such */
						$openContainersThatCouldBeClosed.each( function() {
							var $this = $(this);
							var remoteOptions = $this.data(options.dataItemOnTSContainer).getOptions();
							if (remoteOptions.singleContainerPerPageOpen) {
								collapseSection($(remoteOptions.sectionElement + "." + remoteOptions.sectionClass, $this),
										function() {
											$this.removeClass(remoteOptions.extendedContainerClass);
										});
							}
						});
					}

					collapseSection(
							$(options.sectionElement + "." + options.sectionClass, $openContainersThatNeedToBeClosed),
							function() {
								$openContainersThatNeedToBeClosed.removeClass(options.extendedContainerClass);
							});

				}

				/* deal with own container, at the least */
				if ($container.hasClass("extended")) {
					collapseSection($sectionsWithinContainer, function() {
						$container.removeClass(options.extendedContainerClass);
					});
				} else {
					showSection($sectionsWithinContainer, function() {
						$container.addClass(options.extendedContainerClass);
					});
				}
				return false;
			});

			/* wire the close buttons _within_ sections, if present */
			$(options.closeButtonSelector, $sectionsWithinContainer).click( function() {
				collapseSection($sectionsWithinContainer);
				return false;
			});
		});

		if (options.hideAllOnInit)
			hideAllSections();

		this.getOptions = function() {
			// public method. Call by getting the object off the elements 'data' and calling it
			return options;
		};

	};

	/* actual plugin definition */
	$.fn.extend( {
		collapsibleSection : function(options) {
			// iterate over all passed in objects
			return this.each( function() {
				var element = $(this);

				/* do not allow double instantiation */
				if (element.data("collapsibleSection"))
					return;

				/* create instance */
				var _collapsibleSection = new CollapsibleSection(this, options);
				/* store object in element's data for later reference */
				element.data("collapsibleSection", _collapsibleSection);
			});
		}
	});

	//
	// private variables shared between plugin instances
	//
	var privVar;

	//
	// private functions shared between plugin instances
	//

	var func = function(arg) {
	};

	//
	// defaults, ready to be overridden globally for all new instances of the plugin
	//
	$.fn.collapsibleSection.defaults = {
		triggerAndSectionContainer : "li",
		triggerElement : "a",
		triggerClass : "trigger",
		sectionElement : "",
		sectionClass : "collapsible",
		extendedContainerClass : "extended",
		closeButtonSelector : "a.closeSectionTrigger",
		hideAllOnInit : true,
		singleContainerPerElementOpen : true,
		singleContainerPerPageOpen : false,
		collapseTiming : 250,
		extendTiming : 500,
		dataItemOnTSContainer : "csElementRef"
	};
	$.fn.collapsibleSection.POPDIR_UP = -1;
	$.fn.collapsibleSection.POPDIR_DOWN = 1;

	//
	// end of closure
	//
})(jQuery);

/**
 * Adds 'borders' (corners and optional sidepanels) to an element. The actual
 * visual representation should be handled by css (which makes sure that sizes,
 * paths and positioning are kept there)
 *
 * @Author: Edo Nijmeijer
 */
( function($) {
	//
	// plugin object definition
	//
	var AddBorders = function(element, options) {

		$element = $(element);
		// establish options, falling back to defaults
		var options = $.extend( {}, $.fn.addBorderElements.defaults, options);

		var obj = this;

		this.getOptions = function() {
			// public method. Call by getting the object off the elements 'data' and calling it
			return options;
		};

		if (!options.forInternetExplorerOnly || (options.forInternetExplorerOnly && $.browser.msie)) {
			if (!options.specificMinIEVersion || $.browser.version >= options.specificMinIEVersion) {
				// insert needed elements
				var $firstContainerChild = $element.children().eq(0);

				var cTL, cTR, cBL, cBR, sT, sR, sB, sL, elementArray = $("corners");

				cTL = $(document.createElement("div")).addClass(
						options.baseCornerClass + " " + options.baseCornerClass + options.topClass + options.leftClass);
				cTR = $(document.createElement("div")).addClass(
						options.baseCornerClass + " " + options.baseCornerClass + options.topClass + options.rightClass);
				cBL = $(document.createElement("div")).addClass(
						options.baseCornerClass + " " + options.baseCornerClass + options.bottomClass + options.leftClass);
				cBR = $(document.createElement("div")).addClass(
						options.baseCornerClass + " " + options.baseCornerClass + options.bottomClass + options.rightClass);

				elementArray = elementArray.add(cTL).add(cTR).add(cBL).add(cBR);

				if (options.type == $.fn.addBorderElements.CORNERS_AND_SIDES) {

					$element.css( {
						"overflow" : "visible"
					});

					sT = $(document.createElement("div")).addClass(
							options.baseSideClass + " " + options.baseSideClass + options.topClass);
					sR = $(document.createElement("div")).addClass(
							options.baseSideClass + " " + options.baseSideClass + options.rightClass);
					sB = $(document.createElement("div")).addClass(
							options.baseSideClass + " " + options.baseSideClass + options.bottomClass);
					sL = $(document.createElement("div")).addClass(
							options.baseSideClass + " " + options.baseSideClass + options.leftClass);
					elementArray = elementArray.add(sT).add(sR).add(sB).add(sL);

					if ($.browser.msie && $.browser.version < 7) {
						sT.add(sB).width($element.outerWidth());
						sL.add(sR).height($element.outerHeight());
						$element.resize( function() {
							$this = $(this);
							var $hors = $("." + options.baseSideClass + options.topClass + ", ." + options.baseSideClass
									+ options.bottomClass, $this);
							var $verts = $("." + options.baseSideClass + options.leftClass + ", ." + options.baseSideClass
									+ options.rightClass, $this);
							$hors.width($this.outerWidth());
							$verts.height($this.outerHeight());
						});

					}
				}

				elementArray.insertBefore($firstContainerChild);
			}
		}

	};

	//
	// plugin definition
	//
	$.fn.extend( {
		addBorderElements : function(options) {
			// iterate over all passed in objects
			return this.each( function() {
				var element = $(this);

				// do not allow double instantiation
					if (element.data("addBorderElements"))
						return;

					// create instance
					var _addBorderElements = new AddBorders(this, options);
					// store object in element's data for later reference
					element.data("addBorderElements", _addBorderElements);
				});
		}
	});

	//
	// defaults, ready to be overridden by plugin-user
	//
	$.fn.addBorderElements.defaults = {
		baseCornerClass : "corner",
		baseSideClass : "side",
		topClass : "T",
		bottomClass : "B",
		leftClass : "L",
		rightClass : "R",
		forInternetExplorerOnly : true,
		specificMinIEVersion : undefined,
		type : $.fn.addBorderElements.CORNERS_ONLY
	};
	$.fn.addBorderElements.CORNERS_ONLY = 1;
	$.fn.addBorderElements.CORNERS_AND_SIDES = 2;
	//
	// end of closure
	//
})(jQuery);

/*
 * extend the validation framework (if present) with some methods that can/will be re-used on all pages
 */
if (jQuery.fn.validate) {

	$.extend(jQuery.validator, {
		errorPlacementFn : function(error, element) {
			var $status = element.parent("dd").next("dd.status");
			$status.html("").append(error);
			var $emsgContainer = $(".errormessages ul");
			var message = error.text();
			$emsgContainer.find("li." + element[0].name).remove();
			if (message != "") {
				$emsgContainer.append("<li class=\"" + element[0].name + "\">" + message + "</li>");
			}
			if ($emsgContainer.find("li").length == 0) {
				$(".errormessages").slideUp(500);
			}
		},
		invalidHandlerFn : function(formMap, validator) {
			var errorCount = validator.numberOfInvalids() || 0;
			if (errorCount > 0) {
				$(".errormessages").show();
				$(".errormessages ul").hide();
				$(".errormessages ul").slideDown(500);
			}
		},
		highlightFn : function(element, errorClass) {
			$(element).addClass(errorClass);
			$(element.form).find("label[for=" + element.name + "]").addClass(errorClass);
		},
		unhighlightFn : function(element, errorClass) {
			$(element).removeClass(errorClass);
			$(element.form).find("label[for=" + element.name + "]").removeClass(errorClass);
			$(".errormessages ul").find("li." + element.name).remove();
		},
		successFn : function(label) {
			label.html("").removeClass("invalid").addClass("valid");
		}
	});
}

/*
 * GLOBALS
 */

if (!window.console) {
	console = {};
	console.log = function(txt) {
		window.status = txt;
		return;
	};
	console.info = function(txt) {
		console.log(txt);
	};
	console.error = function(txt) {
		console.log(txt);
	};
	console.debug = function(txt) {
		console.log(txt);
	};
	console.warn = function(txt) {
		console.log(txt);
	};
}

//set up namespace for globals
("moneyou.globals").namespace();

/*
 * START global constants
 */
moneyou.globals.prodLineUpDelay = 500;
moneyou.globals.minFlashVersion = "6.0.0";
moneyou.globals.lastCampaignParametersCookie = "MoneYou.campaign.parameters"
/* END global constants */

/*
 * START dynamically (pre)initialized global variables
 */
moneyou.globals.ieVersion;
moneyou.globals.prodLineUpShowTimer;
moneyou.globals.loginFromButton;
moneyou.globals.flashObjects = new Array();

/* END dynamically (pre)initialized global variables */

/*
 * START helper objects, caches
 */

/* END helper objects, caches */
