PDA

View Full Version : 4.0.2 Ext.form.field.Number : force decimal precision in string value.



pkli
23 Jun 2011, 4:17 AM
Hi,

Here is two (very) simple modifications for "numberfield" prototype.
For beginners ...

A new param "forceDecimals", to force formatting of the string value with as many decimals than "decimalPrecision".

Eg :
decimalPrecision : 2
forceDecimals : true
value : 125.2

=> display/submit value : 125.20

I'm not a javascript expert ...
Comments, criticals or suggestions are welcome ...


bonus track ... As french user, I use "," (comma) as decimalSeparator. A simple way to use "." (dot) as secondary allowed decimalSeparator is to allow it in baseChars ...
So you can use any of them (useful to allow copy/paste from others software using dot as decimal separator)...




if (Ext.form.field.Number){
Ext.apply(Ext.form.field.Number.prototype, {

// force decimals string value
forceDecimals : true,
valueToRaw: function(value) {
var me = this,decimalSeparator = me.decimalSeparator,precision = me.decimalPrecision,forceDecimals = me.forceDecimals;
value = me.parseValue(value);
value = me.fixPrecision(value);
value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));

if (isNaN(value)) return '';
else {
value = String(value).replace('.', decimalSeparator);
if (value.indexOf(decimalSeparator)>=0 && forceDecimals) {
var dec = value.substr(value.indexOf(decimalSeparator)+1);
for(var i=dec.length;i<precision;i++) {
value = value+"0";
}
}
return value;
}
},

// allow dot as decimalSeparator even if this is not the locale setting
baseChars : '0123456789.',
});
}

JanVenekamp
29 Jun 2011, 3:43 AM
You might want to take a look at regular expressions.

Out of my head (so not checked):


{
xtype: 'text',
// forcDecimals: true, numDecimals 2
regex: /^[0-9]+(.|,)[0-9]{2}$/,
regex: new RegExp(
'/^[0-9]+((.|,)[0-9]{'+numDecimals+'})'+ (!forceDecimals ? '?':'') +'$/',
}

pkli
29 Jun 2011, 7:44 AM
@JanVenekamp : "You might want to take a look at regular expressions."

Thanks for your suggestion.
You're right ... but there is a problem ... I HATE regular expressions ! :)

First, I think that RegEx is very powerfull in complex cases but absolutely not intuitive (even good programmers have to double check their expressions ;) ) and sometinmes useless for simple checks.

But also, few years ago, I had to code a PHP function to check if a string was present in long html source codes.
I used RegEx and the result was very time consuming...
So, I used a simple string search and the execution time was reduced by 5 ...

But as you're right on the principle, I do not want to keep this bad experience as reference. So, I just write a single JS test to compare again the two methods in a loop.
Checking with RegEx VS string function.


1 - Using string function to test AND set correct value :



var start = new Date;
for (var t = 0;t<1000000;t++) {

var value = "10.";
if (value.indexOf(".")>=0) {
var dec = value.substr(value.indexOf(".")+1);
for(var i=dec.length;i<2;i++) {
value = value+"0";
}
}

}
var end = new Date;
console.log(end.getTime()-start.getTime());


Result : 473 milliseconds


2 - Using RegEx, just to check value :



var start = new Date;
for (var t = 0;t<1000000;t++) {
var value = "10.";
var reg = new RegExp('/^[0-9]+.[0-9]{2}$/');
var test = reg.test(value);
}
var end = new Date;
console.log(end.getTime()-start.getTime());


Result : 9085 milliseconds !!!!

WOW !!!
Definitely, I do not like RegEx ... :) :) :)

Of course, this test is based on a "1000000" loop ... in "real life", difference is insignificant
but RegEx is really a time consuming method ...

Allan
29 Jun 2011, 7:34 PM
What if you took the new RegExp(...) out of the loop?

pkli
29 Jun 2011, 11:55 PM
@Allan

With "new RegExp" out of the loop, RegExp wins ...



var value = "10.2";
var reg = new RegExp('/^[0-9]+.[0-9]{2}$/');

var start = new Date;
for (var t = 0;t<1000000;t++) {
if (value.indexOf(".")>=0 && value.substr(value.indexOf(".")+1).length < 2 ) {
// set value
}
}
var end = new Date;
console.log(end.getTime()-start.getTime());


start = new Date;
for (var t = 0;t<1000000;t++) {
if (!reg.test(value)) {
// set value
}
}
end = new Date;
console.log(end.getTime()-start.getTime());


String test : 185
RegExp test : 102

So, you're right, using one RegExp to test many string is a quicker method.

But in this example, I think that use a RegExp to check a field value means declare it each time.
So, unless I'm wrong, we have to let it in the test loop ?

Of course, "I hate RegExp" was a joke (even if I really hate it :) :) :) ) because it's a powerful and useful function.
What I mean is that using RegExp seems more effective, but ... not always ...

JanVenekamp
30 Jun 2011, 4:31 AM
@pkli Learning regular expressions can be a , but once you master the basics it's very handy. The one line regex is far more easier to write and interpret for someone who knows regex than 10+ lines of code.

pkli
30 Jun 2011, 5:08 AM
To be a little serious, I think of course you're right in a global approach...

Coding is like anything else ... several ways to get the same result.
As I work alone, I use the easiest way according to my knowledge.

But I promise to take a couple of hours asap to perfect my RegExp knowledge and to reconcile myself with it ... ;)

Thank you for your advice !

brittongr
21 Sep 2011, 5:26 AM
Here is another extension that apply format http://www.sencha.com/forum/showthread.php?147962-Number-Field-with-currency-symbol-thousand-separator-amp-international-support-ExtJS4.

JackThor
28 Jan 2013, 2:05 PM
I can't fine forceDecimal in config. Is it no longer in Ext. JS 4.1.3 or maybe it was put somewhere else