Tablesorter jQuery Plugin - a fix

Updated Airshow 0 Tallied Votes 802 Views Share

Tablesorter (currently v2.0.5) includes an "update" method. This method keeps a Tablesorter object up to date with dynamic changes made to its table(s).

Like other Tablesorter methods "update" is implemented in the form of a custom event.

A typical method call would be $table.trigger("update"); , where $table is a jQuery object.

For some reason unknown to me, the "update" event code is written inside a setTimeout(function(){...}, 1) structure. Presumably this overcomes a problem in some browser or other.

This works fine within itself but means that statement(s) immediately following a .trigger("update") call will be executed before the "update". This is no good when the following statement(s) depend on the update being complete, notably .trigger("sorton", ...) , which (re)implements a sort.

The following patch overcomes the shortcoming by implementing within the "update" method:

  • a way to re-execute the last user-selected sort
  • a generalised way to execute any code of your choice.

For usage instructions, see comment block in code.

Airshow

//--find
                    /*
                    $this.bind("update", function () {
                        var me = this;
                        setTimeout(function () {
                            // rebuild parsers.
                            me.config.parsers = buildParserCache(me, $headers);
                            // rebuild the cache map
                            cache = buildCache(me);
                        }, 1);
                    */
//--replace with
                    /* 
                     * Fix by Airshow, 07 August 2011
                     * Allows post-update actions:
                     * (a) an optional table re-sort.
                     * (b) a callback function.
                     * Sample call with re-sort:
                     *   jqueryObj.trigger({type:'update', resort:true});
                     * Sample call with callback:
                     *   jqueryObj.trigger({type:'update', callback: function(config) {
                     *     $(this).trigger("sorton", [config.sortList]);
                     *   }});
                     * NOTE: The second sample call is functionally identical to the first.
                     */
                    $this.bind("update", function (e) {
                        var me = this;
                        setTimeout(function () {
                            // rebuild parsers.
                            me.config.parsers = buildParserCache(me, $headers);
                            // rebuild the cache map
                            cache = buildCache(me);
                            if(e.resort||e.re_sort) { $(me).trigger("sorton", [config.sortList]); }
                            if(e.callback) { e.callback.call(me, config); }
                        }, 1);
                    //--end fix

*incorporating mikehershey's correction kindly offered below: 22_05_20-12*
mikehershey 13 Newbie Poster

Nice work! I just spent a ton of time trying to fix this bug. Just one little issue with your documentation here your example call with call back should be:

jqueryObj.trigger({type:'update', callback : function(config){
$(this).trigger("sorton", [config.sortList]);
}});

commented: Thanks Mike for correcting my error. +13
Airshow 416 WiFi Lounge Lizard Team Colleague

Mike,

I'm so glad my patch has been of use to you.

Many thanks for the correction to the documentation.

To future users of the patch: Please use mikehershey's version of the "sample call with feedback".

Airshow

alanpuccinelli 0 Newbie Poster

Man, I was banging my head against the wall on this one. They should really implement this into the source. Really frustrating if you're trying to replace the entire set of table data and then re-sort.

Thanks so much for posting!

Airshow 416 WiFi Lounge Lizard Team Colleague

It's very gratifying that folk are registering here at Daniweb just to say thank you. More power to your elbow guys & gals.

The author of Tablesorter has been made aware via his Google code repository.

Airshow

mano7859 0 Newbie Poster

Hi,

Thanks for this code.

I got a probleme with it.
I've modified the 'jquerty.tablesorter.js' with your patch.
When i applied it my table doesn't refresh after deleting a row.
Please help !!!

This is my code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Document sans titre</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="js/jquery.tablesorter.pager.js"></script>
<script type="application/javascript">
$(document).ready(function() { 

$('table').tablesorter({ sortList: [ [0, 0] ], });
 $("table").tablesorterPager({container: $("#pager")}); 


    $("table").delegate('button.remove', 'click' ,function(){ 
        $(this).closest('tr').remove();
        jqueryObj.trigger({type:'update', resort:true});
     }); 

});

</script>
</head>

<body>
<div id="updateTable">
<table id="myTable" class="tablesorter">
    <thead>
        <tr class='test'>
            <th>Nom</th>
            <th>Prénom</th>
            <th>Supprimer</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>Martin</td>
            <td>Alexandre</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Martin</td>
            <td>Thomas</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Dupont</td>
            <td>Edwige</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Durand</td>
            <td>Philippe</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Victor</td>
            <td>Emeline</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Jones</td>
            <td>Cris</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Swain</td>
            <td>Phil</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Bruce</td>
            <td>Noemi</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Smith</td>
            <td>Arnold</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Cavite</td>
            <td>Olivier</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Estebriand</td>
            <td>César</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Polaris</td>
            <td>Benoît</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Roger</td>
            <td>Manon</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
    </tbody>
</table>


    <!-- pager --> 
    <div id="pager" class="pager"> 
      <form> 
        <img src="first.png" class="first"/> 
        <img src="prev.png" class="prev"/> 
        <span class="pagedisplay"></span> <!-- this can be any element, including an input --> 
        <img src="next.png" class="next"/> 
        <img src="last.png" class="last"/> 
        <select class="pagesize"> 
          <option selected="selected" value="10">10</option> 
          <option value="20">20</option> 
          <option value="30">30</option> 
          <option value="40">40</option> 
        </select> 
      </form> 
    </div>

</div>
</body>
</html>
Airshow 416 WiFi Lounge Lizard Team Colleague

A few points ...

  1. Line 12 has an unwanted comma.

  2. I'm not 100% sure that row removal requires a resort. Surely the remaining rows just stay in their current sort order. There's no harm in doing a re-sort but is it necessary, mmmm?

  3. Assuming a resort is necessary, lines 16-19 should read as follows:

With jQuery <1.7 :

$("table").delegate('button.remove', 'click' ,function(){
    var $this = $(this);
    var $table = $this.closest('table');
    $this.closest('tr').remove();
    $table.trigger({type:'update', resort:true});
 });

With jQuery >=1.7, .delegate() is deprecated in favour of a particular use of .on(), therefore :

$("table").on('click', 'button.remove', function() {
    var $this = $(this);
    var $table = $this.closest('table');
    $this.closest('tr').remove();
    $table.trigger({type:'update', resort:true});
});
mano7859 0 Newbie Poster

Thank you Airshow for your answer and to take time to resolve my problem.

I've tried that you purposed me but I've obtained the same result.
I'm explaining:
We have 10 rows (page 1) and 5 rows (page 2). After removing a row, I have 9 rows (page 1) and 5 rows (page 2). The logic was to have 10 rows (page1) and 4 rows (page2).

Could you help me please? Thanks

This is my code after your advising:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Title page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="js/jquery.tablesorter.pager.js"></script>

<script type="application/javascript">
    $(document).ready(function() { 
        $("table").tablesorter({ sortList: [ [0, 0] ], });
        $("table").tablesorterPager({container: $("#pager")}); 

        $("table").delegate('button.remove', 'click' ,function(){
            var $this = $(this);
            var $table = $this.closest('table');
            $this.closest('tr').remove();
            $table.trigger({type:'update', resort:true});
         });
    });
</script>


<body>
<div id="updateTable">
<table id="myTable" class="tablesorter">
    <thead>
        <tr class='test'>
            <th>Nom</th>
            <th>Prénom</th>
            <th>Supprimer</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>Martin</td>
            <td>Alexandre</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Jones</td>
            <td>Cris</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <tr>
            <td>Swain</td>
            <td>Phil</td>
            <td><button class="remove" title="Supprimer l'enregistrement">X</button></td>
        </tr>
        <!-- Other datas -->

    </tbody>
</table>


    <!-- pager --> 
    <div id="pager" class="pager"> 
      <form> 
        <img src="first.png" class="first"/> 
        <img src="prev.png" class="prev"/> 
        <span class="pagedisplay"></span> <!-- this can be any element, including an input --> 
        <img src="next.png" class="next"/> 
        <img src="last.png" class="last"/> 
        <select class="pagesize"> 
          <option selected="selected" value="10">10</option> 
          <option value="20">20</option> 
          <option value="30">30</option> 
          <option value="40">40</option> 
        </select> 
      </form> 
    </div>

</div>
</body>

</html>
punknroll 0 Newbie Poster

Hey man, I have been struggling with this for hours. Your code should go to the official version. greetz

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.