开发者

Reordering html table rows

I am trying to push display:none property rows to the bottom of table. However, my code pushes only the first 开发者_StackOverflow中文版tr with display:none property. The second row stays at the same position, and I am not able to push it down to bottom of the table.

<html>
<head>
<script>
  function moveHiddenRows() 
  { 
    var table = document.getElementById('res'); 
    var rows = table.getElementsByTagName('tr'); 
    for (var a=0, b=rows.length; a<b; a++) 
    { 
      if (rows[a].style.display == 'none') 
      { 
        var row = rows[a].parentNode.removeChild(rows[a]); 
        table.appendChild(row); 
      } 
    } 

    for(var i=0;i<rows.length;i++)
    {
      if(i%2==0)
        rows[i].className="even";
      else
        rows[i].className="odd";
    }
  }  
</script>
<style>
  .odd{
    background-color:red;
  }
  .even{
    background-color:yellow;
  }
</style>
</head>
<body onload="javascript:moveHiddenRows();">
  <table id="res">
    <tbody>
      <tr><td>ABC</td></tr>
      <tr><td>asd</td></tr>
      <tr style="display:none;"><td>XYZ</td></tr>
      <tr style="display:none;"><td>asd</td></tr>
      <tr><td>asd</td></tr>
      <tr><td>asd</td></tr>
    </tbody>
  </table>
</body>
</html>


Part of your problem is here:

var table = document.getElementById('res'); 
var rows = table.getElementsByTagName('tr'); 
for (var a=0, b=rows.length; a<b; a++) 
{ 
    if (rows[a].style.display == 'none') 
    { 
        var row = rows[a].parentNode.removeChild(rows[a]); 
        table.appendChild(row); 
    } 
} 

Firstly, don't declare variables inside an if block, javascript only has function scope so better to declare them at the top of the function so the scope is obvious. I'll leave it for you to fix.

Secondly, in IE rows must be added to a tbody element, other browsers used to add them to the tbody if you don't, but lately Firefox has not done that, so add them to a tBody.

Lastly, your problem is that rows is an HTMLCollection, so it's live. When you move the first row, at index 1, the one below it becomes row 1. So on the next iteration on index 2, it gets the row below it (i.e. the one that was originally index 3 but is now 2 'cos you moved 1 to the bottom). On the last iteration, you get the row you already moved to the bottom.

The simple solution is to go through the collection backwards. Oh, and you don't have to remove and replace the element, you can just move it:

var a=rows.length;
while (a--) 
{         if (rows[a].style.display == 'none') 
    { 
        rows[a].parentNode.appendChild(rows[a]); 
    } 
}

Note however that the rows have been swapped in order. Sorry about that! An alternative to keep them in order is to convert the collection to an array (simply loop over the collection and add the rows to an array), or mess with the counters:

for (var a=0, b=rows.length; a<b; a++) 
{ 
    if (rows[a].style.display == 'none') 
    { 
        rows[a].parentNode.appendChild(rows[a]); 
        a--;  // Move a up because removed a row
        b--;  // Shorten b so don't visit row again at the bottom
    } 
} 

since rows[a].parentNode is the tbody. Note that this moves it to the bottom of the tbody, so if you have multiple tbody elements you'll need to get a reference to the last one and add them there:

var lastTBody = table.tBodies[table.tBodies.length - 1];


You loop through the table using an index, which needs to be updated when you alter the table.

For example, when you move the second line to the bottom, the third line becomes the second line. Since the index advances anyway, the next iteration of the loop looks at the new third line, which was the fourth line before. The previous third line (now second) is therefore ignored.

You can fix this by adjusting the index after moving the row to the bottom.

Once you stop skipping lines, you'll be stuck in an infinite loop, though. You also need to adjust the length to not move the already moved lines again.

For example:

table.appendChild (row);
a--;
b--;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜