Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 11 of 11
  1. #1
    Regular Coder
    Join Date
    May 2009
    Posts
    160
    Thanks
    71
    Thanked 1 Time in 1 Post

    Adding/removing table rows

    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
    Code:
    <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.
    Code:
    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
    Code:
    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

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    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):
    Code:
    <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>.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    This code is actually *NOT* the preferred way to add a row to a table:
    Code:
    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:
    Code:
    function addTableRow() {
        var tbl = document.getElementById("theTable");
        var newrow = tbl.insertRow(tbl.rows.length);
    Complete working example:
    Code:
    <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>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    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.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #5
    Regular Coder
    Join Date
    May 2009
    Posts
    160
    Thanks
    71
    Thanked 1 Time in 1 Post
    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
    Code:
    <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

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    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.

    Code:
     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.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    nick2price (09-26-2012)

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    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
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    nick2price (09-26-2012)

  • #8
    Regular Coder
    Join Date
    May 2009
    Posts
    160
    Thanks
    71
    Thanked 1 Time in 1 Post
    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

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    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.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    nick2price (09-26-2012)

  • #10
    Regular Coder
    Join Date
    May 2009
    Posts
    160
    Thanks
    71
    Thanked 1 Time in 1 Post
    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!!

  • #11
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,211
    Thanks
    75
    Thanked 4,343 Times in 4,309 Posts
    See, instead of using innerHTML and then readjusting everything, you could do this:
    Code:
        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.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    nick2price (09-26-2012)


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •