You are viewing limited content. For full access, please sign in.

Question

Question

Rounding Issue with Javascript, number field times number field to fill currency field

asked on April 19, 2016

On my purchase order form, I had to change the "Price" column of my table to be a number rather than currency, as I needed my users to be able to put in pricing that reflected more than 2 decimal places.  When the calculation is running through javascript to multiply the "Quantity" value by the "Price" value, the result is not being rounded.  Does the Math.round function round on a 5/4 split?  If so, can someone tell me how to implement this into my existing script?  I tried the script to force all currency fields to round on change, but that is not working.  For instance, I can put a quantity of 177 into my form with a price of 0.205, and the result is displaying $36.28; however, if it were rounding on a 5/4 split, it should display $36.29.  

$(document).ready(function(){
  
  //hide Hidden User field
  var $hidden = $('#q71');
  $hidden.hide();
  //hide Hidden Company Name field
  var $hidden = $('#q37');
  $hidden.hide();
  //hide Hidden Vendor Type field
  var $hidden = $('#q73');
  $hidden.hide();
  //hide Hidden Vendor Name field
  var $hidden = $('#q75');
  $hidden.hide();
  
  
  //Round any entries made to the Ext. Total field
  $('.currency').change(function() {
    $(this).val(formatCurrency($(this).val()));
  });
  
  function formatCurrency(value) {
    var float = parseFloat(value);
    return isNaN(float) ? 0 : (Math.round(float*100)/100).toFixed(2);
  }
  
  
  
  //Calculate line item totals, subtotal, and grand total
  $('.cf-table-block').on('blur', 'input', sumtotal);
  $('.tax').on('blur', 'input', sumtotal);
  $('.shipping').on('blur', 'input', sumtotal);
  function sumtotal() {
    var sum = 0;
    $('.cf-table-block tbody tr').each(function () {
      var s = 0;
      s = parseNumber($(this).find('.price input').val()) * parseNumber($(this).find('.quantity input').val());
      $(this).find('.subtotal input').val((s).toFixed(2));
      sum += s; 
    });
  $('.total input').val((sum).toFixed(2));
  $('.grandTotal input').val((sum + parseNumber($('.tax input').val()) + parseNumber($('.shipping input').val())).toFixed(2));  
  $('.ro input').attr('readonly', 'True'); //makes the fields read only after we give them a value.

  }
 function parseNumber(n) {
   var f = parseFloat(n); //Convert to float number.
   return isNaN(f) ? 0 : f; //treat invalid input as 0;
   }




  

  //SET THE HIDDEN VENDOR NAME VARIABLE FOR USE WHEN SAVING TO LASERFICHE:
  //Whenever the Vendor or New Vendor fields are changed, if the New Vendor field is empty,
  //fill the Hidden Vendor Name field with the value from the Vendor field.  
  //Otherwise, fill the Hidden Vendor Name field with the value from the New Vendor field.

  $('.vendor select').change(grabVend);
  $('.newvendor input').change(grabVend);
   
  function grabVend(){
    var hdnvndnm = 0;
    var vndnm = 0;
    vndnm = $('.vendor select').val();
    console.log(vndnm);
    var newvend = 0;
    newvend = $('.newvendor input').val();
    console.log(newvend);
    
    if ((!$('.newvendor input').val())) {
      $('.hdnvendor input').val(vndnm);
    } 
    else {
      $('.hdnvendor input').val(newvend);
    }
    hdnvndnm = $('.hdnvendor input').val();
    console.log(hdnvndnm);
}
  
  
  
  
  
  //handle other scripted activities here
  
});

Thanks for any help you can provide.

0 0

Replies

replied on April 20, 2016

The issue is that float/double is unpredictable.  36.285 may actually equal to 36.284999999999995 in computer, so (36.285).toFixed(2)= 36.28.  We can use the following function to do rounding on a 5/4 split.

function roundDecimal(val, precision) {
  return (Math.round(Math.round(val * Math.pow(10, precision+1))/10)/Math.pow(10, precision)).toFixed(precision);
}

roundDecimal(36.285,2)=36.29

1 0
replied on April 21, 2016

So how exactly would I implement this in my script above?  Copying and pasting it in as either its own separate activity on any change of the "subtotal" field is not working.  Is there something I should be replacing the word "precision" with?

0 0
replied on April 21, 2016

"precision" means how many decimal places to keep.

roundDecimal(36.285,2)=36.29

roundDecimal(36.285,1)=36.3

You can place the (number).toFix(precision) to roundDecimal(number,precision).

$(document).ready(function(){
  
  //hide Hidden User field
  var $hidden = $('#q71');
  $hidden.hide();
  //hide Hidden Company Name field
  var $hidden = $('#q37');
  $hidden.hide();
  //hide Hidden Vendor Type field
  var $hidden = $('#q73');
  $hidden.hide();
  //hide Hidden Vendor Name field
  var $hidden = $('#q75');
  $hidden.hide();
  

  //Round any entries made to the Ext. Total field
  $('.currency').change(function() {
    $(this).val(formatCurrency($(this).val()));
  });
  
  function formatCurrency(value) {
    var float = parseFloat(value);
    return isNaN(float) ? 0:roundDecimal(float,2);
  }
  
  
  
  //Calculate line item totals, subtotal, and grand total
  $('.cf-table-block').on('blur', 'input', sumtotal);
  $('.tax').on('blur', 'input', sumtotal);
  $('.shipping').on('blur', 'input', sumtotal);
  
  function sumtotal() {
    var sum = 0;
    $('.cf-table-block tbody tr').each(function () {
      var s = 0;
      s = parseNumber($(this).find('.price input').val()) * parseNumber($(this).find('.quantity input').val());
      $(this).find('.subtotal input').val(roundDecimal(s,2));
      sum += s; 
    });
  $('.total input').val(roundDecimal(sum,2));

  }
 function parseNumber(n) {
   var f = parseFloat(n); //Convert to float number.
   return isNaN(f) ? 0 : f; //treat invalid input as 0;
   }

  function roundDecimal(val, precision) {
  return (Math.round(Math.round(val * Math.pow(10, precision+1))/10)/Math.pow(10, precision)).toFixed(precision);
}
  
  
  //SET THE HIDDEN VENDOR NAME VARIABLE FOR USE WHEN SAVING TO LASERFICHE:
  //Whenever the Vendor or New Vendor fields are changed, if the New Vendor field is empty,
  //fill the Hidden Vendor Name field with the value from the Vendor field.  
  //Otherwise, fill the Hidden Vendor Name field with the value from the New Vendor field.

  $('.vendor select').change(grabVend);
  $('.newvendor input').change(grabVend);
   
  function grabVend(){
    var hdnvndnm = 0;
    var vndnm = 0;
    vndnm = $('.vendor select').val();
    console.log(vndnm);
    var newvend = 0;
    newvend = $('.newvendor input').val();
    console.log(newvend);
    
    if ((!$('.newvendor input').val())) {
      $('.hdnvendor input').val(vndnm);
    } 
    else {
      $('.hdnvendor input').val(newvend);
    }
    hdnvndnm = $('.hdnvendor input').val();
    console.log(hdnvndnm);
}
  
  
  //handle other scripted activities here
  
});

And I found that if I have two row with price 0.205 and quantity 177, the subtotal are both 36.29 but the total is 72.57 which is equal to 36.285+36.285.

If you want to make the total sum of the rounded values in subtotal , you can change "sum+=s;" to "sum += parseNumber(roundDecimal(s,2));"

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.