views:

4087

answers:

9

I have a aspx page that looks something like this:

<tr id="Row1">
  <td>Some label</td>
  <td>Some complex control</td>
</tr>
<tr id="Row2">
  <td>Some label</td>
  <td>Some complex control</td>
</tr>
<tr id="Row3">
  <td>Some label</td>
  <td>Some complex control</td>
</tr>

As soon as the page is loaded, I would want to reorder these rows based on the user's previously selected order (stored in a database)

How would I use JQuery/JS to accomplish this?

EDIT:

I have run into a performance issue with the appendTo code. It takes 400ms for a table of 10 rows which is really unacceptable. Can anyone help me tweak it for performance?

function RearrangeTable(csvOrder, tableId)
{
  var arrCSVOrder = csvOrder.split(','); 

  //No need to rearrange if array length is 1
  if (arrCSVOrder.length > 1)
  {
    for (var i = 0; i < arrCSVOrder.length; i++)
    {
      $('#' + tableId).find('[fieldname = ' + arrCSVOrder[i] + ']').eq(0).parents('tr').eq(0).appendTo('#' + tableId);
    }
  }
}
+5  A: 

Why not order the rows on the server side? If you are going to reorder them with JQuery as soon as the page is loaded then it will be more efficient to do this job in server code, especially if the user's selected order is stored in a database.

Darin Dimitrov
Do you mean I add these rows dynamically on the server side? Since this is a complicated page, I would want to avoid creating these rows dynamically (these rows have multiple custom controls that I have left out in the example)
DotnetDude
DotnetDude: I fail to see how it would be easier to do this on the client than on the server. How do you plan to tell client in what order you want the rows?
svinto
svinto - My plan is to swap the rows at the DOM level. I am looking for a more elegant solution though. If I have to do this on the server side, I agree it's much simpler, but I will end up having to create all the controls on the fly and I would rather not create dynamic controls (viewstate problem
DotnetDude
Could you not have provided an answer to what DotnetDude has asked for and then suggested what he needs to do afterwards? I don't count this as an answer to the question
Sung Meister
Ditto - this is a question, not an answer.
Eli
+6  A: 

Try the jQuery tablesorter plugin.

When the document loads you can sort the table by specifying the column index to sort on (and it allows sorting by multiple columns):

$(document).ready(function() 
    { 
        $("#myTable").tablesorter( {sortList: [[0,0], [1,0]]} ); 
    } 
);
Chris Pebble
This would be a great solution as one can combine a (un)sorted state from the database and still provide javascript controls to resort the table at the user's whim.
Danny
+2  A: 

Check the jQuery TableSorter Plugin, it's very powerful it detects the underlying datatypes of the columns, and you can sort your table columns programmatically:

$("#yourTable").tablesorter( {sortList: [[0,0]]} );  
// This will sort "yourTable" using 
// the first column, ascending [columnIndex, 0=ASC or 1 = DESC]
CMS
A: 

If the last sorting done by the user is stored as a list containing the row id, you could do this:

loop through list from db {
    $("#"+rowId).appendTo("#tableId")
}

This way, the rows will be taken out of their current location and replaced inside the table in the order they are stored in the database.

peirix
Thanks. I have <tr>s added in design time. So, to clarify, does appendTo remove the existing <tr> and add it to the table specified in the tableId? Will this work if the <tr>s are already inside the table?
DotnetDude
Yes. appendTo makes a clone then appends it to which ever element you specified, and then removes the old one. This will work even if the tr's are just moved inside its own table, yes.
peirix
+5  A: 

Hi,

Just do something like this:

Say you have table like so:

<table id='table'>
    <tr id='row1><td>....</td></tr>
    <tr id='row2><td>....</td></tr>
    <tr id='row3><td>....</td></tr>
    <tr id='row4><td>....</td></tr>
</table>

And an array with the new order like this:

NewOrder[1] = 3;
NewOrder[2] = 4;
NewOrder[3] = 2;

Then, do some something like this (not tested, so you may need to tweak the code, but this is the idea):

for ( i=1; i<=NewOrder.length; i++ ) {
    $('#row'+i).appendTo( '#table' );
}

This way, they are moved to the end of the table in order.

So you will have 3 moved to the end, then 4 behind it, then 2 behind that, etc. After they have ALL been appended to the end of the table, the first one will become the first row, and the rest will be in the correct order behind it.

Edit:

Make the table style='display:none;' and then do $('#table').show(); at startup.

Edit Again: You could do a div around the entire body content, like

<body>
<div id='everything' style='display:none;'>
....
</div>
</body>

So that the entire page will be hidden (just blank white) for the fraction of a second it takes to load and order the table.

Then you would use:

$(function(){
    $('#everything').show();
}

To show the entire page all at once as soon as the DOM is ready. It will take a fraction of a second longer for the page to load, but it will all load at once, so there won't be any flash of missing tables, etc. As long as EVERYTHING is in #everything, it will just look like the page loaded - should be transparent to the viewer.

Eli
This almost works. I still have that fraction of a second when the table is invisible. This is a client facing page and UI behavior is really important. Can you suggest a different way?
DotnetDude
@DotnetDude - See Second Edit.
Eli
+3  A: 

Keep in mind reording client-side leaves yourself open to issues in three ways.

  1. If the client computer is slow this reordering may be visible no matter what you do.
  2. The larger the table of data gets the slower this action will be and the more visible the reordering would be.
  3. Client could have JS disabled, which would break your reordering.

Although it seems you want to do this client-side to save yourself some headaches now on the server-side programming, in the long run investing some time on this now to get it server-side will avoid these troubles.

If you're having issues getting the server-side code to work right with your custom controls post it and we'll help you out.

Parrots
A: 

EDIT appendTo method works. However, in the short delay of rearranging the rows on the client side, I see the rows in their original order for about half a second before the reordering is complete. This UI behavior is more prominent since the page does not use postbacks. Any workaround for this?

Set display:none on the table with css. The when the document ready event fires use the appendTo method. The do show on the table. You can set another style tag with display:block on the table inside <noscript> in case js is disabled.

Vasil
+1  A: 

Working example. Simply iterate through a list containing the new order (which, presumably you read from the DB), building the new table. Then set the table html() to the new table html.

<html>
<head>
    <script type="text/javascript"
    src="http://code.jquery.com/jquery-latest.min.js"&gt;&lt;/script&gt;
    <script>
jQuery.fn.outer = function(){
  return $( $('<div></div>').html(this.clone()) ).html();
}
$(function(){
    newtbl = "";
    neworder = [2,3,1];
    for(i=0;i<neworder.length;i++){
     newtbl += $("#Row"+neworder[i]).outer();
    }
    $("#tbl").html("<table id=\"tbl\">" + newtbl + "</table>")
});
</script>    
</head>
<body>
<table id="tbl">
<tr id="Row1">
  <td>label 1</td>
  <td>Some complex control</td>
</tr>
<tr id="Row2">
  <td>label 2</td>
  <td>Some complex control</td>
</tr>
<tr id="Row3">
  <td>label 3</td>
  <td>Some complex control</td>
</tr>
</table>
</body>
</html>
bill weaver
A: 

Any help with my edit?

Thanks

DotnetDude