0

As the title suggests, I have created a table which I am populating with a list, and I also have a checkbox next to each element of that table. Finally I have a button labelled Delete. I want to attach that button with the actual delete operation.

Code of the button (it is inside another table):

<tr id="deleteproject" >
                        <td width="180" align="center" background="ButtonBackground.png"
onclick = "deleteRow('plist')">
                            <style="text-decoration:none; display:block; width:100%; 

height:100%">
                                <font size="0.5px"><br/></font>
                                <font id="DeleteProject" face="verdana" color="white">
DELETE</font>
                            </a>
                        </td>
</tr>

The table:

<table ID="plist" border="0" cellpadding="0" cellspacing="0" datasrc="#clicklist"
                        style="WIDTH: 380px">
                        <tr>
                            <td id="projline" width="100%" align="left" valign="middle"
 style="margin-left: 16px;">
                                <input type="checkbox" name="AAA"/>
                                <font size="3" face="Arial">
                                    <a id="proj" href="urn:a">
                                        <span datafld="Name" 

style="margin-left: 20px; line-height: 26px;"></span>
                                    </a>
                                </font>
                            </td>
                        </tr>
                    </table>

rowDelete function in JS:

function deleteRow(tableID) {
      try {
        var table = document.getElementById(tableID);
        var rowCount = table.rows.length;

        for(var i=0; i<rowCount; i++) {
            var row = table.rows[i];
            var chkbox = row.cells[0].childNodes[0];
            if(null != chkbox && true == chkbox.checked)
            {
                table.deleteRow(i);
                rowCount--;
                i--;
            }
        }
        }catch(e)
{
            alert(e);
        }
    }

When I select a checkbox from a row and push the delete button, I get an object error, which I think means something is null or not understood in the JS code.

Iason
  • 209
  • 3
  • 11
  • 38
  • In this line `if (row==currentRow.parentNode.parentNode) {` currentRow is not defined or assigned a value before this. What are you trying to accomplish with this line? – Andy Arndt Mar 01 '16 at 15:21
  • The code for that function was not correct. It is updated now on my original question. Still however, I get the same error. – Iason Mar 01 '16 at 15:30
  • Found this. solution might help you today but this will go a long way. http://weblogs.asp.net/stevewellens/jquery-selector-tester-and-cheat-sheet – Jas Mar 01 '16 at 15:41
  • Could you please share what error are you getting? If you look at the console it might give you a fair idea what is going wrong – Jas Mar 01 '16 at 15:10
  • I'm getting [object error], right after clicking the delete button. – Iason Mar 01 '16 at 15:11
  • That is probably your object is empty or you are trying to access a property which is not there inside the object. – Jas Mar 01 '16 at 15:18
  • I updated the JS function code in my original question. However I'm still getting the same error. Could it be because in the var chkbox = row.cells[0].childNodes[0]; line cells[0] could be the wrong position? – Iason Mar 01 '16 at 15:31

1 Answers1

0

You must create a proper table first. The table is invalid in HTML5 and in HTML4, the button needs to be inside a table. Please read this article.

When I select a checkbox from a row and push the delete button, I get an object error, which I think means something is null or not understood in the JS code.

I don't know where to start ... looking at the JS, you are trying to target rows by referencing them by the TableRow Object? or ChildNode? Either way, the vague error message you are receiving is because you must reference the elements in the DOM as an object. There are several ways to do so in your situation, for example:

Please review the demo and ask questions because I can't make a list of what is wrong and what issues that need to be addressed because it would take hours. The demo's styling is not part of the topic, I just used it because it's a default style I use for tables. The structure of the table is important as much as the JS though. The source itself has been extensively annotated. Please do not hesitate to ask if you have any further questions.

Snippet

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title>delRows</title>
  <style>
    .x th {
      color: #FFF;
      background: #2C7EDB;
      padding: 10px;
      text-align: center;
      vertical-align: middle;
    }
    .x tr:nth-child(odd) {
      background-color: #333;
      color: #FFF;
    }
    .x tr:nth-child(even) {
      background-color: #D3E9FF;
      color: #333;
    }
    .x td {
      border-style: solid;
      border-width: 1px;
      border-color: #264D73;
      padding: 5px;
      text-align: left;
      vertical-align: top;
      position: relative;
    }
    .x thead th:first-child {
      border-top-left-radius: 6px;
    }
    .x thead th:last-child {
      border-top-right-radius: 6px;
    }
    .x tbody tr:last-child th:first-child {
      border-bottom-left-radius: 6px;
    }
    .x tbody tr:last-child td:last-child {
      border-bottom-right-radius: 6px;
    }
    th {
      width: 30%;
    }
    th:first-of-type {
      width: 10%;
    }
    table {
      width: 80%;
    }
  </style>
</head>

<body>
  <table id="T1" class="x">
    <thead>
      <tr>
        <th>
          <input id="btn1" type="button" value="DelRows" onclick="delRows('T1')" )/>
        </th>
        <th>A</th>
        <th>B</th>
        <th>C</th>
      </tr>
    </thead>
    <tbody>
      <tr id="row1">
        <td>
          <input id="chx1" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row2">
        <td>
          <input id="chx2" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row3">
        <td>
          <input id="chx3" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row4">
        <td>
          <input id="chx4" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row5">
        <td>
          <input id="chx5" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row6">
        <td>
          <input id="chx6" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row7">
        <td>
          <input id="chx7" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row8">
        <td>
          <input id="chx8" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row9">
        <td>
          <input id="chx9" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr id="row10">
        <td>
          <input id="chx10" type="checkbox" />
        </td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
    </tbody>
  </table>
  <script>
    function delRows(tableID) {
      
   //1| Take the function's argument and reference it as an id.
      var table = document.getElementById(tableID);

   //2| getElementsByTagName()[0]¹ will find the first† element with the <tbody> tag.
   /* †You can use [0] to specify the first tag, [1] for the second tag, etc. <tbody> is the direct parent of all <tr>, so that's why we want a reference to it */
      var tb = table.getElementsByTagName('tbody')[0];

   //3| Collect all checkboxes that are checked into a NodeList² named 'checked'.
 /* querySelectorAll³ is like getElementBy* on steroids. It accepts a selector as a target to reference, the syntax is like CSS or inside a jQuery object $(selector). Notice the ":checked"⁴ pseudoselector */
      var checked = document.querySelectorAll('input[type="checkbox"]:checked');
    
 //4| Collect all <tr> in <tbody> into a NodeList named 'rows'.
 /* Remember we referenced the <tbody> as var tb on step 2? */
      var rows = tb.querySelectorAll('tr');
    
 //5| Iterate through the checked NodeList from step 3.
 /* When dealing with arrays and array-like objects, you'll need to use a 'for loop' to iterate (or loop)⁵ 90% of the time. */
      for (var i = 0; i < checked.length; i++) {
     
 //6| For every checked checkbox find it's parent's parent and name it 'row'.
 /* In the checked NodeList, there are all of the checked checkboxes so on each loop we are finding that particular checkbox's "grandmother". Example: 
 i = 4 means we are on the 3rd iteration (loop). 
 checked[4] is the third checked checkbox.
 .parentNode⁶ is the parent element of the third checked checkbox--a <td> 
 The second .parentNode is the parent of the <td> which is a <tr> */
      var row = checked[i].parentNode.parentNode;
    
 //7| Remove 'row' from <tbody>
 /* removeChild⁷ needs the parent of the element (or node) that you intend to remove. Thinking ahead, we have the parent of all <tr>: tb (a.k.a. <tbody>) from step 2. */
        tb.removeChild(row);
//8| At this point, i is i+1 we go back to step 5 as long as "i < checked.length".
/* var i = one loop of steps 6, 7, and 8. It started initially as 0 which by design coincides with the 0 count index of arrays and array-like objects like the NodeList checked. i is then incremented by 1 (i++) thereby completing the loop. As long as i is less than the total amount of checked checkboxes, it will continue looping. */
      }
//9| At this point, i is greater than the total amount of checked checkboxes and stops looping thru steps 6, 7, and 8. 
/* This is the end of the function. Sometimes you'll see "return false;", but we didn't need it  because the click event that starts this function is just a button. If we kept the original markup, that used an anchor, then "return false" would be necessary because an anchor by default will jump to a location which is undesirable if you are using the anchor as a button instead. */ 
    }
  </script>
</body>

</html>
Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68