Validating numeric input while formatting numeric input - javascript

In an asp.net-mvc project using C#.
I use a function to format larger numbers with commas such as 1,000,000, thanks to this post:
function numberWithCommas(str) {
return str.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
The issue is, I have the inputs locked down to accept only numbers with a min value of zero.
<input type="number" min="0" class="myclass" value="#somevalue" />
This poses a problem using the JS, as it needs only number input. Which brings me to a question like this How to make HTML input tag only accept numerical values?, which also offers a JS solution.
I'm wondering if anyone has developed an elegant way to format numeric input display, while validating numeric input, is there are any other options available here? It doesn't have to purely be a JS solution.

You can't use the numeric input, because, well, JavaScript doesn't consider formatted number to be a number.
The option is to use the non-numeric input but filter out any "problematic" chars.
In the following example, I'm also handling the dot separator in case you need to accept fractions.
As the text box is being edited, it also has to preserve the cursor position. I've achieved it there with the help of Updating an input's value without losing cursor position.
function format(inp){
var start = inp.selectionStart, // get the selection start
end = inp.selectionEnd; // and end, as per the linked post
var s1=inp.value.split(",").length-1; //count the commas before edit
inp.value=numberWithCommas(inp.value.replace(/,|[^\d.]/g,''));
var s2=inp.value.split(",").length-s1-1; //count the commas after edit so as to know where to place the cursor, as the position changes, if there are new commas or some commas have been removed
inp.setSelectionRange(start+s2, end+s2); // set the selection start and end, as per the linked post
}
function numberWithCommas(str) {
var a=str.split('.');
var p=/\B(?=(\d{3})+(?!\d))/g;
if(a.length>1)
return a[0].toString().replace(p, ",")+"."+a[1];
else
return str.toString().replace(p, ",");
}
<input onkeyup="format(this)">

I have the answer of your first question.
You can disable all keys rather than only numbers keys.
function isNumberKey(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode;
if (charCode != 43 && charCode > 31
&& (charCode < 48 || charCode > 57))
return false;
return true;
}
I also created working demo on jsfiddle

The program flow:
Getting the input via an on change event and calling the other functions, showing passing the data through a Ajax POST.
$('.Amount').on("change", function (e) {
var myInput = $(e.target);
var input = this.value;
// Remove any non digits (including commas) to pass value to controller.
var Amount = validateInput(input);
// Format the string to have commas every three digits 1,000,000 for display.
var val = numberWithCommas(Amount);
$(myInput).val(val);
$.ajax({
type: 'POST',
dataType: "json",
url: somesUrl + '/' + somethingelse,
data: JSON.parse('{"Amount": "' + Amount + '"}'), // Amount is a nice format here and will not throw an error.
// TODO etc
});
});
Remove any non numbers and give a value of zero if no numbers are inputted.
var validateInput = function (input) {
input = input.toString().replace(/[^0-9]/g, "");
/* Remove leading zeros. */
input = input.replace(/^0+/, '');
if (input == "")
input = 0;
return input;
}
Format the input with commas 1,000,000,000.
function numberWithCommas(str) {
return str.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
So even if the user types input with commas e.g. 1,734,567 it will work and if they misplace where they put a commas e.g. 17,35,555 it will still validate.
See working fiddle.
I actually worked out a nice solution while trying to meet project deadlines and in part this was solved by this answer by nicael.
This solution does not check the input as it is being typed, but after it is finished, I chose the change event, as opposed to the input event, as it calls the function once and (similar to a submit event) than validates the input in one call. Removing any commas and non digits; solving the issue of formatting with commas, by removing them for the ajax call, then reformatting it with commas for the display. There is a check to remove leading zeros.
If all the input is garbage I replace this value with zero to prevent an error passing to the controller with null data (just a design choice, could display a toast message instead).

Related

toString().length on a number with zeros and only zeros always returns 0

I'm working on a page that accepts 4 digits (exactly 4 digits) pin from users. Something like this.
<input type="number" ng-model="passCode" class="form-control" onpaste="return false" id="passCodeField" ng-disabled="!enablePassCode" ng-change="onInputPasscode()" ng-keypress="onKeyPressPasscode($event)"/>
onKeyPressPasscode function
$scope.onKeyPressPasscode = function($event) {
if(isNaN(String.fromCharCode($event.which || $event.keyCode))){
$event.preventDefault();
}
}
onInputPasscode() function :
$scope.onInputPasscode = function() {
if ($scope.passCode.toString().length > 4){
$scope.passCode = $scope.passcode;
}
if($scope.passCode.toString().length == 4) {
$scope.passcode = $scope.passCode;
$scope.disableContinue = false;
session.put('pinFlow',true);
} else {
console.log("current length - " + $scope.passCode);
$scope.disableContinue = true;
session.put('pinFlow',false);
}
}
This is failing when the input is all zeros. i.e current length is not getting updated hence the user is allowed input as many zeros as he wants. How do I take 4 digit zeros as input and still meet the checks that I have?
This is in angular 1.5.8v. And I'm not an expert in AngularJS. So any help would be appreciated. Also, please let me know if need any other info. I'll update the answer accordingly.
Thanks in advance.
It's not possible to do this with a an input with type set to number.
When user enters a number 0001, that's actually 1.
Things like PINs should be handled with type set to text.
You can then use a regex for validation.
To allow exactly four digits, no more and no less, use the following regex:
^\d{4,4}$
From JavaScript, use this regex to test a string, like the following:
/^\d{4,4}$/.test('1234')
// => true
/^\d{4,4}$/.test('123456')
// => false
/^\d{4,4}$/.test('12')
// => false
The cause of your problem is that if you PIN Scheme allows for leadings zeros, number is not the ideal type for this (because in numbers, leading zeros can be omitted without changing meaning).
Instead, use input type=text or probably even better, input type=password. Also, I wouldn't listen to keypress - instead use the input event.

Function not calculating values of formatted numbers

I built a calculator that takes user input (1 text field, 2 select dropdowns) and then displays the output below if the required conditions are met. I also wanted to have the text input field display thousand separators (commas) dynamically as the user types in a number, which I achieved using this:
$('#orderAmt').keyup(function(event) {
// skip for arrow keys
if (event.which >= 37 && event.which <= 40) return;
// format number
$(this).val(function(index, value) {
return value
.replace(/\D/g, "")
.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
});
});
Now, as expected, the calculator function doesn't recognize any of these values because they have been converted to strings. I assume that the next step is to use something like parseInt, so I added this line at the end of the .keyup function:
var converted = parseInt($('#orderAmt'), 10);
But I'm lost on what to do next, because the actual calculator function is written in vanilla JS and here I am trying to store the user's value in a new jQuery variable. Is there a better approach that I should be taking with this?
Here's my JSFiddle - https://jsfiddle.net/bkroger7/yk13wzcc/
If anyone can point me in the right direction it would be greatly appreciated.
BTW - I've tried the infamous, non-jQuery addCommas function as seen here but it won't work for me - only jQuery-based solutions have been working so far.
your problem is you are adding commas to the input field and then taking it as is...
so when you use $('#orderAmt').val() after you add commas you will get 3,000 instead of 3000
what you need to do is just remove the commas...
here is a working fork
https://jsfiddle.net/Lw9cvzn0/1/
notice: var orderAmount = $('#orderAmt').val().replace(new RegExp(','), '');
You're missing the call to .val() to get the field's value. And then you have to remove the commas before you parse it.
var converted = parseInt($('#orderAmt').val().replace(/,/g, ''), 10);

How to round a number up and add numeric punctuation

I've got the following pen: http://codepen.io/anon/pen/LVLzvR
I cant quite figure out how to round the number up so you don't break the punctuation. I need to round the number up as I don't want to see a value like 33,333.,333
//ADDS PUNCTUATION EVERY THREE CHARACTERS
$('input.numericpunctuation').keyup(function(event){
var oNum= $(this).val(); // USE THIS NUMBER FOR CALCULATION
var num = oNum.replace(/,/gi, "").split("").reverse().join("");
var num2 = RemoveRougeChar(num.replace(/(.{3})/g,"$1,").split("").reverse().join(""));
console.log(num2);
console.log(oNum);
// the following line has been simplified. Revision history contains original.
$(this).val(num2);
});
function RemoveRougeChar(convertString){
if(convertString.substring(0,1) == ","){
return convertString.substring(1, convertString.length)
}
return convertString;
}
Example input event:
If I input 5555, is expect to see (and do see) 5,555. However if I add 5555.55 I get 5,555,.55. Ideally id like to round the number up removing the decimal.
The problem isn't just with decimals, you will get the wrong formatting also by entering non digits, e.g., clicking King Kong will result in Kin,g K,ong. So, what you probably want is to filter out non-digits, which can be done by changing the line var oNum= $(this).val(); to:
var oNum= $(this).val().match(/\d/g).join('');
The value inside the match function is a RegEx object - if you never used it before then congratulations!

JavaScript: Retrieve negative floating point number from string of mutiple sums

I have a simple app that allows me to caculate the total amount invoiced and deposited in a route. However I want to allow the user to input multiple values in a single input field; e.g:
500+50+36.5-45.2-10.
I have written a function that will retrieve this input and then split this string into elements of an array at the + sign and immediately parse the values to numbers and then add them and return the total the user inputs into each individual field. This is all well as long as the user does no use any sign other than +.
I have searched the use of regexp:
regular expression in javascript for negative floating point number result stored in array
Javascript Regular expression to allow negative double value?
but none of the results seem to work.
How could I make my code retrieve the values so that the negative values get passed into the array as negative values?
Here is a snippet of my Js code:
For the full code, visit my fiddle.
totalInvoiced: function () {
var a = A.invoiced.value;
var value1Arr = [];
value1Arr = a.split("+").map(parseFloat);
var value1 = 0;
value1Arr.forEach(function (value) {
value1 += value;
});
I really like PhistucK's solution, but here an alternative with regex:
value1Arr = a.split(/(?=\+|\-)/);
This will split it, but keeps the delimiter, so the result will be:
["500", "+50", "+36.5", "-45.2", "-10"]
A bit dirty, but maybe a.replace(/-/g, "+-").split("+"), this way, you add a plus before every minus, since the negative numbers just basically lack an operator.
You can use this pattern that splits on + sign or before - sign:
var str = '500+50+36.5-45.2-10';
console.log(str.split(/\+|(?=-)/));

Javascript Regex for Decimal Numbers - Replace non-digits and more than one decimal point

I am trying to limit an input to a decimal number. I'd like any invalid characters not to be displayed at all (not displayed and then removed). I already have this implemented but for whole integers (like input for a phone number) but now I need to apply it for decimal input.
Sample input/output:
default value 25.00 -> type 2b5.00 -> display 25.00
default value 265.50 -> type 2.65.50 -> display 265.50 (as if prevented decimal point from being entered)
default value 265.52 -> type 265.52. -> display 265.52 (same as previous one)
End New Edit
I found many threads that dealt with "decimal input" issue but almost 99% of them deal only with "match"ing and "test"ing the input while my need is to replace the invalid characters.
Other than trying many regexes like /^\d+(\.\d{0,2})?$/, I also tried something like the below which keeps only the first occurrence in the input. This still isn't my requirement because I need the "original" decimal point to remain not the first one in the new input. This was the code for it:
[this.value.slice(0, decimalpoint), '.', this.value.slice(decimalpoint)].join('')
This thread is the closest to what I need but since there was no response to the last comment about preventing multiple decimal points (which is my requirement), it wasn't useful.
Any help would be appreciated.
Outline: find the first ., split there and clean the parts, else just return cleaned value.
function clean(string) {
return string.replace(/[^0-9]/g, "");
}
var value = "a10.10.0";
var pos = value.indexOf(".");
var result;
if (pos !== -1) {
var part1 = value.substr(0, pos);
var part2 = value.substr(pos + 1);
result = clean(part1) + "." + clean(part2);
} else {
result = clean(value);
}
console.log(result); // "10.100"

Categories

Resources