Dynamically adding content to a table, working with nodes in javascript

Black-Scout
Black-Scout used Ask the Experts™
on
I have a question about the same dynamically generated table that has been solved in three posts, but isn't working for me :(

The latest post from "digiby" was solved in late march. Could you please post your final code?  

I have been bouncing around with this "lighthouse" dynamically generated table for hours as well and I have read numerous solved posts but my code doesn't work. I've messed it up so much reading the posts that I don't know where I'm going wrong.

I'll paste the javascript code below. With the very lengthy instructions from the textbook.
I will also post the htm file so you can test with me.

When I preview in FF or in IE the table is empty, it is suppose to load with 10 contributors and a total of $1800 in contributions. I also cannot add nor delete a contributor.

Thanks for taking a look:
//display the total number of contributors in the table cells whose ids are "totalContr" and "totalAmt"
function updateTotals() {
	// within the totalContr table cell, display the length of the amount array
    totalC = document.getElementById("totalContr");
	totalC.innerHTML = amount.length;
	// create a variable name totalContributions and set its intital value to 0
	totalContributions = 0;
	/* create a for loop that loops trhough each entry in the amount array. 
	Each time through the loop increase the value of the totalContributions variable by the amount in the current entry in
	the amount array */
	for (var i=0; i <amount.length; i++) {
	    totalContributions += parseInt(amount[i]);	
	}
	// within the totalAmt table cell, display the value of the totalContributions variable
	document.getElementById("totalAmt").innerHTML = totalContributions;
}

   

//creates the contributors table by adding new table rows for each of the entries in the eight data arrays
function makeTable() {
	//Create a variable named headingRow that references the table row with the id "titleRow".
	//This row contains the titles from the contributors table. 
    var headingRow = document.getElementById("titleRow");
	//Create a second variable named blankRow that references the table row with the id "emptyRow"
	var blankRow = document.getElementById("emptyRow");
	/* Use the cloneNode() method to clone the blankRow node.  
	Set the value of the deep variable to true in order to copy the entire node tree.  Store this document fragment in a
	variable named dataRow.
	*/
	dataRow = blankRow.cloneNode(true);
	/*
	Create a for loop that loops through the entries in the amount array.  For each entry call the addRow() function using
	the value of the counter variable in the for loop as the parameter value in the addRow() function.
	*/
	for (var i=0; i<amount.length; i++) {
	    addRow(i);	
	}
	//Call the updateTotals() function  
	updateTotals();
}



/* a function to add a single row to the contributors table, extracting information from the eight data arrays. addRow() has a single parameter named index equal to the array index number from which data is to be taken. */
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow.*/
    newRow = dataRow.cloneNode(true);	
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the ntex string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	newRow.childNodes[3].innerHTML = date[index];
    newRow.childNodes[5].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[7].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[9].innerHTML = amount[index];
	/*  If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)    */
	if (index == 0) { 
	    blankRow.parentNode.replaceChild(newRow, blankRow) 
	}
    else { 
	    headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  
	}
	
}

// a function to create a new contributor record based on the values entered by the user in the web form
function addRecord() {
	// Create a variable named recordNum equal to the length of the amount array.
    recordNum = amount.length;
	/*
	Set the value of first[recordNum] to the value of the fname field from the donations Web form.  
	Set the value of last[recordNum] to the value of the lname field.  
	Set the value of the street array item to the value of the street field
	set the value of the city array item to the value of the city field.  
	Determine which state option has been selected by the user and store the text of the selected option in the state arry
	item. 
	Set the value of the zip, amount, and date array items to the values of the zip, amount, and date fields in the
	donations Web form.  
	*/
	firstName[recordNum] = document.getElementById("fname").value;
	lastName[recordNum] = document.getElementById("lname").value;
	street[recordNum] = document.getElementById("street").value;
	city[recordNum] = document.getElementById("city").value;
	state[recordNum] = document.getElementById("state").value;
	zip[recordNum] = document.getElementById("zip").value;
	amount[recordNum] = document.getElementById("amount").value;	
	date[recordNum] = document.getElementById("date").value;
	//Call the addRow() function using the value of the recordNum variable as the parameter value.
	addRow(recordNum);
	//Call the updateTotals() function.   
	updateTotals();
	
}

/*a funtion to remove a record from each of the eight data arrays. the function has a single parameter "index" that indicates the array item to remove */
function removeRecord(index) {
	/* Use the splice() method to remove the item from the firstName array whose index value equals the value of the index
	parameter.  Remove only one array item.
	*/
	firstName.splice(index,1);
	// Repeat step for the lastName, street, city, state, zip, amount, and date arrays. 
	lastName.splice(index,1);
	street.splice(index,1);
	city.splice(index,1);
	state.splice(index,1);
	zip.splice(index,1);
	amount.splice(index,1);
	date.splice(index,1);
}
 

/* a function whose purpose is to remove a node from a node tree and then return a reference to the node's previious siblings. The single parameter "node" represents the ode hyou want to remove */
function removeNode(node) {
	// Create a variable named prevNode referencing the node's previous sibling. 
	var prevNode = node.previousSibling;
	//Use the removeChild() method to remove the node.  (Hint: Apply the removeChild() method to the node's parent node.)
	prevNode.parentNode.removeChild(prevNode);
	//Return the prevNode variable from the function.      
	return prevNode;
}
 
  
/* Create the removeRecords() function, whose purpose is to remove contributor records from the contributor table and the eight data arrays if the check box for the record has been checked in the contributor table. */
function removeRecords() {
	//  Create a variable named headerRow referencing the row with the id "titleRow".  
	var headerRow;
	ctable.document.getElementById("titleRow") = headerRow;
	// Create a variable named recordNum equal to the length of the amount array.
	var recordNum = amount.length;
	/* Create a for loop that uses familial references, starting with the node variable, n, equal to the first sibling of
	the headerRow node and proceeding to the next sibling (the next table row) until there is no next sibling.
	Within the for loop, decrease the value of the recordNum varialbe by 1.  
	Then, insert an if condition that tests whether the name of the current node is "TR" (a table row).  
	If it is, insert a second if condition that tests whether the check box within the first table cell of the current ro
	has been selected.  (Hint: Reference the check box using the reference n.firstChild.firstChild.)  
	*/
	for ( n = 0; n < headerRow.childNodes.length; n++) {
	recordNum = recordNum - 1;
	if (headerRow.childNodes[n].name = "TR") {
	/*  If the check box has been checked, then: (1) Call the removeRecord() function using the recordNum as the parameter
	value, and (2) Let the node counter, n, be equal to the value returned by the removeNode() function using the n as the
	parameter value. */
  	if (n.firstChild.firstChild != "") {
    removeRecord(recordNum);
	n = removeNode(n)};
	};
	//After the for loop has finished, call the updateTotals() function to update the contribution totals in the Web page.
	updateTotals(); }
}

Open in new window

//display the total number of contributors in the table cells whose ids are "totalContr" and "totalAmt"
function updateTotals() {
	// within the totalContr table cell, display the length of the amount array
    totalC = document.getElementById("totalContr");
	totalC.innerHTML = amount.length;
	// create a variable name totalContributions and set its intital value to 0
	totalContributions = 0;
	/* create a for loop that loops trhough each entry in the amount array. 
	Each time through the loop increase the value of the totalContributions variable by the amount in the current entry in
	the amount array */
	for (var i=0; i <amount.length; i++) {
	    totalContributions += parseInt(amount[i]);	
	}
	// within the totalAmt table cell, display the value of the totalContributions variable
	document.getElementById("totalAmt").innerHTML = totalContributions;
}

   

//creates the contributors table by adding new table rows for each of the entries in the eight data arrays
function makeTable() {
	//Create a variable named headingRow that references the table row with the id "titleRow".
	//This row contains the titles from the contributors table. 
    var headingRow = document.getElementById("titleRow");
	//Create a second variable named blankRow that references the table row with the id "emptyRow"
	var blankRow = document.getElementById("emptyRow");
	/* Use the cloneNode() method to clone the blankRow node.  
	Set the value of the deep variable to true in order to copy the entire node tree.  Store this document fragment in a
	variable named dataRow.
	*/
	dataRow = blankRow.cloneNode(true);
	/*
	Create a for loop that loops through the entries in the amount array.  For each entry call the addRow() function using
	the value of the counter variable in the for loop as the parameter value in the addRow() function.
	*/
	for (var i=0; i<amount.length; i++) {
	    addRow(i);	
	}
	//Call the updateTotals() function  
	updateTotals();
}



/* a function to add a single row to the contributors table, extracting information from the eight data arrays. addRow() has a single parameter named index equal to the array index number from which data is to be taken. */
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow.*/
    newRow = dataRow.cloneNode(true);	
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the ntex string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	newRow.childNodes[3].innerHTML = date[index];
    newRow.childNodes[5].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[7].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[9].innerHTML = amount[index];
	/*  If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)    */
	if (index == 0) { 
	    blankRow.parentNode.replaceChild(newRow, blankRow) 
	}
    else { 
	    headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  
	}
	
}

// a function to create a new contributor record based on the values entered by the user in the web form
function addRecord() {
	// Create a variable named recordNum equal to the length of the amount array.
    recordNum = amount.length;
	/*
	Set the value of first[recordNum] to the value of the fname field from the donations Web form.  
	Set the value of last[recordNum] to the value of the lname field.  
	Set the value of the street array item to the value of the street field
	set the value of the city array item to the value of the city field.  
	Determine which state option has been selected by the user and store the text of the selected option in the state arry
	item. 
	Set the value of the zip, amount, and date array items to the values of the zip, amount, and date fields in the
	donations Web form.  
	*/
	firstName[recordNum] = document.getElementById("fname").value;
	lastName[recordNum] = document.getElementById("lname").value;
	street[recordNum] = document.getElementById("street").value;
	city[recordNum] = document.getElementById("city").value;
	state[recordNum] = document.getElementById("state").value;
	zip[recordNum] = document.getElementById("zip").value;
	amount[recordNum] = document.getElementById("amount").value;	
	date[recordNum] = document.getElementById("date").value;
	//Call the addRow() function using the value of the recordNum variable as the parameter value.
	addRow(recordNum);
	//Call the updateTotals() function.   
	updateTotals();
	
}

/*a funtion to remove a record from each of the eight data arrays. the function has a single parameter "index" that indicates the array item to remove */
function removeRecord(index) {
	/* Use the splice() method to remove the item from the firstName array whose index value equals the value of the index
	parameter.  Remove only one array item.
	*/
	firstName.splice(index,1);
	// Repeat step for the lastName, street, city, state, zip, amount, and date arrays. 
	lastName.splice(index,1);
	street.splice(index,1);
	city.splice(index,1);
	state.splice(index,1);
	zip.splice(index,1);
	amount.splice(index,1);
	date.splice(index,1);
}
 

/* a function whose purpose is to remove a node from a node tree and then return a reference to the node's previious siblings. The single parameter "node" represents the ode hyou want to remove */
function removeNode(node) {
	// Create a variable named prevNode referencing the node's previous sibling. 
	var prevNode = node.previousSibling;
	//Use the removeChild() method to remove the node.  (Hint: Apply the removeChild() method to the node's parent node.)
	prevNode.parentNode.removeChild(prevNode);
	//Return the prevNode variable from the function.      
	return prevNode;
}
 
  
/* Create the removeRecords() function, whose purpose is to remove contributor records from the contributor table and the eight data arrays if the check box for the record has been checked in the contributor table. */
function removeRecords() {
	//  Create a variable named headerRow referencing the row with the id "titleRow".  
	var headerRow;
	ctable.document.getElementById("titleRow") = headerRow;
	// Create a variable named recordNum equal to the length of the amount array.
	var recordNum = amount.length;
	/* Create a for loop that uses familial references, starting with the node variable, n, equal to the first sibling of
	the headerRow node and proceeding to the next sibling (the next table row) until there is no next sibling.
	Within the for loop, decrease the value of the recordNum varialbe by 1.  
	Then, insert an if condition that tests whether the name of the current node is "TR" (a table row).  
	If it is, insert a second if condition that tests whether the check box within the first table cell of the current ro
	has been selected.  (Hint: Reference the check box using the reference n.firstChild.firstChild.)  
	*/
	for ( n = 0; n < headerRow.childNodes.length; n++) {
	recordNum = recordNum - 1;
	if (headerRow.childNodes[n].name = "TR") {
	/*  If the check box has been checked, then: (1) Call the removeRecord() function using the recordNum as the parameter
	value, and (2) Let the node counter, n, be equal to the value returned by the removeNode() function using the n as the
	parameter value. */
  	if (n.firstChild.firstChild != "") {
    removeRecord(recordNum);
	n = removeNode(n)};
	};
	//After the for loop has finished, call the updateTotals() function to update the contribution totals in the Web page.
	updateTotals(); }
}

Open in new window

<html>
<head>
<!-- 
 
   Filename:         clist.htm
   Supporting files: data.js, lhouse.css, logo.jpg, newdata.js

-->
<title>The Lighthouse</title>
<link href="lhouse.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="data.js"> </script>
<script type="text/javascript" src="newdata.js"> </script>
</head>

<body onLoad="makeTable();">
<form name="donations" id="donations" action="">
<div id="title">
   <img src="logo.jpg" alt="The Lighthouse" />
   The Lighthouse<br />
   543 Oak Street<br />
   Delphi, KY &nbsp;&nbsp;89011<br/>
   (542) 555-7511
</div>

<div id="data_entry">
   <table>
   <tr>
      <td>Contributors</td>
      <td id="totalContr"></td>
   </tr>
   <tr>
      <td>Total</td>
      <td id="totalAmt"></td>
   </tr>
   </table>

   <table>
   <tr><td colspan="2"><h3>Enter a New Contributor</h3></td></tr>
   <tr>
      <td>First Name</td><td><input name="fname" id="fname" /></td>
   </tr>
   <tr>
      <td>Last Name</td><td><input name="lname" id="lname" /></td>
   </tr>
   <tr>
      <td>Street</td><td><input name="street" id="street" /></td>
   </tr>
   <tr>
      <td>City</td><td><input name="city" id="city" /></td>
   </tr>
   <tr>
      <td>State</td>
      <td><select name="state" id="state">
      <option>AL</option><option>AK</option><option>AZ</option><option>AR</option>
      <option>CA</option><option>CO</option><option>CT</option><option>DE</option>
      <option>DC</option><option>FL</option><option>GA</option><option>HI</option>
      <option>ID</option><option>IL</option><option>IN</option><option>IA</option>
      <option>KS</option><option>KY</option><option>LA</option><option>ME</option>
      <option>MD</option><option>MA</option><option>MI</option><option>MN</option>
      <option>MS</option><option>MO</option><option>MT</option><option>NE</option>
      <option>NV</option><option>NH</option><option>NJ</option><option>NM</option>
      <option>NY</option><option>NC</option><option>ND</option><option>OH</option>
      <option>OK</option><option>OR</option><option>PA</option><option>RI</option>
      <option>SC</option><option>SD</option><option>TN</option><option>TX</option>
      <option>UT</option><option>VT</option><option>VA</option><option>WA</option>
      <option>WV</option><option>WI</option><option>WY</option>
      </select>
      </td>
   </tr>
   <tr>
      <td>Zip</td><td><input name="zip" id="zip" /></td>
   </tr>
   <tr>
      <td>Amount</td><td><input name="amount" id="amount" /></td>
   </tr>
   <tr>
      <td>Date</td><td><input name="date" id="date" /></td>
   </tr>
   <tr>
      <td colspan="2" id="buttoncell1">
         <input type="button" value="Add Contributor" onClick="addRecord()" />
      </td>
   </tr>
   </table>
</div>

<div id="report">
   <p><input value="Remove Checked Items" type="button" onClick="removeRecords()" /></p>

   <table id="ctable">
   <tr><th colspan="5">Contributor List</th>
   </tr>
   <tr id="titleRow">
      <th>Remove</th>
      <th>Date</th>
      <th>Name</th>
      <th>Address</th>
      <th>Amount</th>
   </tr><tr id="emptyRow"><td class="rc"><input type="checkbox" /></td><td></td><td></td><td></td><td class="ac"></td></tr>
   </table>
</div>

</form>
</body>
</html>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
Sorry, it seems that the js file loaded twice and the html file once, at the end.

The two javascript files are the same, ignore one of them.

My apologies again.
Is it working or you still need some help?

Author

Commented:
It is not working, I haven't changed the code since the first post. I really don't know how to fix it.
Success in ‘20 With a Profitable Pricing Strategy

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Commented:
1 - Working with DIVs is much more faster than working with tables, even if you create an outer div as row, and inner divs as cell (using CSS floating attribute you easily manage to put divs next to each other)
2 - here it is:
var table1             = document.createElement("table");
var row1             = table1.insertRow(table1.rows.length);
var cell1            = row1.insertCell(row.cells.length);
var cell2            = row1.insertCell(row.cells.length);
var cell3            = row1.insertCell(row.cells.length);

cell1.innerHTML            = 'test1';
cell2.innerHTML            = 'test2';
cell3.innerHTML            = 'test3';

Author

Commented:
I guess, but that doesn't help me follow the instructions of the assignment. I'm absolutely certain that the methods discussed in this course are not the most efficient, but I can't deviate too much from them regardless.

I only have two programs left to code before I can put this course to bed, the above js file represents one of them.

Still hoping for some help, thanks
Top Expert 2015

Commented:
Unless you have more code, the main thing that is preventing this from working is the fact that none of your variables, which you reference as if they were global, are ever initialized.

To create the global variables, the first lines of code, outside of any function, should look something like this:

var amount = new Array();
var firstName = new Array();
var lastName = new Array();
var street = new Array();
var city = new Array();
var state = new Array();
var zip = new Array();
var date = new Array();
var headingRow, blankRow, dataRow, recordNum;

Then you must be certain not to re-initialize these in the functions by using the var keyword as in var headerRow.

Author

Commented:
ok, I'll give it a try. If you read the js file I followed the instructions word for word, this could be the root of the problem
Top Expert 2015

Commented:
The other sticking point is that you are referring to objects on the page before they exist. For example, you create a reference to "emptyRow" in your javascript function makeTable() which is called on page load in the head section of the page, but the "emptyRow" object is created below the script in the body of the page.

I see references to two .js files. Is the javascript you posted all of the code in use on the page?

Author

Commented:
Anything else that you noticed? I preview with the same results :(

Author

Commented:
Ok, you are right on, Below I will attempt to post the two js files and the html file in that order.

I am following the instructions as closely as I can, but imagine that the errors are from the instructions just as much as my own misunderstanding.

I have created "newdata.js" as instructed by the text. The other files were created for me.

Here goes:



/*
   New Perspectives on JavaScript
   Tutorial 10
   Case Problem 3

   Filename: data.js

   Variable List:

   firstName: Contains the first name of the contributors.
   lastName:  Contains the last name of the contributors.
   street:    Contains the contributor's street address
   city:      Contains the contributor's city of residence
   state:     Contains the contributor's state of residence
   zip:       Contains the contributor's zip code.
   amount:    Contains the amount of the contribution.
   date:      Contains the date of the contribution.

*/


firstName = new Array();
lastName = new Array();
street = new Array();
city = new Array();
state= new Array();
zip = new Array();
amount = new Array();
date = new Array()


firstName[0]="Steve";
lastName[0]="Bones";
street[0]="900 Lawton Street";
city[0]="Wheaton";
state[0]="KY";
zip[0]="89211";
amount[0]=50;
date[0]="2007-08-25";


firstName[1]="Jeri";
lastName[1]="White";
street[1]="Hawkes Lane";
city[1]="Delphi";
state[1]="KY";
zip[1]="89211";
amount[1]=150;
date[1]="2007-08-25";


firstName[2]="Tom";
lastName[2]="Thomas";
street[2]="Rigel Avenue";
city[2]="Drake";
state[2]="KY";
zip[2]="89411";
amount[2]=100;
date[2]="2007-08-27";


firstName[3]="Hugh";
lastName[3]="Warren";
street[3]="585 Lindon Court";
city[3]="Wheaton";
state[3]="KY";
zip[3]="88877";
amount[3]=50;
date[3]="2007-08-28";


firstName[4]="Lynwood";
lastName[4]="Ingersoll";
street[4]="723 Jackson Avenue";
city[4]="Delphi";
state[4]="KY";
zip[4]="88802";
amount[4]=500;
date[4]="2007-08-30";


firstName[5]="Petronila";
lastName[5]="Damico";
street[5]="44 Stewart Street";
city[5]="Drake";
state[5]="KY";
zip[5]="88604";
amount[5]=250;
date[5]="2007-08-30";


firstName[6]="Livia";
lastName[6]="Mckinnon";
street[6]="557 Ivy Avenue";
city[6]="Jasper";
state[6]="KY";
zip[6]="88960";
amount[6]=50;
date[6]="2007-08-31";


firstName[7]="Kris";
lastName[7]="Levesque";
street[7]="542 Upton Avenue";
city[7]="Delphi";
state[7]="KY";
zip[7]="88793";
amount[7]=100;
date[7]="2007-08-31";


firstName[8]="Basilia";
lastName[8]="Lu";
street[8]="851 Flad Court";
city[8]="Jasper";
state[8]="KY";
zip[8]="88633";
amount[8]=500;
date[8]="2007-09-02";


firstName[9]="Ginny";
lastName[9]="Rainey";
street[9]="657 Dawson Lane";
city[9]="Youngston";
state[9]="KY";
zip[9]="88873";
amount[9]=50;
date[9]="2007-09-03";

Open in new window

<html>
<head>
<!-- 
   New Perspectives on JavaScript
   Tutorial 10
   Case Problem 3

   The Lighthouse
   Author: 
   Date:   

   Filename:         clist.htm
   Supporting files: data.js, lhouse.css, logo.jpg, newdata.js

-->
<title>The Lighthouse</title>
<link href="lhouse.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="data.js"> </script>
<script type="text/javascript" src="newdata.js"> </script>
</head>

<body onLoad="makeTable();">
<form name="donations" id="donations" action="">
<div id="title">
   <img src="logo.jpg" alt="The Lighthouse" />
   The Lighthouse<br />
   543 Oak Street<br />
   Delphi, KY &nbsp;&nbsp;89011<br/>
   (542) 555-7511
</div>

<div id="data_entry">
   <table>
   <tr>
      <td>Contributors</td>
      <td id="totalContr"></td>
   </tr>
   <tr>
      <td>Total</td>
      <td id="totalAmt"></td>
   </tr>
   </table>

   <table>
   <tr><td colspan="2"><h3>Enter a New Contributor</h3></td></tr>
   <tr>
      <td>First Name</td><td><input name="fname" id="fname" /></td>
   </tr>
   <tr>
      <td>Last Name</td><td><input name="lname" id="lname" /></td>
   </tr>
   <tr>
      <td>Street</td><td><input name="street" id="street" /></td>
   </tr>
   <tr>
      <td>City</td><td><input name="city" id="city" /></td>
   </tr>
   <tr>
      <td>State</td>
      <td><select name="state" id="state">
      <option>AL</option><option>AK</option><option>AZ</option><option>AR</option>
      <option>CA</option><option>CO</option><option>CT</option><option>DE</option>
      <option>DC</option><option>FL</option><option>GA</option><option>HI</option>
      <option>ID</option><option>IL</option><option>IN</option><option>IA</option>
      <option>KS</option><option>KY</option><option>LA</option><option>ME</option>
      <option>MD</option><option>MA</option><option>MI</option><option>MN</option>
      <option>MS</option><option>MO</option><option>MT</option><option>NE</option>
      <option>NV</option><option>NH</option><option>NJ</option><option>NM</option>
      <option>NY</option><option>NC</option><option>ND</option><option>OH</option>
      <option>OK</option><option>OR</option><option>PA</option><option>RI</option>
      <option>SC</option><option>SD</option><option>TN</option><option>TX</option>
      <option>UT</option><option>VT</option><option>VA</option><option>WA</option>
      <option>WV</option><option>WI</option><option>WY</option>
      </select>
      </td>
   </tr>
   <tr>
      <td>Zip</td><td><input name="zip" id="zip" /></td>
   </tr>
   <tr>
      <td>Amount</td><td><input name="amount" id="amount" /></td>
   </tr>
   <tr>
      <td>Date</td><td><input name="date" id="date" /></td>
   </tr>
   <tr>
      <td colspan="2" id="buttoncell1">
         <input type="button" value="Add Contributor" onClick="addRecord()" />
      </td>
   </tr>
   </table>
</div>

<div id="report">
   <p><input value="Remove Checked Items" type="button" onClick="removeRecords()" /></p>

   <table id="ctable">
   <tr><th colspan="5">Contributor List</th>
   </tr>
   <tr id="titleRow">
      <th>Remove</th>
      <th>Date</th>
      <th>Name</th>
      <th>Address</th>
      <th>Amount</th>
   </tr><tr id="emptyRow"><td class="rc"><input type="checkbox" /></td><td></td><td></td><td></td><td class="ac"></td></tr>
   </table>
</div>

</form>
</body>
</html>

Open in new window

/*
   New Perspectives on JavaScript
   Tutorial 10
   Case Problem 3

   Author: 
   Date:   

   Filename: newdata.js


   Function List:
      updateTotals(phrase, pnum)
      Updates contents of the table cells "totalContr" and "totalAmt" displaying 
      the total number of contributors and the total contributions

   makeTable()
      Populates the contributors table with the entries of the 8 data arrays by
      calling the addRow() function for each item in the arrays.

   addRow(i)
      Adds a row to the contributors using data from the 8 data arrays who index
      value equals "i".

   addRecord()
      Adds a new record to the end of the 8 data arrays and then calls the addRow() function
      to add a new row to the contributors table and the updateTotals() function to
      update the tables cells displaying the total number of contributors and
      contributions.

    removeRecord(index)
       Removes a record from the eight data arrays whose index value equals index.

    removeNode(node)
       Removes a node from a node tree, and returns a reference to the node's previous sibling.

    removeRecords()
       Loops through the rows in the contributors table checking whether the remove
       checkbox has been selected. For each selected checkbox, the table row is removed
       and the corresponding entries in the 8 data arrays are removed. The updateTotals()
       function is then called.

*/




//display the total number of contributors in the table cells whose ids are "totalContr" and "totalAmt"
function updateTotals() {
	// within the totalContr table cell, display the length of the amount array
    totalC = document.getElementById("totalContr");
	totalC.innerHTML = amount.length;
	// create a variable name totalContributions and set its intital value to 0
	var totalContributions = 0;
	/* create a for loop that loops trhough each entry in the amount array. 
	Each time through the loop increase the value of the totalContributions variable by the amount in the current entry in
	the amount array */
	for (var i=0; i <amount.length; i++) {
	    totalContributions += parseInt(amount[i]);	
	}
	// within the totalAmt table cell, display the value of the totalContributions variable
	document.getElementById("totalAmt").innerHTML = totalContributions;
}

   

//creates the contributors table by adding new table rows for each of the entries in the eight data arrays
function makeTable() {
	//Create a variable named headingRow that references the table row with the id "titleRow".
	//This row contains the titles from the contributors table. 
    var headingRow = document.getElementById("titleRow");
	//Create a second variable named blankRow that references the table row with the id "emptyRow"
	var blankRow = document.getElementById("emptyRow");
	/* Use the cloneNode() method to clone the blankRow node.  
	Set the value of the deep variable to true in order to copy the entire node tree.  Store this document fragment in a
	variable named dataRow.
	*/
	var dataRow = blankRow.cloneNode(true);
	/*
	Create a for loop that loops through the entries in the amount array.  For each entry call the addRow() function using
	the value of the counter variable in the for loop as the parameter value in the addRow() function.
	*/
	for (var i=0; i<amount.length; i++) {
	    addRow(i);	
	}
	//Call the updateTotals() function  
	updateTotals();
}



/* a function to add a single row to the contributors table, extracting information from the eight data arrays. addRow() has a single parameter named index equal to the array index number from which data is to be taken. */
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow.*/
    newRow = dataRow.cloneNode(true);	
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the text string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	newRow.childNodes[3].innerHTML = date[index];
    newRow.childNodes[5].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[7].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[9].innerHTML = amount[index];
	/*  If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)    */
	if (index == 0) { 
	    blankRow.parentNode.replaceChild(newRow, blankRow) 
	}
    else { 
	    headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  
	}
	
}

// a function to create a new contributor record based on the values entered by the user in the web form
function addRecord() {
	// Create a variable named recordNum equal to the length of the amount array.
    recordNum = amount.length;
	/*
	Set the value of first[recordNum] to the value of the fname field from the donations Web form.  
	Set the value of last[recordNum] to the value of the lname field.  
	Set the value of the street array item to the value of the street field
	set the value of the city array item to the value of the city field.  
	Determine which state option has been selected by the user and store the text of the selected option in the state arry
	item. 
	Set the value of the zip, amount, and date array items to the values of the zip, amount, and date fields in the
	donations Web form.  
	*/
	firstName[recordNum] = document.getElementById("fname").value;
	lastName[recordNum] = document.getElementById("lname").value;
	street[recordNum] = document.getElementById("street").value;
	city[recordNum] = document.getElementById("city").value;
	state[recordNum] = document.getElementById("state").value;
	zip[recordNum] = document.getElementById("zip").value;
	amount[recordNum] = document.getElementById("amount").value;	
	date[recordNum] = document.getElementById("date").value;
	//Call the addRow() function using the value of the recordNum variable as the parameter value.
	addRow(recordNum);
	//Call the updateTotals() function.   
	updateTotals();
	
}

/*a funtion to remove a record from each of the eight data arrays. the function has a single parameter "index" that indicates the array item to remove */
function removeRecord(index) {
	/* Use the splice() method to remove the item from the firstName array whose index value equals the value of the index
	parameter.  Remove only one array item.
	*/
	firstName.splice(index,1);
	// Repeat step for the lastName, street, city, state, zip, amount, and date arrays. 
	lastName.splice(index,1);
	street.splice(index,1);
	city.splice(index,1);
	state.splice(index,1);
	zip.splice(index,1);
	amount.splice(index,1);
	date.splice(index,1);
}
 

/* a function whose purpose is to remove a node from a node tree and then return a reference to the node's previious siblings. The single parameter "node" represents the ode hyou want to remove */
function removeNode(node) {
	// Create a variable named prevNode referencing the node's previous sibling. 
	var prevNode = node.previousSibling;
	//Use the removeChild() method to remove the node.  (Hint: Apply the removeChild() method to the node's parent node.)
	prevNode.parentNode.removeChild(prevNode);
	//Return the prevNode variable from the function.      
	return prevNode;
}
 
  
/* Create the removeRecords() function, whose purpose is to remove contributor records from the contributor table and the eight data arrays if the check box for the record has been checked in the contributor table. */
function removeRecords() {
	//  Create a variable named headerRow referencing the row with the id "titleRow".  
	var headerRow;
	ctable.document.getElementById("titleRow") = headerRow;
	// Create a variable named recordNum equal to the length of the amount array.
	var recordNum = amount.length;
	/* Create a for loop that uses familial references, starting with the node variable, n, equal to the first sibling of
	the headerRow node and proceeding to the next sibling (the next table row) until there is no next sibling.
	Within the for loop, decrease the value of the recordNum varialbe by 1.  
	Then, insert an if condition that tests whether the name of the current node is "TR" (a table row).  
	If it is, insert a second if condition that tests whether the check box within the first table cell of the current ro
	has been selected.  (Hint: Reference the check box using the reference n.firstChild.firstChild.)  
	*/
	for ( n = 0; n < headerRow.childNodes.length; n++) {
	recordNum = recordNum - 1;
	if (headerRow.childNodes[n].name = "TR") {
	/*  If the check box has been checked, then: (1) Call the removeRecord() function using the recordNum as the parameter
	value, and (2) Let the node counter, n, be equal to the value returned by the removeNode() function using the n as the
	parameter value. */
  	if (n.firstChild.firstChild != "") {
    removeRecord(recordNum);
	n = removeNode(n)};
	};
	//After the for loop has finished, call the updateTotals() function to update the contribution totals in the Web page.
	updateTotals(); }
}

Open in new window

Top Expert 2015

Commented:
Same problem still exists as described in my post ID:35776323.

A few other problems:
You reference amount.length in the makeTable function, but on page load, amount has zero length. Consider using firstName.length
Your addRow function refers to childNodes[7] for example but I'm only counting five child nodes in the empty row.
You are referencing headingRow, blankRow, dataRow, recordNum as if they were global variables but they are never initialized as such.
You should initialize all variables using the var keyword as in var firstName = new Array();
Do yourself a favor and comment out this line: updateTotals(); in the makeTables function until you have the initial table filled in and working. There are additional problems with the updateTotals function that will prevent the page from loading. Better to take it one step at a time.

Author

Commented:
Did you notice that all the arrays are initialized in the data.js file? Does this change anything?

This was the js file provided to us and the second file that the htm file is referencing. Attached above.

Top Expert 2015
Commented:
I did see the data.js file and that cleared some things up, namely the initialization of the arrays. Although, I still think you should get into the habit of using the var keyword to initialize variables. The data.js file reference is fine where it is but the newData.js file reference is not going to work where you have it because it contains references to objects that do not exist when the makeTable function is called on page load. You should move that reference to the bottom of the markup just before the closing body tag then fix the other problems. By the way, use onload="" not onLoad="", all lowercase.

Author

Commented:
Ok,

I'm calling it a day. I realize that a lot of the habits being taught and enforced are not well respected these days. I'm stuck however because I have to hand in a web site that follows the instructions.

I have fixed the childNodes referencing problem: 1,2,3,4. I have mucked around with the newData.js file to point where the total is correct, but the dynamic table is empty. FF and IE don't log any errors.

I've got an ancient text book, and no idea what I can do to fix this. Can you be specific and help me to recognize my errors and to correct them.

That's a lot to ask, I get it. Thanks for the advice so far.

Top Expert 2015

Commented:
I thought I was being specific in pointing out the problems. I have to be careful not to run afoul of EE rules for student assignments. Can you tell me what bullet points in ID:35776690 you are not clear on.

Did you comment out the call to updateTotals as I suggested? That will shorten the execution of the code temporarily and bypass any problems that exist beyond loading the dynamic table.

As for getting the dynamic table loaded, the changes you need to make are minor but the problems are enough to make the whole execution of the javascript hang and never get to the end and that's why you don't see any errors in IE or FF.

Did you prevent the re-initialization of the variables headerRow and dataRow as I suggested in ID:35776221?

Just keep posting your code as you get it updated and we can pinpoint the remaining problems.

Author

Commented:
Thank you,

I'm new at this as you can probably tell. I will upload again after work. I have so many comments that I need to go through it line by line and check again that I am doing as the textbook instructs. I think I am. I want to clean the entire thing up once it is working, but I will leave the comments in for now to ensure I'm following instructions.

I declared any null or unidentified variables outside of a function like suggested. And changed lines throughout, I think I mucked it up a bit so I'll clean everything up and post again in 5 hours or so.

Just by talking me through you are helping me quite a bit, the course forum is frankly useless. So thanks for the dialog, sincerely.

Till then
Top Expert 2015

Commented:
I guess we are in completely different time zones because five hours from you last post would be shortly after midnight. I'll keep an eye on my email. The changes you need to make to get this working are minor, but as you have discovered, programming is an unforgiving discipline. One character out of place and it fails.

Author

Commented:
Yah, I am not in North America so you guess right.

I commented out the updateTotals() function like suggested and the dynamic table is loading! :) One problem is the <br> in line 105 is not actually calling a line break. I've quoted out the comments in the exact same way and they are working so I'm confused why +", " will work but +" <br>" will not.

I'm not sure about the updateTotals() for obvious reasons, nor the removeRecords() function, because I have not been able to remove or add records during my previous tests.

Still no errors to report, which I suppose it a good thing. It's very nice to read that you think the problems are minor - what a relief!

I'll attach the updated "newData.js" file to this post.
/*
 

   Filename: newdata.js


   Function List:
      updateTotals(phrase, pnum)
      Updates contents of the table cells "totalContr" and "totalAmt" displaying 
      the total number of contributors and the total contributions

   makeTable()
      Populates the contributors table with the entries of the 8 data arrays by
      calling the addRow() function for each item in the arrays.

   addRow(i)
      Adds a row to the contributors using data from the 8 data arrays who index
      value equals "i".

   addRecord()
      Adds a new record to the end of the 8 data arrays and then calls the addRow() function
      to add a new row to the contributors table and the updateTotals() function to
      update the tables cells displaying the total number of contributors and
      contributions.

    removeRecord(index)
       Removes a record from the eight data arrays whose index value equals index.

    removeNode(node)
       Removes a node from a node tree, and returns a reference to the node's previous sibling.

    removeRecords()
       Loops through the rows in the contributors table checking whether the remove
       checkbox has been selected. For each selected checkbox, the table row is removed
       and the corresponding entries in the 8 data arrays are removed. The updateTotals()
       function is then called.

*/



/*
// updateTotals() displays the total number of contributors in the table cells whose ids are "totalContr" and "totalAmt"
function updateTotals() {
	// within the totalContr table cell, display the length of the amount array
	totalContr = document.getElementById("totalContr");
	totalContr.innerHTML = amount.length;
	// create a variable name totalContributions and set its intital value to 0
	var totalContributions = 0;
	/* create a for loop that loops trhough each entry in the amount array. 
	Each time through the loop increase the value of the totalContributions variable by the amount in the current entry in
	the amount array 
	for (var i=0; i <amount.length; i++) {
	    totalContributions += parseInt(amount[i]);	
	}
	// within the totalAmt table cell, display the value of the totalContributions variable
	document.getElementById("totalAmt").innerHTML = totalContributions;
}
*/
var dataRow;
var blankRow;
var headingRow;

//creates the contributors table by adding new table rows for each of the entries in the eight data arrays
function makeTable() {
	//Create a variable named headingRow that references the table row with the id "titleRow".
	//This row contains the titles from the contributors table. 
    headingRow = document.getElementById("titleRow");
	//Create a second variable named blankRow that references the table row with the id "emptyRow"
	blankRow = document.getElementById("emptyRow");
	/* Use the cloneNode() method to clone the blankRow node.  
	Set the value of the deep variable to true in order to copy the entire node tree.  Store this document fragment in a
	variable named dataRow.
	*/
	dataRow = blankRow.cloneNode(true);
	/*
	Create a for loop that loops through the entries in the amount array.  For each entry call the addRow() function using
	the value of the counter variable in the for loop as the parameter value in the addRow() function.
	*/
	for (var i=0; i<amount.length; i++) {
	    addRow(i);	
	}
	//Call the updateTotals() function  
	//updateTotals();
}


var newRow;
/* a function to add a single row to the contributors table, extracting information from the eight data arrays. addRow() has a single parameter named index equal to the array index number from which data is to be taken. */
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow. */
	newRow = dataRow.cloneNode(true);
   
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the text string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	
	
	newRow.childNodes[1].appendChild(document.createTextNode(date[index]));
	newRow.childNodes[2].appendChild(document.createTextNode(lastName[index]+", " +firstName[index]));
	newRow.childNodes[3].appendChild(document.createTextNode(street[index]  +" <br/> " +city[index] +", " +state[index] +zip[index]));
	newRow.childNodes[4].appendChild(document.createTextNode(amount[index]));
	
	/*  If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  */
	if (index == 0) { blankRow.parentNode.replaceChild(newRow, blankRow) };
	/* If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)*/
	if (index !== 0) { headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  };
}

var recordNum;

// addRecord() creates a new contributor record based on the values entered by the user in the web form
function addRecord() {
	// Create a variable named recordNum equal to the length of the amount array. 
	recordNum = amount.length;
   
	//Set the value of first[recordNum] to the value of the fname field from the donations Web form.  
	firstName[recordNum] = data_entry.document.getElementById("fname").value;
	//Set the value of last[recordNum] to the value of the lname field.  
	lastName[recordNum] = data_entry.document.getElementById("lname").value;
	//Set the value of the street array item to the value of the street field
	street[recordNum] = data_entry.document.getElementById("street").value;
	//set the value of the city array item to the value of the city field
	city[recordNum] = data_entry.document.getElementById("city").value;
	/* Determine which state option has been selected by the user and store the text of the selected option in the state
	array item. */
	state[recordNum] = data_entry.document.getElementById("state").value;
	/* 	Set the value of the zip, amount, and date array items to the values of the zip, amount, and date fields in the
	donations Web form. */
	zip[recordNum] = data_entry.document.getElementById("zip").value;
	amount[recordNum] = data_entry.document.getElementById("amount").value;	
	date[recordNum] = data_entry.document.getElementById("date").value;
	
	dataRow = createRow();
	//Call the addRow() function using the value of the recordNum variable as the parameter value.
	addRow(recordNum);
	//Call the updateTotals() function.   
	//updateTotals();
	
}

/*removeRecord() removes a record from each of the eight data arrays. the function has a single parameter "index" that indicates the array item to remove */
function removeRecord(index) {
	/* Use the splice() method to remove the item from the firstName array whose index value equals the value of the index
	parameter.  Remove only one array item.	*/
	firstName.splice(index,1);
	// Repeat the steps for the lastName, street, city, state, zip, amount, and date arrays. 
	lastName.splice(index,1);
	street.splice(index,1);
	city.splice(index,1);
	state.splice(index,1);
	zip.splice(index,1);
	amount.splice(index,1);
	date.splice(index,1);
}
 

/* aremoveNode() removes a node from a node tree and then returns a reference to the node's previious siblings. The single parameter "node" represents the node you want to remove */
function removeNode(node) {
	// Create a variable named prevNode referencing the node's previous sibling. 
	var prevNode = node.previousSibling;
	//Use the removeChild() method to remove the node.  (Hint: Apply the removeChild() method to the node's parent node.)
	prevNode.parentNode.removeChild(prevNode);
	//Return the prevNode variable from the function.      
	return prevNode;
}
 
var headerRow;  
var recordNum;
/* the removeRecords() function removes contributor records from the contributor table and the eight data arrays if the check box for the record has been checked in the contributor table. */
function removeRecords() {
	//  Create a variable named headerRow referencing the row with the id "titleRow".  
	
	ctable.document.getElementById("titleRow") = headerRow;
	// Create a variable named recordNum equal to the length of the amount array.
	recordNum = amount.length;
	/* Create a for loop that uses familial references, starting with the node variable, n, equal to the first sibling of
	the headerRow node and proceeding to the next sibling (the next table row) until there is no next sibling.
	Within the for loop, decrease the value of the recordNum varialbe by 1.  
	Then, insert an if condition that tests whether the name of the current node is "TR" (a table row).  
	If it is, insert a second if condition that tests whether the check box within the first table cell of the current row
	has been selected.  (Hint: Reference the check box using the reference n.firstChild.firstChild.)  
	*/
	for ( n = 0; n < headerRow.childNodes.length; n++) {
	recordNum = recordNum - 1;
	if (headerRow.childNodes[n].name = "TR") {
	/*  If the check box has been checked, then: (1) Call the removeRecord() function using the recordNum as the parameter
	value, and (2) Let the node counter, n, be equal to the value returned by the removeNode() function using the n as the
	parameter value. */
  	if (n.firstChild.firstChild != "") {
    removeRecord(recordNum);
	n = removeNode(n)};
	};
	//After the for loop has finished, call the updateTotals() function to update the contribution totals in the Web page.
	//updateTotals(); 
	}
}

Open in new window

Top Expert 2015

Commented:
Sorry for the delays. The time zone difference is not working out well for you. Also, I am sitting in an arena waiting to see my daughter's college graduation ceremony.

I tried your code at 6 AM, but it hung at newRow.childNodes(... line in addRow function. Is that working for you? You were using innerHTML before and that worked for me.

Author

Commented:
Hmm, The table was working. I was just concerned about the updateTotals() and removeRecords() function.

I can switch it back, I searched online quite a bit trying to sort out my issues and thought I had it working. Maybe not.

Can you help me to get this working? Let me know if you revert back to my previous code and help me to correct the errors with the updateTotals() and removeRecords() functions? When you have time of course.
Top Expert 2015

Commented:
I steered you wrong early on, now i need to correct myself. What you had originally for loading the dynamic table works correctly.

    newRow.childNodes[3].innerHTML = date[index];
    newRow.childNodes[5].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[7].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[9].innerHTML = amount[index];

I know you don't have much flexibility with how you code this, but the method of accessing childNodes by index is not the best practice but we will stick with it for now.

I'll have a look at the other functions.
Top Expert 2015
Commented:
Your updateTotals function works fine as is.

The addRecord function has a few minor problems.

"document" is the second highest level, so there should not be anything before it except "window" as in window.document. This statement would not refer to any object: data_entry.document.getElementById("fname").value

All you really need then is: document.getElementById("fname").value to access the text box values

dataRow = createRow(); refers to a non-existant function and you don't need it anyway because the index of the new row is known so the next line takes care of adding the new row: addRow(recordNum);

Here's another incorrect reference in the removeRecords function: ctable.document.getElementById("titleRow") = headerRow;


Author

Commented:
Oh thank you so much.

It is so close, and you were right just a few fixes away. Here's the only error left the Contributors and Totals display boxes are blank. They should read 10 and 1800 when you first load the page, respectively. Maybe my updateTotals() function isn't fine the way it is?

I can add a new contributor! The dynamic table is correct!! I'm so so close and very excited. Hopefully for the last time, here you go.
/* 

   Filename: newdata.js


   Function List:
      updateTotals(phrase, pnum)
      Updates contents of the table cells "totalContr" and "totalAmt" displaying 
      the total number of contributors and the total contributions

   makeTable()
      Populates the contributors table with the entries of the 8 data arrays by
      calling the addRow() function for each item in the arrays.

   addRow(i)
      Adds a row to the contributors using data from the 8 data arrays who index
      value equals "i".

   addRecord()
      Adds a new record to the end of the 8 data arrays and then calls the addRow() function
      to add a new row to the contributors table and the updateTotals() function to
      update the tables cells displaying the total number of contributors and
      contributions.

    removeRecord(index)
       Removes a record from the eight data arrays whose index value equals index.

    removeNode(node)
       Removes a node from a node tree, and returns a reference to the node's previous sibling.

    removeRecords()
       Loops through the rows in the contributors table checking whether the remove
       checkbox has been selected. For each selected checkbox, the table row is removed
       and the corresponding entries in the 8 data arrays are removed. The updateTotals()
       function is then called.

*/

// updateTotals() displays the total number of contributors in the table cells whose ids are "totalContr" and "totalAmt"
function updateTotals() {
	// within the totalContr table cell, display the length of the amount array
	totalContr = document.getElementById("totalContr");
	totalContr.innerHTML = amount.length;
	// create a variable name totalContributions and set its intital value to 0
	var totalContributions = 0;
	/* create a for loop that loops trhough each entry in the amount array. 
	Each time through the loop increase the value of the totalContributions variable by the amount in the current entry in
	the amount array */
	for (var i=0; i <amount.length; i++) {
	    totalContributions += parseInt(amount[i]);	
	}
	// within the totalAmt table cell, display the value of the totalContributions variable
	document.getElementById("totalAmt").innerHTML = totalContributions;
}

var dataRow;
var blankRow;
var headingRow;

//creates the contributors table by adding new table rows for each of the entries in the eight data arrays
function makeTable() {
	//Create a variable named headingRow that references the table row with the id "titleRow".
	//This row contains the titles from the contributors table. 
    headingRow = document.getElementById("titleRow");
	//Create a second variable named blankRow that references the table row with the id "emptyRow"
	blankRow = document.getElementById("emptyRow");
	/* Use the cloneNode() method to clone the blankRow node.  
	Set the value of the deep variable to true in order to copy the entire node tree.  Store this document fragment in a
	variable named dataRow.
	*/
	dataRow = blankRow.cloneNode(true);
	/*
	Create a for loop that loops through the entries in the amount array.  For each entry call the addRow() function using
	the value of the counter variable in the for loop as the parameter value in the addRow() function.
	*/
	for (var i=0; i<amount.length; i++) {
	    addRow(i);	
	}
	//Call the updateTotals() function  
	//updateTotals();
}


var newRow;
/* a function to add a single row to the contributors table, extracting information from the eight data arrays. addRow() has a single parameter named index equal to the array index number from which data is to be taken. */
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow. */
	newRow = dataRow.cloneNode(true);
   
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the text string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	
	
    newRow.childNodes[1].innerHTML = date[index];
    newRow.childNodes[2].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[3].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[4].innerHTML = amount[index];
	
	/*If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  */
	if (index == 0) { blankRow.parentNode.replaceChild(newRow, blankRow) };
	/* If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)*/
	if (index !== 0) { headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  };
}

var recordNum;

// addRecord() creates a new contributor record based on the values entered by the user in the web form
function addRecord() {
	// Create a variable named recordNum equal to the length of the amount array. 
	recordNum = amount.length;
   	//Set the value of first[recordNum] to the value of the fname field from the donations Web form.  
	firstName[recordNum] = document.getElementById("fname").value;
	//Set the value of last[recordNum] to the value of the lname field.  
	lastName[recordNum] = document.getElementById("lname").value;
	//Set the value of the street array item to the value of the street field
	street[recordNum] = document.getElementById("street").value;
	//set the value of the city array item to the value of the city field
	city[recordNum] = document.getElementById("city").value;
	/* Determine which state option has been selected by the user and store the text of the selected option in the state
	array item. */
	state[recordNum] = document.getElementById("state").value;
	/* 	Set the value of the zip, amount, and date array items to the values of the zip, amount, and date fields in the
	donations Web form. */
	zip[recordNum] = document.getElementById("zip").value;
	amount[recordNum] = document.getElementById("amount").value;	
	date[recordNum] = document.getElementById("date").value;
	
	//Call the addRow() function using the value of the recordNum variable as the parameter value.
	addRow(recordNum);
	//Call the updateTotals() function.   
	updateTotals();
	
}

/*removeRecord() removes a record from each of the eight data arrays. the function has a single parameter "index" that indicates the array item to remove */
function removeRecord(index) {
	/* Use the splice() method to remove the item from the firstName array whose index value equals the value of the index
	parameter.  Remove only one array item.	*/
	firstName.splice(index,1);
	// Repeat the steps for the lastName, street, city, state, zip, amount, and date arrays. 
	lastName.splice(index,1);
	street.splice(index,1);
	city.splice(index,1);
	state.splice(index,1);
	zip.splice(index,1);
	amount.splice(index,1);
	date.splice(index,1);
}
 

/* aremoveNode() removes a node from a node tree and then returns a reference to the node's previious siblings. The single parameter "node" represents the node you want to remove */
function removeNode(node) {
	// Create a variable named prevNode referencing the node's previous sibling. 
	var prevNode = node.previousSibling;
	//Use the removeChild() method to remove the node.  (Hint: Apply the removeChild() method to the node's parent node.)
	prevNode.parentNode.removeChild(prevNode);
	//Return the prevNode variable from the function.      
	return prevNode;
}
 
var headerRow;  
var recordNum;
/* the removeRecords() function removes contributor records from the contributor table and the eight data arrays if the check box for the record has been checked in the contributor table. */
function removeRecords() {
	//  Create a variable named headerRow referencing the row with the id "titleRow".  
	document.getElementById("titleRow") = headerRow;
	// Create a variable named recordNum equal to the length of the amount array.
	recordNum = amount.length;
	/* Create a for loop that uses familial references, starting with the node variable, n, equal to the first sibling of
	the headerRow node and proceeding to the next sibling (the next table row) until there is no next sibling.
	Within the for loop, decrease the value of the recordNum varialbe by 1.  
	Then, insert an if condition that tests whether the name of the current node is "TR" (a table row).  
	If it is, insert a second if condition that tests whether the check box within the first table cell of the current row
	has been selected.  (Hint: Reference the check box using the reference n.firstChild.firstChild.)  
	*/
	for ( n = 0; n < headerRow.childNodes.length; n++) {
	recordNum = recordNum - 1;
	if (headerRow.childNodes[n].name = "TR") {
	/*  If the check box has been checked, then: (1) Call the removeRecord() function using the recordNum as the parameter
	value, and (2) Let the node counter, n, be equal to the value returned by the removeNode() function using the n as the
	parameter value. */
  	if (n.firstChild.firstChild != "") {
    removeRecord(recordNum);
	n = removeNode(n)};
	};
	//After the for loop has finished, call the updateTotals() function to update the contribution totals in the Web page.
	updateTotals(); 
	}
}

Open in new window

Author

Commented:
Ok, so previewing in my last post I noticed that I forgot to remove a comment tag in front of line 80 that called the updateTotals() function.

So here's the interesting thing, and I may be willing to live with it. Once I remove that comment post, everything seems to be working in FF, but the contributors and amount display boxes are still blank in IE.

Is there a quick fix? If not, after all these hours, I'm ready to move on and just preview the final result in FF.
Top Expert 2015
Commented:
Remember what I said about getting into the habit of using the var keyword to initialize variables? On line 42 you introduce a variable called totalContr but it's not initialized with the var keyword. That's why IE does not display the totals. Other browsers will tolerate the missing var keyword.

The updateTotals call in makeTable is still commented out in line 80.

Author

Commented:
Thank you, I fixed the comment issue on line 80, added the var keyword and everything is working.

I didn't realize that IE needs us to initialize all variables with var. I get that now and will correct this with all future functions.

You have helped me so much, so much more than the course forum ever has.

Thanks again. Sincerely!
Top Expert 2015

Commented:
Thanks for the points.

Does the "Remove Checked Items" button need to function? There are a number of problems with it, both with syntax and logic.

Author

Commented:
It works if I refresh the browser, I thought that this was correct because the first 10 items are stored in an array. If I add an additional item, check "remove" and CTRL+R than it is removed, otherwise no.

I am just so happy that the table is working, and no errors are reported, I guess I can live with it for now.

If you have more advice, then I'll never say no. I'm learning quite a bit via this forum.
Top Expert 2015

Commented:
I cannot get the Remove Checked Items function to do anything using the code you posted last. Refreshing the browser does not help. Did you change that code?

I also wanted to show you a more reliable way to build a dynamic table. Using the childNodes collection as an array (i.e. childNodes[3]) is problematic. Different browsers have different  criteria for what constitutes a "child" and the collection size can vary slightly from one browser to the next. This will through off your indexes. The method below does not depend on the childNode collection nor does it depend on the use of innerHTML which is technically not part of the w3c specification. Try this:

In your html, remove all tags from inside the empty row except the checkbox td:

<tr id="emptyRow">
      <td class="rc"><input type="checkbox" /></td>
   </tr>

Then use this code in the addRow function to build each table cell:

        var cell = document.createElement('td');
      var txt = document.createTextNode(date[index]);
      var br = document.createElement('br');
      cell.appendChild(txt);
      newRow.appendChild(cell);
      cell = document.createElement('td');
      txt = document.createTextNode(lastName[index] + ", " + firstName[index]);
      cell.appendChild(txt);
      newRow.appendChild(cell);
      cell = document.createElement('td');
      txt = document.createTextNode(street[index]);
      cell.appendChild(txt);
      cell.appendChild(br);
      txt = document.createTextNode(city[index] + ", " + state[index] + " " +  zip[index]);
      cell.appendChild(txt);
      newRow.appendChild(cell);
      cell = document.createElement('td');
      cell.setAttribute('class', 'ac');
      txt = document.createTextNode(amount[index]);
      cell.appendChild(txt);
      newRow.appendChild(cell);

Author

Commented:
Sorry it took me so long to respond, I've been working on the other programs in this assignment. I couldn't get your method to work.

I started with function addRow(){
// insert your code
}

saved and recalled the html and nothing loaded, should I make further changes throughout the newdata.js file?

Top Expert 2015

Commented:
The alternate code I provided was only supposed to replace this part of the addRow function:

    newRow.childNodes[1].innerHTML = date[index];
    newRow.childNodes[2].innerHTML = lastName[index] + ", " + firstName[index];
    newRow.childNodes[3].innerHTML = street[index] + "<br>" + city[index] + ", " + state[index] + zip[index];
    newRow.childNodes[4].innerHTML = amount[index];

The full addRow function is pasted below.
function addRow(index) {
	/* Use the cloneNode() method to clone the dataRow document fragment you created in the makeTable() function.  Set the
	value of the deep parameter to true.  Store this document fragment in the variable newRow. */
	newRow = dataRow.cloneNode(true);
   
	/* Change the content of newRow's second child node to the value of the date array using the current index. Change the
	content of newRow's third child node to the text string "lastName, firstName" where lastName and firstName are the
	values of the lastName and firstName arrays using the current index. Change the content of newRow's fourth child node to
	the text string "street<br />city, state, zip" where street, city, state, and zip are the current values from the
	street, city, state, and zip arrays. Change the content of newRow's fifth child node to the value of the amount array.
	*/
	var cell = document.createElement('td');
	var txt = document.createTextNode(date[index]);
	var br = document.createElement('br');
	cell.appendChild(txt);
	newRow.appendChild(cell);
	cell = document.createElement('td');
	txt = document.createTextNode(lastName[index] + ", " + firstName[index]);
	cell.appendChild(txt);
	newRow.appendChild(cell);
	cell = document.createElement('td');
	txt = document.createTextNode(street[index]);
	cell.appendChild(txt);
	cell.appendChild(br);
	txt = document.createTextNode(city[index] + ", " + state[index] + " " +  zip[index]);
	cell.appendChild(txt);
	newRow.appendChild(cell);
	cell = document.createElement('td');
	cell.setAttribute('class', 'ac');
	txt = document.createTextNode(amount[index]);
	cell.appendChild(txt);
	newRow.appendChild(cell);
	/*If the value of the index variable equals 0, meaning that this is the first row being added to the contributor
	table, then use the replaceChild() method to replace the blankRow node with newRow.  (Hint: Apply the replaceChild()
	method to the blankRow.parentNode node)  */
	if (index == 0) { blankRow.parentNode.replaceChild(newRow, blankRow) };
	/* If the index variable is not equal to 0, then insert the newRow node before the
	next sibling of the headingRow node. (Hint: Apply the insertBefore() method to the headingRow.parentNode node)*/
	if (index !== 0) { headingRow.parentNode.insertBefore(newRow, headingRow.nextSibling)  };
}

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial