...

View Full Version : Adding/removing table rows



nick2price
09-26-2012, 12:05 AM
Hi guys. A posted a similar question before, but I have come across a different issue now. Basically, I have a table with some rows

<table class="table1">
<tr>
<td class="title">1:</td>
<td><input type="text" placeholder="Giving" class="selector" name="giving2" autocomplete="off"/></td>
<td><input type="text" placeholder="Getting" class="selector" name="getting2" autocomplete="off"/></td>
<td><input type="text" name="popupdate2" id="popupdate2" class="popupdate" value="When" /></td>
</tr>

<tr>
<td class="title">2:</td>
<td><input type="text" placeholder="Giving" class="selector" name="giving2" autocomplete="off"/></td>
<td><input type="text" placeholder="Getting" class="selector" name="getting2" autocomplete="off"/></td>
<td><input type="text" name="popupdate2" id="popupdate2" class="popupdate" value="When" /></td>
</tr>
</table>

Further down the table I have two buttons which will add/remove more rows. The rows which are added contain the exact same td's as the default rows.


var stdContent = "<td class='title'>xx:</td>\n" +
"<td><input type='text' placeholder='Giving' class='selector' name='givingxx' autocomplete='off'/></td>\n" +
"<td><input type='text' placeholder='Getting' class='selector' name='gettingxx' autocomplete='off'/></td>\n" +
"<td><input type='text' name='popupdatexx' id='popupdatexx' class='popupdate' value='When' /></td>\n";
var newno = 3;
function addTableRow() {
var newrow = document.createElement('tr');
// give your table an id..
var theTable = document.getElementById('table1');

theTable.appendChild(newrow);
var newcontent = stdContent.replace('xx', newno);
newrow.innerHTML = newcontent;
newno++;
}

To remove a row, I basically do


var rws;
function deleteTableRow(obj){
obj=document.getElementById(obj);
rws=obj.getElementsByTagName('tr');
obj.removeChild(rws[rws.length-1]);
newno--;
}

My first question is why will the remove rows function only remove dynamically added rows. By this, I mean I can only delete rows which have been added, and I cannot delete rows which are created in my original table.

Secondly, if I am using the same class for the datepicker, why wont they work with dynamically added rows?

Any information appreciated.

Cheers

Old Pedant
09-26-2012, 12:41 AM
Because a <tr> is *NOT* a child of the <table>, unless you (mistakenly) made it so dynamically.

When generated via HTML, a <tr> is a child of the <tbody>. And so a grandchild of the <table>.

Example (that works):



<html>
<body>
<table id="theTable">
<tr><td>row 1</td></tr>
<tr><td>row 2</td></tr>
<tr><td>row 3</td></tr>
<tr><td>row 4</td></tr>
</table>
<input id="theButton" type="button" value="remove last row"/>
<script type="text/javascript">
document.getElementById("theButton").onclick =
function() {
var tbl = document.getElementById("theTable");
var tbody = tbl.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");
if ( rows.length > 0 )
{
tbody.removeChild( rows[rows.length-1] );
}
}
</script>
</body>
</html>

When you generate new <tr>s, you should always make then children of the <tbody>, not directly children of the <table>.

Old Pedant
09-26-2012, 12:51 AM
This code is actually *NOT* the preferred way to add a row to a table:


function addTableRow() {
var newrow = document.createElement('tr');
// give your table an id..
var theTable = document.getElementById('table1');
theTable.appendChild(newrow);
...

The better way is this:


function addTableRow() {
var tbl = document.getElementById("theTable");
var newrow = tbl.insertRow(tbl.rows.length);


Complete working example:


<html>
<body>
<table id="theTable">
<tr><td>row 1</td></tr>
<tr><td>row 2</td></tr>
<tr><td>row 3</td></tr>
<tr><td>row 4</td></tr>
</table>
<input id="theButton" type="button" value="remove last row"/>
<input id="otherButton" type="button" value="clone last row"/>
<script type="text/javascript">
document.getElementById("theButton").onclick =
function() {
var tbl = document.getElementById("theTable");
var tbody = tbl.getElementsByTagName("tbody")[0];
var rows = tbody.getElementsByTagName("tr");
if ( rows.length > 0 )
{
tbody.removeChild( rows[rows.length-1] );
}
}
document.getElementById("otherButton").onclick =
function() {
var tbl = document.getElementById("theTable");
var newrow = tbl.insertRow(-1);
var newcell = newrow.insertCell(-1);
newcell.innerHTML = "row " + tbl.rows.length;
}
</script>
</body>
</html>

Old Pedant
09-26-2012, 12:57 AM
Regarding the datepicker: The code for the datepicker looks for all elements with that given class WHEN THE PAGE IS LOADED. It attaches AT LEAST an onclick event handler to each such element.

When you add a row dynamically, you don't notify the date picker that there is a new element with that class, so it doesn't have a chance to attach the needed onclick handler.

Cloning the HTML of the elements does *NOT* clone the event handlers for those elements.

nick2price
09-26-2012, 01:00 AM
Ah, I see. Is tbody relatively new, because I never remember using it when I used tables a while back. So now it lets me remove all the rows, including the default ones, which is good. One more quick question though which is slightly JQuery, but it happens on some normal fields aswell. One of the fields in a table row is


<input type="text" name="popupdepartdate2[]" id="popupdepartdate2" class="popupdatepicker" value="Depart" />


Now they all use the same class, basically because they use the same datepicker. The date picker displays fine for the rows which are in the original table. It doesnt display though for the new rows which are added. The new rows which have this field have the same class name, so not to sure why this happens? And when I check it with firebug, it has the right class name. The only thing I can think of is this having something to do with the JQuery for the datepicker being processed before the new rows are added, but then how could I get around this?

Nick

Old Pedant
09-26-2012, 01:12 AM
The only thing I can think of is this having something to do with the JQuery for the datepicker being processed before the new rows are added,
Yes, that's what I said.


but then how could I get around this?

By finding the jQuery code that needs to be called to set up the handlers for the added rows and then invoking it properly.

Old Pedant
09-26-2012, 01:16 AM
Is tbody relatively new, because I never remember using it when I used tables a while back.

Well, possibly newer than <table>. I first remember seeing it in 1999, but I saw <table> in 1996. Dunno if it was there prior to that.

Modern browsers all automatically give you a <tbody>, even if you don't explicitly code one. But you can, indeed, explicitly code it. Just as you can also explicity code <thead> and <tfoot>.

http://www.w3schools.com/tags/tag_tbody.asp

nick2price
09-26-2012, 01:17 AM
Kool, thanks for your reply, I will look into that now. I just wanted to quickly ask you a question about your add and remove functions though. I tested them because they looked neater than what I had, but although it adds and removes the rows, it doesnt add the td's with the appropiate fields. In a sense, what I am doing is cloning the previous rows (changing the id's of the new fields) which is why it may actually be better to use JQuery for this. But with the code you demonstrated, was that actually suppossed to add the required fields, or just create a new row with nothing in it?

Nick

Old Pedant
09-26-2012, 01:23 AM
My code was strictly a demo. Had nothing (directly) to do with yours.

Yes, I saw that you are using innerHTML to clone the <td>s.

Personally, for only 3 <td>s, I wouldn't do so. I'd use insertCell and DOM properties, instead. But you can use innerHTML, if you want.

nick2price
09-26-2012, 01:26 AM
Thank you very much for all your help, I really appreciate it. I have learned a lot of new things and now I think its time for me to tidy everything up!!

Old Pedant
09-26-2012, 01:37 AM
See, instead of using innerHTML and then readjusting everything, you could do this:


var tbl = document.getElementById("theTable");
var newrow = tbl.insertRow(-1);

var td0 = newrow.insertCell(-1);
td0.className ="title";
td0.appendChild( document.createTextNode( tbl.rows.length + ":" ) );

var td1 = newrow.insertCell(-1);
var inp1 = document.createElement("input");
inp1.type="text";
inp1.placeholder = "Giving";
inp1.className = "selector";
inp1.name = "giving" + tbl.rows.length;
inp1.autocomplete = "off"; // ??? or false???
td1.appendChild(inp1);

var td2 = newrow.insertCell(-1);
var inp2 = document.createElement("input");
inp2.type="text";
inp2.placeholder = "Getting";
inp2.className = "selector";
inp2.name = "getting" + tbl.rows.length;
inp2.autocomplete = "off"; // ??? or false???
td2.appendChild(inp2);

var td3 = newrow.insertCell(-1);
var inp3 = document.createElement("input");
inp3.type="text";
inp3.className = "popupdate";
inp3.name = inp3.id = "popupdate" + tbl.rows.length;
inp3.value = "when";
... code here to attach the calendar events to this element...
td3.appendChild(inp3);

That really isn't that much code, and it's much clearner than using innerHTML.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum