Jquery - Sum bug with various price formats - javascript

I have problems to calculate price with jquery in various price formats (depending on the language).
With German: 1.375,50 € (Returns 1.38 €)
English format: €1,375.50 (don't work)
French format: 1 375,50 € (Returns 1.00 €)
Italian format: €1,375.50 (don't work)
Spanish format: € 1.375,50 (don't work)
Here is a link of my working demo : http://jsfiddle.net/QmTNZ/63/
And here is my code :
function ca(){
var $overall = 0;
$("tr.sum").each(function() {
var $qnt = $(this).find(".qty");
var $price = $(this).find("td").eq(2);
console.log($qnt + " | " + $price);
var sum = parseFloat($price.text().replace(",", ".")) * parseFloat($qnt.val().replace(",", "."));
if(isNaN(sum)) {
sum = 0;
}
$(this).find("td").eq(3).text(Math.round(sum * 100) / 100);
$overall += sum;
});
$("#total").text($overall);
}
$(function() {
ca();
$('input.qty').bind('change keyup',function(){ca();});
});
The price "td" can contain other texts, for example "Incl. 19% tax".
My questions here is how can I use a css class that englobe only the price, without the Euro Symbol, to use it in calculation, and how can I avoid the problems of the dot and comma in price calculation in all price formats.
(I'm always beginner in jquery....)
Thanks for help !

Regardless of anything else, your code is going to have to know the formatting rules for the locale, otherwise you won't be able to correctly format your resulting sum.
However, you can avoid worrying about the locale differences in the main body of your code by separating out the price data from the price display. One way you can do that is with a data-* attribute on the element containing the price display.
For instance, let's suppose your row looks like this currently:
<tr><td>Widget</td><td>1</td><td>1 375,50 €</td></tr>
There, the 3rd cell contains the price as text with the various formats. Now, when outputting the table, if you include the price as a data-price attribute in a known, specific format, you avoid all this hassle:
<tr><td>Widget</td><td>1</td><td data-price="1375.5">1 375,50 €</td></tr>
You can then access it via attr("data-price"):
var thisPrice = parseFloat($(this).find("td:eq(2)").attr("data-price"));
This gets you the prices in a nice reliable way.
But again, in the end, you'll need to know the locale rules in order to display $overall in the correct format.

Related

NumeralJS No decimal formatting/rounding

I use NumeralJS for formatting amounts as below;
numeral(unformattedValue).format(amtFormat);
So if the amtFormat is set as "0,0.00", then if the amount is entered as "123.1", I get it as "123.10"
But what I want is no formatting/rounding, etc to take place after the decimal...
Thus, if the entered value is 1.999999, I want the output to be 1.999999 (No change after the decimal at all)
Is it possible to pass something to the format() to achieve this ? I could not find anything in the NumeralJS documentation.
Given your requirements of:
Formatting the thousands separator
Keeping the decimals "as-is"
One option you could try is below. There might be a simpler way to do this, perhaps by defining a custom format, but here's one thought:
// example input
let input = [1549.9988, 1549123.9912938, 123.456];
input.forEach(i => {
// count the number of decimals
let numberOfDecimals = i.toString().split(".")[1].length;
// construct a string representing the number of decimals to retain
let decFormat = "0".repeat(numberOfDecimals - 1);
// format the number using this string
let num = numeral(i).format("0,0[." + decFormat + "]");
console.log(num);
});
<script src="//cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>

Change last names into numbers, which relate and display images

Im new to JavaScript and don't have the knowledge to write this myself yet. Any help would be great.
I'm creating pseudorandom illustration generator, comprised of 3 images. They'd be chosen by their name and displayed. Live update would be the best.
I'd like to have the user enter their last name (into a field) which will be changed into an individual set of 3 numbers. From those numbers I'd like the images to be chosen, the 1st from the first etc. then display them vertically respectively.
Any input is welcome, I'm sure there's an easier way of doing it. Thanks for your time.
Edit:
I'd like to change the last name that the user enters into a 3 digit number(000-999), then display 3 images based of the numbers given. If the number made is 015, then the first image displayed would be 000.jpg, the second 010.jpg and the third would be 005.jpg. Id like the same result each time a name is entered and I'd like to update on real time if possible. I hope this helps clear things up, I'm still trying to figure out the best way. Thanks
You can use the ASCII table to get the number matching with a letter.
Then, you can iterate on every char of the last name and sum it.
At the end, you might want to use the % (modulo) of the sum to get a value lesser than 1.000.
A tested code would be:
var lastName = "Connor";
var sum = 0;
for(var i=0; i<lastName.length;i++)
{
sum += lastName[i].charCodeAt(0);
}
sum = (sum%1000);
In your case, the result would be: 623
Then, you might want to get the files: 600.jpg, 020.jpg and 003.jpg
var firstPic = (sum + "").split('')[0] + "00.jpg";
var secondPic = "0" + (sum + "").split('')[1] + "0.jpg";
var thirdPic = "00" + (sum + "").split('')[2] + ".jpg";

TableSorter doesn't recognize numbers

I have these two examples, which both use the same code but different sources of tablesorter. However one of them works as the other one doesn't.
$("table").tablesorter();
http://jsfiddle.net/lightheaded/x78cd/ (doesn't work)
http://jsfiddle.net/lightheaded/RYL54/ (works)
It should first sort by percent and then by users. However it doesn't recognize the second number to be a number. I have a similar situation on my site. What could be the issue? I'm using 2.14.4 min on my site as well.
Upgrade to a more recent version of table sorter. Recent version seems to parse out tokens from strings such as 99% coverage (12.08 million users) and 99% coverage (10.2 million users) and compare them one by one so strings that contain more than one number still sort out as expected (we have 10 compared with 12 in the above example).
OR: you can create a custom parser that normalizes the percentage and users; and use it:
$.tablesorter.addParser({
id: 'percentThenUsers',
is: function (s) {
return false;
},
format: function (s) {
// "99% coverage (12.08 million users)" gets converted to
// "1099 1012.08" which can then be sorted as text
var m = s.replace(/[^\d\.]/g, " ").replace(/ +/g, " ").split(" ");
return (+m[0] + 1000) + " " + (+m[1] + 1000);
},
type: 'text'
});
$(function () {
$("table").tablesorter({
debug: true,
headers: {
0: { sorter: 'percentThenUsers' }
}
});
});
Demo here
Tablesorter attempts to detect the content of table cells automatically. In this case it is finding text and not percentage or digit values.
The first demo is using the original tablesorter which doesn't use alphanumeric sorting, so it can only sort text blocks. Check out this updated demo where a row with this data is added:
<tr><td>10% coverage (1.0 million users)</td></tr>
The 10% is placed above 100% in ascending sorts - not what you would expect.
The second demo is using an updated version of tablesorter which does use alphanumeric sorting. It splits the text into blocks and is able to sort the content as you would expect. Here is an updated demo with the above row included.
If you "need" to use the original tablesorter, then use the parser provided by #SalmanA.

calculate carriage on javascript invoice

Given the following: How would I go about making a function to calculate carriage based on user input (which I have already created with the id "carriage")?
/* Description: Update price function
* #param: $itemRow - Row Object
**/
var updatePrice = function ($itemRow) {
// Calculate the price of the row. Remove and $ so the calculation doesn't break
var price = $itemRow.find('#itemPrice').val().replace(",", "") * $itemRow.find('#itemQty').val();
var carriage = $itemRow.find('#carriage').val();
price = roundNumber(price, 2);
isNaN(price) ? $itemRow.find('#itemLineTotal').val("N/A") : $itemRow.find('#itemLineTotal').val(price);
update_total();
};
var update_total = function () {
var total = 0;
$('input#itemLineTotal').each(function (i) {
price = $(this).val().replace(",", "");
if (!isNaN(price)) total += Number(price);
});
total = roundNumber(total, 2);
$('input#invGrandTotal').val('\u20AC' + total);
};
First, some improvements your code:
You seem to use the same ID for inputs in multiple HTML table rows. HTML allows you to use an ID only once per document. In your case you should use classes instead of IDs.
You remove commas in all numbers. It is not clear if this is correct or not. Do you use the comma as thousands separator (then it is okay) or as decimal separator (then it is not)? This depends on your local number format.
You don't need the (custom?) function roundNumber(), you can use Number.toFixed() e.g. 10.toFixed(2) returns 10.00
In your update_total() function you remove the commas again, but you never added them when writing to each row's itemLineTotal field.
I recommend you to use a consistent coding style, e.g. you sometimes use camel case function names (updatePrice()), sometimes an underscore (update_total()).
In your code example, it looks like there is one carriage input per row. As this is not very common on invoices, I assumed that this was a mistake and there is only one such input in the whole invoice.
To calculate the grand total you have to calculate the sum of all itemLineTotals and then add the value of carriage. You should do that in update_total(). I created a fiddle which shows a working example, hope that helps:
http://jsfiddle.net/pascalockert/8G7mp/
(Perhaps you have to adapt the decimal and thousands separators as mentioned above. See lines 10, 11, 21 and 25. Also, please mind JavaScript's restrictions on floating point numbers)

Excel to XML: Round decimals to the nearest hundredth and keep hyperlinks

I followed this guide to export an Excel Spreadsheet as an XML data file and then this guide to display the XML sheet as an HTML table on my website. It worked great. Now I "only" have to small issues remaining that I couldn't get solved.
(1) The output table contains numbers like 1.325667 but also lots of 0s. I would like the zeroes to be displayed as 0.00 and the numbers with many decimals to be displayed as 1.33. Basically, each number should be displayed with two decimals.
(2) The excel sheet contains hyperlinks to other pages on my website that I would like to keep when rendering the XML data file and then the HTML table. So far, that didn't work. Is this possible?
UPDATE I figured this part out. By breaking up the hyperlinks in just their character-strings, then adding new columns for these character strings, and then tweaking the source code to including
document.write("<tr><td><a href='");
document.write(x[i].getElementsByTagName("character-string")0].childNodes[0].nodeValue);
document.write(".php'>");
document.write(x[i].getElementsByTagName("name")[0].childNodes[0].nodeValue);
document.write("</a></td>");
I was able to include hyperlinks.
The Excel-Sheet is formatted with these two aspects already integrated, but the conversion to an XML file seems to be the problem.
Thank you so much for your help (again and again :-))
UPDATE I now also found a way to do the rounding in Excel, but I'm still stuck with integers and numbers with only one decimal. Basically, I now "only" need a way to show every number with two decimal points, applying to integers (e.g. 0 should 0.00) and numbers with one decimal (e.g. 1.5 should be 1.50). JohnnyReeves' answer seems to be on the right track but I couldn't get it to work. Any other ideas?
The Number Object has the method toFixed():
1.325667.toFixed(2) = 1.33.
Running inside the loop of the XML, select the URL and add it to the link:
document.write("< a href=" + x[i].getElementsByTagName(< your URL link>) + ">);
document.write("some text");
document.write("< /a>");
The Number.toFixed method will only work on floating point values (eg: 2.1), but not on integers (eg: 2, or 0). You will need to convert your number type to a string type so you can format it for display and get consistent results regardless of the input. A function like this should do the trick:
function formatNumber(value) {
var parts,
trailingDigits,
formattedRemainder;
// Coerce the supplied value to a String type.
value = String(value);
// Break the supplied number into two parts, before and after the dot
parts = value.split(".");
// If there was no dot, there will only be one "part" and we can just
// add the trailing zeros.
if (parts.length === 1) {
formattedRemainder = "00";
}
else {
trailingDigits = parts[1];
if (trailingDigits.length === 0) {
// A dot, but no digits. (eg: 2. -> 2.00)
formattedRemainder = "00";
}
else if (trailingDigits.length === 1) {
// Add an extra trailing zero (eg: 2.1 -> 2.10)
formattedRemainder = trailingDigits + "0";
}
else {
// Just take the last two trailing digits.
formattedRemainder = trailingDigits.substring(0, 2);
}
}
// Build the final formatted string for display.
return parts[0] + "." + formattedRemainder;
}

Categories

Resources