/************************************************************************
 globals.js
 jpl 5/31/05
 
	Suite of general purpose JavaScript functions
	
	Data Validation:
		boolean	isInteger(stringValue)
		boolean	isPositiveInteger(stringValue)
		boolean	isNumeric(stringValue)
		boolean	isDate(stringValue)
		boolean	isValidEmailAddress(stringValue)
		boolean	isValidDomainName(stringValue)
	
	String Manipulation:
		int		countInStringMatches(theString, theTarget)
	
	Cookie Interaction:
		String	GetCookie(name)
		SetCookie(name, value)
	
	Window Opening:
		OpenWindow(URL, windowName, width, height,
				   horizontalPosition, verticalPosition)
	
	
	
************************************************************************/

function isArray(a) {
    return isObject(a) && a.constructor == Array;
}

function isBoolean(a) {
    return typeof a == 'boolean';
}

function isEmpty(o) {
    var i, v;
    if (isObject(o)) {
        for (i in o) {
            v = o[i];
            if (isUndefined(v) && isFunction(v)) {
                return false;
            }
        }
    }
    return true;
}

function isFunction(a) {
    return typeof a == 'function';
}

function isNull(a) {
    return typeof a == 'object' && !a;
}

function isNumber(a) {
    return typeof a == 'number' && isFinite(a);
}

function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
}

function isString(a) {
    return typeof a == 'string';
}

function isUndefined(a) {
    return typeof a == 'undefined';
} 

function isInteger(stringValue) {
	if (isString(stringValue)) {
		return stringValue.match(/^-?\d+$/);
	}
	return String(stringValue).match(/^-?\d+$/);
}

function isPositiveInteger(stringValue) {
	return stringValue.match(/^\d+$/);
}

function isNumeric(stringValue) {
	return stringValue.match(/^-?\d*(\.)?\d+$/);
}

function isValidEmailAddress(stringValue) {
	return stringValue.match(/^(\w|-|_|\.)+@(\w|-|_|\.){3,}\.\w{2,5}$/)
}

function isValidDomainName(stringValue) {
	return stringValue.match(/(\w|-|_|\.){3,}\.\w{2,5}$/)
}

function properNumber(value, badReturnValue) {
	if (isString(value)) {
		if(isNumeric(value))
			return Number(value);
	}
	else if(isNumber(value)) {
		return value;
	}
	else
		return badReturnValue;
}


function properInt(value, badReturnValue) {
	if (isString(value)) {
		if(isInteger(value))
			return Number(value);
	}
	else if(isNumber(value)) {
		return parseInt(value);
	}
	else
		return badReturnValue;
}


	function formatNumber(num,decimalNum,bolLeadingZero,bolParens,bolCommas){
	
		if (isNaN(parseInt(num))) {
			alert("Can't format " + num + "!");
			return "NaN";
		}
		
		var tmpNum = num;
		var iSign = num < 0 ? -1 : 1;		// Get sign of number
		
		// Adjust number so only the specified number of numbers after
		// the decimal point are shown.
		tmpNum *= Math.pow(10,decimalNum);
		tmpNum = Math.round(Math.abs(tmpNum))
		tmpNum /= Math.pow(10,decimalNum);
		tmpNum *= iSign;					// Readjust for sign
		
		
		// Create a string object to do our formatting on
		var tmpNumStr = new String(tmpNum);
	
		// See if we need to strip out the leading zero or not.
		if (!bolLeadingZero && num < 1 && num > -1 && num != 0)
			if (num > 0)
				tmpNumStr = tmpNumStr.substring(1,tmpNumStr.length);
			else
				tmpNumStr = "-" + tmpNumStr.substring(2,tmpNumStr.length);
			
		// See if we need to put in the commas
		if (bolCommas && (num >= 1000 || num <= -1000)) {
			var iStart = tmpNumStr.indexOf(".");
			if (iStart < 0)
				iStart = tmpNumStr.length;
	
			iStart -= 3;
			while (iStart >= 1) {
				tmpNumStr = tmpNumStr.substring(0,iStart) + "," + tmpNumStr.substring(iStart,tmpNumStr.length)
				iStart -= 3;
			}		
		}
		
		// See if we need to add trailing zeros:
		if (decimalNum > 0) {
			if (tmpNumStr.indexOf(".") == -1) {  // no decimal at all, must append w/ trailing zeros
				tmpNumStr = tmpNumStr + ".";
				for (var i = 0; i < decimalNum; i++)
					tmpNumStr = tmpNumStr + "0";
			}
			else { // we may need to append trailing zeros
				var decimalDeficit = decimalNum - (tmpNumStr.length - tmpNumStr.indexOf("."))+1;
				for (var i = 0; i < decimalDeficit; i++)
					tmpNumStr = tmpNumStr + "0";
			}
	
		}
		
		// See if we need to use parenthesis
		if (bolParens && num < 0)
			tmpNumStr = "(" + tmpNumStr.substring(1,tmpNumStr.length) + ")";
	
		return tmpNumStr;		// Return our formatted string!
	}


	function multiSelectHasSelectionMade(theSelect) {
		for (var i = 0; i < theSelect.options.length; i++) {
			if (theSelect.options[i].selected)
				return true;
		}
		return false;
	}


	function selectAllOfMultiSelect(theSelect) {
		for (var i = 0; i < theSelect.options.length; i++) {
			theSelect.options[i].selected = true;
		}
		return true;
	}
	
	function countInStringMatches(theString, theTarget) {
		
		var index = 0;
		var findCount = 0;
		while (index >= 0) {
			index = theString.indexOf(theTarget, index)
			if (index >= 0) {
				findCount++;
				index++;
			}
		}
		return findCount;
	}
	
	
	function reverse(string){
		returnString = '';
		for (i = string.length; i >= 0; i--)
			returnString += string.charAt(i);
		return returnString;
	}

	// left is just a rename of substring()
	function left(string, count){
		return string.substring(0, count);
	}

	// right actually uses reverse() and left()
	function right(string, count){
		return reverse(left(reverse(string), count));
	}


	function rtrim(string) {
		return string.replace(/\s+$/,'');
	}
	function ltrim(string){
		return string.replace(/^\s+/,'');
	}
	function trim(string){
		return ltrim(rtrim(string));
	}
	
	function ucase(string){
		return string.toUpperCase();
	}
	function lcase(string){
		return string.toLowerCase();
	}


/**
 * DHTML date validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 *
 * Modified 12/20/2003 by John Larson to allow MM/DD and MM/DD/YY format in addition to
 * MM/DD/YYYY already implemented.
 */
// Declaring valid date character, minimum year and maximum year
var dtCh= "/";
var minYear=1900;
var maxYear=2100;

function stripCharsInBag(s, bag){
	var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++){   
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

function extractCharsInBag(s, bag){
	var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is in bag, append to returnString.
    for (i = 0; i < s.length; i++){   
        var c = s.charAt(i);
        if (bag.indexOf(c) != -1) returnString += c;
    }
    return returnString;
}

function daysInFebruary (year){
	// February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}
function DaysArray(n) {
	for (var i = 1; i <= n; i++) {
		this[i] = 31
		if (i==4 || i==6 || i==9 || i==11) {this[i] = 30}
		if (i==2) {this[i] = 29}
   } 
   return this
}

function isDate(dtStr){
	var daysInMonth = DaysArray(12)
	var pos1=dtStr.indexOf(dtCh)
	var pos2=dtStr.indexOf(dtCh,pos1+1)
	var strMonth=dtStr.substring(0,pos1)
	var strDay=dtStr.substring(pos1+1,pos2)
	var strYear=dtStr.substring(pos2+1)

	var strTodaysYear = new String(new Date().getFullYear());
	if (pos2 < 0) // no year given, so assume this year
		strYr = strTodaysYear;
	else if (strYear.length == 2) // assume only last two digits given, so append first two
		strYr = strTodaysYear.substring(0, 2) + strYear;
	else if (strYear.length == 4) // standard format.
		strYr=strYear
	else
		return false;  // bad year

	if (strDay.charAt(0)=="0" && strDay.length>1) strDay=strDay.substring(1)
	if (strMonth.charAt(0)=="0" && strMonth.length>1) strMonth=strMonth.substring(1)
	for (var i = 1; i <= 3; i++) {
		if (strYr.charAt(0)=="0" && strYr.length>1) strYr=strYr.substring(1)
	}
	month=parseInt(strMonth)
	day=parseInt(strDay)
	year=parseInt(strYr)

	if (pos1==-1){
		//alert("The date format should be : mm/dd/yyyy")
		return false
	}
	if (strMonth.length<1 || month<1 || month>12){
		//alert("Please enter a valid month")
		return false
	}
	if (strDay.length<1 || day<1 || day>31 ||
      (month==2 && day>daysInFebruary(year)) || day > daysInMonth[month]){
		//alert("Please enter a valid day")
		return false
	}
	if (year<minYear || year>maxYear){
		//alert("Please enter a valid 4 digit year between "+minYear+" and "+maxYear)
		return false
	}
	if (!isInteger(stripCharsInBag(dtStr, dtCh))) {
		alert("Please enter a valid date")
		return false
	}
	return true
}














function getCookieVal (offset) 
   {
   var endstr = document.cookie.indexOf (";", offset);
   if (endstr == -1)
      endstr = document.cookie.length;
   return unescape(document.cookie.substring(offset, endstr));
   }

function GetCookie(name) {
   var arg = name + "=";
   var alen = arg.length;
   var clen = document.cookie.length;
   var i = 0;
   while (i < clen) 
      {
      var j = i + alen;
      if (document.cookie.substring(i, j) == arg)
         return getCookieVal (j);
      i = document.cookie.indexOf(" ", i) + 1;
      if (i == 0) break; 
      }
   return null;
}

function SetCookie(name, value) {
   var argv = SetCookie.arguments;
   var argc = SetCookie.arguments.length;
   var expires = (argc > 2) ? argv[2] : null;
   var path = (argc > 3) ? argv[3] : null;
   var domain = (argc > 4) ? argv[4] : null;
   var secure = (argc > 5) ? argv[5] : false;
   document.cookie = name + "=" + escape (value) +
        ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
        ((path == null) ? "" : ("; path=" + path)) +
        ((domain == null) ? "" : ("; domain=" + domain)) +
        ((secure == true) ? "; secure" : "");
}
















function OpenWindow(URL, windowName, width, height, horizontalPosition, verticalPosition) {

	var xOffset, yOffset;
	// The biggest task we have is to determine the x and y offsets for positioning
	// this pop up window.  This will be determined by horizontalPosition and
	// verticalPosition, which we'll let come in either as a percentage or
	// straight pixel amount.
	
	if (horizontalPosition.substring(horizontalPosition.length-1, horizontalPosition.length) == "%") {
		// horizontal position given to us as a percentage
		var horizontalPercentage = horizontalPosition.substring(0, horizontalPosition.length-1)
		
	    if (document.all)  // MSIE
	        var xMax = screen.width;
	    else {
	        if (document.layers) // NN
	            var xMax = window.outerWidth;
	        else // dunno, so we'll guess a 600x800 resolution:
	            var xMax = 800;
	    }
		xOffset = (xMax - width)*(horizontalPercentage/100);
	}
	else // we've been given a straight amount in pixels
		xOffset = horizontalPosition;
	    
	
	
	if (verticalPosition.substring(verticalPosition.length-1, verticalPosition.length) == "%") {
		// vertical position given to us as a percentage
		var verticalPercentage = verticalPosition.substring(0, verticalPosition.length-1)
		
	    if (document.all)  // MSIE
	        var yMax = screen.height;
	    else {
	        if (document.layers) // NN
	            var yMax = window.outerHeight;
	        else // dunno, so we'll guess a 600x800 resolution:
	            var yMax = 600;
	    }
		yOffset = ((yMax-25)- height)*(verticalPercentage/100); // -25 for the task bar probably there
	}
	else // we've been given a straight amount in pixels
		yOffset = verticalPosition;


	

	window.open(URL, windowName,
	            'Height=' + height  + 'px, ' +
	            'Width='  + width   + 'px, ' +
				'left='   + xOffset + 'px, ' +
				'top='    + yOffset + 'px, ' +
				'center=1, help=0, status=1, scrollbars=1, resizable=1');
}





function attributeDiagnostic(element)
{
	var attributes = element.attributes;
	var i = 0;
	var display = ""
	for (var item in attributes) {
		display = display + item + ": " + element.getAttribute(item) + "\n";
		
		i++;
		
		if (i >= 35) { // clear out to make room
			alert("Attributes:\n" + display);
			display = ""
			i = 0;
		}
	}
		
	if (display != "")
		alert("Attributes:\n" + display);
}



//////////////////////////////////////////////////////
// Collapsing/Expanding Elements:
	function expandIt(whichEl) {
		
		if (isString(whichEl)) {
			whichEl = document.getElementById(whichEl);
		}

		if (whichEl.style)
			whichEl.style.display = (whichEl.style.display == "none" ) ? "" : "none";
	}

	
	function expandItDeluxe(arrowImage, whichEl) {
	
		if (isString(whichEl)) {
			whichEl = document.getElementById(whichEl);
		}
		
		if (whichEl.style) {
			whichEl.style.display = (whichEl.style.display == "none" ) ? "" : "none";
			arrowImage.src = "images/arrow_" + ((whichEl.style.display == "none" ) ? "right" : "down") + ".gif"
		}
	}

	function toggleRowSetVisibility(rowSetName) {
		var toggleRows= document.getElementsByName(rowSetName);
		for (var i = 0; i < toggleRows.length; i++) {
			expandIt(toggleRows[i])
		}
	}

	function toggleRowSetVisibilityDeluxe(arrowImage, rowSetName) {
		var toggleRows= document.getElementsByName(rowSetName);

		for (var i = 0; i < toggleRows.length; i++) {
			expandIt(toggleRows[i])
		}
		// toggle the arrow based on the first row:
		arrowImage.src = "images/arrow_" + ((toggleRows[0].style.display == "none" ) ? "right" : "down") + ".gif"

	}
//////////////////////////////////////////////////////




	function getCheckBoxSetNetValue(theCheckboxSet) {
		var result = '';
		if (theCheckboxSet.length) {
			for (i = 0; i < theCheckboxSet.length; i++) {
				if (theCheckboxSet[i].checked)
					result += theCheckboxSet[i].value + ', ';
			}
			
			if (result.length >= 2) // trim the trailing ', ':
				result = result.substring(0, result.length-2);
		}
		else {
			if (theCheckboxSet.checked)
				result = theCheckboxSet.value;
			else
				result = '';
		}
		
		return result;
	}