a:51:{s:9:"#provides";s:11:"dojo.number";s:9:"#resource";s:9:"number.js";s:9:"#requires";a:3:{i:0;a:2:{i:0;s:6:"common";i:1;s:9:"dojo.i18n";}i:1;a:2:{i:0;s:6:"common";i:1;s:11:"dojo.string";}i:2;a:2:{i:0;s:6:"common";i:1;s:11:"dojo.regexp";}}s:11:"dojo.number";a:2:{s:4:"type";s:6:"Object";s:7:"summary";s:52:"localized formatting and parsing routines for Number";}s:27:"dojo.number.__FormatOptions";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:1254:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:35:"dojo.number.__FormatOptions.pattern";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"String?";s:7:"summary";s:107:"override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) with this string";s:14:"private_parent";b:1;}s:32:"dojo.number.__FormatOptions.type";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"String?";s:7:"summary";s:120:"choose a format type based on the locale from the following: decimal, scientific, percent, currency. decimal by default.";s:14:"private_parent";b:1;}s:34:"dojo.number.__FormatOptions.places";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"Number?";s:7:"summary";s:96:"fixed number of decimal places to show. This overrides any information in the provided pattern.";s:14:"private_parent";b:1;}s:33:"dojo.number.__FormatOptions.round";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"Number?";s:7:"summary";s:83:"5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 means do not round.";s:14:"private_parent";b:1;}s:36:"dojo.number.__FormatOptions.currency";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"String?";s:7:"summary";s:111:"an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"";s:14:"private_parent";b:1;}s:34:"dojo.number.__FormatOptions.symbol";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"String?";s:7:"summary";s:25:"localized currency symbol";s:14:"private_parent";b:1;}s:34:"dojo.number.__FormatOptions.locale";a:4:{s:8:"instance";s:27:"dojo.number.__FormatOptions";s:4:"type";s:7:"String?";s:7:"summary";s:54:"override the locale used to determine formatting rules";s:14:"private_parent";b:1;}s:18:"dojo.number.format";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:5:"value";a:2:{s:4:"type";s:6:"Number";s:7:"summary";s:26:"the number to be formatted";}s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:27:"dojo.number.__FormatOptions";}}s:6:"source";s:422:" options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String";s:7:"summary";s:59:"Format a Number as a String, using locale-specific settings";s:11:"description";s:354:"Create a string from a Number using a known localized pattern. Formatting patterns appropriate to the locale are chosen from the [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and delimiters. See If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.";s:7:"returns";s:11:"null|String";}s:25:"dojo.number._applyPattern";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:5:"value";a:2:{s:4:"type";s:6:"Number";s:7:"summary";s:27:"the number to be formatted.";}s:7:"pattern";a:2:{s:4:"type";s:6:"String";s:7:"summary";s:112:"a pattern string as described by [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)";}s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:27:"dojo.number.__FormatOptions";}}s:6:"source";s:4571:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));";s:7:"summary";s:97:"Apply pattern to format value as a string using options. Gives no consideration to local customs.";s:7:"returns";s:11:"null|String";s:7:"private";b:1;}s:17:"dojo.number.round";a:7:{s:4:"type";s:8:"Function";s:10:"parameters";a:6:{s:5:"value";a:2:{s:4:"type";s:6:"Number";s:7:"summary";s:19:"The number to round";}s:6:"places";a:3:{s:8:"optional";b:1;s:4:"type";s:6:"Number";s:7:"summary";s:113:"The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. Must be non-negative.";}s:9:"increment";a:3:{s:8:"optional";b:1;s:4:"type";s:6:"Number";s:7:"summary";s:67:"Rounds next place to nearest value of increment/10. 10 by default.";}s:1:"v";a:1:{s:4:"type";s:0:"";}s:1:"p";a:1:{s:4:"type";s:0:"";}s:1:"m";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:163:" var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d);";s:7:"summary";s:83:"Rounds to the nearest value with the given number of decimal places, away from zero";s:11:"description";s:330:"Rounds to the nearest value with the given number of decimal places, away from zero if equal. Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by fractional increments also, such as the nearest quarter. NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround.";s:7:"returns";s:6:"Number";s:8:"examples";a:1:{i:0;s:162:">>> dojo.number.round(-0.5) -1 >>> dojo.number.round(162.295, 2) 162.29 // note floating point error. Should be 162.3 >>> dojo.number.round(10.71, 0, 2.5) 10.75";}}s:35:"dojo.number.__FormatAbsoluteOptions";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:6585:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:43:"dojo.number.__FormatAbsoluteOptions.decimal";a:4:{s:8:"instance";s:35:"dojo.number.__FormatAbsoluteOptions";s:4:"type";s:7:"String?";s:7:"summary";s:21:"the decimal separator";s:14:"private_parent";b:1;}s:41:"dojo.number.__FormatAbsoluteOptions.group";a:4:{s:8:"instance";s:35:"dojo.number.__FormatAbsoluteOptions";s:4:"type";s:7:"String?";s:7:"summary";s:19:"the group separator";s:14:"private_parent";b:1;}s:42:"dojo.number.__FormatAbsoluteOptions.places";a:4:{s:8:"instance";s:35:"dojo.number.__FormatAbsoluteOptions";s:4:"type";s:16:"Integer?|String?";s:7:"summary";s:77:"number of decimal places. the range "n,m" will format to m places.";s:14:"private_parent";b:1;}s:41:"dojo.number.__FormatAbsoluteOptions.round";a:4:{s:8:"instance";s:35:"dojo.number.__FormatAbsoluteOptions";s:4:"type";s:7:"Number?";s:7:"summary";s:82:"5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 means don't round.";s:14:"private_parent";b:1;}s:27:"dojo.number._formatAbsolute";a:5:{s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:5:"value";a:2:{s:4:"type";s:6:"Number";s:7:"summary";s:40:"the number to be formatted, ignores sign";}s:7:"pattern";a:2:{s:4:"type";s:6:"String";s:7:"summary";s:49:"the number portion of a pattern (e.g. `#,##0.00`)";}s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:35:"dojo.number.__FormatAbsoluteOptions";}}s:6:"source";s:2334:" options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || ".");";s:7:"summary";s:95:"Apply numeric pattern to absolute value using options. Gives no consideration to local customs.";s:7:"private";b:1;}s:27:"dojo.number.__RegexpOptions";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:10041:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:35:"dojo.number.__RegexpOptions.pattern";a:4:{s:8:"instance";s:27:"dojo.number.__RegexpOptions";s:4:"type";s:7:"String?";s:7:"summary";s:72:"override pattern with this string. Default is provided based on locale.";s:14:"private_parent";b:1;}s:32:"dojo.number.__RegexpOptions.type";a:4:{s:8:"instance";s:27:"dojo.number.__RegexpOptions";s:4:"type";s:7:"String?";s:7:"summary";s:120:"choose a format type based on the locale from the following: decimal, scientific, percent, currency. decimal by default.";s:14:"private_parent";b:1;}s:34:"dojo.number.__RegexpOptions.locale";a:4:{s:8:"instance";s:27:"dojo.number.__RegexpOptions";s:4:"type";s:7:"String?";s:7:"summary";s:54:"override the locale used to determine formatting rules";s:14:"private_parent";b:1;}s:34:"dojo.number.__RegexpOptions.strict";a:4:{s:8:"instance";s:27:"dojo.number.__RegexpOptions";s:4:"type";s:8:"Boolean?";s:7:"summary";s:32:"strict parsing, false by default";s:14:"private_parent";b:1;}s:34:"dojo.number.__RegexpOptions.places";a:4:{s:8:"instance";s:27:"dojo.number.__RegexpOptions";s:4:"type";s:14:"Number|String?";s:7:"summary";s:149:"number of decimal places to accept: Infinity, a positive number, or a range "n,m". Defined by pattern or Infinity if pattern not provided.";s:14:"private_parent";b:1;}s:18:"dojo.number.regexp";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:27:"dojo.number.__RegexpOptions";}}s:6:"source";s:57:" return dojo.number._parseInfo(options).regexp; // String";s:7:"summary";s:43:"Builds the regular needed to parse a number";s:11:"description";s:89:"Returns regular expression with positive and negative match, group and decimal separators";s:7:"returns";s:6:"String";}s:22:"dojo.number._parseInfo";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"Object";}}s:6:"source";s:2700:" options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object";s:7:"returns";s:6:"Object";s:7:"private";b:1;s:7:"summary";s:0:"";}s:26:"dojo.number.__ParseOptions";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:13741:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places; } dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){ // summary: // Builds the regular needed to parse a number // description: // Returns regular expression with positive and negative match, group // and decimal separators return dojo.number._parseInfo(options).regexp; // String } dojo.number._parseInfo = function(/*Object?*/options){ options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object } dojo.number.__ParseOptions = function(){ // pattern: String // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // currency: Object // object with currency information this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.currency = currency;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:34:"dojo.number.__ParseOptions.pattern";a:4:{s:8:"instance";s:26:"dojo.number.__ParseOptions";s:4:"type";s:6:"String";s:7:"summary";s:72:"override pattern with this string. Default is provided based on locale.";s:14:"private_parent";b:1;}s:31:"dojo.number.__ParseOptions.type";a:4:{s:8:"instance";s:26:"dojo.number.__ParseOptions";s:4:"type";s:7:"String?";s:7:"summary";s:120:"choose a format type based on the locale from the following: decimal, scientific, percent, currency. decimal by default.";s:14:"private_parent";b:1;}s:33:"dojo.number.__ParseOptions.locale";a:4:{s:8:"instance";s:26:"dojo.number.__ParseOptions";s:4:"type";s:6:"String";s:7:"summary";s:54:"override the locale used to determine formatting rules";s:14:"private_parent";b:1;}s:33:"dojo.number.__ParseOptions.strict";a:4:{s:8:"instance";s:26:"dojo.number.__ParseOptions";s:4:"type";s:8:"Boolean?";s:7:"summary";s:32:"strict parsing, false by default";s:14:"private_parent";b:1;}s:35:"dojo.number.__ParseOptions.currency";a:4:{s:8:"instance";s:26:"dojo.number.__ParseOptions";s:4:"type";s:6:"Object";s:7:"summary";s:32:"object with currency information";s:14:"private_parent";b:1;}s:17:"dojo.number.parse";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:10:"expression";a:2:{s:4:"type";s:6:"String";s:7:"summary";s:35:"A string representation of a Number";}s:7:"options";a:2:{s:8:"optional";b:1;s:4:"type";s:26:"dojo.number.__ParseOptions";}}s:6:"source";s:757:" var info = dojo.number._parseInfo(options); var results = (new RegExp("^"+info.regexp+"$")).exec(expression); if(!results){ return NaN; //NaN } var absoluteMatch = results[1]; // match for the positive expression if(!results[1]){ if(!results[2]){ return NaN; //NaN } // matched the negative pattern absoluteMatch =results[2]; info.factor *= -1; } // Transform it to something Javascript can parse as a number. Normalize // decimal point and strip out group separators or alternate forms of whitespace absoluteMatch = absoluteMatch. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). replace(info.decimal, "."); // Adjust for negative sign, percent, etc. as necessary return absoluteMatch * info.factor; //Number";s:7:"summary";s:90:"Convert a properly formatted string to a primitive Number, using locale-specific settings.";s:11:"description";s:234:"Create a Number from a string using a known localized pattern. Formatting patterns are chosen appropriate to the locale and follow the syntax described by [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)";s:7:"returns";s:10:"NaN|Number";}s:35:"dojo.number.__RealNumberRegexpFlags";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:16120:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places; } dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){ // summary: // Builds the regular needed to parse a number // description: // Returns regular expression with positive and negative match, group // and decimal separators return dojo.number._parseInfo(options).regexp; // String } dojo.number._parseInfo = function(/*Object?*/options){ options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object } dojo.number.__ParseOptions = function(){ // pattern: String // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // currency: Object // object with currency information this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.currency = currency; } dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){ // summary: // Convert a properly formatted string to a primitive Number, using // locale-specific settings. // description: // Create a Number from a string using a known localized pattern. // Formatting patterns are chosen appropriate to the locale // and follow the syntax described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // expression: // A string representation of a Number var info = dojo.number._parseInfo(options); var results = (new RegExp("^"+info.regexp+"$")).exec(expression); if(!results){ return NaN; //NaN } var absoluteMatch = results[1]; // match for the positive expression if(!results[1]){ if(!results[2]){ return NaN; //NaN } // matched the negative pattern absoluteMatch =results[2]; info.factor *= -1; } // Transform it to something Javascript can parse as a number. Normalize // decimal point and strip out group separators or alternate forms of whitespace absoluteMatch = absoluteMatch. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). replace(info.decimal, "."); // Adjust for negative sign, percent, etc. as necessary return absoluteMatch * info.factor; //Number }; dojo.number.__RealNumberRegexpFlags = function(){ // places: Number? // The integer number of decimal places or a range given as "n,m". If // not given, the decimal part is optional and the number of places is // unlimited. // decimal: String? // A string for the character used as the decimal point. Default // is ".". // fractional: Boolean|Array? // Whether decimal places are allowed. Can be true, false, or [true, // false]. Default is [true, false] // exponent: Boolean|Array? // Express in exponential notation. Can be true, false, or [true, // false]. Default is [true, false], (i.e. will match if the // exponential part is present are not). // eSigned: Boolean|Array? // The leading plus-or-minus sign on the exponent. Can be true, // false, or [true, false]. Default is [true, false], (i.e. will // match if it is signed or unsigned). flags in regexp.integer can be // applied. this.places = places; this.decimal = decimal; this.fractional = fractional; this.exponent = exponent; this.eSigned = eSigned;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:42:"dojo.number.__RealNumberRegexpFlags.places";a:4:{s:8:"instance";s:35:"dojo.number.__RealNumberRegexpFlags";s:4:"type";s:7:"Number?";s:7:"summary";s:156:"The integer number of decimal places or a range given as "n,m". If not given, the decimal part is optional and the number of places is unlimited.";s:14:"private_parent";b:1;}s:43:"dojo.number.__RealNumberRegexpFlags.decimal";a:4:{s:8:"instance";s:35:"dojo.number.__RealNumberRegexpFlags";s:4:"type";s:7:"String?";s:7:"summary";s:80:"A string for the character used as the decimal point. Default is ".".";s:14:"private_parent";b:1;}s:46:"dojo.number.__RealNumberRegexpFlags.fractional";a:4:{s:8:"instance";s:35:"dojo.number.__RealNumberRegexpFlags";s:4:"type";s:14:"Boolean|Array?";s:7:"summary";s:100:"Whether decimal places are allowed. Can be true, false, or [true, false]. Default is [true, false]";s:14:"private_parent";b:1;}s:44:"dojo.number.__RealNumberRegexpFlags.exponent";a:4:{s:8:"instance";s:35:"dojo.number.__RealNumberRegexpFlags";s:4:"type";s:14:"Boolean|Array?";s:7:"summary";s:159:"Express in exponential notation. Can be true, false, or [true, false]. Default is [true, false], (i.e. will match if the exponential part is present are not).";s:14:"private_parent";b:1;}s:43:"dojo.number.__RealNumberRegexpFlags.eSigned";a:4:{s:8:"instance";s:35:"dojo.number.__RealNumberRegexpFlags";s:4:"type";s:14:"Boolean|Array?";s:7:"summary";s:201:"The leading plus-or-minus sign on the exponent. Can be true, false, or [true, false]. Default is [true, false], (i.e. will match if it is signed or unsigned). flags in regexp.integer can be applied.";s:14:"private_parent";b:1;}s:29:"dojo.number._realNumberRegexp";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"flags";a:2:{s:8:"optional";b:1;s:4:"type";s:35:"dojo.number.__RealNumberRegexpFlags";}}s:6:"source";s:17579:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places; } dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){ // summary: // Builds the regular needed to parse a number // description: // Returns regular expression with positive and negative match, group // and decimal separators return dojo.number._parseInfo(options).regexp; // String } dojo.number._parseInfo = function(/*Object?*/options){ options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object } dojo.number.__ParseOptions = function(){ // pattern: String // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // currency: Object // object with currency information this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.currency = currency; } dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){ // summary: // Convert a properly formatted string to a primitive Number, using // locale-specific settings. // description: // Create a Number from a string using a known localized pattern. // Formatting patterns are chosen appropriate to the locale // and follow the syntax described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // expression: // A string representation of a Number var info = dojo.number._parseInfo(options); var results = (new RegExp("^"+info.regexp+"$")).exec(expression); if(!results){ return NaN; //NaN } var absoluteMatch = results[1]; // match for the positive expression if(!results[1]){ if(!results[2]){ return NaN; //NaN } // matched the negative pattern absoluteMatch =results[2]; info.factor *= -1; } // Transform it to something Javascript can parse as a number. Normalize // decimal point and strip out group separators or alternate forms of whitespace absoluteMatch = absoluteMatch. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). replace(info.decimal, "."); // Adjust for negative sign, percent, etc. as necessary return absoluteMatch * info.factor; //Number }; dojo.number.__RealNumberRegexpFlags = function(){ // places: Number? // The integer number of decimal places or a range given as "n,m". If // not given, the decimal part is optional and the number of places is // unlimited. // decimal: String? // A string for the character used as the decimal point. Default // is ".". // fractional: Boolean|Array? // Whether decimal places are allowed. Can be true, false, or [true, // false]. Default is [true, false] // exponent: Boolean|Array? // Express in exponential notation. Can be true, false, or [true, // false]. Default is [true, false], (i.e. will match if the // exponential part is present are not). // eSigned: Boolean|Array? // The leading plus-or-minus sign on the exponent. Can be true, // false, or [true, false]. Default is [true, false], (i.e. will // match if it is signed or unsigned). flags in regexp.integer can be // applied. this.places = places; this.decimal = decimal; this.fractional = fractional; this.exponent = exponent; this.eSigned = eSigned; } dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){ // summary: // Builds a regular expression to match a real number in exponential // notation // assign default values to missing paramters flags = flags || {}; //TODO: use mixin instead? if(!("places" in flags)){ flags.places = Infinity; } if(typeof flags.decimal != "string"){ flags.decimal = "."; } if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; } if(!("exponent" in flags)){ flags.exponent = [true, false]; } if(!("eSigned" in flags)){ flags.eSigned = [true, false]; } // integer RE var integerRE = dojo.number._integerRegexp(flags); // decimal RE var decimalRE = dojo.regexp.buildGroupRE(flags.fractional, function(q){ var re = ""; if(q && (flags.places!==0)){ re = "\\" + flags.decimal; if(flags.places == Infinity){ re = "(?:" + re + "\\d+)?"; }else{ re += "\\d{" + flags.places + "}"; } } return re; }, true ); // exponent RE var exponentRE = dojo.regexp.buildGroupRE(flags.exponent, function(q){ if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; } return ""; } ); // real number RE var realRE = integerRE + decimalRE; // allow for decimals without integers, e.g. .25 if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";} return realRE + exponentRE; // String";s:7:"returns";s:29:"null|String|Number|Object|NaN";s:7:"private";b:1;s:7:"summary";s:0:"";}s:32:"dojo.number.__IntegerRegexpFlags";a:5:{s:4:"type";s:8:"Function";s:6:"source";s:18310:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places; } dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){ // summary: // Builds the regular needed to parse a number // description: // Returns regular expression with positive and negative match, group // and decimal separators return dojo.number._parseInfo(options).regexp; // String } dojo.number._parseInfo = function(/*Object?*/options){ options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object } dojo.number.__ParseOptions = function(){ // pattern: String // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // currency: Object // object with currency information this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.currency = currency; } dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){ // summary: // Convert a properly formatted string to a primitive Number, using // locale-specific settings. // description: // Create a Number from a string using a known localized pattern. // Formatting patterns are chosen appropriate to the locale // and follow the syntax described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // expression: // A string representation of a Number var info = dojo.number._parseInfo(options); var results = (new RegExp("^"+info.regexp+"$")).exec(expression); if(!results){ return NaN; //NaN } var absoluteMatch = results[1]; // match for the positive expression if(!results[1]){ if(!results[2]){ return NaN; //NaN } // matched the negative pattern absoluteMatch =results[2]; info.factor *= -1; } // Transform it to something Javascript can parse as a number. Normalize // decimal point and strip out group separators or alternate forms of whitespace absoluteMatch = absoluteMatch. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). replace(info.decimal, "."); // Adjust for negative sign, percent, etc. as necessary return absoluteMatch * info.factor; //Number }; dojo.number.__RealNumberRegexpFlags = function(){ // places: Number? // The integer number of decimal places or a range given as "n,m". If // not given, the decimal part is optional and the number of places is // unlimited. // decimal: String? // A string for the character used as the decimal point. Default // is ".". // fractional: Boolean|Array? // Whether decimal places are allowed. Can be true, false, or [true, // false]. Default is [true, false] // exponent: Boolean|Array? // Express in exponential notation. Can be true, false, or [true, // false]. Default is [true, false], (i.e. will match if the // exponential part is present are not). // eSigned: Boolean|Array? // The leading plus-or-minus sign on the exponent. Can be true, // false, or [true, false]. Default is [true, false], (i.e. will // match if it is signed or unsigned). flags in regexp.integer can be // applied. this.places = places; this.decimal = decimal; this.fractional = fractional; this.exponent = exponent; this.eSigned = eSigned; } dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){ // summary: // Builds a regular expression to match a real number in exponential // notation // assign default values to missing paramters flags = flags || {}; //TODO: use mixin instead? if(!("places" in flags)){ flags.places = Infinity; } if(typeof flags.decimal != "string"){ flags.decimal = "."; } if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; } if(!("exponent" in flags)){ flags.exponent = [true, false]; } if(!("eSigned" in flags)){ flags.eSigned = [true, false]; } // integer RE var integerRE = dojo.number._integerRegexp(flags); // decimal RE var decimalRE = dojo.regexp.buildGroupRE(flags.fractional, function(q){ var re = ""; if(q && (flags.places!==0)){ re = "\\" + flags.decimal; if(flags.places == Infinity){ re = "(?:" + re + "\\d+)?"; }else{ re += "\\d{" + flags.places + "}"; } } return re; }, true ); // exponent RE var exponentRE = dojo.regexp.buildGroupRE(flags.exponent, function(q){ if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; } return ""; } ); // real number RE var realRE = integerRE + decimalRE; // allow for decimals without integers, e.g. .25 if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";} return realRE + exponentRE; // String }; dojo.number.__IntegerRegexpFlags = function(){ // signed: Boolean? // The leading plus-or-minus sign. Can be true, false, or `[true,false]`. // Default is `[true, false]`, (i.e. will match if it is signed // or unsigned). // separator: String? // The character used as the thousands separator. Default is no // separator. For more than one symbol use an array, e.g. `[",", ""]`, // makes ',' optional. // groupSize: Number? // group size between separators // groupSize2: Number? // second grouping, where separators 2..n have a different interval than the first separator (for India) this.signed = signed; this.separator = separator; this.groupSize = groupSize; this.groupSize2 = groupSize2;";s:7:"private";b:1;s:9:"classlike";b:1;s:7:"summary";s:0:"";}s:39:"dojo.number.__IntegerRegexpFlags.signed";a:4:{s:8:"instance";s:32:"dojo.number.__IntegerRegexpFlags";s:4:"type";s:8:"Boolean?";s:7:"summary";s:145:"The leading plus-or-minus sign. Can be true, false, or `[true,false]`. Default is `[true, false]`, (i.e. will match if it is signed or unsigned).";s:14:"private_parent";b:1;}s:42:"dojo.number.__IntegerRegexpFlags.separator";a:4:{s:8:"instance";s:32:"dojo.number.__IntegerRegexpFlags";s:4:"type";s:7:"String?";s:7:"summary";s:168:"The character used as the thousands separator. Default is no separator. For more than one symbol use an array, e.g. `[",", ""]`, makes ',' optional.";s:14:"private_parent";b:1;}s:42:"dojo.number.__IntegerRegexpFlags.groupSize";a:4:{s:8:"instance";s:32:"dojo.number.__IntegerRegexpFlags";s:4:"type";s:7:"Number?";s:7:"summary";s:29:"group size between separators";s:14:"private_parent";b:1;}s:43:"dojo.number.__IntegerRegexpFlags.groupSize2";a:4:{s:8:"instance";s:32:"dojo.number.__IntegerRegexpFlags";s:4:"type";s:7:"Number?";s:7:"summary";s:101:"second grouping, where separators 2..n have a different interval than the first separator (for India)";s:14:"private_parent";b:1;}s:26:"dojo.number._integerRegexp";a:6:{s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"flags";a:2:{s:8:"optional";b:1;s:4:"type";s:32:"dojo.number.__IntegerRegexpFlags";}}s:6:"source";s:19639:"dojo.provide("dojo.number"); dojo.require("dojo.i18n"); dojo.requireLocalization("dojo.cldr", "number"); dojo.require("dojo.string"); dojo.require("dojo.regexp"); dojo.number = { // summary: localized formatting and parsing routines for Number } dojo.number.__FormatOptions = function(){ // pattern: String? // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // with this string // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // places: Number? // fixed number of decimal places to show. This overrides any // information in the provided pattern. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means do not round. // currency: String? // an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD" // symbol: String? // localized currency symbol // locale: String? // override the locale used to determine formatting rules this.pattern = pattern; this.type = type; this.places = places; this.round = round; this.currency = currency; this.symbol = symbol; this.locale = locale; } dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){ // summary: // Format a Number as a String, using locale-specific settings // description: // Create a string from a Number using a known localized pattern. // Formatting patterns appropriate to the locale are chosen from the // [CLDR](http://unicode.org/cldr) as well as the appropriate symbols and // delimiters. See // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. // value: // the number to be formatted options = dojo.mixin({}, options || {}); var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); options.customs = bundle; var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null return dojo.number._applyPattern(value, pattern, options); // String }; //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){ // summary: // Apply pattern to format value as a string using options. Gives no // consideration to local customs. // value: // the number to be formatted. // pattern: // a pattern string as described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // options: dojo.number.__FormatOptions? // _applyPattern is usually called via `dojo.number.format()` which // populates an extra property in the options parameter, "customs". // The customs object specifies group and decimal parameters if set. //TODO: support escapes options = options || {}; var group = options.customs.group; var decimal = options.customs.decimal; var patternList = pattern.split(';'); var positivePattern = patternList[0]; pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); //TODO: only test against unescaped if(pattern.indexOf('%') != -1){ value *= 100; }else if(pattern.indexOf('\u2030') != -1){ value *= 1000; // per mille }else if(pattern.indexOf('\u00a4') != -1){ group = options.customs.currencyGroup || group;//mixins instead? decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? pattern = pattern.replace(/\u00a4{1,3}/, function(match){ var prop = ["symbol", "currency", "displayName"][match.length-1]; return options[prop] || options.currency || ""; }); }else if(pattern.indexOf('E') != -1){ throw new Error("exponential notation not supported"); } //TODO: support @ sig figs? var numberPatternRE = dojo.number._numberPatternRE; var numberPattern = positivePattern.match(numberPatternRE); if(!numberPattern){ throw new Error("unable to find a number expression in pattern: "+pattern); } if(options.fractional === false){ options.places = 0; } return pattern.replace(numberPatternRE, dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); } dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){ // summary: // Rounds to the nearest value with the given number of decimal places, away from zero // description: // Rounds to the nearest value with the given number of decimal places, away from zero if equal. // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by // fractional increments also, such as the nearest quarter. // NOTE: Subject to floating point errors. See dojox.math.round for experimental workaround. // value: // The number to round // places: // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. // Must be non-negative. // increment: // Rounds next place to nearest value of increment/10. 10 by default. // example: // >>> dojo.number.round(-0.5) // -1 // >>> dojo.number.round(162.295, 2) // 162.29 // note floating point error. Should be 162.3 // >>> dojo.number.round(10.71, 0, 2.5) // 10.75 var factor = 10 / (increment || 10); return (factor * +value).toFixed(places) / factor; // Number } if((0.9).toFixed() == 0){ // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit // is just after the rounding place and is >=5 (function(){ var round = dojo.number.round; dojo.number.round = function(v, p, m){ var d = Math.pow(10, -p || 0), a = Math.abs(v); if(!v || a >= d || a * Math.pow(10, p + 1) < 5){ d = 0; } return round(v, p, m) + (v > 0 ? d : -d); } })(); } dojo.number.__FormatAbsoluteOptions = function(){ // decimal: String? // the decimal separator // group: String? // the group separator // places: Integer?|String? // number of decimal places. the range "n,m" will format to m places. // round: Number? // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 // means don't round. this.decimal = decimal; this.group = group; this.places = places; this.round = round; } dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){ // summary: // Apply numeric pattern to absolute value using options. Gives no // consideration to local customs. // value: // the number to be formatted, ignores sign // pattern: // the number portion of a pattern (e.g. `#,##0.00`) options = options || {}; if(options.places === true){options.places=0;} if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit var patternParts = pattern.split("."); var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0; if(!(options.round < 0)){ value = dojo.number.round(value, maxPlaces, options.round); } var valueParts = String(Math.abs(value)).split("."); var fractional = valueParts[1] || ""; if(options.places){ var comma = dojo.isString(options.places) && options.places.indexOf(","); if(comma){ options.places = options.places.substring(comma+1); } valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true); }else if(patternParts[1] && options.places !== 0){ // Pad fractional with trailing zeros var pad = patternParts[1].lastIndexOf("0") + 1; if(pad > fractional.length){ valueParts[1] = dojo.string.pad(fractional, pad, '0', true); } // Truncate fractional var places = patternParts[1].length; if(places < fractional.length){ valueParts[1] = fractional.substr(0, places); } }else{ if(valueParts[1]){ valueParts.pop(); } } // Pad whole with leading zeros var patternDigits = patternParts[0].replace(',', ''); pad = patternDigits.indexOf("0"); if(pad != -1){ pad = patternDigits.length - pad; if(pad > valueParts[0].length){ valueParts[0] = dojo.string.pad(valueParts[0], pad); } // Truncate whole if(patternDigits.indexOf("#") == -1){ valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); } } // Add group separators var index = patternParts[0].lastIndexOf(','); var groupSize, groupSize2; if(index != -1){ groupSize = patternParts[0].length - index - 1; var remainder = patternParts[0].substr(0, index); index = remainder.lastIndexOf(','); if(index != -1){ groupSize2 = remainder.length - index - 1; } } var pieces = []; for(var whole = valueParts[0]; whole;){ var off = whole.length - groupSize; pieces.push((off > 0) ? whole.substr(off) : whole); whole = (off > 0) ? whole.slice(0, off) : ""; if(groupSize2){ groupSize = groupSize2; delete groupSize2; } } valueParts[0] = pieces.reverse().join(options.group || ","); return valueParts.join(options.decimal || "."); }; dojo.number.__RegexpOptions = function(){ // pattern: String? // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String? // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // places: Number|String? // number of decimal places to accept: Infinity, a positive number, or // a range "n,m". Defined by pattern or Infinity if pattern not provided. this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.places = places; } dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){ // summary: // Builds the regular needed to parse a number // description: // Returns regular expression with positive and negative match, group // and decimal separators return dojo.number._parseInfo(options).regexp; // String } dojo.number._parseInfo = function(/*Object?*/options){ options = options || {}; var locale = dojo.i18n.normalizeLocale(options.locale); var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale); var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; //TODO: memoize? var group = bundle.group; var decimal = bundle.decimal; var factor = 1; if(pattern.indexOf('%') != -1){ factor /= 100; }else if(pattern.indexOf('\u2030') != -1){ factor /= 1000; // per mille }else{ var isCurrency = pattern.indexOf('\u00a4') != -1; if(isCurrency){ group = bundle.currencyGroup || group; decimal = bundle.currencyDecimal || decimal; } } //TODO: handle quoted escapes var patternList = pattern.split(';'); if(patternList.length == 1){ patternList.push("-" + patternList[0]); } var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")"; return pattern.replace(dojo.number._numberPatternRE, function(format){ var flags = { signed: false, separator: options.strict ? group : [group,""], fractional: options.fractional, decimal: decimal, exponent: false}; var parts = format.split('.'); var places = options.places; if(parts.length == 1 || places === 0){flags.fractional = false;} else{ if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0')+1 : Infinity; } if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } flags.places = places; } var groups = parts[0].split(','); if(groups.length>1){ flags.groupSize = groups.pop().length; if(groups.length>1){ flags.groupSize2 = groups.pop().length; } } return "("+dojo.number._realNumberRegexp(flags)+")"; }); }, true); if(isCurrency){ // substitute the currency symbol for the placeholder in the pattern re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ var prop = ["symbol", "currency", "displayName"][target.length-1]; var symbol = dojo.regexp.escapeString(options[prop] || options.currency || ""); before = before ? "[\\s\\xa0]" : ""; after = after ? "[\\s\\xa0]" : ""; if(!options.strict){ if(before){before += "*";} if(after){after += "*";} return "(?:"+before+symbol+after+")?"; } return before+symbol+after; }); } //TODO: substitute localized sign/percent/permille/etc.? // normalize whitespace and return return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object } dojo.number.__ParseOptions = function(){ // pattern: String // override pattern with this string. Default is provided based on // locale. // type: String? // choose a format type based on the locale from the following: // decimal, scientific, percent, currency. decimal by default. // locale: String // override the locale used to determine formatting rules // strict: Boolean? // strict parsing, false by default // currency: Object // object with currency information this.pattern = pattern; this.type = type; this.locale = locale; this.strict = strict; this.currency = currency; } dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){ // summary: // Convert a properly formatted string to a primitive Number, using // locale-specific settings. // description: // Create a Number from a string using a known localized pattern. // Formatting patterns are chosen appropriate to the locale // and follow the syntax described by // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) // expression: // A string representation of a Number var info = dojo.number._parseInfo(options); var results = (new RegExp("^"+info.regexp+"$")).exec(expression); if(!results){ return NaN; //NaN } var absoluteMatch = results[1]; // match for the positive expression if(!results[1]){ if(!results[2]){ return NaN; //NaN } // matched the negative pattern absoluteMatch =results[2]; info.factor *= -1; } // Transform it to something Javascript can parse as a number. Normalize // decimal point and strip out group separators or alternate forms of whitespace absoluteMatch = absoluteMatch. replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). replace(info.decimal, "."); // Adjust for negative sign, percent, etc. as necessary return absoluteMatch * info.factor; //Number }; dojo.number.__RealNumberRegexpFlags = function(){ // places: Number? // The integer number of decimal places or a range given as "n,m". If // not given, the decimal part is optional and the number of places is // unlimited. // decimal: String? // A string for the character used as the decimal point. Default // is ".". // fractional: Boolean|Array? // Whether decimal places are allowed. Can be true, false, or [true, // false]. Default is [true, false] // exponent: Boolean|Array? // Express in exponential notation. Can be true, false, or [true, // false]. Default is [true, false], (i.e. will match if the // exponential part is present are not). // eSigned: Boolean|Array? // The leading plus-or-minus sign on the exponent. Can be true, // false, or [true, false]. Default is [true, false], (i.e. will // match if it is signed or unsigned). flags in regexp.integer can be // applied. this.places = places; this.decimal = decimal; this.fractional = fractional; this.exponent = exponent; this.eSigned = eSigned; } dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){ // summary: // Builds a regular expression to match a real number in exponential // notation // assign default values to missing paramters flags = flags || {}; //TODO: use mixin instead? if(!("places" in flags)){ flags.places = Infinity; } if(typeof flags.decimal != "string"){ flags.decimal = "."; } if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; } if(!("exponent" in flags)){ flags.exponent = [true, false]; } if(!("eSigned" in flags)){ flags.eSigned = [true, false]; } // integer RE var integerRE = dojo.number._integerRegexp(flags); // decimal RE var decimalRE = dojo.regexp.buildGroupRE(flags.fractional, function(q){ var re = ""; if(q && (flags.places!==0)){ re = "\\" + flags.decimal; if(flags.places == Infinity){ re = "(?:" + re + "\\d+)?"; }else{ re += "\\d{" + flags.places + "}"; } } return re; }, true ); // exponent RE var exponentRE = dojo.regexp.buildGroupRE(flags.exponent, function(q){ if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; } return ""; } ); // real number RE var realRE = integerRE + decimalRE; // allow for decimals without integers, e.g. .25 if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";} return realRE + exponentRE; // String }; dojo.number.__IntegerRegexpFlags = function(){ // signed: Boolean? // The leading plus-or-minus sign. Can be true, false, or `[true,false]`. // Default is `[true, false]`, (i.e. will match if it is signed // or unsigned). // separator: String? // The character used as the thousands separator. Default is no // separator. For more than one symbol use an array, e.g. `[",", ""]`, // makes ',' optional. // groupSize: Number? // group size between separators // groupSize2: Number? // second grouping, where separators 2..n have a different interval than the first separator (for India) this.signed = signed; this.separator = separator; this.groupSize = groupSize; this.groupSize2 = groupSize2; } dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){ // summary: // Builds a regular expression that matches an integer // assign default values to missing paramters flags = flags || {}; if(!("signed" in flags)){ flags.signed = [true, false]; } if(!("separator" in flags)){ flags.separator = ""; }else if(!("groupSize" in flags)){ flags.groupSize = 3; } // build sign RE var signRE = dojo.regexp.buildGroupRE(flags.signed, function(q){ return q ? "[-+]" : ""; }, true ); // number RE var numberRE = dojo.regexp.buildGroupRE(flags.separator, function(sep){ if(!sep){ return "(?:\\d+)"; } sep = dojo.regexp.escapeString(sep); if(sep == " "){ sep = "\\s"; } else if(sep == "\xa0"){ sep = "\\s\\xa0"; } var grp = flags.groupSize, grp2 = flags.groupSize2; //TODO: should we continue to enforce that numbers with separators begin with 1-9? See #6933 if(grp2){ var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})"; return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE; } return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)"; }, true ); // integer RE return signRE + numberRE; // String";s:7:"returns";s:29:"null|String|Number|Object|NaN";s:7:"private";b:1;s:7:"summary";s:0:"";}s:28:"dojo.number._numberPatternRE";a:2:{s:7:"private";b:1;s:7:"summary";s:0:"";}s:4:"dojo";a:2:{s:4:"type";s:6:"Object";s:7:"summary";s:0:"";}}