jquerytablesorter

Sorting multiple tables with tablesorter


I'm using the jQuery tablesorter plugin to allow users to sort tables of data on our site. I recently came across an area where multiple tables using the tablesorter were going to be displayed on the same page, I didn't have any troubles with this and the tablesorter plugin worked great. We had a request by a few users to be able to sort all tables at the same time, which is fine since the tables all have the same structure just different data in them. Here is an example for table 1:

<table>
    <thead>
       <tr>
           <th>ID</th>
           <th>Name</th>
           <th>Age</th>
       </tr>
    </thead>
    <tbody>
       <tr>
           <td>1</td>
           <td>Bob</td>
           <td>24</td>
       </tr>
       <tr>
           <td>1</td>
           <td>James</td>
           <td>33</td>
       </tr>
    </tbody>
</table>

Example for table 2:

<table>
    <thead>
       <tr>
           <th>ID</th>
           <th>Name</th>
           <th>Age</th>
       </tr>
    </thead>
    <tbody>
       <tr>
           <td>5</td>
           <td>PJ</td>
           <td>28</td>
       </tr>
       <tr>
           <td>1</td>
           <td>Sue</td>
           <td>39</td>
       </tr>
    </tbody>
</table>

So as you can see the table are similar but displaying different data. The problem became how do I allow users to sort all tables at the same time, but let them still sort tables separately as well, since they might want to do that. We came up with the idea of if they sort the first table on the page we'd like to use that event as our indication they want to sort all the tables on the page in the same sorting structure as the first. My main question is how would someone go about doing this? I think I found the best area to make this work, tablesorter widgets, but can't seem to get that last piece of the puzzle in place.

Here is what I currently have for my widget and tablesorter registration code:

$(function() {

    $("table:not(:first)").tablesorter();

    $.tablesorter.addWidget({
        id: "tableForceSort",
        format: function (table) {
            if (table.config.sortList.length > 0) {
                $('table:not(:first)').trigger("sorton", table.config.sortList);
            }
        }
    });

    $("table:first").tablesorter({
        widgets: ['tableForceSort']
    });
});

As you can see I'm adding the tablesorter to all tables in the page, but doing a separate registration for the first table so that I can add a special widget to that table to force the sort on the rest of the tables on the page. This all works, the problem appears for me when I actually try to sort the table and it fires the trigger event, this causes the page to break and I can't seem to figure out why. If anyone has some way to fix this or some other ideas on how to solve this problem please let me know.

Thanks


Solution

  • Try using the "sortEnd" event... I had to add a flag to prevent recursion. Hopefully I added enough comments so it all makes sense (demo).

    $('table').tablesorter();
    
    // using a flag that prevents recursion - repeatedly calling this same function,
    // because it will trigger the "sortEnd" event after sorting the other tables.
    var recursionFlag = false;
    
    // bind to table sort end event on ALL tables
    $("table").bind("sortEnd",function(e, table) {
    
        // ignore if the flag is set
        if (!recursionFlag) {
            recursionFlag = true;
    
            // find other tables to resort (but not the current one)
            // the current sort is stored in "table.config.sortList"
            $('table').not(this).trigger("sorton", [ table.config.sortList ]);
    
            // reset recursion flag after 1 second... so you can't sort faster
            // than that or it won't trigger the other tables
            // you can adjust this value; it all depends on how much data needs
            // to be sorted in the tables. Run the tablesorter with "debug:true"
            // to find out the times needed to sort (but do it in IE as it is
            // the slowest browser)
            setTimeout(function(){ recursionFlag = false; }, 1000);
    
        }
    });