Watch jQuery Calculation Plug-in in action!

Categories: jQuery

A few weeks ago I posted a blog entry on my jQuery Calculation Plug-in. However, I never think I do an adequate job of describing what it does so I thought a little video might be more useful. Since I just installed Jing a few days ago, I thought this plug-in made a perfect candidate for my first Jing post!

Something I forgot to specifically mention in my demo, but which I think is really significant, is that the dynamic calculation code would work regardless of how many rows were in your table. If you only had 1 item in your basket or 20 items, the exact same code is used. The key is to use a naming convention that is consistent and easy for jQuery to parse.

My original post goes into the technical details behind the demo above, so make sure to read the post for the detailed information on what's going on.

Related Blog Entries

Comments

Jim Priest's Gravatar Very cool! Both the plugin and the interactive demo!! Things like this really shine when you can see them in action!
Kevin Sargent's Gravatar I've just been getting into jquery lately, so it's cool to see more plugins like this get created.

Just remember to never rely on client side code for important values that get sent BACK to the server!
Dan G. Switzer, II's Gravatar @Kevin:

Your absolutely correct in that you should never rely on values, like price, which are passed from the client to the server. This script is to help you implement better UI controls, not to be as an aid for any server-side logic that's needed.

There are many use cases for needing to calculate values based upon your DOM layout and this is the reason I created the plug-in.
Karl Swedberg's Gravatar Excellent demo video, Dan! Great plugin, too. It was really fun to see it in action.
Kevin Sargent's Gravatar @Dan

Exactly, Sorry to make it sound like you wouldn't know better. I guess my comment was for the google searcher / passer byer that was looking for scripts to copy / paste.
Dan G. Switzer, II's Gravatar @Kevin:

It's a point always worth preaching. I've done a lot of presentations at User Groups and Conferences on JavaScript--which tend to focus on the subject of Form Validation (since that's typically one of the first things people want to do with JavaScript.) While I'm a huge advocate of implementing JS-based validation because it improves the UI, I always make sure to re-iterate throughout my presentation that you can not use JS-based validation as your only method of validating data.

Client-side technologies (such as JS) should only be used to enhance the user's experience, but the server-side is where you must validate all input to ensure that the data your receiving is valid.
Njau Ndirangu's Gravatar Nice plugin but has one flaw, it is not versatile enough to be used in multiple tables. There will be a conflict from grandTotal. Another thing, maybe an option were you used checkbox and radio should be implemented. Lets say you click on radio; somehow the price should be included in the calculation. all in all nice plugin.
Dan G. Switzer, II's Gravatar @Njau:

There's no problem using this with multiple tables, you just need to invoke 2 different unique instances. Also, there shouldn't be a problem implementing radio buttons into the equation--provided the elements have valid numeric values.
Morton's Gravatar Dan, would you mind showing with an example how to implement multiple tables and the radio button with values.Would be interesting to know for a rookie like me.

Thanks
Rick's Gravatar I'm also looking for an example of this being used with radio buttons.. Where would I find an example like that or even some documentation that step by steps it??
Daniel's Gravatar Brilliant plugin, Dan! Thank you very much!
Since I am not the superadvanced poweruser... Is there a way to allow only integer numbers or the "." to be ignored?
Dan G. Switzer, II's Gravatar @Daniel:

You could change the regex used to parse the numbers if you wanted just integers to something like:

$.Calculation.setDefaults({
reNumbers: /(\d+(,\d{3})/g
});
Daniel's Gravatar Thank you, Dan! ;)
Phil's Gravatar I'm also trying to get this to work with radio buttons, seems to add all the options up and not only the selected ones.
Dan G. Switzer, II's Gravatar @Phil:

What do your selectors look like? I suspect your selectors are wrong for picking the value from the selected radio element.
Phil's Gravatar Sorry, been away from this project for a little while.

jQuery(function( $ ){
$("input[@name='processor'], input[@name='memory'], input[@name='hard_drive']").sum('click','#total');
});


Code sample:
<dt>Memory</dt>
<dd>
<div class="configurator_option">
<input type="radio" name="memory" value="16"/>
<label>1GB DDR2 667Mhz (1-1GB) - $16 | $25</label>
</div>
<div class="configurator_option">
<input type="radio" name="memory" value="38"/>
<label>1GB ECC DDR2 667 (1 - 1GB) - $38 | $60</label>
</div>
<div class="configurator_option">
<input type="radio" name="memory" value="38"/>
<label>2GB DDR2 667Mhz (1-2GB) - $38 | $50</label>
</div>
<div class="configurator_option">
<input type="radio" name="memory" value="64"/>
<label>2GB ECC DDR2 677 (1 - 2GB) - $64 | $100</label>
</div>
</dd>

I fully admit that javascript/jquery are quite new for me so I could be 100% guilty of making an error a more experienced person wouldn't make.
Dan G. Switzer, II's Gravatar @Phil:

Use this instead for your jQuery call:

$("input[@name='processor'], input[@name='memory'], input[@name='hard_drive']").sum({bind: 'click', selector: '#total'});

There appears to be a bug detecting the bind parameter unless you use the object notation.
Dan G. Switzer, II's Gravatar @Phil:

I've just updated the code so that your original syntax should work.
Phil's Gravatar Thanks, I will see if I can make it work now!
Phil's Gravatar It still seems to add all the options rather than only the ones selected. In my example above it would add all 4 of the Memory options rather than only the selected one.

I did update to the latest version. The sum is working, just not quite how I thought it should.
Dan G. Switzer, II's Gravatar @Phil:

Make sure you're loading the Field Plug-in:
http://jquery.com/plugins/project/field

Otherwise the val() function will return the value for each element (since you're not filtering to only the checked items.)
Phil's Gravatar I am using the Field plug-in. I also switched the selector to

$("input[@type=radio][@checked]").sum('click','#total');

Which seems to have done the trick. But now, again likely due to my inexperience with this, the total doesn't update when I click a different radio button.

Thanks for all your help so far. It is very much appreciated.
Dan G. Switzer, II's Gravatar @Phil:

You can't use the "checked" attribute selector, because then only the originally checked item gets the behavior applied to it.

When I do:

$(document).ready(
   function (){
      $("input[@name='processor'], input[@name='memory'], input[@name='hard_drive']").sum('click', '#total');
   }
);

<dt>Memory</dt>
<dd>
   <div class="configurator_option">
      <input type="radio" name="memory" value="16"/>
      <label>1GB DDR2 667Mhz (1-1GB) - $16 | $25</label>
   </div>
   <div class="configurator_option">
      <input type="radio" name="memory" value="38"/>
      <label>1GB ECC DDR2 667 (1 - 1GB) - $38 | $60</label>
   </div>
   <div class="configurator_option">
      <input type="radio" name="memory" value="38"/>
      <label>2GB DDR2 667Mhz (1-2GB) - $38 | $50</label>
   </div>
   <div class="configurator_option">
      <input type="radio" name="memory" value="64"/>
      <label>2GB ECC DDR2 677 (1 - 2GB) - $64 | $100</label>
   </div>
</dd>

<div>
   <strong>Total:</strong>
   $<span id="total">0</span>
</div>

Only the memory item that is checked has it's value copied to the #total element.
Phil's Gravatar Hooray! The difference was in our functions. I pasted yours in place of mine and it worked.

Me: function( $ )

You: function ()

Like I said, I'm new and dysfunctional with jquery.

Thanks much. Your plugin does exactly what I needed.
Philipp's Gravatar Hi,

It's a great plugin, just one question.

I'm programming an german onlineShop, so I have to use , instead of . for decimals,
what do I have to change in the source to keep the calculation working?
Dan G. Switzer, II's Gravatar @Philipp:

All you need to do is to change the default regex used for finding numbers and modify the cleanse 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, ".");
   }
})

The above has been tested and verified to work. I've also added this information to the example page.
Philipp's Gravatar Hi

THX for ur reply.
I tried it but it's still the same, I cleared the cache etc..

It's still calculating but I get a point instead of a comma.
My prices are using commas.

what else can I try?
Dan G. Switzer, II's Gravatar @Philipp:

Are you sure you're running the latest version? Also, as my note above stated I didn't actually test the regex, but it looks like I missed escaping the "." Try this instead:

reNumbers: /(-|-\$)?(\d+(\.\d{3})*(\,\d{1,})?|\,\d{1,})?/g

That escapes the period to actually capture the period instead of a wildcard character.

Let me know if that works and I'll update my comment above.
Trever's Gravatar Hi Dan,

I've been following your comments with Phil, and have been doing every last thing in my hopeless search to just get your plug-in working. I'm very limited with Javascript jargon, and jQuery in general. If you wouldn't mind, please have a look at my page, I've been at this for quite some time now with no luck.

http://www.yurtsofhawaii.com/site/calc.html

Thanks in advance!
Dan G. Switzer, II's Gravatar @Trever:

You need to load jQuery before loading any jQuery plug-in. That's the reason it's not working.

Also, while it may not make a difference, I know jQuery 1.3.0 had a number of issues that have been fixed, so you might want to use v1.3.2 instead.

Google hosts jQuery on their CDN for the public to use. The url of v1.3.2 is:
http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/...
Trever's Gravatar Dan,

I've was calling jQuery from the Google server, so I've just changed that up again for you to see that it still won't work.

After I left this post last night I experimented for another hour. I copied your entire demo page, and tried calling your exact scripts in the header. That worked. When I called the field, and calculation plug-in from my server, it stopped working.

I'm now calling the jQuery from the Google server in the header, at:
http://www.yurtsofhawaii.com/site/calc.html but it's not working.

Thanks again Dan!
Dan G. Switzer, II's Gravatar @Trever:

The "@" was depreciated a while back, change your selector to match the format "input[name='memory']" instead of "input[@name='memory'] and it should work fine. I just ran this code in Firebug:

$("input[name='memory']").sum('click', '#total')

And your page began working fine.
Philipp's Gravatar Hi

Sorry I wasn't online for a while.

Finally I transferred my project on a testserver.
Till now I wasn't able to get it running with commas.

U can see it here:
http://dev.fotosemrad.at/index.php?idcatside=4&...

What if I just reformat the output? Would the total Sum then still work???

THX Philipp
Dan G. Switzer, II's Gravatar @Phillip:

I don't see where you're using the setDefaults() method in your code. If you use that code, it should work fine with European formatting.
Philipp's Gravatar Hi

I changed the code in here:

http://admin.dev.fotosemrad.at/plugins/shop/inc/js...

is that wrong??
Dan G. Switzer, II's Gravatar @Phillip:

I advice against changing the source code, because then it becomes more difficult to upgrade if a new version is released. That's the reason it's better to use the setDefaults() to change the behavior. Then hopefully upgrading is as simple as dropping in a new script.
Simon's Gravatar Hi Dan,

I'm looking to try and do something a little different with your plug-in and wondering whether it is possible in some way.

I have a number of INPUT fields with multiple values attached to various attributes. Depending on the situation, instead of taking the usual VALUE attribute, I need to be able to chose the actual attribute from which to SUM.

eg
<input id="item1" name="item1" value="3" value2="1.67" value3="3.5" />
<input id="item2" name="item2" value="4" value2="2" value3="5" />

I was hoping to be able to do something like:
$(#item1").attr("value2").sum();

but unfortunately that doesn't work.
Any ideas?

Thanks,
Simon
Dan G. Switzer, II's Gravatar @Simon:

No, that won't work. What I would recommend doing instead is changing the value attribute to the correct value based on your condition. That way the correct value gets sent to the server on a post as well.
Simon's Gravatar That might work. I'm not too bothered about the posted values as all the calculation is happening client side, and any posting in happening via Ajax in the background. Here's me trying to overly complicate things. Thanks for your thoughts!
Dan G. Switzer, II's Gravatar @Simon:

I'm sure you're aware, but I would never use calculation done on the client side on the server side of thing--it's too easy for that data to be manipulated. I also add this disclaimer. You should only be using the calc() plug-in to provide the user with live feedback and shouldn't trust the values as being valid.
Kevin's Gravatar Is there a way to evaluate the result of:

$("input[type=text]").sum("keyup", "#total");

I need to throw an alert if the value of the sum exceeds 100.

Thanks,

Kevin
Dan G. Switzer, II's Gravatar @Kevin:

If you pass in a option object, you can use the "oncalc" callback to configure something to run after the calculation takes place. For example:

$("input[type=text]").sum({
    bind: "keyup"
   , selector: "#total"
   , oncalc: function (value, settings){
      // use this callback for validation
   }
});

So, you can do your validation in the oncalc callback.
deleteYourslf's Gravatar I'm working on a project to convert metric units. Everything works fine in all browsers except Internet Explorer. In IE, it seems like the 2nd bind event never gets called so #kg-cm never calculates. Is there something I am doing wrong with the calc() method?

I have a few text fields:

<table width="100%" border="0" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>Bar</th>
<th>KG/CM</th>
<th>PSI</th>
</tr>
</thead>
<tr>
<td><input id="bar" type="text" name="ztest1" /></td>
<td><input id="kg-cm" type="text" name="ztest2" /></td>
<td><input id="psi" type="text" name="ztest3" /></td>
</tr>
</table>

$(document).ready(function() {
//pressure fields
         
   $('#bar').bind('keyup', function(event){
   
   $('#psi').calc(
      
         'bar * numberA',
         
         {
            bar: $('#bar'),
            numberA: ('14.503861')
         },
         
         function (a){
         
            return a.toFixed(2);
         },
         
         function ($this){
         
            var sum = $this.sum();
            
            $('#psi').text(sum.toFixed(2));
         }
      );
   
   });
   
   
   $('#bar').bind('keyup', function(event){
                           

    $('#kg-cm').calc(
      
         'bar * numberB',
         
         {
            bar: $('#bar'),
            numberB: ('1.02')
         },
         
         function (a){
         
            return a.toFixed(2);
         },
         
         function ($this){
         
            var sum = $this.sum();
            
            $('#kg-cm').text(sum.toFixed(2));
         }
      );   
   
   });

}
);
Dan G. Switzer, II's Gravatar @deleteYourslf:

It might be because your defining the numberA and numberB variables as strings instead of floats. It shouldn't affect things, but it might be causing issues.
v's Gravatar how do i use this javascript to calculate multiple input?

here is my html form
<form name="form1" id="form1" method="post" action="...">
water<input type="text" name="water"> power<input type="text" name="power">
</form>
and loop form to 47
...
<form name="form47" id="form47" method="post" action="...">
water<input type="text" name="water"> power<input type="text" name="power">
</form>

i want each form calculation water+power not calculate all from.
thanks for help.
Karthik's Gravatar Hi Dan

Thank you for the plugin. I was trying to use the calculator plugin for data grid that is loaded from a database. How do i support this plugin for the same ?

Thanks
jeff's Gravatar hey great plugin,

i try to use the european number format (german).. but same problem than phillip..

http://webasic.de/calculation/

it doesn work with ","
Dan G. Switzer, II's Gravatar @Jeff:

It works fine with Euro strings--the problem you're having is do to the whitespace in the tag. I'm surprised this issue hasn't come up for me before, but I suspect it's because I don't leave beginning/trailing whitespace to my value.

I've just pushed up v0.4.07, which trims the value before sending it to the regex and your code works fine now.

http://www.pengoworks.com/workshop/jquery/calculat...
jeff's Gravatar thx for updating,

now it works in euro format.. i'm add replace(/\./,',') + " EUR" to the recalc function..

like this: return s.toFixed(2).replace(/\./,',') + " EUR";

i know, its not the best way

Add Comment

Leave this field empty


If you subscribe, any new posts to this thread will be sent to your email address.