PDA

View Full Version : help modifying a script that calculates order form totals



2njenn
05-24-2005, 11:55 PM
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)

mwinter
05-25-2005, 08:15 PM
The original unmodified script is as follows:When posting code, please use the
<script language="JavaScript" type="text/javascript">
<!--[/quote]Just


<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 (http://jigsaw.w3.org/css-validator/) provided by the W3C (http://www.w3.org/). Your markup is also in need of revision, but fixing your style sheet is probably more important for now.

Mike

2njenn
05-26-2005, 12:25 AM
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

mwinter
05-26-2005, 12:32 PM
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

2njenn
11-17-2005, 11:36 PM
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



/* 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
}

mwinter
11-18-2005, 09:58 PM
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:



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

2njenn
11-19-2005, 06:03 PM
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