]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/form/NumberTextBox.js.uncompressed.js
1 define ( "dijit/form/NumberTextBox" , [
2 "dojo/_base/declare" , // declare
3 "dojo/_base/lang" , // lang.hitch lang.mixin
4 "dojo/number" , // number._realNumberRegexp number.format number.parse number.regexp
6 ], function ( declare
, lang
, number
, RangeBoundTextBox
){
9 // dijit/form/NumberTextBox
12 var NumberTextBoxMixin
= declare ( "dijit.form.NumberTextBoxMixin" , null , {
14 // A mixin for all number textboxes
18 // Override ValidationTextBox.pattern.... we use a reg-ex generating function rather
19 // than a straight regexp to deal with locale (plus formatting options too?)
20 pattern
: number
. regexp
,
23 // constraints: NumberTextBox.__Constraints
24 // Despite the name, this parameter specifies both constraints on the input
25 // (including minimum/maximum allowed values) as well as
26 // formatting options like places (the number of digits to display after
27 // the decimal point).
32 // The value of this NumberTextBox as a Javascript Number (i.e., not a String).
33 // If the displayed value is blank, the value is NaN, and if the user types in
34 // an gibberish value (like "hello world"), the value is undefined
35 // (i.e. get('value') returns undefined).
37 // Symmetrically, set('value', NaN) will clear the displayed value,
38 // whereas set('value', undefined) will have no effect.
41 // editOptions: [protected] Object
42 // Properties to mix into constraints when the value is being edited.
43 // This is here because we edit the number in the format "12345", which is
44 // different than the display value (ex: "12,345")
45 editOptions
: { pattern
: '#.######' },
48 _formatter: function(value, options){
50 // _formatter() is called by format(). It's the base routine for formatting a number,
51 // as a string, for example converting 12345 into "12,345".
53 // The number to be converted into a string.
54 // options: number.__FormatOptions?
57 // protected extension
59 return "12345"; // String
62 _formatter
: number
. format
,
64 postMixInProperties : function (){
65 this . inherited ( arguments
);
66 this . _set ( "type" , "text" ); // in case type="number" was specified which messes up parse/format
69 _setConstraintsAttr : function ( /*Object*/ constraints
){
70 var places
= typeof constraints
. places
== "number" ? constraints
. places
: 0 ;
71 if ( places
){ places
++; } // decimal rounding errors take away another digit of precision
72 if ( typeof constraints
. max
!= "number" ){
73 constraints
. max
= 9 * Math
. pow ( 10 , 15 - places
);
75 if ( typeof constraints
. min
!= "number" ){
76 constraints
. min
= - 9 * Math
. pow ( 10 , 15 - places
);
78 this . inherited ( arguments
, [ constraints
]);
79 if ( this . focusNode
&& this . focusNode
. value
&& ! isNaN ( this . value
)){
80 this . set ( 'value' , this . value
);
85 if ( this . disabled
){ return ; }
86 var val
= this . get ( 'value' );
87 if ( typeof val
== "number" && ! isNaN ( val
)){
88 var formattedValue
= this . format ( val
, this . constraints
);
89 if ( formattedValue
!== undefined ){
90 this . textbox
. value
= formattedValue
;
93 this . inherited ( arguments
);
96 format : function ( /*Number*/ value
, /*number.__FormatOptions*/ constraints
){
98 // Formats the value as a Number, according to constraints.
102 var formattedValue
= String ( value
);
103 if ( typeof value
!= "number" ){ return formattedValue
; }
104 if ( isNaN ( value
)){ return "" ; }
105 // check for exponential notation that dojo/number.format() chokes on
106 if (!( "rangeCheck" in this && this . rangeCheck ( value
, constraints
)) && constraints
. exponent
!== false && /\de[-+]?\d/i . test ( formattedValue
)){
107 return formattedValue
;
109 if ( this . editOptions
&& this . focused
){
110 constraints
= lang
. mixin ({}, constraints
, this . editOptions
);
112 return this . _formatter ( value
, constraints
);
116 _parser: function(value, constraints){
118 // Parses the string value as a Number, according to constraints.
120 // String representing a number
121 // constraints: number.__ParseOptions
122 // Formatting options
126 return 123.45; // Number
129 _parser
: number
. parse
,
131 parse : function ( /*String*/ value
, /*number.__FormatOptions*/ constraints
){
133 // Replaceable function to convert a formatted string to a number value
135 // protected extension
137 var v
= this . _parser ( value
, lang
. mixin ({}, constraints
, ( this . editOptions
&& this . focused
) ? this . editOptions
: {}));
138 if ( this . editOptions
&& this . focused
&& isNaN ( v
)){
139 v
= this . _parser ( value
, constraints
); // parse w/o editOptions: not technically needed but is nice for the user
144 _getDisplayedValueAttr : function (){
145 var v
= this . inherited ( arguments
);
146 return isNaN ( v
) ? this . textbox
. value
: v
;
149 filter : function ( /*Number*/ value
){
151 // This is called with both the display value (string), and the actual value (a number).
152 // When called with the actual value it does corrections so that '' etc. are represented as NaN.
153 // Otherwise it dispatches to the superclass's filter() method.
155 // See `dijit/form/TextBox.filter()` for more details.
156 return ( value
== null /* or undefined */ || value
=== '' ) ? NaN
: this . inherited ( arguments
); // set('value', null||''||undefined) should fire onChange(NaN)
159 serialize : function ( /*Number*/ value
, /*Object?*/ options
){
161 // Convert value (a Number) into a canonical string (ie, how the number literal is written in javascript/java/C/etc.)
164 return ( typeof value
!= "number" || isNaN ( value
)) ? '' : this . inherited ( arguments
);
167 _setBlurValue : function (){
168 var val
= lang
. hitch ( lang
. mixin ({}, this , { focused
: true }), "get" )( 'value' ); // parse with editOptions
169 this . _setValueAttr ( val
, true );
172 _setValueAttr : function ( /*Number*/ value
, /*Boolean?*/ priorityChange
, /*String?*/ formattedValue
){
174 // Hook so set('value', ...) works.
175 if ( value
!== undefined && formattedValue
=== undefined ){
176 formattedValue
= String ( value
);
177 if ( typeof value
== "number" ){
178 if ( isNaN ( value
)){ formattedValue
= '' }
179 // check for exponential notation that number.format chokes on
180 else if (( "rangeCheck" in this && this . rangeCheck ( value
, this . constraints
)) || this . constraints
. exponent
=== false || ! /\de[-+]?\d/i . test ( formattedValue
)){
181 formattedValue
= undefined ; // lets format compute a real string value
183 } else if (! value
){ // 0 processed in if branch above, ''|null|undefined flows through here
186 } else { // non-numeric values
190 this . inherited ( arguments
, [ value
, priorityChange
, formattedValue
]);
193 _getValueAttr : function (){
195 // Hook so get('value') works.
196 // Returns Number, NaN for '', or undefined for unparseable text
197 var v
= this . inherited ( arguments
); // returns Number for all values accepted by parse() or NaN for all other displayed values
199 // If the displayed value of the textbox is gibberish (ex: "hello world"), this.inherited() above
200 // returns NaN; this if() branch converts the return value to undefined.
201 // Returning undefined prevents user text from being overwritten when doing _setValueAttr(_getValueAttr()).
202 // A blank displayed value is still returned as NaN.
203 if ( isNaN ( v
) && this . textbox
. value
!== '' ){
204 if ( this . constraints
. exponent
!== false && /\de[-+]?\d/i . test ( this . textbox
. value
) && ( new RegExp ( "^" + number
. _realNumberRegexp ( lang
. mixin ({}, this . constraints
))+ "$" ). test ( this . textbox
. value
))){ // check for exponential notation that parse() rejected (erroneously?)
205 var n
= Number ( this . textbox
. value
);
206 return isNaN ( n
) ? undefined : n
; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check)
208 return undefined ; // gibberish
211 return v
; // Number or NaN for ''
215 isValid : function ( /*Boolean*/ isFocused
){
216 // Overrides dijit/form/RangeBoundTextBox.isValid() to check that the editing-mode value is valid since
217 // it may not be formatted according to the regExp validation rules
218 if (! this . focused
|| this . _isEmpty ( this . textbox
. value
)){
219 return this . inherited ( arguments
);
221 var v
= this . get ( 'value' );
222 if (! isNaN ( v
) && this . rangeCheck ( v
, this . constraints
)){
223 if ( this . constraints
. exponent
!== false && /\de[-+]?\d/i . test ( this . textbox
. value
)){ // exponential, parse doesn't like it
224 return true ; // valid exponential number in range
226 return this . inherited ( arguments
);
235 var NumberTextBox
= declare ( "dijit.form.NumberTextBox" , [ RangeBoundTextBox
, NumberTextBoxMixin
], {
237 // A TextBox for entering numbers, with formatting and range checking
239 // NumberTextBox is a textbox for entering and displaying numbers, supporting
240 // the following main features:
242 // 1. Enforce minimum/maximum allowed values (as well as enforcing that the user types
243 // a number rather than a random string)
244 // 2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point"
245 // depending on locale).
246 // 3. Separate modes for editing the value and displaying it, specifically that
247 // the thousands separator character (typically comma) disappears when editing
248 // but reappears after the field is blurred.
249 // 4. Formatting and constraints regarding the number of places (digits after the decimal point)
250 // allowed on input, and number of places displayed when blurred (see `constraints` parameter).
252 baseClass
: "dijitTextBox dijitNumberTextBox"
255 NumberTextBox
. Mixin
= NumberTextBoxMixin
; // for monkey patching
258 NumberTextBox.__Constraints = declare([RangeBoundTextBox.__Constraints, number.__FormatOptions, number.__ParseOptions], {
260 // Specifies both the rules on valid/invalid values (minimum, maximum,
261 // number of required decimal places), and also formatting options for
262 // displaying the value when the field is not focused.
265 // To specify a field between 0 and 120:
267 // To specify a field that must be an integer:
268 // | {fractional:false}
269 // To specify a field where 0 to 3 decimal places are allowed on input:
274 return NumberTextBox
;