How to validate currency value by Locale? - javascript

We have a big web application, that has portals in different countries.
In these countries the money value is inserted differently.
Exists a solution which can validate the money value by locale?

i would recommend the http://openexchangerates.github.io/money.js/ this would provide you the live currency conversion rates.
for the formatting purpose look into AccountingJs https://josscrowcroft.github.io/accounting.js/

you can provide a dropdown next to the currency text box. so user can select the approperiate currency and can fill the value.
and in backend you need to get both value. entered value by user and the currecy selected.
based on location, you can change the selected currency by default.

"We have a big web application, that has portals in different countries"
I highly recommend setting up localization with Globalize. After setting it up correctly, all you have to do is change the locale of the user and all the locale dependent formatting (e.g currency, date, number, units, etc.) fixes itself.
If you want to use it just for currency, see their currency module: Globalize Currency Module

I've implemented it now via an own function:
/*
* checks if a given money value is a correct one via locale language
* */
function isMoney(moneyValue) {
var currentSelectedLanguage = $('#currentSelectedLanguage').val();
switch (currentSelectedLanguage)
{
// checks for , as separator and . as decimal separator e.g.: 1,234,567,890.98 - also allows without , as separator e.g.: 1234567890.98
case "en":
return /(?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)?(\.[0-9]{1,2})?$/.test(moneyValue);
break;
// checks for . as separator and , as decimal separator e.g.: 1.234.567.890,98 - also allows without . as separator e.g.: 1234567890,98
case "de":
case "el":
case "es":
case "hr":
case "ro":
case "sl":
case "sr":
return /(?=.)^\$?(([1-9][0-9]{0,2}(\.[0-9]{3})*)|[0-9]+)?(,[0-9]{1,2})?$/.test(moneyValue);
break;
// checks for space as separator and , as decimal separator e.g.: 1 234 567 890,98, also allows without space as separator e.g.: 1234567890,98
case "bg":
case "cs":
case "hu":
case "pl":
case "ru":
case "sk":
case "uk":
return /(?=.)^\$?(([1-9][0-9]{0,2}( [0-9]{3})*)|[0-9]+)?(,[0-9]{1,2})?$/.test(moneyValue);
break;
// checks for . as separator and , as decimal separator e.g.: 1.234.567.890,98 - also allows without . as separator e.g.: 1234567890,98
default:
return /(?=.)^\$?(([1-9][0-9]{0,2}(\.[0-9]{3})*)|[0-9]+)?(,[0-9]{1,2})?$/.test(moneyValue);
}
}
Only downside is, that I've to extend it on my own if there is a new locale in our application

Related

use a custom number format for money in HTML

i have an interactive report in my apex page with numbers (money) in it, the default money format is U.S which is like this :
###,###,###,###.##
what i need is this :
### ### ### ###,##
is there a way to do so in HTML or in CSS or JAVASCRIPT
The display format in an apex report is determined by 2 parameters:
Appearance > Format Mask of the column in your interactive report
Decimal and Group separator set in the database session.
Decimal and group separator
In oracle this is determined at session level. You want , as decimal and space as group separator. To change this for your database session run the following statement.
ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ', ';
To change this for your entire application, set the following in Shared Components > Security > Database Session > Initialization PL/SQL Code
EXECUTE IMMEDIATE q'!ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ', '!';
To just set this for the page you have your report on you can either use an application process (with condition Current Page is contained within expression) = "your page" or a before header process to execute the EXECUTE IMMEDIATE statement above
Format Mask
The Number Format Models documentation might give you some clues here: 9is a NUMBER, D is the decimal separator, G is the group separator. So you're looking for 999G999G999G999D99
SELECT TO_CHAR(9866166747393/100,'999G999G999G999D99') from dual;
98 661 667 473,93
Set this as Appearance > Format Mask of the column in your interactive report.
How about
Intl.NumberFormat
or
toLocaleString
const number = 10000.50
console.log(new Intl.NumberFormat('fr-FR',{minimumFractionDigits:2}).format(number))
console.log(number.toLocaleString('fr-Fr', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 2
}));

javascript toLocaleString returns 0

I find toLocaleString function very odd.
the following line will return 0.003:
alert(0.0031.toLocaleString(2))
this line will return 0:
alert(0.00031.toLocaleString(2))
why?
This is not a valid parameters to the method toLocaleString.
You can use minimumFractionDigits param like this:
var res = 0.00031.toLocaleString(undefined, {minimumFractionDigits: 4});
console.log(res);
The toLocaleString() method returns a string with a language sensitive representation of this number.
numObj.toLocaleString([locales [, options]]) has two parameters.
Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
var num = 0.00031;
console.log(num.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}));
console.log(num.toLocaleString(undefined, { maximumFractionDigits: 4}));
toLocaleString truncates and rounds the decimal number to 3 digits after the decimal.
0.0005.toLocaleString()
for example will return 0.001.
The 2 in that you pass in as a method param doesn't do anything.
2 is not a valid argument for toLocaleString method of a Number. You may only pass a locale, which is a string, and and an object of options.
Options object can be used, among other things, to specify number of fraction digits:
number.toLocaleString(undefined, { maximumFractionDigits: 4 })
And the default value for it happens to be 3:
maximumFractionDigits
The maximum number of fraction digits to use.
Possible values are from 0 to 20; the default for plain number
formatting is the larger of minimumFractionDigits and 3; the default
for currency formatting is the larger of minimumFractionDigits and the
number of minor unit digits provided by the ISO 4217 currency code
list (2 if the list doesn't provide that information); the default for
percent formatting is the larger of minimumFractionDigits and 0.
The number 2 in the argument is not making any difference. toLocaleString returns a string with a language sensitive representation of the number.
In the second case of your problem it is basically 0.000 which is equal to 0
console.log("Passing argument " + 0.0031.toLocaleString(2))
console.log("Without argument " + 0.0031.toLocaleString())
console.log("Zeros " + 0.000)
number.toLocaleString() returns language sensitive representation of the number. Here in your case you are first not passing any locale information, and you are not telling this function that what is your max fraction limit.
See this example
0.0003.toLocaleString(undefined, {minimumFractionDigits: 2})
"0.00"
0.0003.toLocaleString(undefined, {minimumFractionDigits: 3})
"0.000"
0.0003.toLocaleString(undefined, {minimumFractionDigits: 4})
"0.0003
As per spec, first two arguments to toLocaleString is locale and options
When the toLocaleString method is called with optional arguments
locales and options, the following steps are taken:
When this API receive value 2 or 3, it first try to resolve locales and if not found the check within the supported locales.
The resolved locale is used as an effective locale to format the number as per the locale as per Common Locale Data Repository.
NOTE It is recommended that implementations use the locale data
provided by the Common Locale Data Repository (available at
http://cldr.unicode.org/).
As per documentation
The locales argument must be either a string holding a BCP 47 language
tag, or an array of such language tags. If the locales argument is not
provided or is undefined, the runtime's default locale is used.
A BCP 47 language tag defines a language and minimally contains a
primary language code. In its most common form it can contain, in
order: a language code, a script code, and a country or region code,
all separated by hyphens. While the tag is not case sensitive, it is
recommended to use title case for script code, upper case for country
and region codes and lower case for everything else.
Finally, lookup is performed to find the best fit from the supported locales as per BCP47 logic as per locales registered in IANA language subtag registry as per various attributes of a language mentioned.
2 doesn't matches any of the supported locales so, default maximum fraction digits as per your system environment is used from available value (appears to be 3 in your case.)
Hence you get
0.00031.toLocaleString(2) //"0"
0.0031.toLocaleString(2) //"0.003"

CRM 2011 Contact Address Set up for Both Domestic and Internationl

Great community here!
I am currently working within a 2011 CRM system that has a new requirement of the end users updating Contact Addresses from domestic (US) addressing to International. The system was originally set up for just Domestic addresses.
My problems are with the Telephone field and zip code. Both have custom javascript to format the integers in the field and ensure length compliance.
Now, is it possible to manipulate the JavaScript below to handle the both domestic and international phone numbers?
Below is the function that is called on an onchange event:
function checkPhoneNumberFormat(obj) {
var phoneNumber = obj.getEventSource().getValue();
if (phoneNumber != null) {
var sTmp = phoneNumber.replace(/[^0-9]/g, "");
switch (sTmp.length) {
case 10:
obj.getEventSource().setValue("(" + sTmp.substr(0, 3) + ") " + sTmp.substr(3, 3) + "-" + sTmp.substr(6, 4));
break;
default:
alert("Phone must contain 10 numbers.");
break;
}
}
}
Somewhat new to java scripting, just looking for some feed back, on how to manipulate this code. It would be great if it had the ability to auto format 9 digit as well as 14 digit phone numbers. And only allow numbers of those lengths to be passed through on the save.
Any comments or ideas are greatly appreciated.
Thank You!
Yes Pawel, this is pretty simple to do:
put another case statement like this (this means do nothing, but don't throw that alert up when the length is 14, since you don't want to do any special formatting)
case 14:
break;
Then in your onsave - you can do the same thing but block saving in the "Default" case.
default:
alert("Phone number must contain 10 or 14 digits");
executionObj.getEventArgs().preventDefault();
break;
One thing to note about phone numbers is that often there can be extensions, this doesn't seem to be handled by your code, but maybe that is not relevant to your application.

jQuery Globalization. Pass currency unit as argument for C format

I am setting up a multilingual site that deals with currencies. I want to be able to display correct currency formats based on the selected language. The server side PHP stuff is a doddle. Using a combination of PHPs NumberFormatter and strftime I have been able to format currencies and dates correctly.
There is however a requirement to have the same degree of formatting done client side with javascript.
I have come across Globalization (former jQuery plugin) and it looks quite promising.
If I want to display a dollar value in American English I can do something like this:
jQuery.preferCulture("en-US");
// Formatting price
var price = jQuery.format(3899.888, "c");
//Assigning stock price to the control
jQuery("#price").html(price);
and this will output:
$3,899.89
While doing:
jQuery.preferCulture("fr-FR");
// Formatting price
var price = jQuery.format(3899.888, "c");
//Assigning stock price to the control
jQuery("#price").html(price);
outputs:
3 899,89 €
which looks perfect. however, I have a need to output multiple currencies. So, if I have 'fr-FR' selected as my preferred culture, how can I output, say, a dollar value like so:
3 899,89 $
so that the format is French, but the value is American Dollar. I have looked but not found anyway to pass a currency symbol as an argument.
The only documented way to modify the currency symbol in Globalize is to change the numberFormat.currency.symbol property of a given culture—in this case, the fr-FR culture. This will kind of do what you want, but it’s not a very elegant solution, and you would need to manually build a table of correct symbols for each locale and write another method to swap them out. (n.b. It is possible to pass a third argument to Globalize.format with a different locale identifier, but this just formats the number using that locale’s cultural settings.) Looking at the culture definition syntax, there is simply no provision for displaying different currencies using a given locale.
If you were to look elsewhere, the dojo/currency module in the Dojo Toolkit does do exactly what you need, using data from the Unicode Common Locale Data Repository to determine how to represent various currencies in different locales. So you can set your locale to fr, write currency.format(3899.888, { currency: "USD" }), and it will output the currency in USD in the correct format for the French locale.
I had the same problem, in the end I just replaced the default currency symbol on the output with the symbol I wanted to display. It's a bit primitive but it keeps the formatting correct for the locale with the currency symbol you want.
function formatCurrency(value, format, symbol){
var formattedValue = Globalize.format(value, format);
if (typeof symbol === "string") {
formattedValue = formattedValue.replace(Globalize.culture().numberFormat.currency.symbol, symbol);
}
return formattedValue;
}
document.getElementById("price1").innerHTML = formatCurrency(123.34,"c"); //<-- $123.34
document.getElementById("price2").innerHTML = formatCurrency(123.34,"c","£"); //<-- £123.34
Here is the fiddle

Encoding strings to small sizes for QRCode generation

I'm generating QR codes using strings that could very easily be longer in length then a QRCode could handle. I'm looking for suggestions on algorithms to encode these strings as small as possible, or a proof that the string cannot be shrunk any further.
Since I'm encoding a series of items, I can represent them using ID's and delineate them using pipes as in the following lookup table:
function encodeLookUp(character){
switch(character){
case '0': return '0000';
case '1': return '0001';
case '2': return '0010';
case '3': return '0011';
case '4': return '0100';
case '5': return '0101';
case '6': return '0110';
case '7': return '0111';
case '8': return '1000';
case '9': return '1001';
case '|': return '1010';
case ':': return '1011';
}
return false;
}
Using this table I am already doing a base 16 encoding, therefore each 32 ascii character from the original string becomes half a character in the new string (effectively halving the length).
Starting String: 01251548|4654654:4465464 // ID1 | ID2 : ID3 demonstrates both pipes.
Bit String: 000000010010010100010101010010001010010001100101010001100101010010110100010001100101010001100100
Result String: %H¤eFT´FTd // Half the length of the starting string.
Then this new ascii code, is translated according to QRCode specification.
EDIT: The most amount of characters currently encodable: 384
CLARIFICATION: Both ID numberic length, and the quantity of ID's or pipes is variable with a tendancy towards one. I am looking to be able to reduce this algorithm to contain on average the least amount of characters by the time its a 'result string'.
NOTE: The result string is only an ascii represenetaion of the binary string i've encoded with the data to conform with standard QRCode specifications and readers.
If you have relatively non-random data, a Huffman encoding might be a good solution.
Using the function, you're going to loose a lot of space (since 4 bits are way too much storage for 12 combinations).
I'd start by looking at the maximum length possible for your IDs and find a suitable storage block.
If you are storing these items serially in a fixed count (say, 4 ids). You would need id_length*id_count at most, and you won't need to use any separators.
Edit: Again according to the number of IDs you want to write and their expected maximum length, there may be different types of encodings to compress it done. RLE (run length encoding) came to my mind.
QR codes support a binary mode, and that's going to be the most efficient way for you to store your IDs. Either:
Pick a length (in bytes) that is sufficient to store all your IDs, and encode the QR-code as a series of fixed-length integers. 4 bytes (32 bits) is a standard choice that ought to cover the likely range, or
If you want to be able to encode a wide range of IDs, but expect most of the values to be small, use a variable-length encoding scheme. One example is to use the lowest 7 bits of each byte to store the integer, and the most significant bit to indicate if there are any further bytes.
Also note that QR codes can be a lot larger than 384 characters!
Edit: From your original question, though, it looks like you're encoding more than just a series of integers - you have at least two different types of delimiters. Where can they appear and in what circumstances? The encoding format is going to depend on those parameters.
QR codes already have special encoding modes that are optimized for digits, or just alphanumeric data. It would probably be easier to take advantage of these rather than invent a scheme.
If you're going to do something custom, I think you'll find it hard to beat something like gzip compression. Just gzip the bytes, encode the bytes in byte mode, and decompress on the other end.
As a start of an answer to my own question:
If I start with a string of numbers
I can parse that string for patterns and hold those patters in special symbols that are able to take up the other 4 spaces available in my Huffman tree.
EDIT: Example: staring string 12222345, ending string 12x345. Where x is a symbol that means 'repeat the last symbol 3 more times'

Categories

Resources