2010-11-15 08:39:52 +01:00
/ *
2011-11-08 17:40:44 +01:00
Copyright ( c ) 2004 - 2011 , The Dojo Foundation All Rights Reserved .
2010-11-15 08:39:52 +01:00
Available via Academic Free License >= 2.1 OR the modified BSD license .
see : http : //dojotoolkit.org/license for details
* /
2011-11-08 17:40:44 +01:00
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 ;
2010-11-15 08:39:52 +01:00
dojo . provide ( "dijit.form.NumberTextBox" ) ;
dojo . require ( "dijit.form.ValidationTextBox" ) ;
dojo . require ( "dojo.number" ) ;
2011-11-08 17:40:44 +01:00
/ * = = = = =
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"
}
) ;
2010-11-15 08:39:52 +01:00
}