﻿//Browser extensions
Object.append(Browser, {
    getHost: function (url) { return new URI(url).get('host'); }
	, getQueryStringValue: function (key, url) { return new URI(url).getData(key); }
	, getQueryStringValues: function (url) { return new URI(url).getData(); }
	, getPort: function (url) { return new URI(url).get('port'); }
});
Element.Events.hashchange = {
    /*
    description: Added the onhashchange event
    license: MIT-style
    authors: 
    - sdf1981cgn
    - Greggory Hernandez
    requires: 
    - core/1.2.4: '*'
    provides: [Element.Events.hashchange]
    */
    onAdd: function () {
        var hash = self.location.hash;
        var hashchange = function () {
            if (hash == self.location.hash) return;
            else hash = self.location.hash;
            var value = (hash.indexOf('#') == 0 ? hash.substr(1) : hash);
            window.fireEvent('hashchange', value);
            document.fireEvent('hashchange', value);
        };
        if ("onhashchange" in window) window.onhashchange = hashchange;
        else hashchange.periodical(50);
    }
};
//Date extensions
Date.implement({
    dateFormat: function () {
        intDt = this.getDate();
        intMn = this.getMonth();
        intYr = this.getFullYear();
        return intMn + '/' + intDt + '/' + intYr;
    }
    , dateAdd: function (timeU, byMany) {
        var millisecond = 1;
        var second = millisecond * 1000;
        var minute = second * 60;
        var hour = minute * 60;
        var day = hour * 24;
        var month = day * 30;
        var year = day * 365;
        var newDate;
        var dVal = this.valueOf();
        switch (timeU) {
            case "ms": newDate = new Date(dVal + millisecond * byMany); break;
            case "s": newDate = new Date(dVal + second * byMany); break;
            case "mi": newDate = new Date(dVal + minute * byMany); break;
            case "h": newDate = new Date(dVal + hour * byMany); break;
            case "d": newDate = new Date(dVal + day * byMany); break;
            case "mm": newDate = new Date(dVal + month * byMany); break;
            case "y": newDate = new Date(dVal + year * byMany); break;
        }
        return newDate;
    }
});
//Number extensions
Number.implement({
    numberFormat: function (decimals, dec_point, thousands_sep) {
        decimals = Math.abs(decimals) + 1 ? decimals : 2;
        dec_point = dec_point || '.';
        thousands_sep = thousands_sep || ',';
        var matches = /(-)?(\d+)(\.\d+)?/.exec((isNaN(this) ? 0 : this) + '');
        var remainder = matches[2].length > 3 ? matches[2].length % 3 : 0;
        return (matches[1] ? matches[1] : '') + (remainder ? matches[2].substr(0, remainder) + thousands_sep : '') + matches[2].substr(remainder).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep) + (decimals ? dec_point + (+matches[3] || 0).toFixed(decimals).substr(2) : '');
    }
	, formatPercent: function () {
	    var threeDec = new String((this * 100).toFixed(3).toFloat().numberFormat(3) + '%');
	    while (threeDec.indexOf("0%") > 0) threeDec = threeDec.replace("0%", "%");
	    return threeDec.replace(".%", "%");
	}
	, formatCurrency: function () {
	    return "$" + this.toFixed(2).toFloat().numberFormat();
	}
});
//String extensions
String.implement({
    strip: function () {
        arrChars = this.clean().split("");
        arrChars.each(function (item, indx, arr) { if (isNaN(item) || item == ' ') arr[indx] = ''; });
        return arrChars.join("");
    }
	, formatPhone: function () {
	    strResult = "";
	    this.strip().split("").each(function (item, indx, arr) {
	        if (indx == 0) strResult += "(";
	        if (indx == 3) strResult += ") ";
	        if (indx == 6) strResult += "-";
	        strResult += item;
	    });
	    return strResult;
	}
	, formatSSN: function () {
	    strResult = "";
	    this.strip().split("").each(function (item, indx, arr) {
	        if (indx == 3) strResult += "-";
	        if (indx == 5) strResult += "-";
	        strResult += item;
	    });
	    return strResult;
	}
	, formatEIN: function () {
	    strResult = "";
	    this.strip().split("").each(function (item, indx, arr) {
	        if (indx == 2) strResult += "-";
	        strResult += item;
	    });
	    return strResult;
	}
	, right: function (len) {
	    if (len <= 0) return "";
	    else if (len > this.length) return this;
	    else {
	        var iLen = this.length;
	        return this.substring(iLen, iLen - len);
	    }
	}
	, left: function (len) {
	    if (len <= 0) return "";
	    else if (len > this.length) return this;
	    else return this.substring(0, len);
	}
	, mid: function (start, len) {
	    if (start < 0 || len < 0) return "";
	    else {
	        var iEnd;
	        var iLen = this.length;
	        if (start + len > iLen) iEnd = iLen;
	        else iEnd = start + len;
	        return this.substring(start, iEnd);
	    }
	}
	, isDate: function () {
	    var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
	    var matchArray = this.match(datePat);
	    if (matchArray == null) return false;
	    month = matchArray[1];
	    day = matchArray[3];
	    year = matchArray[5];
	    if (month < 1 || month > 12) return false;
	    if (day < 1 || day > 31) return false;
	    if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) return false;
	    if (month == 2) {
	        var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
	        if (day > 29 || (day == 29 && !isleap)) return false;
	    }
	    return true;
	}
});
//DOM extensions
Element.implement({
    sumOfChildrenWidths: function (tag) {
        intChildWidthSum = 0;
        arrChildren = this.getChildren(tag);
        al = arrChildren.length;
        for (n = 0; n < al; n++) {
            if (arrChildren[n].getStyle("display") != "none") {
                if (arrChildren[n].getSize().x > 0) intChildWidthSum += arrChildren[n].getSize().x;
                else if (arrChildren[n].getStyle('width').toInt() > 0) intChildWidthSum += arrChildren[n].getStyle('width').toInt();
                else if (arrChildren[n].getProperties('width').width != null) intChildWidthSum += arrChildren[n].getProperty('width').toInt();
            }
        }
        return intChildWidthSum;
    }
	, sumOfChildrenHeights: function (tag) {
	    intChildHeightSum = 0;
	    arrChildren = this.getChildren(tag);
	    al = arrChildren.length;
	    for (n = 0; n < al; n++) {
	        if (arrChildren[n].getStyle("display") != "none") {
	            if (arrChildren[n].getSize().y > 0) intChildHeightSum += arrChildren[n].getSize().y;
	            else if (arrChildren[n].getStyle('height').toInt() > 0) intChildHeightSum += arrChildren[n].getStyle('height').toInt();
	            else if (arrChildren[n].getProperties('height').height != null) intChildHeightSum += arrChildren[n].getProperty('height').toInt();
	        }
	    }
	    return intChildHeightSum;
	}
	, maxOfChildrenWidths: function (tag) {
	    intChildWidthMax = 0;
	    arrChildren = this.getChildren(tag);
	    al = arrChildren.length;
	    for (n = 0; n < al; n++) {
	        if (arrChildren[n].getStyle("display") != "none") {
	            if (arrChildren[n].getSize().x > 0) { if (arrChildren[n].getSize().x > intChildWidthMax) intChildWidthMax = arrChildren[n].getSize().x; }
	            else if (arrChildren[n].getStyle('width').toInt() > intChildWidthMax) { intChildWidthMax = arrChildren[n].getStyle('width').toInt(); }
	            else if (arrChildren[n].getProperties('width').width.toInt() > intChildWidthMax) { intChildWidthMax = arrChildren[n].getProperty('width').toInt(); }
	        }
	    }
	    return intChildWidthMax;
	}
	, maxOfChildrenHeights: function (tag) {
	    intChildHeightMax = 0;
	    arrChildren = this.getChildren(tag);
	    al = arrChildren.length;
	    for (n = 0; n < al; n++) {
	        if (arrChildren[n].getStyle("display") != "none") {
	            if (arrChildren[n].getSize().y > 0) { if (arrChildren[n].getSize().y > intChildHeightMax) intChildHeightMax = arrChildren[n].getSize().y; }
	            else if (arrChildren[n].getStyle('height').toInt() > intChildHeightMax) { intChildHeightMax = arrChildren[n].getStyle('height').toInt(); }
	            else if (arrChildren[n].getProperties('height').height.toInt() > intChildHeightMax) { intChildHeightMax = arrChildren[n].getProperty('height').toInt(); }
	        }
	    }
	    return intChildHeightMax;
	}
});
//Form.Validator extensions
Form.Validator.add("validate-integer-allow-zero", {
    errorMsg: "Please enter an integer in this field."
	, test: function (field) {
	    return (field.value == field.value.strip());
	}
});
Form.Validator.add("validate-minimum-integer", {
    errorMsg: "Please enter an value of (x) or higher in this field."
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(8) == "minValue") {
	            var minValue = arrElemClasses[c].substr(9).toInt();
	        }
	    }
	    this.errorMsg = this.errorMsg.replace('(x)', minValue);
	    if (field.value < minValue) return false;
	    else return true;
	}
});
Form.Validator.add("validate-maximum-integer", {
    errorMsg: "Please enter an value of (x) or less in this field."
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(8) == "maxValue") {
	            var maxValue = arrElemClasses[c].substr(9).toInt();
	        }
	    }
	    this.errorMsg = this.errorMsg.replace('(x)', maxValue);
	    if (field.value > maxValue) return false;
	    else return true;
	}
});
Form.Validator.add("validate-minimum-numeric", {
    errorMsg: "Please enter an value of (x) or higher in this field."
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(8) == "minValue") {
	            var minValue = arrElemClasses[c].substr(9).toFloat();
	        }
	    }
	    this.errorMsg = this.errorMsg.replace('(x)', minValue);
	    if (field.value < minValue) return false;
	    else return true;
	}
});
Form.Validator.add("validate-maximum-numeric", {
    errorMsg: "Please enter an value of (x) or less in this field."
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(8) == "maxValue") {
	            var maxValue = arrElemClasses[c].substr(9).toFloat();
	        }
	    }
	    this.errorMsg = this.errorMsg.replace('(x)', maxValue);
	    if (field.value > maxValue) return false;
	    else return true;
	}
});
Form.Validator.add("validate-one-checked-by-parent", {
    errorMsg: "You must provide a selection for one of the items above."
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(8) == "parentID") {
	            var parentID = arrElemClasses[c].substr(9);
	        }
	    }
	    blnReturn = false;
	    $$('#' + parentID + ' input[type=radio]').each(function (el) { if (el.checked) blnReturn = true; });
	    return blnReturn;
	}
});
Form.Validator.add("validate-companion", {
    errorMsg: "You must also enter a "
	, test: function (field) {
	    arrElemClasses = field.className.split(" ");
	    al = arrElemClasses.length;
	    for (c = 0; c < al; c++) {
	        if (arrElemClasses[c].left(11) == "companionID") {
	            var companionID = arrElemClasses[c].substr(12);
	        }
	    }
	    if ($(companionID).value == "") {
	        al = arrElemClasses.length
	        for (c = 0; c < al; c++) {
	            if (arrElemClasses[c].substr(0, 13) == "companionText") {
	                companionText = arrElemClasses[c].substr(14);
	            }
	        }
	    }
	    if (companionText != "") {
	        this.errorMsg += companionText.replace(/%20/g, " ") + ".";
	        return false;
	    }
	    else return true;
	}
});
Form.Validator.add("validate-words", {
    errorMsg: "Numbers are not permitted within this field."
	, test: function (field) {
	    reNums = /[\d]/;
	    return !reNums.test(field.value);
	}
});
Form.Validator.add("validate-expiry", {
    errorMsg: "The expiration date provided is not valid."
	, test: function (field) {
	    if (field.hasClass('required')) {
	        arrElemClasses = field.className.split(" ");
	        al = arrElemClasses.length;
	        for (c = 0; c < al; c++) {
	            if (arrElemClasses[c].left(5) == "month") {
	                var monthID = arrElemClasses[c].substr(6);
	            }
	        }
	        for (c = 0; c < al; c++) {
	            if (arrElemClasses[c].left(4) == "year") {
	                var yearID = arrElemClasses[c].substr(5);
	            }
	        }
	        if ($(monthID).selectedIndex > 0 && $(yearID).selectedIndex > 0) {
	            var cDate = new Date();
	            var xDate = new Date(($(monthID).selectedIndex) + '/1/' + ($(yearID).options[$(yearID).selectedIndex].value));
	            if (xDate < cDate) return false;
	            else return true;
	        }
	        else if ($(monthID).hasFocus() || $(yearID).hasFocus()) return true;
	        else return false;
	    }
	    else return true;
	}
});
Form.Validator.add("validate-atleastonealpha", {
    errorMsg: "At least one letter is required."
	, test: function (field) {
	    return isNaN(field.value);
	}
});
Form.Validator.add("validate-zip-usa", {
    errorMsg: "Enter a properly formatted, 5-digit United States zip code."
	, test: function (field) {
	    if (field.hasClass('required')) {
	        var usZip = /^\d{5}$/i;
	        return usZip.test(field.value);
	    }
	    else return true;
	}
});
Form.Validator.add("validate-zip-canada", {
    errorMsg: "Enter a properly formatted Canadian zip code."
	, test: function (field) {
	    if (field.hasClass('required')) {
	        var caZip = /^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$/i;
	        return caZip.test(field.value);
	    }
	    else return true;
	}
});
Form.Validator.add("validate-ssn", {
    errorMsg: "Enter your 9-digit Social Security Number."
	, test: function (field) {
	    if (field.value != "") {
	        var reSSN = /^\d{3}\-\d{2}\-\d{4}$/;
	        return reSSN.test(field.value.formatSSN());
	    }
	    else return true;
	}
});
Form.Validator.add("validate-ein", {
    errorMsg: "Enter your 9-digit Employer Identification Number."
	, test: function (field) {
	    if (field.value != "") {
	        var reEIN = /^\d{2}\-\d{7}$/;
	        return reEIN.test(field.value.formatEIN());
	    }
	    else return true;
	}
});
Form.Validator.add("validate-phone", {
    errorMsg: "Enter a 10-digit phone number."
	, test: function (field) {
	    if (field.value != "") {
	        var rePhone = /^\(\d{3}\)\s\d{3}\-\d{4}$/;
	        return rePhone.test(field.value.formatPhone());
	    }
	    else return true;
	}
});
Form.Validator.add("validate-numerals", {
    errorMsg: "Enter a number."
	, test: function (field) {
	    if (field.value == "") return true;
	    else {
	        arrElemClasses = field.className.split(" ");
	        for (c = 0; c < arrElemClasses.length; c++) {
	            if (arrElemClasses[c].substr(0, 9) == "numLength") var requiredNumeralCount = arrElemClasses[c].substr(10).toInt();
	        }
	        if (isNaN(requiredNumeralCount) || field.value == "") return true;
	        else this.errorMsg = "Enter a " + requiredNumeralCount + "-digit number.";
	        if (field.value.strip().length == requiredNumeralCount) return true;
	        else return false;
	    }
	}
});
Form.Validator.add("validate-usernameavailable", {
    //make sure that the username is available
    errorMsg: "The username entered is already in use. Please try a different name."
	, test: function (field) {
	    var objAvailCheck = new Request({
	        url: window.location.protocol + "//" + window.location.hostname + "/_scripts/checkUsernameAvailability.asp"
			, async: false
			, method: "post"
			, headers: { "Content-Type": "application/x-www-form-urlencoded" }
			, result: false
			, onSuccess: function (rT, rX) { this.result = eval(rT); }
	    })
	    objAvailCheck.send("login=" + field.value);
	    return objAvailCheck.result;
	}
});
Form.Validator.add("validate-emailregistered", {
    //make sure that the username is available
    errorMsg: "The email address is not registered."
	, test: function (field) {
	    var objEmailRegistered = new Request({
	        url: window.location.protocol + "//" + window.location.hostname + "/_scripts/checkEmailRegistered.asp"
			, async: false
			, method: "post"
			, headers: { "Content-Type": "application/x-www-form-urlencoded" }
			, result: false
			, onSuccess: function (rT, rX) { this.result = eval(rT); }
	    });
	    objEmailRegistered.send("email=" + field.value);
	    return objEmailRegistered.result;
	}
});
//Patch MooTools Request.HTML for WebKit
Request.HTML.implement({
    processHTML: function (text) {
        var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
        text = (match) ? match[1] : text;
        var container = new Element('div');
        return $try(function () {
            var root = '<root>' + text + '</root>', doc;
            if (Browser.ie) {
                doc = new ActiveXObject('Microsoft.XMLDOM');
                doc.async = false;
                doc.loadXML(root);
            }
            else {
                doc = new DOMParser().parseFromString(root, 'text/html');
            }
            root = doc.getElementsByTagName('root')[0];
            for (var i = 0, k = root.childNodes.length; i < k; i++) {
                var child = Element.clone(root.childNodes[i], true, true);
                if (child) container.grab(child);
            }
            return container;
        }) || container.set('html', text);
    }
});
