Changeset 7361
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/number.js
r6926 r7361 7 7 dojo.require("dojo.string.common"); 8 8 dojo.require("dojo.string.extras"); 9 dojo.require("dojo.regexp"); // should we eliminate this dependency or try to make use of regexp number routines?9 dojo.require("dojo.regexp"); 10 10 11 11 dojo.number.format = function(/*Number*/value, /*Object?*/options){ … … 35 35 }; 36 36 37 dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0]+(?:\.0*#*)?/; // not precise, but good enough 37 //dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough 38 dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough 38 39 39 40 dojo.number.applyPattern = function(/*Number*/value, /*String*/pattern, /*Object?*/options){ … … 161 162 }; 162 163 164 dojo.number.regexp = function(/*Object?*/options){ 165 // 166 // summary: 167 // Builds the regular needed to parse a number 168 // 169 // description: 170 // returns regular expression with positive and negative match, group and decimal separators 171 // 172 // options: object {pattern: String, type: String locale: String, strict: Boolean, places: mixed} 173 // pattern- override pattern with this string 174 // type- choose a format type based on the locale from the following: decimal, scientific, percent, currency. decimal by default. 175 // locale- override the locale used to determine formatting rules 176 // strict- strict parsing, false by default 177 // places- number of decimal places to accept: Infinity, a positive number, or a range "n,m" 178 return dojo.number._parseInfo(options).regexp; // String 179 } 180 181 dojo.number._parseInfo = function(/*Object?*/options){ 182 options = options || {}; 183 var locale = dojo.hostenv.normalizeLocale(options.locale); 184 var bundle = dojo.i18n.getLocalization("dojo.i18n.cldr", "number", locale); 185 var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; 186 //TODO: memoize? 187 var group = bundle.group; 188 // if(!options.strict){ group = [group,""]; } 189 var decimal = bundle.decimal; 190 191 //TODO: handle quoted escapes 192 var patternList = pattern.split(';'); 193 if (patternList.length == 1){ 194 patternList.push("-" + patternList[0]); // substitute negative sign? 195 } 196 197 var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ 198 pattern = "(?:"+dojo.string.escape('regexp', pattern, '.')+")"; 199 return pattern.replace(dojo.number._numberPatternRE, function(format){ 200 var flags = { 201 signed: false, 202 separator: options.strict ? group : [group,""], 203 decimal: decimal, 204 exponent: false}; 205 var parts = format.split('.'); 206 if(parts.length == 1){parts.fractional = false;} 207 else{ 208 var places = options.places; 209 if(typeof places == "undefined"){ places = parts[1].lastIndexOf('0')+1; } 210 if(places){parts.fractional = true;} // required fraction 211 flags.places = places; 212 if(places < parts[1].length){ flags.places += "," + parts[1].length; } 213 } 214 var groups = parts[0].split(','); 215 if(groups.length>1){ 216 flags.groupSize = groups.pop().length; 217 if(groups.length>1){ 218 flags.groupSize2 = groups.pop().length; 219 } 220 } 221 return "("+dojo.regexp.realNumber(flags)+")"; 222 }); 223 }, true); 224 225 if(!options.strict){ 226 // TODO: handle .### with no leading integer? 227 //TODO: !strict: make currency symbol too 228 } 229 230 return {regexp: re, group: group, decimal: decimal}; // Object 231 } 232 163 233 dojo.number.parse = function(/*String*/expression, /*Object?*/options){ 164 234 // … … 176 246 // options: object {pattern: string, locale: string, strict: boolean} 177 247 // pattern- override pattern with this string 248 // type- choose a format type based on the locale from the following: decimal, scientific, percent, currency. decimal by default. 178 249 // locale- override the locale used to determine formatting rules 179 250 // strict- strict parsing, false by default 180 251 181 options = options || {}; 182 var locale = dojo.hostenv.normalizeLocale(options.locale); 183 var bundle = dojo.i18n.getLocalization("dojo.i18n.cldr", "number", locale); 184 var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; 185 var group = bundle.group; 186 var decimal = bundle.decimal; 187 188 //TODO: handle quoted escapes 189 var patternList = pattern.split(';'); 190 if (patternList.length == 1){ 191 patternList.push("-" + patternList[0]); // substitute negative sign? 192 } 193 194 if(options.strict && !dojo.number._buildNumberFormatRE(pattern, {/*TODO*/}).test(expression)){ 195 return NaN; //NaN 196 } 197 198 var re = dojo.regexp.buildGroupRE(patternList, function(pattern){ 199 pattern = dojo.regexp.group(dojo.string.escape('regexp', pattern, '.'), true); 200 return pattern.replace(dojo.number._numberPatternRE, "([\\d\\"+group+"]+(?:\\"+decimal+"\\d+)?)"); // also handle .### with no leading integer? 201 }, true); 252 var info = dojo.number._parseInfo(options); 253 var group = info.group; 254 var decimal = info.decimal; 255 var re = info.regexp; 202 256 203 257 //TODO: substitute currency symbol, percent/permille/etc. … … 220 274 //TODO: handle exponent 221 275 } 222 223 276 return value; 224 277 }; 225 226 dojo.number._buildNumberFormatRE = function(/*String*/pattern, /*Object*/options){227 //TODO: sign228 //TODO: currency229 //TODO: exp?230 //TODO: number groups231 dojo.unimplemented("dojo.number._buildNumberFormatRE");232 var numberPatternRE = dojo.number._numberPatternRE;233 var numberPattern = pattern.match(numberPatternRE);234 if(!numberPattern){235 dojo.raise("unable to find a number expression in pattern: "+pattern);236 }237 //TODO: escape special chars in regexp238 pattern = pattern.replace(numberPatternRE, "\\d...");239 return new RegExp("^" + pattern + "$"); // RegExp240 //TODO: memoize?241 }; -
trunk/src/regexp.js
r6985 r7361 256 256 // build sign RE 257 257 var signRE = dojo.regexp.buildGroupRE(flags.signed, 258 function(q) { return q ? "[-+]" : ""; } 258 function(q) { return q ? "[-+]" : ""; }, 259 true 259 260 ); 260 261 … … 262 263 var numberRE = dojo.regexp.buildGroupRE(flags.separator, 263 264 function(sep){ 264 if( sep == ""){265 return "( 0|[1-9]\\d*)";265 if(!sep){ 266 return "(?:0|[1-9]\\d*)"; 266 267 } 267 268 var grp = flags.groupSize, grp2 = flags.groupSize2; 268 if( typeof grp2 != "undefined"){269 var grp2RE = "( 0|[1-9]\\d{0," + (grp2-1) + "}([" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";270 return ((grp-grp2) > 0) ? "( " + grp2RE + "|(0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;269 if(grp2){ 270 var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})"; 271 return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE; 271 272 } 272 return "(0|[1-9]\\d{0," + (grp-1) + "}([" + sep + "]\\d{" + grp + "})*)"; 273 } 273 return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)"; 274 }, 275 true 274 276 ); 275 277 … … 282 284 // 283 285 // flags:An object 284 // flags.places The integer number of decimal places .286 // flags.places The integer number of decimal places or a range given as "n,m" 285 287 // If not given, the decimal part is optional and the number of places is unlimited. 286 288 // flags.decimal A string for the character used as the decimal point. Default is ".". … … 295 297 // assign default values to missing paramters 296 298 flags = (typeof flags == "object") ? flags : {}; 297 if(typeof flags.places != "number"){ flags.places = Infinity; }299 if(typeof flags.places == "undefined"){ flags.places = Infinity; } 298 300 if(typeof flags.decimal != "string"){ flags.decimal = "."; } 299 301 if(typeof flags.fractional == "undefined"){ flags.fractional = [true, false]; } … … 308 310 function(q){ 309 311 var re = ""; 310 if(q && (flags.places >0)){312 if(q && (flags.places!==0)){ 311 313 re = "\\" + flags.decimal; 312 314 if(flags.places == Infinity){ 313 re = "( " + re + "\\d+)?";314 }else{ 315 re = re +"\\d{" + flags.places + "}";315 re = "(?:" + re + "\\d+)?"; 316 }else{ 317 re += "\\d{" + flags.places + "}"; 316 318 } 317 319 } 318 319 320 return re; 320 } 321 }, 322 true 321 323 ); 322 324