So I have this project I am doing for my Comp. Science class and I have had no issues with the other two assignments. This program I am writing is designed to take orders (it doesnt record them, it just keeps a running total and outputs a total price at the end). The user has to input a valid size and a valid flavor (cant use radio buttons). If these conditions are met, the program prompts the user if they want to add another item to the order. If they then enter 'y', the while statement continues to run, compounding on the total price each time until it falls out of this loop and outputs the final total.

I think my issue lies entirely in nesting... Right now it doesnt work after adding the flavor validation

So I have this project I am doing for my Comp. Science class and I have had no issues with the other two assignments. This program I am writing is designed to take orders (it doesnt record them, it just keeps a running total and outputs a total price at the end). The user has to input a valid size and a valid flavor (cant use radio buttons). If these conditions are met, the program prompts the user if they want to add another item to the order. If they then enter 'y', the while statement continues to run, compounding on the total price each time until it falls out of this loop and outputs the final total.

I think my issue lies entirely in nesting... Right now it doesnt work after adding the flavor validation

In the first part, you have curly braces in the wrong spot (see below). To help with these and other problems specific to JS, I recommend following Douglas Crockford's formatting (http://javascript.crockford.com/code.html). Note that with JS, not following these specific conventions will create very hard to find bugs due to automatic semi-colon insertion.

Also never, NEVER use '=='. ALWAYS use '==='. If your instructor says to use '==' call him/her out for the idiot he/she is. In JS, type coercion is problematic, but occurs automatically with '=='. The "triple equals" was specifically added to the language to work around this well-known issue.

I normally don't "give answers", but you seemed to have put in some effort, so let me walk you through this (note that I haven't tested the code):

Code:

//The outer 'function' ensures our code is contained and not in the global variable space.
(function () {
//note: all the variable declarations are comma separated
//and only the final one ends in a semi-colon
var total = 0, //we'll be counting the total in cents (no decimal)
order_temp = {}, //individual order
i, //iterator
len, //length of object
order = [], //this holds their final order
options = { //this object is the stuff they can choose from. Ideally, it would be better designed. I leave that to you.
flavor: ["cherry", "lime", "watermelon", "grape", "orange"],
size: ["small", "medium", "large"]
};
//this function returns true if an item is in an array
//I've done this to reduce code later
//this is necessary because the 'in' keyword is bugged for arrays
//There's an OOP way that's a little better, but this is easier to understand
var contains_p = function (item, list) {
var len = list.length,
i = 0;
exists = false;
for (i; i < len; i += 1) {
if (item === list[i]) {
exists = true;
break;
}
}
return exists;
};
//the true means that the loop will continue until 'break' is called
while (true) {
//the main idea here is to get the correct order stuff.
order_temp.flavor = prompt("We offer: \nCherry\nLime\nWatermelon\nGrape\nOrange\nPlease enter your choice: ");
order_temp.size = prompt("Pick your size (small, medium, or large): ");
//check if both items are valid, if so, add the item to your list
//if not, tell them and then start over.
if (contains_p(order_temp.flavor, options.flavor) && contains_p(order_temp.size, options.size)) {
alert("your item has been added");
//you don't mention pricing, but it should be in the options object above and added here
//to the order_temp.price variable
order.push(order_temp);
} else {
alert("Part of your order could not be handled. Please try again.");
continue; //forces the loop to jump to the top and go again.
}
if ("y" !== prompt("Add another item y/n? ")) {
break;
}
}
//get the total price
len = order.length;
for (i = 0; i < len; i += 1) {
total += order[i].price;
}
//convert the total from cents to dollars and cents
//floor is needed because floating point numbers round
//the modulus gets the remainder (in this case, the cents)
alert("Your total is $" + Math.floor(total / 100) + "." + (total % 100);
}());

In the first part, you have curly braces in the wrong spot (see below). To help with these and other problems specific to JS, I recommend following Douglas Crockford's formatting (http://javascript.crockford.com/code.html). Note that with JS, not following these specific conventions will create very hard to find bugs due to automatic semi-colon insertion.

Also never, NEVER use '=='. ALWAYS use '==='. If your instructor says to use '==' call him/her out for the idiot he/she is. In JS, type coercion is problematic, but occurs automatically with '=='. The "triple equals" was specifically added to the language to work around this well-known issue.

I normally don't "give answers", but you seemed to have put in some effort, so let me walk you through this (note that I haven't tested the code):

Code:

//The outer 'function' ensures our code is contained and not in the global variable space.
(function () {
//note: all the variable declarations are comma separated
//and only the final one ends in a semi-colon
var total = 0, //we'll be counting the total in cents (no decimal)
order_temp = {}, //individual order
i, //iterator
len, //length of object
order = [], //this holds their final order
options = { //this object is the stuff they can choose from. Ideally, it would be better designed. I leave that to you.
flavor: ["cherry", "lime", "watermelon", "grape", "orange"],
size: ["small", "medium", "large"]
};
//this function returns true if an item is in an array
//I've done this to reduce code later
//this is necessary because the 'in' keyword is bugged for arrays
//There's an OOP way that's a little better, but this is easier to understand
var contains_p = function (item, list) {
var len = list.length,
i = 0;
exists = false;
for (i; i < len; i += 1) {
if (item === list[i]) {
exists = true;
break;
}
}
return exists;
};
//the true means that the loop will continue until 'break' is called
while (true) {
//the main idea here is to get the correct order stuff.
order_temp.flavor = prompt("We offer: \nCherry\nLime\nWatermelon\nGrape\nOrange\nPlease enter your choice: ");
order_temp.size = prompt("Pick your size (small, medium, or large): ");
//check if both items are valid, if so, add the item to your list
//if not, tell them and then start over.
if (contains_p(order_temp.flavor, options.flavor) && contains_p(order_temp.size, options.size)) {
alert("your item has been added");
//you don't mention pricing, but it should be in the options object above and added here
//to the order_temp.price variable
order.push(order_temp);
} else {
alert("Part of your order could not be handled. Please try again.");
continue; //forces the loop to jump to the top and go again.
}
if ("y" !== prompt("Add another item y/n? ")) {
break;
}
}
//get the total price
len = order.length;
for (i = 0; i < len; i += 1) {
total += order[i].price;
}
//convert the total from cents to dollars and cents
//floor is needed because floating point numbers round
//the modulus gets the remainder (in this case, the cents)
alert("Your total is $" + Math.floor(total / 100) + "." + (total % 100);
}());

Hajile,

While I appreciate the script youve provided, I dont believe my teacher wanted us to go into that level of detail. Could we perhaps analyze the 'broken' variant of my script and mitigate the problems?
Looking at the article you provided at the moment

My code isn't much bigger than your own (especially when yours is formatted correctly). A major difference is that mine is easy to change when the number of items, kind of items or price changes. Even if your teacher didn't demand that kind of detail, it is what's required in the real world of programming (that's what you're really studying for). Teach yourself to do that early and you won't have to get kicked so hard when you first start work on real projects.

I'll go over what's specifically broken in your code, but I think you should look over and understand what my code is doing.

A word on your broken one. It's trying to check the user input and keep asking for input until it gets something acceptable. The answer here is a do..while loop. This loop acts like a while loop except that it does the first iteration before checking.

Code:

do {
//stuff
//more stuff
} while (<condition>); //note the semicolon that should be used in this form

You brought up some interesting points Hajile, also, I really do appreciate the critique and revised version of the code. I will try the fixed version and let you know (of course I am going to manually edit my version so I get a better understanding of what needs to be happening.Edited by raidmaxGuy - 11/14/13 at 8:44am

Just throwing in another reason not to use toFixed(): Its behaviour is not consistent across browsers. Try 0.045.toFixed(2) in IE and Firefox and you'll get different results. I know an insurance company that uses toFixed all over the place when calculating online premiums, and you can get a different premium in different browsers (only 1 or 2 cents, but it's still not good). I would have thought that the repeated use of parseFloat() (since toFixed returns a string) would have also raised a flag that they were probably using the wrong method, but apparently not.