The question is already answered, but there are some things about your code, that make it inefficient and quite error-prone. Consider this piece of code:
$.fn.boundForm = function(options) {
var defaults = {
fields: ".three-digit",
total: ".percentage-current",
validateInput: function(item) {
item.value = parseInt(item.value.replace(/[^0-9]+/g, "")) || 0;
return parseInt(item.value);
},
calculateTotal: function(fields) {
return fields.toArray().reduce(function(sum, item) {
return sum + this.validateInput(item);
}.bind(this), 0);
},
refresh: function(form) {
form.find(this.total).text(this.calculateTotal(form.find(this.fields)));
}
}
var o = $.extend({}, defaults, options);
this.each(function() {
var $form = $(this);
$form.on("input", o.fields, function() {
o.refresh($form);
});
o.refresh($form);
});
};
$(".percentage-validate").boundForm();
This is a basic widget, that does the same thing as your code, but:
- It includes validation method
validateInput, that replaces any non-numbers, and return 0 if value is empty;
- It doesn't require 'dirty checking' every time interval to determine if value has changed, so it is more efficient;
- It is reusable - if you need to calculate some other values elsewhere - you can easily do so just by passing an object containing different selectors, methods, and whatever, and it would still work just fine, and you'd need to simply call
$("#myContainer").boundForm(myOptions);
All in all, that makes for much more convenient code to work with. Hope that helps.
P. S. Here's fiddle
parseInton a value that is not a number - try to inspect each value in each iteration and validate that you are indeed dealing with numerical values.