corrade-http-templates – Rev 62

Subversion Repositories:
Rev:
/*!
 * Globalize
 *
 * http://github.com/jquery/globalize
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( window, undefined ) {

var Globalize,
        // private variables
        regexHex,
        regexInfinity,
        regexParseFloat,
        regexTrim,
        // private JavaScript utility functions
        arrayIndexOf,
        endsWith,
        extend,
        isArray,
        isFunction,
        isObject,
        startsWith,
        trim,
        truncate,
        zeroPad,
        // private Globalization utility functions
        appendPreOrPostMatch,
        expandFormat,
        formatDate,
        formatNumber,
        getTokenRegExp,
        getEra,
        getEraYear,
        parseExact,
        parseNegativePattern;

// Global variable (Globalize) or CommonJS module (globalize)
Globalize = function( cultureSelector ) {
        return new Globalize.prototype.init( cultureSelector );
};

if ( typeof require !== "undefined" &&
        typeof exports !== "undefined" &&
        typeof module !== "undefined" ) {
        // Assume CommonJS
        module.exports = Globalize;
} else {
        // Export as global variable
        window.Globalize = Globalize;
}

Globalize.cultures = {};

Globalize.prototype = {
        constructor: Globalize,
        init: function( cultureSelector ) {
                this.cultures = Globalize.cultures;
                this.cultureSelector = cultureSelector;

                return this;
        }
};
Globalize.prototype.init.prototype = Globalize.prototype;

// 1. When defining a culture, all fields are required except the ones stated as optional.
// 2. Each culture should have a ".calendars" object with at least one calendar named "standard"
//    which serves as the default calendar in use by that culture.
// 3. Each culture should have a ".calendar" object which is the current calendar being used,
//    it may be dynamically changed at any time to one of the calendars in ".calendars".
Globalize.cultures[ "default" ] = {
        // A unique name for the culture in the form <language code>-<country/region code>
        name: "en",
        // the name of the culture in the english language
        englishName: "English",
        // the name of the culture in its own language
        nativeName: "English",
        // whether the culture uses right-to-left text
        isRTL: false,
        // "language" is used for so-called "specific" cultures.
        // For example, the culture "es-CL" means "Spanish, in Chili".
        // It represents the Spanish-speaking culture as it is in Chili,
        // which might have different formatting rules or even translations
        // than Spanish in Spain. A "neutral" culture is one that is not
        // specific to a region. For example, the culture "es" is the generic
        // Spanish culture, which may be a more generalized version of the language
        // that may or may not be what a specific culture expects.
        // For a specific culture like "es-CL", the "language" field refers to the
        // neutral, generic culture information for the language it is using.
        // This is not always a simple matter of the string before the dash.
        // For example, the "zh-Hans" culture is netural (Simplified Chinese).
        // And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
        // field is "zh-CHS", not "zh".
        // This field should be used to navigate from a specific culture to it's
        // more general, neutral culture. If a culture is already as general as it
        // can get, the language may refer to itself.
        language: "en",
        // numberFormat defines general number formatting rules, like the digits in
        // each grouping, the group separator, and how negative numbers are displayed.
        numberFormat: {
                // [negativePattern]
                // Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
                // but is still defined as an array for consistency with them.
                //   negativePattern: one of "(n)|-n|- n|n-|n -"
                pattern: [ "-n" ],
                // number of decimal places normally shown
                decimals: 2,
                // string that separates number groups, as in 1,000,000
                ",": ",",
                // string that separates a number from the fractional portion, as in 1.99
                ".": ".",
                // array of numbers indicating the size of each number group.
                // TODO: more detailed description and example
                groupSizes: [ 3 ],
                // symbol used for positive numbers
                "+": "+",
                // symbol used for negative numbers
                "-": "-",
                // symbol used for NaN (Not-A-Number)
                "NaN": "NaN",
                // symbol used for Negative Infinity
                negativeInfinity: "-Infinity",
                // symbol used for Positive Infinity
                positiveInfinity: "Infinity",
                percent: {
                        // [negativePattern, positivePattern]
                        //   negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
                        //   positivePattern: one of "n %|n%|%n|% n"
                        pattern: [ "-n %", "n %" ],
                        // number of decimal places normally shown
                        decimals: 2,
                        // array of numbers indicating the size of each number group.
                        // TODO: more detailed description and example
                        groupSizes: [ 3 ],
                        // string that separates number groups, as in 1,000,000
                        ",": ",",
                        // string that separates a number from the fractional portion, as in 1.99
                        ".": ".",
                        // symbol used to represent a percentage
                        symbol: "%"
                },
                currency: {
                        // [negativePattern, positivePattern]
                        //   negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
                        //   positivePattern: one of "$n|n$|$ n|n $"
                        pattern: [ "($n)", "$n" ],
                        // number of decimal places normally shown
                        decimals: 2,
                        // array of numbers indicating the size of each number group.
                        // TODO: more detailed description and example
                        groupSizes: [ 3 ],
                        // string that separates number groups, as in 1,000,000
                        ",": ",",
                        // string that separates a number from the fractional portion, as in 1.99
                        ".": ".",
                        // symbol used to represent currency
                        symbol: "$"
                }
        },
        // calendars defines all the possible calendars used by this culture.
        // There should be at least one defined with name "standard", and is the default
        // calendar used by the culture.
        // A calendar contains information about how dates are formatted, information about
        // the calendar's eras, a standard set of the date formats,
        // translations for day and month names, and if the calendar is not based on the Gregorian
        // calendar, conversion functions to and from the Gregorian calendar.
        calendars: {
                standard: {
                        // name that identifies the type of calendar this is
                        name: "Gregorian_USEnglish",
                        // separator of parts of a date (e.g. "/" in 11/05/1955)
                        "/": "/",
                        // separator of parts of a time (e.g. ":" in 05:44 PM)
                        ":": ":",
                        // the first day of the week (0 = Sunday, 1 = Monday, etc)
                        firstDay: 0,
                        days: {
                                // full day names
                                names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
                                // abbreviated day names
                                namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
                                // shortest day names
                                namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
                        },
                        months: {
                                // full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
                                names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
                                // abbreviated month names
                                namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
                        },
                        // AM and PM designators in one of these forms:
                        // The usual view, and the upper and lower case versions
                        //   [ standard, lowercase, uppercase ]
                        // The culture does not use AM or PM (likely all standard date formats use 24 hour time)
                        //   null
                        AM: [ "AM", "am", "AM" ],
                        PM: [ "PM", "pm", "PM" ],
                        eras: [
                                // eras in reverse chronological order.
                                // name: the name of the era in this culture (e.g. A.D., C.E.)
                                // start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
                                // offset: offset in years from gregorian calendar
                                {
                                        "name": "A.D.",
                                        "start": null,
                                        "offset": 0
                                }
                        ],
                        // when a two digit year is given, it will never be parsed as a four digit
                        // year greater than this year (in the appropriate era for the culture)
                        // Set it as a full year (e.g. 2029) or use an offset format starting from
                        // the current year: "+19" would correspond to 2029 if the current year 2010.
                        twoDigitYearMax: 2029,
                        // set of predefined date and time patterns used by the culture
                        // these represent the format someone in this culture would expect
                        // to see given the portions of the date that are shown.
                        patterns: {
                                // short date pattern
                                d: "M/d/yyyy",
                                // long date pattern
                                D: "dddd, MMMM dd, yyyy",
                                // short time pattern
                                t: "h:mm tt",
                                // long time pattern
                                T: "h:mm:ss tt",
                                // long date, short time pattern
                                f: "dddd, MMMM dd, yyyy h:mm tt",
                                // long date, long time pattern
                                F: "dddd, MMMM dd, yyyy h:mm:ss tt",
                                // month/day pattern
                                M: "MMMM dd",
                                // month/year pattern
                                Y: "yyyy MMMM",
                                // S is a sortable format that does not vary by culture
                                S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
                        }
                        // optional fields for each calendar:
                        /*
                        monthsGenitive:
                                Same as months but used when the day preceeds the month.
                                Omit if the culture has no genitive distinction in month names.
                                For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
                        convert:
                                Allows for the support of non-gregorian based calendars. This convert object is used to
                                to convert a date to and from a gregorian calendar date to handle parsing and formatting.
                                The two functions:
                                        fromGregorian( date )
                                                Given the date as a parameter, return an array with parts [ year, month, day ]
                                                corresponding to the non-gregorian based year, month, and day for the calendar.
                                        toGregorian( year, month, day )
                                                Given the non-gregorian year, month, and day, return a new Date() object
                                                set to the corresponding date in the gregorian calendar.
                        */
                }
        },
        // For localized strings
        messages: {}
};

Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;

Globalize.cultures.en = Globalize.cultures[ "default" ];

Globalize.cultureSelector = "en";

//
// private variables
//

regexHex = /^0x[a-f0-9]+$/i;
regexInfinity = /^[+\-]?infinity$/i;
regexParseFloat = /^[+\-]?\d*\.?\d*(e[+\-]?\d+)?$/;
regexTrim = /^\s+|\s+$/g;

//
// private JavaScript utility functions
//

arrayIndexOf = function( array, item ) {
        if ( array.indexOf ) {
                return array.indexOf( item );
        }
        for ( var i = 0, length = array.length; i < length; i++ ) {
                if ( array[i] === item ) {
                        return i;
                }
        }
        return -1;
};

endsWith = function( value, pattern ) {
        return value.substr( value.length - pattern.length ) === pattern;
};

extend = function() {
        var options, name, src, copy, copyIsArray, clone,
                target = arguments[0] || {},
                i = 1,
                length = arguments.length,
                deep = false;

        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
        }

        // Handle case when target is a string or something (possible in deep copy)
        if ( typeof target !== "object" && !isFunction(target) ) {
                target = {};
        }

        for ( ; i < length; i++ ) {
                // Only deal with non-null/undefined values
                if ( (options = arguments[ i ]) != null ) {
                        // Extend the base object
                        for ( name in options ) {
                                src = target[ name ];
                                copy = options[ name ];

                                // Prevent never-ending loop
                                if ( target === copy ) {
                                        continue;
                                }

                                // Recurse if we're merging plain objects or arrays
                                if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
                                        if ( copyIsArray ) {
                                                copyIsArray = false;
                                                clone = src && isArray(src) ? src : [];

                                        } else {
                                                clone = src && isObject(src) ? src : {};
                                        }

                                        // Never move original objects, clone them
                                        target[ name ] = extend( deep, clone, copy );

                                // Don't bring in undefined values
                                } else if ( copy !== undefined ) {
                                        target[ name ] = copy;
                                }
                        }
                }
        }

        // Return the modified object
        return target;
};

isArray = Array.isArray || function( obj ) {
        return Object.prototype.toString.call( obj ) === "[object Array]";
};

isFunction = function( obj ) {
        return Object.prototype.toString.call( obj ) === "[object Function]";
};

isObject = function( obj ) {
        return Object.prototype.toString.call( obj ) === "[object Object]";
};

startsWith = function( value, pattern ) {
        return value.indexOf( pattern ) === 0;
};

trim = function( value ) {
        return ( value + "" ).replace( regexTrim, "" );
};

truncate = function( value ) {
        if ( isNaN( value ) ) {
                return NaN;
        }
        return Math[ value < 0 ? "ceil" : "floor" ]( value );
};

zeroPad = function( str, count, left ) {
        var l;
        for ( l = str.length; l < count; l += 1 ) {
                str = ( left ? ("0" + str) : (str + "0") );
        }
        return str;
};

//
// private Globalization utility functions
//

appendPreOrPostMatch = function( preMatch, strings ) {
        // appends pre- and post- token match strings while removing escaped characters.
        // Returns a single quote count which is used to determine if the token occurs
        // in a string literal.
        var quoteCount = 0,
                escaped = false;
        for ( var i = 0, il = preMatch.length; i < il; i++ ) {
                var c = preMatch.charAt( i );
                switch ( c ) {
                        case "\'":
                                if ( escaped ) {
                                        strings.push( "\'" );
                                }
                                else {
                                        quoteCount++;
                                }
                                escaped = false;
                                break;
                        case "\\":
                                if ( escaped ) {
                                        strings.push( "\\" );
                                }
                                escaped = !escaped;
                                break;
                        default:
                                strings.push( c );
                                escaped = false;
                                break;
                }
        }
        return quoteCount;
};

expandFormat = function( cal, format ) {
        // expands unspecified or single character date formats into the full pattern.
        format = format || "F";
        var pattern,
                patterns = cal.patterns,
                len = format.length;
        if ( len === 1 ) {
                pattern = patterns[ format ];
                if ( !pattern ) {
                        throw "Invalid date format string \'" + format + "\'.";
                }
                format = pattern;
        }
        else if ( len === 2 && format.charAt(0) === "%" ) {
                // %X escape format -- intended as a custom format string that is only one character, not a built-in format.
                format = format.charAt( 1 );
        }
        return format;
};

formatDate = function( value, format, culture ) {
        var cal = culture.calendar,
                convert = cal.convert,
                ret;

        if ( !format || !format.length || format === "i" ) {
                if ( culture && culture.name.length ) {
                        if ( convert ) {
                                // non-gregorian calendar, so we cannot use built-in toLocaleString()
                                ret = formatDate( value, cal.patterns.F, culture );
                        }
                        else {
                                var eraDate = new Date( value.getTime() ),
                                        era = getEra( value, cal.eras );
                                eraDate.setFullYear( getEraYear(value, cal, era) );
                                ret = eraDate.toLocaleString();
                        }
                }
                else {
                        ret = value.toString();
                }
                return ret;
        }

        var eras = cal.eras,
                sortable = format === "s";
        format = expandFormat( cal, format );

        // Start with an empty string
        ret = [];
        var hour,
                zeros = [ "0", "00", "000" ],
                foundDay,
                checkedDay,
                dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
                quoteCount = 0,
                tokenRegExp = getTokenRegExp(),
                converted;

        function padZeros( num, c ) {
                var r, s = num + "";
                if ( c > 1 && s.length < c ) {
                        r = ( zeros[c - 2] + s);
                        return r.substr( r.length - c, c );
                }
                else {
                        r = s;
                }
                return r;
        }

        function hasDay() {
                if ( foundDay || checkedDay ) {
                        return foundDay;
                }
                foundDay = dayPartRegExp.test( format );
                checkedDay = true;
                return foundDay;
        }

        function getPart( date, part ) {
                if ( converted ) {
                        return converted[ part ];
                }
                switch ( part ) {
                        case 0:
                                return date.getFullYear();
                        case 1:
                                return date.getMonth();
                        case 2:
                                return date.getDate();
                        default:
                                throw "Invalid part value " + part;
                }
        }

        if ( !sortable && convert ) {
                converted = convert.fromGregorian( value );
        }

        for ( ; ; ) {
                // Save the current index
                var index = tokenRegExp.lastIndex,
                        // Look for the next pattern
                        ar = tokenRegExp.exec( format );

                // Append the text before the pattern (or the end of the string if not found)
                var preMatch = format.slice( index, ar ? ar.index : format.length );
                quoteCount += appendPreOrPostMatch( preMatch, ret );

                if ( !ar ) {
                        break;
                }

                // do not replace any matches that occur inside a string literal.
                if ( quoteCount % 2 ) {
                        ret.push( ar[0] );
                        continue;
                }

                var current = ar[ 0 ],
                        clength = current.length;

                switch ( current ) {
                        case "ddd":
                                //Day of the week, as a three-letter abbreviation
                        case "dddd":
                                // Day of the week, using the full name
                                var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
                                ret.push( names[value.getDay()] );
                                break;
                        case "d":
                                // Day of month, without leading zero for single-digit days
                        case "dd":
                                // Day of month, with leading zero for single-digit days
                                foundDay = true;
                                ret.push(
                                        padZeros( getPart(value, 2), clength )
                                );
                                break;
                        case "MMM":
                                // Month, as a three-letter abbreviation
                        case "MMMM":
                                // Month, using the full name
                                var part = getPart( value, 1 );
                                ret.push(
                                        ( cal.monthsGenitive && hasDay() ) ?
                                        ( cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ] ) :
                                        ( cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ] )
                                );
                                break;
                        case "M":
                                // Month, as digits, with no leading zero for single-digit months
                        case "MM":
                                // Month, as digits, with leading zero for single-digit months
                                ret.push(
                                        padZeros( getPart(value, 1) + 1, clength )
                                );
                                break;
                        case "y":
                                // Year, as two digits, but with no leading zero for years less than 10
                        case "yy":
                                // Year, as two digits, with leading zero for years less than 10
                        case "yyyy":
                                // Year represented by four full digits
                                part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
                                if ( clength < 4 ) {
                                        part = part % 100;
                                }
                                ret.push(
                                        padZeros( part, clength )
                                );
                                break;
                        case "h":
                                // Hours with no leading zero for single-digit hours, using 12-hour clock
                        case "hh":
                                // Hours with leading zero for single-digit hours, using 12-hour clock
                                hour = value.getHours() % 12;
                                if ( hour === 0 ) hour = 12;
                                ret.push(
                                        padZeros( hour, clength )
                                );
                                break;
                        case "H":
                                // Hours with no leading zero for single-digit hours, using 24-hour clock
                        case "HH":
                                // Hours with leading zero for single-digit hours, using 24-hour clock
                                ret.push(
                                        padZeros( value.getHours(), clength )
                                );
                                break;
                        case "m":
                                // Minutes with no leading zero for single-digit minutes
                        case "mm":
                                // Minutes with leading zero for single-digit minutes
                                ret.push(
                                        padZeros( value.getMinutes(), clength )
                                );
                                break;
                        case "s":
                                // Seconds with no leading zero for single-digit seconds
                        case "ss":
                                // Seconds with leading zero for single-digit seconds
                                ret.push(
                                        padZeros( value.getSeconds(), clength )
                                );
                                break;
                        case "t":
                                // One character am/pm indicator ("a" or "p")
                        case "tt":
                                // Multicharacter am/pm indicator
                                part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
                                ret.push( clength === 1 ? part.charAt(0) : part );
                                break;
                        case "f":
                                // Deciseconds
                        case "ff":
                                // Centiseconds
                        case "fff":
                                // Milliseconds
                                ret.push(
                                        padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
                                );
                                break;
                        case "z":
                                // Time zone offset, no leading zero
                        case "zz":
                                // Time zone offset with leading zero
                                hour = value.getTimezoneOffset() / 60;
                                ret.push(
                                        ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
                                );
                                break;
                        case "zzz":
                                // Time zone offset with leading zero
                                hour = value.getTimezoneOffset() / 60;
                                ret.push(
                                        ( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 ) +
                                        // Hard coded ":" separator, rather than using cal.TimeSeparator
                                        // Repeated here for consistency, plus ":" was already assumed in date parsing.
                                        ":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
                                );
                                break;
                        case "g":
                        case "gg":
                                if ( cal.eras ) {
                                        ret.push(
                                                cal.eras[ getEra(value, eras) ].name
                                        );
                                }
                                break;
                case "/":
                        ret.push( cal["/"] );
                        break;
                default:
                        throw "Invalid date format pattern \'" + current + "\'.";
                }
        }
        return ret.join( "" );
};

// formatNumber
(function() {
        var expandNumber;

        expandNumber = function( number, precision, formatInfo ) {
                var groupSizes = formatInfo.groupSizes,
                        curSize = groupSizes[ 0 ],
                        curGroupIndex = 1,
                        factor = Math.pow( 10, precision ),
                        rounded = Math.round( number * factor ) / factor;

                if ( !isFinite(rounded) ) {
                        rounded = number;
                }
                number = rounded;

                var numberString = number+"",
                        right = "",
                        split = numberString.split( /e/i ),
                        exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
                numberString = split[ 0 ];
                split = numberString.split( "." );
                numberString = split[ 0 ];
                right = split.length > 1 ? split[ 1 ] : "";

                if ( exponent > 0 ) {
                        right = zeroPad( right, exponent, false );
                        numberString += right.slice( 0, exponent );
                        right = right.substr( exponent );
                }
                else if ( exponent < 0 ) {
                        exponent = -exponent;
                        numberString = zeroPad( numberString, exponent + 1, true );
                        right = numberString.slice( -exponent, numberString.length ) + right;
                        numberString = numberString.slice( 0, -exponent );
                }

                if ( precision > 0 ) {
                        right = formatInfo[ "." ] +
                                ( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
                }
                else {
                        right = "";
                }

                var stringIndex = numberString.length - 1,
                        sep = formatInfo[ "," ],
                        ret = "";

                while ( stringIndex >= 0 ) {
                        if ( curSize === 0 || curSize > stringIndex ) {
                                return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
                        }
                        ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );

                        stringIndex -= curSize;

                        if ( curGroupIndex < groupSizes.length ) {
                                curSize = groupSizes[ curGroupIndex ];
                                curGroupIndex++;
                        }
                }

                return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
        };

        formatNumber = function( value, format, culture ) {
                if ( !isFinite(value) ) {
                        if ( value === Infinity ) {
                                return culture.numberFormat.positiveInfinity;
                        }
                        if ( value === -Infinity ) {
                                return culture.numberFormat.negativeInfinity;
                        }
                        return culture.numberFormat.NaN;
                }
                if ( !format || format === "i" ) {
                        return culture.name.length ? value.toLocaleString() : value.toString();
                }
                format = format || "D";

                var nf = culture.numberFormat,
                        number = Math.abs( value ),
                        precision = -1,
                        pattern;
                if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );

                var current = format.charAt( 0 ).toUpperCase(),
                        formatInfo;

                switch ( current ) {
                        case "D":
                                pattern = "n";
                                number = truncate( number );
                                if ( precision !== -1 ) {
                                        number = zeroPad( "" + number, precision, true );
                                }
                                if ( value < 0 ) number = "-" + number;
                                break;
                        case "N":
                                formatInfo = nf;
                                /* falls through */
                        case "C":
                                formatInfo = formatInfo || nf.currency;
                                /* falls through */
                        case "P":
                                formatInfo = formatInfo || nf.percent;
                                pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
                                if ( precision === -1 ) precision = formatInfo.decimals;
                                number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
                                break;
                        default:
                                throw "Bad number format specifier: " + current;
                }

                var patternParts = /n|\$|-|%/g,
                        ret = "";
                for ( ; ; ) {
                        var index = patternParts.lastIndex,
                                ar = patternParts.exec( pattern );

                        ret += pattern.slice( index, ar ? ar.index : pattern.length );

                        if ( !ar ) {
                                break;
                        }

                        switch ( ar[0] ) {
                                case "n":
                                        ret += number;
                                        break;
                                case "$":
                                        ret += nf.currency.symbol;
                                        break;
                                case "-":
                                        // don't make 0 negative
                                        if ( /[1-9]/.test(number) ) {
                                                ret += nf[ "-" ];
                                        }
                                        break;
                                case "%":
                                        ret += nf.percent.symbol;
                                        break;
                        }
                }

                return ret;
        };

}());

getTokenRegExp = function() {
        // regular expression for matching date and time tokens in format strings.
        return (/\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g);
};

getEra = function( date, eras ) {
        if ( !eras ) return 0;
        var start, ticks = date.getTime();
        for ( var i = 0, l = eras.length; i < l; i++ ) {
                start = eras[ i ].start;
                if ( start === null || ticks >= start ) {
                        return i;
                }
        }
        return 0;
};

getEraYear = function( date, cal, era, sortable ) {
        var year = date.getFullYear();
        if ( !sortable && cal.eras ) {
                // convert normal gregorian year to era-shifted gregorian
                // year by subtracting the era offset
                year -= cal.eras[ era ].offset;
        }
        return year;
};

// parseExact
(function() {
        var expandYear,
                getDayIndex,
                getMonthIndex,
                getParseRegExp,
                outOfRange,
                toUpper,
                toUpperArray;

        expandYear = function( cal, year ) {
                // expands 2-digit year into 4 digits.
                if ( year < 100 ) {
                        var now = new Date(),
                                era = getEra( now ),
                                curr = getEraYear( now, cal, era ),
                                twoDigitYearMax = cal.twoDigitYearMax;
                        twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
                        year += curr - ( curr % 100 );
                        if ( year > twoDigitYearMax ) {
                                year -= 100;
                        }
                }
                return year;
        };

        getDayIndex = function  ( cal, value, abbr ) {
                var ret,
                        days = cal.days,
                        upperDays = cal._upperDays;
                if ( !upperDays ) {
                        cal._upperDays = upperDays = [
                                toUpperArray( days.names ),
                                toUpperArray( days.namesAbbr ),
                                toUpperArray( days.namesShort )
                        ];
                }
                value = toUpper( value );
                if ( abbr ) {
                        ret = arrayIndexOf( upperDays[1], value );
                        if ( ret === -1 ) {
                                ret = arrayIndexOf( upperDays[2], value );
                        }
                }
                else {
                        ret = arrayIndexOf( upperDays[0], value );
                }
                return ret;
        };

        getMonthIndex = function( cal, value, abbr ) {
                var months = cal.months,
                        monthsGen = cal.monthsGenitive || cal.months,
                        upperMonths = cal._upperMonths,
                        upperMonthsGen = cal._upperMonthsGen;
                if ( !upperMonths ) {
                        cal._upperMonths = upperMonths = [
                                toUpperArray( months.names ),
                                toUpperArray( months.namesAbbr )
                        ];
                        cal._upperMonthsGen = upperMonthsGen = [
                                toUpperArray( monthsGen.names ),
                                toUpperArray( monthsGen.namesAbbr )
                        ];
                }
                value = toUpper( value );
                var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
                if ( i < 0 ) {
                        i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
                }
                return i;
        };

        getParseRegExp = function( cal, format ) {
                // converts a format string into a regular expression with groups that
                // can be used to extract date fields from a date string.
                // check for a cached parse regex.
                var re = cal._parseRegExp;
                if ( !re ) {
                        cal._parseRegExp = re = {};
                }
                else {
                        var reFormat = re[ format ];
                        if ( reFormat ) {
                                return reFormat;
                        }
                }

                // expand single digit formats, then escape regular expression characters.
                var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
                        regexp = [ "^" ],
                        groups = [],
                        index = 0,
                        quoteCount = 0,
                        tokenRegExp = getTokenRegExp(),
                        match;

                // iterate through each date token found.
                while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
                        var preMatch = expFormat.slice( index, match.index );
                        index = tokenRegExp.lastIndex;

                        // don't replace any matches that occur inside a string literal.
                        quoteCount += appendPreOrPostMatch( preMatch, regexp );
                        if ( quoteCount % 2 ) {
                                regexp.push( match[0] );
                                continue;
                        }

                        // add a regex group for the token.
                        var m = match[ 0 ],
                                len = m.length,
                                add;
                        switch ( m ) {
                                case "dddd": case "ddd":
                                case "MMMM": case "MMM":
                                case "gg": case "g":
                                        add = "(\\D+)";
                                        break;
                                case "tt": case "t":
                                        add = "(\\D*)";
                                        break;
                                case "yyyy":
                                case "fff":
                                case "ff":
                                case "f":
                                        add = "(\\d{" + len + "})";
                                        break;
                                case "dd": case "d":
                                case "MM": case "M":
                                case "yy": case "y":
                                case "HH": case "H":
                                case "hh": case "h":
                                case "mm": case "m":
                                case "ss": case "s":
                                        add = "(\\d\\d?)";
                                        break;
                                case "zzz":
                                        add = "([+-]?\\d\\d?:\\d{2})";
                                        break;
                                case "zz": case "z":
                                        add = "([+-]?\\d\\d?)";
                                        break;
                                case "/":
                                        add = "(\\/)";
                                        break;
                                default:
                                        throw "Invalid date format pattern \'" + m + "\'.";
                        }
                        if ( add ) {
                                regexp.push( add );
                        }
                        groups.push( match[0] );
                }
                appendPreOrPostMatch( expFormat.slice(index), regexp );
                regexp.push( "$" );

                // allow whitespace to differ when matching formats.
                var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
                        parseRegExp = { "regExp": regexpStr, "groups": groups };

                // cache the regex for this format.
                return re[ format ] = parseRegExp;
        };

        outOfRange = function( value, low, high ) {
                return value < low || value > high;
        };

        toUpper = function( value ) {
                // "he-IL" has non-breaking space in weekday names.
                return value.split( "\u00A0" ).join( " " ).toUpperCase();
        };

        toUpperArray = function( arr ) {
                var results = [];
                for ( var i = 0, l = arr.length; i < l; i++ ) {
                        results[ i ] = toUpper( arr[i] );
                }
                return results;
        };

        parseExact = function( value, format, culture ) {
                // try to parse the date string by matching against the format string
                // while using the specified culture for date field names.
                value = trim( value );
                var cal = culture.calendar,
                        // convert date formats into regular expressions with groupings.
                        // use the regexp to determine the input format and extract the date fields.
                        parseInfo = getParseRegExp( cal, format ),
                        match = new RegExp( parseInfo.regExp ).exec( value );
                if ( match === null ) {
                        return null;
                }
                // found a date format that matches the input.
                var groups = parseInfo.groups,
                        era = null, year = null, month = null, date = null, weekDay = null,
                        hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
                        pmHour = false;
                // iterate the format groups to extract and set the date fields.
                for ( var j = 0, jl = groups.length; j < jl; j++ ) {
                        var matchGroup = match[ j + 1 ];
                        if ( matchGroup ) {
                                var current = groups[ j ],
                                        clength = current.length,
                                        matchInt = parseInt( matchGroup, 10 );
                                switch ( current ) {
                                        case "dd": case "d":
                                                // Day of month.
                                                date = matchInt;
                                                // check that date is generally in valid range, also checking overflow below.
                                                if ( outOfRange(date, 1, 31) ) return null;
                                                break;
                                        case "MMM": case "MMMM":
                                                month = getMonthIndex( cal, matchGroup, clength === 3 );
                                                if ( outOfRange(month, 0, 11) ) return null;
                                                break;
                                        case "M": case "MM":
                                                // Month.
                                                month = matchInt - 1;
                                                if ( outOfRange(month, 0, 11) ) return null;
                                                break;
                                        case "y": case "yy":
                                        case "yyyy":
                                                year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
                                                if ( outOfRange(year, 0, 9999) ) return null;
                                                break;
                                        case "h": case "hh":
                                                // Hours (12-hour clock).
                                                hour = matchInt;
                                                if ( hour === 12 ) hour = 0;
                                                if ( outOfRange(hour, 0, 11) ) return null;
                                                break;
                                        case "H": case "HH":
                                                // Hours (24-hour clock).
                                                hour = matchInt;
                                                if ( outOfRange(hour, 0, 23) ) return null;
                                                break;
                                        case "m": case "mm":
                                                // Minutes.
                                                min = matchInt;
                                                if ( outOfRange(min, 0, 59) ) return null;
                                                break;
                                        case "s": case "ss":
                                                // Seconds.
                                                sec = matchInt;
                                                if ( outOfRange(sec, 0, 59) ) return null;
                                                break;
                                        case "tt": case "t":
                                                // AM/PM designator.
                                                // see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
                                                // the AM tokens. If not, fail the parse for this format.
                                                pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
                                                if (
                                                        !pmHour && (
                                                                !cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
                                                        )
                                                ) return null;
                                                break;
                                        case "f":
                                                // Deciseconds.
                                        case "ff":
                                                // Centiseconds.
                                        case "fff":
                                                // Milliseconds.
                                                msec = matchInt * Math.pow( 10, 3 - clength );
                                                if ( outOfRange(msec, 0, 999) ) return null;
                                                break;
                                        case "ddd":
                                                // Day of week.
                                        case "dddd":
                                                // Day of week.
                                                weekDay = getDayIndex( cal, matchGroup, clength === 3 );
                                                if ( outOfRange(weekDay, 0, 6) ) return null;
                                                break;
                                        case "zzz":
                                                // Time zone offset in +/- hours:min.
                                                var offsets = matchGroup.split( /:/ );
                                                if ( offsets.length !== 2 ) return null;
                                                hourOffset = parseInt( offsets[0], 10 );
                                                if ( outOfRange(hourOffset, -12, 13) ) return null;
                                                var minOffset = parseInt( offsets[1], 10 );
                                                if ( outOfRange(minOffset, 0, 59) ) return null;
                                                tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
                                                break;
                                        case "z": case "zz":
                                                // Time zone offset in +/- hours.
                                                hourOffset = matchInt;
                                                if ( outOfRange(hourOffset, -12, 13) ) return null;
                                                tzMinOffset = hourOffset * 60;
                                                break;
                                        case "g": case "gg":
                                                var eraName = matchGroup;
                                                if ( !eraName || !cal.eras ) return null;
                                                eraName = trim( eraName.toLowerCase() );
                                                for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
                                                        if ( eraName === cal.eras[i].name.toLowerCase() ) {
                                                                era = i;
                                                                break;
                                                        }
                                                }
                                                // could not find an era with that name
                                                if ( era === null ) return null;
                                                break;
                                }
                        }
                }
                var result = new Date(), defaultYear, convert = cal.convert;
                defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
                if ( year === null ) {
                        year = defaultYear;
                }
                else if ( cal.eras ) {
                        // year must be shifted to normal gregorian year
                        // but not if year was not specified, its already normal gregorian
                        // per the main if clause above.
                        year += cal.eras[( era || 0 )].offset;
                }
                // set default day and month to 1 and January, so if unspecified, these are the defaults
                // instead of the current day/month.
                if ( month === null ) {
                        month = 0;
                }
                if ( date === null ) {
                        date = 1;
                }
                // now have year, month, and date, but in the culture's calendar.
                // convert to gregorian if necessary
                if ( convert ) {
                        result = convert.toGregorian( year, month, date );
                        // conversion failed, must be an invalid match
                        if ( result === null ) return null;
                }
                else {
                        // have to set year, month and date together to avoid overflow based on current date.
                        result.setFullYear( year, month, date );
                        // check to see if date overflowed for specified month (only checked 1-31 above).
                        if ( result.getDate() !== date ) return null;
                        // invalid day of week.
                        if ( weekDay !== null && result.getDay() !== weekDay ) {
                                return null;
                        }
                }
                // if pm designator token was found make sure the hours fit the 24-hour clock.
                if ( pmHour && hour < 12 ) {
                        hour += 12;
                }
                result.setHours( hour, min, sec, msec );
                if ( tzMinOffset !== null ) {
                        // adjust timezone to utc before applying local offset.
                        var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
                        // Safari limits hours and minutes to the range of -127 to 127.  We need to use setHours
                        // to ensure both these fields will not exceed this range.      adjustedMin will range
                        // somewhere between -1440 and 1500, so we only need to split this into hours.
                        result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
                }
                return result;
        };
}());

parseNegativePattern = function( value, nf, negativePattern ) {
        var neg = nf[ "-" ],
                pos = nf[ "+" ],
                ret;
        switch ( negativePattern ) {
                case "n -":
                        neg = " " + neg;
                        pos = " " + pos;
                        /* falls through */
                case "n-":
                        if ( endsWith(value, neg) ) {
                                ret = [ "-", value.substr(0, value.length - neg.length) ];
                        }
                        else if ( endsWith(value, pos) ) {
                                ret = [ "+", value.substr(0, value.length - pos.length) ];
                        }
                        break;
                case "- n":
                        neg += " ";
                        pos += " ";
                        /* falls through */
                case "-n":
                        if ( startsWith(value, neg) ) {
                                ret = [ "-", value.substr(neg.length) ];
                        }
                        else if ( startsWith(value, pos) ) {
                                ret = [ "+", value.substr(pos.length) ];
                        }
                        break;
                case "(n)":
                        if ( startsWith(value, "(") && endsWith(value, ")") ) {
                                ret = [ "-", value.substr(1, value.length - 2) ];
                        }
                        break;
        }
        return ret || [ "", value ];
};

//
// public instance functions
//

Globalize.prototype.findClosestCulture = function( cultureSelector ) {
        return Globalize.findClosestCulture.call( this, cultureSelector );
};

Globalize.prototype.format = function( value, format, cultureSelector ) {
        return Globalize.format.call( this, value, format, cultureSelector );
};

Globalize.prototype.localize = function( key, cultureSelector ) {
        return Globalize.localize.call( this, key, cultureSelector );
};

Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
        return Globalize.parseInt.call( this, value, radix, cultureSelector );
};

Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
        return Globalize.parseFloat.call( this, value, radix, cultureSelector );
};

Globalize.prototype.culture = function( cultureSelector ) {
        return Globalize.culture.call( this, cultureSelector );
};

//
// public singleton functions
//

Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {

        var base = {},
                isNew = false;

        if ( typeof cultureName !== "string" ) {
                // cultureName argument is optional string. If not specified, assume info is first
                // and only argument. Specified info deep-extends current culture.
                info = cultureName;
                cultureName = this.culture().name;
                base = this.cultures[ cultureName ];
        } else if ( typeof baseCultureName !== "string" ) {
                // baseCultureName argument is optional string. If not specified, assume info is second
                // argument. Specified info deep-extends specified culture.
                // If specified culture does not exist, create by deep-extending default
                info = baseCultureName;
                isNew = ( this.cultures[ cultureName ] == null );
                base = this.cultures[ cultureName ] || this.cultures[ "default" ];
        } else {
                // cultureName and baseCultureName specified. Assume a new culture is being created
                // by deep-extending an specified base culture
                isNew = true;
                base = this.cultures[ baseCultureName ];
        }

        this.cultures[ cultureName ] = extend(true, {},
                base,
                info
        );
        // Make the standard calendar the current culture if it's a new culture
        if ( isNew ) {
                this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
        }
};

Globalize.findClosestCulture = function( name ) {
        var match;
        if ( !name ) {
                return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
        }
        if ( typeof name === "string" ) {
                name = name.split( "," );
        }
        if ( isArray(name) ) {
                var lang,
                        cultures = this.cultures,
                        list = name,
                        i, l = list.length,
                        prioritized = [];
                for ( i = 0; i < l; i++ ) {
                        name = trim( list[i] );
                        var pri, parts = name.split( ";" );
                        lang = trim( parts[0] );
                        if ( parts.length === 1 ) {
                                pri = 1;
                        }
                        else {
                                name = trim( parts[1] );
                                if ( name.indexOf("q=") === 0 ) {
                                        name = name.substr( 2 );
                                        pri = parseFloat( name );
                                        pri = isNaN( pri ) ? 0 : pri;
                                }
                                else {
                                        pri = 1;
                                }
                        }
                        prioritized.push({ lang: lang, pri: pri });
                }
                prioritized.sort(function( a, b ) {
                        if ( a.pri < b.pri ) {
                                return 1;
                        } else if ( a.pri > b.pri ) {
                                return -1;
                        }
                        return 0;
                });
                // exact match
                for ( i = 0; i < l; i++ ) {
                        lang = prioritized[ i ].lang;
                        match = cultures[ lang ];
                        if ( match ) {
                                return match;
                        }
                }

                // neutral language match
                for ( i = 0; i < l; i++ ) {
                        lang = prioritized[ i ].lang;
                        do {
                                var index = lang.lastIndexOf( "-" );
                                if ( index === -1 ) {
                                        break;
                                }
                                // strip off the last part. e.g. en-US => en
                                lang = lang.substr( 0, index );
                                match = cultures[ lang ];
                                if ( match ) {
                                        return match;
                                }
                        }
                        while ( 1 );
                }

                // last resort: match first culture using that language
                for ( i = 0; i < l; i++ ) {
                        lang = prioritized[ i ].lang;
                        for ( var cultureKey in cultures ) {
                                var culture = cultures[ cultureKey ];
                                if ( culture.language === lang ) {
                                        return culture;
                                }
                        }
                }
        }
        else if ( typeof name === "object" ) {
                return name;
        }
        return match || null;
};

Globalize.format = function( value, format, cultureSelector ) {
        var culture = this.findClosestCulture( cultureSelector );
        if ( value instanceof Date ) {
                value = formatDate( value, format, culture );
        }
        else if ( typeof value === "number" ) {
                value = formatNumber( value, format, culture );
        }
        return value;
};

Globalize.localize = function( key, cultureSelector ) {
        return this.findClosestCulture( cultureSelector ).messages[ key ] ||
                this.cultures[ "default" ].messages[ key ];
};

Globalize.parseDate = function( value, formats, culture ) {
        culture = this.findClosestCulture( culture );

        var date, prop, patterns;
        if ( formats ) {
                if ( typeof formats === "string" ) {
                        formats = [ formats ];
                }
                if ( formats.length ) {
                        for ( var i = 0, l = formats.length; i < l; i++ ) {
                                var format = formats[ i ];
                                if ( format ) {
                                        date = parseExact( value, format, culture );
                                        if ( date ) {
                                                break;
                                        }
                                }
                        }
                }
        } else {
                patterns = culture.calendar.patterns;
                for ( prop in patterns ) {
                        date = parseExact( value, patterns[prop], culture );
                        if ( date ) {
                                break;
                        }
                }
        }

        return date || null;
};

Globalize.parseInt = function( value, radix, cultureSelector ) {
        return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
};

Globalize.parseFloat = function( value, radix, cultureSelector ) {
        // radix argument is optional
        if ( typeof radix !== "number" ) {
                cultureSelector = radix;
                radix = 10;
        }

        var culture = this.findClosestCulture( cultureSelector );
        var ret = NaN,
                nf = culture.numberFormat;

        if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
                // remove currency symbol
                value = value.replace( culture.numberFormat.currency.symbol, "" );
                // replace decimal seperator
                value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
        }

        //Remove percentage character from number string before parsing
        if ( value.indexOf(culture.numberFormat.percent.symbol) > -1){
                value = value.replace( culture.numberFormat.percent.symbol, "" );
        }

        // remove spaces: leading, trailing and between - and number. Used for negative currency pt-BR
        value = value.replace( / /g, "" );

        // allow infinity or hexidecimal
        if ( regexInfinity.test(value) ) {
                ret = parseFloat( value );
        }
        else if ( !radix && regexHex.test(value) ) {
                ret = parseInt( value, 16 );
        }
        else {

                // determine sign and number
                var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
                        sign = signInfo[ 0 ],
                        num = signInfo[ 1 ];

                // #44 - try parsing as "(n)"
                if ( sign === "" && nf.pattern[0] !== "(n)" ) {
                        signInfo = parseNegativePattern( value, nf, "(n)" );
                        sign = signInfo[ 0 ];
                        num = signInfo[ 1 ];
                }

                // try parsing as "-n"
                if ( sign === "" && nf.pattern[0] !== "-n" ) {
                        signInfo = parseNegativePattern( value, nf, "-n" );
                        sign = signInfo[ 0 ];
                        num = signInfo[ 1 ];
                }

                sign = sign || "+";

                // determine exponent and number
                var exponent,
                        intAndFraction,
                        exponentPos = num.indexOf( "e" );
                if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
                if ( exponentPos < 0 ) {
                        intAndFraction = num;
                        exponent = null;
                }
                else {
                        intAndFraction = num.substr( 0, exponentPos );
                        exponent = num.substr( exponentPos + 1 );
                }
                // determine decimal position
                var integer,
                        fraction,
                        decSep = nf[ "." ],
                        decimalPos = intAndFraction.indexOf( decSep );
                if ( decimalPos < 0 ) {
                        integer = intAndFraction;
                        fraction = null;
                }
                else {
                        integer = intAndFraction.substr( 0, decimalPos );
                        fraction = intAndFraction.substr( decimalPos + decSep.length );
                }
                // handle groups (e.g. 1,000,000)
                var groupSep = nf[ "," ];
                integer = integer.split( groupSep ).join( "" );
                var altGroupSep = groupSep.replace( /\u00A0/g, " " );
                if ( groupSep !== altGroupSep ) {
                        integer = integer.split( altGroupSep ).join( "" );
                }
                // build a natively parsable number string
                var p = sign + integer;
                if ( fraction !== null ) {
                        p += "." + fraction;
                }
                if ( exponent !== null ) {
                        // exponent itself may have a number patternd
                        var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
                        p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
                }
                if ( regexParseFloat.test(p) ) {
                        ret = parseFloat( p );
                }
        }
        return ret;
};

Globalize.culture = function( cultureSelector ) {
        // setter
        if ( typeof cultureSelector !== "undefined" ) {
                this.cultureSelector = cultureSelector;
        }
        // getter
        return this.findClosestCulture( cultureSelector ) || this.cultures[ "default" ];
};

}( this ));

Generated by GNU Enscript 1.6.5.90.