Results 1 to 7 of 7

Thread: help modifying a script that calculates order form totals

  1. #1
    Join Date
    May 2005
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default help modifying a script that calculates order form totals

    I'm having difficulty modifying a free script and am hoping someone can help me out! I want to add subtotal and discount calculations to the script posted below.

    I am trying to add the following conditions and I want the fields order_subtotal and order_discount to do a running total, just like the original total field. I'm pretty new to this and I think I am missing something really obvious... Thanks for any help!

    My attempt is listed at bottom of post.

    The form is located at:

    http://www.gotbusch.com/dev/dqp/orderinfo/order.html

    The original unmodified script is as follows:

    <script language="JavaScript" type="text/javascript">
    <!--

    /* This script is Copyright (c) Paul McFedries and
    Logophilia Limited (http://www.mcfedries.com/).
    Permission is granted to use this script as long as
    this Copyright notice remains in place.*/

    function CalculateTotal(frm) {
    var order_total = 0

    // Run through all the form fields
    for (var i=0; i < frm.elements.length; ++i) {

    // Get the current field
    form_field = frm.elements[i]

    // Get the field's name
    form_name = form_field.name

    // Is it a "product" field?
    if (form_name.substring(0,4) == "PROD") {

    // If so, extract the price from the name
    item_price = parseFloat(form_name.substring(form_name.lastIndexOf("_") + 1))

    // Get the quantity
    item_quantity = parseInt(form_field.value)

    // Update the order total
    if (item_quantity >= 0) {
    order_total += item_quantity * item_price
    }
    }
    }

    // Display the total rounded to two decimal places
    frm.TOTAL.value = round_decimals(order_total, 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
    }

    //-->
    </script>
    =======================================================

    here are my proposed additions that do not work...

    var order_subtotal = 0
    var order_discount = 0
    var order_total = 0

    // Update the order subtotal
    if (item_quantity >= 0) {
    order_subtotal += item_quantity * item_price


    if (order_subtotal >= 100) {
    order_discount += item_quantity * item_price * 0.20
    }
    else
    if (order_subtotal >= 30) {
    order_discount += item_quantity * item_price * 0.10
    }

    else
    if (order_subtotal < 30) {
    order_discount += item_quantity * item_price}


    if (order_subtotal >= 100) {
    order_total += item_quantity * item_price * 0.80
    }
    else
    if (order_subtotal >= 30) {
    order_total += item_quantity * item_price * 0.90
    }

    else
    if (order_subtotal < 30) {
    order_total += item_quantity * item_price
    }


    // Display the total rounded to two decimal places
    frm.subtotal.value = round_decimals(order_subtotal, 2)

    // Display the total rounded to two decimal places
    frm.discount.value = round_decimals(order_discount, 2)

  2. #2
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by 2njenn
    The original unmodified script is as follows:
    When posting code, please use the [code&#93; and [/code&#93;, or [html&#93; and [/html&#93;, meta tags. These preserve formatting and make things much easier to read.

    <script language="JavaScript" type="text/javascript">
    <!--
    Just

    HTML Code:
    <script type="text/javascript">
    will do. You can remove the //--> at the end, too.

    Before I continue, I'd like to say I dislike this script immensely. Calculations are performed using floating point arithmetic, which should always be avoided when dealing with money, it forces a ridiculous naming scheme, and it dumps variables into the global namespace. But, for the purposes of expediency, I've simply updated CalculateTotal, below.

    Code:
    function CalculateTotal(form) {
      var subTotal = 0,
          discount, field, fieldName, price, quantity, total;
    
      for(var i = 0, n = form.elements.length; i < n; ++i) {
        field = form.elements[i];
        fieldName = field.name;
    
        if('PROD' == fieldName.substring(0, 4)) {
          price = parseFloat(fieldName.substring(fieldName.lastIndexOf("_") + 1));
          quantity = parseInt(field.value, 10);
    
          if(quantity) {
            subTotal += quantity * price;
          }
        }
      }
      form.elements.TOTAL.value = round_decimals(subTotal, 2);
    
      if(30 <= subTotal) {
        discount = 0.1;
      } else if(100 <= subTotal) {
        discount = 0.2;
      } else {
        discount = 0;
      }
      discount *= subTotal;
      form.elements.discount.value = round_decimals(discount, 2);
    
      form.elements.FTOTAL.value = round_decimals(subTotal - discount, 2);
    }
    I might post a completely different alternative at some point, but not now.

    By the way, your CSS is completely broken. Run it through the CSS validator provided by the W3C. Your markup is also in need of revision, but fixing your style sheet is probably more important for now.

    Mike

  3. #3
    Join Date
    May 2005
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Hi Mike,

    I can't thank you enough for your generous assistance with the script and for providing your insight about the script itself. I really appreciate that you took the time to go above and beyond answering my question.

    As well, thank you for your other tips/suggestions such as the posting code format and letting me know that my CSS/markup is broken. This site is the first time that I've used CSS so I appreciate the link to the W3. Yikes! The W3 checker had an issue with the whole thing... I'll see what I can do about understanding the problems and correcting them.

    Thanks again!!
    2nJenn

  4. #4
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by 2njenn
    Yikes! The W3 checker had an issue with the whole thing...
    There are some fundamental problems. The first is that you have HTML in your style sheet. Like .js files should only contain ECMAScript/Javascript, .css files should only contain CSS rules and statements; begin by removing the style starting and closing tags, and the SGML comment delimiters (<!-- -->).

    The next thing is to check that blocks (regions surrounded by curly braces) start and end properly. For instance, the rule with the body selector at the start doesn't close properly because you've missed the closing curly brace (}).

    I'll see what I can do about understanding the problems and correcting them.
    Some of the errors will be due to unknown properties, such as the scrollbar properties you've used. These proprietary properties aren't part of any standard, so the validator will complain. You might have the same problem if you use proprietary values, too (like Microsoft's hand). If these warnings are too distracting, you can always comment them out temporarily using C-style (/* ... */) comments.

    If you can't decipher a particular error message, by all means, post a follow-up here and I'll help you out.

    Mike

  5. #5
    Join Date
    May 2005
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Well, it seems I require more help with this script.
    I have been asked to add an option where if a customer so chooses, they can have a hard copy of their purchase at an extra cost. The simplest way on the actual form was to add a checkbox option at the bottom of the form, however I am having trouble getting the form to calculate the correct totals.

    Thanks in advance for any assistance that can be offered.

    http://www.gotbusch.com/dev/dqp/orderinfo/order2.html

    Code:
    /* This script is Copyright (c) Paul McFedries and 
    Logophilia Limited (http://www.mcfedries.com/).
    Permission is granted to use this script as long as 
    this Copyright notice remains in place.*/
    
    //Note: script was modified with help from member: MWinter at http://www.dynamicdrive.com/forums/
    
    function CalculateTotal(form) {
      var subTotal = 0,
          discount, field, fieldName, price, quantity, hardcopy, total;
    
      for(var i = 0, n = form.elements.length; i < n; ++i) {
        field = form.elements[i];
        fieldName = field.name;
    
        if('PROD' == fieldName.substring(0, 4)) {
          price = parseFloat(fieldName.substring(fieldName.lastIndexOf("_") + 1));
          quantity = parseInt(field.value, 10);
    
          if(quantity) {
            subTotal += quantity * price;
          }
        }
      }
      form.elements.TOTAL.value = round_decimals(subTotal, 2);
    
      if(30 <= subTotal) {
        discount = 0.1;
      } else if(100 <= subTotal) {
        discount = 0.2;
      } else {
        discount = 0;
      }
      discount *= subTotal;
      form.elements.discount.value = round_decimals(discount, 2);
    
      form.elements.hardcopy.value = round_decimals(hardcopy, 2);
    
    if(quantity) {
    	hardcopy += (quantity * price) + (quantity * 7);
          }
    
    if(30 <= subTotal) {
        discount = 0.1;
      } else if(100 <= subTotal) {
        discount = 0.2;
      } else {
        discount = 0;
      }
      discount *= subTotal;
    
      form.elements.FTOTAL.value = round_decimals(subTotal - discount + hardcopy, 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
    }

  6. #6
    Join Date
    Dec 2004
    Location
    UK
    Posts
    2,358
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Quote Originally Posted by 2njenn
    I have been asked to add an option where if a customer so chooses, they can have a hard copy of their purchase at an extra cost. The simplest way on the actual form was to add a checkbox option at the bottom of the form, however I am having trouble getting the form to calculate the correct totals.
    You need to update the hardcopy amount in the loop, as that's where quantity changes. I've taken a slightly different route, though:

    Code:
    function CalculateTotal(form) {
      var subTotal        = 0,
          numberOfScripts = 0,
          discount, field, fieldName, hardCopy, price, quantity, total;
    
      for(var i = 0, n = form.elements.length; i < n; ++i) {
        field = form.elements[i&#93;;
        fieldName = field.name;
    
        if('PROD' == fieldName.substring(0, 4)) {
          price = parseFloat(fieldName.substring(fieldName.lastIndexOf("_") + 1));
          quantity = parseInt(field.value, 10);
    
          if(quantity) {
            subTotal += quantity * price;
    
            /* Keep a running total of the
             * number of scripts ordered.
             */
            numberOfScripts += quantity;
          }
        }
      }
      form.elements.TOTAL.value = round_decimals(subTotal, 2);
    
      if(30 <= subTotal) {
        discount = 0.1;
      } else if(100 <= subTotal) {
        discount = 0.2;
      } else {
        discount = 0;
      }
      discount *= subTotal;
      form.elements.discount.value = round_decimals(discount, 2);
    
      /* If the visitor has requested hard copies,
       * determine how much more the order will
       * cost at $7 per script.
       */
      hardCopy = form.elements.checkbox.checked
               ? numberOfScripts * 7
               : 0;
    
      /* Output this excess... */
      form.elements.hardcopy.value = round_decimals(hardCopy, 2);
    
      /* ...and add it to the final total. */
      form.elements.FTOTAL.value = round_decimals(subTotal - discount + hardcopy, 2);
    }
    I've included comments were I've made changes.

    Hope that helps; I haven't checked.
    Mike

  7. #7
    Join Date
    May 2005
    Posts
    5
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Hi Mike,

    As usual, your help and work is awesome!!
    Thanks for adding in the comments to the script so I can follow it easier... I still have lots to learn This site was done pro-bono, so I really appreciate your assistance.

    Thanks again!
    Jenn

Bookmarks

Posting Permissions

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