/// <reference path="prototype.js" />
var HO = {
	Version: '1.0.2',
	Copyright: 'Copyright (c)HarborObjects',
	Author: 'Glenn Byron',
	prototypeVersion: parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1])
}

// Prototype now needs to be at least version 1.6, and this function
// does not check for release canidate 1 (rc1)
if((typeof Prototype=='undefined') || HO.prototypeVersion < 1.6)
    throw ("HO requires the Prototype JavaScript framework >= 1.6");
      
HO.isIE = navigator.appVersion.match(/MSIE/) == "MSIE";

// ************************************************
// Extend JavaScript String object
//
// The following functions have been added
// to the JavaScirpt String function.
//
// trimLeft()
// trimRight()
// trim()
// padLeft()
// padRight()
// left(n)
// right(n)
// cleanSeperators() - used to remove common seperators in phone numbers, etc.
// cleanCurrency()
// restoreCurrency()
// removeCommas() - for numbers
// addCommas() - for numbers
// restoreUSPhone()
// isNumeric()
// isSignedInteger()
// isPostiveInteger()
// isUSCurrency()
// isUSDate()
// isUSZipCode()
// isUSPhone()
// ************************************************
Object.extend(String.prototype, {
    trimLeft: function() {
        /// <summary>romoves spaces from left side</summary>
        /// <returns>string</returns>
        return this.replace(/^\s+/, '');
    },
    trimRight: function() {
        /// <summary>romoves spaces from right side</summary>
        /// <returns>string</returns>
        return this.replace(/\s+$/, '');
    },
    trim: function() {
        /// <summary>romoves spaces from both sides</summary>
        /// <returns>string</returns>
        return this.trimRight().trimLeft()
    },

    padLeft: function(chr, num) {
        /// <summary>right-aligns the characters in this instance</summary>
        /// <param name="chr">padding character</param>
        /// <param name="num">minumum width</param>
        /// <returns>string</returns>
        var re = new RegExp(".{" + num + "}$");
        var pad = "";

        do {
            pad += chr;
        } while (pad.length < num)
        return re.exec(pad + this);
    },

    padRight: function(chr, num) {
        /// <summary>left-aligns the characters in this instance</summary>
        /// <param name="chr">padding character</param>
        /// <param name="num">minumum width</param>
        /// <returns>string</returns>
        var re = new RegExp("^.{" + num + "}");
        var pad = "";

        do {
            pad += chr;
        } while (pad.length < num)
        return re.exec(this + pad);
    },

    left: function(num) {
    /// <summary>left part of the string</summary>
    /// <param name="num">number of characters</param>
    /// <returns>string</returns>
    if (num <= 0)
            return "";
        else if (num > String(this).length)
            return this;
        else
            return String(this).substring(0, num);

    },
    right: function(num) {
    /// <summary>right part of the string</summary>
    /// <param name="num">number of characters</param>
    /// <returns>string</returns>
        if (num <= 0)
            return "";
        else if (num > String(this).length)
            return this;
        else {
            var iLen = String(this).length;
            return String(this).substring(iLen, iLen - num);
        }
    },
    cleanSeperators: function() {
        /// <summary>remove common seperators in phone numbers, etc.</summary>
        /// <returns>string</returns>
        return this.replace(/[\(\)\.\-\/\s,]/g, "");
    },

    cleanCurrency: function() {
        /// <summary>removes non-numeric currency characters</summary>
        /// <returns>string</returns>
        var objRegExp = /\(/;
        var strMinus = '';

        if (objRegExp.test(this)) strMinus = '-';

        objRegExp = /\)|\(|[,]/g;
        var inputValue = this.replace(objRegExp, '');

        if (inputValue.indexOf('$') <= 0) {
            inputValue = inputValue.substring(1, inputValue.length);
        }
        return strMinus + inputValue;
    },

    restoreCurrency: function() {
        /// <summary>formats a numeric string to currency</summary>
        /// <returns>string</returns>
        var objRegExp = /-?[0-9]+\.[0-9]{2}$/;

        if (objRegExp.test(this)) {
            objRegExp.compile('^-');
            var inputValue = this.addCommas();
            if (objRegExp.test(inputValue)) {
                inputValue = '(' + inputValue.replace(objRegExp, '') + ')';
            }
            return '$' + inputValue;
        } else
            return this;
    },

    removeCommas: function() {
        /// <summary>removes commas</summary>
        /// <returns>string</returns>
        var objRegExp = /,/g;
        return this.replace(objRegExp, '');
    },

    addCommas: function() {
        /// <summary>adds commas to numeric string</summary>
        /// <returns>string</returns>

        var inputValue = this.trim().removeCommas();
        len = inputValue.indexOf(".");
        if (len == -1) {
            len = inputValue.length;
            out = "";
        } else {
            out = inputValue.substring(len);
        }

        for (var i = 0; i < len; i++) {
            if (i != 0 && i % 3 == 0) {
                out = "," + out
            }
            out = inputValue.charAt(len - i - 1) + out
        }
        return out
    },

    restoreUSPhone: function() {
        /// <summary>formats a 10 character numeric string to a phone number format</summary>
        /// <returns>string</returns>

        if (this == '') return this;
        var n1 = this.substring(0, 3)
        var n2 = this.substring(3, 6)
        var n3 = this.substring(6, 10)
        return ("(" + n1 + ") " + n2 + "-" + n3)
    },

    //****************************
    //Check for types of things
    //****************************
    isSignedNumeric: function() {
        /// <summary>determines if numeric string is a number</summary>
        /// <returns>boolean</returns>
        return /^[-+]?\d+(\.\d+)?$/.test(this.trim());
    },

    isPositiveNumeric: function() {
        /// <summary>determines if numeric string is a number</summary>
        /// <returns>boolean</returns>
        return /^\d+(\.\d+)?$/.test(this.trim());
    },

    isSignedInteger: function() {
        /// <summary>determines if numeric string is a signed integer</summary>
        /// <returns>boolean</returns>
        return /^[-+]?\d+$/.test(this.trim());
    },

    isPostiveInteger: function() {
        /// <summary>determines if numeric string is a postive integer</summary>
        /// <returns>boolean</returns>
        return /^\d+$/.test(this.trim());
    },

    isUSCurrency: function() {
        /// <summary>if numeric string is currency format that allows optional $, optional \";-\" (MinusSignNegative) OR \"()\" (ParenNegative) but not both, optional cents, and optional commas separating thousands. Minus sign can be before or after $, but parens must be outside the $.</summary>
        /// <returns>boolean</returns>
        return /^\$?\-?([1-9]{1}[0-9]{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\-?\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\(\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))\)$/.test(this.trim());
    },

    isUSDate: function() {
        /// <summary>determines if numeric string is a US Date</summary>
        /// <returns>boolean</returns>
        var objRegExp = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/

        //check to see if in correct format
        if (!objRegExp.test(this))
            return false; //doesn't match pattern, bad date
        else {
            var strSeparator = this.substring(2, 3) //find date separator
            var arrayDate = this.split(strSeparator); //split date into month, day, year

            var arrayLookup = {
                '01': 31, '03': 31, '04': 30, '05': 31, '06': 30, '07': 31,
                '08': 31, '09': 30, '10': 31, '11': 30, '12': 31
            };

            var intDay = parseInt(arrayDate[1], 10);

            //check if month value and day value agree
            if (arrayLookup[arrayDate[0]] != null) {
                if (intDay <= arrayLookup[arrayDate[0]] && intDay != 0)
                    return true;
            }

            var intMonth = parseInt(arrayDate[0], 10);
            if (intMonth == 2) {
                var intYear = parseInt(arrayDate[2]);
                if (intDay > 0 && intDay < 29) {
                    return true;
                } else if (intDay == 29) {
                    if ((intYear % 4 == 0) && (intYear % 100 != 0) || (intYear % 400 == 0)) {
                        // year div by 4 and ((not div by 100) or div by 400) -> ok
                        return true;
                    }
                }
            }
        }
        return false; //any other values, bad date
    },

    isUSTime: function(checkAMPM) {

        /// <summary>determines if a string is a US time</summary>
        // Expected format is HH:MM:SS AM/PM. The seconds and AM/PM are optional.
        /// <returns>boolean</returns>

        var objRegExp = /^(\d{1,2}):(\d{2})(:(\d{2}))?(\s?(AM|am|PM|pm))?$/;

        //check to see if in correct format
        if (!objRegExp.test(this))
            return false; //doesn't match pattern, bad time
        else {
            var matchArray = this.match(objRegExp);
            hour = matchArray[1];
            minute = matchArray[2];
            second = matchArray[4];
            ampm = matchArray[6];

            if (second == "") { second = null; }
            if (ampm == "") { ampm = null }

            //Hour must be between 1 and 12 or 0 and 23 for military time
            if (hour < 0 || hour > 23) {
                return false;
            }
            //must specify AM or PM
            if (hour <= 12 && ampm == null && checkAMPM == true) {
                return false;
            }
            //can't specify AM or PM for military time
            if (hour > 12 && ampm != null) {
                return false;
            }
            //Minute must be between 0 and 59
            if (minute < 0 || minute > 59) {
                return false;
            }
            //Second must be between 0 and 59
            if (second != null && (second < 0 || second > 59)) {
                return false;
            }
            return true;
        }
        return false; //any other values, bad time
    },

    isUSZipCode: function() {
        /// <summary>determines if string is a 5 digit US Zip Code</summary>
        /// <returns>boolean</returns>
        var objRegExp = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
        return objRegExp.test(this);
    },

    isUSPhone: function() {
        /// <summary>determines if string is a US phone number with area code</summary>
        /// <returns>boolean</returns>
        var cleanNumber = this.cleanSeperators();
        if ((cleanNumber.isPostiveInteger() && cleanNumber.cleanSeperators().length == 10) || cleanNumber == '') {
            return true;
        } else {
            return false;
        }
    }
}, false);

// ******************************
// Two functions to get the postion and size 
// of the current window so you can postion 
// things like windows
// 
// getPageScroll()
// getPageSize()
// ******************************
HO.WindowUtilities = {
 	getPageScroll :function() {
		var yScroll;

		if (self.pageYOffset) {
			yScroll = self.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
			yScroll = document.documentElement.scrollTop;
		} else if (document.body) {// all other Explorers
			yScroll = document.body.scrollTop;
		}
		return yScroll;
	},

	// getPageSize()
	// Returns properties with page width, height and window width, height
	// Core code from - quirksmode.org
	// Edit for Firefox by pHaez
	// Edit to return properties and not an array by Glenn Byron @ Dynamic Digital Media Group
	getPageSize: function(){
		var xScroll, yScroll;
	
		if (window.innerHeight && window.scrollMaxY) {	
			xScroll = document.body.scrollWidth;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
	
		var windowWidth, windowHeight;
		if (self.innerHeight) {	// all except Explorer
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	
	
		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		} else { 
			pageHeight = yScroll;
		}

		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){	
			pageWidth = windowWidth;
		} else {
			pageWidth = xScroll;
		}
		return {pageWidth: pageWidth, pageHeight: pageHeight, windowWidth: windowWidth, windowHeight: windowHeight};
	}
}
