Updating jQuery Tablesorter plugin after removing a row from DOM
Asked Answered
L

8

20

I have some code at the moment that hides a row that is deleted and then removes it using the .remove() function.

However I'm having difficulty is making it remain "deleted" as every time I refresh the table sorted pager plugin or the filter plugin addon I'm using.. the deleted rows re-appear as they are of course cached.

Current code just simple with widget update at the moment

$('.deleteMAP').live("click", function(){
  $(this).closest('tr').css('fast', function() {
 $(this).remove();
 $(".tablesorter").trigger("update");
 $(".tablesorter").trigger("applyWidgets");
  });
})

Is there anyway to remove the "row" from both the cache of the pager plugin and also the tablesorter plugin so that when I "update" the table to reflect the fact a row has been removed they don't re-appear back from the dead via the cache!

Lazurite answered 14/12, 2009 at 21:58 Comment(0)
C
18

I found a solution that worked for me:

var usersTable = $(".tablesorter");
usersTable.trigger("update")
  .trigger("sorton", [usersTable.get(0).config.sortList])
  .trigger("appendCache")
  .trigger("applyWidgets");

Put this after the place where you've edited the table.

Colligate answered 6/1, 2010 at 14:34 Comment(1)
Thanks for this. One thing - usersTable.get(0).config.sortList is already an array. You don't need to wrap it in [ ], and the sorton trigger won't work if you do.Marybellemarybeth
T
5

After some tinkering around with this problem I conclude the problems arise from the combined use of jQuery Tablesorter + jQuery TablesorterPager. With out the pager removing the row and doing and "update" is enough.

When you also include the pager it gets much more difficult to do this right (as how you noticed correctly there are some caching issues).

But the main reason for your problem is that jQuery Tablesorter isn't thought to be used for tables which you intent to modify (in the sense of adding/removing rows). And this applies even more when you additionally use TablesorterPager. Just reread the description of jQuery Tablesorter

tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes.

A clear and concise field of application for TableSorter. It doesn't even mention ajax, edit, remove, append, ..... or similar terms on the page. It is only for sorting a static table.

So the actual solution is.... start looking for another jQuery "Table" plugin which was built from the start with the intention/possibility that the table can be modified. And which supports this by default (removing, adding, ....)


Ok nonetheless here is the solution for:

jQuery Tablesorter + TablesorterPager remove rows (TR)

Quick copy-paste of the javascript source-code (HTML based on TablesorterPager example)

// "borrowed" from John Resig: Javascript Array Remove
// http://ejohn.org/blog/javascript-array-remove/
Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

//repopulate table with data from rowCache
function repopulateTableBody(tbl) {
    //aka cleanTableBody from TableSorter code
    if($.browser.msie) {
        function empty() {
            while ( this.firstChild ) this.removeChild( this.firstChild );
        }
        empty.apply(tbl.tBodies[0]);
    } else {
        tbl.tBodies[0].innerHTML = "";
    }
    jQuery.each(tbl.config.rowsCopy, function() {
        tbl.tBodies[0].appendChild(this.get(0));
    });
}
//removes the passed in row and updates the tablesorter+pager
function remove(tr, table) {
    //pager modifies actual DOM table to have only #pagesize TR's
    //thus we need to repopulate from the cache first
    repopulateTableBody(table.get(0));
    var index = $("tr", table).index(tr)-2;
    var c = table.get(0).config;
    tr.remove();
    //remove row from cache too
    c.rowsCopy.remove(index);
    c.totalRows = c.rowsCopy.length;
    c.totalPages = Math.ceil(c.totalRows / config.size);
    //now update
    table.trigger("update");
    //simulate user switches page to get pager to update too
    index = c.page < c.totalPages-1;
    $(".next").trigger("click");
    if(index)
        $(".prev").trigger("click");
}

$(function() {
    var table;
    //make all students with Major Languages removable
    $('table td:contains("Languages")').css("background-color", "red").live("click", function() {
        remove($(this).parents('tr').eq(0), table);
    });

    //create tablesorter+pager
    // CHANGED HERE OOPS
    // var table = $("table#tablesorter");
    table = $("table#tablesorter");
    table.tablesorter( { sortList: [ [0,0], [2,1] ] } )
        .tablesorterPager( { container: $("#pager")}  );
});

I made a testpage for you with my solution (click the red TD's == removing that row).

http://jsbin.com/uburo (http://jsbin.com/uburo/edit for the source)

If question remain on how/why/.... Comment

Targum answered 15/12, 2009 at 12:32 Comment(4)
Hey, I've been messing around trying to get this to work in firefox but no luck so far. Any ideas?Lazurite
Oops minor error in my demo page redeclaration of existing variable. Updated link and source in answer. Check at end of source in ready function for // CHANGED HERE OOPS comment for the changeTargum
for me works var index = $("tr", table).index(tr)-1; and not var index = $("tr", table).index(tr)-2; is normal?Clotheshorse
rewriting the method Array.prototype.remove is necessary?Clotheshorse
T
4

Things goes tricky when you use both tablesorterpager and tablesorterfilter plugins - solution with:

$("#gridTable").trigger("update").trigger("appendCache").trigger("applyWidgets");

works only for pager, filter has another cache. I've looking for solution for almost 2 hours, at last i've written something like this:

$("#deleteRowButton").click( function(){
  // index of row which will be deleted
  var index = $('#gridTable tr[rel="'+$("#removeThisID").val()+'"]').index();
  // table with tablesorter
  var table = document.getElementById( 'gridTable' ).config.cache.row;
  // deleting row
  $('#gridTable tr[rel="'+$("#removeThisID").val()+'"]').remove();
  // truly DELETING row, not only mark as deleted - after this list of rows should look like [tr], [tr], [tr], undefined, [tr], ...
  delete( table[index] );
  // tablesorter things
  $("#gridTable").trigger("update").trigger("appendCache").trigger("applyWidgets");
});

I'm deleting row which has rel attribute the same as input#removeThisID value.

Now it's time to modify tablesorterfilter plugin. In doFilter function, find lines:

// Walk through all of the table's rows and search.
// Rows which match the string will be pushed into the resultRows array.
var allRows = table.config.cache.row;
var resultRows = [];

and replace these with:

// Walk through all of the table's rows and search.
// Rows which match the string will be pushed into the resultRows array.
var allRows = table.config.cache.row;

// refresh cache 'by hand'
var newcache = new Array();
var i = 0;        
for( var a in allRows )
{
  newcache[i] = allRows[a];
  i++;
}
allRows = newcache;
var resultRows = [];

that's all...

regards form Poland :)

Twirl answered 18/5, 2011 at 12:23 Comment(0)
M
3

This seems an odd approach, but actually it worked for me. Table renders fine and pager works properly.

$("#tabeBodyId").empty();
$("#tableId colgroup").remove();

//Update table(done using Ajax)
$("#tableId").tablesorter({widthFixed: true}).tablesorterPager({container: $("#pager")}); 
Minna answered 25/1, 2012 at 9:27 Comment(0)
A
1

Jitter solution was almost working for me although a line was missing for update (see code below). I've extended the code to allow insert new TR's in table.

I've been playing around and it works for me under FFox, didn't check on IExplorer. Anyway there's a bug I couldn't fix yet: If you add a new TR and then you try to delete it it won't be deleted from table :(

// "borrowed" from John Resig: Javascript Array Remove
// http://ejohn.org/blog/javascript-array-remove/
Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

//repopulate table with data from rowCache
function repopulateTableBody(tbl) {
    //aka cleanTableBody from TableSorter code
    if($.browser.msie) {
        function empty() {
            while ( this.firstChild ) this.removeChild( this.firstChild );
        }
        empty.apply(tbl.tBodies[0]);
    } else {
        tbl.tBodies[0].innerHTML = "";
    }
    jQuery.each(tbl.config.rowsCopy, function() {
        tbl.tBodies[0].appendChild(this.get(0));
    });
}
//removes the passed in row and updates the tablesorter+pager
function tablesorter_remove(tr, table) {
    //pager modifies actual DOM table to have only #pagesize TR's
    //thus we need to repopulate from the cache first
    repopulateTableBody(table.get(0));
    var index = $("tr", table).index(tr)-2;
    var c = table.get(0).config;
    tr.remove();

    //remove row from cache too
    c.rowsCopy.remove(index);
    c.totalRows = c.rowsCopy.length;
    c.totalPages = Math.ceil(c.totalRows / config.size);

    //now update
    table.trigger("update");
    table.trigger("appendCache");

    //simulate user switches page to get pager to update too
    index = c.page < c.totalPages-1;
    $(".next").trigger("click");
    if(index)
        $(".prev").trigger("click");
}

function tablesorter_add(tr, table) {
    //pager modifies actual DOM table to have only #pagesize TR's
    //thus we need to repopulate from the cache first
    repopulateTableBody(table.get(0));
    table.append(tr);

    //add row to cache too
    var c = table.get(0).config;
    c.totalRows = c.rowsCopy.length;
    c.totalPages = Math.ceil(c.totalRows / config.size);

    //now update
    table.trigger("update");
    table.trigger("appendCache");

    //simulate user switches page to get pager to update too
    index = c.page < c.totalPages-1;
    $(".next").trigger("click");
    if(index)
        $(".prev").trigger("click");

    //Set previous sorting method
    var sorting = c.sortList;
    if(sorting == '')
        sorting = [[0,0]];
    table.trigger("sorton", [sorting]);
}

And you can use is as follows:

Add new TR with complex HTML in it:

tablesorter_add('<tr id="'+data.id+' " title="Haz click para editar" onclick="edit('+data.id+')"><td id="'+data.id+'_genus">'+data.genus+'</td><td id="'+data.id+'_species">'+data.species+'</td></tr>', $("#orchid_list"));

Remove any TR:

tablesorter_remove($("#"+orchid_id),$("#orchid_list"));

My simplified sample table:

<table id="orchid_list" class="tablesorter">
<thead>
<tr>
    <th id="genus">Género</th>
    <th id="species">Especie</th>
</tr>
</thead>
<tbody>
    <tr id="2" title="Haz click para editar" onclick="edit('2')">
        <td id="2_genus">Amitostigma</td>

        <td id="2_species">capitatum</td>
    </tr>
    <tr id="4" title="Haz click para editar" onclick="edit('4')">
        <td id="4_genus">Amitostigma</td>
        <td id="4_species">tetralobum</td>
    </tr>
</tbody>
</table>
Adeliaadelice answered 15/2, 2010 at 11:47 Comment(0)
T
1

Better to use table.splice(index, 1); than delete( table[index] );! "Delete" do just empty element of array, but not deleted completely. Sorry for my English! =)

Thoma answered 21/10, 2011 at 13:28 Comment(0)
C
1

Please have a look at Motties tablesorter fork. He made an example for adding/removing rows when using tablesorter and pager plugin. http://mottie.github.com/tablesorter/docs/example-pager.html

Closefitting answered 12/2, 2012 at 13:44 Comment(0)
A
0

Old Question, but sometimes a basic solution is best for providing a quick fix to old code.

So, an easy option is to just hide the row.

var rowId = 20;
var rowToDelete = $('.tablesorter').find('tr#' + rowId);
rowToDelete.attr('id','REMOVED');   //so your JS code will not find
rowToDelete.addClass('hide');       //so the row isn't re-displayed by the tablesorter plugin when a sort is performed after an update.
rowToDelete.remove();               //delete from HTML
Alessandro answered 1/3, 2023 at 22:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.