Forums

Problem With Math Concatinating Instead of Adding

sbrant 29 Nov, 2016
Preface - I'm no programmer. Having a heck of a time adding field values together. They want to concat instead of add. I followed the instructions found here https://www.chronoengine.com/forums/posts/t65691/p266274.html#p266274 and ran into two problems.

1. The math was wrong for some multipliers. For example, 19.95 x 3 would result in: 59.849999999999994. So I added $('variable_here').value = Math.round($('gtotal1').value * 100) / 100; and that seems to work. Is this a proper solution?

2. I have a grand total field that I can not get to add instead of concat. The form is set up with 12 multi fields. Each has a predefined value (price) a user defined value (quantity) and a total value (price x quantity). These work fine. The form has a "grand total" field that is supposed to show the calculated total of all the total fields. This is where the problem lies.

Example: Line A price 1 is 19.95. User selects 3. Total value for line A is 59.85. Line B price is 1.00. User selects 3. Total value for Line B is 3.00. Grand Total is 59.853 instead of 62.853.

I tried adding validators through the designer view. I validated "number" for all number fields. It made no difference.

I found a few ways to force number instead of string but can't seem to get the syntax right. Partly because I don't understand what the $ is doing - I believe it is referencing a method - so that may be a conflict when using parseFloat for example.

Here is a shortened (2 lines instead of 12) version of my code (I'm sure it could be shortened and improved - but this works - but for the concat issue. All tips welcome!). Note I left the non functioning parseFloat in there so you could see how I was attempting to use it.
window.addEvent('domready', function() {
$('quan1').addEvent('input', rekenen1);
$('quan2').addEvent('input', rekenen2);
}

function rekenen1(){
  $('gtotal1').value = $('quan1').value *  $('price1').value;
$('gtota1').value = Math.round($('gtotal1').value * 100) / 100;
parseFloat($('gtotal1').value);
}

function rekenen2(){
  $('gtotal2').value = $('quan2').value *  $('price2').value;
 $('gtota2').value = Math.round($('gtotal2').value * 100) / 100;
parseFloat($('gtotal2').value);

function total_all(){
 $('betrag').value = $('gtotal1').value + $('gtotal2').value; 
 $('betrag').value = Math.round($('betrag').value * 100) / 100;
 parseFloat($('betrag').value );
}
}


LAST - the function total_all is currently being called by a radio button click. Is there a way to call this from any field input? Example, user input of quan1 or quan2 etc.
GreyHead 01 Dec, 2016
Hi sbrant,

First off, I assume that you are using CFv5 with Joomla! 3 - in that case you have the jQuery JavaScript library available with can help with some of these.

1. There is a .toFixed('decimals') method that will pretty up your numbers for you
var sum;
sum = 19.95 x 3;
sum= sum.toFixed(2);


2. For practical jQuery has a default assumption that most variables are strings and + concatenates strings. To make then sum use .parseInt(var) or .parseFloat(var)
var total;
total = parseFloat(price) * parseInt(qty);


The $ is referencing the jQuery library (unless you are using CFv4 on Joomla! 1.5 or 2 when it might be a MooTools library). Because that gets confusing for me I swap the $ for jQuery or, more often, jQ

Before giving a more detailed example it would be helpful to know which versions you are using?

Bob
sbrant 01 Dec, 2016
Hi Bob, Thanks so much for the help! I put both the CF version and Joomla! version in teh forum topic submit fields. Weird that they show when reading posts - but not when responding. Product: ChronoForms5 / System: Joomnla 3.6.4
sbrant 01 Dec, 2016
I get what you are saying and I understand what parseInt, parseFloat and tofixed do, but I can't figure out the right syntax. I'm adding the code in setup/Load JavaScript/JS - right after Load Google NoCapthca.

Do I declare the variable and set toFIxed inside the window.addEvent('domready', function() { } function? It doesn't seem to work on it's own.

How would I properly add parseFloat and parseInt to this: $('gtotal12').value = $('quan12').value * $('price12').value; I tried parseFloat$('gtotal12') and (parseFloat$('gtotal12')) - neither work.

I have 12 fields that are auto totaling (subtotals) on input. $('quan1').addEvent('input', rekenen1);
I need to add all of their values and display in one field (total). I stuck a button in the form to test totaling the quantities. $('calc_sub').addEvent('click', total_all);
How could I call the total function without a button click?

Again, not a programmer - be gentle.😉
GreyHead 02 Dec, 2016
Hi sbrant,

We're safely in Joomla! 3.6 so can go with jQuery.

Step 1. Use this wrapper round the jQuery code
jQuery(document).ready(function(jQ) {
  // rest of the code goes here.
}):
This tells he browser not to run this until the document is ready (basically all the HTML and main code is loaded); and to use jQ as a shortcode for jQuery (just because I'm lazy and it's less confusing than $).

Step 2. jQuery has a whole bunch of ways to identify elements in the page and treat them as jQuery objects so that you can access and change them. The most basic one is the CSS ID selector # - so var quan12 = jQ('#quan12'); finds the form element with the id quan12 and adds it to the JavaScript variable named quan12. The name is just a shorthand way of addressing the object. Note that HTML IDs should be unique in the page so this should pin down that single element.

Step 3. You can get (and set) the value of a form element using the jQuery .val() method. So var quan12_val = quan12.val(); will create a new variable equal to the value of quan12. And FYI quan12.val('xxx'); will set the value of the element to the string xxx.

Step 4. You use events to trigger chunks of code to run. As an example .ready() in the wrapper was an event. More often you are going to want to check for events like 'click', 'change', 'keyup', . . . more here So, for example, if you want to run a function calculate() when the value of the quan12 element changes you might use quan12.on('keyup', calculate); or jQ('#quan12').on('keyup', calculate);

Example 1.

To just do the calculation of one price + qty
jQuery(document).ready(function(jQ) {
  jQ('#quan12').on('keyup', calculate); 
  // I'm assuming price12 is in a readonly or hidden input so it won’t change
  
  function calculate() {
    // define variable names
    var price, qty, value;
    price = jQ('#price12').val();
    qty = jQ('#quan12').val();
    value = parseFloat(price) * parseInt(qty);
    value = value.toFixed(2);
    jQ('#value12').val(value);
  }
}):


That does just one of your sets of inputs.

To do them all you could repeat this 12 times but that is long-winded. Instead you can use a selector that will get all the quantity inputs jQ("[name|='quan']").on('keyup', calculate); which will create an array of objects where the name attribute starts with quan and call the calculate function when any of them changes.

Now you need the calculate function to be able to identify the particular element that has changed. Inside the function the changed element is available as 'this'. So you can get it's ID var id = jQ(this).prop('id'); which will give you e.g. 'quan12' - you only want the integer part of this so id = parseInt(var); will extract that which can then be used to concatenate with quan+ price+ etc.

Lastly you need to calculate the total of all the values so we'll add a it at the bottom to add up all the value fields once the new value has been calculated
jQuery(document).ready(function(jQ) {
  jQ("[name|='quan']").on('keyup', calculate);
  // I'm assuming price12 is in a readonly or hidden input so it won’t change
  
  function calculate() {
    // define variable names
    var id, price, qty, value, total;
    id = jQ(this).prop('id');
    id = parseInt(var);
    price = jQ('#price'+id).val();
    qty = jQ('#quan'+id).val();
    value = parseFloat(price) * parseInt(qty);
    value = value.toFixed(2);
    jQ('#value'+id).val(value);
    // calculate the total
    total = 0;
    jQ("[name|='value']").each(function() {
      total += parseFloat(jQ(this).val()): 
    }
    total = total.toFixed(2);
    jQ('#total').val(total);
  }
}):
!!! Not tested and probably needs debugging !!!

Bob
sbrant 07 Dec, 2016
BOB! With respect to your generous support on this forum, I spent a few days trying to figure this out on my own. I'm just plain stuck. I visited several Jquerry sites searching for answers and implemented a lot of their suggestions. Their influence should be obvious. This is what I've ended up with:

( function($) {
$(document).ready( function() { 
alert("nyah nyah! I'm able to use '$'!!!!");  

function calculate() {
    alert("calculate!");  
    var id, price, qty, value, total;
    id = $(this).prop("id");
    id = parseInt(val,10);
    price = $("#price"+id).val();
    qty = $("#quan"+id).val();
    value = parseFloat(price) * parseInt(qty,10);
    value = value.toFixed(2);
    $("#value"+id).val(value);
    total = 0;

$("name|='qty]").on('keyup', calculate);

$("name|='value']").each(function() {
      total += parseFloat($(this).val());
   });
   
 total = total.toFixed(2);
    $('#total').val(total);
  
  }

} );
} ) ( jQuery );




You can see I slapped in a few alerts to see if the code is working. The first alert is working telling me the code has no errors (I think). The second does not fire, telling me there is something wrong in the logic - not the syntax (I think). Any ideas? I'm happy to pay you Bob - I know the help you have already given is beyond the scope of this forum and I'm very appreciative. Just PM me or tell me how many coffees it would take to get this working.

just to re-cap -
First goal: Get all ("#quan") to multiply by their (#price") and display result in ("#total").
Second goal: Add all ("#total") together and display result in ("#gtotal") - this is not yet part of the code, I know. I tried to get one step working first.

Any ideas are greatly appreciated!
GreyHead 08 Dec, 2016
HI sbrant,

I can see two problems - the first is mine, my apologies for that :-(

The selectors $("name|='value']") are missing a [ - they should look like [color=#000080]$("[name|='value']")[/color]

The second is that there is nothing in your code to call the calculate() function. You do have this line $("[name|='qty]").on('keyup', calculate); but that is inside the function so will probably never be called.

Bob
This topic is locked and no more replies can be posted.