(function($) {
    var methods = {
        dateIsValid: function(dtStr) {
            /**
            * jQuery static function adaptation of the DHTML date validation script as
            * found on SmartWebby.com (http://www.smartwebby.com/dhtml/)
            */
            var dtCh = "/";
            var minYear = 1900;
            var maxYear = 2100;

            function isInteger(s) {
                var i;
                for (i = 0; i < s.length; i++) {
                    var c = s.charAt(i);
                    if (((c < "0") || (c > "9"))) return false;
                }
                return true;
            }
            function stripCharsInBag(s, bag) {
                var i;
                var 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) {
                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;
            }
            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);
            strYr = strYear;
            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 || pos2 == -1) {
                return false;
            }
            if (strMonth.length < 1 || month < 1 || month > 12) {
                return false
            }
            if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > daysInFebruary(year)) || day > daysInMonth[month]) {
                return false
            }
            if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear) {
                return false
            }
            if (dtStr.indexOf(dtCh, pos2 + 1) != -1 || isInteger(stripCharsInBag(dtStr, dtCh)) == false) {
                return false;
            }
            return true;
        },
        IsEmail: function(text) {
            return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(text);
        },
        IsBlank: function(text) {
            return $.trim(text) == "";
        }
    }
    $.extend(methods);
    if (jQuery.validator) {
        jQuery.validator.addMethod("validdate", function(value, element) {
            return this.optional(element) || $.dateIsValid(value);
        }, "Please enter a valid date");
    }
    $.fn.collapsible = function(opts) {
        $.fn.collapsible.defaults = {
            multi: true,
            toggleClass: "open"
        };
        var opts = $.extend({}, $.fn.collapsible.defaults, opts);
        var frag = $.param.fragment();
        return this.each(function(idx) {
            if (opts.multi || !frag || $(this).attr("id") != frag) $(this).removeClass("open").children(":heading:first").nextAll().hide();
            else if ($(this).attr("id") == frag) $(this).addClass("open").children().show();
            $(this).children(":heading:first").click(function() {
                var cEl = $(this).parent();
                $(this).nextAll().toggle();
                $(cEl).toggleClass(opts.toggleClass);
                if (!opts.multi) {
                    if ($(cEl).hasClass(opts.toggleClass) && $(cEl).attr("id")) {
                        $(cEl).siblings("." + opts.toggleClass).removeClass(opts.toggleClass).children(":heading:first").siblings().hide();
                        window.location.hash = $(cEl).attr("id");
                    }
                }
            });
        });
    }
})(jQuery);