dynamically add a table row with onclick

C

cool2005

I tried to dynamically add/clone a <tr> from an existing <tr> to a
<table> but the problem
is that I need to have a "onclick" event handler in the <tr>.


I have tried following

A. approach 1.

1. find the <tr> that I will insert <tr>s right after it
2. get content (collection of outerHTML of those <tr>s to be
inserted)
3. use insertAdjacentHTML to perform the inserting.

This approach failed with a "runtime error" at step 3. The code is
below


function loadSubRows222(tr_id) {

var doc = top.mainFrame.listFrame.document;
var table = doc.getElementById("tree_table");

//swDebugInfo(table.outerHTML, "1111");
var tb = table.children[0];
var trs = tb.children;
var sel = null;
var isEnd = false;


for (var i=0; i<trs.length; i++) {
if (trs.id==tr_id) {

if (i==trs.length-1) {
isEnd = true;
} else {
sel = trs;
}
break;
}
}
if (sel==null && !isEnd) {
alert("Selected row not found.");
return;
}

var pn = doc.getElementById(tr_id);
pn.loaded = '1';
var doc2 = top.hiddenFrame.document;
var table2 = doc2.getElementById("subListTable");
//swDebugInfo(table2.outerHTML, "hiddenFrame.document");
var tb2 = table2.children[0];
var ttt = tb2.innerHTML;
sel.insertAdjacentHTML("afterEnd", ttt);
}

B. Approach 2.

1. find the <tr> that I will insert <tr>s right after it
2. create a <tr> using createElement("tr"), say newTr
3. assign outerHTM of the new <tr> content to newTr's outerHTML
(I have to use outerHTML instead of innerHTM since I need to
carry the onclick)
This failed too with the "runtime error" when assign outerHTML

C. approach 3
1. find the <tr> that I will insert <tr>s right after it
2. create a <tr> using createElement("tr"), say newTr
3. copy/construct the newTr copyTr (see below)
trying to assign onclick as a field of newTr failed
since the "onclick" was not recongnized as an event
handler.



function copyTr(doc, t1, t2) {

t1.id = t2.id;
t1.loaded = t2.loaded;
t1.level = t2.level;

//get the content of onclick
var oStr = t2.outerHTML;
var i=oStr.indexOf(" onclick=\"");
var j=oStr.indexOf("\"", i+10);

//assignment
t1.onClick = oStr.substring(i+10, j);


var ch = t2.children;
for (var i=0; i<ch.length; i++) {
var newTd = doc.createElement("td");
newTd.innerHTML = ch.innerHTML;
t1.appendChild(newTd);
}


}



My target is IE.

Any suggestion will be very appreciated.

thanks
 
M

Martin Honnen

cool2005 said:
I tried to dynamically add/clone a <tr> from an existing <tr> to a
<table> but the problem
is that I need to have a "onclick" event handler in the <tr>.

How about
var newRow = oldRow.cloneNode(true);
and if the onclick handler is really missing then doing
newRow.onclick = oldRow.onclick;
If you don't want to copy the onclick but create a new one then make
sure you assign a function object e.g.
newRow.onclick = function (evt) {
// code goes here
};
 
R

RobG

cool2005 said:
I tried to dynamically add/clone a <tr> from an existing <tr> to a
<table> but the problem
is that I need to have a "onclick" event handler in the <tr>.


I have tried following

A. approach 1.

1. find the <tr> that I will insert <tr>s right after it
2. get content (collection of outerHTML of those <tr>s to be
inserted)
3. use insertAdjacentHTML to perform the inserting.

This approach failed with a "runtime error" at step 3. The code is
below

Inserting HTML into a table element to create a new TR will modify
the table's innerHTML property, which is read-only in IE:

"...the innerText and innerHTML properties of the table and tr
objects are read-only."

<URL:http://msdn.microsoft.com/workshop/author/tables/buildtables.asp>

The following also in regard to innerHTML:

"The property is read/write for all objects except the following, for
which it is read-only: COL, COLGROUP, FRAMESET, HTML, STYLE, TABLE,
TBODY, TFOOT, THEAD, TITLE, TR. The property has no default value."

<URL:http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/innerhtml.asp>

You can use innerHTML to modify the content of a cell (TR), but
generally it is better to use DOM methods unless you are just doing
something simple like replacing text.

As Martin suggested, the simplest way to create a copy of an existing
row is with cloneNode. The following example clones the last row in
the table and adds a new clone after it (tested in IE and Firefox).
I've included a document.all method, but I'm not sure how well
cloneNode is supported by older versions of IE that require it.


<script type="text/javascript">
function cloneRow(t){
if (document.getElementById( {
t = document.getElementById(t);
} else if (document.all) {
t = document.all[t];
} else { return;}

if (t.nodeName && 'TABLE' == t.nodeName){
var oldRow = t.rows[t.rows.length - 1];
var newRow = oldRow.cloneNode(true);
oldRow.parentNode.insertBefore(newRow, oldRow.nextSibling);
}
}
</script>

<input type="button" value="Add another row by cloning"
onclick="cloneRow('tableA')">
<table id="tableA">
<tr onclick="alert('hi from row ' + this.rowIndex)";>
<td>Click this to activate the tr onlcick</td>
</tr>
</table>

A word of caution: the element and its content are cloned exactly, so
if the tr has an id, the new row will have an identical id. You
should change it before adding it to the table.

Similarly, any enclosed form or other elements will be cloned exactly
too, so you may need to change their ID or NAME also as appropriate.

Lastly, when adding TR elements to a table, IE requires you to add
them to the tbody, not the table (HTML 4 conforming browsers will add
a tbody element regardless if it's been coded in the HTML). In the
code above, I've avoided the issue by adding the new row to the
parent of the old row.

Another approach would be to put the id on a tbody element and add
the new row to that.

...
if (t.nodeName && 'TBODY' == t.nodeName){
var oldRow = t.rows[t.rows.length - 1];
var newRow = oldRow.cloneNode(true);
t.insertBefore(newRow, oldRow.nextSibling);
}
...

<table>
<tbody id="tableA">
<tr onclick="alert('hi from row ' + this.rowIndex)";>
...



[...]
 
C

cool2005

The cloneNode won't work in my case.
The <tr> I cloned from resided in a hidden frame.
The "onclick" in new <tr> (from cloning) worked until
the hidden frame is resubmit (means the content of
the hidden frame was changed - the <tr> as the cloned source
was gone). It looks like that the new cloned <tr> still have some
sort of connection to the <tr> it was cloned from. The "onclick"
worked only when the source <tr> existed.

Let me redescribe my problem:

I want to create a <tr> with a variable "onclick" (varible means
the onclick contains row dependent info - can not be defined
as a static "function" - function doesn't help since the arguments
are row dependent). I actually need to "clone or create" this <tr>s
from a
hidden frame returned from the server.

The problem is that I can not assign the outerHTML that include the
"onclick" to a created new <tr> nor set "onclick" as an attribute.

I really appreciate the suggestions from both of you.

Any further thought?

thanks
 
C

cool2005

I forgot to mantion:

After cloning I tried to use insertBefore and failed with a
error of "invalid argument":

for (var i=0; i<trs2.length; i++) {
newTr = trs2.cloneNode(true);
tb.insertBefore(newTr, sel);
sel = newTr;
}
where sel is the row to insert before and trs2 is the
<tr> in the hidden frame to clone from.

Then I tried insertAdjacentElement as

for (var i=0; i<trs2.length; i++) {
newTr = trs2.cloneNode(true);
sel.insertAdjacentElement("afterEnd", newTr);
sel = newTr;
}
in this case sel is the one to be inserted after.
The "onclick" worked after the statements above.
But it won't work if I do

for (var i=0; i<trs2.length; i++) {
newTr = trs2.cloneNode(true);
sel.insertAdjacentElement("afterEnd", newTr);
sel = newTr;
}

refreshHidden();

Any suggestion will be appreciated
 
C

cool2005

OK, problem solved: I was able to create a function and passed
row related info with "this" and used "this" as the only argument to
make the onclick the same for all rows.

I then cloneNode from the same table and changed cell info.

The key help is the cloneNode!

thanks a lot!!
 
R

RobG

cool2005 said:
I forgot to mantion:

After cloning I tried to use insertBefore and failed with a
error of "invalid argument":

for (var i=0; i<trs2.length; i++) {
newTr = trs2.cloneNode(true);
tb.insertBefore(newTr, sel);
sel = newTr;
}


Seems you got it working, but for the record if you are just inserting
after the current rows (assuming tb is the tbody and that trs is the
collection of rows you are cloning):

for (var i=0, j=trs2.length; i<j; i++) {
tb.appendChild(trs2.cloneNode(true));
}

or

var i=0;
do {
tb.appendChild(trs.cloneNode(true));
} while(trs[++i]);

[...]
 
R

Richard Cornford

RobG wrote:
... (HTML 4 conforming browsers will
add a tbody element regardless if
it's been coded in the HTML).
<snip>

In HTML 4 the opening and closing TBODY tags are optional, so their
absence from source mark-up is irrelevant, the mark-up still specifies
the creation of a TBODY element. The TBODY _is_ coded in the HTML by the
act of placing a TR directly inside a TABLE.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top