1,105,625 Community Members

Tablesorter jQuery Plugin - a fix

Member Avatar
(Airshow)
Reputation Points: 333 [?]
Q&As Helped to Solve: 393 [?]
Skill Endorsements: 11 [?]
 
0
 

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*
Member Avatar
mikehershey
Newbie Poster
1 post since Dec 2011
Reputation Points: 13 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
1
 

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]);
}});

Member Avatar
Airshow
WiFi Lounge Lizard
2,798 posts since Apr 2009
Reputation Points: 333 [?]
Q&As Helped to Solve: 393 [?]
Skill Endorsements: 11 [?]
Team Colleague
 
0
 

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

Member Avatar
alanpuccinelli
Newbie Poster
1 post since Dec 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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!

Member Avatar
Airshow
WiFi Lounge Lizard
2,798 posts since Apr 2009
Reputation Points: 333 [?]
Q&As Helped to Solve: 393 [?]
Skill Endorsements: 11 [?]
Team Colleague
 
0
 

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

Member Avatar
mano7859
Newbie Poster
22 posts since May 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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>
Member Avatar
Airshow
WiFi Lounge Lizard
2,798 posts since Apr 2009
Reputation Points: 333 [?]
Q&As Helped to Solve: 393 [?]
Skill Endorsements: 11 [?]
Team Colleague
 
0
 

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});
});
Member Avatar
mano7859
Newbie Poster
22 posts since May 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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>
Member Avatar
punknroll
Newbie Poster
1 post since Oct 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

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

You
Post:
Start New Discussion
View similar articles that have also been tagged: