www.webdeveloper.com
Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 44

Thread: Javascript sums for 2 different sub total fields help

  1. #16
    Join Date
    Apr 2014
    Posts
    36
    Thank you very much for taking the time to write this. I will plug it in today and test it out
    Is there any chance it can be changed so that there is a quantity drop down (only up to 3 items ) If more than 1 item is selected then 2 different width and height fields will show up. My requirements have changed a bit..
    If a customer chooses 1 item then they put in the width height, colour, tooling.
    If a customer chooses 2 or 3 items the colour and tooling will not change but they can enter up to 3 different height and widths options. From what I understand if they choose tooling on item 1 then item 2 and 3 will automatically have tooling selected as well (factored in for pricing)

  2. #17
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    Right now none of the changes I've posted here include a dropdown to control the number of items. Because your form is very... specific, it would take a little bit of time to rework the form to function dynamically (changing the number of items displayed).

    The function I most recently posted simply was designed so that you can calculate the total and grand total regardless of the number of items. The same function will calculate the total of any individual item and loop through all available items to get a grand total. So it would work for 1 item or 15 items, it's just a matter of having the proper <input> fields in your form and setting the $itemCount variable when items are added or removed from the form.

    If you make the changes you want in regard to 1 set of tooling options and then multiple width/length fields I can try working with that. But first I'd say it's a matter of at least getting your form the way you want it (functionality aside) and I could write a function to show/hide the extra width/length fields based on the number of items selected.

  3. #18
    Join Date
    Apr 2014
    Posts
    36
    Hi, I attempted to implement the code you gave me and it didn't work. Here is what I did.
    1. Added your code above to the existing js file.
    2. In Javascript file changed the form number from 1 to 0 since there is only 1 form
    3. for 2 items added
    <input class="short" onchange="Calculate(0)" name="width">
    <input class="short" onchange="Calculate(0)" name="length">

    *little unsure where to put form document.forms reference in html and where the $itemCount come into play.
    <input class="short" onchange="Calculate(1)" name="width">
    <input class="short" onchange="Calculate(1" name="lenght">

    what did I miss?

  4. #19
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    Okay, a couple of things to note here. Firstly, if this is going on your order form test page that you linked earlier, you actually do have 2 forms (the first one is the newsletter subscription form at the top of the page). So you may need to keep the form reference number at 1 rather than 0. Alternatively, you can just add a name="" value to the form and then use something like
    Code:
    document.forms["myFormName"]["length"].value;
    This would use the form object if you set the name attribute to 'myFormName', rather than trying to reference the form via index. Since there wasn't already a name on the form I just used the index for simplicity (less work for you).

    Next, $itemCount won't be messed with currently. Your form has 2 items and that doesn't change. I know you wish to change this soon, but based on the current form the number of items doesn't change, so $itemCount can be left at 2 (which it is by default).

    Lastly, it looks like I have trouble spelling from time to time. There was a mistake in my code (calling $lFiends and $wFiends instead of the correct variable names: $lFields and $wFields). Here's the corrected version:
    Code:
    if(typeof(_N) != "function") function _N($n, $d) { return ($d) ? Number($n).toFixed($d).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : $n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }
    
    $itemCount = 2;
    $lFields = ["length", "length2", "length3", "length4"];
    $wFields = ["width", "width2", "width3", "width4"];
    $tFields = ["totalcost", "totalcost2", "totalcost3", "totalcost4"];
    
    function Calculate($a) {
    	var order_total, length, width, i;
    	order_total = 0;
    
    	length = parseFloat(document.forms[1][$lFields[$a]].value);
    	width = parseFloat(document.forms[1][$wFields[$a]].width.value);
    
    	if(length > 0 && width > 0) {
    		order_total = length * width;
    		for(i = 0; i < document.forms[1]["tooling"].length; i++) {
    			if (document.forms[1]["tooling"][i].value === "withouttooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".30";
    			if (document.forms[1]["tooling"][i].value === "withtooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".40";
    		}
    		//order_total = order_total * .35
    		order_total = order_total + 25;
    	} else {
    		order_total = 0;
    	}
    
    	// Display the total rounded to two decimal places
    	//frm.totalcost.value = '$ ' + round_decimals(order_total, 2);
    	document.forms[1]["totalcost"].value = '$' + _N(order_total, 2);
    	_CalculateTotal();
    }
    
    function _CalculateTotal() {
    	var $grandTotal = 0;
    	var $f = document.forms[1];
    	for(var $i = 0; $i < $itemCount; $i++) {
    		$grandTotal = ($grandTotal) + parseFloat($f[$tFields[$i]].value.replace(/[^0-9.]/g, ""));
    	}
    	document.getElementById("grandTotal").innerHTML = _N($grandTotal, 2);
    }

  5. #20
    Join Date
    Apr 2014
    Posts
    36
    I added the modified code leaving the reference number to 1 but nothing happens on my form. I am missing something.

    js code
    if(typeof(_N) != "function") function _N($n, $d) { return ($d) ? Number($n).toFixed($d).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : $n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }

    function Calculate(frm) {
    var order_total, length, width, i;
    order_total = 0;

    length = parseFloat(frm.length.value);
    width = parseFloat(frm.width.value);

    if(length > 0 && width > 0) {
    order_total = length * width;
    for(i = 0; i < frm.tooling.length; i++) {
    if (frm.tooling[i].value === "withouttooling" && frm.tooling[i].checked === true) order_total = order_total * ".35";
    if (frm.tooling[i].value === "withtooling" && frm.tooling[i].checked === true) order_total = order_total * ".45";
    }
    //order_total = order_total * .35
    order_total = order_total
    } else {
    order_total = 0;
    }

    // Display the total rounded to two decimal places
    //frm.totalcost.value = '$ ' + round_decimals(order_total, 2);
    frm.totalcost.value = '$' + _N(order_total, 2);
    _CalculateTotal(frm);
    }


    function Calculateitem2(frm) {
    var order_total, length, width, i;
    order_total = 0;

    length = parseFloat(frm.length2.value);
    width = parseFloat(frm.width2.value);

    if(length > 0 && width > 0) {
    order_total = length * width;
    for(i = 0; i < frm.tooling2.length; i++) {
    if(frm.tooling2[i].value === "withouttooling" && frm.tooling2[i].checked === true) order_total = order_total * ".35";
    if(frm.tooling2[i].value === "withtooling" && frm.tooling2[i].checked === true) order_total = order_total * ".45";
    }
    //order_total2 = order_total2 * .35
    order_total = order_total;
    } else {
    order_total = 0;
    }

    // Display the total rounded to two decimal places
    //frm.totalcost2.value = '$ ' + round_decimals(order_total, 2);
    frm.totalcost2.value = '$' + _N(order_total, 2);
    _CalculateTotal(frm);
    }

    function _CalculateTotal($f) {
    var $total1 = parseFloat($f.totalcost.value.replace(/[^0-9.]/g, ""));
    var $total2 = parseFloat($f.totalcost2.value.replace(/[^0-9.]/g, ""));
    console.log($total1, $total2);
    document.getElementById("grandTotal").innerHTML = (!isNaN($total1) && !isNaN($total2)) ? "$" + _N($total1 + $total2, 2) : "";
    }

    function round_decimals(original_number, decimals) {
    var result1 = original_number * Math.pow(10, decimals);
    var result2 = Math.round(result1);
    var result3 = result2 / Math.pow(10, decimals);
    return pad_with_zeros(result3, decimals);
    }

    function pad_with_zeros(rounded_value, decimal_places) {
    // Convert the number to a string
    var value_string = rounded_value.toString();

    // Locate the decimal point
    var decimal_location = value_string.indexOf(".");

    // Is there a decimal point?
    if(decimal_location == -1) {
    // If no, then all decimal places will be padded with 0s
    decimal_part_length = 0;

    // If decimal_places is greater than zero, tack on a decimal point
    value_string += decimal_places > 0 ? "." : "";
    } else {
    // If yes, then only the extra decimal places will be padded with 0s
    decimal_part_length = value_string.length - decimal_location - 1;
    }

    // Calculate the number of decimal places that need to be padded with 0s
    var pad_total = decimal_places - decimal_part_length;

    if(pad_total > 0) {
    // Pad the string with 0s
    for(var counter = 1; counter <= pad_total; counter++) {
    value_string += "0";
    }
    }
    return value_string;
    }
    if(typeof(_N) != "function") function _N($n, $d) { return ($d) ? Number($n).toFixed($d).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : $n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }

    $itemCount = 2;
    $lFields = ["length", "length2", "length3", "length4"];
    $wFields = ["width", "width2", "width3", "width4"];
    $tFields = ["totalcost", "totalcost2", "totalcost3", "totalcost4"];

    function Calculate($a) {
    var order_total, length, width, i;
    order_total = 0;

    length = parseFloat(document.forms[1][$lFields[$a]].value);
    width = parseFloat(document.forms[1][$wFields[$a]].width.value);

    if(length > 0 && width > 0) {
    order_total = length * width;
    for(i = 0; i < document.forms[1]["tooling"].length; i++) {
    if (document.forms[1]["tooling"][i].value === "withouttooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".30";
    if (document.forms[1]["tooling"][i].value === "withtooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".40";
    }
    //order_total = order_total * .35
    order_total = order_total + 25;
    } else {
    order_total = 0;
    }

    // Display the total rounded to two decimal places
    //frm.totalcost.value = '$ ' + round_decimals(order_total, 2);
    document.forms[1]["totalcost"].value = '$' + _N(order_total, 2);
    _CalculateTotal();
    }

    function _CalculateTotal() {
    var $grandTotal = 0;
    var $f = document.forms[1];
    for(var $i = 0; $i < $itemCount; $i++) {
    $grandTotal = ($grandTotal) + parseFloat($f[$tFields[$i]].value.replace(/[^0-9.]/g, ""));
    }
    document.getElementById("grandTotal").innerHTML = _N($grandTotal, 2);
    }

    form same as before but input length and width replaced as referenced above.
    http://www.webcrawldesigns.com/dct/order-form-test/
    thx

  6. #21
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    You are using the same names for each field, so it's hitting an error. Your first width and length field should be named like they currently are. The second width and length field should be called "width2" and "length2" (respectively). Just correct the name values and it should work.

  7. #22
    Join Date
    Apr 2014
    Posts
    36
    I changed the width and length to 2 and now it looks like it is registering but shows total cost of item one for example as $0.00 and grand total is NaN

  8. #23
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    Alright, two things need to be adjusted. I did just notice two more issues with the code I gave you. I wasn't setting the width value correctly (thus the $0.00 price). The item total also wasn't set to write to each total box dynamically, so it only worked for the first item. Both are fixed in the code below:
    Code:
    function Calculate($a) {
    	var order_total, length, width, i;
    	order_total = 0;
    
    	length = parseFloat(document.forms[1][$lFields[$a]].value);
    	width = parseFloat(document.forms[1][$wFields[$a]].value);
    
    	if(length > 0 && width > 0) {
    		order_total = length * width;
    		for(i = 0; i < document.forms[1]["tooling"].length; i++) {
    			if (document.forms[1]["tooling"][i].value === "withouttooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".30";
    			if (document.forms[1]["tooling"][i].value === "withtooling" && document.forms[1]["tooling"][i].checked === true) order_total = order_total * ".40";
    		}
    		//order_total = order_total * .35
    		order_total = order_total + 25;
    	} else {
    		order_total = 0;
    	}
    
    	// Display the total rounded to two decimal places
    	//frm.totalcost.value = '$ ' + round_decimals(order_total, 2);
    	document.forms[1][$tFields[$a]].value = '$' + _N(order_total, 2);
    	_CalculateTotal();
    }

    As for the NaN grand total. This is because not all of the total boxes have a total/value when the grand total is being calculated. This can be fixed a few different ways. The easiest way is to have a default value in those total boxes. Since those inputs have an empty string, it fails to pull a total to add and thus the result is indeed not a number (aka NaN).
    But since it's also a best practice to have the code check and correct all issues, I've modified my grand total function as well:
    Code:
    function _CalculateTotal() {
    	var $grandTotal = 0;
    	var $f = document.forms[1];
    	for(var $i = 0; $i < $itemCount; $i++) {
    		var $tmpTotal = parseFloat($f[$tFields[$i]].value.replace(/[^0-9.]/g, ""));
    		$grandTotal = (isNaN($tmpTotal)) ? ($grandTotal) + 0 : ($grandTotal) + $tmpTotal;
    	}
    	document.getElementById("grandTotal").innerHTML = _N($grandTotal, 2);
    }
    Though I still feel there should be a default value in those total boxes.

  9. #24
    Join Date
    Apr 2014
    Posts
    36
    Now we are getting somewhere thanks for this. I have a few questions.
    1. Can I have the no tooling selected for all 3 items ? I attempted to change the value for tooling to tooling2 and tooling3 but that didn't do it.
    2. You mentioned something about passing the grandTotal variable via .php to email not an option.. how do you suggest going about sending the values to an email where I can pick up the grandTotal amount?
    Thanks

  10. #25
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    So, another thing I noticed in my code that doesn't coincide well with your actual page is the tooling options. The ability to have separate tooling options (and thus tooling calculations) per item can be added into the function, however I was under the impression you were headed in the direction of having 1 set of tooling options and the only duplicated elements on the form would be the length and width boxes (one set per item). This is currently how the _Calculate() function operates. So depending on how you are going to do this in the form, I can either modify the javascript, or the form itself will have to be changed to only show 1 set of tooling options.

    And regarding your second question, currently the grand total is not being put into an <input> element in the form. This means when the form is submitted the grand total is not passed to PHP. Again, I strongly feel that while it's important to preform these totaling calculations on the user's end (javascript) to allow them to see their totals, the actual totals to be send to an email or database should be calculated in PHP. The same way you calculate these things in javascript, you would do this on the PHP side of things, reading the length and width of all submitted fields as well as the tooling option choice.

    From a very basic standpoint though, you could simply use PHP to add the two submitted totals together. I have no idea what your PHP looks like, but you'd be doing something like this:
    PHP Code:
    $totalcost = (isset($_POST["totalcost"])) ? (int)preg_replace("/[^0-9.]/"""$_POST["totalcost"]) : 0;
    $totalcost2 = (isset($_POST["totalcost2"])) ? (int)preg_replace("/[^0-9.]/"""$_POST["totalcost2"]) : 0;

    $grandTotal $totalcost $totalcost2
    But keep in mind that's a very basic way of handling this. Realistically you would actually just take the width, length and tooling option values into your PHP and then recalculate the totals. This would give you the most accurate and reliable totals.

  11. #26
    Join Date
    Apr 2014
    Posts
    36
    and then $grandTotal could be passed to email from php rather then form?

    I will post up my new requirements shorty, I want to fully understand them so I don't waste your time.
    Thx

  12. #27
    Join Date
    Apr 2014
    Posts
    36
    Ok I think I have it all defined now.. when you get time could you modify the code so that this happens.

    On from quantity drop down 1 - 3 (items max)
    width / height
    no tooling / tooling

    totalcost

    grand total

    IF quantity of 2 is selected an extra width and height and total cost2 field appears above grand total. *whatever was selected for tooling in item 1 will be the same.

    IF quantity of 3 is selected an same thing would happen but would show 2 height, width and total costs above grand total.

    so potentially the form could look like this

    quantity 3 selected

    item 1 - width / height
    no tooling / tooling
    total cost

    item 2 - width / height
    totalcost2

    item 3 width / height
    totalcost 3

    grand total

    thanks again.

  13. #28
    Join Date
    Apr 2014
    Posts
    36
    one more thing to add.. would be good if there was a quantity button beside items numbers in case someone wants to order 2 items as an example with the same width and height

  14. #29
    Join Date
    Apr 2014
    Posts
    36
    Hello, any chance you can come up with the new code next week based on last 2 posts?
    Thx

  15. #30
    Join Date
    Mar 2005
    Location
    Behind you...
    Posts
    1,033
    If 'the next week' means one week from today then I'm certain I can have some new code by then.

    Though I do feel I should mention, I don't want you or anyone to get the wrong idea. Generally post like this are things to avoid as it's essentially free, non-contracted work on sites that I have no affiliation or stake in (aka Freelance). Most things I answer on here are fairly simple things that I can deal with in a matter of minutes. And occasionally things take a bit more effort as the actual issues are more complex. But I post here because I enjoy web development and certainly don't mind helping those willing to learn in this industry.

    That being said, your issue here isn't complex but rather, time consuming, as it's a full solution or rather an effective replacement of something that already existed. Again, I don't mind helping but please keep in mind this is me in my free time offering what knowledge and assistance I can to those who could benefit from it. I'll try to take time today to dig into your order form, and I'll likely complete it today.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles