trim trailing zeros not quite working - javascript

I have a number of prices on a page that arein 4 decimal places. Some products are priced in 4 decimal places, but some are only in 2.
At the moment our website is set to display in 4 decimal places for every product and I have to use javascript to trim down the prices on those products that aren't 2 decimal places.
So I have prices like so...
£0.1234
£1.1000
£10.9900
£100.0000
I have the following javascript which works fine for prices that have a number greater than 1 after the decimal point, but it fails on prices where there are just 0's after the decimal point...
$.each($("#mydiv"),function(){
var price = $(this).text().replace("£","");
var number = parseFloat(price);
var integerPart = number.toString().split(".")[0] == 0 ? 0: number.toString().split(".")[0].length;
var decimalPart = number.toString().split(".")[1].length;
if(decimalPart > 2){
$(this).text("£" + number.toPrecision(integerPart + decimalPart));
}else{
$(this).text("£" + number.toPrecision(integerPart + 2));
}
});
The ones it fails on are prices like £100.0000 - I would like the prices to appear as follows - no rounding...
£0.1234
£1.10
£10.99
£100.00

Just use a regexp to remove any trailing zeroes if the preceeding characters are the decimal period followed by another two digits:
$('.myClass').text(function(_, t) {
return t.replace(/(\.\d\d)00$/, '$1');
});
NB: you can't use duplicate element ID's, so your $.each call should be moot. If there really are multiple fields that this needs doing to, mark them with a class, not an ID. The .text call in the code above will automatically cope with multiple elements.
EDIT if you really can't upgrade your jQuery:
$('.myClass').each(function() {
var $this = $(this);
var text = $this.text();
text = text.replace(/(\.\d\d)00$/, '$1');
$this.text(text);
});

Additional to Alnitak's answer, I would highly recommend to store the prices of your store's items as integers (or maybe in your case longs), so you don't have to worry about imprecisions of double or float.
Because you have 4 decimal places the integers (or longs) can not represent pence, but 1/100 pence.
Example:
Price on website | price in database
-------------------------------------------
£0.1234 | 1234
£1.10 | 11000
£10.99 | 109900
£100.00 | 1000000

Related

Checking if a value has more than 3 decimal places in AngularJS

As the title states I am trying to check if a value had greater than 3 decimal places. This is the first time that I have had to deal with angularjs and I am not certain how to check that. I have check if value is whole number, greater than 0, etc.. But I am uncertain on the decimal places. Here is a snippet of my whole number check. Any suggestions on how I could do the check for the decimals would be greatly appreciated. I am trying to show a error message if the user goes over 3 decimals places.
Whole number example:
(mySubmittedOrder && myQuantity % 1 ===0)
var num1 = 1.123;
function decimalCount(num){
var numStr = String(num);
// String Contains Decimal
if (numStr.includes('.')) {
return numStr.split('.')[1].length;
};
// String Does Not Contain Decimal
return 0;
}
var decimalNumber = decimalCount(num1);
if(decimalNumber == 3){
console.log("3 decimals");
}else{
console.log("Not 3 decimals");
}
jQuery :
$filter('number')(number, fractionSize)
or
Angular:
<span id='number-default'>{{val | number}}</span><br>

Format number to last two decimals

I am trying to format numbers in JS to last two decimal.
For example 10100 becomes 101.00 - 606000 becomes 6,060.00 - 7600 becomes 76.00 and so on.
I have tried num.toFixed(2) but that was not of help. I also tried Number(10100).toLocaleString("es-ES", {minimumFractionDigits: 0}) but I end up with 10.100 so it seems off by one decimal.
So
num.toFixed(2)
What its doing its formatting,
Which would be 10.123 -> 10.12
what you should do is divide number by 100.
var number = 10100
number = number / 100
would be what you need.
I will approach this problem by using the help of strings.
Strings can be easily manipulated based on our requirements and then can be converted back to numbers. So, the solution goes like this
Convert the number to string
Manipulate the string to add a decimal before last two character
Convert the string back to number
const formatNumberToLastTwoDecimal = (number) => {
// Convert the number to String
const inputNumAsStr = number.toString();
// Manipulate the string and add decimal before two char
const updatedStr = `${inputNumAsStr.slice(0, -2)}.${inputNumAsStr.slice(-2)}`;
// Return by converting the string to number again
// Fix by 2 to stop parseFloat() from stripping zeroes to right of decimal
return new Number(parseFloat(updatedStr)).toFixed(2);
}
console.log(formatNumberToLastTwoDecimal(606000));
The most simplified way:
output = (number/100).toFixed(2)
And the complex way:
var c = 7383884
a = c.toString()
var output = parseFloat([a.slice(0, -2), ".",a.slice(-2)].join(''))
document.write(output)

Format a number to replace a decimal with space

I have a field on a form in Adobe that automatically sums the values from six other fields. The sum results in a decimal "." being placed so there are always 2 digits following.
The values in each of the six fields are typed in using a space to act as decimal place, as in "14 50" = $14.50 (see image).
The resulting sum is correct, but I'd like to add custom formatting that will replace the "." with a space, so that the sum in my example would read "87 00" rather than "87.00"
The javascript must be code that will work in the Adobe Pro custom format option for the field.
var num = 87.27;
var formatted;
if (num % 1 === 0) {
formatted = num.toString() +' 00';
} else {
formatted = num.toString().replace('.', ' ');
}

Aligning Decimal Values with Blank Space String?

I am having trouble adding blank spaces to align the decimals. I understand the logic but I can't put it into code.
for(var j in totals_array)
{
var amount = format_numeric_with_commas(totals_array[j].amount);
var currency = totals_array[j].currency;
if(j < 1)
{
costs_total.push(currency + " " + amount + "\x0A");
}
else
costs_total.push(currency + Array(0).join(" ") + amount + "\x0A");
}
totals_array holds a number of objects which looks like this.
{"currency":"AUD","amount":210543}
format_numeric_with_commas gives me the amount value in the appropriate format which is stored into the variable amount. While currency takes the currency of the value, i.e. GBP, USD, etc. What the if statement is for checks if it's the first index in the array. As I already sort the values with the highest at the top. So what I want is for the other values to align with the top number's decimal.
I take the currency type and value and push into a new array called costs_total. This is what it currently looks like.
Current layout:
How would I go about doing a loop to check how many spaces are needed for different lengths of currency values?
Why not do something like this instead? (some examples with actual text / numbers)
costs_total.push(String.Format("{0} {1,12:N}\x0A", "USD", 123456.0));
// "USD 123,456.00\n"
costs_total.push(String.Format("{0} {1,12:N}\x0A", "AUD", 123.0));
// "AUD 123.00\n"
costs_total.push(String.Format("{0} {1,12:N}\x0A", currency, amount));
You'd just need to find the number of digits in the largest number and set the width (12 in this case) appropriately.

How do I use regex to pick the following price values?

I have a scenario where I am trying to pick the price values in Rs from strings in Javascript as follows
The price was Rs.1000
The price was Rs 1000
The price was Rs.1000 - 5000
The price was Rs.1000 - Rs.5000
The price was Rs.50,000
The price was Rs 1,25,000 - Rs 2,45,000
Now obviously, given the input with so much variety in it, its not a good idea to make a single very long cumbersome regex expression.
Currently I have divided this task into 4 parts
Part 1
// Extracts all Rs.1000 or Rs 1000
var regex = new RegExp(/\brs\W*?(\d{1,7})\b(?![,\d])/i)
Part 2
//Extracts all Rs.1000 - 2000 or Rs 1000 - Rs 2000 and any combinations of this
regex = new RegExp(/\brs\W*?(\d{1,7})\b(?![,\d])\s*?(?:-|to)\s*?(?:\brs\b\W*?)?(\d{1,7})\b(?![,\d])/i)
I need to capture the currency values like 1000 and 2000 to store and process it.
A few questions right off the bat, my array in JS has around 3000 items. I am stuck on Part 3 and 4 that involves commas. Is this the right way to go about it.
How do I get the values in 1 stroke where commas are present
This Regex seems to capture both normal numbers and numbers with commas, and since I just want numeric values rather than have anything to do with where the commas are placed,
\brs\W*?\d.,?.\d\b
I am trying to work one step forward on this expression to include 1000 - 2000 types as well. Any ideas?
You can use a regex for this task - you have a regular pattern used to find repeated patterns in a plain text, just create the pattern dynamically. There are 2 main blocks, one that will match the prices glued to other words (so that we could skip that text) and the other will capture the prices only in valid contexts.
The whole regex looks ugly and long:
/\Brs\W*(?:\d{1,7}(?:,\d+)*)\b(?:\s*(?:-|to)\s*(?:\brs\b\W*?)?(?:\d{1,7}(?:,\d+)*)\b)?|\brs\W*(\d{1,7}(?:,\d+)*)\b(?:\s*(?:-|to)\s*(?:\brs\b\W*?)?(\d{1,7}(?:,\d+)*)\b)?/gi
However, it is clear it consists of simple and easily editable building blocks:
(\\d{1,7}(?:,\\d+)*)\\b - the number part
rs\\W*${num}(?:\\s*(?:-|to)\\s*(?:\\brs\\b\\W*?)?${num})? - the price part
NOTE that the capturing groups are made non-capturing with .replace(/\((?!\?:)/g, '(?:') further in the RegExp constructor.
See the JS demo:
const num = "(\\d{1,7}(?:,\\d+)*)\\b";
const block = `rs\\W*${num}(?:\\s*(?:-|to)\\s*(?:\\brs\\b\\W*?)?${num})?`;
const regex = RegExp(`\\B${block.replace(/\((?!\?:)/g, '(?:')}|\\b${block}`, 'ig');
const str = `The price was Rs.1000
The price was Rs 1000
The price was Rs.1000 - 5000
The price was Rs.1000 - Rs.5000
The price was Rs.50,000
The price was Rs 1,25,000 - Rs 2,45,000
The price was dummytestRs 1,2665,000 - Rs 2,45,000`;
let m;
let result = [];
while ((m = regex.exec(str)) !== null) {
if (m[2]) {
result.push([m[1].replace(/,/g, ''), m[2]]);
} else if (m[1]) {
result.push([m[1].replace(/,/g, ''), ""]);
}
}
document.body.innerHTML = "<pre>" + JSON.stringify(result, 0, 4) + "</pre>";

Categories