//JavaScript Document

/*====================================================================
//NOTE: Requires jQuery 1.4.2 or greater and jQueryUI 1.8.1 or greater
======================================================================*/

var $j = jQuery.noConflict();
var psRTELoaded = false;
var psTableToGridLoaded = false;
var radioSliderLoaded = false;

//psDateWidget was here...
//This script loads external .js files if the dependent objects exist on a page
var __maxlength_count = 0;
var __maxlength_tracker = {};	// key = id, value = function to call when it has focus
var __maxlength_curFocus = null;
function handleTextAreaMaxLength(el, maxlen) {
	if (maxlen > 0) {
		// If the textarea does not have an id, give it one. We need the id to
		// track when the textarea gets focus.
		var textAreaId = el.attr("id");
		if (!textAreaId) {
			textAreaId = "__maxlength_textarea"+__maxlength_count;
			el.attr("id", textAreaId);
		}
		
		// Add in the display part
		var id = "__maxlength_count"+__maxlength_count;
		
		// See which message to use. If the field is < 1000 characters, don't even need to worry
		// about possibly exceeding the 4000B limit, so we'll just say n characters left instead of
		// about n left.
		var charsLeftKey = "psx.js.scripts.psbehaviors.n_characters_left";
		if (maxlen > 1000) charsLeftKey = "psx.js.scripts.psbehaviors.about_n_characters_left";
		
		el.after ("<p class='textareaCounter'>"+pss_text(charsLeftKey, ["<span id='"+id+"'>"+maxlen+"</span>"])+"</p>");
		__maxlength_tracker[textAreaId] = function () {
			var e2 = el.get(0);
			maxlength(e2, maxlen, id);
		};
		__maxlength_tracker[textAreaId]();		// Call it once to set the initial # characters
		
		// Finally, add on focus/blur events to keep track of which of these guys has focus
		el.focus (function () {
			__maxlength_curFocus = $j(this).attr("id");
		});
		el.blur (function () {
			if (__maxlength_curFocus == $j(this).attr("id")) {
				__maxlength_curFocus = null;
			}
		});
		__maxlength_count++;
	}
}

function jsLazyLoader(){
	// Deal with maxlength annotations. We'd like to just use the maxlength attribute,
	// but unfortunately struts2 doesn't let you pass that.
	if ( $j('textarea[class^="maxlength"]').length) {
		$j('textarea[class^="maxlength"]').each (function() {
			var el = $j(this);
			var classList = el.attr('class').split(/\s+/);
			var maxlen = 0;
			$j.each( classList, function(index, item){
			    maxlen = item.substr(9);
			});
			handleTextAreaMaxLength(el, maxlen);
		});
	}

	if ( $j('textarea[maxlength]').length) {
		$j('textarea[maxlength]').each (function() {
			var el = $j(this);
			handleTextAreaMaxLength(el, el.attr("maxlength"));
		});
	}

	// If there were any max length counter areas set up, set up a periodic length checker.
	if (__maxlength_count) {
		setInterval(function() {
			// Get the current focus id. This allows us to only do checking on the textarea
			// that currently has focus.
			if (__maxlength_curFocus && __maxlength_tracker[__maxlength_curFocus]) {
				__maxlength_tracker[__maxlength_curFocus]();
			}
		}, 250);
	}
	var pathname = 	window.location.pathname;
	var isSRPage = pathname.toLowerCase().indexOf("state") >= 0;
	if (!isSRPage) {
		//Parse data-validation JSON and handle for data types
		//It would be nice to lazy load this code, but getScript seems to be acting asynchronously 
		//and therefore preventing the loading of later scripts.
		$j('[data-validation]:not("[type=hidden]")').each(function() {
			var data = $j.parseJSON($j(this).attr("data-validation"));
			if (data.type != null) {
				if (data.type == "number") { //add number type-specific cases 
					$j(this).addClass("psNumWidget");
					if (data.minValue != null) {
						$j(this).attr("data-minvalue", data.minValue);
					} 
					if (data.maxValue != null) {
						$j(this).attr("data-maxvalue", data.maxValue);
					}
					if (data.isinteger != null) {
						if (data.isinteger == "true") {
							$j(this).attr("data-isinteger", "true");
						}
					}				
				} else if (data.type == "date") { //add date type-specific cases
					$j(this).addClass("psDateWidget");
					if (data.minValue != null){
						$j(this).attr("data-mindate", data.minValue);
					}
					if (data.maxValue != null) {
						$j(this).attr("data-maxdate", data.maxValue);
					}
				} 
				if (data.minlength != null) {
					$j(this).attr("minlength", data.minlength);
				} 
	
				if (data.maxlength != null) {
					$j(this).attr("maxlength", data.maxlength);
				}
				if (data.required == "true") { //add required flag
					$j(this).addClass("required");
				}
			}
		});
	
		//Loads required widget
		if( $j( 'input.required' ).length ){
			$j.getScript("/scripts/psRequired.js", function(){});
			$j('input.required').closest("form").addClass('validatedForm');
	
			// mark elements initially with unvalidated class, so we know what's been touched later
			$j('input.required').addClass('unvalidated').after('<em>*</em>');
		}
	
		//Loads numeric entry widget
		if( $j( 'input.psNumWidget' ).length ){
			$j.getScript("/scripts/psNumWidget.js", function(){});
			$j('input.psNumWidget').closest("form").addClass('validatedForm');
	
			// mark elements initially with unvalidated class, so we know what's been touched later
			$j('input.psNumWidget').addClass('unvalidated');
		}
		// Sprinkle submitOnce on all forms for double-click prevention
		$j('form:not(.noSubmitLoading)').addClass('submitOnce'); 

		// Existing submitOnceCond classes should be removed, as submitOnce will handle conditional events
		$j('form.submitOnceCond').removeClass('submitOnceCond');
		
	}
	//Loads calendar injection code file using jQuery getScript()
	if( $j( 'input.psDateWidget' ).length ){
		$j.getScript("/scripts/psDateWidget.js", function(){});
		$j.getScript("/scripts/psDateValidate.js", function(){});
		$j('input.psDateWidget').closest("form").addClass('validatedForm');

		// mark elements initially with unvalidated class, so we know what's been touched later
		$j('input.psDateWidget').addClass('unvalidated');
	}
	if( $j( 'input.psDateWidget.psDateHighlight' ).length ){
		$j.getScript("/scripts/psDateWidgetHighlight.js", function(){});	
	}
	
	// Forms that contain validated elements have validation functionality tacked onto it
	if ( $j('form.validatedForm').length ) {
			$j.getScript("/scripts/psFormValidate.js", function(){});
			$j('form.validatedForm').each(function(){
				// push the value into a different attribute - so the default onsubmit is not executed
				var onsubmitContents = $j(this).attr('onsubmit');
				$j(this).attr('data-onsubmit', onsubmitContents);
				$j(this).removeAttr('onsubmit');
	
				// if submitOnce, nuke class
				$j(this).removeClass('submitOnce');
		});
	}
	
	lazyLoadTableToGrid();
	if( $j('textarea.psRTE').length && !psRTELoaded) {
		$j.getScript("/scripts/markitup/jquery.markitup.js", function() {
			$j.getScript("/scripts/markitup/sets/html/set.js", function() {
				$j.getScript("/scripts/singleField_translation.js", function() {
				
				initPsRTE();		// instead of loading psRTE.js
				
				//Load style sheets for the html widget
				$j("head").append("<link>");
				skinsCSS = $j("head").children(":last");
				skinsCSS.attr({
				      rel:  "stylesheet",
				      type: "text/css",
				      href: "/scripts/markitup/skins/simple/style.css"
				    });
				$j("head").append("<link>");
				setCSS = $j("head").children(":last");
				setCSS.attr({
				      rel:  "stylesheet",
				      type: "text/css",
				      href: "/scripts/markitup/sets/html/style.css"
				    });
				
				psRTELoaded = true;
				});
			});
		});
	}
	
	//Loads psRadioDiv code file using jQuery getScript()
	if( $j( 'select[radioDivPre], input[type="checkbox"].radioDivPre, input[type="radio"].radioDivPre' ).length ){
		$j.getScript("/scripts/psRadioDiv.js", function(){});
	}

	//Loads the "inlineDiff" presentation
	if( $j( 'ul.inlineDiff' ).length ){
		$j.getScript("/scripts/diff.js", function(){});
		
		// There might be more than one on the page ... want to treat each one separately.
		$j( 'ul.inlineDiff' ).each (function() {
			var el = $j(this);
			var parts = el.find("li");
			
			// Right now, only know how to deal with it when there are two <li> elements
			if (parts.length == 2) {
				// Hide the original list
				el.hide();

				// See if any title is desired
				var insTitleHTML, delTitleHTML;
				var delTitle = $j(parts[0]).attr("title");
				if (delTitle) delTitleHTML = pss_text("psx.js.scripts.psbehaviors.deleted_xx", [delTitle]); else delTitleHTML = pss_text("psx.js.scripts.psbehaviors.deleted");
				var insTitle = $j(parts[1]).attr("title");
				if (insTitle) insTitleHTML = pss_text("psx.js.scripts.psbehaviors.added_xx", [insTitle]); else insTitleHTML = pss_text("psx.js.scripts.psbehaviors.added");
				
				wDiffHtmlDeleteStart = '<del title="'+delTitleHTML+'">';
				wDiffHtmlDeleteEnd   = '</del>';
				wDiffHtmlInsertStart = '<ins title="'+insTitleHTML+'">';
				wDiffHtmlInsertEnd   = '</ins>';

				// Create new element
				var oldText = $j(parts[0]).html();
				var newText = $j(parts[1]).html();
				var newElHTML = "<p>"+WDiffString(oldText,newText)+"</p>";
				el.after($j(newElHTML));
			}
		});

	}
	
	 if ($j('input[type="checkbox"].selectAllFor').length) {
		  $j('input[type="checkbox"].selectAllFor').each (function (index, el) {
		    var that = $j(el);
		    
		    // Get the target off the checkbox - that target should have a bunch of
		    // checkboxes under it.
		    var target = that.attr('data-target');
		    if (target) {
		      that.click (function () {
		        $j(target).find(':checkbox').attr('checked', this.checked);
		      });
			}

			// Now, if it also has a startSelected class, start the subs all checked.	
			if (that.hasClass("startSelected")) {
				that.attr('checked',true);
				$j(target).find(':checkbox').attr('checked', true);
			}
		  });
		}

		if( $j( 'button.next, a.button.next' ).length ){
			dropPointySubElements($j( 'button.next, a.button.next' )).append("<em>&nbsp;</em>");
		}
		if( $j( 'button.prev, a.button.prev' ).length ){
			dropPointySubElements($j( 'button.prev, a.button.prev' )).prepend("<em>&nbsp;</em>");
		}

	/*if( $j( '.tableToGrid' ).length ){
		$j.getScript("/scripts/jqgrid-i18n/grid.locale-en.js", function(){});
		$j.getScript("/scripts/jquery.jqGrid.min.js", function(){});
	}*/
}

function lazyLoadTableToGrid() {
	if($j( 'table.tableToGrid' ).length && !psTableToGridLoaded) {
		$j( '.tableToGrid' ).each(function (index, table) {
			$j(table).hide();
			var divElement = $j('<div class="tableToGridLoadingImage" style="height:100%; padding:100px;"><img src="/images/img/jquery/ui-anim_basic_16x16.gif" /> <strong> '+pss_text("psx.common.loading")+'</strong> </div></div>');
			$j(table).before(divElement);
		});
		
		
		$j.getScript("/scripts/psTableToGridWidget.js", function() {});
		psTableToGridLoaded = true;
	}
}

/**
 * Go through a jquery object that holds a list of elements and drop out the ones that
 * already have the <em>&nbsp;</em> required to make them pointy (aka the pointified ones).
 * This is to avoid double-pointy elements when psbehaviors.js is called again (as well as
 * avoiding them if the <em>&nbsp;</em> is manually put in the button).
 * @param element the jquery object, which should contain zero or more matching elements
 * @returns a new jquery object with the same elements except the ones that are already pointified
 */
function dropPointySubElements(element) {
	var ret = [];
	element.each(function (idx, el) {
		var jel = $j(el);
		var hadOne = false;
		jel.find("em").each(function (idx2, el2) {
			var jel2 = $j(el2);
			if (jel2.html() == "&nbsp;") {
				hadOne = true;
			}
		});
		
		if (!hadOne) {
			ret.push(el);
		}
	});
	return $j(ret);
}

function initPsRTE() {
	var ccEditor = $j('.psRTE');
	
	ccEditor.each (function (index, el) {
		// Check for search hints class
		var settings = {
			    nameSpace:       "html", // Useful to prevent multi-instances CSS conflict
			    onShiftEnter:    {keepDefault:false, replaceWith:'<br />\n'},
			    onCtrlEnter:     {keepDefault:false, openWith:'\n<p>', closeWith:'</p>\n'},
			    onTab:           {keepDefault:false, openWith:'    '},
			    previewInWindow: 'width=800, height=600, resizable=yes, scrollbars=yes',
			    markupSet:  [
			        {name:'Heading 1', key:'1', openWith:'<h1(!( class="[![Class]!]")!)>', closeWith:'</h1>', placeHolder:'Your title here...' },
			        {name:'Heading 2', key:'2', openWith:'<h2(!( class="[![Class]!]")!)>', closeWith:'</h2>', placeHolder:'Your title here...' },
			        {name:'Heading 3', key:'3', openWith:'<h3(!( class="[![Class]!]")!)>', closeWith:'</h3>', placeHolder:'Your title here...' },
			        {name:'Heading 4', key:'4', openWith:'<h4(!( class="[![Class]!]")!)>', closeWith:'</h4>', placeHolder:'Your title here...' },
			        {name:'Heading 5', key:'5', openWith:'<h5(!( class="[![Class]!]")!)>', closeWith:'</h5>', placeHolder:'Your title here...' },
			        {name:'Heading 6', key:'6', openWith:'<h6(!( class="[![Class]!]")!)>', closeWith:'</h6>', placeHolder:'Your title here...' },
			        {name:'Paragraph', openWith:'<p(!( class="[![Class]!]")!)>', closeWith:'</p>'  },
			        {separator:'---------------' },
			        {name:'Bold', key:'B', openWith:'<strong>', closeWith:'</strong>' },
			        {name:'Italic', key:'I', openWith:'<em>', closeWith:'</em>'  },
			        {name:'Stroke through', key:'S', openWith:'<del>', closeWith:'</del>' },
			        {name:'Underline', key:'U', openWith:'<span style="text-decoration: underline">', closeWith:'</span>' },
			        {separator:'---------------' },
			        {name:'Ul', openWith:'<ul class="text">\n', closeWith:'</ul>\n' },
			        {name:'Ol', openWith:'<ol class="text">\n', closeWith:'</ol>\n' },
			        {name:'Li', openWith:'<li>', closeWith:'</li>' },
			        {separator:'---------------' },
			        {name:'Picture', key:'P', replaceWith:'<img src="[![Source:!:http://]!]" alt="[![Alternative text]!]" />' },
			        {name:'Link', key:'L', openWith:'<a href="[![Link:!:http://]!]"(!( title="[![Title]!]")!)>', closeWith:'</a>', placeHolder:'Your text to link...' },
			        {separator:'---------------' },
			        {name:'Box', replaceWith:'\n<div class=\"box-round\">\n    <h2>Your title here...<\/h2>\n    <p>Your content here...<\/p> \n<\/div>\n' },
			        {name:'Table', replaceWith:'\n<!-- This is a standards driven table. there are no styles, borders, widths and there is a header row--> \n   <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"grid\" id=\"tableUniqueID\"> \n   <CAPTION>This text appears above the table<\/CAPTION>\n   <thead> \n     <tr> \n       <th>H1 content<\/th> \n       <th>H2 content<\/th> \n       <th>H3 content<\/th> \n     <\/tr> \n   <\/thead> \n   <tfoot> \n     <tr> \n       <td colspan=\"3\">This will display at the bottom of the table. Ideal for legends.<\/td> \n         <\/tr> \n   <\/tfoot> \n   <tbody> \n     <tr> \n       <td>R1C1 content<\/td> \n       <td>R1C2 content<\/td> \n       <td>R1C3 content<\/td> \n     <\/tr> \n     <tr> \n       <td>R2C1 content<\/td> \n       <td>R2C2 content<\/td> \n       <td>R2C3 content<\/td> \n     <\/tr> \n    <\/tbody> \n   <\/table> \n' }
			    ]
			};
		
		var jel = $j(el);
		if (jel.hasClass("psRTESearch")) {
			 settings = $j.extend(true, {}, settings);
			 var markupSet = settings.markupSet;

			 markupSet.push({name:'Translation Hints', call: function() { 
				 var toLangField = $j(el).attr('tolang');
				 
				 var fromLanguage = $j($j(el).attr('fromlang')).val(); 
				 var toLanguage = $j(toLangField).val(); 
				 
				 handleSelectedText(fromLanguage, toLanguage);
			 }});
		}
		jel.markItUp(settings);
	});
}

//A way to initiate some common UI widgets from dialogs
function initBehaviors(){
	jsLazyLoader();
	
    /* Reloading "alsoResize" plugin to correct popup bounding issue (jQuery bug 4603/5559).
     * This code snippet was taken from jquery-ui-1.8.1.custom.min.js and modified to use the jQuery alias
     * in this script. It reloads the "alsoResize" plugin, because in that file the "alsoResize" plugin
     * is loaded prior to the "container" plugin, which causes "alsoResize" to fail to respect the bounds
     * of the container. 
     * 
     * Remove this block of code when jQuery is fixed.
     */
//	$j.ui.plugin.add("resizable","alsoResize",{start:function(){
//	var b=$j(this).data("resizable").options,a=function(c){$j(c).each(function(){
//	$j(this).data("resizable-alsoresize",{width:parseInt($j(this).width(),10),
//	height:parseInt($j(this).height(),10),left:parseInt($j(this).css("left"),10),top:parseInt($j(this).css("top"),10)})})};
//	if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}
//	else $j.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(){
//	var b=$j(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},
//	f=function(h,i){$j(h).each(function(){var j=$j(this),l=$j(this).data("resizable-alsoresize"),p={};
//	$j.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){
//	if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&& $j.browser.opera){
//	b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};
//	typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?$j.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){
//	var b=$j(this).data("resizable");if(b._revertToRelativePosition&&$j.browser.opera){b._revertToRelativePosition=false;
//	el.css({position:"relative"})}$j(this).removeData("resizable-alsoresize-start")}});
	// END: Fix for jQuery bug 4603/5559
	
	$j('div.tabs').tabs();
	$j('h2.accordion').accordion();
	$j('#psDialog button.cancel').live('click',function(){$j('#psDialog').dialog('close');});
	//Zebra stripes
	$j('fieldset > div:odd:visible').addClass('alt');
	$j('fieldset > div:even:visible').removeClass('alt');
	//YUI style kill later
	$j('.bd tr:even').addClass('alt');
	
	// For any dialog with class "linkClose", unless the specific links have "noClose" on them,
	// close the dialog when the user clicks them.
	$j('.linkClose a:not(.noClose)').click(function(){$j('#psDialog').dialog('close');});
	
	$j('.dialog, .dialogC, .dialogM, .dialogR, .dialogF, .dialogDiv, .dialogDivC, .dialogDivM, .replaceNext').css('visibility','visible'); //Dialog links are hidden till ready this reveals them
	var dialogObjects = '.dialog, .dialogC, .dialogM, .dialogR, .dialogF, .dialogDiv, .dialogDivC, .dialogDivM';
	$j(dialogObjects).each(function() {
		var url = $j(this).attr('href');
		$j(this).attr('href', ''); //to avoid clicking on link if page did not load completely
		if (url == '') {
			url = $j(this).attr('dialogContent');
		}
		if (url) {
			$j(this).attr('dialogContent', url); //will be restored to href in function psDialog()
		}
	});

	if(!radioSliderLoaded){
	$j( 'input.radioSlider' ).each(function() {
		var dis = $j(this);
		var el = dis.attr('id');
		var state = dis.attr('checked');
		
		// Allow changing of the text with data-text-on and data-text-off
		var onText = dis.attr("data-text-on");
		if (!onText) onText = pss_text('psx.js.scripts.psbehaviors.on');
		var offText = dis.attr("data-text-off");
		if (!offText) offText = pss_text('psx.js.scripts.psbehaviors.off');
		
		var labelId = el + 'Label';
		dis.after('<label for="' + el +'" class="radioSlider" id="' + labelId +'"><span class="txtOn">'+onText+'</span><em>&nbsp;</em><span class="txtOff">'+offText+'</span></label>');
		radioSliderState(el, state);
		if (isIEBelow(9)) {
			$j('label[for='+el+']').click(function() {
				var x = $j(this).attr('for');
				var cb = $j('#'+x);
				if (cb.is(':checked')) {
					cb.removeAttr('checked');
				} else {
					cb.attr('checked', true);
				}
			});
		}
	})
		radioSliderLoaded=true;
	}

	$j( 'input.radioSlider' ).bind(isIEBelow(9)?'propertychange':'change', function () {
		var el = $j(this).attr('id');
		var state = $j(this).attr('checked');
		radioSliderState(el, state);
	});
}
	blinker('.blink', 20);//Blink tag function selector, repeat value
//	psTip(); //instantiate tooltip code

function radioSliderState(el, state) {
	if (state === true || state === 'checked') {
		$j('#' + el + 'Label').addClass('on').removeClass('off'); 
	} else {
		$j('#' + el + 'Label').addClass('off').removeClass('on'); 
	}
}

/**
 * A horribly hacky function to check for IE less than some arbitrary mess.
 * @param version version to check
 * @returns true if browser is (1) IE and (2) less than the given version
 */
function isIEBelow(version) {
	if ($j.browser.msie && $j.browser.version < version) {
		return true;
	} else {
		return false;
	}
}

//Parent portal active nav highlighting function
function setActive() {
	var setActive = $j('#activeNav').val();
	$j(setActive).addClass('selected');
}

//expands or collapses an h2 with class="toggle collapsed" or class="toggle expanded" and has a span with a checkbox
function psEnableCheck(){
	$j('h2 input:checkbox:enabled').each( function() {
	var checked = $j(this).attr('checked');
	var heading = $j(this).parentsUntil('.box-round').last();
	var content = $j(this).parentsUntil('.box-round').next();
		 if(checked){
			content.show();
			heading.removeClass('collapsed').addClass('toggle expanded');//adds classes if they aren't present
		 }else{
			 content.hide();
			 heading.removeClass('expanded').addClass('toggle collapsed');
		}
	});
}

//turns h2 with class="toggle collapsed" or class="toggle expanded" toggle-able widget	
function psToggle(){
	//this is a toggle replacement for the flipvis code
	var togCol = $j(this).hasClass("expanded");
//	changes the class on the header/control
	if (togCol) {
		$j(this).removeClass('expanded').addClass('collapsed');
	} else{
		$j(this).removeClass('collapsed').addClass('expanded');
	}
	$j(this).next().toggle();//hides/shows the next sibling object (div, fieldset, etc)
}
function initToggle () {
	$j('.toggle.collapsed').next().hide();
}
//Toggles all the toggles on a page, constrained to an id'd parent object
function psToggleAll(direction, target){
	var targEl = target + ' .toggle';
	if (direction == 'expand') {
		$j(targEl).each(function(){
			$j(this).removeClass('collapsed').addClass('expanded');
			$j(targEl).next().show();
		});
	} else if (direction == 'collapse'){
		$j(targEl).each(function(){
			$j(this).removeClass('expanded').addClass('collapsed');
			$j(targEl).next().hide();
		});
	}
	
}

/**
 * Drop-in safer replacement for standard jQuery ajax method. The standard method is not
 * very graceful when it comes to session timeouts, etc. We'll deal with those situations here.
 * @param opts hash of options
 * @throws "ajax_error" if some error occurred other than session timeout/logoff from another user logging in
 */
function psAjax (opts) {
	// If there's no error handler (likely there isn't), add it here. Let's *hope* the developer
	// doesn't just catch the error condition and ignore it. :-O
	if (!opts.error) {
		opts.error = function (jqXHR, textStatus, errorThrown) {
			psAjaxError();
		};
	}
	
	// Replace the success handler (if there is one) with a safer one.
	var successHandler = opts.success;
	opts.success = function(data, textStatus, jqXHR) {
		// Check that the response looks legal for an Ajax call. If it's not, 
		// this method will never return.
		psCheckAjaxResponse(jqXHR.status, data);
		
		// Looked ok, pass it on.
		if (successHandler) successHandler(data, textStatus, jqXHR);
	};
	
	// Finally, make the real jQuery ajax call
	$j.ajax (opts);
}

/**
 * Drop-in safe replacement for standard jQuery load method. The standard method is convenient, but it's not
 * very graceful when it comes to session timeouts, etc. We'll deal with those situations here.
 * @param content the URL to load
 * @param success success handler
 * @throws "ajax_error" if some error occurred other than session timeout/logoff from another user logging in
 */
$j.fn.psLoad = function (content, success) {
	var el = this;
	psAjax({ url: content, type: "GET", cache: false,
		success: function(responseText, textStatus, xhr) {
			// If we get here, the response looks good. Replace the element.
			el.html(responseText);
			
			// Finally, call the success callback
			if (success) success();
		}
	});
}

function replaceNext(event){
	var content = $j(this).attr("href");
	var curID = $j(this).attr('id');
	var nextID = $j(this).next().attr('id');
	$j(this).next().psLoad(content, function(){initBehaviors();
		if ( curID == "schoolContext" || "termContext"){
			$j('#'+ nextID).find('select').focus();
		}
	});
	event.preventDefault();
} 


function loadingDialog(message){
	$j('body').append('<div id="loading"></div>');
	if (!message) message = pss_text("psx.js.scripts.psbehaviors.loading");
	$j('#loading').dialog({title: message, width: 228, height:35, resizable:false, position: 'center', modal: true, closeText: '',beforeclose: function (event, ui) { return false; },dialogClass: "dialogLoading", autoOpen: true,open: function(event, ui) {$j(this).closest('.ui-dialog').find('.ui-dialog-titlebar-close').hide();}});
}

function closeLoading() {
	var loading = $j('#loading');
	if (loading) loading.dialog().remove();
}

/**
 * Check the ajax response back from the server to see if it looks like a response is supposed
 * to look. If it does not, then log off the user (if what came back looks like a login page)
 * or just display an error alert (otherwise).
 * @param status
 * @param responseText
 */
function psCheckAjaxResponse(status, responseText) {
	if (!responseText) return;
	
	if (status && (status < 200 || status > 299)) {
		psAjaxError();
	}
	
	responseText = responseText.toLowerCase();
	var isDocument = false;
	for (var i = 0; i < responseText.length; i++) {
		// Ignore whitespace
		if (" \t\n\r".indexOf(responseText.charAt(i)) >= 0) continue;
		
		// If it's got an <html> or <!DOCTYPE> at the beginning, it's bad.
		if (responseText.indexOf("<html", i) == i || responseText.indexOf("<!doctype", i) == i) {
			isDocument = true;
			break;
		}

		// If it starts with a comment, skip it
		if (responseText.indexOf("<!--", i) == i) {
			var endPos = responseText.indexOf("-->", i+1);
			if (endPos >= 0) {
				i = endPos + 2;		// Skip to end of comment, but leave one for the loop incr
				continue;
			} else {
				// Comment to the end? OK, whatever...
				break;
			}
		}
	
		// Otherwise, if it survives, it's not a whole document.
		break;
	}
	
	if (isDocument) {
		// OK, it's a whole document. See if it looks like a login page.
		var loginRegex = /type\s*=\s*["']password["'].*name\s*=\s*["'](password|pw)["']/i;
		if (responseText.match(loginRegex)) {
			psLogoutError();
		} else {
			// Not a login page, just throw up an error and quit loading
			psAjaxError();
		}
	}
}

if(!_messages) var _messages = {};
/**
 * Get texts from the server based on a prefix.
 * @param prefix the prefix to use
 * @param onlyIfNotPresent (optional) if passed, check to see if message is present yet; only fetch the
 *   texts from the server if this key is not present
 */
if (typeof pss_get_texts != 'function') pss_get_texts = function (prefix, onlyIfNotPresent) {
  if (onlyIfNotPresent && _messages[onlyIfNotPresent]) return;
  
  jQuery.ajax ({async: false, 
    url:'/getMessages.action', 
    data:{prefix: prefix, locale: get_locale()},
    dataType:'json',
    success: function (msgs) {
      jQuery.each(msgs, function (key, value) {
        _messages[key] = value;
      });
    }
  });
}
	
function psLogoutError() {
	pss_get_texts("psx.js.scripts.psbehaviors.", "psx.js.scripts.psbehaviors.you_have_been_logged_out");
	alert(pss_text("psx.js.scripts.psbehaviors.you_have_been_logged_out"));
	
	var portal = window.location.href.split("/")[3];
	var url;
	if (portal != 'guardian') url = "/"+portal+"/~loff";
	else url = "/"+portal+"/home.html?ac=logoff";
	
	window.location = url;
	throw "ajax_logout";
}

function psAjaxError() {
	pss_get_texts("psx.js.scripts.psbehaviors.", "psx.js.scripts.psbehaviors.an_error_was_detected_contacting_server");
	alert(pss_text("psx.js.scripts.psbehaviors.an_error_was_detected_contacting_server"));

	// In case it's open (doesn't hurt if not)
	closeLoading();
	
	throw "ajax_error";
}
/* PowerSchool Tooltip Code */
//var initTip = function () {
//	//This function slurps out the title text, removes the title attribute, and moves content to data-tip attribute
//	//preventing the default tooltip rendering
//	"use strict";
//	$j('[title]').each(function () {
//		if (this.title !== '') {
//			this.t = this.title;
//			$j(this).removeAttr('title').attr('data-tip', this.t);
//		}
//	});
//};
//initTip();
//function psTip() {
//	//This function creates rich html tooltips
//	"use strict";
//	var xOffset = -5, yOffset = 20; //mouse offsets
//	$j('.psTip, [title], [data-tip]').unbind().live('mouseover mouseout mousemove', function (e) {
//		//binds hover, and mousemove events on tooltipped, and titled tags
//		initTip();
//		var dataTip = $j(this).attr('data-tip'); //Looks for data-tip attribute and uses it if present		
//		if (e.type === 'mouseover') {
//			if (dataTip === null) {
//				return false;
//			} else if (dataTip.length !== 0) {
//				this.t = $j(this).attr('data-tip');
//			}
//			this.top = (e.pageY + yOffset); this.left = (e.pageX + xOffset); //gets position of tooltip relative to mouse
//			$j('body').append('<div id="psTipPanel">' + this.t + '</div>'); //instantiates tooltip div
//			$j('div#psTipPanel').css("top", this.top + "px").css("left", this.left + "px").delay(500).fadeIn(500); //sets position of tooltip			
//		} else if (e.type === 'mouseout') {
//			$j("div#psTipPanel").fadeOut(500).remove(); //kills tooltip div
//		} else {
//			//on mousemove updates tooltip position
//			this.top = (e.pageY + yOffset);
//			this.left = (e.pageX + xOffset);
//			$j("div#psTipPanel").css("top", this.top + "px").css("left", this.left + "px");
//		}
//	});
//};

/* end tooltip */
//Dialog widget	
function psDialog(a) {
	//loading panel
	loadingDialog();
	// The tag in the page <a href="content.html" title="Dialog Title" class="dialog" or "dialogC" or "dialogM">Open Dialog</a>
	// The content page is wrapped with a <div  style="width:XXXpx">content</div> this sets the width of the dialog
	$j('#psDialog').dialog('remove');
	$j('#psDialog').empty();
	var dWidth = "auto",
		dHeight = "auto",
		dIdent = $j(this).attr("id"),
		content = $j(this).attr("href");
	if (content == '' ) {
		var url = $j(this).attr('dialogContent'); //this is set in initBehaviors()
		if (url) {
			content = url;
		}
	}
	var dTitle = $j(this).attr("title"),
		dClass = $j(this).attr("class"),
		dModal = false,
		dResize = false,
		x = 0,
		y = 0;
	
	var dClasses = dClass.split(/\s+/g);
	var foundOne = false;
	$j.each(dClasses, function(index, dClassPart) {
		switch(dClassPart)
	{
	case 'dialogC':
		x = 'center';
		y = 'center';
			foundOne = true;
			return false;
	case 'dialogM':
		x = 'center';
		y = 'center';
		//modal dialog
		dModal = true;
			foundOne = true;
			return false;
	case 'dialogR':
		x = 'center';
		y = 'center';
		//resizable dialog
		dResize = true;
		dHeight = 500;
		dModal = true;
			foundOne = true;
			return false;
	case 'dialogDivC':
		x = 'center';
		y = 'center';
			foundOne = true;
			return false;
	case 'dialogDivM':
		x = 'center';
		y = 'center';
		//modal dialog
		dModal = true;
			foundOne = true;
			return false;
		default:
		break;
		}
		return true;
	});

	if (!foundOne) {
		x = $j(this).offset().left;
		y = $j(this).offset().top - $j(document).scrollTop();
	}
	
	if (dClass == 'dialogDiv' | dClass == 'dialogDivM' | dClass == 'dialogDivC') {
		var divContent = $j(content).html();
		$j('#psDialog').append(divContent);
		dWidth = $j(content).css('width');
		$j('#psDialog').dialog({
	 	    title : dTitle,
			closeText: 'X',
			width: dWidth,
			minWidth: 200,
			minHeight : 40,
			resizable : dResize,
			position: [x,y],
			draggable: true,
			modal: dModal,
			autoOpen: false,
			zIndex: 1005
		});
		$j('#loading').dialog().remove();
		$j('#psDialog').dialog('open');
		$j("#psDialog :input:visible:enabled:first").focus();
	} else {
		$j('#psDialog').psLoad(content, function() {
			$j('#errorMsg').hide();
			$j('#InboundRequests').click(function(event) 
			{
	    		$j.ajax({
	       			url: "/admin/studentmobility/notificationsInstitutionAJAX.action",
	          		type: "GET",
		          	dataType: "json",
		          	success: function (data) 
	    	      	{
	        	  		if(data.success == "true")
	          			{
	          				$j('#errorMsg').hide();
	          				window.open($j('#InboundRequests').attr('href'),'popup');
		          		}
		          		else
	    	      		{
	        	  			$j('#errorMsg').show();
	          			}
	          		},
					error: function(data)
					{
						psAjaxError();
			   		}
	     		});
		    	event.preventDefault();
			});
			dWidth = $j('#psDialog div:first-child').css('width');
			
			if (dWidth === "0px"){//fix for resizable width with jQuery 1.7 update
				dWidth = 600;
			}
			if (!dHeight){
				dHeight = $j('#psDialog').css('height');
			}
//			console.log(dWidth);
			$j('#psDialog').dialog({
		 	    title : dTitle,
				closeText: 'X',
				width: dWidth,
				minWidth: 200,
				minHeight : 40,
				height: dHeight,
				resizable : dResize,
				position: [x,y],
				draggable: true,
				modal: dModal,
				autoOpen: false,
				zIndex: 1005
			});
			initBehaviors();
			$j('#loading').dialog().remove();
			$j('#psDialog').dialog('open');
			$j("#psDialog :input:visible:enabled:first").focus();
		});
		
	}
	return false;
	/*End psDIalog*/
}

//4D Table formatting injection script: custom field pages lack some basic styling, this fixes them: Remove when we fix 4D
function fourDTableFix(){
	$j('.fourDTable').prepend('<tr class="hide"><td></td><td></td></tr>');
	$j('.fourDTable tr:odd').addClass('alt');
	$j('.fourDTable td:first-child').wrapInner('<strong />');
}
//Blinker code to animate content
function blinker(el, c){
	$j(el).effect("pulsate", { times: c }, 1000, function () {})
}
//Animation Codes for UI notification
function shaker(el, c){
	$j(el).effect("shake", { times:c, distance:2, direction: "up" }, 100, function () {})
}
//view-events/data collection floating feedback widget
function psSystemFeedback(){
	if(typeof feedbackEnabled != 'undefined' && feedbackEnabled){
		if ($j('#feedbackSend').size() == 0)
		{
			   if(!recordingActivated){
				   $j('body:not(body.pslogin)').append('<div id="feedbackSend" class="group">' +
							'<div class="button" id="recordingStart">' + pss_text("psx.js.scripts.psbehaviors.recording_start") + '</div>' +
							'<div class="button" id="pageFeedback">' + pss_text("psx.js.scripts.psbehaviors.send_report") + '</div>' + 
							'<div class="button hide" id="recordingStop">' + pss_text("psx.js.scripts.psbehaviors.recording_stop") + '</div>' +
							'<div class="button hide" id="commentaryAddition">' + pss_text("psx.js.scripts.psbehaviors.add_issue_comment") + '</div>' +
							'<div class="button hide" id="recordingCancel">' + pss_text("psx.js.scripts.psbehaviors.recording_cancel") + '</div>' +
						 '</div>');
			   }else{
				   $j('body:not(body.pslogin)').append('<div id="feedbackSend" class="group">' +
							'<div class="button hide" id="recordingStart">' + pss_text("psx.js.scripts.psbehaviors.recording_start") + '</div>' +
							'<div class="button hide" id="pageFeedback">' + pss_text("psx.js.scripts.psbehaviors.send_report") + '</div>' + 
							'<div class="button" id="recordingStop">' + pss_text("psx.js.scripts.psbehaviors.recording_stop") + '</div>' +
							'<div class="button" id="commentaryAddition">' + pss_text("psx.js.scripts.psbehaviors.add_issue_comment") + '</div>' +
							'<div class="button" id="recordingCancel">' + pss_text("psx.js.scripts.psbehaviors.recording_cancel") + '</div>' +
				   '</div>');
			   }
			   
			   $j('#reportIssueLink').addClass('hide');
			   
			   $j('#pageFeedback').click(function(ev){
				   feedbackwindow();
				   $j('#feedbackSend').remove();
				   $j('#reportIssueLink').removeClass('hide');
				   $j(this).blur();
				   return false;
			   });
			   
			   $j('#recordingStart').click(function(ev){
				   //Hide feedbackSend and recordingStart buttons
				   $j('#pageFeedback, #recordingStart').addClass('hide');
				   //Show recordingStop and commentaryAddition buttons
				   $j('#recordingStop, #commentaryAddition, #recordingCancel').removeClass('hide');
				   $j(this).blur();
				   var referringDoc = window.document;
				   var url = referringDoc.URL;	       
				   var htmlTag = referringDoc.getElementsByTagName("html")[0];
				   var screenshot = htmlTag.innerHTML;
				   var queryString = window.location.search;
				   var responseText = submitScreenShot(screenshot, url, queryString);
				   return false;
			   });
			   
			   $j('#recordingStop').click(function(ev){
				   recordingWindow();
				   $j(this).blur();
				   return false;
			   });
			   
			   $j('#commentaryAddition').click(function(ev){
				   commentsWindow();
				   $j(this).blur();
				   return false;
			   });
			   
			   $j('#recordingCancel').click(function(ev){
				   cancelRecording();
				   //Remove hover buttons
				   $j('#feedbackSend').remove();
				   $j('#reportIssueLink').removeClass('hide');
				   $j(this).blur();
				   recordingActivated=false;
				   return false;
			   });
		   }
	}
}

// *********************************************
// ****** General Widget Message Handling ******
// *********************************************

// to be used sparingly (Please don't). Written speicifically for dates used in incident_actions.js
// which is controlled by incident management validation. The popup is a single page include that can
// be used multiple times before the data is submitted. Only used to make sure errors aren't propogated
// from one action to another. 
// clears all errors under the passed in element
function clearAndResetAllErrors(jQueryElement) {
	//children of the passed in element and clear any error messages
    var children = jQueryElement.find('.error');
    if (children.length) {
    	children.each(function(){ 
    		clearError($j(this));
    		//set it back as if it were just loaded
    		$j(this).addClass("unvalidated");
    		$j(this).removeClass("hasHadError");
    	});
    }
}

// utility to clear widget errors for a given element
function clearError(jQueryElement) {
	// clear error class from the element
	jQueryElement.removeClass("error");
	jQueryElement.removeClass("unvalidated");
	// find the element's error message display element
	var errorMessageBlock = findMsgBlockForElement(jQueryElement, false);
	// clear the error message display element if necessary
	if (errorMessageBlock.length == 1 ) {
		// if we've previously had errors, lets just hide the error display element
		errorMessageBlock.hide();
		errorMessageBlock.html("");
	}
}

// utility to set widget errors for a given element
function setError(jQueryElement, errorMsg) {
	jQueryElement.addClass("error"); 
	//flag that isn't cleared - lets the js know to keep an eye on this rascal
	jQueryElement.addClass("hasHadError"); 
	// find the element's error message display element
	var errorMessageBlock = findMsgBlockForElement(jQueryElement, true);
	// just to make sure nothing hinkie happened
	if (errorMessageBlock.length == 1) {
		// set the passed message to the display element
		errorMessageBlock.html(errorMsg);
		// make sure we show it
		errorMessageBlock.show();
	}
}

// given an element, find an existing error message block and 
// return a handle to it
// if one does not exist and genIfMissing is true, create one to hand back
// if one does not exist and genIfMissing is false, hand back an empty referrence
function findMsgBlockForElement(jQueryElement, genIfMissing) {

	// get the id of the element
	var elementID = getElementID(jQueryElement);
	
	// does this element have an error block (elementID_error)?
	var errorBlockID = elementID + "_error";
	var errorMessageBlock = $j('#' + errorBlockID);
	
	// if we don't have a message display element already
	if (errorMessageBlock.length == 0 ) {
		
		if (genIfMissing) {
			// we are setting an error, lets create the element
			jQueryElement.parent().append("<p id ='" + errorBlockID + "' class='error-message'></p>");
			// now grab ahold of it
			errorMessageBlock = $j('#' + errorBlockID);
		}
		// else we are clearing a message element... if it doesn't exist, don't worry about it

	}
	// else we have a message display element alvalidateValueBeforeMax, return that

	return errorMessageBlock;
}

// counter for generated IDs
var generatedIdCounter = 1;

// wrapper function for jQuery function.
// returns the elements ID attribute. If an ID attribute
// does not exist, the function will create a unique ID on the
// element and return that newly created value
function getElementID(jQueryElement) {

	var theID = jQueryElement.attr('id');
	//if the element doesn't have an id, let's make one
	if (theID == null || theID == "") {
		jQueryElement.attr('id', 'ldv_generatedID' + generatedIdCounter++);
		theID = jQueryElement.attr('id');
	}
	return theID;

}

// ******************** End ********************
// ****** General Widget Message Handling ******
// *********************************************

// *********************************************
// ******* General Form Message Handling *******
// *********************************************

// Clear the feedback message block
function clearFeedback() {
	var feedbackDiv = $j('#feedback-message');
	//clear if it exists
	if (feedbackDiv.length > 0) {
		feedbackDiv.hide();
		feedbackDiv.html("");
	}
}

// Display to the user one or more messages in as a 'feedback-alert' if possible.
// If the page does not have a 'feedback-message' block to display the messages, 
// shove the values in an alert. Then scroll the page to the feedback (if present)
// or the topmost error
function setFeedback_Alert(messageArray) {
	var feedbackDiv = $j('#feedback-message');
	
	// no feedback? can we auto-drop it in?
	if (feedbackDiv.length == 0) {
		//try to fabricate a feedback
		var firstBoxRound = $j('.box-round:first');
		if (firstBoxRound.length > 0){
			firstBoxRound.before('<div class="feedback-alert" id="feedback-message" style="display: none;"></div>');
			feedbackDiv = $j('#feedback-message');
		}
		
	}
	
	// if we have a feedback div, plug the messages into it and show it
	if (feedbackDiv.length > 0) {
		feedbackDiv.html("");	// clear the message.
		//plug each message into the feedback
		$j.each(messageArray, function() {
			$j('#feedback-message').append('<p>' + this + '</p>');
		});
		$j('#feedback-message').removeClass('feedback-confirm');
		$j('#feedback-message').addClass('feedback-alert');
		if ($j('#feedback-message').is(":hidden"))
			$j('#feedback-message').show();
		// scroll up to the feedback
		scrollToElement($j("#feedback-message"));
	}
	// this page does not implement the feedback, scroll to the topmost error
	else {
		// give the user 'some' notion that something happened. 
		var alertText = "";
		$j.each(messageArray, function() {
			alertText = alertText + this + '\n';
		});
		alert(alertText);
		// scroll up to the first error
		scrollToElement($j('.error:first'));
	}
}

//scroll the page to a specific element
function scrollToElement(jQueryElement) {

	if (isInView(jQueryElement) != true)
		$j("html, body").animate({ scrollTop: jQueryElement.offset().top }, "fast");
	
}

// is this element in the current view?
function isInView(elem)
{
	if (elem == null || elem == "")
		return false;
    var docViewTop = $j(window).scrollTop();
    var docViewBottom = docViewTop + $j(window).height();

    var elemTop = $j(elem).offset().top;
    var elemBottom = elemTop + $j(elem).height();

    return ( (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

// ******************** End ********************
// ******* General Form Message Handling *******
// *********************************************


//Send screen shot. Should only be called when page is loaded (on DOM is ready) and recording is active
function sendRecordingScreenShot(){
	var referringDoc = window.document;
	var url = referringDoc.URL;
	var htmlTag = referringDoc.getElementsByTagName("html")[0];
	var screenshot = htmlTag.innerHTML;
	var queryString = window.location.search;
	var responseText = submitScreenShot(screenshot, url, queryString);			
}

function submitScreenShot(screenshot, url, queryString)
{
	var base = "/recordingAJAX.action";
	var postData = "screenshot=" + escape(screenshot);
	postData = postData + "&url=" + encodeURIComponent(url);
	postData = postData + "&params=" + escape(queryString);
	
	var request = new XMLHttpRequest();
	request.open("POST", base, false);
	//Send the proper header information along with the request
	request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	request.setRequestHeader("Content-length", postData.length);
	request.setRequestHeader("Connection", "close");
	request.send(postData);
	return request.responseText;
}

function cancelRecording(){
	var base = "/cancelRecordingAJAX.action";
	
	var request = new XMLHttpRequest();
	var postData = "";
	request.open("POST", base, false);
	request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	request.setRequestHeader("Content-length", postData.length);
	request.setRequestHeader("Connection", "close");
	request.send(postData);
	return request.responseText;
}

//Functions that makes the windows calls, same as commonscript.ftl, coz the changes done there were no reflected.
function recordingWindow () {
	window.showModalDialog('/stopRecording.action','stop_recording','dialogWidth:640px; dialogHeight:500px; scroll:no;');
}

function commentsWindow () {
	window.showModalDialog('/getRecordCommentaryForm.action','add_commentary','dialogWidth:900px; dialogHeight:400px; scroll:no;');
}

	
//Change the buttons visualization
function changeStopButton(){
    $j('#feedbackSend').remove();
    $j('#reportIssueLink').removeClass('hide');
	$j('#recordingStop, #commentaryAddition, #recordingCancel').addClass('hide');
	$j('#pageFeedback, #recordingStart').removeClass('hide');
}

//Extract URL parameter values
//Returns String 'null' if parameter is not present
function getURLParameter(name) {
    return unescape(
        (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
    );
}

$j(document).ready(function () {
	//Set keyboard focus to the first component on the first form and select the text, now excludes attendance forms
	$j("form:not(#attendance) :input:not(:button, :checkbox, :radio):visible:enabled:first:[readonly!=\"readonly\"]").each(function (idx, el) {
		el.focus();
		if (el.type == "text") {
			el.select();
		}
	});

	initBehaviors();
	
	setActive();
	// Remove the Report an Issue link if the feature is disabled
	if(typeof feedbackEnabled != 'undefined' && !feedbackEnabled){
		$j("#reportIssueLink").remove();
	} 
	//  This is now activated by a link on the bottom of the page. Only do this here when recording is active	
	//  Also only activate link on the bottom of the page if it isn't of class pslogin and frameMenu
	var temp = $j('body:not(.pslogin,.frameMenu)').length;
	if (recordingActivated && temp>0)
	{
		psSystemFeedback();
	}
	psEnableCheck();
	fourDTableFix();
		
	// Checks if the recording function is active. if it does, the info page is submitted to the recording action
	if (recordingActivated){
		sendRecordingScreenShot();	
	}

	/*Invoke widgets, and hooks into DOM*/

	$j('<div id="psDialog"></div>').appendTo('body').hide();//Create a dialog div
	$j('a.dialog').live('click',psDialog);
	$j('a.dialogDiv').live('click',psDialog);
	$j('a.dialogDivC').live('click',psDialog);
	$j('a.dialogDivM').live('click',psDialog);
	$j('a.dialogC').live('click',psDialog);
	$j('a.dialogM').live('click',psDialog);
	$j('a.dialogR').live('click',psDialog);
	$j('a.dialogF').live('click',psDialog);//Listen for clicks on links with these classes

	$j('a.replaceNext').live('click',replaceNext);
	$j('table.linkDescList').find('tr:not(thead tr):even').addClass('alt');
	
	$j('#expand_all_changes-button').live('click',function(){psToggleAll('expand', '#change_reasons_div');});//YUI dialogs' buttons to expand all
	$j('#collapse_all_changes-button').live('click',function(){psToggleAll('collapse', '#change_reasons_div');});//YUI dialogs' buttons to collapse all
	$j('.expandAll').live('click',function(){psToggleAll('expand', '#content-main');});//buttons to expand all toggles: 'class','parent constraint'
	$j('.collapseAll').live('click',function(){psToggleAll('collapse', '#content-main');});//buttons to collapse all toggles: 'class','parent constraint'
	$j('h2.toggle').live('click', psToggle);//turns h2 with class="toggle collapsed" or class="toggle expanded" toggle-able widget
	$j('h3.toggle').live('click', psToggle);//turns h2 with class="toggle collapsed" or class="toggle expanded" toggle-able widget
	initToggle();
	
	$j('button.toggle').live('click', function(){$j(this).addClass('hide').next().removeClass('hide');});//toggles next element
	$j('button.toggleParent').live('click', function(){$j(this).parent().addClass('hide').prev().removeClass('hide');});//toggles parent tag off, used with toggle above
	
	$j('button#btnSubmit.disabled').attr('disabled','true');//workaround for disabling button to aid LoadRunner
	
//confirmation for all delete buttons---------------*
	var delBtn = $j('button#btnDelete:not(.confirmOnly), a#btnDelete:not(.confirmOnly)');// real delete button
	if (delBtn.length == 1) {
		var delBtnConfTxt = pss_text("psx.js.scripts.psbehaviors.confirm_delete");// Replacement text for real delete button
		var delFake = $j('<button type="button" id="btnConfirmDeleteProxy">' + pss_text("psx.js.scripts.psbehaviors.delete") + '</button>');// substitute delete button, replaces real delete, to add additional click before delete
		var delCancel = $j('<button type="button" id="btnConfirmCancel">' + pss_text("psx.js.scripts.psbehaviors.cancel") + '</button>').addClass('hide');// this button returns buttons to default state, fake delete visible, others hidden
		delFake.click(function () { // this event shows the real delete, and cancel button hide the fake delete
			"use strict";
			$j(this).toggleClass('hide');
			$j(delCancel).toggleClass('hide');
			$j(delBtn).toggleClass('hide');
		});
		delCancel.click(function () { // this event hides the real delete and cancel, shows the fake delete
			"use strict";
			$j(this).toggleClass('hide');
			$j(delBtn).toggleClass('hide');
			$j(delFake).toggleClass('hide');
		});
		delBtn.text(delBtnConfTxt).addClass('hide'); // hides the real delete button
		delBtn.after(delFake).after(delCancel); // injects the two new buttons dynamically
	}
//end delete confirm code---------------------------*

	$j('form.submitOnce').submit(function(){if(typeof submitOnce_shouldShow != 'undefined'){if(submitOnce_shouldShow){loadingDialog();}}else{loadingDialog();}});
	$j('form.submitOnceCond').submit(function(){if(submitOnce_shouldShow){loadingDialog()}});
	
	$j('a.popWin').click(function(){
		var winURL = $j(this).attr('href');
		window.open(winURL);
		return false;
	});
	//$j( 'div#statsBuddy table' ).addClass('tableToGrid');

	//jQgrid convert table to grid...
	//tableToGrid('.tableToGrid', {altRows: true, altclass: 'alt', width: "100%",height: "200", scrollOffset:0, pager: '#pagernav'});

	//These functions create a button next to an input classed with 'massFill' that will copy the value from that input to all inputs in that column
	$j('input.massFill').live('focus', function(){
		var button = $j(this).siblings().filter('button.btnMassFill');
		if (button.length === 0){
			$j(this).parent().append('<button type="button" class="btnMassFill"><span>&nbsp</span></button>');
		}
	});
	$j('button.btnMassFill').live('click', function(){
		var source = $j(this).siblings().filter('input').val();
		$j(this).parents('table').find('td:nth-child(' + ($j(this).parent().index() + 1) + ') input').val(source);
	});

	//initially implemented to open requestformpreview.html from admin portal
	if (getURLParameter('mode') == 'preview' && $j('#header a').length) {
		$j('#header a, #usercontext-bar a, #nav-main a').removeAttr('href');
		$j('#header a, #nav-main a').css('color', 'grey');
		$j('#userName span').css('text-decoration', 'line-through').css('color', 'gray');
		$j('#header a, #nav-main a, #tools2 a').removeClass();
	}
	$j.getScript("/scripts/jquery.cookie.js", function () {'use strict'; initUIControls(); }); //Commenting this one line disables the left nav show/hide functionality

/*End DOC Ready*/
});

//Frame nav, and Left nav hide: 
function setUICookie(cookie, state) { // sets cookie for nav state
	'use strict';
	$j.cookie(cookie, state, { path: '/', expires: 1 });
}
var frameSet = $j('#frameSet', top.document);
function frameStatus(s) {
    'use strict';
	if (s === 'off') {
		frameSet.attr('cols', '0,*');
	} else if (s === 'on') {
		frameSet.attr('cols', '208,*');
				}
		}
function uiStateSet(ui, title, cookie, state, frame) { // collapse code
	setUICookie(cookie, state);
	if (state === 'expanded') {
		$j('body').addClass('ui' + ui); //ui = NoNav, Max
		frameSet.addClass('ui' + ui);
		$j('#btn' + ui).addClass('expanded').removeClass('collapsed');
		$j('#btn' + ui).attr({'title': title});
	} else if (state === null) {
		$j('body').removeClass('ui' + ui);
		frameSet.removeClass('ui' + ui);
		$j('#btn' + ui).removeClass('expanded').addClass('collapsed');
		$j('#btn' + ui).attr({'title': title});
	}
	frameStatus(frame);
		}
function initUIControls() {
	var btnNoNavExpTxt = pss_text('psx.js.scripts.psbehaviors.show_main_menu'),
		btnNoNavTxt = pss_text('psx.js.scripts.psbehaviors.hide_main_menu'),
		btnContMaxExpTxt = pss_text('psx.js.scripts.psbehaviors.show_header'),
		btnContMaxTxt = pss_text('psx.js.scripts.psbehaviors.hide_header'),
		btnNoNav = $j('<div id="btnNoNav" class="collapsed" title="' + btnNoNavTxt + '"><em>&nbsp;</em></div>'),
		btnContMax = $j('<div id="btnContMax" class="collapsed" title="' + btnContMaxExpTxt + '"><em>&nbsp;</em></div>');
	if ($j('#btnNoNav', top.document).length === 0) { // inject NoNav button that toggles left nav
		$j('#content-main').prepend(btnNoNav); // instantiate NoNav
		}
	if ($j('#btnContMax', top.document).length === 0) {
		$j('#content-main, #content-lunch').prepend(btnContMax); // instantiate
			}
	if ($j.cookie('uiStateNav') === 'expanded') { // checks cookie and set state of left nav
		uiStateSet('NoNav', btnNoNavExpTxt, 'uiStateNav', 'expanded', 'off');//uiStateSet(ui, title, cookie, state, frame)
	} else {
		uiStateSet('NoNav', btnNoNavTxt, 'uiStateNav', null, 'on');
		}
	if ($j.cookie('uiStateCont') === 'expanded') {
		uiStateSet('ContMax', btnContMaxExpTxt, 'uiStateCont', 'expanded');
	} else {
		uiStateSet('ContMax', btnContMaxTxt, 'uiStateCont', null);
		}
	btnNoNav.click(function () {
		if ($j.cookie('uiStateNav') === 'expanded') {
			uiStateSet('NoNav', btnNoNavTxt, 'uiStateNav', null, 'on');
			} else {
			uiStateSet('NoNav', btnNoNavExpTxt, 'uiStateNav', 'expanded', 'off');
			}
		});
	btnContMax.click(function () {
		if ($j.cookie('uiStateCont') === 'expanded') {
			uiStateSet('ContMax', btnContMaxTxt, 'uiStateCont', null);
		} else {
			uiStateSet('ContMax', btnContMaxExpTxt, 'uiStateCont', 'expanded');
	}
	});
}
//End frame nav, and Left nav hide
/* ------------------------------------------------------
JS for inserting the selected field list item into the 
HTML object value, aka INPUT/TEXTAREA tag.

Parameters:
		inputObjName: ID of HTML object to have item inserted into.
		insertValue: The value to be inserted.
		option: Any additional options, number value.
			* If negative, add ^() around the insert value.
			* If 99 or -99, then add a carriage return after insert value.
			* If 5 or -5, then replace the value, aka oldValue=insertValue.
------------------------------------------------------ */
function ads (inputObjName, insertValue, option) {
	var inputObject = document.getElementById(inputObjName),
		s = 0;
	
	// verify and convert option to an integer.
	option = parseInt(option);
	
	/* Check to add code tag around value... If negative, add code tag */
	if (option<0) {
		insertValue="^("+insertValue+")";
		option=((-1)*option);
	}

 if (document.selection) { /* IE */
 	inputObject.focus();
 	if (option==5) {
 		inputObject.value=insertValue;
 	} else if (option==99) {
 		document.selection.createRange().text=insertValue+"\n";
 	} else {
 		document.selection.createRange().text=insertValue;
 	}
	} else { /* Mozilla/Netscape */
		s = inputObject.selectionStart;
		
		var startValue = inputObject.value.substring(0, s),
			endValue = inputObject.value.substring(s),
			insertReturn="";

		/* Replace the oldValue with insertValue */
		if (option==5) {
			inputObject.value=insertValue;
			startValue='';
			endValue='';
		}
		/* Check to add carriage return after value... */
		if ( (option==99) && endValue.substring(0, 1)!="\n" ) {
			insertReturn="\n";
		} 
		/* Check for carriage return between startValue and endValue */
		if (endValue.substring(0, 1)=="\n") {
			insertValue="\n"+insertValue;
		}
		
		insertValue=insertValue+insertReturn;
		inputObject.value = startValue+insertValue+endValue;
		
		setSelectionRange(inputObject,s+insertValue.length,s+insertValue.length);
	}
		
	oResizePanel.hide();
	/* oResizePanel.destroy(); */
	inputObject.focus(1);
}

/*FUTURE Scripts*/


//Nav-main injection--------------------*
//
//	function injectNavMain() { // inject nav-main wildcard into the top of frames based navigations
//	    'use strict';
//	    var navMainHeaderTxt = pss_text('psx.js.scripts.psbehaviors.main_navigation'),
//	    	navMainHeader = $j('<h3 id="navMainHeader" class="toggle collapsed">' + navMainHeaderTxt + '</h3>'),
//	    	navMainInject = $j('<div id="navMainInject"></div>'); // create container to inject nav-main into
//	    if ($j('#nav-main-frame').length !== 0 && $j('#navMainHeader').length === 0 && $j('#navMainInject').length === 0) { // check that they exist
//	        $j('#nav-main-frame').prepend(navMainHeader);
//	        navMainHeader.after(navMainInject); // instantiate the elements
//	        navMainInject.psLoad('/admin/admin_nav_main_inject.html', function () {
//	            $j('#nav-main a').attr('target', '_top'); // Makes nav-main wildcard links frames compatible
//	        });
//	        initToggle();
//	    }
//		}
//	if ($j('#frameSet', top.document).length !== 0) { //If frameset
//		injectNavMain(); //Inject nav-main into frames.
//		}
//end nav-main injection------------------*


//This function returns the TH on a clicked table cell
$j('td').click(function(){
var col = $j(this).prevAll().length;
var headerObj = $j(this).parents('table').find('th').eq(col);
// A quick test!
//alert("My cell header is called: " + headerObj.text());
});

//This function highlights the rows and columns when hovering over a cell
/*	$j("tr").hover(
		function() {
			$j(this).addClass('highlight');
			//too laggy	//$j(this).parentsUntil('table').find('td:nth-child(' + ($j(this).index() + 1) + ')').add($j(this).parent()).addClass('highlight');
      },
      function() {
			$j(this).removeClass('highlight');
			//too laggy	//$j(this).parentsUntil('table').find('td:nth-child(' + ($j(this).index() + 1) + ')').add($j(this).parent()).removeClass('highlight');
		});*/
 
/*$j("td").hover(
		function() {
			$j(this).parent().addClass('highlight');
		//too laggy	//$j(this).parentsUntil('table').find('td:nth-child(' + ($j(this).index() + 1) + ')').add($j(this).parent()).addClass('highlight');
      },
      function() {
   	  $j(this).parent().removeClass('highlight');
		//too laggy	//$j(this).parentsUntil('table').find('td:nth-child(' + ($j(this).index() + 1) + ')').add($j(this).parent()).removeClass('highlight');
		});*/
 

