Displaying a currency from a number - javascript

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;
}

Related

How to prevent ✳ symbol converting to emoji

I have a problem where my ✳ (Eight-Spoked Asterisk) symbol is converting to emoji on iOS/android devices..
https://hotemoji.com/eight-spoked-asterisk-emoji.html#:~:text=%E2%9C%B3%EF%B8%8F%20Meaning%20%E2%80%93%20Eight%2DSpoked%20Asterisk,a%20list%20as%20bullet%20points.
Can somebody help me on what to do to prevent convertion of normal symbol ✳ to emoji asterisk! I am working with react/typescript.
Example:
I want 1234 ✳✳✳✳ ✳✳✳✳ 5678 - this is fine on desktop
I dont want 1234 1234 ✳️✳️✳️✳️ ✳️✳️✳️✳️ 5678 - this happens on ios/android
Thanks
EDIT - Function that does replacement:
export const hideDigits = (value: string) => {
const parsedValue = value.slice(0, 4) + value.slice(4, value.length -4).replace(/\d/g,'\u2733') + value.slice(value.length -4);
return (
normalizeVoucherCode(parsedValue)
);
};
Solved it like this for anyone who is wondering!
//Force ✳︎ to never be parsed as emoji with variation selector \u{FE0E}!
const textSymbol = '\u{2733}\u{FE0E}';

Explaining functions of Vigenère cipher

i found the following code at http://rosettacode.org for the Vigenère cipher and i would like to undestand it better.
Could someone explain me what the single lines of code in function ordA(a) and in function(a) do?
function ordA(a) {
return a.charCodeAt(0) - 65;
}
// vigenere
function vigenere2(text, key, decode) {
var i = 0, b;
key = key.toUpperCase().replace(/[^A-Z]/g, '');
return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, function(a) {
b = key[i++ % key.length];
return String.fromCharCode(((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65));
});
}
I'm not sure if that is supposed to be example code, but it mainly shows how not to program. Smart decisions are being made, but obviously the problem decomposition, variable naming and documentation leave a lot to be desired. Repeated code, convoluted lines, unexplained code fragments, the list goes on. Decode is a boolean, but the opposite of encryption is decryption not decoding. This code was made to not understand what is going on; what it does on the Rosetta site is mind-boggling in that respect.
returns an index in the English alphabet or ABC, assuming uppercase characters, 0 to 25 instead of 1 to 26 (because you can do modular calculations with zero indexing, not with one based indexing)
return a.charCodeAt(0) - 65;
function definition that takes a plaintext or ciphertext, a key which may be smaller than the plaintext and a Boolean to indicate if we're encoding or decoding
function vigenere2(text, key, decode)
index in plaintext and variable b, which will hold a character of the key for the index
var i = 0, b;
converts the key to uppercase and removed all characters not in the uppercase alphabet as well
key = key.toUpperCase().replace(/[^A-Z]/g, '');
this line is too long obviously; it converts the text to uppercase and removes the non-alphabet characters again
then it replaces the characters in the string using the function defined in the second argument of replace
return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, function(a) {
take the next character of the key in round robin fashion, using the modulus operator, update the index afterwards
b = key[i++ % key.length];
too much going on here, very bad program decomposition; in order of execution:
(decode ? 26 - ordA(b) : ordA(b)): calculate a number in the range to update the index of the plaintext character; use the opposite value for decryption (wrongly called "decoding" here)
(ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 perform the addition with the calculated number, reduce to 0 to 25 (i.e. when reaching Z continue with A and vice versa)
((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65) add 65 so the index is converted back into the ASCII index of uppercase characters, using two completely spurious parentheses
finally, returns a string from one character code result, otherwise + will be addition instead of concatenation
return String.fromCharCode(((ordA(a) + (decode ? 26 - ordA(b) : ordA(b))) % 26 + 65));
well, it needed to end
});
}
Let's show another way of programming this, using well named variables, functions for reused code and regular expressions that badly need a name to explain what they do.
var ALPHABET_SIZE = 'Z'.charCodeAt(0) - 'A'.charCodeAt(0) + 1;
var encrypted = vigenere(false, "B", "Zaphod Breeblebox");
document.body.append('<div>' + encrypted + '</div>');
var decrypted = vigenere(true, "B", encrypted);
document.body.append('<div>' + decrypted + '</div>');
function vigenere(decrypt, key, text) {
key = toJustUppercase(key);
text = toJustUppercase(text);
var textOffset = 0;
// iterate over all characters, performing the function on each of them
return text.replace(/[A-Z]/g, function(textChar) {
var keyChar = key[textOffset++ % key.length];
var cryptedChar = substituteCharacter(decrypt, keyChar, textChar);
return cryptedChar;
});
}
function substituteCharacter(decrypt, keyChar, textChar) {
var keyIndex = charToABCIndex(keyChar);
if (decrypt) {
// create the opposite of the encryption key index
keyIndex = ALPHABET_SIZE - keyIndex;
}
var textIndex = charToABCIndex(textChar);
// the actual Vigenere substitution, the rest is just indexing and conversion
var substitutedIndex = (textIndex + keyIndex) % ALPHABET_SIZE;
var substitutedChar = abcIndexToChar(substitutedIndex);
return substitutedChar;
}
function toJustUppercase(text) {
return text.toUpperCase().replace(/[^A-Z]/g, '')
}
function charToABCIndex(charValue) {
return charValue.charCodeAt(0) - 'A'.charCodeAt(0);
}
function abcIndexToChar(index) {
return String.fromCharCode(index + 'A'.charCodeAt(0));
}
Too many functions you say? Not really, I've not implemented ord and chr, or vigenereEncrypt and viginereDecrypt to make it even easier to read.

Auto populate Comma and Decimal in Text Box

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});

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'));

Angularjs Template Default Value if Binding Null / Undefined (With Filter)

I have a template binding that displays a model attribute called 'date' which is a date, using Angular's date filter.
<span class="gallery-date">{{gallery.date | date:'mediumDate'}}</span>
So far so good. However at the moment, if there is no value in the date field, the binding displays nothing. However, I would like it to display the string 'Various' if there is no date.
I can get the basic logic using a binary operator:
<span class="gallery-date">{{gallery.date || 'Various'}}</span>
However I can't get it to work with the date filter:
<span class="gallery-date">{{gallery.date | date:'mediumDate' || "Various"}}</span>
How can I use the binary operator alongside the date filter?
Turns out all I needed to do was wrap the left-hand side of the expression in soft brackets:
<span class="gallery-date">{{(gallery.date | date:'mediumDate') || "Various"}}</span>
I made the following filter:
angular.module('app').filter('ifEmpty', function() {
return function(input, defaultValue) {
if (angular.isUndefined(input) || input === null || input === '') {
return defaultValue;
}
return input;
}
});
To be used like this:
<span>{{aPrice | currency | ifEmpty:'N/A'}}</span>
<span>{{aNum | number:3 | ifEmpty:0}}</span>
Just in case you want to try something else. This is what worked for me:
Based on Ternary Operator which has following structure:
condition ? value-if-true : value-if-false
As result:
{{gallery.date?(gallery.date | date:'mediumDate'):"Various" }}
How can I use the binary operator alongside the date filter?
<span class="gallery-date">{{gallery.date | date:'mediumDate' || "Date Empty"}}</span>
you also try:
<span class="gallery-date">{{ gallery.date == 'NULL' ? 'mediumDate' : "gallery.date"}}</span>
I really liked this answer, with ngBind, your default text can just live in the element body, and then if the ngBind evaluates to something non-null/undefined, your content is replaced automatically, and everythings happy
angularjs setting default values to display before evaluation
In your cshtml,
<tr ng-repeat="value in Results">
<td>{{value.FileReceivedOn | mydate | date : 'dd-MM-yyyy'}} </td>
</tr>
In Your JS File, maybe app.js,
Outside of app.controller, add the below filter.
Here the "mydate" is the function which you are calling for parsing the date.
Here the "app" is the variable which contains the angular.module
app.filter("mydate", function () {
var re = /\/Date\(([0-9]*)\)\//;
return function (x) {
var m = x.match(re);
if (m) return new Date(parseInt(m[1]));
else return null;
};
});

Categories

Resources