views:

336

answers:

4

I am using the following javascript to dynamically add rows in a table:-

 var trObj = document.createElement('tr');
 trObj.setAttribute('name', 'dynamicTR');

 var tdObjEmpty = document.createElement('td');
 tdObjEmpty.setAttribute('colspan', '2');
 tdObjEmpty.innerHTML = ' '
 trObj.appendChild ( tdObjEmpty );

 var tdObj = document.createElement('td');
 tdObj.setAttribute('colspan', '15');
 tdObj.innerHTML = postingDivObj.innerHTML; // <-- copy the innerHTML
 trObj.appendChild ( tdObj ); 
 parentObj = approvedDisapprovedTableObj.getElementsByTagName('tbody')[0];     
 targetElementObj = getNthTr ( parentObj, rowIndex1 - extraTr ); // <-- it will just return the trObject, 
 if ( targetElementObj ){
  parentObj.insertBefore(trObj, targetElementObj.nextSibling )
 }else{
  //alert ( 'targetElementObj is null' );
 }

This is working in FF as well as in IE, [ but, i guess, in case of IE name and colspan attribute is not set using setAttribute. but not sure ] .

Now, when i have to remove all rows which are dynamically created i use:-

dynamicTRObjs = document.getElementsByName('dynamicTR');
    if ( dynamicTRObjs ){
         parentObj = approvedDisapprovedTableObj.getElementsByTagName('tbody')[0];
         for ( i = 0 ; i < dynamicTRObjs.length; i++ ){       
          parentObj.removeChild ( dynamicTRObjs[i] );    
          extraTr++;
         } 
        }

This code removes all dynamically created TRs. and it works fine in FF, but not in IE.
Also in case of IE dynamicTRObjs.length is always 0,whereas in FF dynamicTRObjs.length it gives correct number of rows. Please tell me what i am missing here.

+1  A: 

http://www.quirksmode.org/dom/w3c%5Fcore.html

getElementsByName() is not working well in IE6-8

I would suggest that you some other way of identifying that element if you want cross browser usability.

MikeEL
oh great, now what should i do? Please suggest something Mike
Rakesh Juyal
you could give them a common id
Richard
`you could give them a common id` let me try this too
Rakesh Juyal
ID attributes have to be unique per document instance. The function is document.getElementById() - singular.
Michiel Kalkman
I always just keep an array of my dynamic objects in memory, because finding them later is expansive. Avoid working with the DOM when you can.
MikeEL
+5  A: 

The HTML4 spec list of attributes lists elements that the name attribute can be set on. Tables and table elements are not on the list. The most obvious option is one of,

  • Keep references to alle TRs you create so you don't have to find them in the DOM
  • Set a className on your TRs and use selectors to find them

That Firefox uses getElementsByName 'correctly' and IE does not is something others have run into too. I'd just avoid using name here altogether.

Michiel Kalkman
+1 `Set a className on your TRs and use selectors to find them` i am going to use it now, i think it should work.
Rakesh Juyal
var arr = document.getElementsByClassName('dynamicTR'); #=> Array of TRsThat should do it.
Michiel Kalkman
`getElementsByClassName` will not work in IE :( http://www.quirksmode.org/dom/w3c%5Fcore.html
Rakesh Juyal
@Rakesh Juyal : doh! I forgot that. If you don't mind polluting global scope you can push all the dynamic TRs to an array there. Not very clean, I admit, but it'll work.
Michiel Kalkman
+1  A: 

I know, it's a bit off-topic, but let me give you a small advice on using getElementsByName functionality in a browser. It will not help you to solve the current problem (which is because TR can not have Name attribute ), but it will definitely help you to prevent future problems which you will met.

getElementsByName returns you collection, which always keeps itself up-to-date with the DOM tree. This means, that at the moment when you remove ONE item with removeChild, the SIZE of collection will be decreased. So, if you will removing nodes and keep relying on the length of the collection, not all nodes will be removed.

Check this example of your for loop:

  • Collection length is 3, Your i var is 0, i < length
    You remove child,
  • collection length is 2, your i var is 1, i < length
    you remove child,
  • collection length is 1 and your i var i 2.
    Condition i< length == true that means that for loop will stop, BUT some of the elements will still be presented in the DOM.

Choose any solution you like to fix this, but try to avoid relying on the length of the Collection which is returned by getElementsByTagName.

Good luck

nemisj
+1  A: 

since I'm not the only one to suggest avoidance of low-level DOM manipulation, here's an example: an untested implementation with jquery. not exactly an answer to your question, but a comment would lose the formatting.

var mkTd = function (colspan, html)
{
    return $('<td />')
        .attr('colspan', colspan)
        .html(html)
    ;
}

var addRow = function (rowNr)
{
    var target = $('#approvedDisapprovedTableObj tbody tr:eq('+rowNr+')');
    if (!target.length) {
        //alert ( 'target is null' );
        return;
    }
    target.after(
        $('<tr />')
            .addClass('dynamicTR')
            .append(mkTd(2, '&nbsp;')
            .append(mkTd(15, $('#postingDivObj').html()))
    );
}
var dropRows = function ()
{
    $('.dynamicTR').remove();
}

notice that the expression $('.dynamicTR').remove() achieves the same as your

dynamicTRObjs = document.getElementsByName('dynamicTR');
if ( dynamicTRObjs ){
    parentObj = approvedDisapprovedTableObj.getElementsByTagName('tbody')[0];
    for ( i = 0 ; i < dynamicTRObjs.length; i++ ){                          
        parentObj.removeChild ( dynamicTRObjs[i] );                      
        extraTr++;
    } 
}

IMO it's obvious that the benefits are huge.

just somebody
+1 for writing the code using a framework, though we'll just have to agree to disagree on the universal application of frameworks.
Michiel Kalkman