diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/form/NumberTextBox.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/form/NumberTextBox.js')
-rw-r--r-- | lib/dijit/form/NumberTextBox.js | 370 |
1 files changed, 268 insertions, 102 deletions
diff --git a/lib/dijit/form/NumberTextBox.js b/lib/dijit/form/NumberTextBox.js index d477d1ba9..4d0d64f99 100644 --- a/lib/dijit/form/NumberTextBox.js +++ b/lib/dijit/form/NumberTextBox.js @@ -1,112 +1,278 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit.form.NumberTextBox"]){ -dojo._hasResource["dijit.form.NumberTextBox"]=true; +if(!dojo._hasResource["dijit.form.NumberTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit.form.NumberTextBox"] = true; dojo.provide("dijit.form.NumberTextBox"); dojo.require("dijit.form.ValidationTextBox"); dojo.require("dojo.number"); -dojo.declare("dijit.form.NumberTextBoxMixin",null,{regExpGen:dojo.number.regexp,value:NaN,editOptions:{pattern:"#.######"},_formatter:dojo.number.format,_setConstraintsAttr:function(_1){ -var _2=typeof _1.places=="number"?_1.places:0; -if(_2){ -_2++; -} -if(typeof _1.max!="number"){ -_1.max=9*Math.pow(10,15-_2); -} -if(typeof _1.min!="number"){ -_1.min=-9*Math.pow(10,15-_2); -} -this.inherited(arguments,[_1]); -if(this.focusNode&&this.focusNode.value&&!isNaN(this.value)){ -this.set("value",this.value); -} -},_onFocus:function(){ -if(this.disabled){ -return; -} -var _3=this.get("value"); -if(typeof _3=="number"&&!isNaN(_3)){ -var _4=this.format(_3,this.constraints); -if(_4!==undefined){ -this.textbox.value=_4; -} -} -this.inherited(arguments); -},format:function(_5,_6){ -var _7=String(_5); -if(typeof _5!="number"){ -return _7; -} -if(isNaN(_5)){ -return ""; -} -if(!("rangeCheck" in this&&this.rangeCheck(_5,_6))&&_6.exponent!==false&&/\de[-+]?\d/i.test(_7)){ -return _7; -} -if(this.editOptions&&this._focused){ -_6=dojo.mixin({},_6,this.editOptions); -} -return this._formatter(_5,_6); -},parse:dojo.number.parse,_getDisplayedValueAttr:function(){ -var v=this.inherited(arguments); -return isNaN(v)?this.textbox.value:v; -},filter:function(_8){ -return (_8===null||_8===""||_8===undefined)?NaN:this.inherited(arguments); -},serialize:function(_9,_a){ -return (typeof _9!="number"||isNaN(_9))?"":this.inherited(arguments); -},_setValueAttr:function(_b,_c,_d){ -if(_b!==undefined&&_d===undefined){ -_d=String(_b); -if(typeof _b=="number"){ -if(isNaN(_b)){ -_d=""; -}else{ -if(("rangeCheck" in this&&this.rangeCheck(_b,this.constraints))||this.constraints.exponent===false||!/\de[-+]?\d/i.test(_d)){ -_d=undefined; -} -} -}else{ -if(!_b){ -_d=""; -_b=NaN; -}else{ -_b=undefined; -} -} -} -this.inherited(arguments,[_b,_c,_d]); -},_getValueAttr:function(){ -var v=this.inherited(arguments); -if(isNaN(v)&&this.textbox.value!==""){ -if(this.constraints.exponent!==false&&/\de[-+]?\d/i.test(this.textbox.value)&&(new RegExp("^"+dojo.number._realNumberRegexp(dojo.mixin({},this.constraints))+"$").test(this.textbox.value))){ -var n=Number(this.textbox.value); -return isNaN(n)?undefined:n; -}else{ -return undefined; -} -}else{ -return v; -} -},isValid:function(_e){ -if(!this._focused||this._isEmpty(this.textbox.value)){ -return this.inherited(arguments); -}else{ -var v=this.get("value"); -if(!isNaN(v)&&this.rangeCheck(v,this.constraints)){ -if(this.constraints.exponent!==false&&/\de[-+]?\d/i.test(this.textbox.value)){ -return true; -}else{ -return this.inherited(arguments); -} -}else{ -return false; -} -} -}}); -dojo.declare("dijit.form.NumberTextBox",[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],{}); + + +/*===== +dojo.declare( + "dijit.form.NumberTextBox.__Constraints", + [dijit.form.RangeBoundTextBox.__Constraints, dojo.number.__FormatOptions, dojo.number.__ParseOptions], { + // summary: + // Specifies both the rules on valid/invalid values (minimum, maximum, + // number of required decimal places), and also formatting options for + // displaying the value when the field is not focused. + // example: + // Minimum/maximum: + // To specify a field between 0 and 120: + // | {min:0,max:120} + // To specify a field that must be an integer: + // | {fractional:false} + // To specify a field where 0 to 3 decimal places are allowed on input: + // | {places:'0,3'} +}); +=====*/ + +dojo.declare("dijit.form.NumberTextBoxMixin", + null, + { + // summary: + // A mixin for all number textboxes + // tags: + // protected + + // Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather + // than a straight regexp to deal with locale (plus formatting options too?) + regExpGen: dojo.number.regexp, + + /*===== + // constraints: dijit.form.NumberTextBox.__Constraints + // Despite the name, this parameter specifies both constraints on the input + // (including minimum/maximum allowed values) as well as + // formatting options like places (the number of digits to display after + // the decimal point). See `dijit.form.NumberTextBox.__Constraints` for details. + constraints: {}, + ======*/ + + // value: Number + // The value of this NumberTextBox as a Javascript Number (i.e., not a String). + // If the displayed value is blank, the value is NaN, and if the user types in + // an gibberish value (like "hello world"), the value is undefined + // (i.e. get('value') returns undefined). + // + // Symmetrically, set('value', NaN) will clear the displayed value, + // whereas set('value', undefined) will have no effect. + value: NaN, + + // editOptions: [protected] Object + // Properties to mix into constraints when the value is being edited. + // This is here because we edit the number in the format "12345", which is + // different than the display value (ex: "12,345") + editOptions: { pattern: '#.######' }, + + /*===== + _formatter: function(value, options){ + // summary: + // _formatter() is called by format(). It's the base routine for formatting a number, + // as a string, for example converting 12345 into "12,345". + // value: Number + // The number to be converted into a string. + // options: dojo.number.__FormatOptions? + // Formatting options + // tags: + // protected extension + + return "12345"; // String + }, + =====*/ + _formatter: dojo.number.format, + + _setConstraintsAttr: function(/*Object*/ constraints){ + var places = typeof constraints.places == "number"? constraints.places : 0; + if(places){ places++; } // decimal rounding errors take away another digit of precision + if(typeof constraints.max != "number"){ + constraints.max = 9 * Math.pow(10, 15-places); + } + if(typeof constraints.min != "number"){ + constraints.min = -9 * Math.pow(10, 15-places); + } + this.inherited(arguments, [ constraints ]); + if(this.focusNode && this.focusNode.value && !isNaN(this.value)){ + this.set('value', this.value); + } + }, + + _onFocus: function(){ + if(this.disabled){ return; } + var val = this.get('value'); + if(typeof val == "number" && !isNaN(val)){ + var formattedValue = this.format(val, this.constraints); + if(formattedValue !== undefined){ + this.textbox.value = formattedValue; + } + } + this.inherited(arguments); + }, + + format: function(/*Number*/ value, /*dojo.number.__FormatOptions*/ constraints){ + // summary: + // Formats the value as a Number, according to constraints. + // tags: + // protected + + var formattedValue = String(value); + if(typeof value != "number"){ return formattedValue; } + if(isNaN(value)){ return ""; } + // check for exponential notation that dojo.number.format chokes on + if(!("rangeCheck" in this && this.rangeCheck(value, constraints)) && constraints.exponent !== false && /\de[-+]?\d/i.test(formattedValue)){ + return formattedValue; + } + if(this.editOptions && this._focused){ + constraints = dojo.mixin({}, constraints, this.editOptions); + } + return this._formatter(value, constraints); + }, + + /*===== + _parser: function(value, constraints){ + // summary: + // Parses the string value as a Number, according to constraints. + // value: String + // String representing a number + // constraints: dojo.number.__ParseOptions + // Formatting options + // tags: + // protected + + return 123.45; // Number + }, + =====*/ + _parser: dojo.number.parse, + + parse: function(/*String*/ value, /*dojo.number.__FormatOptions*/ constraints){ + // summary: + // Replacable function to convert a formatted string to a number value + // tags: + // protected extension + + var v = this._parser(value, dojo.mixin({}, constraints, (this.editOptions && this._focused) ? this.editOptions : {})); + if(this.editOptions && this._focused && isNaN(v)){ + v = this._parser(value, constraints); // parse w/o editOptions: not technically needed but is nice for the user + } + return v; + }, + + _getDisplayedValueAttr: function(){ + var v = this.inherited(arguments); + return isNaN(v) ? this.textbox.value : v; + }, + + filter: function(/*Number*/ value){ + // summary: + // This is called with both the display value (string), and the actual value (a number). + // When called with the actual value it does corrections so that '' etc. are represented as NaN. + // Otherwise it dispatches to the superclass's filter() method. + // + // See `dijit.form.TextBox.filter` for more details. + return (value === null || value === '' || value === undefined) ? NaN : this.inherited(arguments); // set('value', null||''||undefined) should fire onChange(NaN) + }, + + serialize: function(/*Number*/ value, /*Object?*/ options){ + // summary: + // Convert value (a Number) into a canonical string (ie, how the number literal is written in javascript/java/C/etc.) + // tags: + // protected + return (typeof value != "number" || isNaN(value)) ? '' : this.inherited(arguments); + }, + + _setBlurValue: function(){ + var val = dojo.hitch(dojo.mixin({}, this, { _focused: true }), "get")('value'); // parse with editOptions + this._setValueAttr(val, true); + }, + + _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ + // summary: + // Hook so set('value', ...) works. + if(value !== undefined && formattedValue === undefined){ + formattedValue = String(value); + if(typeof value == "number"){ + if(isNaN(value)){ formattedValue = '' } + // check for exponential notation that dojo.number.format chokes on + else if(("rangeCheck" in this && this.rangeCheck(value, this.constraints)) || this.constraints.exponent === false || !/\de[-+]?\d/i.test(formattedValue)){ + formattedValue = undefined; // lets format comnpute a real string value + } + }else if(!value){ // 0 processed in if branch above, ''|null|undefined flow thru here + formattedValue = ''; + value = NaN; + }else{ // non-numeric values + value = undefined; + } + } + this.inherited(arguments, [value, priorityChange, formattedValue]); + }, + + _getValueAttr: function(){ + // summary: + // Hook so get('value') works. + // Returns Number, NaN for '', or undefined for unparsable text + var v = this.inherited(arguments); // returns Number for all values accepted by parse() or NaN for all other displayed values + + // If the displayed value of the textbox is gibberish (ex: "hello world"), this.inherited() above + // returns NaN; this if() branch converts the return value to undefined. + // Returning undefined prevents user text from being overwritten when doing _setValueAttr(_getValueAttr()). + // A blank displayed value is still returned as NaN. + if(isNaN(v) && this.textbox.value !== ''){ + if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value) && (new RegExp("^"+dojo.number._realNumberRegexp(dojo.mixin({}, this.constraints))+"$").test(this.textbox.value))){ // check for exponential notation that parse() rejected (erroneously?) + var n = Number(this.textbox.value); + return isNaN(n) ? undefined : n; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check) + }else{ + return undefined; // gibberish + } + }else{ + return v; // Number or NaN for '' + } + }, + + isValid: function(/*Boolean*/ isFocused){ + // Overrides dijit.form.RangeBoundTextBox.isValid to check that the editing-mode value is valid since + // it may not be formatted according to the regExp vaidation rules + if(!this._focused || this._isEmpty(this.textbox.value)){ + return this.inherited(arguments); + }else{ + var v = this.get('value'); + if(!isNaN(v) && this.rangeCheck(v, this.constraints)){ + if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value)){ // exponential, parse doesn't like it + return true; // valid exponential number in range + }else{ + return this.inherited(arguments); + } + }else{ + return false; + } + } + } + } +); + +dojo.declare("dijit.form.NumberTextBox", + [dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin], + { + // summary: + // A TextBox for entering numbers, with formatting and range checking + // description: + // NumberTextBox is a textbox for entering and displaying numbers, supporting + // the following main features: + // + // 1. Enforce minimum/maximum allowed values (as well as enforcing that the user types + // a number rather than a random string) + // 2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point" + // depending on locale). + // 3. Separate modes for editing the value and displaying it, specifically that + // the thousands separator character (typically comma) disappears when editing + // but reappears after the field is blurred. + // 4. Formatting and constraints regarding the number of places (digits after the decimal point) + // allowed on input, and number of places displayed when blurred (see `constraints` parameter). + + baseClass: "dijitTextBox dijitNumberTextBox" + } +); + } |