I have a form that accepts currency from several fields and depending on what I enter into one, it calculates others. For this most part the code below works (example being the invoice amount field)

<xp:inputText value="#{FInvoiceDoc.InvoiceAmount}" id="InvoiceAmount">
 <xp:this.converter>
  <xp:convertNumber type="currency"></xp:convertNumber></xp:this.converter>
  <xp:eventHandler event="onchange" submit="false" id="eventHandler5">
   <xp:this.script><![CDATA[var rate = XSP.getElementById("#{id:ExchangeRate}").value;
    var stAmount = XSP.getElementById("#{id:InvoiceAmount}").value;
    var stTvat = XSP.getElementById("#{id:TVAT}").value;
    var stTst = XSP.getElementById("#{id:TST}").value;
    var stToop = XSP.getElementById("#{id:Toop}").value;
    var tmp;
// get the dojo currency code
    dojo.require("dojo.currency");
// get the numeric values using parse
    amount = dojo.currency.parse(stAmount,{currency:"USD"});
    total = rate * amount;
    XSP.getElementById("#{id:EstUSAmount}").innerHTML = dojo.currency.format(total,{currency:"USD"});
    XSP.getElementById("#{id:InvoiceAmount}").value = dojo.currency.format(amount,{currency:"USD"});
    if (amount != 0) {
     tvat = dojo.currency.parse(stTvat,{currency:"USD"});
     tst = dojo.currency.parse(stTst,{currency:"USD"});
     toop = dojo.currency.parse(stToop,{currency:"USD"});
     tmp = (tvat / (amount-tvat-tst-toop)) * 100;
     XSP.getElementById("#{id:VP}").innerHTML = tmp.toFixed(2);
     tmp = (tst / (amount-tvat-tst-toop)) * 100;
     XSP.getElementById("#{id:STP}").innerHTML = tmp.toFixed(2);
     tmp = (toop / (amount-tvat-tst-toop)) * 100;
     XSP.getElementById("#{id:OoPP}").innerHTML = tmp.toFixed(2);
     }
   ]]></xp:this.script>
  </xp:eventHandler>
</xp:inputText>

Like I said, for the most part this works, but if I enter only a partial number like

200.2

instead of

200.20

then it fails. Most data entry folks will want to not have to key in the last "0" just so it's legal.

btw, if I enter it in as just 200 with no cents, it's OK.

It's as if the statement;

amount = dojo.currency.parse(stAmount,{currency:"USD"});

requires a 2 digit penny amount or no pennys, but doesn't like just the leading cents digit.

Any way around this?

有帮助吗?

解决方案

The currency format is very restrictive and needs the certain number of decimal places for a given currency. As you can see here there can be different number of decimal places depending on currency. For most currencies it needs two decimal places though. But, you can trick the parser. Just try it with standard number of decimal places and if it fails try it with one decimal place again. Your code would look like this then:

var amount = dojo.currency.parse(stAmount,{currency:"USD"});
if (!amount && amount!==0) {
    amount = dojo.currency.parse(stAmount,{currency:"USD",places:"1"});
}

This accepts inputs like

12
12.3
12.34
$12
$12.3
$12.34

But it is still very picky. It doesn't accept spaces or more decimal places then currency allows.

If you want more flexibility for your users and need USD currency only I'd go for dojo.number or other number parsing instead and show the "$" outside the input field. Then, you'd be able to accept much more formats and could add functions like rounding.

其他提示

Yeah, I've played with the converters. Thing is I want the converter to stay "Currency". The data I receive from the notes database is always correct and formats properly. Its the manipulation that I''m having a problem with. Since this is all on the client side, I've created a function that I can reuse throughout the page.

<script>
function isNumeric(n) {
  n = parseFloat(n);
  return !isNaN(n) || n != n;
}
// We call this if its a currency amount. If they only entered one number after
// the decimal, then we just append a 0. We're expecting a string and we send
// the string back.
function cMask(Amount) 
{
    if (Amount == "") { return "0.00" }
    a = Amount.split(".");
    if (a.length == 2) 
    {
        if (a[1] != null)
        {
            if (a[1].length == 1) 
            {
                Amount = Amount + "0";
            }
        }
    }
// get the dojo currency code
    dojo.require("dojo.currency");
    b = dojo.currency.parse(Amount,{currency:"USD"});
    if (isNumeric(b)) {return Amount} else {return "0.00"}
}
</script>

Then its a matter of just changing the initial variable load line.

var stAmount = cMask(XSP.getElementById("#{id:InvoiceAmount}").value);

Seems to work and I've just taught myself how to create reusable client-side javascript for my page.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top