PDA

View Full Version : Resolved Adding and Deleting table row style



bigalo
05-01-2008, 07:20 PM
I currently have a script that adds and deletes table rows. However, I do not know how to change the code to make the new rows have the same style as the default row (the row style id needed to add is named "even" which shows the grey border etc...). Does anyone know how to make this change?



<html>
<head>
<title>Adding and Removing Rows from a table using DHTML and JavaScript</title>
<script language="javascript">

//add a new row to the table
function addRow()
{
//add a row to the rows collection and get a reference to the newly added row
var newRow = document.all("tblGrid").insertRow();

//add 3 cells (<th>) to the new row and set the innerHTML to contain text boxes

var oCell = newRow.insertCell();
oCell.innerHTML = "<input type='text' name='t1'>";

oCell = newRow.insertCell();
oCell.innerHTML = "<input type='text' name='t2'>";

oCell = newRow.insertCell();
oCell.innerHTML = "<span style='text-align:center'><input type='text' name='t3'></span>";

oCell = newRow.insertCell();
oCell.innerHTML = "<input type='button' value='Delete' onclick='removeRow(this);'/>";
}

//deletes the specified row from the table
function removeRow(src)
{
/* src refers to the input button that was clicked.
to get a reference to the containing <tr> element,
get the parent of the parent (in this case case <tr>)
*/
var oRow = src.parentElement.parentElement;

//once the row reference is obtained, delete it passing in its rowIndex
document.all("tblGrid").deleteRow(oRow.rowIndex);
}

</script>
<style>
/*---------------------------------*/
/* Table Grid */
/*---------------------------------*/

/* The initial default settings for the Table */
table.grid {
width: 100%;
height: 20px;
border: 1px solid #6688A4;
border-collapse: collapse;
}

/* Style for the title header of the table */
tr#header {
border-bottom: 1px solid #6688A4;
background-color: #6688A4;
color: #FFFFFF;
font-family: Arial;
font-weight: bold;
font-size: 11px;
padding-left: 0px;
height: 20px;
}

tr#header th{
padding-left: 12px;
color: #FFFFFF;
font-family: arial;
font-size: 11px;
text-align: left;
}


/* Style for the row containing the MAIN PARAMETERS for the table (row after the Title row) */
tr#mainDiv {
background-color: #CCCCCC;
color: #000;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 18px;
}

tr#mainDiv th{
text-align: center;
font-family: arial;
font-size: 11px;
font-weight: normal;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}



/* Style for the EVEN data rows with the white background */
tr#even {
background-color: #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 28px;
}

tr#even th{
padding-left: 5px;
color: #333333;
font-family: arial;
font-size: 11px;
font-weight:normal;
text-align: left;
padding-right: 5px;
border: 1px solid #E6E6E6;
}

tr#even th#yr{
text-align: center;
}

tr#even th#inc{
color: #008000;
}

tr#even th#dec{
color: #EF0303;
}







</style>
</head>
<body>
Demo of a simple table grid that allows adding and deleting rows using DHTML
and Javascript
<p/>
Try it out - Click on the Delete button to delete the corresponding row. Click Add Row button to insert a new row.
<p/>
<p/>Browser compatility - this sample has been tested to work with IE5.0 and above.
<p/>

<input type="button" value="Add Row" onClick="addRow();" />
<hr>
<!-- sample table grid with 3 columns and 4 rows that are presented by default -->
<table class="grid" id="tblGrid" style="table-layout:fixed" border="0">
<tr id="mainDiv">
<th width="150px">Field1</th>
<th width="150px">Field2</th>
<th width="250px">Field3</th>
<th width="250px">Action</th>
</tr>
<tr id="even">
<th><input type="text" name="t1" /></th>
<th><input type="text" name="t2" /></th>
<th><input type="text" name="t3" /></th>
<th><input type="button" value="Delete" onClick="removeRow(this);" /></th>
</tr>

</table>
<hr>

</body>
</html>

jscheuer1
05-02-2008, 12:24 AM
Technically speaking, and for most practical purposes in javascript, you may only have one element per page with a given id. Style may also be imparted using a class name. In javascript, the way to assign a class name is via the element's className property.

Now, since (from what you say, without dissecting your javascript code, it looks like) you are only assigning the id for style purposes, you might be able to get away with something like so:


el.id='even';

where el represents a variable that references the element you want to assign the id to. That would respond to a selector in your stylesheet like:


#even {
property/value pairs here
}

But even so it is technically invalid, so some browsers may not allow it. If on the other hand, after assigning the id 'even' to more than one element, you try to access that element via javascript using its id as a reference, that will certainly fail. In javascript, each element must have a unique id, or no id.

To assign a class name of 'even', use:


el.className='even';

Then that element (and all elements with that class name) will respond to style in your stylesheet selected like so:


.even {
property/value pairs here
}

You may have any number of elements on a page with the same class name.

For more info on practical ways to do this see this thread:
http://www.dynamicdrive.com/forums/showthread.php?p=141404#post141404

rangana
05-02-2008, 01:36 AM
Yes, John had explained regarding ID's VS. Classes ;)

...NOw i'll go ahead for things that are erroneous. Your example code does'nt work.

...Also, the p tag closes with a slash in the front and not in the back (<p/>) :)

...width is a deprecated attribute (http://www.codehelp.co.uk/html/deprecated.html) :(

...Here's your code...with a number of changes:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Adding and Removing Rows from a table using DHTML and JavaScript
</title>
<script language="javascript">

//add a new row to the table
function addRow()
{
//add a row to the rows collection and get a reference to the newly added row
var newRow = document.getElementById("tblGrid").insertRow(-1);

newRow.className = "even";
//add 3 cells (<th>) to the new row and set the innerHTML to contain text boxes

var oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='text' name='t1'>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='text' name='t2'>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<span style='text-align:center'><input type='text' name='t3'></span>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='button' value='Delete' onclick='removeRow(this);'/>";

}

//deletes the specified row from the table
function removeRow(src)
{
/* src refers to the input button that was clicked.
to get a reference to the containing <tr> element,
get the parent of the parent (in this case case <tr>)
*/
var oRow = src.parentNode.parentNode;

//once the row reference is obtained, delete it passing in its rowIndex
document.getElementById("tblGrid").deleteRow(oRow.rowIndex);

}

</script>
<style>
/*---------------------------------*/
/* Table Grid */
/*---------------------------------*/

/* The initial default settings for the Table */
table.grid {
width: 100%;
height: 20px;
border: 1px solid #6688A4;
border-collapse: collapse;
}

/* Style for the title header of the table */
tr#header {
border-bottom: 1px solid #6688A4;
background-color: #6688A4;
color: #FFFFFF;
font-family: Arial;
font-weight: bold;
font-size: 11px;
padding-left: 0px;
height: 20px;
}

tr#header th{
padding-left: 12px;
color: #FFFFFF;
font-family: arial;
font-size: 11px;
text-align: left;
}


/* Style for the row containing the MAIN PARAMETERS for the table (row after the
Title row) */
tr#mainDiv {
background-color: #CCCCCC;
color: #000;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 18px;
}

tr#mainDiv th{
text-align: center;
font-family: arial;
font-size: 11px;
font-weight: normal;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}



/* Style for the EVEN data rows with the white background */
tr.even {
background-color: #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 28px;
}
tr.even th,tr.even td{
padding-left: 5px;
color: #333333;
font-family: arial;
font-size: 11px;
font-weight:normal;
text-align: left;
padding-right: 5px;
border: 1px solid #E6E6E6;
}

tr.even th#yr{
text-align: center;
}

tr.even th#inc{
color: #008000;
}

tr.even th#dec{
color: #EF0303;
}
</style>
</head>
<body>
<p>
Demo of a simple table grid that allows adding and deleting rows using D
HTML
and Javascript
</p>
<p>
Try it out - Click on the Delete button to delete the corresponding row.
Click Add Row button to insert a new row.
</p>
<p>Browser compatility - this sample has been tested to work with IE5.0
and above.
</p>

<input type="button" value="Add Row" onClick="addRow();" />
<hr>
<!-- sample table grid with 3 columns and 4 rows that are presented by d
efault -->
<table class="grid" id="tblGrid" style="table-layout:fixed" border="0">
<tr id="mainDiv">
<th style="width:150px;">Field1</th>
<th style="width:150px;">Field2</th>
<th style="width:250px;">Field3</th>
<th style="width:250px;">Action</th>
</tr>
<tr class="even">
<th><input type="text" name="t1" /></th>
<th><input type="text" name="t2" /></th>
<th><input type="text" name="t3" /></th>
<th><input type="button" value="Delete" onClick="removeRow(this);" /></th>
</tr>
</table>
<hr>

</body>
</html>

See if it helps :)

jscheuer1
05-02-2008, 06:59 AM
Pretty good rangana! One really should use the DOM to create and insert the inputs, etc. to the cells though.

bigalo
05-02-2008, 01:22 PM
Thank you rangana for your help! Just so you know, this was not my script. I truly know how to code html tags :) Thanks to you both the script works great!

bigalo
05-02-2008, 02:42 PM
Hi rangana,

I have another request if you don't mind. I would like to add a new column on the far left to incorporate the row count (1, 2, 3, ect...) also, I would like to have a Totals footer row appear once the 1st row is added as well as it dissapear if all the rows are deleted. Is that possible?



<html>
<head>
<title>Adding and Removing Rows from a table using DHTML and JavaScript</title>
<script language="JavaScript" type="text/javascript">

//add a new row to the table
function addRow()
{
//add a row to the rows collection and get a reference to the newly added row
var newRow = document.all("tblGrid").insertRow(-1);

newRow.className = "even";
//add 3 cells (<th>) to the new row and set the innerHTML to contain text boxes

var oCell = newRow.insertCell(-1);
oCell.innerHTML = "1";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='text' name='t1'>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='text' name='t2'>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<span style='text-align:center'><input type='text' name='t3'></span>";

oCell = newRow.insertCell(-1);
oCell.innerHTML = "<input type='button' value='Delete' onclick='removeRow(this);'/>";

}

//deletes the specified row from the table
function removeRow(src)
{
/* src refers to the input button that was clicked.
to get a reference to the containing <tr> element,
get the parent of the parent (in this case case <tr>)
*/
var oRow = src.parentElement.parentElement;

//once the row reference is obtained, delete it passing in its rowIndex
document.all("tblGrid").deleteRow(oRow.rowIndex);

}

</script>
<style>
/*---------------------------------*/
/* Table Grid */
/*---------------------------------*/

/* The initial default settings for the Table */
table.grid {
width: 100%;
height: 20px;
border: 1px solid #6688A4;
border-collapse: collapse;
}

/* Style for the title header of the table */
tr#header {
border-bottom: 1px solid #6688A4;
background-color: #6688A4;
color: #FFFFFF;
font-family: Arial;
font-weight: bold;
font-size: 11px;
padding-left: 0px;
height: 20px;
}

tr#header th{
padding-left: 12px;
color: #FFFFFF;
font-family: arial;
font-size: 11px;
text-align: left;
}


/* Style for the row containing the MAIN PARAMETERS for the table (row after the Title row) */
tr#mainDiv {
background-color: #CCCCCC;
color: #000;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 18px;
}

tr#mainDiv th{
text-align: center;
font-family: arial;
font-size: 11px;
font-weight: normal;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}



/* Style for the EVEN data rows with the white background */
tr#even {
background-color: #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 28px;
}

tr#even th,tr.even td{
padding-left: 5px;
color: #333333;
font-family: arial;
font-size: 11px;
font-weight:normal;
text-align: left;
padding-right: 5px;
border: 1px solid #E6E6E6;
}

tr#even th#yr{
text-align: center;
}

tr#even th#inc{
color: #008000;
}

tr#even th#dec{
color: #EF0303;
}

</style>
</head>
<body>


<input type="button" value="Add Row" onClick="addRow();" />
<hr>
<!-- sample table grid with 3 columns and 4 rows that are presented by default -->
<table class="grid" id="tblGrid" style="table-layout:fixed" border="0">
<tr id="mainDiv">
<th width="20px">Row</th>
<th width="150px">Field1</th>
<th width="150px">Field2</th>
<th width="250px">Field3</th>
<th width="250px">Action</th>
</tr>
<!--<tr id="even">
<th>1</th>
<th><input type="text" name="t1" /></th>
<th><input type="text" name="t2" /></th>
<th><input type="text" name="t3" /></th>
<th><input type="button" value="Delete" onClick="removeRow(this);" /></th>
</tr>
<tr id="even">
<th>&nbsp;</th>
<th>Total:</th>
<th><input type="text" name="t3" /></th>
<th><input type="text" name="t3" /></th>
</tr>-->
</table>
<hr>

</body>
</html>

jscheuer1
05-02-2008, 02:46 PM
Stop using innerHTML! If you ever use this code for real form data, you will have countless problems because of it.

bigalo
05-02-2008, 02:50 PM
Stop using innerHTML! If you ever use this code for real form data, you will have countless problems because of it.

What should I use in place of innerHTML?

jscheuer1
05-02-2008, 02:50 PM
Pure DOM methods:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Adding and Removing Rows from a table using DHTML and JavaScript
</title>
<script language="javascript">

//add a Node
function addNode(tag, dat, el){

//create new node and get a reference to it
var newNode = document.createElement(tag);

//add attributes to the node
for (var p in dat)
if(p == 'text')
newNode.appendChild(document.createTextNode(dat[p]));
else if(typeof dat[p] != 'object')
newNode[p] = dat[p];
else for (var sp in dat[p])
newNode[p][sp] = dat[p][sp];

//return it, or if a parent 'el' is supplied append it to the parent and return the parent
if(!el) return newNode;
el.appendChild( newNode );
return el;
}

//add a new row to the table
function addRow()
{
//add a row to the rows collection and get a reference to the newly added row
var newRow = document.getElementById("tblGrid").insertRow(-1);

newRow.className = "even";
//add 4 cells (<td>) to the new row and populate them with elements

var oCell = newRow.insertCell(-1);
addNode('input', {type:'text', name:'t1'}, oCell);

oCell = newRow.insertCell(-1);
addNode('input', {type:'text', name:'t2'}, oCell);

oCell = newRow.insertCell(-1);
oCell.appendChild(addNode('input', {type:'text', name:'t3'}, addNode('span', {style:{textAlign:'center'}})));

oCell = newRow.insertCell(-1);
addNode('input', {type:'button', value:'Delete', onclick:function(){removeRow(this);}}, oCell);

}

//deletes the specified row from the table
function removeRow(src)
{
/* src refers to the input button that was clicked.
to get a reference to the containing <tr> element,
get the parent of the parent (in this case case <tr>)
*/
var oRow = src.parentNode.parentNode;

//once the row reference is obtained, delete it passing in its rowIndex
document.getElementById("tblGrid").deleteRow(oRow.rowIndex);

}

</script>
<style>
/*---------------------------------*/
/* Table Grid */
/*---------------------------------*/

/* The initial default settings for the Table */
table.grid {
width: 100%;
height: 20px;
border: 1px solid #6688A4;
border-collapse: collapse;
}

/* Style for the title header of the table */
tr#header {
border-bottom: 1px solid #6688A4;
background-color: #6688A4;
color: #FFFFFF;
font-family: Arial;
font-weight: bold;
font-size: 11px;
padding-left: 0px;
height: 20px;
}

tr#header th{
padding-left: 12px;
color: #FFFFFF;
font-family: arial;
font-size: 11px;
text-align: left;
}


/* Style for the row containing the MAIN PARAMETERS for the table (row after the
Title row) */
tr#mainDiv {
background-color: #CCCCCC;
color: #000;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 18px;
}

tr#mainDiv th{
text-align: center;
font-family: arial;
font-size: 11px;
font-weight: normal;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}



/* Style for the EVEN data rows with the white background */
tr.even {
background-color: #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 28px;
}
tr.even th,tr.even td{
padding-left: 5px;
color: #333333;
font-family: arial;
font-size: 11px;
font-weight:normal;
text-align: left;
padding-right: 5px;
border: 1px solid #E6E6E6;
}

tr.even th#yr{
text-align: center;
}

tr.even th#inc{
color: #008000;
}

tr.even th#dec{
color: #EF0303;
}
</style>
</head>
<body>
<p>
Demo of a simple table grid that allows adding and deleting rows using D
HTML
and Javascript
</p>
<p>
Try it out - Click on the Delete button to delete the corresponding row.
Click Add Row button to insert a new row.
</p>
<p>Browser compatility - this sample has been tested to work with IE5.0
and above.
</p>

<input type="button" value="Add Row" onClick="addRow();" />
<hr>
<!-- sample table grid with 3 columns and 4 rows that are presented by d
efault -->
<table class="grid" id="tblGrid" style="table-layout:fixed" border="0">
<tr id="mainDiv">
<th style="width:150px;">Field1</th>
<th style="width:150px;">Field2</th>
<th style="width:250px;">Field3</th>
<th style="width:250px;">Action</th>
</tr>
<tr class="even">
<th><input type="text" name="t1" /></th>
<th><input type="text" name="t2" /></th>
<th><input type="text" name="t3" /></th>
<th><input type="button" value="Delete" onClick="removeRow(this);" /></th>
</tr>
</table>
<hr>

</body>
</html>

bigalo
05-02-2008, 02:59 PM
Thanks so much John! As you can see I am a total novice! Would you be able to help with my code change request using updated version?

Request:

I would like to add a new column on the far left to incorporate the row count (1, 2, 3, ect...) also, I would like to have a Totals footer row appear once the 1st row is added as well as it dissapear if all the rows are deleted. Is that possible?


Also, how would you translate this using addnode: oCell.innerHTML = "<input name='' type='text' size='10' class='normal' onFocus=\"this.style.background='#F3F6F9'\" onblur=\"this.style.background='#FFF'\">";

jscheuer1
05-02-2008, 05:02 PM
This needs some refinement, a lot actually, but it's working:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Adding and Removing Rows from a table using DHTML and JavaScript
</title>
<script language="javascript">

//add a Node
function addNode(tag, dat, el){

//create new node and get a reference to it
var newNode = document.createElement(tag);

//add attributes to the node
for (var p in dat)
if(p == 'text')
newNode.appendChild(document.createTextNode(dat[p]));
else if(typeof dat[p] != 'object')
newNode[p] = dat[p];
else for (var sp in dat[p])
newNode[p][sp] = dat[p][sp];

//return it, or if a parent 'el' is supplied append it to the parent and return the parent
if(!el) return newNode;
el.appendChild( newNode );
return el;
}

function totRows(t){
if(typeof t=='number'&&t<4){
var tot=0;
for (var v=document.getElementsByTagName('input'), i = v.length-1; i > -1; --i)
if(v[i].name=='t'+t)
tot += (v[i].value-0);
document.getElementById('t'+t+'t').value=tot;
if(t<3)
totRows(++t);
}else totRows(1);
}


//add a new row to the table
function addRow()
{
//add a row to the rows collection and get a reference to the newly added row
var newRow = document.getElementById("tblGrid").insertRow(-1);
if(document.getElementById('totals')){
addRow.foot = document.getElementById('totals');
addRow.footP = addRow.foot.parentNode;
addRow.foot = addRow.footP.removeChild(addRow.foot);
}

newRow.className = "even";
//add 4 cells (<td>) to the new row and populate them with elements

var oCell = newRow.insertCell(-1);
addNode('span', {className:'counter', text:document.getElementById("tblGrid").rows.length-1}, oCell);

oCell = newRow.insertCell(-1);
addNode('input', {type:'text', name:'t1', onchange:totRows}, oCell);

oCell = newRow.insertCell(-1);
addNode('input', {type:'text', name:'t2', onchange:totRows}, oCell);

oCell = newRow.insertCell(-1);
oCell.appendChild(addNode('input', {type:'text', name:'t3', onchange:totRows}, addNode('div', {style:{textAlign:'center'}})));

oCell = newRow.insertCell(-1);
addNode('input', {type:'button', value:'Delete', onclick:function(){removeRow(this);}}, oCell);

addRow.footP.appendChild(addRow.foot);

}

//deletes the specified row from the table
function removeRow(src)
{
/* src refers to the input button that was clicked.
to get a reference to the containing <tr> element,
get the parent of the parent (in this case case <tr>)
*/
var oRow = src.parentNode.parentNode, oTable = document.getElementById("tblGrid");

//once the row reference is obtained, delete it passing in its rowIndex
oTable.deleteRow(oRow.rowIndex);

for (var c=oTable.rows.length, s=oTable.getElementsByTagName('span'), i = s.length-1; i > -1; --i)
if(s[i].className == 'counter') s[i].firstChild.nodeValue = --c-1;
totRows();
if(oTable.rows.length==2){
addRow.foot = document.getElementById('totals');
addRow.footP = addRow.foot.parentNode;
addRow.foot = addRow.footP.removeChild(addRow.foot);
}

}
window.onload=totRows;
</script>
<style>
/*---------------------------------*/
/* Table Grid */
/*---------------------------------*/

/* The initial default settings for the Table */
table.grid {
width: 100%;
height: 20px;
border: 1px solid #6688A4;
border-collapse: collapse;
}

/* Style for the title header of the table */
tr#header {
border-bottom: 1px solid #6688A4;
background-color: #6688A4;
color: #FFFFFF;
font-family: Arial;
font-weight: bold;
font-size: 11px;
padding-left: 0px;
height: 20px;
}

tr#header th{
padding-left: 12px;
color: #FFFFFF;
font-family: arial;
font-size: 11px;
text-align: left;
}


/* Style for the row containing the MAIN PARAMETERS for the table (row after the
Title row) */
tr#mainDiv {
background-color: #CCCCCC;
color: #000;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 18px;
}

tr#mainDiv th{
text-align: center;
font-family: arial;
font-size: 11px;
font-weight: normal;
border-top: 1px solid #FFFFFF;
border-left: 1px solid #FFFFFF;
border-right: 1px solid #FFFFFF;
}



/* Style for the EVEN data rows with the white background */
tr.even {
background-color: #FFFFFF;
border-left: 1px solid #6688A4;
border-right: 1px solid #6688A4;
height: 28px;
}
tr.even th,tr.even td{
padding-left: 5px;
color: #333333;
font-family: arial;
font-size: 11px;
font-weight:normal;
text-align: left;
padding-right: 5px;
border: 1px solid #E6E6E6;
}

tr.even th#yr{
text-align: center;
}

tr.even th#inc{
color: #008000;
}

tr.even th#dec{
color: #EF0303;
}
</style>
</head>
<body>
<p>
Demo of a simple table grid that allows adding and deleting rows using D
HTML
and Javascript
</p>
<p>
Try it out - Click on the Delete button to delete the corresponding row.
Click Add Row button to insert a new row.
</p>
<p>Browser compatility - this sample has been tested to work with IE5.0
and above.
</p>

<input type="button" value="Add Row" onClick="addRow();">
<hr>
<!-- sample table grid with 3 columns and 4 rows that are presented by d
efault -->
<table class="grid" id="tblGrid" style="table-layout:fixed" border="0">
<tr id="mainDiv">
<th style="width:1em;">#</th>
<th style="width:150px;">Field1</th>
<th style="width:150px;">Field2</th>
<th style="width:250px;">Field3</th>
<th style="width:250px;">Action</th>
</tr>
<tr class="even">
<th><span class="counter">1</span></th>
<th><input type="text" name="t1" onchange="totRows();"></th>
<th><input type="text" name="t2" onchange="totRows();"></th>
<th><div style="text-align:center;"><input type="text" name="t3" onchange="totRows();"></div></th>
<th><input type="button" value="Delete" onClick="removeRow(this);"></th>
</tr>
<tr id="totals" class="even" style="background-color:gray;">
<th style="background-color:#fff;"><span>&nbsp;</span></th>
<th><input type="text" id="t1t" name="t1t" value=0 readonly></th>
<th><input type="text" id="t2t" name="t2t" value=0 readonly></th>
<th><div style="text-align:center;"><input type="text" id="t3t" name="t3t" value=0 readonly></div></th>
<th style="background-color:#fff;"><input type="button" value="Totals"></th>
</tr>
</table>
<hr>

</body>
</html>

Now let's see about that other thing (untested):


addNode('input', {type:'text', size:10, className:'normal',
onfocus:function(){this.style.background='#f3f6f9';},
onblur:function(){this.style.background='#fff'}}, oCell);

If the functions would be used by other nodes, they could be defined separately and then used in addNode like I did the totRows function in the new version of the page above. This is a great savings over innerHTML;

bigalo
05-02-2008, 05:36 PM
This is Great John! I think this will work. I do have a few small requests, maybe I was not specific in my earlier request.

1. I wanted to make the button “Total” to be text.
2. Could the Totals row be hidden if there aren’t any rows? and I just need totals for 2 columns.
3. Instead of starting with 1 row, I wanted to start with 0 rows and no Totals row.
4. To be specific, I wanted 9 columns with the following elements, and only the 2 bolded columns need to be totaled.
[#] [input] [input] [select] [select] [select] [input][input][Action]

I have added a screenshot of how it should look after adding 2 rows. Before adding those rows it should just show the header row.
http://www.geocities.com/bigalo1/addRow.gif

jscheuer1
05-04-2008, 04:37 PM
Sorry to take so long getting back to you, but the code needed, as I mentioned, considerable refinement. And this was, in case I hadn't made myself clear, simply to the code as it was. I have included some of your customization request either here or earlier. However, the setup and maintenance of your code requires more than just the image and short description you furnished in you previous post. And it would best be done by you. I can help guide you through some of the rough spots, but in the spirit of these forums, it is you who supply the bulk of the markup and markup related script code. Although, I might consider scripting this from the HTML code of a table that you would make that shows how things should look after a data row or two are added. I don't believe the script would need to be changed much anyway from its new form I'll be posting below, except perhaps to accommodate the functionality of some of the other elements it looks like you are introducing. Will/should the page output any data to the server as a form using GET or POST?

Some improvements to the code that may not be readily apparent:


The math can now accept and deal properly with negative numbers, if used.
An alert will be given if the user inserts a value that isn't a number.
Totaling occurs onkeyup for faster real time running totals, but will also still update onchange for those cases when the user pastes in the data. However, with paste, there will be a delay until the user changes the focus away from the input. I don't believe there is any way to speed up registering of the change with paste, though I'd be open to finding one if it exists or I can dream one up.
The number of t1, t2, t3 groups, the t# named text input groups isn't hard coded into the script, but is calculated onload, on the basis of how many elements you have in the totals row with an id in the form of t#t. They still need to be numbered sequentially, starting at 1 (ex, name="t1" for a group of sender inputs and id="t1t" for their receiver input).
I changed the way addNode works to give it more functionality and make its use, hopefully more intuitive. You can see examples of it in the code, and I have documented its use at the beginning of the function. It may still be used with the exact same syntax we were using before, if you prefer that, or just inadvertently slip back into using it the old way.
The totals row is now removed and stored on page load, so it will not appear until a row is added. And there are no data rows at first. I may have had it like this in the last version, but the code for it has been streamlined, and the efficiency improved by not removing the totals row except when absolutely necessary.
Markup and css style have been streamlined and validated.


Oh, the code had to be (what with its now extensive comments) attached due to size limitations:

1750

jscheuer1
05-05-2008, 01:50 AM
I hit upon an idea that really simplifies creating the new rows. With it no javascript is required to make all the individual cells, your markup is removed and saved, and subsequently cloned to create each new row. The addNode function is no longer required. All of the upgrades (other than to addNode) mentioned in my previous post are still used. As a result, you can just write out the table using HTML, with header, a single data row, and the totals row. The script will take care of the rest:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Adding and Removing Rows from a table using D HTML and JavaScript</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
/*-------------------*/
/* Table Grid Styles */
/*-------------------*/

/* The initial default settings for the Table */
.grid {
width: 100%;
border: 1px solid #6688a4;
border-collapse: collapse;
table-layout:fixed;
}

/* Style for the top row containing the headings for the table rows */
.topRow {
background-color: #cccccc;
color: #000;
border-top: 1px solid #fff;
border-left: 1px solid #6688a4;
border-right: 1px solid #6688a4;
}
.topRow th {
font: normal 68.75% arial, sans-serif;
border-top: 1px solid #fff;
border-left: 1px solid #fff;
border-right: 1px solid #fff;
}

/* Style for the data rows */
.data {
background-color: #fff;
border-left: 1px solid #6688a4;
border-right: 1px solid #6688a4;
}
.data td {
color: #333;
font: normal 68.75% arial, sans-serif;
padding: 3px 0.46em;
border: 1px solid #e6e6e6;
}

/* Minor adjustments */
th div {
text-align:left;
padding-left:2em;
}
.m1 {
width:2.19%;
text-align:center;
}
.p150 {
width:18.41%;
}
.p250 {
width:30.47%;
}
.gray {
background-color:gray;
}
.cent {
text-align:center;
}
.f110 {
font-size:110%;
}

/*-----------------------*/
/* End Table Grid Styles */
/*-----------------------*/
</style>
<script type="text/javascript">

/* Create Global References to the Totals Row and its parent, remove the row and save it */
function killTot(){
var foot = document.getElementById('totals');
if(!addRow.footP)
addRow.footP = foot.parentNode;
addRow.foot = addRow.footP.removeChild(foot);
}

/* Create Global Reference to the Data Row, remove and save it */
function killDat(){
var dat = document.getElementById('tblGrid').rows[1];
for (var t = dat.getElementsByTagName('input'), i = t.length-1; i > -1; --i)
if(t[i].type=='text') t[i].value='';
addRow.dat = addRow.footP.removeChild(dat);
}

/* Runs on init and each time called by onkeyup and/or onchange of an input */
function totRows(t){
if(!totRows.t&&totRows.setT) totRows.setT(); //Find the number t#t id'ed elements once at startup.
t=typeof t=='number'? t : 1;
/* if argument t (a number) is in range of the t# (numbering starts at 1) named inputs - total up that t# group */
if(t<totRows.t+1){
var tot=0;
for (var v=document.getElementsByTagName('input'), i = v.length-1; i > -1; --i)
if(v[i].name=='t'+t)
tot += v[i].value=='-'? 0 : v[i].value-0;
if(!isNaN(tot))
/* totlas for all t# named inputs in a group go to their corresponding t#t id'ed input */
document.getElementById('t'+t+'t').value = tot;
else if(!totRows.bad) {totRows.bad = 1; alert('Numbers Only Please!'); return;} // error checking
else {totRows.bad = 0; return} // prevent duplicate warning on duplicate event
if(t<totRows.t) // Number of t# input groups to be totaled - if we are in range, increment and run again
totRows(++t);
}
if(!addRow.footP && document.getElementById('totals')){
killTot(); // Runs here only on init to kill and store the totals row.
killDat();
}
}

totRows.setT = function(){ //calculates the number t#t id'ed elements
for (var c=0, v=document.getElementsByTagName('input'), i = v.length-1; i > -1; --i)
if(/^t\d+t$/.test(v[i].id)) c++;
totRows.t = c; totRows.setT=null;
}

//add a new row to the table
function addRow(){
//if no totals footer, add it
if(!document.getElementById('totals')) // If the totals row is absent, bring it back.
addRow.footP.appendChild(addRow.foot);
//add a row to the rows collection and get a reference to the newly added row
var oTable = document.getElementById("tblGrid"), newRow;
addRow.footP.insertBefore(addRow.dat.cloneNode(true), addRow.foot)
oTable.rows[newRow=oTable.rows.length-2].cells[0].firstChild.firstChild.nodeValue=newRow;
}

//deletes the specified row from the table
function removeRow(e){
e=e||window.event;
var src=e.target? e.target : e.srcElement;
/* e refers to the event of the input button being clicked.
to get a reference to the containing <tr> element, we
get the parent of the parent of its srcElement or target (in this case case the <tr>)
*/
var oRow = src.parentNode.parentNode, oTable = document.getElementById("tblGrid");

//once the row reference is obtained, delete it passing in its rowIndex
oTable.deleteRow(oRow.rowIndex);

//renumber rows after deletion
for (var c=oTable.rows.length, s=oTable.getElementsByTagName('span'), i = s.length-1; i > -1; --i)
if(s[i].className == 'counter') s[i].firstChild.nodeValue = --c-1;
totRows(); // Total up, things may have changed
if(oTable.rows.length==2) // If only the header and totals row remain, remove and store totals row
killTot();
}

if(typeof window.addEventListener != 'undefined') //Total up at 0 everything at page load
window.addEventListener('load', totRows, false); //Browsers that don't support one of
else if (typeof window.attachEvent != 'undefined') //these methods can't handle the script anyway
window.attachEvent('onload', totRows);
else alert('To use this page, your browser must be IE version 5 or better,\n'+
' FF, or a near enough equivalent like modern Opera or Safari.');
</script>
</head>
<body>
<noscript><div style="font-weight:bold;color:red;">This Page Requires Javascript Enabled, IE version 5 or better, FF,<br>
or a near enough equivalent like modern Opera or Safari.</div></noscript>
<p>Demo of a simple table grid that allows adding and deleting rows using D HTML and Javascript</p>
<p>Try it out - Click on the Delete button to delete the corresponding row. Click Add Row button to insert a new row.</p>
<p>Browser compatility - this sample has been tested to work with IE5.0 and above.</p>

<div><input type="button" value="Add Row" onclick="addRow();"></div>
<hr>
<table class="grid" id="tblGrid">
<tbody><tr class="topRow">
<th class="m1">#</th>
<th class="p150"><div>Field1</div></th>
<th class="p150"><div>Field2</div></th>
<th class="p250">Field3</th>
<th class="p250"><div>Action</div></th>
</tr>

<tr class="data">
<td class="m1"><span class="counter">1</span></td>
<td><input name="t1" size="16" type="text" onkeyup="totRows();" onchange="totRows();"></td>
<td><input name="t2" size="16" type="text" onkeyup="totRows();" onchange="totRows();"></td>
<td><div class="cent"><input name="t3" type="text" onkeyup="totRows();" onchange="totRows();"></div></td>
<td><input value="Delete" type="button" onclick="removeRow(event);"></td>
</tr>

<tr id="totals" class="data">
<td><span>&nbsp;</span></td>
<td class="gray"><input size="16" id="t1t" name="t1t" value="0" readonly type="text"></td>
<td class="gray"><input size="16" id="t2t" name="t2t" value="0" readonly type="text"></td>
<td class="gray"><div class="cent"><input id="t3t" name="t3t" value="0" readonly type="text"></div></td>
<td><div class="f110">&nbsp;Totals</div></td>
</tr></tbody></table>
<hr>
</body>
</html>

Notes: I believe that some refinements are still in order, but these shouldn't for the most part affect how this is used, but will insulate the code from other scripts and make it modular (applicable to more than one table on a page).

bigalo
05-05-2008, 03:34 PM
John,

I just want to thank you so much for your time and ability to keep improving on something that started out so simple!!! You are truly a JavaScript King!!!!! I've tested most of this code and it's so much more intuitive and easy to customize to my standards. Cheers to you John!!!!

BliarOut
08-01-2008, 11:40 AM
John, can I just say this is utterly fantastic!

I've been trying to code something like this for absolutely ages with no success and this does almost exactly what I want :D

I know this is a lot to ask in a first post, but I don't suppose you could simplify it to remove the requirement for numeric values could you?

I'm trying but I just don't understand it well enough to do it without breaking it :( (I can actually figure out how to remove the totals line all by myself :D)

What I'm trying to do is use this as the basis for entering an initially unknown number of rows into a MySQL table.

Once I have all the rows filled I'd like to know how to pass the js variables contained in each cell over to PHP and execute a MySQL INSERT query at the server.

Normally I'd do something like

$count=count($_POST['ThePostThat ContainsTheLineNumber']);

for ($j=0; $j <$count; $j++)
{
mysql_query("INSERT INTO MyTable (LineNumber, Location, Event, ItemsRequired, ) VALUES ('". $_POST['LineNumber'][$j]."', '". $_POST['Location'][$j]."', '".$_POST['Event'][$j]."', '". $_POST['NewItemsRequired'][$j]."')")or die(mysql_error());
}

But I can't seem to read what's in the cells.

If you could help I'd be eternally grateful.

Regards,

Rob

ETA:

I'm aware that I have to pass the results of the contents of the table to another page.

Having read it few a few times I think I've sussed out how to do it without killing it now! Just remove/comment out any calls to totRows?

All I've got left to do is grab the variables out of the page now.

BliarOut
08-01-2008, 05:13 PM
In the spirit of the forum, and of trying to learn by myself I've almost sussed it. The only thing I can't figure out now is how to access the data that's stored in the text boxes. I know it's there as it remains sticky when you delete a row, but I'll be darned if I can figure out which bit of the code actually holds it :(

Could someone point me to how it retains the values in the text boxes and how I can pass those values onto a MySQL insert station when I've finished adding/deleting/ammending rows.

Pretty pretty please with sugar on top.

My hacking attempts to see what's going on are below.

//add a new row to the table
function addRow(){
//if no totals footer, add it
if(!document.getElementById('totals')) // If the totals row is absent, bring it back.
addRow.footP.appendChild(addRow.foot);
//add a row to the rows collection and get a reference to the newly added row
var oTable = document.getElementById("tblGrid"), newRow;
addRow.footP.insertBefore(addRow.dat.cloneNode(true), addRow.foot)
oTable.rows[newRow=oTable.rows.length-2].cells[0].firstChild.firstChild.nodeValue=newRow;
//Added by RB to put the row numbers into an array. We start at row 3!!!!
if (newRow<2){
myArray = new Array();
myArray[1] = (newRow +2, "Bill"+newRow);
alert ("This is the first row.\nMy Array contains "+myArray);
}else{
//alert ("This isn't the first new row");
myArray[newRow] = (newRow +2, "Bill"+newRow);
alert ("This isn't the first new row\nMy Array now contains "+myArray);
}
//RB mods end.
}

//deletes the specified row from the table
function removeRow(e){
e=e||window.event;
var src=e.target? e.target : e.srcElement;
/* e refers to the event of the input button being clicked.
to get a reference to the containing <tr> element, we
get the parent of the parent of its srcElement or target (in this case case the <tr>)
*/
var oRow = src.parentNode.parentNode, oTable = document.getElementById("tblGrid");
//once the row reference is obtained, delete it passing in its rowIndex
//Added by RB
alert ("My Array contains "+myArray+ " Row "+oRow.rowIndex+" will be deleted");
myArray.splice(oRow.rowIndex, 1)
alert ("My Array now contains "+myArray);
//RB mods end
oTable.deleteRow(oRow.rowIndex);
//renumber rows after deletion
for (var c=oTable.rows.length, s=oTable.getElementsByTagName('span'), i = s.length-1; i > -1; --i)
if(s[i].className == 'counter') s[i].firstChild.nodeValue = --c-1;
//Row below removed by RB to remove totalling functionality
//totRows(); // Total up, things may have changed

if(oTable.rows.length==2) // If only the header and totals row remain, remove and store totals row
killTot();
}