user1425385
user1425385

Reputation: 127

performing calculations on text input values

I have a page which can have multiple rows with 4 input fields on each, like this

1.Number of units 2.Unit price 3.Discount rate 4.Total

I'd like to perform calculations based on the field values. As the user enters values I'd like to update the fourth field (total) depending on the values entered in the boxes, the fourth field shall not be editable by the user. If the discount rate is empty or that field shall be ignored.

To clarify, the total field shall only be updated once there are values in both the amount and price fields. Also the total field shall display the total with the discount deducted if a number is entered into the discount field.

Unfortunately I have no clue and am hoping for some help here.

The rows on the page can vary, the user can add/delete rows to the page (this is already in place)

the html looks like below, and here is a jsfiddle

<div class="row">
  <div>
    <input class="form-control" id="num-of-prods-1" type="text" placeholder="Number of units">
  </div>
  <div>
    <input class="form-control" id="prod-unit-price-1" type="text" placeholder="Unit price">
  </div>
  <div>
    <input class="form-control" id="discount-rate-1" type="text" placeholder="Discount rate %">
  </div>
  <div>
    <input class="form-control" id="order-amount-1" type="text" placeholder="Total">
  </div>
</div>

<div class="row">
  <div>
    <input class="form-control" id="num-of-prods-2" type="text" placeholder="Number of units">
  </div>
  <div>
    <input class="form-control" id="prod-unit-price-2" type="text" placeholder="Unit price">
  </div>
  <div>
    <input class="form-control" id="discount-rate-2" type="text" placeholder="Discount rate %">
  </div>
  <div>
    <input class="form-control" id="order-amount-2" type="text" placeholder="Total">
  </div>
</div>

Upvotes: 1

Views: 3962

Answers (3)

Jason Aller
Jason Aller

Reputation: 3654

The html has been simplified, the ids have been removed, classes have been added, and the disabled attribute has been set on .total. These things were done so that more rows could be handled without having to assign new ids, so that the calculation could be triggered per row, and so that total wouldn't be editable by the user, but would stay an input field.

<div class="row">
    <input class="units" type="text" placeholder="Number of units"/>
    <input class="price" type="text" placeholder="Unit price"/>
    <input class="rate" type="text" placeholder="Discount rate %"/>
    <input class="total" type="text" placeholder="Total" disabled/>
</div>
<div class="row">
    <input class="units" type="text" placeholder="Number of units"/>
    <input class="price" type="text" placeholder="Unit price"/>
    <input class="rate" type="text" placeholder="Discount rate %"/>
    <input class="total" type="text" placeholder="Total" disabled/>
</div>

This allows the following JavaScript to work:

function calculate(units, price, discount) {
    return units * price * ((discount) ? discount : 1);
}

$('input').on('change', function () {
    var scope = $(this).parent('.row'),
        units = $('.units', scope).val(),
        price = $('.price', scope).val(),
        discount = $('.rate', scope).val(),
        total = $('.total', scope);
    if ($.isNumeric(units) && $.isNumeric(price) && ($.isNumeric(discount) || discount === '')) {
        total.val(calculate(units, price, discount));
    }
});

The JavaScript used sets up a function for the calculation which allows the discount rate to either be set or to be optional.

After that is set up we can set up a jQuery call for any time an input is changed. Once it is we get row that was changed into scope and use that to filter when we find each field.

The if statement checks to see if there are numbers present for units and price and if the discount rate is either a number or empty. If these conditions are met then it replaces the content of .total with the result of calculation.

see http://jsfiddle.net/RtN4e/6/

edited per comments

The HTML is now:

<div class="row">
    <div>
        <input class="units" type="text" placeholder="Number of units"/>
    </div>
    <div>
        <input class="price" type="text" placeholder="Unit price"/>
    </div>
    <div>
        <input class="rate" type="text" placeholder="Discount rate %"/>
    </div>
    <div>
        <input class="total" type="text" placeholder="Total" disabled/>
    </div>
</div>

and the JavaScript is now:

function calculate(units, price, discount) {
    if (discount) {
        if (discount < 0 || discount > 100) {
            discount = 0;
        }
    } else {
        discount = 0;
    }
    return (units * price) * (1 - (discount / 100));
}

$('input').on('change', function () {
    var scope = $(this).closest('.row'),
        units = $('.units', scope).val(),
        price = $('.price', scope).val(),
        discount = $('.rate', scope).val(),
        total = $('.total', scope);
    if ($.isNumeric(units) && $.isNumeric(price) && ($.isNumeric(discount) || discount === '')) {
        total.val(calculate(units, price, discount));
    } else {
        total.val('');
    }
});

This incorporates the discount calculation that Luxelin suggested along with a simplified set of limits that remove any discount if it is out of range and changes .parent() to .closest() to allow for wrapping <div> elements on each input.

Upvotes: 2

Jordan Schnur
Jordan Schnur

Reputation: 1353

You're going to want to use the keyup, parseFloat(To get numbers with a decimal) and isNaN to check if it's a number or not.

    $(".form-control").keyup(function(e) {
   var num = parseFloat(String.fromCharCode(e.which));
    if(!isNaN(num)) {
        if(num == 0) {
             $(this).val("You entered 0!");   
        }
    }
});

If you want to ignore a textbox add something like data-editable="false" and check it with the .data method.

Try it out: http://jsfiddle.net/Zyneak/AGAj8/

Upvotes: 0

ibonly
ibonly

Reputation: 133

you can check out the fiddle: http://jsfiddle.net/RtN4e/3/

$('#inputFormID').blur(function(e) {
    var txtVal = parseFloat($(this).val());
    $('#outputF').val(txtVal);
});

since you want to be able to add more rows programmatically, you'll just have to include class in you input tag and concatinate the class to the id referenceing.

Upvotes: 0

Related Questions