Number3.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-form-field-Number'>/**
  19. </span> * @docauthor Jason Johnston &lt;jason@sencha.com&gt;
  20. *
  21. * A numeric text field that provides automatic keystroke filtering to disallow non-numeric characters,
  22. * and numeric validation to limit the value to a range of valid numbers. The range of acceptable number
  23. * values can be controlled by setting the {@link #minValue} and {@link #maxValue} configs, and fractional
  24. * decimals can be disallowed by setting {@link #allowDecimals} to `false`.
  25. *
  26. * By default, the number field is also rendered with a set of up/down spinner buttons and has
  27. * up/down arrow key and mouse wheel event listeners attached for incrementing/decrementing the value by the
  28. * {@link #step} value. To hide the spinner buttons set `{@link #hideTrigger hideTrigger}:true`; to disable
  29. * the arrow key and mouse wheel handlers set `{@link #keyNavEnabled keyNavEnabled}:false` and
  30. * `{@link #mouseWheelEnabled mouseWheelEnabled}:false`. See the example below.
  31. *
  32. * # Example usage
  33. *
  34. * @example
  35. * Ext.create('Ext.form.Panel', {
  36. * title: 'On The Wall',
  37. * width: 300,
  38. * bodyPadding: 10,
  39. * renderTo: Ext.getBody(),
  40. * items: [{
  41. * xtype: 'numberfield',
  42. * anchor: '100%',
  43. * name: 'bottles',
  44. * fieldLabel: 'Bottles of Beer',
  45. * value: 99,
  46. * maxValue: 99,
  47. * minValue: 0
  48. * }],
  49. * buttons: [{
  50. * text: 'Take one down, pass it around',
  51. * handler: function() {
  52. * this.up('form').down('[name=bottles]').spinDown();
  53. * }
  54. * }]
  55. * });
  56. *
  57. * # Removing UI Enhancements
  58. *
  59. * @example
  60. * Ext.create('Ext.form.Panel', {
  61. * title: 'Personal Info',
  62. * width: 300,
  63. * bodyPadding: 10,
  64. * renderTo: Ext.getBody(),
  65. * items: [{
  66. * xtype: 'numberfield',
  67. * anchor: '100%',
  68. * name: 'age',
  69. * fieldLabel: 'Age',
  70. * minValue: 0, //prevents negative numbers
  71. *
  72. * // Remove spinner buttons, and arrow key and mouse wheel listeners
  73. * hideTrigger: true,
  74. * keyNavEnabled: false,
  75. * mouseWheelEnabled: false
  76. * }]
  77. * });
  78. *
  79. * # Using Step
  80. *
  81. * @example
  82. * Ext.create('Ext.form.Panel', {
  83. * renderTo: Ext.getBody(),
  84. * title: 'Step',
  85. * width: 300,
  86. * bodyPadding: 10,
  87. * items: [{
  88. * xtype: 'numberfield',
  89. * anchor: '100%',
  90. * name: 'evens',
  91. * fieldLabel: 'Even Numbers',
  92. *
  93. * // Set step so it skips every other number
  94. * step: 2,
  95. * value: 0,
  96. *
  97. * // Add change handler to force user-entered numbers to evens
  98. * listeners: {
  99. * change: function(field, value) {
  100. * value = parseInt(value, 10);
  101. * field.setValue(value + value % 2);
  102. * }
  103. * }
  104. * }]
  105. * });
  106. */
  107. Ext.define('Ext.form.field.Number', {
  108. extend:'Ext.form.field.Spinner',
  109. alias: 'widget.numberfield',
  110. alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
  111. <span id='Ext-form-field-Number-cfg-stripCharsRe'> /**
  112. </span> * @cfg {RegExp} stripCharsRe
  113. * @private
  114. */
  115. <span id='Ext-form-field-Number-cfg-maskRe'> /**
  116. </span> * @cfg {RegExp} maskRe
  117. * @private
  118. */
  119. <span id='Ext-form-field-Number-cfg-allowDecimals'> /**
  120. </span> * @cfg {Boolean} allowDecimals
  121. * False to disallow decimal values
  122. */
  123. allowDecimals : true,
  124. //&lt;locale&gt;
  125. <span id='Ext-form-field-Number-cfg-decimalSeparator'> /**
  126. </span> * @cfg {String} decimalSeparator
  127. * Character(s) to allow as the decimal separator
  128. */
  129. decimalSeparator : '.',
  130. //&lt;/locale&gt;
  131. //&lt;locale&gt;
  132. <span id='Ext-form-field-Number-cfg-submitLocaleSeparator'> /**
  133. </span> * @cfg {Boolean} [submitLocaleSeparator=true]
  134. * False to ensure that the {@link #getSubmitValue} method strips
  135. * always uses `.` as the separator, regardless of the {@link #decimalSeparator}
  136. * configuration.
  137. */
  138. submitLocaleSeparator: true,
  139. //&lt;/locale&gt;
  140. //&lt;locale&gt;
  141. <span id='Ext-form-field-Number-cfg-decimalPrecision'> /**
  142. </span> * @cfg {Number} decimalPrecision
  143. * The maximum precision to display after the decimal separator
  144. */
  145. decimalPrecision : 2,
  146. //&lt;/locale&gt;
  147. <span id='Ext-form-field-Number-cfg-minValue'> /**
  148. </span> * @cfg {Number} minValue
  149. * The minimum allowed value. Will be used by the field's validation logic,
  150. * and for {@link Ext.form.field.Spinner#setSpinUpEnabled enabling/disabling the down spinner button}.
  151. *
  152. * Defaults to Number.NEGATIVE_INFINITY.
  153. */
  154. minValue: Number.NEGATIVE_INFINITY,
  155. <span id='Ext-form-field-Number-cfg-maxValue'> /**
  156. </span> * @cfg {Number} maxValue
  157. * The maximum allowed value. Will be used by the field's validation logic, and for
  158. * {@link Ext.form.field.Spinner#setSpinUpEnabled enabling/disabling the up spinner button}.
  159. *
  160. * Defaults to Number.MAX_VALUE.
  161. */
  162. maxValue: Number.MAX_VALUE,
  163. <span id='Ext-form-field-Number-cfg-step'> /**
  164. </span> * @cfg {Number} step
  165. * Specifies a numeric interval by which the field's value will be incremented or decremented when the user invokes
  166. * the spinner.
  167. */
  168. step: 1,
  169. //&lt;locale&gt;
  170. <span id='Ext-form-field-Number-cfg-minText'> /**
  171. </span> * @cfg {String} minText
  172. * Error text to display if the minimum value validation fails.
  173. */
  174. minText : 'The minimum value for this field is {0}',
  175. //&lt;/locale&gt;
  176. //&lt;locale&gt;
  177. <span id='Ext-form-field-Number-cfg-maxText'> /**
  178. </span> * @cfg {String} maxText
  179. * Error text to display if the maximum value validation fails.
  180. */
  181. maxText : 'The maximum value for this field is {0}',
  182. //&lt;/locale&gt;
  183. //&lt;locale&gt;
  184. <span id='Ext-form-field-Number-cfg-nanText'> /**
  185. </span> * @cfg {String} nanText
  186. * Error text to display if the value is not a valid number. For example, this can happen if a valid character like
  187. * '.' or '-' is left in the field with no number.
  188. */
  189. nanText : '{0} is not a valid number',
  190. //&lt;/locale&gt;
  191. //&lt;locale&gt;
  192. <span id='Ext-form-field-Number-cfg-negativeText'> /**
  193. </span> * @cfg {String} negativeText
  194. * Error text to display if the value is negative and {@link #minValue} is set to 0. This is used instead of the
  195. * {@link #minText} in that circumstance only.
  196. */
  197. negativeText : 'The value cannot be negative',
  198. //&lt;/locale&gt;
  199. <span id='Ext-form-field-Number-cfg-baseChars'> /**
  200. </span> * @cfg {String} baseChars
  201. * The base set of characters to evaluate as valid numbers.
  202. */
  203. baseChars : '0123456789',
  204. <span id='Ext-form-field-Number-cfg-autoStripChars'> /**
  205. </span> * @cfg {Boolean} autoStripChars
  206. * True to automatically strip not allowed characters from the field.
  207. */
  208. autoStripChars: false,
  209. initComponent: function() {
  210. var me = this,
  211. allowed;
  212. me.callParent();
  213. me.setMinValue(me.minValue);
  214. me.setMaxValue(me.maxValue);
  215. // Build regexes for masking and stripping based on the configured options
  216. if (me.disableKeyFilter !== true) {
  217. allowed = me.baseChars + '';
  218. if (me.allowDecimals) {
  219. allowed += me.decimalSeparator;
  220. }
  221. if (me.minValue &lt; 0) {
  222. allowed += '-';
  223. }
  224. allowed = Ext.String.escapeRegex(allowed);
  225. me.maskRe = new RegExp('[' + allowed + ']');
  226. if (me.autoStripChars) {
  227. me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
  228. }
  229. }
  230. },
  231. <span id='Ext-form-field-Number-method-getErrors'> /**
  232. </span> * Runs all of Number's validations and returns an array of any errors. Note that this first runs Text's
  233. * validations, so the returned array is an amalgamation of all field errors. The additional validations run test
  234. * that the value is a number, and that it is within the configured min and max values.
  235. * @param {Object} [value] The value to get errors for (defaults to the current field value)
  236. * @return {String[]} All validation errors for this field
  237. */
  238. getErrors: function(value) {
  239. var me = this,
  240. errors = me.callParent(arguments),
  241. format = Ext.String.format,
  242. num;
  243. value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
  244. if (value.length &lt; 1) { // if it's blank and textfield didn't flag it then it's valid
  245. return errors;
  246. }
  247. value = String(value).replace(me.decimalSeparator, '.');
  248. if(isNaN(value)){
  249. errors.push(format(me.nanText, value));
  250. }
  251. num = me.parseValue(value);
  252. if (me.minValue === 0 &amp;&amp; num &lt; 0) {
  253. errors.push(this.negativeText);
  254. }
  255. else if (num &lt; me.minValue) {
  256. errors.push(format(me.minText, me.minValue));
  257. }
  258. if (num &gt; me.maxValue) {
  259. errors.push(format(me.maxText, me.maxValue));
  260. }
  261. return errors;
  262. },
  263. rawToValue: function(rawValue) {
  264. var value = this.fixPrecision(this.parseValue(rawValue));
  265. if (value === null) {
  266. value = rawValue || null;
  267. }
  268. return value;
  269. },
  270. valueToRaw: function(value) {
  271. var me = this,
  272. decimalSeparator = me.decimalSeparator;
  273. value = me.parseValue(value);
  274. value = me.fixPrecision(value);
  275. value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
  276. value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
  277. return value;
  278. },
  279. getSubmitValue: function() {
  280. var me = this,
  281. value = me.callParent();
  282. if (!me.submitLocaleSeparator) {
  283. value = value.replace(me.decimalSeparator, '.');
  284. }
  285. return value;
  286. },
  287. onChange: function() {
  288. this.toggleSpinners();
  289. this.callParent(arguments);
  290. },
  291. toggleSpinners: function(){
  292. var me = this,
  293. value = me.getValue(),
  294. valueIsNull = value === null;
  295. me.setSpinUpEnabled(valueIsNull || value &lt; me.maxValue);
  296. me.setSpinDownEnabled(valueIsNull || value &gt; me.minValue);
  297. },
  298. <span id='Ext-form-field-Number-method-setMinValue'> /**
  299. </span> * Replaces any existing {@link #minValue} with the new value.
  300. * @param {Number} value The minimum value
  301. */
  302. setMinValue : function(value) {
  303. this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
  304. this.toggleSpinners();
  305. },
  306. <span id='Ext-form-field-Number-method-setMaxValue'> /**
  307. </span> * Replaces any existing {@link #maxValue} with the new value.
  308. * @param {Number} value The maximum value
  309. */
  310. setMaxValue: function(value) {
  311. this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
  312. this.toggleSpinners();
  313. },
  314. // private
  315. parseValue : function(value) {
  316. value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
  317. return isNaN(value) ? null : value;
  318. },
  319. <span id='Ext-form-field-Number-method-fixPrecision'> /**
  320. </span> * @private
  321. */
  322. fixPrecision : function(value) {
  323. var me = this,
  324. nan = isNaN(value),
  325. precision = me.decimalPrecision;
  326. if (nan || !value) {
  327. return nan ? '' : value;
  328. } else if (!me.allowDecimals || precision &lt;= 0) {
  329. precision = 0;
  330. }
  331. return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
  332. },
  333. beforeBlur : function() {
  334. var me = this,
  335. v = me.parseValue(me.getRawValue());
  336. if (!Ext.isEmpty(v)) {
  337. me.setValue(v);
  338. }
  339. },
  340. onSpinUp: function() {
  341. var me = this;
  342. if (!me.readOnly) {
  343. me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
  344. }
  345. },
  346. onSpinDown: function() {
  347. var me = this;
  348. if (!me.readOnly) {
  349. me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
  350. }
  351. }
  352. });
  353. </pre>
  354. </body>
  355. </html>