/**
	This files contains common java script function.
	Make sure this function does not exist in any js framework like jquery, if we are using
 **/

/**
 **/
var searchArray = (
		!Array.indexOf ? function (o,arr)
				{
			var l = arr.length + 1;
			while (l -= 1)
			{
				if (arr[l - 1] === o)
				{
					return true;
				}
			}
			return false;
				} : function (o,arr)
				{
					return (arr.indexOf(o) !== -1);
				}
);



function isVarSet(vartocheck){
	if(vartocheck == "" ||vartocheck=="undefined" || vartocheck==null )
		return false;
	else if(typeof(vartocheck) == "string" && trim(vartocheck)=="")
		return false;
	else
		return true;
}

function trim(str, chars) {
	return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
	chars = chars || "\\s";
	return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}

function rtrim(str, chars) {
	chars = chars || "\\s";
	return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}

/**
 * this will copy options from select1 to select2
 **/
function copySelectOptions(select1, select2){
	select2.options.length=0;
	for(i=0; i<select1.options.length;i++){
		select2.options[i] = new Option(select1.options[i].text, select1.options[i].value, select1.options[i].selected, select1.options[i].defaultSelected);
		if(select1.selectedIndex >=0 && select1.selectedIndex<select2.options.length)
			select2.selectedIndex = select1.selectedIndex;
	}
}

function CreditCardValidation(){

	this.ccErrorNo = 0;
	this.ccErrors = new Array ()

	this.ccErrors [0] = "Unknown card type";
	this.ccErrors [1] = "No card number provided";
	this.ccErrors [2] = "Credit card number is in invalid format";
	this.ccErrors [3] = "Credit card number is invalid";
	this.ccErrors [4] = "Credit card number has an inappropriate number of digits";

	this.checkCreditCard = function checkCreditCard (cardnumber, cardname) {

		// Array to hold the permitted card characteristics
		var cards = new Array();

		// Define the cards we support. You may add addtional card types.

		//  Name:      As in the selection box of the form - must be same as user's
		//  Length:    List of possible valid lengths of the card number for the card
		//  prefixes:  List of possible prefixes for the card
		//  checkdigit Boolean to say whether there is a check digit

		cards [0] = {name: "Visa", 
				length: "13,16", 
				prefixes: "4",
				checkdigit: true};
		cards [1] = {name: "MasterCard", 
				length: "16", 
				prefixes: "51,52,53,54,55",
				checkdigit: true};
		cards [2] = {name: "DinersClub", 
				length: "14,16", 
				prefixes: "305, 36, 38, 54,55",
				checkdigit: true};
		cards [3] = {name: "CarteBlanche", 
				length: "14", 
				prefixes: "300,301,302,303,304,305",
				checkdigit: true};
		cards [4] = {name: "AmEx", 
				length: "15", 
				prefixes: "34,37",
				checkdigit: true};
		cards [5] = {name: "Discover", 
				length: "16", 
				prefixes: "6011,622,64,65",
				checkdigit: true};
		cards [6] = {name: "JCB", 
				length: "16", 
				prefixes: "35",
				checkdigit: true};
		cards [7] = {name: "enRoute", 
				length: "15", 
				prefixes: "2014,2149",
				checkdigit: true};
		cards [8] = {name: "Solo", 
				length: "16,18,19", 
				prefixes: "6334, 6767",
				checkdigit: true};
		cards [9] = {name: "Switch", 
				length: "16,18,19", 
				prefixes: "4903,4905,4911,4936,564182,633110,6333,6759",
				checkdigit: true};
		cards [10] = {name: "Maestro", 
				length: "12,13,14,15,16,18,19", 
				prefixes: "5018,5020,5038,6304,6759,6761",
				checkdigit: true};
		cards [11] = {name: "VisaElectron", 
				length: "16", 
				prefixes: "417500,4917,4913,4508,4844",
				checkdigit: true};
		cards [12] = {name: "LaserCard", 
				length: "16,17,18,19", 
				prefixes: "6304,6706,6771,6709",
				checkdigit: true};

		// Establish card type
		var cardType = -1;
		for (var i=0; i<cards.length; i++) {

			// See if it is this card (ignoring the case of the string)
			if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
				cardType = i;
				break;
			}
		}

		// If card type not found, report an error
		if (cardType == -1) {
			ccErrorNo = 0;
			return false; 
		}

		// Ensure that the user has provided a credit card number
		if (cardnumber.length == 0)  {
			ccErrorNo = 1;
			return false; 
		}

		// Now remove any spaces from the credit card number
		cardnumber = cardnumber.replace (/\s/g, "");

		// Check that the number is numeric
		var cardNo = cardnumber
		var cardexp = /^[0-9]{13,19}$/;
		if (!cardexp.exec(cardNo))  {
			ccErrorNo = 2;
			return false; 
		}

		// Now check the modulus 10 check digit - if required
		if (cards[cardType].checkdigit) {
			var checksum = 0;                                  // running checksum total
			var mychar = "";                                   // next char to process
			var j = 1;                                         // takes value of 1 or 2

			// Process each digit one by one starting at the right
			var calc;
			for (i = cardNo.length - 1; i >= 0; i--) {

				// Extract the next digit and multiply by 1 or 2 on alternative digits.
				calc = Number(cardNo.charAt(i)) * j;

				// If the result is in two digits add 1 to the checksum total
				if (calc > 9) {
					checksum = checksum + 1;
					calc = calc - 10;
				}

				// Add the units element to the checksum total
				checksum = checksum + calc;

				// Switch the value of j
				if (j ==1) {j = 2} else {j = 1};
			} 

			// All done - if checksum is divisible by 10, it is a valid modulus 10.
			// If not, report an error.
			if (checksum % 10 != 0)  {
				ccErrorNo = 3;
				return false; 
			}
		}  

		// The following are the card-specific checks we undertake.
		var LengthValid = false;
		var PrefixValid = false; 
		var undefined; 

		// We use these for holding the valid lengths and prefixes of a card type
		var prefix = new Array ();
		var lengths = new Array ();

		// Load an array with the valid prefixes for this card
		prefix = cards[cardType].prefixes.split(",");

		// Now see if any of them match what we have in the card number
		for (i=0; i<prefix.length; i++) {
			var exp = new RegExp ("^" + prefix[i]);
			if (exp.test (cardNo)) PrefixValid = true;
		}

		// If it isn't a valid prefix there's no point at looking at the length
		if (!PrefixValid) {
			ccErrorNo = 3;
			return false; 
		}

		// See if the length is valid for this card
		lengths = cards[cardType].length.split(",");
		for (j=0; j<lengths.length; j++) {
			if (cardNo.length == lengths[j]) LengthValid = true;
		}

		// See if all is OK by seeing if the length was valid. We only check the 
		// length if all else was hunky dory.
		if (!LengthValid) {
			ccErrorNo = 4;
			return false; 
		};   

		// The credit card is in the required format.
		return true;
	}


}

//check time in HH:MM format
function checkTime(s){
	if(s == null) return false;
	if(s.indexOf(":") == -1) return false;
	var spl = s.split(":");
	if(parseInt(spl[0]) < 24 && parseInt(spl[0]) >=0 && parseInt(spl[1])<60 && parseInt(spl[1])>=0)
		return true;
	else return false;
}

function removeChildrenFromNode(e) {
	if(!e) {
		return false;
	}
	if(typeof(e)=='string') {
		e = xGetElementById(e);
	}
	while (e.hasChildNodes()) {
		e.removeChild(e.firstChild);
	}
	return true;
}

function getMonthName(monthNumber){
	var monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
	return monthNames[monthNumber];
}

//Check if string is currency
var isCurrency_re    = /^\s*(\+|-)?((\d+(\.\d\d)?)|(\.\d\d))\s*$/;
function isCurrency (s) {
	return String(s).search (isCurrency_re) != -1;
}

/**
 *
 *  URL encode / decode
 *  http://www.webtoolkit.info/
 *
 **/

var URL = {

		// public method for url encoding
		encode : function (string) {
	return escape(this._utf8_encode(string));
},

//public method for url decoding
decode : function (string) {
	return this._utf8_decode(unescape(string));
},

//private method for UTF-8 encoding
_utf8_encode : function (string) {
	string = string.replace(/\r\n/g,"\n");
	var utftext = "";

	for (var n = 0; n < string.length; n++) {

		var c = string.charCodeAt(n);

		if (c < 128) {
			utftext += String.fromCharCode(c);
		}
		else if((c > 127) && (c < 2048)) {
			utftext += String.fromCharCode((c >> 6) | 192);
			utftext += String.fromCharCode((c & 63) | 128);
		}
		else {
			utftext += String.fromCharCode((c >> 12) | 224);
			utftext += String.fromCharCode(((c >> 6) & 63) | 128);
			utftext += String.fromCharCode((c & 63) | 128);
		}

	}

	return utftext;
},

//private method for UTF-8 decoding
_utf8_decode : function (utftext) {
	var string = "";
	var i = 0;
	var c = c1 = c2 = 0;

	while ( i < utftext.length ) {

		c = utftext.charCodeAt(i);

		if (c < 128) {
			string += String.fromCharCode(c);
			i++;
		}
		else if((c > 191) && (c < 224)) {
			c2 = utftext.charCodeAt(i+1);
			string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
			i += 2;
		}
		else {
			c2 = utftext.charCodeAt(i+1);
			c3 = utftext.charCodeAt(i+2);
			string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
			i += 3;
		}

	}

	return string;
}

}

/**
 * javascript equivalant to php function empty
 * <div>
 *  example 1: empty(null); //returns 1: true   <br>   
 *  example 2: empty(undefined); // returns 2: true<br>
 *  example 3: empty([]); // returns 3: true<br>
 *  example 4: empty({});//returns 4: true<br>
 *  example 5: empty({'aFunc' : function () { alert('humpty'); } }); //returns 5: false<br>
 * </div>
 * @param mixed_var
 * @return boolean
 */
function empty (mixed_var) {
	var key;    
	if (mixed_var === "" ||
			mixed_var === 0 ||
			mixed_var === "0" ||
			mixed_var === null ||        mixed_var === false ||
			typeof mixed_var === 'undefined'
	){
		return true;
	} 
	if (typeof mixed_var == 'object') {
		for (key in mixed_var) {
			return false;
		}        return true;
	}

	return false;
}

/**
 * javascript equivalant for is_array function
 * <div>
 * example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);//returns 1: true<br>
 * example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});//returns 2: false<br>
 * example 3: in_array(1, ['1', '2', '3']);//returns 3: true<br>
 * example 3: in_array(1, ['1', '2', '3'], false);//returns 3: true<br>
 * example 4: in_array(1, ['1', '2', '3'], true);//returns 4: false<br>
 * </div>
 * @param needle
 * @param haystack
 * @param argStrict
 * @return true if element in array
 */
function in_array (needle, haystack, argStrict) {
	var key = '', strict = !!argStrict;

	if (strict) {
		for (key in haystack) {
			if (haystack[key] === needle) {
				return true;
			}
		}
	} else {
		for (key in haystack) {
			if (haystack[key] == needle) {
				return true;
			}
		}
	}

	return false;
}

function array_key_exists ( key, search ) {
	if (!search || (search.constructor !== Array && search.constructor !== Object)){
		return false;
	}

	return key in search;
}

/**
 *  javascript equivalant of implode
 *  <div>
 *  example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);    //  returns 1: 'Kevin van Zonneveld'<br>
 *   example 2: implode(' ', {first:'Kevin', last: 'van Zonneveld'});/returns 2: 'Kevin van Zonneveld'
 *  </div>
 * @param glue
 * @param pieces
 * @return string 
 */
function implode (glue, pieces) {
	var i = '', retVal='', tGlue='';
	if (arguments.length === 1) {        
		pieces = glue;
		glue = '';
	}
	if (typeof(pieces) === 'object') {
		if (pieces instanceof Array) {            
			return pieces.join(glue);
		}
		else {
			for (i in pieces) {
				retVal += tGlue + pieces[i];                
				tGlue = glue;
			}
			return retVal;
		}
	}    else {
		return pieces;
	}
}


/**
 * php date equivalent, taken from phphjs.org
 * <div>
 * example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400);// returns 1: '09:09:40 m is month'<br>  
 * example 2: date('F j, Y, g:i a', 1062462400);//returns 2: 'September 2, 2003, 2:26 am'<br>
 * example 3: date('Y W o', 1062462400);//returns 3: '2003 36 2003'<br>
 * example 4: x = date('Y m d', (new Date()).getTime()/1000); <br>
 * example 4: (x+'').length == 10 // 2009 01 09  //returns 4: true<br>
 * example 5: date('W', 1104534000);// returns 5: '53' <br>  
 * example 6: date('B t', 1104534000);// returns 6: '999 31'<br>
 * example 7: date('W', 1293750000); // 2010-12-31  //returns 7: '52'<br>
 * example 8: date('W', 1293836400); // 2011-01-01//returns 8: '52'<br>
 * example 9: date('W Y-m-d', 1293974054);// 2011-01-02//returns 9: '52 2011-01-02'<br>
 * </div>
 * @param format
 * @param timestamp
 * @return date in specified format
 */
var dateJs = function date(format, timestamp) {
    var that = this,
        jsdate, f, formatChr = /\\?([a-z])/gi, formatChrCb,
        // Keep this here (works, but for code commented-out
        // below for file size reasons)
        //, tal= [],
        _pad = function (n, c) {
            if ((n = n + "").length < c) {
                return new Array((++c) - n.length).join("0") + n;
            } else {
                return n;
            }
        },
        txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
        "January", "February", "March", "April", "May", "June", "July",
        "August", "September", "October", "November", "December"],
        txt_ordin = {
            1: "st",
            2: "nd",
            3: "rd",
            21: "st", 
            22: "nd",
            23: "rd",
            31: "st"
        };
    formatChrCb = function (t, s) {
        return f[t] ? f[t]() : s;
    };
    f = {
    // Day
        d: function () { // Day of month w/leading 0; 01..31
            return _pad(f.j(), 2);
        },
        D: function () { // Shorthand day name; Mon...Sun
            return f.l().slice(0, 3);
        },
        j: function () { // Day of month; 1..31
            return jsdate.getDate();
        },
        l: function () { // Full day name; Monday...Sunday
            return txt_words[f.w()] + 'day';
        },
        N: function () { // ISO-8601 day of week; 1[Mon]..7[Sun]
            return f.w() || 7;
        },
        S: function () { // Ordinal suffix for day of month; st, nd, rd, th
            return txt_ordin[f.j()] || 'th';
        },
        w: function () { // Day of week; 0[Sun]..6[Sat]
            return jsdate.getDay();
        },
        z: function () { // Day of year; 0..365
            var a = new Date(f.Y(), f.n() - 1, f.j()),
                b = new Date(f.Y(), 0, 1);
            return Math.round((a - b) / 864e5) + 1;
        },

    // Week
        W: function () { // ISO-8601 week number
            var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3),
                b = new Date(a.getFullYear(), 0, 4);
            return 1 + Math.round((a - b) / 864e5 / 7);
        },

    // Month
        F: function () { // Full month name; January...December
            return txt_words[6 + f.n()];
        },
        m: function () { // Month w/leading 0; 01...12
            return _pad(f.n(), 2);
        },
        M: function () { // Shorthand month name; Jan...Dec
            return f.F().slice(0, 3);
        },
        n: function () { // Month; 1...12
            return jsdate.getMonth() + 1;
        },
        t: function () { // Days in month; 28...31
            return (new Date(f.Y(), f.n(), 0)).getDate();
        },

    // Year
        L: function () { // Is leap year?; 0 or 1
            var y = f.Y(), a = y & 3, b = y % 4e2, c = y % 1e2;
            return 0 + (!a && (c || !b));
        },
        o: function () { // ISO-8601 year
            var n = f.n(), W = f.W(), Y = f.Y();
            return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9);
        },
        Y: function () { // Full year; e.g. 1980...2010
            return jsdate.getFullYear();
        },
        y: function () { // Last two digits of year; 00...99
            return (f.Y() + "").slice(-2);
        },

    // Time
        a: function () { // am or pm
            return jsdate.getHours() > 11 ? "pm" : "am";
        },
        A: function () { // AM or PM
            return f.a().toUpperCase();
        },
        B: function () { // Swatch Internet time; 000..999
            var H = jsdate.getUTCHours() * 36e2, // Hours
                i = jsdate.getUTCMinutes() * 60, // Minutes
                s = jsdate.getUTCSeconds(); // Seconds
            return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3);
        },
        g: function () { // 12-Hours; 1..12
            return f.G() % 12 || 12;
        },
        G: function () { // 24-Hours; 0..23
            return jsdate.getHours();
        },
        h: function () { // 12-Hours w/leading 0; 01..12
            return _pad(f.g(), 2);
        },
        H: function () { // 24-Hours w/leading 0; 00..23
            return _pad(f.G(), 2);
        },
        i: function () { // Minutes w/leading 0; 00..59
            return _pad(jsdate.getMinutes(), 2);
        },
        s: function () { // Seconds w/leading 0; 00..59
            return _pad(jsdate.getSeconds(), 2);
        },
        u: function () { // Microseconds; 000000-999000
            return _pad(jsdate.getMilliseconds() * 1000, 6);
        },

    // Timezone
        e: function () { // Timezone identifier; e.g. Atlantic/Azores, ...
// The following works, but requires inclusion of the very large
// timezone_abbreviations_list() function.
/*              var abbr = '', i = 0, os = 0;
            if (that.php_js && that.php_js.default_timezone) {
                return that.php_js.default_timezone;
            }
            if (!tal.length) {
                tal = that.timezone_abbreviations_list();
            }
            for (abbr in tal) {
                for (i = 0; i < tal[abbr].length; i++) {
                    os = -jsdate.getTimezoneOffset() * 60;
                    if (tal[abbr][i].offset === os) {
                        return tal[abbr][i].timezone_id;
                    }
                }
            }
*/
            return 'UTC';
        },
        I: function () { // DST observed?; 0 or 1
            // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC.
            // If they are not equal, then DST is observed.
            var a = new Date(f.Y(), 0), // Jan 1
                c = Date.UTC(f.Y(), 0), // Jan 1 UTC
                b = new Date(f.Y(), 6), // Jul 1
                d = Date.UTC(f.Y(), 6); // Jul 1 UTC
            return 0 + ((a - c) !== (b - d));
        },
        O: function () { // Difference to GMT in hour format; e.g. +0200
            var a = jsdate.getTimezoneOffset();
            return (a > 0 ? "-" : "+") + _pad(Math.abs(a / 60 * 100), 4);
        },
        P: function () { // Difference to GMT w/colon; e.g. +02:00
            var O = f.O();
            return (O.substr(0, 3) + ":" + O.substr(3, 2));
        },
        T: function () { // Timezone abbreviation; e.g. EST, MDT, ...
// The following works, but requires inclusion of the very
// large timezone_abbreviations_list() function.
/*              var abbr = '', i = 0, os = 0, default = 0;
            if (!tal.length) {
                tal = that.timezone_abbreviations_list();
            }
            if (that.php_js && that.php_js.default_timezone) {
                default = that.php_js.default_timezone;
                for (abbr in tal) {
                    for (i=0; i < tal[abbr].length; i++) {
                        if (tal[abbr][i].timezone_id === default) {
                            return abbr.toUpperCase();
                        }
                    }
                }
            }
            for (abbr in tal) {
                for (i = 0; i < tal[abbr].length; i++) {
                    os = -jsdate.getTimezoneOffset() * 60;
                    if (tal[abbr][i].offset === os) {
                        return abbr.toUpperCase();
                    }
                }
            }
*/
            return 'UTC';
        },
        Z: function () { // Timezone offset in seconds (-43200...50400)
            return -jsdate.getTimezoneOffset() * 60;
        },

    // Full Date/Time
        c: function () { // ISO-8601 date.
            return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb);
        },
        r: function () { // RFC 2822
            return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb);
        },
        U: function () { // Seconds since UNIX epoch
            return Math.round(jsdate.getTime() / 1000);
        }
    };
    this.date = function (format, timestamp) {
        that = this;
        jsdate = (
            (typeof timestamp === 'undefined') ? new Date() : // Not provided
            (timestamp instanceof Date) ? new Date(timestamp) : // JS Date()
            new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int)
        );
        return format.replace(formatChr, formatChrCb);
    };
    return this.date(format, timestamp);
}


/**
 * php strtotime equivalent, taken from http://phpjs.org
 * <div>
 * example 1: strtotime('+1 day', 1129633200);//returns 1: 1129719600 <br>
 * example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);// returns 2: 1130425202<br>
 * example 3: strtotime('last month', 1129633200);// returns 3: 1127041200<br>
 * example 4: strtotime('2009-05-04 08:30:00');// returns 4: 1241418600<br>
 * </div>
 * @param str
 * @param now
 * @return timestamp
 */
function strtotime (str, now) {
    var i, match, s, strTmp = '', parse = '';

    strTmp = str;
    strTmp = strTmp.replace(/\s{2,}|^\s|\s$/g, ' '); // unecessary spaces
    strTmp = strTmp.replace(/[\t\r\n]/g, ''); // unecessary chars

    if (strTmp == 'now') {
        return (new Date()).getTime()/1000; // Return seconds, not milli-seconds
    } else if (!isNaN(parse = Date.parse(strTmp))) {
        return (parse/1000);
    } else if (now) {
        now = new Date(now*1000); // Accept PHP-style seconds
    } else {
        now = new Date();
    }

    strTmp = strTmp.toLowerCase();

    var __is =
    {
        day:
        {
            'sun': 0,
            'mon': 1,
            'tue': 2,
            'wed': 3,
            'thu': 4,
            'fri': 5,
            'sat': 6
        },
        mon:
        {
            'jan': 0,
            'feb': 1,
            'mar': 2,
            'apr': 3,
            'may': 4,
            'jun': 5,
            'jul': 6,
            'aug': 7,
            'sep': 8,
            'oct': 9,
            'nov': 10,
            'dec': 11
        }
    };

    var process = function (m) {
        var ago = (m[2] && m[2] == 'ago');
        var num = (num = m[0] == 'last' ? -1 : 1) * (ago ? -1 : 1);

        switch (m[0]) {
            case 'last':
            case 'next':
                switch (m[1].substring(0, 3)) {
                    case 'yea':
                        now.setFullYear(now.getFullYear() + num);
                        break;
                    case 'mon':
                        now.setMonth(now.getMonth() + num);
                        break;
                    case 'wee':
                        now.setDate(now.getDate() + (num * 7));
                        break;
                    case 'day':
                        now.setDate(now.getDate() + num);
                        break;
                    case 'hou':
                        now.setHours(now.getHours() + num);
                        break;
                    case 'min':
                        now.setMinutes(now.getMinutes() + num);
                        break;
                    case 'sec':
                        now.setSeconds(now.getSeconds() + num);
                        break;
                    default:
                        var day;
                        if (typeof (day = __is.day[m[1].substring(0, 3)]) != 'undefined') {
                            var diff = day - now.getDay();
                            if (diff == 0) {
                                diff = 7 * num;
                            } else if (diff > 0) {
                                if (m[0] == 'last') {diff -= 7;}
                            } else {
                                if (m[0] == 'next') {diff += 7;}
                            }
                            now.setDate(now.getDate() + diff);
                        }
                }
                break;

            default:
                if (/\d+/.test(m[0])) {
                    num *= parseInt(m[0], 10);

                    switch (m[1].substring(0, 3)) {
                        case 'yea':
                            now.setFullYear(now.getFullYear() + num);
                            break;
                        case 'mon':
                            now.setMonth(now.getMonth() + num);
                            break;
                        case 'wee':
                            now.setDate(now.getDate() + (num * 7));
                            break;
                        case 'day':
                            now.setDate(now.getDate() + num);
                            break;
                        case 'hou':
                            now.setHours(now.getHours() + num);
                            break;
                        case 'min':
                            now.setMinutes(now.getMinutes() + num);
                            break;
                        case 'sec':
                            now.setSeconds(now.getSeconds() + num);
                            break;
                    }
                } else {
                    return false;
                }
                break;
        }
        return true;
    };

    match = strTmp.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);
    if (match != null) {
        if (!match[2]) {
            match[2] = '00:00:00';
        } else if (!match[3]) {
            match[2] += ':00';
        }

        s = match[1].split(/-/g);

        for (i in __is.mon) {
            if (__is.mon[i] == s[1] - 1) {
                s[1] = i;
            }
        }
        s[0] = parseInt(s[0], 10);

        s[0] = (s[0] >= 0 && s[0] <= 69) ? '20'+(s[0] < 10 ? '0'+s[0] : s[0]+'') : (s[0] >= 70 && s[0] <= 99) ? '19'+s[0] : s[0]+'';
        return parseInt(this.strtotime(s[2] + ' ' + s[1] + ' ' + s[0] + ' ' + match[2])+(match[4] ? match[4]/1000 : ''), 10);
    }

    var regex = '([+-]?\\d+\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)'+
        '|(last|next)\\s'+
        '(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?'+
        '|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday'+
        '|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))'+
        '(\\sago)?';

    match = strTmp.match(new RegExp(regex, 'gi')); // Brett: seems should be case insensitive per docs, so added 'i'
    if (match == null) {
        return false;
    }

    for (i = 0; i < match.length; i++) {
        if (!process(match[i].split(' '))) {
            return false;
        }
    }

    return (now.getTime()/1000);
}

function isValidEmail(emailAddress) {
	var pattern = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
	return pattern.test(emailAddress);
}


