JavaScript Addition Calculator Help

Good evening guys and girls! (At least it’s evening time where I am in the world.)

I’m pretty good at creating JS scripts that use inline JS however, this is totally wrong, evil and can sometimes bring about an apocalypse! :eek: I don’t want any of this :frowning:

I’ve been learning Unobtrusive DOM Scripting and all that lovely stuff :slight_smile: But I still sometimes struggle with creating unobtrusive scripts!

I want a simple (and I know how simple it is because I know a fair bit of beginners JS and this is super simple stuff, especially for you masters of the language!) script that adds two numeric values together which provide a total. So simply put: 1 + 1 = 2.

Here is the working, evil script I currently have (and feel free to give it the evil eye, I do!):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>JavaScript Calculator: Addition</title>
		<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
		<script type="text/javascript">
			function fnTotal(a,b) {
				alert(fnAdd(a,b));
			}

			function fnAdd(c,d) {
				return(parseInt(c)+parseInt(d));
			}
		</script>
	</head>

	<body>
		<div id="wrapper">
			<h1>JavaScript Calculator: Addition</h1>

			<p>Use the JavaScript calculator below to add two numbers together from the two text boxes.</p>

			<input type="text" name="firstNum">
			<input type="text" name="secondNum">
			<input type=button value="Add" onClick="fnTotal(firstNum.value,secondNum.value)">
		</div>
	</body>
</html>

That works (at least in IE8 and FF3, so I assume, although I shouldn’t, that it works in most other modern browsers) but it isn’t what I want. It’s totally wrong and bad and -whacks it- :mad:

This is the new and lovely addition.html I have:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>JavaScript Calculator: Addition</title>
		<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
		<script type="text/javascript" src="addition.js"></script>
	</head>

	<body>
		<div id="wrapper">
			<h1>JavaScript Calculator: Addition</h1>

			<p>Use the JavaScript calculator below to add two numbers together from the two text boxes.</p>

				<input type="text" id="firstNum" name="firstNum">
				<input type="text" id="secondNum" name="secondNum">
				<input type="button" value="Add" id="add">
		</div>
	</body>
</html>

And this is the weird external addition.js JavaScript file that seems to be giving me some problems!

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function addition() {
	if (!document.getElementById) return false;

	var c = document.getElementById("firstNum");
	var d = document.getElementById("secondNum");
	var add = document.getElementById("add");

	add.onclick = function() {
		// return (parseInt(c) + parseInt(d));
		// alert(parseInt(c) + parseInt(d));
		// Your Solution Here? Pretty Please! :D
	}
}

addLoadEvent(addition);

I’ve checked in Dreamweaver CS3 to see if there are any problems - Nope. I don’t get any errors in IE8 or in FF3 Error Console. When I type in 1 in the first text box and 1 in the second text box and then click on the Add button I just receive NaN. I know NaN = Not a Number but I can’t figure out what to do to fix it.

I’ve commented out the first two statements that begin with return and alert. And below that you can see a place where I’d love to fit your working solution in :stuck_out_tongue: :smiley: I’d like an explanation please too! Or if I’m very close to a solution, I obviously need help in seeing where I’ve made an error :nono:

Help, pretty please? :slight_smile:

Andrew Cooper

You need to do a parseInt on c.value and d.value, not on c and d

So:


add.onclick = function() {
   alert(parseInt(c.value) + parseInt(d.value));
   return (parseInt(c.value) + parseInt(d.value));
}

Also, if you use return in a function, the rest of that function is not executed. So you first need to do alert()s and then return, not the other way around, because that way you’ll never actually see your alerts :slight_smile:

Oh god…I was actually thinking it might have something to do with needing a .value somewhere! But I just didn’t do it…:nono: But thank you so much! That has been wracking my brain for so damn long!

And thanks for the information on using return and alert in a function together. It was just for testing because it’s what we use to do in college. I’ve changed the script to the following.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>JavaScript Calculator: Addition</title>
		<link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
		<script type="text/javascript" src="addition.js"></script>
	</head>

	<body>
		<div id="wrapper">
			<h1>JavaScript Calculator: Addition</h1>

			<p>Use the JavaScript calculator below to add two numbers together from the two text boxes.</p>

				<input type="text" id="firstNum" name="firstNum">
				<input type="text" id="secondNum" name="secondNum">
				<input type="button" value="Add" id="add">

			<p id="answer"></p>
		</div>
	</body>
</html>

And the amended external JavaScript file:

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function addition() {
	if (!document.getElementById) return false;

	var c = document.getElementById("firstNum");
	var d = document.getElementById("secondNum");
	var add = document.getElementById("add");
	var answer = document.getElementById("answer");

	add.onclick = function() {
		answer.innerHTML = (parseInt(c.value) + parseInt(d.value));
	}
}

addLoadEvent(addition);

Any suggestions or ideas on how to improve any of the HTML or JS code at all (to make it cleaner or more efficient or something)? I’d like to expand on this by eventually creating a JS Calculator performing simple mathematical functions like addition, subtraction, multiplication, and division at first and then perhaps create some functions for it to do some scientific and statistical calculations. So we’ll see where that goes. :slight_smile:

Thanks for the prompt reply with the great explanation and solution! :slight_smile: I can’t thank you enough! :smiley:

Andrew Cooper

Move the “var c” and “var d” and “var answer” lines into the onclick event, and use the radix parameter with parseInt as well, and you should be right.


add.onclick = function() {
    var c = document.getElementById("firstNum");
    var d = document.getElementById("secondNum");
    var answer = document.getElementById("answer");
    answer.innerHTML = (parseInt(c.value, 10) + parseInt(d.value, 10));
}

Alternatively, you can use the Number object instead.


...
answer.innerHTML = (Number(c.value) + Number(d.value));

But what if I’m adding a function for subtraction, multiplication, and division? Couldn’t I do the following?

function calculator() {
	if (!document.getElementById) return false;

	var c = document.getElementById("firstNum");
	var d = document.getElementById("secondNum");
	var add = document.getElementById("add");
	var subtract = document.getElementById("subtract");
	var multiply = document.getElementById("multiply");
	var divide = document.getElementById("divide");
	var answer = document.getElementById("answer");

	add.onclick = function() {
		answer.innerHTML = (parseInt(c.value, 10) + parseInt(d.value, 10));
	}

	subtract.onclick = function() {
		answer.innerHTML = (parseInt(c.value, 10) - parseInt(d.value, 10));
	}

	multiply.onclick = function() {
		answer.innerHTML = (parseInt(c.value, 10) * parseInt(d.value, 10));
	}

	divide.onclick = function() {
		answer.innerHTML = (parseInt(c.value, 10) / parseInt(d.value, 10));
	}
}

Wouldn’t that be more efficient by not repeating all of the variable declarations? Or is there a particular reason as to why you suggested placing all the variable declarations inside the add.onclick function? Otherwise it’s an awful lot of repetition isn’t it?

I understand why you suggested to place the radix parameter too! Thanks! I should have thought about that but I’ll be honest and say I didn’t really know about it until you suggested it. :blush: Thanks for teaching me something new though! :smiley:

Heh, didn’t know about this either! What’s the difference between parseInt and Number then? I mean, I can see that by using the Number object you don’t need to include the radix parameter? Or is that wrong? What would you suggest / prefer? Number or parseInt? Or are they both as good as each other?

Thanks a lot to both of you ScallioXTX and pmw57 :slight_smile:

Andrew Cooper

Then you could either pass them to the function, or perhaps more appropriately here, have the function reach out to a global register. The intention is to limit the function’s reliance in large numbers of global variables.

parseInt is the only function that uses the radix parameter. The parseInt function converts the value to an integer, which ends up rounding down 2.56 to 2

The Number constructor converts whatever is entered in to a valid number. It can accept any valid number, whether that be 2.56, or even 256e-2

You may want to check though that the values of c and d are valid numbers (using isNaN) before using them.

parseInt converts the string to an integer (any base between 2 and 36) discarding any trailing non-numerics

parseFloat does the same but also allows for fractions after the point (still any base between 2 and 36)

in both of the above not specifying the second parameter will result in the number being assumed to be base 16 if it starts with 0x, base 8 if it starts with 0 or base 10 if it starts with anything else.

Number() converts a string to a number but will return NaN if the entire field isn’t a number.

other ways to convert to a number inclide:

num-0
num*1
num/1
+num

Sorry but I’ve read this around 8 times or so and I still don’t understand what you’re saying here. Could you rephrase what you said or make it simpler please?

I understand what you’re saying here though and this is crucial information! I obviously want to be able to use decimal numbers in my calculator and not have it round up / down! I’ve decided to change to the Number constructor so I can do calculations such as 1.5 + 1.5 = 3 :slight_smile:

	add.onclick = function() {
		answer.innerHTML = (Number(c.value) + Number(d.value));
	}

It’s also less code too which I would imagine makes it better because it saves more bytes?

Don’t understand this. How would I do this?

Thanks for the extra information felgall :slight_smile:

Andrew Cooper

PS: I know I said this was a simple script…But I guess really I’m not qualified to say such a thing. On a scale of 1 - 10, what would you rate this calculator script? 1 being a simple alert message and 10 being something super-advanced and complicated like a game or animation (or is there more complicated / advanced JS scripts out there?)

It is a simple script. It would have to be either a 1 or at most a 2.

Those complicated game and animation scripts you mention would probably rate about a 6 or 7 to leave room for the more complicated JavaScripts.

Heh, I feel so terribly newbie! :blush: But we all must start somewhere! :slight_smile:

What type of script would you rate as a solid 10?

Also, when I try 1.5 + 1.5 I get 3 as the answer, which is correct. On the other hand when I try 1.5 * 2.5 I get 4 as the answer, which is wrong, as I should receive 3.75 as the answer, shouldn’t I? Yet if I try 1.5 * 3 I receive 4.5 as the answer, which is correct.

Help please?

Andrew Cooper

Try 6 * 1 and you should get 7, which indicates that the add operation is being performed instead.

Exactly what does your code look like that is doing the multiplication.

Oh deary me! :eek: :blush: I knew something wasn’t quite right…I’m so stupid…I didn’t even check my code! All of the operators were + rather than +, -, *, / which is what they are now and everything is running smoothly when I get the answer :slight_smile:

I’ve just had a glass of wine though, is that a good enough excuse for the carelessness? :lol:

What about the issue with the rephrasing of your statement pmw57, and help with understanding what you mean about wanting to check that the values of c and d are valid numbers (using isNaN) before using them?

Thanks for the help guys! Really appreciated!

Andrew Cooper

Functions are at their most stable when their proper working relies on as few assumptions as possible. That is achieved by the function relying on values that are passed to them, or on well known assumptions such as other functions, or object such as the document object.

With the calculator project, the add() function makes assumptions that answer, c, and d exist in some manner.

A more stable solution could be to call an update function, and pass it a function that performs the calculations.


function add() {
    var add = function (c, d) {
        return c + d;
    };
    update(add);
}
function update(func) {
    var cInput = ...,
        dInput = ...,
        answer = ...,
        c = Number(cInput.value) || 0,
        d = Number(dInput.value) || 0;
    answer.innerHTML = func(c, d);
}

You can use isNaN(c) to check if the value of c is a number. If it’s not, you can assign a replacement number, such as 0 instead.


c = Number(cInput.value);
if (isNaN(c)) {
    c = 0;
}

You can also use what is known of as a “default operator” to do the same job.


c = Number(cInput.value) || 0;

You’ll see that technique used in the earlier script example.

[edit]

Working on it as you speak.[/edit]

The jQuery library is perhaps getting up toward the 10 end of the range.

How about Yahoo’s YUI library. I know that it’s not as popular here as jQuery, but would YUI be in advance of jQuery by a point or two?

I haven’t really looked at either library all that closely but the libraries are definitely the types of scripts at the top end of the range with the ones closest to being a 10 being the ones that can do the most with the least amount of code (while being totally unobtrusive).

Most of the actual scripts you see in web pages would only use a small fraction of the code that those libraries make available and so would be far simpler than a library if you only include the actual code that is needed.

Ok, I think I understand this. It makes it easier for functions to work more reliably if they can find things more easily. Or something along the lines.

Ok, I tried editing my JS code to reflect this solution and this is the JS code I now have and it doesn’t work for addition or any others:

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

function calculator() {
	if (!document.getElementById) return false;

	function update(func) {
		var firstNum = document.getElementById("firstNum"),
		    secondNum = document.getElementById("secondNum"),
		    answer = document.getElementById("answer"),
		    a = Number(firstNum.value) || 0,
		    b = Number(secondNum.value) || 0;

		answer.innerHTML = function(a, b);
	}

	add.onlick = function() {
		var add = function(a, b) {
			return a + b;
		};
		update(add);
	}

	// function add() {
	//	var add = function(a, b) {
	//		return a + b;
	//	};
	//	update(add);
	// }

	function subtract() {
		var subtract = function(a, b) {
			return a - b;
		};
		update(subtract);
	}

	function multiply() {
		var multiply = function(a, b) {
			return a * b;
		};
		update(multiply);
	}

	function divide() {
		var divide = function(a, b) {
			return a / b;
		};
		update(divide);
	}

}

addLoadEvent(calculator);

Any help here please?

I’ll use the default operator method. I’ll assume that the default operator method is the better method to use because it is less typing (meaning less bytes)?

Thanks for the help on this Paul and Stephen, it’s really appreciated. A lot of the JavaScript books I have don’t cover numbers. I figured that creating a simple calculator script would be a good beginners project but it seems there is more to it than the basic beginners knowledge, despite this being a newbie / beginnger script.

Andrew Cooper

There are a couple of issues, one that you introduced, and one from me too.

When the answer is calculated, it should call the func object that was passed in to the update function. Where you renamed func(a, b) to function(a, b), please change it back to func(a, b)


function update(func) {
    ...
    answer.innerHTML = func(a, b);
}

The other issue is my fault. Please change onlick to onclick. Sorry :rolleyes:

Heh. I changed func(a, b) to function(a, b) because I didn’t see anywhere where this was referenced. It was referenced as a parameter to the update function, right?

Paul, I can bet you’re probably calling me all sorts of names right now (or maybe not, I probably would be) but I kind of don’t understand. I think it’s because you used the word object and I don’t know anything about objects right now, or maybe I do but I don’t realise what objects are. I understand that answer.innerHTML = func(a, b); is a reference to the parameter function updateb[/b] here and that’s about it. But I don’t understand what this is doing and how it is doing it. Could you explain this please?

Actually, that was my fault, so don’t apologise! :eek: The code you gave me was:

function add() {
    var add = function (c, d) {
        return c + d;
    };
    update(add);
}
function update(func) {
    var cInput = ...,
        dInput = ...,
        answer = ...,
        c = Number(cInput.value) || 0,
        d = Number(dInput.value) || 0;
    answer.innerHTML = func(c, d);
}

I amended that to include the add.onclick but it turned out to be add.onlick - Clearly a typo from me because if there is at least one thing I know about JavaScript it’s that it doesn’t lick anything! :lol:

Thanks again for the code help and explanations, I really appreciate it.

Andrew Cooper