function Util() {
}
var Util = new Util();

$(document).ready(function() {	
	$(document).click(function(event) {
		// if the popup is open and they click outside it, close it; if they click on the "divOutsidePopup" div then close the popup
		if (event.target.id == 'divOutsidePopup') {
			if (!Util.isModalPopup) { 
				Util.closePopup();
			}
			return;			
		}
		return;		
	});
	
	$(document).keypress(function(event) {
	  try {
		var code = (event.keyCode ? event.keyCode : event.which); 
		if (code==27) { // ESC
			if (!Util.isModalPopup) { 
				Util.closePopup();
			}
			return;			
		}
		
	  } catch(e) {}
	});
});


Util.selectRadio = function(radioName,valueToPick) {
	var radioArray = document.forms['frmMain'][radioName];
	for (var x=0;x<radioArray.length;x++) {
		if (radioArray[x].value==valueToPick) {
			radioArray[x].checked=true;
			return;
		}
	}
	return;
}

//function to return the value of the checked radio button
Util.getSelectedRadio = function(radioName, theForm) {
	if (theForm == null) {
		theForm = eval('document.forms[0]');
	}
	var radioArray = theForm[radioName];
	// if there are multiple radios, they will be in an array
	if (typeof(radioArray.length) == 'undefined') {
		return radioArray.value;
	}
	for (var x=0;x<radioArray.length;x++) {
		if (radioArray[x].checked == true)
		{
			return radioArray[x].value;
		}
	}
	return '';
}

Util.checkUncheckAllCheckboxes = function(strName, bUncheck, theForm) {
	if (theForm == null) {
		theForm = eval('document.forms[0]');
	}
	var checkArray = theForm[strName];
	if (typeof(checkArray) == 'undefined') {
		return;
	}
	if (typeof(checkArray.length) == 'undefined') {
		checkArray.checked = bUncheck;
		return;
	} else {
		for (var x=0;x<checkArray.length;x++) {
			checkArray[x].checked = bUncheck;
		}
		return;
	}
}


Util.showSelectedOption = function(theSelect,valueToSelect) {
	var length=theSelect.length;
	for (var i=0;i<length;i++) {
		if (theSelect.options[i].value==valueToSelect) {
			theSelect.selectedIndex = i;//options[i].selected=true;
			return;
		}
	}
}

/****************************************************************************************
 * Function     - Function to populate a select with ref data options with a matching parent
 *                Removes all options starting with the indexToRemoveFrom, in case
 *                there's a 'select one' option or something
 * return       - Nothing
 ****************************************************************************************/
Util.populateFilteredRefData = function(type,theSelect,parentId,indexToRemoveFrom) {
    var theArray = allRefData[type];
    if (parentId == null)
        parentId = '';
    if (parentId==null || parentId=='')
        return;
    if (theArray == null) {
        return;
    }
    var arrSize = theArray.length;

    theSelect.options.length=indexToRemoveFrom;
    var theIndex = indexToRemoveFrom;
    for (x in theArray) {
        if (theArray[x].parentId == parentId) {
            theSelect.options[theIndex++] = new Option(theArray[x].desc,theArray[x].id);
        }
    }
}

Util.escapeQuote = function(strVar) {
	return strVar.replace('\'','\\\'');
}

Util.clearCommasFromNumber = function(objInput) {
	if (objInput !== undefined && objInput.value !== undefined) {
		objInput.value = objInput.value.replace(',','');
		objInput.value = objInput.value.replace('$','');
	}
	return true;
}

Util.hexChars = '0123456789abcdef';

Util.checkTextInTextareas = function() {
	for(i=0; i<document.forms[0].elements.length; i++) {
		if(document.forms[0].elements[i].type=="textarea") {
			document.forms[0].elements[i].value=Util.stringToUnicode(document.forms[0].elements[i].value);
		}
	}
}

Util.stringToUnicode = function(str) {
	convStr = '';
	for (var x = 0;x<str.length;x++) {
		convStr += Util.charToUni(str.charCodeAt(x));
	}
	return convStr;
}

Util.getHex = function(i) {
	return Util.hexChars.charAt(i & 0x0f);
}

Util.hexVal = function(v) {
	return Util.getHex(v >>> 12) + Util.getHex(v >>> 8) + Util.getHex(v >>> 4) + Util.getHex(v);
}

Util.charToUni = function(ch) {
	switch(ch) {
	case 9:
		return ' ';    	
	case 10:
		return '\n';    	
	case 13:
		return '\r';
	case 8211:
		return '-';
	case 8220:
	case 8221:
		return '"';
		break;
	case 8217:
		return "'";
		break;
	case 8226:
		return '-';
		break;
	case 8230:
		return '...';
		break;
	default:
    	return String.fromCharCode(ch);
    	break;
		
	/*
		if (ch < 32 || ch > 126) {
			//alert('check this one!! ' + ch + ': ' + String.fromCharCode(ch) + '!');
			return "\\u" + Util.hexVal(ch);
		}
		else 
			return String.fromCharCode(ch);
	*/
//	alert('ch: ' + ch + ': ' + String.fromCharCode(ch));
//	return String.fromCharCode(ch);

	}
	return;
}


/**
* strWindowName: the target of the action
*/
Util.doAction = function(strAction,doValidation,strFormName,strWindowName) {
	if (strFormName === undefined) {
		strFormName = 'frmMain';
	}

	Util.clearErrors();
    Util.checkTextInTextareas();
    
    if (doValidation && !Validator.isFormValid()) {
    	$('.validationError').html(Validator.errorMessage).show();
        return;
    }
	if (strAction != null) {
		// could just want the default action
		document.forms[strFormName].action=strAction;
	}
    if (strWindowName) {
    	document.forms[strFormName].target=strWindowName;
    }
    document.forms[strFormName].submit();
}


Util.submitFormOnEnter = function(event, functionToCall) {
	if (functionToCall == null || typeof(functionToCall) == 'undefined') {
		return;
	}
	var code = 0;
	if (NS4) {
		code = event.which;
	} else {
		code = event.keyCode;
	}
	if (code==13) {
		eval(functionToCall);
	}
}

/**
* The jquery one doesn't handle the case where it's ie 6.01+ and using loose.dtd, always returns 0
*/
Util.scrollTop = function() {
  if (document.documentElement && document.documentElement.scrollTop) {
  	return document.documentElement.scrollTop;
  } else {
	return $(document).scrollTop();
  }
}

Util.addRandomToURL = function(strParamString) {
	return ('date=' + new Date().getTime() + '&' + strParamString); 
}

Util.onAjaxError = function(XMLHttpRequest, textStatus, errorThrown) {
	//alert('error, http: ' + XMLHttpRequest + ' status: ' + textStatus + ' error: ' + errorThrown);	
	// typically only one of textStatus or errorThrown will have info
	Util.showPopup('/pub/ajaxError',300);
}	

Util.formToString = function(objForm) {
	//alert(objForm.outerHTML);
	var strData = '';
    for (var x=0;x<objForm.elements.length;x++) {
    	strData += Util.formElementToString(objForm.elements[x]);
    	if (x < (objForm.elements.length-1)) {
			strData += '&';
		}
		/* select-one select-multiple textarea button checkbox radio file hidden image password hidden reset submit text */		
	}
	return strData;
}

Util.formElementToString = function(objFormElement) {
	var strData = '';
	if (objFormElement.type == 'checkbox' || objFormElement.type == 'radio') {
		//strData += objFormElement.name + '=' + (objFormElement.checked ? objFormElement.value : '');
		if (objFormElement.checked) strData += objFormElement.name + '=' + objFormElement.value;
	} else if (objFormElement.type == 'hidden' || objFormElement.type == 'text' || objFormElement.type == 'textarea' || objFormElement.type == 'password') {
		strData += objFormElement.name + '=' + objFormElement.value;
	} else if (objFormElement.type == 'select-one') {
		strData += objFormElement.name + '=' + objFormElement.options[objFormElement.selectedIndex].value;
	} else if (objFormElement.type == 'select-multiple') {
		for (var opt=0;opt<objFormElement.options.length;opt++) {
			if (objFormElement.options[opt].selected) {
				if (strData != '') {
					strData += '&';
				}
				strData += objFormElement.name + '=' + objFormElement.options[opt].value;
			}
		}					
	} else {
		alert('Need to finish the Form function synchFieldsWithOriginalUI to handle type: ' + objFormElement.type + '!');
	}
	return strData;
}

/**
* called when an inline popup opens, init the stuff inside the popup
*/ 
Util.initPopupForm = function(fnToCall) {
	$('#modalDiv form').keypress(function(event) {
	  try {
		var code = (event.keyCode ? event.keyCode : event.which); 
		if (code==13) { // ENTER
			//alert('in keypress in the form; code: ' + code + ' form: ' + this);
			event.preventDefault();
			event.stopPropagation();
			//Util.submitForm({strFormName:this.name,bValidate:true,bPopup:true});
			fnToCall.call();			
			return;			
		}
		
	  } catch(e) {}
	});
}

Util.showPopup = function(strURL, intWidth, strDivName, bModal) {
	Util.closePopup();
	Validator.clearValidations({strFormName:'frmPopup'});			
	// show the modal grey screen
	// put in the box, hit the server between .  position the grey filter at document height-4, otherwise the page will start scrolling on ie
	var strHtml = 
	'<div id="modalDiv" style="position:absolute;width:100%;height:' + ($(document).height() - 4) + 'px;left:0;top:0;"><div id="divOutsidePopup" style="position:absolute;width:100%;height:100%;left:0;top:0;background-color:#666666;filter:alpha(opacity=50);-moz-opacity:.50;opacity:.50;"></div>' +
	'<div id="' + strDivName + '" style="position:absolute;text-align:center;left:' + (Math.round($('body').width()/2)-Math.round(intWidth/2)) + 'px;top:' + (Util.scrollTop() + 120) + 'px;width:' + intWidth + 'px;">' +
	'</div>' +
	'</div>';

	$('body').append(strHtml);	
	
	if (strURL != null) {	
		// now request page 1 for the screen, add the "ajax=true" to the request
		strURL += (strURL.indexOf('?') > 0 ? '&' : '?') + Util.addRandomToURL('ajax=true');
		$('#' + strDivName).load(strURL);
	}
	if (bModal) {
		Util.isModalPopup = true;		
	} else {
		Util.isModalPopup = false;
	}
}

Util.closePopup = function() {
  if ($('#modalDiv')) {
	$('#modalDiv').remove();
  }
}


/**
* called when a form is submitted using the enter button
*/
Util.onSubmitForm = function(objForm) {
	Util.submitForm({strFormName:objForm.name});
	return false;
}


/**
* objOptions can contain: strFormName, bValidate, bPopup, bAjax, strURL, fnOnInvalid, fnOnSuccess, fnClearErrors
* bPopup assumes that bAjax is true
* TODO: what if there are two forms going, wanting to validate the popup but not the lower one?  will have to address if it comes up, 
* add to the test or check "isPopup" or something
*/
Util.submitForm = function(objOptions) {
	if (objOptions === undefined) {
		objOptions = {};
	}
	if (objOptions.strFormName === undefined) {
		objOptions.strFormName = (objOptions.bPopup ? 'frmPopup' : 'frmMain');
	}
	if (objOptions.bValidate) {
		if (objOptions.fnClearErrors != undefined) {
			objOptions.fnClearErrors.call();
		}
		var bValid = true;
		//var strValidationMessage = 'Please complete the highlighted fields';
		// things to validate should already be registered with the validator, so can just call a validate() method
		// return if not validated	
		if (!Validator.isFormValid(objOptions.strFormName)) {
			objOptions.fnOnInvalid.call(this,Validator.errorMessage);
			return;
		}
	}
	
	var theForm = document.forms[objOptions.strFormName];
	var strURL = (objOptions.strURL === undefined ? theForm.action : objOptions.strURL); 
	if (objOptions.bPopup || objOptions.bAjax) {
		var strData = Util.formToString(theForm);
		strData += ((strData == '' ? '' : '&') + Util.addRandomToURL('ajax=true')); 		
		var fnOnSuccess = (objOptions.fnOnSuccess == undefined ? 
			function(html) {
				$('#modalDiv:firstChild').html(html);
			} : objOptions.fnOnSuccess);
		var fnOnError = (objOptions.fnOnError == undefined ? 
			function(XMLHttpRequest, textStatus, errorThrown) {
				Util.onAjaxError(XMLHttpRequest, textStatus, errorThrown);
			} : objOptions.fnOnError);

		$.ajax({type: 'POST',	
			url: strURL,
			data: strData,
			success: fnOnSuccess,
			error: fnOnError
		});
		
	} else {
		theForm.action = strURL;
		theForm.submit();
		// not a popup, just submit the form	
	}
}

Util.clearErrors = function(bPopup) {
//alert('in clear errors');

	if (bPopup) {
		$('#modalDiv .form .error').removeClass('error');
		$('.divErrorPopup').hide();
	} else {
		$('#contentDiv .form .error').removeClass('error');
		$('.divError').hide();	
		//TODO: be consistent
		$('.frmMain .error').removeClass('error');
		$('.validationError').hide();
	}
}

Util.copyBodyToClipboard = function() {
	clipboardData.setData('Text', $('body').html());
	return;
}

Util.getPosition = function(objTarget) {
	var curleft = 0 + $(objTarget).offset().left;
	var curtop = 0 + $(objTarget).offset().top;
	return {x:curleft,y:curtop};
}

Util.showTab = function(whichTabGroup,whichTab) {
	$('#'+whichTabGroup+' .tabOn').removeClass('tabOn');
	$('#'+whichTabGroup+' #tab' + whichTab).addClass('tabOn'); 
	$('#'+whichTabGroup+' .tabBody').hide();
	$('#'+whichTabGroup+' #tabBody' + whichTab).show();
	//tabsSameHeight(whichTabGroup); // since the content of the tab can change as you view it, ex. by clicking to view the detail
}

/**
 * Pops up a confirmation box with "yes" and "no" instead of "ok" and "cancel"
 * strMessage: the text to display
 * fnOnYes: fn to call when they click the "yes" button
 * fnOnNo: fn to call when they click the "no" button
 */
Util.confirm = function(strMessage, fnOnYes, fnOnNo, bDontCloseWindow) {	
	Util.bDontCloseWindow=bDontCloseWindow;
	//alert('dont close: ' + bDontCloseWindow + '!' + Util.bDontCloseWindow);
	if (fnOnNo === undefined) {
		fnOnNo = function() {} // do nothing, the popup will close
	}
	Util.fnOnNo = fnOnNo;
	Util.fnOnYes = fnOnYes;
	
	var strHtml = 
	'<div class="popupShadow" style="width:420px;">' +
		'<div class="popupTitle"><div style="text-align:center;margin:14px;">Confirm</div></div>' +
		'<div style="padding:10px;text-align:left;background-color:#fff;font-size:1.2em;">' +
			strMessage +
		'</div>' +	
		'<div class="bottomButtonDiv" style="text-align:center;">' +	
			'<a onclick="javascript:Util.onConfirm(\'yes\')" class="adminLink" style="margin-right:25px;">Yes</a>' +	
			'<a onclick="javascript:Util.onConfirm(\'no\')" class="adminLink">No</a>' +	
		'</div>' +
	'</div>';	
	
	Util.showPopup(null, 420, 'popupConfirm', true);
	$('#popupConfirm').html(strHtml);
}

/**
* added the optional bCloseWindow in case need to confirm multiple things, don't want one closing the next one
*/
Util.onConfirm = function(strParam,bDontCloseWindow) {
	if ('yes' == strParam) {
		this.fnOnYes.call();
	} else {
		this.fnOnNo.call();
	}
	if (!Util.bDontCloseWindow) {
		Util.closePopup();
	}
}


Util.getCookie = function(strCookieName){
  if (document.cookie.length > 0){
	c_start = document.cookie.indexOf(strCookieName + "=");
	if (c_start != -1) { 
	  c_start = c_start + strCookieName.length + 1; 
	  c_end = document.cookie.indexOf(";",c_start);
	  if (c_end == -1) {
	  	c_end = document.cookie.length;
	  }
		return unescape(document.cookie.substring(c_start,c_end));
	} 
  }
  return '';
}

Util.setCookie = function(strCookieName,value,expiredays) {
  //if (!Util.getCookie(strCookieName)) {
	var exdate = new Date();
	exdate.setDate(exdate.getDate()+expiredays);
	document.cookie = strCookieName + '=' +escape(value)+((expiredays==null) ? '' : ';expires='+exdate.toGMTString());
  //}
}

Util.deleteCookie = function(strCookieName) {
  if (Util.getCookie(strCookieName)) {
	document.cookie = strCookieName + '=;expires=Thu, 01-Jan-70 00:00:01 GMT';
  }
}

/**
* given a string in the format mm/dd/yyyy returns a date object
*/
Util.parseDate = function(strDate) {
    if (!(
    	strDate.match(/^[0-9][0-9]?-[0-9][0-9]?-[0-9]+$/) || 
    	strDate.match(/^[0-9][0-9]?\/[0-9][0-9]?\/[0-9]+$/)
    	)) {
        return null;
    }
    var delim = (strDate.indexOf('-') > 0 ? '-' : '/');
    var arrDate = strDate.split(delim);
    try {
    	var month = parseInt(arrDate[0],10);
    	var day = parseInt(arrDate[1],10);
    	var year = parseInt(arrDate[2],10);
    	var theDate = new Date(year,month,day);
    	return theDate;
    } catch(err) {
    	return null;
    }
}

/**
* given a date object, returns a formatted string mm/dd/yyyy
*/
Util.formatDate = function(objDate) {
	return (objDate.getMonth() < 10 ? '0' : '') + objDate.getMonth() + (objDate.getDate() < 10 ? '/0' : '/') + objDate.getDate() + '/' + objDate.getFullYear();
}

Util.escapeStringForJQuery = function(str) {
	return str.replace(/\./g,'\\.').replace(/\[/g,'\\[').replace(/\]/g,'\\]').replace(/\_/g,'\\_');
}	

/**
* update the sort order of a row of something, pass in:
* upOrDown: 'UP' or 'DOWN'
* strLabel: string used in the html id's to identify these pieces, ex. 'menuItem'
* strId: the primary key of the object in the row to move (usually an int)
*/
Util.reorderItem = function(strLabel, upOrDown, strId) {
	var trItem = $('#'+strLabel+'_' + strId + '_tr');
	var hdnSortOrder = $('#'+strLabel+'_' + strId + '_sortOrder');
	var theSib = (upOrDown == 'UP' ? trItem.prev() : trItem.next()); // get the row above or below
	if (theSib === undefined || theSib[0] == undefined || theSib[0].id === undefined || theSib[0].id.indexOf(strLabel+'_') < 0) {
		return;
	}
	var theSibId = theSib[0].id.replace(strLabel+'_','').replace('_tr','');
	trItem.replaceWith('');
	if (upOrDown == 'UP') {
		trItem.insertBefore(theSib);
	} else {
		trItem.insertAfter(theSib);
	}
	
	// now update the sort orders, swap the values of the current row and the sib
	var sortOrderMenuItem = $('#'+strLabel+'_' + strId + '_sortOrder').val();
	$('#'+strLabel+'_' + strId + '_sortOrder').val($('#'+strLabel+'_' + theSibId + '_sortOrder').val());
	$('#'+strLabel+'_' + theSibId + '_sortOrder').val(sortOrderMenuItem);
}