Many companies normally charge a shipping and handling charge for purchases. Create a Web page that allows a user to enter a purchase price into a text box and includes a JavaScript function that calculates shipping and handling. Add functionality to the script that adds a minimum shipping and handling charge of $1.50 for any purchase that is less than or equal to $25.00. For any orders over $25.00, add 10% to the total purchase price for shipping and handling, but do not include the $1.50 minimum shipping and handling charge. The formula for calculating a percentage is price * percent / 100. For example, the formula for calculating 10% of a $50.00 purchase price is 50 * 10 / 100, which results in a shipping and handling charge of $5.00. After you determine the total cost of the order (purchase plus shipping and handling), display it in an alert dialog box. Save the document as CalcShipping.html.
Where am I going wrong?
Here is my code:
Code:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
<title>Calcuate Shipping</title>
<style>
body {
text-align: center;
font-family: sans-serif;
}
ul {
list-style-type: none;
}
ul li {
padding-bottom: 6px;
}
form label {
display: inline-block;
text-align: right;
width: 150px;
}
</style>
<script>
function calcShipping() {
// Declare variables.
var price = document.getElementById("price"),
shipping = document.getElementById
("shipping"),
total = document.getElementById("total"),
output;
// First, get the price. The value of a text input
is a string.
// Before we can do math, covert the string to a
number
// using parseFloat().
price = parseFloat(price.value);
// Next we check to see if the price is greater
than zero and
// less than or equal to $25.00.
// If it is, we put $1.50 in the shipping field,
add $1.50 to
// the price and display it in the total field.
// The return keyword tells the program to end.
// toFixed makes sure it displays two decimal
places, even if
// they're zeros.
if (price > 0 && price <= 25) {
shipping.value = "$1.50";
output = price + 1.50;
total.value = "$" + (output).toFixed(2);
return;
}
// Next, if the price is greater than $25.00 we
set the
// shipping cost as 10% of the price, show the
shipping,
// and add the price and shipping together and
show it
// in the total.
// The answer is rounded to two decimal places.
if (price > 25) {
output = (Math.round(price * 0.1) * 100) / 100;
shipping.value = "$" + output.toFixed(2);
total.value = "$" + (price + output).toFixed(2);
}
}
</script>
</head>
<body>
<form>
<ul>
<li>
<h1>Calculate Shipping</h1>
</li>
<li>
<label for="price">Purchase Price:</label>
<input type="text" id="price" size="10">
</li>
<li>
<label for="shipping">Shipping:</label>
<input type="text" id="shipping" size="10">
</li>
<li>
<input type="button" value="Calculate
Shipping"
onclick="calcShipping();">
<input type="reset" value="Reset">
</li>
<li>
<label for="total">Total:</label>
<input type="text" id="total" size="10">
</li>
</ul>
</form>
</body>
</html>
Does not work in any version of IE before IE9. Only works in IE9 with a <!DOCTYPE>, in other words HTML5.
It is obvious to anyone who knows that Internet Explorer generates additional variables to reference every id and name within the page so as to effectively run the equivalent of:
id = document.getElementById(id);
before any of your code runs whether you want it to or not - and keeps both pointing to the same thing so that redefining one redefines the other - so that any attempt on your part to use variables as in your example will crash because at least one variable no longer contains what you expect it to.
The only way to get the code to work in those browsers without using different names is to wrap the whole code inside a function so that the global variables do not interfere with the ones you want to create.
So Airblader either always wraps the code inside functions so that it has different scope OR doesn't test in IE and so doesn't see how such code breaks in that browser.
I agree that it is best to avoid the entire problem by using different names for your variables to what you use for the ids they refer to (although I also agree that giving them the same names would have be preferable if it were not for this problem with IE).
But having said all of that (to which I agree, on all points).
It actually does *NOT* hurt to do
Code:
var price = document.getElementById("price");
even in MSIE, because all you are doing is re-defining the global variable price to be the same thing that MSIE has already defined it to be.
So this is the sole exception to Philip's rule: A variable name that references an element with the same id as the variable name (and is used only for that purpose).
But since this exception is so easy to violate (e.g., re-purpose a variable without realizing the implications), Philip's rule is a good one.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
But since this exception is so easy to violate (e.g., re-purpose a variable without realizing the implications), Philip's rule is a good one.
Thank you! I see the matter as simple common sense. Easy rule - Do not duplicate names/ids/Javascript variables. Period. There are many millions of words and their abbreviations, they are all entirely free, so why use the same one twice? Likewise I would advise do not use the same name for both a Javascript global variable and a local variable - it will work, but is fraught with danger and potential confusion. There is simply no need to do such a risky thing.
Likewise IMO there is no sense in using the same (duplicated) name for a local variable but within a different function. Just bound to lead to confusion, especially when you return to the code after a time.
And I always try to make my names/ids meaningful = e.g. "unitPrice" rather than "box2".
var price = document.getElementById("price"); // yes, that works, but then leads to
document.getElementById("price").value = price; // which I think is potentially confusing. The two prices are completely different. As I say, no possible need for it!
Quote:
Originally Posted by felgall
So Airblader either always wraps the code inside functions so that it has different scope OR doesn't test in IE and so doesn't see how such code breaks in that browser.
That just about sums it up.
FWIIW I use IE9 for preference, although I have Chrome (second choice) and Firefox (a distant third choice). But that is simply my preferences. Some people dislike IE, perhaps for reasons which are no longer applicable. I admit that I am prejudiced in favour of Microsoft - over the years Bill Gates has made me a lot of money.
__________________
All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.
Last edited by Philip M; 02-19-2013 at 09:46 PM..
Reason: Typos
As a matter of fact, I do use my own scopes. Most of my code is in classes which, of course, don't resemble any DOM element names. And since I wouldn't think about putting references to DOM elements into the global scope, I'm safe.
However, I was in fact not aware of that IE quirk – and when I do test in IE, I only test if it works, I don't check any warnings or whatever (does it even throw warnings?). Which I don't do often lately because I write Cordova apps that I only have to test in webkit browsers.
In any case, my variable names rarely ever have the same name as my DOM elements, simply because my DOM ids/classes usually carry a prefix or whatever. So I wouldn't usually run into this problem even if I didn't use my own scopes.
Quote:
And I always try to make my names/ids meaningful = e.g. "unitPrice" rather than "box2
"unitPrice" was my example from a previous thread – your example this thread was "pr". I don't call that meaningful.
Quote:
Likewise IMO there is no sense in using the same (duplicated) name for a local variable but within a different function.
There is no way such a rule can be followed in a project growing past a certain size. So according to you, this is bad code (besides using global functions) because two functions use the variable name 'price'? I just want to make sure I'm understanding you correctly.
Code:
function getPrice () {
return /* whatever */;
}
function getTaxes () {
var price = getPrice(),
taxes = TAXES_FACTOR * price;
return taxes;
}
function displayPrice () {
var price = getPrice();
setOutputElementOrWhatever( price );
}
Or did you mean two different variables in different functions having the same name? That would make more sense to me, although I still think it's impractical in bigger projects. I do agree, though, that it might be an indicator for not very precise naming – which really is something that one should fix.
Edit:
Quote:
Likewise I would advise do not use the same name for both a Javascript global variable and a local variable
At least on that I fully agree.
Last edited by Airblader; 02-20-2013 at 05:26 AM..
function getPrice () {
return /* whatever */;
}
function getTaxes () {
var price = getPrice(),
taxes = TAXES_FACTOR * price;
return taxes;
}
function displayPrice () {
var price = getPrice();
setOutputElementOrWhatever( price );
}
Or did you mean two different variables in different functions having the same name? That would make more sense to me, although I still think it's impractical in bigger projects. I do agree, though, that it might be an indicator for not very precise naming – which really is something that one should fix.
If "price" is the same thing in both functions, then that is fine. But not if price in function1 is price before tax, and price in function 2 is price after tax, or whatever.
Duplication may or may not be impractical in bigger projects. I would not know, as I do not work on bigger projects. I just (try to) follow the rules I have developed over very many years of experience. Your mileage may differ.
__________________
All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.
Duplication may or may not be impractical in bigger projects.
Okay, I absolutely agree. If variables describe different things, they generally should have different names. Although I doubt it will always work – it comes down to some sort of common sense.
It's like with the granularity of functions. It's really hard to put into words (and rules) when a function is "too big".
Okay, I absolutely agree. If variables describe different things, they generally should have different names. Although I doubt it will always work – it comes down to some sort of common sense.
It's like with the granularity of functions. It's really hard to put into words (and rules) when a function is "too big".
Yes, that is what I said.
__________________
All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.