var alphanumchars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzƒŠŒšœŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ0123456789';
var alphachars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzƒŠŒšœŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþ';
var numchars = '0123456789';

/**
 * BROWSER DETECTION
 *
 *  Note: On IE5, these return 4, so use is_ie5up to detect IE5.
 */
var agt = navigator.userAgent.toLowerCase();

var is_major = parseInt(navigator.appVersion);
var is_minor = parseFloat(navigator.appVersion);
var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible') == -1));
var is_nav2 = (is_nav && (is_major == 2));
var is_nav3 = (is_nav && (is_major == 3));
var is_nav4 = (is_nav && (is_major == 4));
var is_nav4up = (is_nav && (is_major >= 4));
var is_navonly = (is_nav && ((agt.indexOf(";nav") != -1) || (agt.indexOf("; nav") != -1)) );
var is_nav5 = (is_nav && (is_major == 5));
var is_nav5up = (is_nav && (is_major >= 5));
var is_ie   = (agt.indexOf("msie") != -1);
var is_ie3  = (is_ie && (is_major < 4));
var is_ie4  = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")==-1) );
var is_ie4up  = (is_ie  && (is_major >= 4));
var is_ie5  = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")!=-1) );
var is_ie5up  = (is_ie  && !is_ie3 && !is_ie4);

/**
 * GENERIC UTILITY FUNCTIONS
 */ 
function isEmpty(str) {
    return ((str == null) || (str == ''));
}

function focusFirstField(form) {
    for(var x = 0; x < form.elements.length; x++)
        if(form.elements[x].type != 'hidden')
            break;
    form.elements[x].focus();
}

/**
 * REGULAR EXPRESSIONS
 *
 *  BOI = Beginning Of Input, EOI = End Of Input
 *  For explanations of the regexp special characters such as
 *  ^ $ \s + [] \d * ! ? \ .
 *  see http://developer.netscape.com/library/documentation/communicator/jsguide/regexp.htm
 */ 

// BOI, followed by one or more whitespace characters, followed by EOI.
var reWhitespace = /^\s+$/
// BOI, followed by one lower or uppercase English letter, followed by EOI.
var reLetter = /^[a-zA-Z]$/
// BOI, followed by one or more lower or uppercase English letters, followed by EOI.
var reAlphabetic = /^[a-zA-Z]+$/
// BOI, followed by one or more lower or uppercase English letters or digits, followed by EOI.
var reAlphanumeric = /^[a-zA-Z0-9]+$/
// BOI, followed by one digit, followed by EOI.
var reDigit = /^\d/
// BOI, followed by one lower or uppercase English letter or digit, followed by EOI.
var reLetterOrDigit = /^([a-zA-Z]|\d)$/
// BOI, followed by one or more digits, followed by EOI.
var reInteger = /^\d+$/
// BOI, followed by one of these two patterns:
// (a) one or more digits, followed by ., followed by zero or more digits
// (b) zero or more digits, followed by ., followed by one or more digits
// ... followed by EOI.
var reFloat = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/
// BOI, followed by one or more characters, followed by @,
// followed by one or more characters, followed by ., 
// followed by one or more characters, followed by EOI.
var reEmail = /^.+\@.+\..+$/

/**
 * Validation Function Using Regular Expresssions
 */

function isInteger(s) {
    return reInteger.test(s);
}

function isFloat(s) {
    return reFloat.test(s);
}

function isWhitespace (s) {
    return reWhitespace.test(s);
}

function isValidEmail(s){
    return reEmail.test(s);
}

// Returns true if character c is a standard upper or lower letter
// ([a-zA-Z])
function isLetter (c) {
    return reLetter.test(c)
}

// Returns true if character c is a digit [0-9]
function isDigit (c) {
    return reDigit.test(c)
}

// Returns true if character c is a digit [0-9] or standard upper 
// or lower letter [a-zA-Z]
function isLetterOrDigit (c) {
    return reLetterOrDigit.test(c)
}

/**
 * MISC GENERIC FUNCTIONS
 */
function LTrim(str) {
    var s = new String(str);
    var whitespace = new String(' \t\n\r');

    // Strip all leading white-space characters
    if (whitespace.indexOf(s.charAt(0)) != -1) {

        var j=0, i = s.length;
    
        // Iterate from the left until we have no more whitespace...
        while (j < i && whitespace.indexOf(s.charAt(j)) != -1)
            j++;

        // Get the substring from the first non-whitespace 
        // character to the end of the string...
        s = s.substring(j, i);
    }
    return s;
}

function RTrim(str) {
    var s = new String(str);
    var whitespace = new String(' \t\n\r');

    // Strip all trailing white-space characters
    if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {

        var i = s.length - 1;

        // Iterate from the right until we have no more whitespace...
        while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1)
            i--;

        // Get the substring from the beginning of the string to
        // where the last non-whitespace character
        s = s.substring(0, i+1);
    }
    return s;
}

function Trim(str) {
    // Strip away all leading and trailing white-space characters
    return RTrim(LTrim(str));
}

function TrimAll(form) {
   // Trim() the text and hidden inputs values
    for(var x = 0; x < form.elements.length; x++) {
		if(form.elements[x].type == 'text' || form.elements[x].type == 'hidden') {
            form.elements[x].value = Trim(form.elements[x].value);
        }
    }
}

function isAlphanumeric(s, valid_chars) {
    var allValid = true;
    var ch = '';
    for (i = 0;  i < s.length;  i++) {
        ch = s.charAt(i);

    for (j = 0;  j < valid_chars.length;  j++)
        if (ch == valid_chars.charAt(j))
            break;
            if (j == valid_chars.length) {
                allValid = false;
                break;
            }
        }
        return allValid;
}

function bContainsValidChars(s, valid_chars) {
    var allValid = true;
    var ch = '';
    for (i = 0;  i < s.length;  i++) {
        ch = s.charAt(i);
        for (j = 0;  j < valid_chars.length;  j++)
            if (ch == valid_chars.charAt(j))
            break;
        if (j == valid_chars.length) {
            allValid = false;
            break;
        }
    }
    return allValid;
}

// Removes all characters which appear in string bag from string s.
function stripCharsInString (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++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }

    return returnString;
}

// Removes all characters which do NOT appear in string from string s.
function stripCharsNotInString (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++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) != -1) returnString += c;
    }

    return returnString;
}



// Removes all whitespace characters from sstring.
// Global variable whitespace (see above) defines which characters are considered whitespace.
function stripWhitespace (s) {
    return stripCharsInBag (s, whitespace)
}

function openWindow(Url, Handle, Target, Height, Width, Resize, Scroll, Status, Dirs, Location, Toolbar, Menubar) {
/****************************************** 
 *  Parameters:
 *   Url      - A string specifying the URL to open in the new window
 *   Handle   - reference to new Window object
 *   Target   - A string specifying the window name to use in the TARGET attribute 
 *              of a FORM or  tag; assumes alphanumeric or underscore characters
 *  (Window Features)
 *   Height   - Specifies the height of the window in pixels
 *   Width    - Specifies the width of the window in pixels
 *   Resize   - value of 1 allows a user to resize the window.
 *   Scroll   - value of 1 creates horizontal and vertical scrollbars
 *   Status   - value of 1 creates the status bar at the bottom of the window.
 *   Dir      - value of 1 creates the standard browser directory buttons (Netscape)
 *   Location - value of 1 creates a location entry field.
 *   Toolbar  - value of 1 creates the toolbar at the top of the window
 *   MenuBar  - value of 1 creates the menu at the top of the window
 ******************************************/
  var features = '';
  features += 'height=' + Height;
  features += ',width=' + Width;
  features += ',resizable=' + Resize;
  features += ',scrollbars=' + Scroll;
  features += ',status=' + Status;
  features += ',directories=' + Dirs;
  features += ',location=' + Location;
  features += ',toolbar=' + Toolbar;
  features += ',menubar=' + Menubar;
  if(screen != null) {
    if(is_nav) {
    // Netscape
    features += ',screenX=' + ((screen.availWidth/2) - (Width/2));
    features += ',screenY=' + ((screen.availHeight/2) - (Height/2));
    }
	if(is_ie) {
    // Internet Explorer
    features += ',left=' + (screen.availWidth - Width)/2;
    features += ',top='  + (screen.availHeight - Height)/2;
	}
  }

  Handle = window.open(Url, (Target=='')?'':Target, features);

  //Handle.moveTo((screen.availWidth - Width)/2, (screen.availHeight - Height)/2);
  if (Handle != null) {
    if (Handle.opener == null) {
       Handle.opener = self;
    }
    Handle.location.href = Url;
  }
}

function verifyCC(ccNumber, ccType, ccExpMonth, ccExpYear) {
    /*
    ==============================================================
    Type Of Card                    Prefix                  Length
    ==============================================================
    MASTERCARD                      51,52,53,54,55          16
    VISA                            4                       13,16
    AMEX                            34,37                   15
    DINER'S CLUB/CARTE BLANCHE      30,36,38                14
    DISCOVER                        6011                    16
    JCB                             3                       16
    JCB                             2131,1800               15
    ==============================================================
    */

    // convert it to a string...
    var msg = 'Invalid credit card number';
    
    // parse out any non-digit characters, including whitespace characters...
    var cc = ccNumber.toString();
    var prefix = '';
    switch(ccType.toUpperCase()) {
        case 'MASTERCARD':
            if(cc.length != 16) {
                alert(msg);
                return false;
            }
            prefix = cc.substring(0,2) // prefix = first two characters
            if(prefix != '51' && prefix != '52' && prefix != '53' && prefix != '54' && prefix != '55') {
                alert(msg);
                return false;
            }
            break;
        case 'VISA':
            if(cc.length != 13 && cc.length != 16) {
                alert(msg);
                return false;
            }
            prefix = cc.substring(0,1) // prefix = first character
            if(prefix != '4') {
                alert(msg);
                return false;
            }
            break;
        case 'AMEX':
        case 'AMERICAN EXPRESS':
            if(cc.length != 15) {
                alert(msg);
                return false;
            }
            prefix = cc.substring(0,2) // prefix = first two characters
            if(prefix != '34' && prefix != '37') {
                alert(msg);
                return false;
            }
            break;
        case 'DINERS':
        case 'CARTE BLANCHE':
            if(cc.length != 14) {
                alert(msg);
                return false;
            }
            prefix = cc.substring(0,2) // prefix = first two characters
            if(prefix != '30' && prefix != '36' && prefix != '38') {
                alert(msg);
                return false;
            }
            break;
        case 'DISCOVER':
            if(cc.length != 16) {
                alert(msg);
                return false;
            }
            prefix = cc.substring(0,4) // prefix = first two characters
            if(prefix != '6011') {
                alert(msg);
                return false;
            }
            break;
        case 'JCB':
            if(cc.length != 15 || cc.length != 16) {
                alert(msg);
                return false;
            }
            if(cc.length == 15) {
                prefix = cc.substring(0,5) // prefix = first 4 characters
                if(prefix != '6011') {
                    alert(msg);
                    return false;
                }
            } else {
                prefix = cc.substring(0,1) // prefix = first character
                if(prefix != '2131' && prefix != '1800') {
                    alert(msg);
                    return false;
                }
            }
            break;
        default:
            alert('Unknown Credit Card Type.');
            return false;
    }

    // does it pass the LUHN checK?
    if(!luhnCheck(ccNumber)) {
        alert(msg);
        return false;
    }

    // validate the expiry month (don't need to validate year since the year
    // select box will never show year's prior to the current year
    
    // if the expiry year is this year, then the expiry month must be the
    // current month or later; if the expiry year is later than the current
    // year, then no need to validate the month...
    var objDate = new Date();
    var iCurrYear = objDate.getFullYear();
    var iCurrMonth = objDate.getMonth() + 1;
    var iCCExpYear = parseInt(ccExpYear,10);
    var iCCExpMonth = parseInt(ccExpMonth,10);

    // if the passed in date is 2-digits, prepend "20" to the value...
    iCCExpYear += ((ccExpYear.toString().length == 2) ? 2000 : 0);

    if(iCCExpYear == iCurrYear) {
        if(iCCExpMonth < iCurrMonth) {
            alert('This card has expired.');
            return false;
        }
    }

    return true;
}

function luhnCheck(ccNumber) {
    /*
    "Luhn Check Digit Algorithm" (aka "Mod10")
    
    Beginning with the second digit from the RIGHT, and every other digit to the left, 
    mutiply by 2. Any summed number over 4, (6 for example) must have the sum of the 
    resulting digits added together. (6 * 2 = 12. sum of 1 + 2 = 3) 

    If the sum of all didits is divisible by 10, then your credit card number passes 
    the LUHN Forumula
    
    More info on the validation logic can be found at:
      http://www.lewismoten.com/Programming/Scripts/ASP/CreditCardValidation/HowItWorks.asp 
    ==============================================================
    
    This function assumes that the cards have already passed the rudimentary
    credit card validation rules (i.e. prefix and length)
    */
    var sum = 0;
    var skip = true;
    var tmp = '';
    var debugMsg = '';
    var bDebug = true;

    for(var i = ccNumber.length - 1; i >= 0; i--) {
        if(skip) {  // last digit or every other digit to the left of last digit...
            debugMsg += '\ncharacter: ' + i + ' : Adding ' + ccNumber.charAt(i) + ' to sum.';
            sum += parseInt(ccNumber.charAt(i),10);
        } else {    // add this value * 2 to sum; if necessary, add summed digits together
            var subt = parseInt(ccNumber.charAt(i),10) * 2;
            debugMsg += '\ncharacter: ' + i + ' : Adding product of 2 * ' + ccNumber.charAt(i) + ' = ' + subt.toString();
            if(subt > 4) {
                tmp = subt.toString();
                var sumOfDigits = 0;
                for(var j=0; j < tmp.length; j++) {
                    sumOfDigits += parseInt(tmp.charAt(j),10);
                }
                debugMsg += '\n  (intermediate product is greater than 4, so summing digits to get --> ' + subt +')';
                sum += sumOfDigits;
            } else {
                sum += subt;
            }
        }
        skip = !skip;
    }

    if(bDebug) alert(debugMsg + '\n\nSUM: ' + sum);

    return ((sum % 10) == 0);
}

function isValidDate(year, month, day){
/*
Programmer:		Ikram Tahir
Date:			July 18, 2001
Purpose:		validates if  year, month and day makes a valid date.
Inputs:			year integer  --four digit year
				month integer
				day integer	
Output:			True		--valid date
				False		--invalid date
*/			
		var inputDate;
		//check invalid inputs
		if ((isNaN(Number(year))) || (isNaN(Number(month))) || (isNaN(Number(day)))) {
			alert("invalid input");
			return false;
		}
		
		//since month starts from 0
		month = month - 1; 
	
		inputDate = new Date(year, month, day);
		//alert(inputDate);
		if ((year != inputDate.getYear()) || (month != inputDate.getMonth()) || (day != inputDate.getDate()) ){
			return false;
		}
		return true;
}// isValidDate()

function validateSearchDates(form){
/*
Programmer:		Ikram Tahir
Date:			July 18, 2001
Purpose:		alerts player if startdate is later than enddate
input:			form name -- assuming that form contains startyear, startmonth, startday, endyear, endmonth, endday
return:			true
				false 
*/
	var todaydate, startdate, enddate, startyear, startmonth, startday, endyear, endmonth, endday;
	startyear = form.startyear.value;
	startmonth = form.startmonth.value;
	startday = form.startday.value;
	endyear = form.endyear.value;
	endmonth = form.endmonth.value;
	endday = form.endday.value;
	// check that "To:" date is on or after the "From:" date..
    var fromDate = new Date(parseInt(startyear), parseInt(startmonth) - 1, parseInt(startday) );
    var toDate =   new Date(parseInt(endyear), parseInt(endmonth) - 1, parseInt(endday) );
    // The valueOf method of Date returns the primitive value of a Date object as a 
    // number data type, the number of milliseconds since midnight 01 January, 1970 UTC.
    if(toDate.valueOf() < fromDate.valueOf()) {
        alert('The \'From:\' date must later than or equal to \'To:\' date');
        return false;
    }
	
	
		return true;
}//validateSearchDates()