 /**
 * Copyright (c) 2011 Faculty of Environmental Studies, York University.  All rights reserved.
 * http://www.yorku.ca/fes/
 *
 * The use, duplication, redistribution or modification of any code in this file,
 * in whole or in part, is strictly prohibited.
 *
 * @author		Brenn Kha, bnkha @ yorku . ca
 * @version		Version 2.0.0, 2011-02-22 10:24:13
 */

var FES = {
	Ajax : {},
	App : {},
	Constants : {},
	Debug : {},
	Page : {},
	Template : {},
	UI : {},
	Url : {},
	Widgets : {}
};

FES.Constants =
{
	HOMEPAGE : "/fes/"
};

FES.Debug =
{
	mode : function(on)
	{
		if (on)
		{
			$.w = FES.Debug.wp;
			$.a = FES.Debug.ap;
			$.c = FES.Debug.console;
			a = "__hello, world__";
		}
	},
	
	// alert properties
	ap : function(selector)
	{
		var output = FES.Debug._getOutput(selector);
		var div = $("<div></div>").html(output);
		alert(div.text());

		/*
		var o = "";
		var e = $(selector);
		for (var x in e)
		{
			o += x + " = " + e[x] + "\n\n";
			if (o.length > 300)
			{
				alert(o);
				o = "";
			}
		}
		*/
	},

	// write properties
	wp : function(selector)
	{
		var output = FES.Debug._getOutput(selector);
		
		$("body").css("background", "#fff");
		$("body").html("<pre>" + output + "</pre>");
		
		FES.Debug.abort();
	},
	
	console : function(selector)
	{
		var output = FES.Debug._getOutput(selector);
		var button = $("#_debug_console_button");
		var div = $("#_debug_console");
		if (div.length == 0)
		{
			button = '<button id="_debug_console_button" style="position: absolute; z-index: 99999" onclick="$(\'#_debug_console\').toggle()">Show/Hide</button>';
			div = $('<div id="_debug_console" style="position: absolute; background-color: #000; color: #fff; padding: 0.5em"></div>');
		}
		div.html(div.html() + "\n" + String(output));
		div = div.wrapInner("<pre>");
		$("body").prepend(div).prepend(button);
	},
	
	_getOutput : function(selector)
	{
		var output = "";
		
		var type = typeof(selector);
		if (selector == null)
		{
			output += "NULL";
		}
		else if ($.inArray(type, ["string", "number", "boolean"]) != -1) // && selector.match(/^(#|\.)/) == null)
		{
			output += selector;
		}
		else if (selector.jquery == null)
		{
			output += "<b>type</b>" + " = " + $.type(selector) + "\n";
			for (var p in selector)
			{
				output += "<b>" + p + "</b>" + " = " + selector[p] + "\n";
			}
		}
		else
		{
			output += "<b>type</b>" + " = " + $.type(selector) + "\n";
			
			var el = $(selector);
			
			if (el.length == 1)
			{
				output += "<b>nodeName</b>" + " = " + $(selector).get(0).nodeName + "\n";
			}
			
			//var jqProperties = ["init", "size", "toArray", "get", "pushStack", "each", "ready", "eq", "first", "last", "slice", "map", "end", "push", "sort", "splice", "extend", "data", "removeData", "queue", "dequeue", "delay", "clearQueue", "attr", "removeAttr", "addClass", "removeClass", "toggleClass", "hasClass", "val", "bind", "one", "unbind", "delegate", "undelegate", "trigger", "triggerHandler", "toggle", "hover", "live", "die", "blur", "focus", "focusin", "focusout", "load", "resize", "scroll", "unload", "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseover", "mouseout", "mouseenter", "mouseleave", "change", "select", "submit", "keydown", "keypress", "keyup", "error", "find", "has", "not", "filter", "is"];
			var jqObj = $();
			var jqKeepProperties = ["selector", "context", "length"];
			for (var property in el)
			{
				//if ($.inArray(property, jqProperties) != -1)
				//{
				//	continue;
				//}
				if ($.inArray(property, jqKeepProperties) == -1 && jqObj[property] != null)
				{
					continue;
				}
				output += "<b>" + property + "</b>" + " = " + el[property] + "\n";
			}
		}
		
		return output;
	},
	
	abort : function()
	{
		throw new Error('FES.Debug.abort() called.');
	}
};

FES.Ajax =
{
	getJsonp : function(conf)
	{
		conf.dataType = "jsonp";
		conf.jsonp = "jpcb";
		conf.jsonpCallback =  "jpcb_" + conf.jsonpCallback;
		//conf.error = function(jqXHR, status, errorThrown)
		//{
		//	$.get("http://fes.apps01.yorku.ca/system/log/error/ajax");
		//}
		
		$(document).ready(function()
		{
			$.ajax(conf);
		});
	}
};

FES.Url =
{
	queryString : function(url)
	{
		var qsObj = {};
		var qs = null
		if (url != null)
		{
			qs = url.split("?");
			qs = (qs[1] !== undefined) ? qs[1] : "";
		}
		else
		{
			qs = window.location.search.substr(1);
		}
		
		var tokens = qs.split("&");
		var pair;
		for (i in tokens)
		{
			pair = tokens[i].split("=");
			qsObj[pair[0]] = (pair[1] !== undefined) ? pair[1] : null;
		}

		qsObj.length = (qs.length > 0) ? tokens.length : 0;
		qsObj.exists = FES.Url._queryString_exists;
		return qsObj;
	},
	
	_queryString_exists: function(name)
	{
		return this[name] !== undefined;
	}
	
};

FES.Template =
{
	Ajax : {},
	
	showContentOnly : function()
	{
		var width = "730px";
		
		var body = $("body");
		body
			.hide()
			.css("background", "none")
			//.css("float", "left")
			.css("width", width)
			.children().not("#t-body").remove()
		;
		
		var innerBody = body.children("#t-body");
		innerBody
			//.css("float", "left")
			.css("width", width)
			.children().not("#t-nav-and-content-area").remove()
			//.children().not("#t-nav-and-content-area").hide()
		;
		
		var navAndContentArea = innerBody.children("#t-nav-and-content-area");
		navAndContentArea
			//.css("float", "left")
			.css("width", width)
			.children().not("#t-content-area").remove()
			//.children().not("#t-content-area").hide()
		;
		
		var contentArea = navAndContentArea.children("#t-content-area");
		contentArea
			.css("width", width)
			.children().not("#t-content").remove()
			//.children().not("#t-content").hide()
		;
		
		var content = contentArea.children("#t-content");
		content
			.css("margin", "0")
			.css("background", "none")
			.css("padding", "0")
			.css("width", width)
		;
		
		body.show();
	}
};

FES.UI =
{
	button : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		conf.color = (conf.color != null) ? conf.color : "purple";
		
		selector = $(selector);
		var content = selector.html();
		selector.html('<span class="text">' + content + '</span><span>&nbsp;</span>');
		
		var cssClass1 = "c-button-" + conf.color;
		var cssClass2 = cssClass1 + "-js";
		selector.addClass(cssClass1, !selector.hasClass(cssClass1));
		selector.addClass(cssClass2);

		// @note: Browser detection may be deprecated in future jQuery releases
		// @note: This hack may not work in IE9 as it relies on IE blur filter, which is deprecated for IE9
		//if ($.browser.msie && ($.browser.version == "7.0" || $.browser.version == "8.0"))
		if ($.browser.msie)
		{
			var text = selector.children("span").first();
			text
				.css("z-index", "0")
				.css("position", "relative")
			;
			
			var filter =
				$('<span class="text">' + text.text() + '</span>')
				.css("z-index", "-1")
				.css("position", "absolute")
				.css("filter", "progid:DXImageTransform.Microsoft.Blur(pixelradius=2, enabled=\'true\')")
				.css("padding", "0")
				.css("color", "#333")
				.css("top", "-1px")
				.css("left", "-1px")
				.css("background", "none")
				
				.css("padding-left", text.css("padding-left"));
			;
			
			text.append(filter);
		}

		return selector;
	},
	
	more : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		
		selector = $(selector);
		
		prefix = '<span class="c-raquo">&raquo;</span> ';
		selector.each(function(i)
		{
			var el = $(this);
			el.html(prefix + el.html());
		});
	},
	
	focus : function(selector, conf)
	{
		selector = $(selector);
		conf = (conf != null) ? conf : {};
		
		selector.focus();
	}
};

FES.UI.Icons =
{
	_iconStyles : "",
	_defaultStyles : "",
	_iconOnlyStyles : "",
	
	_init : function()
	{
		FES.UI.Icons._iconStyles = "display: inline-block; text-indent: 0; vertical-align: text-bottom; margin-left: -16px;";
		FES.UI.Icons._iconStyles += "cursor: pointer;" // IE7 fix
		
		FES.UI.Icons._defaultStyles = "display: inline-block; white-space: nowrap; padding-left: 16px;";
		FES.UI.Icons._iconOnlyStyles = "width: 0px; overflow: hidden;";
		
		//var dialogId = 1;
	},
	
	NewWin :
	{
		setup : function(conf)
		{
			conf = (conf != null) ? conf : {};
			conf.selector = (conf.selector != null) ? $(conf.selector) : $(".c-icon-newwin, .c-icon-newwin-text");
			
			// init
			FES.UI.Icons._init();
			
			// new window
			var icon = conf.selector;
			if (icon.length > 0)
			{
				icon.prepend('<span class="ui-icon ui-icon-newwin" style="' + FES.UI.Icons._iconStyles + '"></span>')
					.attr(
					{
						style: function(i, val)
						{
							var style = "";
							var el = $(this);
							if (el.is(".c-icon-newwin"))
							{
								style = FES.UI.Icons._iconOnlyStyles;
								el.attr("title", el.text());
							}
							
							return FES.UI.Icons._defaultStyles + style;
						},
						target: "_blank",
						title: function(i, val)
						{
							return $(this).attr("href");
						}
					})
				;
			}
		} 
	},

	Update :
	{
		setup : function(conf)
		{
			conf = (conf != null) ? conf : {};
			conf.selector = (conf.selector != null) ? $(conf.selector) : $(".c-icon-update, .c-icon-update-text");
			
			// init
			FES.UI.Icons._init();
			
			// update
			icon = conf.selector;
			if (icon.length > 0)
			{
				icon.prepend('<span class="ui-icon ui-icon-pencil" style="' + FES.UI.Icons._iconStyles + '"></span>')
					.attr(
					{
						style: function(i, val)
						{
							var style = "";
							var el = $(this);
							if (el.is(".c-icon-update"))
							{
								style = FES.UI.Icons._iconOnlyStyles;
								el.attr("title", el.text());
							}
							
							return FES.UI.Icons._defaultStyles + style;
						}
					})
				;
			}

		} 
	},

	Delete :
	{
		setup : function(conf)
		{
			conf = (conf != null) ? conf : {};
			conf.selector = (conf.selector != null) ? $(conf.selector) : $(".c-icon-delete, .c-icon-delete-text");
			
			// init
			FES.UI.Icons._init();
			
			// delete
			icon = conf.selector;
			if (icon.length > 0)
			{
				icon
					.prepend('<span class="ui-icon ui-icon-trash" style="' + FES.UI.Icons._iconStyles + '"></span>')
					.attr(
					{
						style: function(i, val)
						{
							var style = "";
							var el = $(this);
							if (el.is(".c-icon-delete"))
							{
								style = FES.UI.Icons._iconOnlyStyles;
								el.attr("title", el.text());
							}
							
							return FES.UI.Icons._defaultStyles + style;
						}
					})
				;
				
				iconAjax = icon.filter(".c-ajax-delete-row, .c-delete-row");
				if (iconAjax.length > 0)
				{
					icon
						.after(function(i, html) // append dialog html
						{
							var idPrefix = $(this).attr("id");
							id = idPrefix.split("_").pop();
							return '<div id="' + idPrefix + '_dialog">Are you sure you want to delete <strong>ID:' + id + '</strong>?</div>';
						})
						.click(function()
						{
							var id = $(this).attr("id") + "_dialog";
							$("#" + id).dialog("open");
							
							return false;
						})
						.next()
							.dialog(
							{
								autoOpen: false,
								modal: true,
								resizable: false,
								draggable: false,
								show: "fade",
								title: "Confirm delete",
								buttons:
								{
									"Yes, delete now": function()
									{
											var el = $(this);
											el.dialog("close");
											
											var id = el.attr("id").replace("_dialog", "");
											var icon = $("#" + id);
											var url = icon.attr("href");
											
											if (icon.is(".c-ajax-delete-row"))
											{
												url += "/ajax/json";
												$.getJSON(url, function(data, status, xhr)
												{
													if (data.status == "success")
													{
														var row = icon.closest("tr");
														row.children("td").each(function()
														{
															$(this).wrapInner("<div></div>").children("div:first").slideUp("slow", function(){row.remove()});
														});
													}
													
													var msg_el = $(".c-ajax-msg");
													if (msg_el.is(":visible"))
													{
														msg_el.fadeOut(function()
														{
															$(this).html(data.message).fadeIn();
														});
													}
													else
													{
														msg_el.html(data.message).slideDown();
													}
													
													//$(document).scrollTop(0);
												});
											}
											else
											{
												window.location.href = url;
											}
									},
									"No": function()
									{
											$(this).dialog("close");
									}
								},
								open: function()
								{
									var el = $(this);
									var buttons = el.dialog("widget").find("button");
									buttons.first().blur();
									buttons.last().focus();
								}
							}
						)
					;
				}
			}
		} 
	},

	X :
	{
		setup : function(conf)
		{
			conf = (conf != null) ? conf : {};
			conf.selector = (conf.selector != null) ? $(conf.selector) : $(".c-icon-x, .c-icon-x-text");
			
			// init
			FES.UI.Icons._init();
			
			// x
			icon = conf.selector;
			if (icon.length > 0)
			{
				icon.prepend('<span class="ui-icon ui-icon-circle-close" style="' + FES.UI.Icons._iconStyles + '"></span>')
					.attr(
					{
						style: function(i, val)
						{
							var style = "";
							var el = $(this);
							if (el.is(".c-icon-x"))
							{
								style = FES.UI.Icons._iconOnlyStyles;
								el.attr("title", el.text());
							}
							
							return FES.UI.Icons._defaultStyles + style;
						}
					})
				;
			}
		} 
	},
	
	init : function(conf)
	{
		conf = (conf != null) ? conf : {};
		//conf.newwin = (conf.newwin != null) ? conf.newwin: {showText: false};
		
		/*
		.ui-icon {
			display: inline-block !important;
			text-indent: 0 !important;
			vertical-align: text-bottom;
		}
		*/
		
		FES.UI.Icons.NewWin.setup();
		FES.UI.Icons.Update.setup();
		FES.UI.Icons.Delete.setup();
		FES.UI.Icons.X.setup();
	}
};

FES.UI.RichTextArea =
{
	setup : function(selector, conf)
	{
		if ($.fn.tinymce == null)
		{
			return;
		}

		conf = (conf != null) ? conf : {};
		conf.validElements = "";
		
		// markup configurations
		conf.validElements += (conf.textarea) ? ",p,br" : "";
		conf.validElements += (conf.link) ? ",a[href]" : "";
		conf.link = (conf.link) ? ",|,link,unlink" : "";
		
		// for cross-domain support
		document.domain = 'yorku.ca';
	
		$(selector).tinymce(
		{
			// Location of TinyMCE script
			script_url : 'http://www.yorku.ca/fes/www2/js/jquery/plugins/tiny_mce/tiny_mce.js',

			// General options
			theme : "advanced",
			plugins : "inlinepopups,paste",
			
			// Theme options
			//theme_advanced_buttons1 : "bold,italic,charmap",
			theme_advanced_buttons1 : "bold,italic,charmap" + conf.link,
			theme_advanced_buttons2 : "",
			theme_advanced_buttons3 : "",
			theme_advanced_buttons4 : "",
			theme_advanced_toolbar_location : "top",
			theme_advanced_toolbar_align : "left",
			theme_advanced_statusbar_location : "none",
			theme_advanced_resizing : false,

			// paste options
			paste_auto_cleanup_on_paste : true,

			// Example content CSS (should be your site CSS)
			content_css : "http://www.yorku.ca/fes/www2/js/jquery/plugins/tiny_mce/tiny_mce.css",
			
			valid_elements : "strong/b,em/i" + conf.validElements
		});
	}
};

FES.UI.DatePicker =
{
	setup : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		conf.selector = $(selector);

		if (conf.selector.length > 0)
		{
			// @note: .mask "hangs" page, hence the 'if' condition
			conf.selector
				.datepicker()
				.mask("m9/d9/9999")
			;
		}
	}
};

FES.UI.Overlay =
{
	api : {},
	
	setup : function(selector, conf)
	{
		var uid = $(selector).selector.replace(/[\ \.#:\(\)]/g, "_");
		var targetId = "_overlay_" + uid;		
		var newWin = "";
		var content = "";
		var footer = "";
		
		conf = (conf != null) ? conf : {};
		conf.selector = $(selector);
		conf.target = (conf.target != null) ? conf.target : "#" + targetId;
		conf.mask = (conf.mask != null) ? conf.mask :
		{
			color: "#333",
			opacity: 0.5
		};
		conf.footer = (conf.footer != null) ? conf.footer : "";
		conf.external = (conf.external != null) ? conf.external : false;
		conf.height = (conf.height != null) ? conf.height : null;
		conf.maxHeight = (conf.maxHeight != null) ? conf.maxHeight : null;
		//conf.heightParam = (conf.heightParam != null) ? conf.heightParam : "h";
		//conf.topParam = (conf.heightParam != null) ? conf.topParam : "t";
		//conf.newWinParam = (conf.newWinParam != null) ? conf.newWinParam : 'nw';
		conf.newWin = (conf.newWin != null) ? conf.newWin : false;
		conf.fixed = (conf.fixed != null) ? conf.fixed : false;
		
		// 'conf.external = true' only
		conf.layout = (conf.layout != null) ? conf.layout : null;

		if (conf.external)
		{
			content = '<iframe src="http://www.yorku.ca/fes/web/default/iframe.htm" scrolling="auto" frameborder="0" allowtransparency="true">Your browser does not support iframes.</iframe>';
			
			conf.onBeforeLoad = function()
			{
				// @note: 'this' == this.api
				FES.UI.Overlay._loadContent(uid, this);
			};

			conf.onClose = function()
			{
				var overlay = this.getOverlay();
				
				var content = overlay.find(".content");
				content.hide();
				content.find("iframe").attr("src", "about:blank");
				
				var ajaxLoader = overlay.find(".c-ajax-loader-text");
				ajaxLoader.show();
			};
		}
		
		newWin =
			'<p class="new-win" style="margin: 5px 30px 0 0; text-align: right; display: none"><a class="c-small c-icon-newwin-text" href="#" target="_blank">Open in new window</a></p>' +
			'<script type="text/javascript">FES.UI.Icons.NewWin.setup({selector: ".c-icon-newwin-text"});</script>'
		;
		
		if (conf.footer == "navigation")
		{
			footer =
				'<div class="nav">' +
					'<a href="#" class="prev active" onclick="return FES.UI.Overlay.prev(\'' + uid + '\')"></a>' +
					'<a href="#" class="next active" onclick="return FES.UI.Overlay.next(\'' + uid + '\')"></a>' + 
				'</div>'
			;
		}

		if ($("#" + targetId).length == 0)
		{
			$("body").append(
				'<div id="' + targetId + '" class="w-overlay">' +
					'<div class="content">' +
						newWin +
						content +
						footer +
					'</div>' +
					'<p class="c-ajax-loader-text">Loading...</p>' +
				'</div>'
			);
			
			// IE fix: Not show modal background
			
			ieConf =
			{
				mask:
				{
					loadSpeed: 0,
					opacity: 0
				}
			};

			$("body").append('<div id="_ie' + targetId + '" style="display: none"></div>');
			var ieOverlay = $("#_ie" + targetId).overlay(ieConf).data("overlay").load().close();
		}
		
		conf.selector.overlay(conf);
		
		return conf.selector;
	},
	
	prev : function(uid)
	{
		var api = this.api[uid];
		var current =  api.getTrigger();
		var prev = FES.UI.Overlay._getPrev(uid, current);
		
		if (prev.length > 0)
		{
			this._loadContent(uid, prev.data("overlay"));
		}
		
		return false;
	},
	
	next : function(uid)
	{
		var api = this.api[uid]
		var current =  api.getTrigger();
		var next = FES.UI.Overlay._getNext(uid, current);
		
		if (next.length > 0)
		{
			this._loadContent(uid, next.data("overlay"));
		}
		
		return false;
	},
	
	_loadContent : function(uid, api)
	{
		this.api[uid] = api;
		var conf = api.getConf();
		var overlay = api.getOverlay();
		var trigger = api.getTrigger();
		
		var newWin = overlay.find(".new-win a");
		var content = overlay.find(".content");
		var ajaxLoader = overlay.find(".c-ajax-loader-text");
		
		var src = trigger.attr("href");
		var iframe = overlay.find("iframe");

		iframe.one('load', function()
		{
			//var qs = FES.Url.queryString(src);
			
			// set height
			var height;
			if (conf.height != null)
			{
				height = conf.height;
			}
			else
			{
				content.show();
				height = $(this).contents().find("#t-content").height();
				
				if (conf.maxHeight != null && height < 100)
				{
					height = conf.maxHeight;
				}
			}
			$(this).height(height);
			
			content.hide().css("visibility", "visible").slideDown();
			ajaxLoader.hide();
		});

		content.slideUp(function()
		{
			ajaxLoader.slideDown("fast", function()
			{
				var prev = FES.UI.Overlay._getPrev(uid, trigger);
				$(".w-overlay .nav .prev").toggleClass("active", prev.length > 0).blur();
				var next = FES.UI.Overlay._getNext(uid, trigger);
				$(".w-overlay .nav .next").toggleClass("active", next.length > 0).blur();
				
				newWin.attr("href", src);
				if	(conf.newWin)
				{
					newWin.closest(".new-win").show();
				}
				else
				{
					newWin.closest(".new-win").hide();
				}

				if (conf.layout == "content")
				{
					var qs = FES.Url.queryString(src);
					src = (qs.length > 0) ? src + "&c" : src + "?c";
				}
				
				iframe.attr("src", src);
			});
		});
	},
	
	_getPrev : function(uid, current)
	{
		var api = this.api[uid];
		var selector = $(api.getConf().selector.selector);
		var currentIndex = selector.index(current);
		
		var prevs = selector.filter(':lt(' + currentIndex + ')').filter(':[href!="' + current.attr('href') + '"]');
		var prev = prevs.last();
		
		return prev;
	},

	_getNext : function(uid, current)
	{
		var api = this.api[uid];
		var selector = $(api.getConf().selector.selector);
		var currentIndex = selector.index(current);
		
		var nexts = selector.filter(':gt(' + currentIndex + ')').filter(':[href!="' + current.attr('href') + '"]');
		var next = nexts.first();
		
		return next;
	}
};

FES.UI.Dropdown =
{
	mouseOver : false,
	
	setup : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		
		selector = $(selector);
		selector.css("display", "block");
		//selector.css("visibility", "hidden");

		var wrapper = $('<div class="_wrapper"></div>');
		var labelClass = "w-ui-dropdown-label";
		
		var label;
		var height, labelHeight;
		
		//$(window).load(function(e) // FF fix
		//{
			wrapper
				.addClass("w-ui-dropdown")
				.css("overflow", "hidden")
				.css("z-index", "999")
				.html(selector.html())
			;
	
			selector.html(wrapper);
	
			label = wrapper.children("*:first-child");
			label.addClass(labelClass);
			label.css("cursor", "pointer");
			
			height = selector.height();
			labelHeight = label.outerHeight();
			
			wrapper.height(labelHeight);
			wrapper.css("position", "absolute");
			//wrapper.css("z-index", "1000");
			
			//
			var padding = selector.css("padding-top") + " " + selector.css("padding-right") + " " + selector.css("padding-bottom") + " " + selector.css("padding-left");
			
			var borderTop = selector.css("border-top-width") + " " + selector.css("border-top-style") + " " + selector.css("border-top-color");
			var borderRight = selector.css("border-right-width") + " " + selector.css("border-right-style") + " " + selector.css("border-right-color");
			var borderBottom = selector.css("border-bottom-width") + " " + selector.css("border-bottom-style") + " " + selector.css("border-bottom-color");
			var borderLeft = selector.css("border-left-width") + " " + selector.css("border-left-style") + " " + selector.css("border-left-color");
			var background = selector.css("background-position") != null ? selector.css("background-position") : selector.css("background-position-x") + " " + selector.css("background-position-y");
			background = selector.css("background-color") + " " + selector.css("background-image") + " " + selector.css("background-repeat") + " " + background;
			
			selector.css("padding", "0");
			selector.css("border", "0 none");
			
			wrapper.css("padding", padding);
			wrapper.css("border-top", borderTop);
			wrapper.css("border-right", borderRight);
			wrapper.css("border-bottom", borderBottom);
			wrapper.css("border-left", borderLeft);
			wrapper.css("background", background);
			
			selector.css("visibility", "visible");
		//});
		
		selector.hover(
			function()
			{
				FES.UI.Dropdown.mouseOver = true;
			},
			function()
			{
				FES.UI.Dropdown.mouseOver = false;
			}
		);

		$("body").mouseup(function(e)
		{
			if (FES.UI.Dropdown.mouseOver)
			{
				var isTitle = $(e.target).is("." + labelClass);
				if (wrapper.height() < height)
				{
					wrapper.animate({height: height});
				}
				else if (isTitle)
				{
					wrapper.animate({height: labelHeight});
				}
			}
			else
			{
				if (wrapper.height() > labelHeight)
				{
					wrapper.animate({height: labelHeight});
				}
			}
		});
		
		return selector;
	}
};

FES.UI.Watermark =
{
	setup : function(selector, conf)
	{
		selector = $(selector);
		
		conf = (conf != null) ? conf : {};
		conf.watermark =  (conf.watermark != null) ? conf.watermark : selector.val();
		
		selector.focus(function(e)
		{
			var value = $(this).val();
			if (value == conf.watermark)
			{
				$(this).val("");
			}
		});

		selector.blur(function(e)
		{
			var value = $(this).val();
			if (value == "")
			{
				$(this).val(conf.watermark);
			}
		});
	}
}

FES.UI.Upload =
{
	Constants : 
	{
		NO_FILE : "None"
	},
	
	Messages :
	{
		ERROR__INVALID_TYPE : "Error: Invalid file type.",
		ERROR__FILE_NAME_MAX : "Error: File name is too long. Shorten file name and upload again.",
		UPLOADING : "Uploading... please wait."
	}
};

/**
 * @note: Legacy code
 */
FES.UI.Message =
{
	show : function(selector, message, conf)
	{
		if (typeof(message) == "object")
		{
			conf = message;
			message = selector;
		}
		conf = (conf != null) ? conf : {};
		conf.type = (conf.type != null) ? conf.type : "default";
		conf.type = (conf.location == null) ? conf.type : "overlay"; 

		var e = $(selector);
		if (conf.type == "default")
		{
			conf.appendCssClass = (conf.appendCssClass != null) ? conf.appendCssClass : true;
			conf.cssClass = (conf.cssClass != null) ? conf.cssClass : null;

			if (!conf.appendCssClass)
			{
				e.removeClass();
			}

			e.hide();
			if (conf.cssClass != null)
			{
				e.addClass(conf.cssClass);
			}
			e.fadeIn("slow").html(message)
			return;
		}
		else if (conf.type == "overlay" && false) // TODO: Beta: Do not use
		{
			/*
			FesWebApp.Libraries.load(FesWebApp.Libraries.Overlay, function()
			{
				var overlay = $("#_overlay");
				if (overlay.length == 0)
				{
					overlay = '<div id="_overlay" class="c_message__overlay"></div>' ;
					$("body").prepend(overlay);
				}
				overlay = $("#_overlay").html(message);
				overlay.overlay(
				{
					absolute: true,
					top: 0,
					api: true
				}).load();
			});
			return;
			*/
		}
	
	}
};

FES.Widgets.YorkSearch =
{
	watermark : "",
	
	setup : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		conf.selector = $(selector);
		conf.watermark = (conf.watermark != null) ? conf.watermark : null;
		
		var query = conf.selector.children("input[name='q']");
		
		// config: watermark
		conf.watermark = (conf.watermark != null) ? conf.watermark : query.val();
		FES.Widgets.YorkSearch.watermark = conf.watermark;
		
		//		
		conf.selector.submit(function()
		{
			var query = $(this).children("input[name='q']");
			var q = $.trim(query.val());
			query.val(q);
			
			if (query.val() == FES.Widgets.YorkSearch.watermark)
			{
				return false;
			}
		});
		
		query
			.focus(function()
			 {
				var $this = $(this);
				if ($this.val() == FES.Widgets.YorkSearch.watermark)
				{
					$this.val("");
				}
				 
			 })
			.blur(function()
			{
				var $this = $(this);
				if ($this.val() == "")
				{
					$this.val(FES.Widgets.YorkSearch.watermark);
				}
			})
		;
		
		return conf.selector;
	}
};

FES.Widgets.QuickSearch =
{
	watermark : "",
	
	setup : function(selector, conf)
	{
		conf = (conf != null) ? conf : {};
		conf.selector = $(selector);
		conf.textWidth = (conf.textWidth != null) ? conf.textWidth : 170;
		conf.watermark = (conf.watermark != null) ? conf.watermark : null;
		
		var query = conf.selector.children("input[name='q']");
		
		// config: watermark
		conf.watermark = (conf.watermark != null) ? conf.watermark : query.val();
		FES.Widgets.QuickSearch.watermark = conf.watermark;
		
		//
		conf.selector.submit(function()
		{
			var query = $(this).children("input[name='q']");
			var q = $.trim(query.val());
			query.val(q);
			
			if (query.val() == "")
			{
				return false;
			}
		});
		
		query
			.click(function(e)
			{
				var $this = $(this);
				if ($this.val() == FES.Widgets.QuickSearch.watermark)
				{
					$this.val("");
				}
				
				var x = e.pageX - $this.offset().left;
				if (x > conf.textWidth)
				{
					$this.parent("form").submit();
					return false;
				}
			})
			.mousemove(function(e)
			{
				var $this = $(this);
				var x = e.pageX - $this.offset().left;
				if (x > conf.textWidth)
				{
					$this.css("cursor", "pointer");
				}
				else
				{
					$this.css("cursor", "");
				}
			})
			.blur(function()
			{
				var $this = $(this);
				if ($this.val() == "")
				{
					$this.val(FES.Widgets.QuickSearch.watermark);
				}
			})
		;
		
		return conf.selector;
	}
};

FES.Widgets.Breadcrumbs =
{
	setup : function(selector, conf)
	{
		selector = $(selector);
		conf = (conf != null) ? conf : {};
		conf.structure = (conf.structure != null) ? $(conf.structure) : null;
		conf.separator = (conf.separator != null) ? conf.separator : " &rsaquo; ";
		conf.map = (conf.map != null) ? conf.map : {};
	
		var breadcrumbs = [];
		var path = window.location.pathname + window.location.search;
		
		var urls;
		var calcPriority = 0, priority = 0;
		var cls = null;
		var EXACT_MATCH = 1000;
		for (var nCls in conf.map)
		{
			// @note: improve performance
			
			urls = conf.map[nCls];
			for (var i in urls)
			{
				if (urls[i].match("\\.\\*") == null) // match exact path
				{
					if (urls[i] == path)
					{
						priority = EXACT_MATCH; // set to highest priority
						cls = nCls;
						break;
					}
				}
				else
				{
					calcPriority = FES.Widgets.Breadcrumbs._calculatePriority(path, urls[i]);
					if (calcPriority > priority)
					{
						priority = calcPriority;
						cls = nCls;
					}
				}
			}
			
			if (priority == EXACT_MATCH)
			{
				break;
			}
		}

		if (cls != null)
		{
			var classTokens = cls.split(" ");
			var item = "";
			var crumb, label, url;
			for (var i = 0; i < classTokens.length; i++)
			{
				if (i > 0)
				{
					item += " > ul > ";
				}
				item += classTokens[i];
				
				crumb = conf.structure.find(item).contents().first();
				crumb = crumb.is("a") ? crumb.clone().wrap("<div>").parent().html() : crumb.text();
				breadcrumbs.push(crumb);
			}
		}

		selector.html(breadcrumbs.join(conf.separator));
	},
	
	_calculatePriority : function(path, match)
	{
		var priority = 0;
		var isMatchAll = false;
		var pathTokens = path.split("/");
		var matchTokens = match.split("/");
		
		var length = (pathTokens.length < matchTokens.length) ? pathTokens.length : matchTokens.length;
		for (var i = 0; i < length; i++)
		{
			if (i == (matchTokens.length-1) && matchTokens[i] == ".*")
			{
				isMatchAll = true;
			}

			if (isMatchAll || pathTokens[i] == matchTokens[i])
			{
				priority++;
			}
			else
			{
				break;
			}
		}

		return priority;
	}
};

FES.Widgets.Navigation =
{
	setup : function(selector, conf)
	{
		selector = $(selector);
		conf = (conf != null) ? conf : {};
		conf.map = (conf.map != null) ? conf.map : {};
		
		var path = window.location.pathname + window.location.search;
		
		var uris;
		var calcPriority = 0, priority = 0;
		var cls = null;
		var EXACT_MATCH = 1000;
		for (var nCls in conf.map)
		{
			// @note: improve performance
			
			uris = conf.map[nCls];
			for (var i in uris)
			{
				if (uris[i].match("\\.\\*") == null) // match exact path
				{
					if (uris[i] == path)
					{
						priority = EXACT_MATCH; // set to highest priority
						cls = nCls;
						break;
					}
				}
				else
				{
					calcPriority = FES.Widgets.Breadcrumbs._calculatePriority(path, uris[i]);
					if (calcPriority > priority)
					{
						priority = calcPriority;
						cls = nCls;
					}
				}
			}
			
			if (priority == EXACT_MATCH)
			{
				break;
			}
		}

		if (cls != null)
		{
			var item = selector.find(cls);
			item
				.addClass("w-active")
				.children("ul").addClass("w-active")
				.end()
				.parents("ul:hidden").addClass("w-active")
				.closest("li").addClass("w-active")
			;
		}
	}
};

FES.Widgets.SectionTitle =
{
	setup : function(selector, conf)
	{
		selector = $(selector);
		conf = (conf != null) ? conf : {};
		conf.map = (conf.map != null) ? conf.map : {};
		
		var path = window.location.pathname + window.location.search;

		var uris;
		var calcPriority = 0, priority = 0;
		var title = "";
		var EXACT_MATCH = 1000;
		for (var nTitle in conf.map)
		{
			// @note: improve performance
			
			uris = conf.map[nTitle].uris;
			for (var i in uris)
			{
				if (uris[i].match("\\.\\*") == null) // match exact path
				{
					if (uris[i] == path)
					{
						priority = EXACT_MATCH; // set to highest priority
						title = nTitle;
						break;
					}
				}
				else
				{
					calcPriority = FES.Widgets.Breadcrumbs._calculatePriority(path, uris[i]);
					if (calcPriority > priority)
					{
						priority = calcPriority;
						title = nTitle;
					}
				}
			}
			
			if (priority == EXACT_MATCH)
			{
				break;
			}
		}
		
		var mapped = conf.map[title];
		if (mapped.url != null)
		{
			title = '<a href="' + mapped.url + '">' + title + '</a>';
		}
		var h1 = $(selector).find(".arc h1");
		h1.html(title);
		if (h1.height() > 30)
		{
			h1.css("padding-top", "25px");
		}

		if (mapped.banner != null)
		{
			$(selector).css("background-image", 'url("' +  mapped.banner + '")');
		}
	}
};

FES.Widgets.Gallery =
{
	setup : function(selector, conf)
	{
		selector = $(selector);
		conf = (conf != null) ? conf : {};
		conf.dataSource = (conf.dataSource != null) ? conf.dataSource : null;
		conf.qs = (conf.qs != null) ? conf.qs : false;
		conf.heightParam = (conf.heightParam != null) ? conf.heightParam : 'h';
		conf.height = (conf.height != null) ? conf.height : 690;
		conf.lightboxParam = (conf.lightboxParam != null) ? conf.lightboxParam : 'lb';
		conf.lightbox = (conf.lightbox != null) ? conf.lightbox : true;

		if (conf.dataSource.length > 0)
		{
			if (conf.qs)
			{
				var qs = FES.Url.queryString();
				if (qs.exists("qs") && qs.exists(qs["qs"]))
				{
					conf.height = qs.exists(conf.heightParam) ? parseInt(qs[conf.heightParam]) : conf.height;
					conf.height = isNaN(conf.height) ? 690 : conf.height;
					conf.lightbox = (!qs.exists(conf.lightboxParam) || qs[conf.lightboxParam] == "1") ? true : false;
				}
			}

			selector.galleria(
			{
				dataSource: conf.dataSource,
				height: conf.height,
				_toggleInfo: false,
				transition: "fade",
				lightbox: conf.lightbox
			});
		}
		else
		{
			selector.html('<p class="c-small">Media not available.</p>');
		}
	}
};
