/************** GLOBAL VARIABLES **************/

/**
 * Used by the "coverThis" JQuery extension (see below)
 */
var coverCount = 0;

/**
 * Standard options for a JQuery dialog.
 */
var dialogOpts = {
		resizable: false,
		draggable: true,
		modal: true,
		autoOpen: false,
		position: [40, 40]	};

/** 
 * This global variable stores the site's "full BASE url" - e.g. "http://www.foo.com"
 * It is used when injecting CSS files with an absolute URL to prevent problems in IE6 & IE7.
 * (see "orbisApp.components" below) 
 *
 * FIXME: this variable should be a member of the orbisApp object itself.
 */
var fullBaseURL = window.location.protocol + "//" + window.location.hostname;


/************** GLOBAL JQUERY DOC-READY BLOCK **************
 * This is a global "document ready" block that applies 
 * various global behaviours to the entire site.
 */
$(document).ready(function() {	
	orbisApp.hideSuccessMsg();
	orbisApp.renderNotePopups();
});


/************** GLOBAL OBJECT: orbisApp **************
 * "orbisApp" is a global object that holds various 
 * utility methods that are used throughout the site.
 */
var orbisApp = {

	/**
	 * "addComponent" function is called by the JSP to dynamically 
	 * inject a component from "this.components" in the the <head>
	 */
	addComponent : function(component) {
		var c = this.components[component];
		
		if (c)
		{
			if (c.loaded === false)
			{
				if(c.dependencies)
				{
					for(var i = 0; i < c.dependencies.length; i++)
					{
						this.addComponent(c.dependencies[i]);				
					}
				}			
	
				$("head").append(c.tag);			
				c.loaded = true;
			}
		}
		else
		{
			this.alertDialog("Error -> orbisApp.addComponent() -> Component '" + component + "' is undefined.", true);
		}				
	},

	/**
	 * This is the global map of all the available "components" that a JSP can choose from. 
	 */
	components : {
		
		jqueryAutocomplete : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.autocomplete-1.0.2/jquery.autocomplete.pack.js'></script>",
			dependencies : ["jqueryAutocomplete_css"],
			loaded : false
		},
		
		jqueryAutocomplete_css : {
			tag : "<link type='text/css' rel='Stylesheet' href='" + fullBaseURL + "/core/scripts/jquery/jquery.autocomplete-1.0.2/jquery.autocomplete.css' />",
			loaded : false
		},
		
		jqGrid : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.jqGrid-3.6.2/js/jquery.jqGrid.min.js'></script>",
			dependencies : ["jqGrid_css", "jqGrid_locale", "multiselect", "json"],
			loaded : false
		},
		
		jqGrid_css : {
			tag : "<link type='text/css' rel='stylesheet' href='" + fullBaseURL + "/core/scripts/jquery/jquery.jqGrid-3.6.2/css/ui.jqgrid.css' />",
			loaded : false
		},

		jqGrid_locale : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.jqGrid-3.6.2/js/i18n/grid.locale-en.js'></script>",
			loaded : false
		},
		
		multiselect : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.multiselect-1.7/js/ui.multiselect.js'></script>",
			dependencies : ["multiselect_css"],
			loaded : false
		},
		
		multiselect_css : {
			tag : "<link type='text/css' rel='stylesheet' href='" + fullBaseURL + "/core/scripts/jquery/jquery.multiselect-1.7/css/ui.multiselect.css' />",
			loaded : false
		},
		
		json : {
			tag : "<script type='text/javascript' src='/core/scripts/json/json2.js'></script>",
			loaded : false
		},

		blockUI : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.blockUI-2.31/jquery.blockUI.js'></script>",
			loaded : false
		},
		
		form : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.form-2.43/jquery.form.js'></script>",
			loaded : false
		},
		
		calendar : {
			tag : "<script type='text/javascript' src='/core/scripts/calendar/calendar.js'></script>",
			dependencies : ["calendar_css", "calendar_setup", "calendar_en"],
			loaded : false
		},

		calendar_css : {
			tag : "<link type='text/css' rel='stylesheet' href='" + fullBaseURL + "/core/scripts/calendar/calendar-blue.css' />",
			loaded : false
		},
		
		calendar_setup : {
			tag : "<script type='text/javascript' src='/core/scripts/calendar/calendar-setup.js'></script>",
			loaded : false
		},
		
		calendar_en : {
			tag : "<script type='text/javascript' src='/core/scripts/calendar/lang/calendar-en.js'></script>",
			loaded : false
		},
		
		jqueryValidate : {
			tag : "<script type='text/javascript' src='/core/scripts/jquery/jquery.validate-1.5.1/jquery.validate.js'></script>",
			loaded : false
		},
		
		tooltip : {
			tag : "<script type='text/javascript' src='/core/scripts/tooltip/form-field-tooltip.js'></script>",
			dependencies : ["tooltipCorners", "tooltip_css"],
			loaded : false
		},
		
		tooltipCorners : {
			tag : "<script type='text/javascript' src='/core/scripts/tooltip/rounded-corners.js'></script>",
			loaded : false
		},
		
		tooltip_css : {
			tag : "<link type='text/css' rel='stylesheet' href='" + fullBaseURL + "/core/css/tooltip/form-field-tooltip.css' />",
			loaded : false
		}
		
		
	},
	
	/** 
	 * "hideSuccessMsg" automatically hides "successMsgFadeout" div's after 5 seconds
	 */
	hideSuccessMsg : function() {
		$(".successMsgFadeout:visible").stepDelay(5000, function() {$(this).fadeOut("slow")});
	},
	
	/** 
	 * Note system
	 * Create a span with class="notePopup" around the note text where you want the link to be
	 * set the span style="display:none;" <- This fixes a minor glitch where the popup text would display before being replaced by 'Note'
	 * To edit the link style use the class ".noteLink"
	 */
	renderNotePopups : function() {
		var noteDialogNum = 0;
		$("span.notePopup").each(function(){
			var noteText = $(this).html();
			var dialogId = "note"+noteDialogNum;
			var thisDialog = "div[aria-labelledby='ui-dialog-title-" + dialogId + "']";
			var setTitle = "<img src='/core/images/iconHelp.gif' alt='Click here for more information' style='width: 14px; height: 14px; margin-top: 3px; margin-left: 5px;' /> " + $(this).attr("noteTitle"); 
			$("body").append("<div class='notePopupClass' id='"+dialogId+"' style='display:none; width: 100%; height: 100%;' title=' '><div id='noteText'><div style='text-align: center; margin-bottom: 10px;'><img src='core/images/iconHelp.gif' /></div>"+noteText+"</div></div>");		
			orbisApp.setUpRegularDialog("#"+dialogId, {}, {width: 300, title:setTitle});
			//$(thisDialog).find('div.ui-widget-header').css({'background':'#B90101'});
			$(this).html("<a href='#' class='noteLink' onClick=\"$('#"+dialogId+"').dialog('open'); this.centerDiv('#"+dialogId+"', 'noteText'); return false;\"><img src='/core/images/iconHelp.gif' alt='Click here for more information' style='width: 14px; height: 14px; margin-top: 3px; margin-left: 5px;' /></a>");
			$(this).css({display:"inline"});
			$("#noteText").css({"text-align":"left !important", "font-size":11, "line-height":1});		
					
			noteDialogNum++;
		});		
	},

	/**
	 * "orbisApp.checkAjaxResponse" is a utility method that can be used for 
	 * checking an ajax response for error conditions.  If such a 
	 * condition is detected then this method will perform the 
	 * appropriate UI behaviour, and also return FALSE which the 
	 * caller can use to stop normal application flow.
	 *
	 * @param xmlHttpRequest<XmlHttpRequest> - the ajax-object used to perform the ajax request.
	 * @return <boolean> - FALSE if there was a problem, otherwise TRUE
	 */
	checkAjaxResponse : function (xmlHttpRequest)
	{
		var happy = true;
		
		if (!this.isEmpty(xmlHttpRequest))
		{
			if (!this.isEmpty(xmlHttpRequest.getResponseHeader("notLoggedIn")))
			{
				happy = false;
			    window.parent.location = "/notLoggedIn.htm";
			}
			else if (!this.isEmpty(xmlHttpRequest.getResponseHeader("portalError")))
			{
				happy = false;
			    window.parent.location = "/portalError.htm";
			}
			else if (this.isEmpty(xmlHttpRequest.status))
			{
				happy = false;
				this.alertDialog("There has been a communication error with the server(1).  Please try again.", true);			
			}
			else if (xmlHttpRequest.status != 200)
			{
				happy = false;
				this.alertDialog("There has been a communication error with the server(2).  Please try again.", true);			
			}
		}
		else
		{
			happy = false;
			this.alertDialog("There has been a communication error with the server(3).  Please try again.", true);			
		}
		
		return happy;
	},
	
	/**
	 * Returns TRUE if obj is "empty", otherwise returns FALSE
	 */
	isEmpty : function (obj)
	{
		return obj == undefined || obj == null || obj == "";
	},
	
	/**
	 * Returns the specified "str" without the left or right
	 * "chars".
	 */
	trim : function (str, chars) {
		return this.ltrim(this.rtrim(str, chars), chars);
	},
	 
	/**
	 * Returns the specified "str" without the left "chars".
	 */
	ltrim : function (str, chars) {
		chars = chars || "\\s";
		return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
	},
	 
	/**
	 * Returns the specified "str" without the right "chars".
	 */
	rtrim : function (str, chars) {
		chars = chars || "\\s";
		return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
	},
	
	
	/*********** DATEPICKER STUFF **************/
	
	/**
	 * "defaultDatePickerOpts" is used to set the standard options
	 * for a JQuery datepicker. 
	 *
	 * example: $("#fooInput").datepicker(orbisApp.defaultDatePickerOpts);
	 */
	defaultDatePickerOpts : {
		buttonImage: "/core/images/icons/calendar-16x16.png",
		buttonImageOnly: true,
		buttonText: "",
		changeMonth: true, 
		changeYear: true,
		dateFormat: "mm/dd/yy",
		showAnim: "fadeIn",
		showOn: "both"},
	
	/*********** DIALOG STUFF **************/
	
	numOfDialogs : 0,
	
	defaultDialogOpts : {
		resizable: false,
		draggable: true,
		modal: true,
		autoOpen: false,
		position: [40, 40],
		width: 600   },
			
	/**
	 * A "private" function use for supporting dialog functionality.
	 */
	resetDialog : function (dialogDiv, options)
	{
		var dName;
		if (dialogDiv.substr(0, 1) == "#")
		{
			dName = $(dialogDiv).attr("id");
		}
		else if (dialogDiv.substr(0, 1) == ".")
		{
			dName = $(dialogDiv).attr("class");
		}
		else 
		{
			dName = dialogDiv;
		}
	
		var showTitle = $(dialogDiv).attr("title") != undefined && $(dialogDiv).attr("title") != null && $(dialogDiv).attr("title") != "";
	
		if (options)
		{
			$(dialogDiv).dialog(options);
		}
		else
		{
			$(dialogDiv).dialog(this.defaultDialogOpts);
		}	
		
		var thisDialog = $("div[aria-labelledby='ui-dialog-title-" + dName + "']");
	
		if (!showTitle)
		{		
			$(thisDialog).find(".ui-dialog-titlebar").css({"display" : "none"});
		}
		else
		{
			$(thisDialog).find(".ui-dialog-titlebar").css({"display" : "block"});
		}
	
		$(dialogDiv).dialog('option', 'open', function() { $(this).css({'max-height': ($(window).height()-160), 'overflow-y':'auto'}); }); 	
		$(dialogDiv).dialog('option', 'buttons', {"Close": function(){ $(dialogDiv).dialog("close");}});		
		$(dialogDiv).dialog('option', 'closeOnEscape', true );			
	},
	
	/**
	 * A utiltiy for turning any <div> into a standard dialog.  Once 
	 * this method is called, the target div will be turned into a dialog
	 * but you are still required to call $(divClassOrId).dialog("open");
	 * and $(divClassOrId).dialog("close"); to open and close the dialog
	 * respectively.
	 * 
	 * @param divClassOrId - a JQuery selector to your target div
	 * @param buttons - a JQuery dialog button object (for custom buttons)
	 * @param opts - a JQuery dialog options object (for custom dialog behaviour)
	 */
	setUpRegularDialog : function (divClassOrId, buttons, opts)
	{		
		this.resetDialog(divClassOrId, this.extendOptions(opts));			 	
		
		if(buttons && buttons != null)
		{
			$(divClassOrId).dialog('option', 'buttons', buttons);
		}	
	},
	
	/**
	 * A "private" function use for supporting dialog functionality.
	 */
	extendOptions : function (options)
	{
		if (options)
		{
			return $.extend(this.defaultDialogOpts, options);
		}
		return this.defaultDialogOpts;
	},
	
	/**
	 * A utility for showing a standard "confirmation dialog"
	 * 
	 * @param message<string> - the text to be displayed in the dialog
	 * @param callback<function> - the callback to be fired when "Ok" gets clicked.
	 */
	confirmDialog : function (message, callback)
	{	
		var dName = this.createDialogDiv();
		$("#" + dName).attr("title", "Confirmation");
		var opts = {"close": function() {$("#" + dName).dialog("destroy");}};	
		this.resetDialog("#" + dName, this.extendOptions(opts));
		var thisDialog = $("div[aria-labelledby='ui-dialog-title-" + dName + "']");
		
		var r;
		
		$("#" + dName).dialog('option', 'width', '');
		$("#" + dName).dialog('option', 'buttons', '');
		$("#" + dName).dialog('option', 'buttons', {
									"OK": function(){ 
										$("#" + dName).dialog("close"); 									
										if (callback)
										{
											callback();
										}
									},
									"Cancel": function(){
										$("#" + dName).dialog("close"); 
										}																
									});
		
		$("#" + dName).html("<div id='centerThis'>" + message + "</div>");		
		$("#" + dName).dialog("open");					
		$(thisDialog).find(".ui-dialog-buttonpane button").css({"float":"none"}); //these 3 lines will hack the default UI settings and make the buttons center
		$(thisDialog).find(".ui-dialog-buttonpane").css({"text-align":"center"});
		$(thisDialog).find(".ui-dialog-buttonpane").css({"padding":"0px"});	
		$(thisDialog).find(".ui-dialog-title").css({"width":"100%", "text-align":"center"});	
			
		this.centerDiv("#" + dName, "#centerThis");		
		
		return "#" + dName;
	},
	
	/**
	 * A utility for showing a standard "alert dialog"
	 * 
	 * @param message<string> - the text to be displayed in the dialog
	 * @param error<boolean> - when TRUE, the dialog will be styled as an "error alert".
	 */
	alertDialog : function (message, error)
	{	
		var dName = this.createDialogDiv();
		$("#" + dName).attr("title", "Alert");
		var opts = {"close": function() {$("#" + dName).dialog("destroy");}};	
		this.resetDialog("#" + dName, this.extendOptions(opts));
		var thisDialog = $("div[aria-labelledby='ui-dialog-title-" + dName + "']");
		
		var r;
			
		$("#" + dName).dialog('option', 'width', '');
		$("#" + dName).dialog('option', 'buttons', '');
		$("#" + dName).dialog('option', 'buttons', {
									"OK": function(){ 
										$("#" + dName).dialog("close"); 									
										}															
									});
		$("#" + dName).html("<div id='centerThis'>" + message + "</div>");		
		$("#" + dName).dialog("open");
		
		if(error)
		{
			$("#" + dName).addClass("ui-state-error");
			$(thisDialog).find(".ui-dialog-title").css({"color":"#FFFFFF"});		
			$(thisDialog).find(".ui-dialog-titlebar").css({"background":"#B90101"});
		}
									
		$(thisDialog).find(".ui-dialog-title").css({"width":"100%", "text-align":"center"});
		$(thisDialog).find(".ui-dialog-title").css({"display" : "block", "padding-left":"0px", "padding-right":"0px"});//display title bar	
		$(thisDialog).find(".ui-dialog-buttonpane button").css({"float":"none"}); //these 2 lines will hack the default UI settings and make the buttons center
		$(thisDialog).find(".ui-dialog-buttonpane").css({"text-align":"center", "padding":"0px"});
		
		this.centerDiv("#" + dName, "#centerThis");
		
		return "#" + dName;		
	},
	
	/**
	 * A utility for showing a standard "message dialog"
	 * NOTE: you must call "closeTempMessageDialog" to close it
	 * 
	 * @param text<string> - the message to display in the pop-up
	 * @param waitBar<boolean> - will show a "loading graphic" when TRUE
	 * @returns <string> - the JQuery selector of the pop-up (to be passed in the "closeTempMessageDialog" call)  
	 */
	openTempMessageDialog : function (text, waitBar)
	{		
		var dName = this.createDialogDiv();
		var opts = {"close": function() {$("#" + dName).dialog("destroy");}};	
		this.resetDialog("#" + dName, this.extendOptions(opts));
		
		if (waitBar)
		{
			 text += " <br /> <img src='/core/images/loading2.gif' />";
		}
		
		$("#" + dName).html("<div class='textToCenter-" + dName + "'>" + text + "</div>");
		$("#" + dName).dialog("option", "buttons", "");
		$("#" + dName).dialog('option', 'width', "");	
		$("#" + dName).dialog('option', 'closeOnEscape', false );	
		$("#" + dName).dialog("open");
		this.centerDiv("#" + dName, ".textToCenter-" + dName);
		
		return "#" + dName;
	},
	
	/**
	 * A utility for closing a standard "message dialog"
	 *
	 * @param dName<string> - the JQuery selector that should be used for closing the "tempMessageDialog"
	 */
	closeTempMessageDialog : function (dName)
	{
		$(dName).dialog("close");	
	},
	
	/**
	 * A utility for showing a standard "message dialog" which will
	 * automatically close after the specified "mili" seconds.
	 * 
	 * @param text<string> - the message to display in the pop-up
	 * @param mili<int> - this lengh of time (in miliseconds) before the pop-up closes
	 * @param callback<function> - the callback that will be fired after the pop-up closes
	 */
	timedMessageDialog : function (text, mili, callback)
	{
		var toClose = this.openTempMessageDialog(text);
		$(toClose).stepDelay(mili, function() {orbisApp.closeTempMessageDialog(toClose);});
		if (callback) { 
			$("html").stepDelay(mili, function() {callback();}); 
		}	
	},
	
	/**
	 * A "private" function use for supporting dialog functionality.
	 */
	centerDiv : function (nameOfContainer, nameOfChild)
	{
		cHeight = $(nameOfContainer).height();
		cWidth = $(nameOfContainer).width();
		
		tHeight = $(nameOfContainer + " " + nameOfChild).height();
		tWidth = $(nameOfContainer + " " + nameOfChild).width();
		
		$(nameOfContainer + " " + nameOfChild).css({"text-align" : "center"});	
		$(nameOfContainer + " " + nameOfChild).css({"margin-top" : ((cHeight/2) - (tHeight/2))});
		$(nameOfContainer + " " + nameOfChild).css({"margin-left" : ((cWidth/2) - (tWidth/2))});
	},
	
	/**
	 * A "private" function use for supporting dialog functionality.
	 */
	createDialogDiv : function ()
	{
		this.numOfDialogs++;
		var dName = "dialog_" + this.numOfDialogs;
		$("body").append("<div id='" + dName + "'></div>");
		return dName;
	}
	
};

/************** GLOBAL JQUERY EXTENSIONS **************/

$.fn.stepDelay = function(time, callback){
	$.fx.step.delay = function(){};
	return this.animate({delay:1}, time, callback); //the callback is the function that will wait for the delay to run before it executes
}

$.fn.coverThis = function(){	
	if($(this).find("#" + $(this).attr("coverId")).length == 0)
	{
		$(this).attr("coverId", "cover" + coverCount);
		if($(this).css("position") == "static")
		{		
			$(this).css({"position":"relative"});
		}
		$(this).prepend("<div class='coverStyles' id='cover" + coverCount + "' style='margin-left: -"+$(this).css("padding-left")+"; margin-top: -"+$(this).css("padding-top")+";'></div>");		
		coverCount++;
	}
}

$.fn.uncoverThis = function(){	
	$(this).find("#" + $(this).attr("coverId")).remove();
	$(this).removeAttr("coverId");
}

$.fn.groupCheckboxes = function(selectAll){	
	
	var checkAll = false;
	var groupOfChkBxs = this.selector;
	var lastChecked = null;
	
	checkAll = $(groupOfChkBxs + ":checked").length == $(groupOfChkBxs).length;		
	$(selectAll).attr('checked', checkAll);
	
	if(selectAll)
	{			
		$(selectAll).click(function() {			
			checkAll = $(selectAll).attr("checked");				
			$(groupOfChkBxs).attr("checked", checkAll);				
		});
	}	
			
	$(groupOfChkBxs).click(function(event) {											
		if(!lastChecked) 
		{					
        	lastChecked = this;	              
        }

        if(event.shiftKey) 
        {        	
            var start = $(groupOfChkBxs).index(this);
            var end = $(groupOfChkBxs).index(lastChecked);                                                        
            $(groupOfChkBxs).slice(Math.min(start,end), Math.max(start,end) + 1).attr("checked", lastChecked.checked);
        }
              
        lastChecked = this;                
        
		checkAll = $(groupOfChkBxs + ":checked").length == $(groupOfChkBxs).length;		
		$(selectAll).attr('checked', checkAll);
	});
}

/************** GLOBAL "ROLL-OVER" FUNCTIONS **************/

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_nbGroup(event, grpName) { //v6.0
  var i,img,nbArr,args=MM_nbGroup.arguments;
  if (event == "init" && args.length > 2) {
    if ((img = MM_findObj(args[2])) != null && !img.MM_init) {
      img.MM_init = true; img.MM_up = args[3]; img.MM_dn = img.src;
      if ((nbArr = document[grpName]) == null) nbArr = document[grpName] = new Array();
      nbArr[nbArr.length] = img;
      for (i=4; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) {
        if (!img.MM_up) img.MM_up = img.src;
        img.src = img.MM_dn = args[i+1];
        nbArr[nbArr.length] = img;
    } }
  } else if (event == "over") {
    document.MM_nbOver = nbArr = new Array();
    for (i=1; i < args.length-1; i+=3) if ((img = MM_findObj(args[i])) != null) {
      if (!img.MM_up) img.MM_up = img.src;
      img.src = (img.MM_dn && args[i+2]) ? args[i+2] : ((args[i+1])? args[i+1] : img.MM_up);
      nbArr[nbArr.length] = img;
    }
  } else if (event == "out" ) {
    for (i=0; i < document.MM_nbOver.length; i++) {
      img = document.MM_nbOver[i]; img.src = (img.MM_dn) ? img.MM_dn : img.MM_up; }
  } else if (event == "down") {
    nbArr = document[grpName];
    if (nbArr)
      for (i=0; i < nbArr.length; i++) { img=nbArr[i]; img.src = img.MM_up; img.MM_dn = 0; }
    document[grpName] = nbArr = new Array();
    for (i=2; i < args.length-1; i+=2) if ((img = MM_findObj(args[i])) != null) {
      if (!img.MM_up) img.MM_up = img.src;
      img.src = img.MM_dn = (args[i+1])? args[i+1] : img.MM_up;
      nbArr[nbArr.length] = img;
  } }
}

