jQuery.NumPad icon indicating copy to clipboard operation
jQuery.NumPad copied to clipboard

Comma ?

Open cotiga opened this issue 8 years ago • 4 comments

Good work, but comma clears instead of adding decimals

cotiga avatar Nov 06 '17 21:11 cotiga

I ran into this and came up with a hack/workaround. Explanation below and file: jquery.numpad.js.zip

I need to accept decimal numbers without a leading 0. The keypad should add the leading zero if it's not there i.e.) Entering ".3" should be acceptable and show "0.3". How it works currently: If a number is pressed after a decimal point (first press "." then press "3") the entire input is cleared. "3" will be shown.

The reason is the nmpd.getValue() function in jquery.numpad.js uses the native javascript isNaN() function to determine if the current input is a number or not. isNaN('.') returns true, so if the user enters a '.' the getValue function will return a 0.

Both the getValue and setValue functions need to be updated. Typical usage of the number keys is setValue(getValue + some new value). Basically set the value of the display to the current value plus the key that was pressed.

So getValue needs to allow returning "." and setValue needs to add a leading 0 if the value is "."

Original getValue() function:

/**
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
	return isNaN(nmpd.display.val()) ? 0 : nmpd.display.val();
};

New getValue() and setValue() functions:

/** NEW
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
	if(nmpd.display.val() == options.decimalSeparator) {
		// Special case to support decimals without leading zeros. If the display value is the separator ex) '.',
		// this still needs to be considered a valid number even though isNaN('.') is true.
		return nmpd.display.val();
	}
	else {
		return isNaN(nmpd.display.val()) ? 0 : nmpd.display.val();
	}
};

/** NEW
* Sets the display value of the numpad and then trigger the onChange function if it was defined in the options.
* @param string value
* @return jQuery object nmpd
*/
nmpd.setValue = function(value){
	if (nmpd.display.attr('maxLength') < value.toString().length) {
		value = value.toString().substr(0, nmpd.display.attr('maxLength'));
	}
	if(value[0] == options.decimalSeparator) {
		// If there is a leading decimal, then add a zero for display.
		value = 0 + value;
	}
	nmpd.display.val(value);
	// When you set the value of the numpad, change the value of dirty to 1 to keep track of a the dirty input.
	nmpd.find('.dirty').val('1');
	nmpd.trigger('numpad.change', [value]);
	return nmpd;
};

rswamy avatar Feb 23 '18 23:02 rswamy

Specifying the decimalSeparator didn't solve the issue but was part of the solution, all you have to do is to add a replace at line #162: Original code:

/**
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
    return isNaN(nmpd.display.val()) ? 0 : nmpd.display.val();
};

New code:

/**
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
    return isNaN(nmpd.display.val().replace(options.decimalSeparator, ".")) ? 0 : nmpd.display.val();
};

galloverde11 avatar Mar 14 '18 13:03 galloverde11

FYI @rswamy I don't think your solution works as of jQuery 3.3.1. Calling nmpd.display.val(value); with a trailing decimal in value causes jQuery to give you the following error:

The specified value "0." is not a valid number. 
The value must match to the following regular expression: -?(\d+|\d+\.\d+|\.\d+)([eE][-+]?\d+)?

I'm going to see if I can find a solution tomorrow.

EDIT:

Just kidding. It looks like your solution works fine as long as you leave the <input> as type="text". I had changed it to type="number" at some point. Thanks!

There are a couple quirks.

  1. It looks like this addition allows 2 decimals to be entered before it clears rather than just the original 1.
  2. If you are running .numpad(); against a <input type="number"> it will fail if you click Done when the value has a trailing decimal, for the same reason my jQuery was failing above.

To resolve the second issue I modified the following code from nmpd.close:

if (target.prop("tagName") == 'INPUT') {
    target.val(nmpd.getValue().toString().replace('.', options.decimalSeparator));
} else {
    target.html(nmpd.getValue().toString().replace('.', options.decimalSeparator));
}

To:

var val = nmpd.getValue().toString().replace('.', options.decimalSeparator);
if (val.length > 0 && val[val.length - 1] === ".") { val = val + 0; }
if (target.prop("tagName") == 'INPUT') {
    target.val(val);
} else {
    target.html(val);
}

orionstudt avatar Mar 14 '18 22:03 orionstudt

I think this PR fixes some of the issues mentioned here, including being unable to begin an entry with a decimal separator, whichever is for your locale.

https://github.com/kabachello/jQuery.NumPad/pull/12

FeIronMonkey avatar Aug 06 '21 15:08 FeIronMonkey