Auto populate Comma and Decimal in Text Box - javascript

I have a text box of dollar amount ( html below ). I am trying to add some css or jquery to auto populate comma and decimal when user enters value in the text box. For eg , if the user enters 123456789 , it should automatically become 12,345,667.89 .
<html:text styleId="incomePerPeriod" styleClass="textbox" property="employment.incomePerPeriod" maxlength="10" />
I added the below class to the html code above but it's not working. Can anyone please help me on how to achieve this ?
class="form-control text-right number"

It might be or might not be simpler by pure JS string functions but here is a regexp version.
The thing is, i couldn't find a way to group the entered number string into ??n nnn ... nnn nnn nn matches with regexp. However it relatively simple to get groups like nn nnn nnn ... nnn n??. This is the regex;
/(^\d{2})|(\d{1,3})(?=\d{1,3}|$)/g
So i reverse the string to start with as follows;
Array.prototype.reduce.call(str,(p,c) => c + p)
then applying the regex to my reversed string with .match(rex) would work like, "123456789" to yield [ '98', '765', '432', '1' ].
Then of course join them with . and , at proper positions with
.reduce((p,c,i) => i - 1 ? p + "," + c : p + "." + c)
and get 98.765,432,1. Well we just need to reverse this string again of course. So here is a working example.
function formatNumber(e){
var rex = /(^\d{2})|(\d{1,3})(?=\d{1,3}|$)/g,
val = this.value.replace(/^0+|\.|,/g,""),
res;
if (val.length) {
res = Array.prototype.reduce.call(val, (p,c) => c + p) // reverse the pure numbers string
.match(rex) // get groups in array
.reduce((p,c,i) => i - 1 ? p + "," + c : p + "." + c); // insert (.) and (,) accordingly
res += /\.|,/.test(res) ? "" : ".0"; // test if res has (.) or (,) in it
this.value = Array.prototype.reduce.call(res, (p,c) => c + p); // reverse the string and display
}
}
var ni = document.getElementById("numin");
ni.addEventListener("keyup", formatNumber);
<input id="numin" placeholder="enter number">
The res += /\.|,/.test(res) ? "" : ".0"; part takes care of prefixing a "0." when we only have the cents.

<input id="num" type="text" />
function addCommas(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
$('#num').keypress(function() {
var numberTyped = $("#num").val();
var convertedNum = addCommas(numberTyped);
$("#num").val(convertedNum);
});
The script uses a regular expression to add commas. Passing a number like 23456789.12345 produces 23,456,789.12345, which is the desired result.
Second Example
http://jsfiddle.net/ezbao2a3/15/

Here's a solution that formats the number onkeyup, in order to get the actual value of the input.
The keypress event checks for valid keys (e.g. only numbers and backspace). This could probably be perfected and moved to a js event listener.
The formatter regular expression can also be adjusted to handle decimals.
Here's a snippet. Hope it helps.
isNumberKey = function(evt) {
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode != 46 && charCode > 31
&& (charCode < 48 || charCode > 57))
return false;
return true;
}
var textInput = document.getElementById('txtChar');
textInput.addEventListener('keyup', function(evt){
var n = parseInt(this.value.replace(/\D/g,''),10);
textInput.value = n.toLocaleString();
}, false);
<input id="txtChar" onkeypress="return isNumberKey(event)" type="text" name="txtChar" />

I tried this solution and it worked. Import the below line in your script tag .
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.10/jquery.mask.js"></script>
Then on onLoad function , use the below lines:
$('#incomePerPeriod').mask("#,##0.00", {reverse: true});

Related

How to replace exact values for .replace script using regex?

I have here a javascript replace script that is activated via onclick of a button.
I'm using this to easily replace numbers based on a long list of numbers.
What I'm doing is:
I have this list (please know that this is a sample, there's about a thousand more)
.replaceAll("10,", "80,")
.replaceAll("1,", "75,")
.replaceAll("0,", "65,")
.replaceAll("83,", "50,")
If I enter 10 in textarea, and if I click the "Update button", it should become 80 and not 865 or 7565 since I need an exact value. Right now this is what it's doing, changing 10 to 80 and then the 0 in the 80 into 65.
I'm looking for a quick or clean way of doing this using RegEx, to maybe add to the script that I only want to change the specified numbers in the quote marks and not those with preceding or following numbers.
Here's my sample code:
function fixTextarea(textarea) {
textarea.value = textarea.value.replaceAll("3d ed", "4th ed")
.replaceAll("437,", "511,")
.replaceAll("438,", "512, 517,")
.replaceAll("21,", "24,")
.replaceAll("309,", "357,")
.replaceAll("425,", "491,")
.replaceAll("427,", "493,")
.replaceAll("430,", "496-502,")
.replaceAll("10,", "80,")
.replaceAll("1,", "75,")
.replaceAll("0,", "65,")
.replaceAll("83,", "50,")
};
function fixtext() {
let textarea = document.getElementById("textarea1");
textarea.select();
fixTextarea(textarea);
}
window.addEventListener('DOMContentLoaded', function(e) {
var area = document.getElementById("textarea1");
var getCount = function(str, search) {
return str.split(search).length - 1;
};
var replace = function(search, replaceWith) {
if (typeof(search) == "object") {
area.value = area.value.replace(search, replaceWith);
return;
}
if (area.value.indexOf(search) >= 0) {
var start = area.selectionStart;
var end = area.selectionEnd;
var textBefore = area.value.substr(0, end);
var lengthDiff = (replaceWith.length - search.length) * getCount(textBefore, search);
area.value = area.value.replace(search, replaceWith);
area.selectionStart = start + lengthDiff;
area.selectionEnd = end + lengthDiff;
}
};
});
<textarea id="textarea1" rows="4" cols="50">Witkin & Epstein, Criminal Law (3d ed), Pretrial Proceedings §§ 10, 438,</textarea>
<button class="nbtngreen" onclick="fixtext()">Update</button>
I've tried using something like .replaceAll("/^10,\z/", "80,") but it doesn't seem to work.
I'd appreciate any help. I'm stuck with this and I really cannot solve it on my own anymore.
One option could be to create a Map where you would specify what to replace.
Then you could use a pattern to match 1 or more digits, preceded by a word boundary \b to prevent a partial match and assert a comma directly to the right (?=,) using a positive lookahead.
In the callback of replace, check if the string exists in the Map. Return the mapped value if it does, else return the original match to leave it unchanged.
Press the button once to do all the replacements.
\b\d+(?=,)
Regex demo
For example:
const mapper = new Map();
mapper.set("10", "80");
mapper.set("437", "511");
mapper.set("80", "81");
function fixtext() {
const elm = document.getElementById("textarea1");
if (elm) {
elm.value = elm.value
.replace(
/\b\d+(?=,)/g,
m => mapper.has(m) ? mapper.get(m) : m
);
}
}
<textarea id="textarea1" rows="4" cols="50">Witkin & Epstein, Criminal Law (3d ed), Pretrial Proceedings §§ 10,438, this should not change 437 and this should: 437,9999</textarea>
<button class="nbtngreen" onclick="fixtext()">Update</button>

Dynamic Regex for Decimal Precision not Working

I have the following hard-coded RegEx expression for decimal precision & scale, which works (in another project):
// This would be a Decimal(2,3)
var regex = /\d{0,2}(\.\d{1,3})?$/;
var result = regex.test(text);
However, I don't want to hard-code multiple variations. And, interestingly, the following fails...but I don't know why.
I "think" the concatenation may (somehow) be effecting the "test"
What am I doing wrong here?
SAMPLE:
var validationRules = {
decimal: {
hasPrecision: function (precision, scale, text) {
var regex = new RegExp('\d{0,' + precision + '}(\.\d{1,' + scale + '})?$');
var result = regex.test(text);
// result is ALWAYS true ????
alert(result);
alert(regex);
}
}
};
FAILING SAMPLE-SNIPPET:
$(document).ready(function () {
var validationRules = {
decimal: {
hasPrecision: function (precision, scale, text) {
var regex = new RegExp('\d{0,' + precision + '}(\.\d{1,' + scale + '})?$');
var result = regex.test(text);
alert(result);
alert(regex);
}
}
};
var masks = {
decimal: function (e) {
// TODO: get Kendo MaskedTextBox to run RegEx
var regex = new RegExp("^([0-9\.])$");
var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
if (!regex.test(key)) {
event.preventDefault();
return false;
}
}
};
var button = $('.btn');
var textbox = $('.txt');
textbox.on('keypress', masks.decimal);
button.on('click', function () {
var text = textbox.val();
validationRules.decimal.hasPrecision(2, 3, text);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" value="1111" class="txt">
<input type="button" class="btn" value="Run it">
Always look at the result when building dynamic strings. In your case you're building it and just assuming it's turning into the REGEX pattern you want.
What you're actually building is, for example:
d{0,2}(.d{1,3})?$
Why? Because REGEX patterns built via the constructor (as opposed to literals) are built as strings - and in strings \ is interpreted as an escape character.
You, however, need these back slashes to persist into your pattern, so you need to double escape. In effect, you need to escape the escape so the final one is retained.
var regex = new RegExp('\\d{0,' + precision + '}(\\.\\d{1,' + scale + '})?$');
This will result in an equivalent of your hard-coded pattern assuming precision and scale contain the intergers you think they do. Check this too. (If they contain floats, for example, this will ruin your pattern.)
As for your false positives, this is probably down to a missing start-anchor instruction, i.e. ^.
/\d{0,2}(\.\d{1,3})?$/.test("1234"); //true
/^\d{0,2}(\.\d{1,3})?$/.test("1234"); //false, note ^
please try this I have implement on my project and it's working fine
const integer = Number(4)
const decimal=Number(2)
const reg = new RegExp(^[0-9]{0,${integer }}(\\.\\d[0-9]{0,${decimal- 1}})?$)
return value && !reg.test(value) ? Maximum length for integer is ${integer} and for decimal is ${decimal} : undefined;

Displaying a currency from a number

How can I change a number ( integer ) into a currency format while live input/typing?
ex :
45678 => 456.78
or
234567 => 2345.67 or 2,345.67 or 2 345.67
( depending on the mask format used )
Before people start tagging this question as an existing one, I have already seen the existing codes that format numbers, but those examples do not handle the last two numbers as decimals. Instead those format the string 45678 into 45 678.00 or 45,678.00 instead of 456.78.
Something like convert:
######## into ### ###.##
You could iterate the mask and reassemble the result string.
It creates from both values two arrays (with spread syntax ...) for a single number or mask character in an array.
Then it iterates the mask characters from the right side and
(m === '#' ? v.pop() || '' : v.length ? m : '') + s
builds a new string with either a numerical value, if # is found
m === '#' ? v.pop() || ''
or takes the value of the mask by checking the length of the values
v.length ? m : ''
to prevent adding spaces or unwanted characters.
function convert(i, mask) {
var v = [...i.toString()];
return [...mask].reduceRight((s, m) => (m === '#' ? v.pop() || '' : v.length ? m : '') + s, '');
}
console.log(convert(45678, '### ###.##')); // 456.78
console.log(convert(234567, '### ###.##')); // 2345.67
console.log(convert(234567, '###,###.##')); // 2,345.67
console.log(convert(234567, '### ###.##')); // 2 345.67
Add an event handler for when you type into the input to format the value for that input.
$('#myTextbox').keyup(function(){
$(this).val(($(this).val() /100).toFixed(2);
});
(number).toFixed() function converts a number to string. To avoid this try:
var x4 = 999546765687;
x4 = x4/100;
x4.toFixed(2);
Number(x4)
The toLocaleString() method returns a string with a language sensitive representation of this number.
var currency = 234567/100;
var currencyString = currency.toLocaleString('en-US')
console.log(currencyString);
For angular
https://angular.io/api/common/CurrencyPipe
Try using
#Component({
selector: 'currency-pipe',
template: `
A: {{a | currency}}
<!--output 'CA$0.26'-->
<p>A: {{a | currency:'CAD'}}</p>
<!--output 'CAD0.26'-->
<p>A: {{a | currency:'CAD':'code'}}</p>
<!--output 'CA$0,001.35'-->
<p>B: {{b | currency:'CAD':'symbol':'4.2-2'}}</p>
<!--output '$0,001.35'-->
<p>B: {{b | currency:'CAD':'symbol-narrow':'4.2-2'}}</p>
<!--output '0 001,35 CA$'-->
<p>B: {{b | currency:'CAD':'symbol':'4.2-2':'fr'}}</p>
</div>`
})
export class CurrencyPipeComponent {
a: number = 0.259;
b: number = 1.3495;
}

Regex to separate thousands with comma and keep two decimals

I recently came up with this code while answering another StackOverflow question. Basically, on blur, this code will properly comma separate by thousands and leave the decimal at two digits (like how USD is written [7,745.56]).
I was wondering if there is more concise way of using regex to , separate and cut off excessive decimal places. I recently updated this post with my most recent attempt. Is there a better way of doing this with regex?
Input -> Target Output
7456 -> 7,456
45345 -> 45,345
25.23523534 -> 25.23
3333.239 -> 3,333.23
234.99 -> 234.99
2300.99 -> 2,300.99
23123123123.22 -> 23,123,123,123.22
Current Regex
var result;
var str = []
reg = new RegExp(/(\d*(\d{2}\.)|\d{1,3})/, "gi");
reversed = "9515321312.2323432".split("").reverse().join("")
while (result = reg.exec(reversed)) {
str.push(result[2] ? result[2] : result[0])
}
console.log(str.join(",").split("").reverse().join("").replace(",.","."))
As an alternative to the Regex, you could use the following approach
Number(num.toFixed(2)).toLocaleString('en-US')
or
num.toLocaleString('en-US', {maximumFractionDigits: 2})
You would still have the toFixed(2), but it's quite clean. toFixed(2) though won't floor the number like you want. Same with {maximumFractionDigits: 2} as the second parameter to toLocaleString as well.
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums)
console.log(num, '->', Number(num.toFixed(2)).toLocaleString('en-US') )
Flooring the number like you showed is a bit tricky. Doing something like (num * 100 | 0) / 100 does not work. The calculation loses precision (e.g. .99 will become .98 in certain situations). (also |0 wouldn't work with larger numbers but even Math.floor() has the precision problem).
The solution would be to treat the numbers like strings.
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums) console.log(num, '->', format(num))
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
(when changing to another format than 'en-US' pay attention to the . in numbers as some languages use a , as fractal separator)
For Compatibility, according to CanIUse toLocaleString('en-US') is
supported in effectively all browsers (since IE6+, Firefox 2+, Chrome
1+ etc)
If you really insist on doing this purely in regex (and truncate instead of round the fractional digits), the only solution I can think of is to use a replacement function as the second argument to .replace():
('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
This makes all your test cases pass:
function format(num){
return ('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
}
test(7456, "7,456");
test(45345, "45,345");
test(25.23523534, "25.23"); //truncated, not rounded
test(3333.239, "3,333.23"); //truncated, not rounded
test(234.99, "234.99");
test(2300.99, "2,300.99");
test(23123123123.22, "23,123,123,123.22");
function test(num, expected){
var actual = format(num);
console.log(num + ' -> ' + expected + ' => ' + actual + ': ' +
(actual === expected ? 'passed' : 'failed')
);
}
I added another layer where regex that drops the unwanted decimals below hundredths on top of your regex comma adding logic;
val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,")
doIt("7456");
doIt("45345");
doIt("25.23523534");
doIt("3333.239");
doIt("234.99");
doIt("2300.99");
doIt("23123123123.22");
doIt("5812090285.2817481974897");
function doIt(val) {
console.log(val + " -> " + val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,"));
}
If multiple calls of regex replace is OK, this answer should satisfy you, since it is only has regex replace logic and nothing else.
Try:
var n = 5812090285.2817481974897;
n = n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
console.log(n);
Outputs:
5,812,090,285.28
Note: .toFixed(2) returns a string. So in order to simplify this further you must add a way to turn n into a string before executing your regex. For example:
n.toString.replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); //ofc with the additional regex
Although you would think it wouldn't matter in javascript, it apparently does in this situation. So I dont know how much 'less' messy it would be to not use.
Here is a way to do it without a regular expression:
value.toLocaleString("en-US", { maximumFractionDigits: 2 })
function formatValue() {
var source = document.getElementById("source");
var output = document.getElementById("output");
var value = parseFloat(source.value);
output.innerText = value.toLocaleString("en-US", { maximumFractionDigits: 2 });
}
<input id="source" type="text" />
<button onclick="formatValue()">Format</button>
<div id="output"></div>
RegEx to rescue again!
My solution has two parts :
.toFixed : Used to limit the decimal limit
/(\d)(?=(\d\d\d)+(?!\d))/g : It makes use of back reference with three digits at a time
Here's everything put together :
// .toFixed((/\./g.test(num)) ? 2 : 0) it tests if the input number has any decimal places, if so limits it to 2 digits and if not, get's rid of it altogether by setting it to 0
num.toFixed((/\./g.test(num)) ? 2 : 0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
You can see it in action here :
var input = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
input.forEach(function(num) {
$('div')
.append(
$('<p>').text(num + ' => ' +
num.toFixed( (/\./g.test(num))?2:0 ).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> </div>
NOTE: I've only used jQuery to append the results
You can do like this
(parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
Here just convert number to formatted number with rounded down to 2 decimal places and then remove the .00 if exist.
This can be one approach you can use.
var format = function (num) {
return (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
}
$(function () {
$("#principalAmtOut").blur(function (e) {
$(this).val(format($(this).val()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="principalAmtOut" type="text" />
You can use Intl.NumberFormat with style set to "decimal" and maximumFractionDigits set to 2 at options object passed at second parameter
const nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22];
const formatOptions = {style:"decimal", maximumFractionDigits:2};
const formatter = new Intl.NumberFormat("en-US", formatOptions);
const formatNums = num => formatter.format(num);
let formattedNums = nums.map(formatNums);
console.log(formattedNums);
I found a solution based on #Pierre's answer without using of toFixed:
function format(n) {
n = +n;
var d = Math.round(n * 100) % 100;
return (Math.floor(n) + '').replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (d > 9 ? '.' + d : d > 0 ? '.0' + d : '');
}
console.log(format(7456));
console.log(format(7456.0));
console.log(format(7456.1));
console.log(format(7456.01));
console.log(format(7456.001));
console.log(format(45345));
console.log(format(25.23523534));
console.log(format(3333.239));
console.log(format(234.99));
console.log(format(2300.99));
console.log(format(23123123123.22));
console.log(format('23123123123.22'));

Regex to replace non-numeric characters and insert dashes for phone number as it is typed

I need javascript to format a telephone number as it is typed. This would replace all non-numeric characters and insert dashes if the user doesn't type them in. So far this is the closest I've gotten, but it is thrown off if they put a dash in the wrong spot. The ideal solution would be to replace dashes only in the wrong spots. I was looking for a way to possibly replace the 4th and the 8th digit differently but haven't come up with a solution.
$('#TelephoneNo').keyup(function (ev) {
if (/[^0-9\-]/g.test(this.value))
{
this.value = this.value.replace(/[^0-9\-]/g, '');
}
if (/^(\d{3})(\d)/.test(this.value))
{
this.value = this.value.replace(/^(\d{3})(\d)/, '$1-$2');
}
if (/^(\d{3}-\d{3})(\d)/.test(this.value))
{
this.value = this.value.replace(/^(\d{3}-\d{3})(\d)/, '$1-$2');
}
});
Assuming you want the format "123-456-7890":
function formatPhoneNumber(s) {
var s2 = (""+s).replace(/\D/g, '');
var m = s2.match(/^(\d{3})(\d{3})(\d{4})$/);
return (!m) ? null : m[1] + " -" + m[2] + "-" + m[3];
}
<html>
<head>
<script type="text/javascript">
function CheckNum(ev) {
var inputval=document.getElementById("TelephoneNo").value;
debugger
if(inputval){
if (/[^0-9\-]/g.test(inputval))
{
inputval = inputval.replace(/[^0-9\-]/g, '');
}
if(detectPosition()){
if (/^(\d{3})(\d)/.test(inputval))
{
inputval = inputval.replace(/^(\d{3})(\d)/, '$1-$2');
}
if (/^(\d{3}-\d{3})(\d)/.test(inputval))
{
inputval = inputval.replace(/^(\d{3}-\d{3})(\d)/, '$1-$2');
}
}
document.getElementById("TelephoneNo").value=inputval;
}
}
function detectPosition() { var inputval=document.getElementById("TelephoneNo").value;
if(inputval.indexOf("-") ==4 || inputval.indexOf("-") ==8)
{
return 1;
}
return -1;
}
</script>
</head>
<body>
<input type="text" id="TelephoneNo" onkeyup="CheckNum(this)">
</body>
</html>
I know this is an old question, but I figured I might help someone out.
I did this xxx-xxx-xxxx as-you-type formatting using two cases: one for formatting where the length required one hyphen, and another for formatting with two required. That way, the last group always expects an unknown char count and doesn't wait until the end of the user input to enforce the format.
function formatPhone() {
var element = document.getElementById('phone');
var inputValue = element.value;
// length < 3 : no formatting necessary
if (inputValue.length > 3 && inputValue.length < 8)
// length < 8 : only one hyphen necessary, after first group of 3
// replace (remove) non-digits, then format groups 1 and 2
result = inputValue.replace(/\D/gi, '').replace(/(.{3})(.{0,3})/g, '$1-$2');
else
// length >= 8 : 2 hyphens required, after first two groups of 3
// replace (remove) non-digits, then format groups 1, 2, and 3
result = inputValue.replace(/\D/gi, '').replace(/(.{3})(.{3})(.{0,4})/g, '$1-$2-$3');
element.value = result;
}
Type a phone number, it will be formatted to xxx-xxx-xxxx as you type:<br/><br/>
<input type="text" id="phone" maxlength="12" onkeyup="formatPhone()"></input>

Categories

Resources