jQuery Calculation Plug-in v0.3 released...

Posted by Dan on Mar 2, 2008 @ 5:09 PM

I've updated the jQuery Calculation Plug-in with a few changes:

  • Refactored the aggregate methods (since they all use the same core logic) to use the $.extend() method
  • Added support for negative numbers in the regex (now uses /-?\d+(,\d{3})*(\.\d{1,})?/g)
  • Added min/max aggregate methods
  • Added defaults.onParseError and defaults.onParseClear methods to add logic for parsing errors

The onParseError/onParseClear methods are useful when you need to flag the element that threw the error—such as changing the background color of the element to highlight it doesn't contain a valid number.

Make sure to check out the example of the avg() method on the documentation page. If you input an alpha string into any of the fields, the field will turn red to indicate the parsing engine could not find a number in the field.

I also added support for negative numbers—which was an oversight on my part.

Categories: jQuery

18 Comments

  • Great work Dan!
  • @Rey:

    Thanks!
  • Thanks Dan!
  • Hey Dan,

      I had a need to use parenthesis to indicate negative numbers in an app. To still use the calc plugin, I added a replace to the parseNumber function so that the parenthesis would be replaced with a minus sign. This seems to do the trick. Just thought I would mention it to you.

    v=$el[sMethod]().replace('(','-').replace(')','').match(defaults.reNumbers,"");

    Thanks,
    Dave
  • Hi Dan,

    thanks for this great script.
    I got a question, on this page: http://bettenmanufaktur.de/dev/ I'm trying to get the price_item of the (ddlObj1) on click. But every time I click a field, all values are selected.

    Could you please give me a hint?

    here's a bit of code:

    ddlObj1.addItem('<table><tr><td>90 cm x 200 cm</td><td><span class="thistext">90 cm x 200 cm</span></td><td><span name="qty_item" id="price_item_1" value="10">90</span></td></tr></table>','');
    ddlObj1.addItem('<table><tr><td>100 cm x 200 cm</td><td><span class="thistext">100 cm x 200 cm</span></td><td><span name="qty_item" id="price_item_2">100</span></td></tr></table>','');

    <script>
    $(document).ready(function() {

                 $(ddlObj1).click(
                    function() {
                        var summe = 0;
                        $('span[id^=price_item_]').each(function () {
                                summe += parseInt($(this).html());
                            });
                            $("#grandTotal").html(summe);
                        })
                        .change();
                });
    </script>

    Thanks
    Philipp
  • @Philipp:

    In your code, you have the selector:

    $('span[id^=price_item_]')

    This is going to grab each element that has an id that starts with "price_item_". So the the code's doing exactly what you're telling it to do.

    You're going to need to change things up so that it only grabs the selected value.
  • First, awesome script.

    Second, I am building an order form for my clients site, and I can't get the "grandTotal" field to pass threw on the form after it is submitted. Each item_total comes threw, but the grandTotal will not. Any idea how to get this to work.

    Here is the page: http://www.scratchbread.com/order/index_2.html

    Thanks.
  • @Nick:

    First, I would ignore any value coming through in the grandTotal field. You never want to trust pricing information coming through a JS form--it's too easy for a user to overwrite these values or post their own data to your server. The calc plug-in should purely be used to provide UI feedback to the user. You should always be calculating pricing on the backend based upon quantity and a unique identifier for the product (so that you can look up pricing via the database.)

    However, to answer your question, you have 2 elements with the "id" of "grandTotal"--a div and an input element. Each element should have a unique id (which is per the W3C spec.) What's happening in your situation is that since the first element with the grandTotal id is the div, it's html is being replaced with the calculated value--which is removing the input element from the DOM.

    What you want is to move the input element directly under your form element and change it to:

    <input type="hidden" name="grandTotal" id="grandTotalHidden" value="$0.00" size="8" />

    Now change the selector in your recalc() function to:

    $("#grandTotalHidden").calc( [option here] );

    This will pass the grandTotal named form element. However, as I stated earlier, since you can't trust this value--I wouldn't even include it.
  • Thanks for your help and advice I appreciate it.

    Again, great script and nice work.
  • Hello Dan,

    I am trying to get the grand total to work, but jquery 1.3.2 gives me an error.

    Is there somethin I need to do to get it to work? Like adding extra code for the grandTotal?

    Thanks
  • @Danny:

    There's not enough information in your post to even begin to help you. However, the calc plug-in works fine with jQuery v1.3.2.
  • Hi Dan,

    I'm trying use Brazilian/European format, but I haven't success.
    I paste the code below on my page.

    $.Calculation.setDefaults({
        reNumbers: /(-|-\$)?(\d+(\.\d{3})*(,\d{1,})?|,\d{1,})?/g
        , cleanseNumber: function (v){
        return v.replace(/[^0-9,\-]/g, "").replace(/,/g, ".");
        }
    })

    The result is ok, but this don't change "." to "," in the final value.
    And consequently, the result that sum the results values (#valorTotal), appears wrong, without decimal values.

    What can I do?

    Here is my full script:
    <script type="text/javascript" >
    $(document).ready(function(){

        $.Calculation.setDefaults({
            // a regular expression for detecting European-style formatted numbers
            reNumbers: /(-|-\$)?(\d+(\.\d{3})*(,\d{1,})?|,\d{1,})?/g
            // define a procedure to convert the string number into an actual usable number
            , cleanseNumber: function (v){
                // cleanse the number one more time to remove extra data (like commas and dollar signs)
                // use this for European numbers: v.replace(/[^0-9,\-]/g, "").replace(/,/g, ".")
                return v.replace(/[^0-9,\-]/g, "").replace(/,/g, ".");
            }
        })

        $("input[name^=orcitem_quantidade]").bind("keyup", recalc);
        $("input[name^=orcitem_vu_]").bind("keyup", recalc);

        function recalc(){
            $("input[id^=orcitem_vu_total]").calc("qty * price",{ qty:$("input[id^=orcitem_quantidade]"),price:$("input[id^=orcitem_vu_material]")},function (s){ return s.toFixed(2); })
            $("input[id^=orcitem_valor_total]").calc("servico + material",{ servico:$("input[id^=orcitem_vu_servico]"),material:$("input[id^=orcitem_vu_total]")},function (s){ return s.toFixed(2); },
            function ($this){
          var sum = $this.sum();
                $("#orc_valor_total").val(sum.toFixed(2));
                $("#valorTotal").text(sum.toFixed(2))
            })
        };
    });
    </script>

    Thanks!

    []'s
    Gustavo
  • @Gustavo:

    You will not be able to use toFixed() unless you replace the periods with commas. When JS deals with numbers, it'll use the US-style syntax of a period to separate the decimal.

    You will have to manually convert the calculated number to display in the format you want.
  • i need to deduct number from the grand total??
  • Hi Dan, great script!
    Just wondering about one thing...is there any way to trigger the sum function when the inputs are being updated by a script and not by direct user interaction. "change" and "keyup" doesn't work unless the user is typing something or removing focus after inputting data. I have a scenario where values are being passed to a few hidden inputs and i want the sumTotal to automatically update everytime that happens. Any help would be greatly appreciated! Cheers, Carsten
  • @Carsten:

    I'd recommend using jQuery's trigger() method on the keyup event--which will run any keyup event handlers defined for the field.
  • Stuart Kirkland's Gravatar
    Stuart Kirkland
    Hello Dan

    I was wondering if you could please help me.

    I am trying to get the value of span grandTotal into my database and all i get is the value grandTotal rather than a number. Any ideas what i am doing wrong?

    Stuart
  • @Stuart:

    You never want to accept calculations done on the client-side in your database. Those values are too easy for a user to spoof. The purpose of the calculation plug-in is to provide an easier way to provide real-time visual feedback to users.

    You want to redo the calculations on the server-side, where you can absolutely trust the calculations as being accurate.

Comments for this entry have been disabled.