Thread: Problems using JavaScript and calculations

1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2000
Posts
5
Rep Power
0

Problems using JavaScript and calculations

Hi!

I'm trying to complete a Laboratory Exercise for a course at Uni, and I have to design a page, using JavaScript, that will allow users to enter the current price of a stock, the number of shares owned, the amount of dividends paid on each share, and how often dividends are paid out. The fields are then validated (to ensure they are numbers), and the page is supposed to display the amount of time it will take to earn a new share of stock by investing the dividends.

Now, I haven't had much experience with JavaScript, but I'm slowly making my way through the textbook (these activities are done without any formal teaching), and using the examples, I've been able to get the form fields to correspond to values, which have been validated. I've also got a form field to display the amount of dividends paid out per period. What I'm having a problem with, however, is working out how long it will take to earn a new share of stock by investing the dividends.

Here's the JavaScript code from the page:
Code:
```	<script type="text/javascript" language="javascript">
<!--
function Calc(divCalc) {
var stockPrice = document.divCalc.stockPrice.value
var stockPrice = parseFloat(stockPrice)

if (isNaN(stockPrice)) {
alert( "The stock price is not a number!")
document.divCalc.stockPrice.value = ""
document.divCalc.stockPrice.focus()
}
else {
var stockNum = document.divCalc.stockNum.value
var stockNum = parseInt(stockNum, 10)

if (isNaN(stockNum)) {
alert( "The number of stocks is not a number!")
document.divCalc.stockNum.value = " "
document.divCalc.stockNum.focus()
}
else {
var divPrice = document.divCalc.divPrice.value
var divPrice = parseFloat(divPrice)

if (isNaN(divPrice)) {
alert( "The price of dividends is not a number!")
document.divCalc.divPrice.value = " "
document.divCalc.divPrice.focus()
}
else {
var divFreq = document.divCalc.divFreq.value
var divFreq = parseInt(divFreq, 10)

if (isNaN(divFreq)) {
alert( "The frequency of dividends is not a number!")
document.divCalc.divFreq.value = ""
document.divCalc.divFreq.focus()
}
}
}
}
var divPayment=document.divCalc.divPayment.value
var divPayment=parseFloat(divPayment)
document.divCalc.divPayment.value=calculateDivPayment(stockNum, divPrice, divFreq)

function calculateDivPayment(stockNum, divPrice, divFreq) {
return ((stockNum * divPrice) / divFreq)
}
var divTime=document.divCalc.divTime.value
var divTime=parseFloat(divTime)
document.divCalc.divTime.value=calculateDivTime(divPayment, stockPrice)

function calculateDivTime(divPayment, stockPrice) {
var divTime=stockPrice/divPayment
alert("It would take "+divTime+" to earn enough money to buy one new stock.")
}
}
//-->
</script>```
The variable that is troublesome is divTime. The alert box that displays says "NaN" (which I know means "Not a Number"), instead of some number. I'm not quite sure why it's doing this...

Can anyone help? It would be greatly appreciated!

Thanks a lot!
2. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Nov 2001
Posts
765
Rep Power
14
JavaScript manipulates objects created with HTML; without both, there's no way to accurately test your form, short of writing the whole thing from scratch. You've got some syntax errors (curly braces) and it looks like you're using nested functions, not advisable for beginners. Also - you're not returning false when bad input is detected. Post a usable page for better feedback.
3. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2000
Posts
5
Rep Power
0
Whoops, here's the entire HTML file:

Code:
```<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<title>Stock Dividend Reinvestment Calculator</title>
<meta name="generator" content="BBEdit 7.0.3">
<script type="text/javascript" language="javascript">
<!--
function Calc(divCalc) {
var stockPrice = document.divCalc.stockPrice.value
var stockPrice = parseFloat(stockPrice)

if (isNaN(stockPrice)) {
alert( "The stock price is not a number!")
document.divCalc.stockPrice.value = ""
document.divCalc.stockPrice.focus()
}
else {
var stockNum = document.divCalc.stockNum.value
var stockNum = parseInt(stockNum, 10)

if (isNaN(stockNum)) {
alert( "The number of stocks is not a number!")
document.divCalc.stockNum.value = " "
document.divCalc.stockNum.focus()
}
else {
var divPrice = document.divCalc.divPrice.value
var divPrice = parseFloat(divPrice)

if (isNaN(divPrice)) {
alert( "The price of dividends is not a number!")
document.divCalc.divPrice.value = " "
document.divCalc.divPrice.focus()
}
else {
var divFreq = document.divCalc.divFreq.value
var divFreq = parseInt(divFreq, 10)

if (isNaN(divFreq)) {
alert( "The frequency of dividends is not a number!")
document.divCalc.divFreq.value = ""
document.divCalc.divFreq.focus()
}
}
}
}
var divPayment=document.divCalc.divPayment.value
var divPayment=parseFloat(divPayment)
document.divCalc.divPayment.value=calculateDivPayment(stockNum, divPrice, divFreq)

function calculateDivPayment(stockNum, divPrice, divFreq) {
return ((stockNum * divPrice) / divFreq)
}
var divTime=document.divCalc.divTime.value
var divTime=parseFloat(divTime)
document.divCalc.divTime.value=calculateDivTime(divPayment, stockPrice)

function calculateDivTime(divPayment, stockPrice) {
var divTime=stockPrice/divPayment
alert("It would take "+divTime+" to earn enough money to buy one new stock.")
}
}
//-->
</script>

<body>

<h3 align="center">Dividend Reinvestment Calculator</h3>

<form name="divCalc">
<table align="center">
<tr align="center">
<td>Current Stock Price (\$):</td>
<td><input type="text" name="stockPrice"></td>
</tr>
<tr align="center">
<td>Number of Stocks Held:</td>
<td><input type="text" name="stockNum"></td>
</tr>
<tr align="center">
<td>Price of Dividends (\$):</td>
<td><input type="text" name="divPrice"></td>
</tr>
<tr align="center">
<td>Frequency of Dividend Payment in Months:</td>
<td><input type="text" name="divFreq"></td>
</tr>
<tr align="center">
<td><input type="button" value="Calculate" onclick="Calc(divCalc)"><input type="reset">
</td>
</tr>
<tr align="center">
<td>Amount of Dividends Paid Per Period (\$):</td>
</tr>
<tr align="center">
<td>The time taken to earn a new share of stock is </td>
<td> months.</td>
</tr>
</table>
</form>

</body>
</html>```
Thanks!
4. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Nov 2001
Posts
765
Rep Power
14
A few problems:

1) Not returning false when validation fails
2) Nested functions; don't really need additional ones
3) Declaring variables twice in paired statements

I rewrote this (in a hurry) for you; seems OK but you be the judge. Compressed some code; no point taking two lines to do what you can in one, if the intent is clear. Passing the form object (<form....onsubmit="return Calc(this)">) saves a lot of typing, and eliminates re-finding it after the function is called.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<title>untitled</title>
<script type="text/javascript" language="javascript">

<!--
function Calc(oForm) {
var el, msg = 'The following entries are blank/invalid:\n';
msg += '______________________________\n\n';
var stockPrice = parseFloat(oForm.stockPrice.value, 10);
if (isNaN(stockPrice) || stockPrice == 0) {
msg += '\tCurrent Stock Price\n';
if (!el) el = oForm.stockPrice;
}
var stockNum = parseInt(oForm.stockNum.value, 10);
if (isNaN(stockNum) || stockNum == 0) {
msg += '\tNumber of Stocks Held\n';
if (!el) el = oForm.stockNum;
}
var divPrice = parseFloat(oForm.divPrice.value, 10);
if (isNaN(divPrice) || divPrice == 0) {
msg += '\tPrice of Dividends\n';
if (!el) el = oForm.divPrice;
}
var divFreq = parseInt(oForm.divFreq.value, 10);
if (isNaN(divFreq) || divFreq == 0) {
msg += '\tFrequency of Dividend Payment in Months\n';
if (!el) el = oForm.divFreq;
}
if (el) {
msg += '\nPlease correct and re-submit.';
el.focus();
el.select();
return false;
}
var divPayment = stockNum * divPrice / divFreq;
oForm.divPayment.value = ' ' + roundTo(divPayment, 2);
var divTime = stockPrice/divPayment;
oForm.divTime.value = ' ' + roundTo(divTime, 2);
return false;
}

function roundTo(num, places) {
return Math.round(num * Math.pow(10, places)) / Math.pow(10, places);
}

//-->
</script>

</script>
<div align="center"><br>
<h2 style="color:white;">&amp;#149; Dividend Reinvestment Calculator &amp;#149;</h2>
onreset="this.elements[0].focus()"
onsubmit="return Calc(this)">
<table>
<tr>
<td align="right">Current Stock Price__________________</td>
<td><b>\$</b><input type="text" name="stockPrice" size="12"></td>
<td></td>
</tr>
<tr>
<td align="right">Number of Stocks Held________________</td>
<td colspan="2">&amp;nbsp;&amp;nbsp;<input type="text" name="stockNum" size="12"></td>
</tr>
<tr>
<td align="right">Price of Dividends____________________</td>
<td colspan="2"><b>\$</b><input type="text" name="divPrice" size="12"></td>
</tr>
<tr>
<td align="right">Frequency of Dividend Payment in Months___</td>
<td colspan="2">&amp;nbsp;&amp;nbsp;<input type="text" name="divFreq" size="12"></td>
</tr>
<tr>
<td colspan="3"><hr></td>
</tr>
<tr>
<td align="center" colspan="3"><input type="submit" value="Calculate">
<input type="reset" onclick="return confirm('Clear all entries?')">
</td>
</tr>
<tr>
<td colspan="3"><hr></td>
</tr>
<tr>
<td align="center">Amount of Dividends Paid Per Period:</td>
</tr>
<tr>
<td align="center">The time taken to earn a new share of stock is</td>
<td> month(s).</td>
</tr>
</table>
</form>
</div>
</body>
</html>

hth, _rf
Last edited by mrrichardfeder; April 8th, 2003 at 10:43 PM.
5. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Oct 2000
Posts
5
Rep Power
0
Thankyou very much for your help! I got rid of the functions to calculate the time and payments, as you had done, as well as the double-declarations of variables, but I still kept the nested alerts and all of that stuff, because I didn't quite understand what your changes did.

Now that I have some time, I'd just like to try and understand some of the changes you made...

Code:
```var el, msg = 'The following entries are blank/invalid:\n';
msg += '______________________________\n\n';
var stockPrice = parseFloat(oForm.stockPrice.value, 10);
if (isNaN(stockPrice) || stockPrice == 0) {
msg += '\tCurrent Stock Price\n';
if (!el) el = oForm.stockPrice;
}
...
if (el) {
msg += '\nPlease correct and re-submit.';
el.focus();
el.select();
return false;
}```
What does the 'el' variable do? Also, what does "msg += '...'" achieve? I haven't seen that before...

Thanks a lot!
6. No Profile Picture
Contributing User
Devshed Novice (500 - 999 posts)

Join Date
Nov 2001
Posts
765
Rep Power
14
Hey, you're welcome.

Any time you look at your code and see repetition, think loop. If you're performing the same operation over and over, you can generally extract any specific data from the basic procedure, and condense the entire thing down to a repeating bit of code, which fills in the necessary differences each time it recycles. Validation is typical - the above does the same thing (more or less) to several fields; the only specific information the code needs for each check is 1) which field is this - so it can get focus if invalid, and 2) what do we need to add to the error prompt? The variable el holds the field reference:

if (!el) el = oForm.stockPrice;

The conditional translates as: if nothing has been assigned to el yet, set it as a pointer to this invalid field. If another field is later found invalid, this assures that el won't be reassigned, as we want the bad field highest up on the page to get focus (which also scrolls the page). msg simply holds the prompt string, assembled as we go along. This:

if (el) .....

translates as: if el is set, must have been a bad field, so alert the user.

http://www.dardenhome.com/js/x622847.htm