views:

93

answers:

5

I have a table of 50 odd rows with 11 columns. Each row has a unique id made up of id="row_<clientid>_rownumber". There is a checkbox in the second column with id="group_<clientid>_<petid>_rownumber"

Redacted Screenshot

When the user clicks a checkbox I want to remove all rows except any that belong to the selected client. I have code that works as follows:

var sClient = $(this).attr("id").substring(6); // trim off group_
sClient = sClient.substring(0,sClient.indexOf("_")); // trim off anything after clientid
$("tr[id^=row_]").not("tr[id^=row_" + sClient + "]").remove(); 

The problem is it takes so long that in IE I get the "script is taking too long" warning.

Is there a faster method to remove many rows?

BTW: It takes 4.4 seconds using jQuery 1.4.3 and 1.3 seconds with jQuery 1.4.2

Problem Solved thanks to all. Final hint provided by @VisusZhao. This is final working snippet:

var KeepRows = $("#bookingstable tbody tr[id^=row_" + sClient + "_]");
$("#bookingstable tbody").empty();
$("#bookingstable tbody").append(KeepRows);

Thank you all

+1  A: 

First of all, give the table an id.

<table id="departures">

Store all of the required rows in a jQuery object, and only those inside #departures.

var $departures = $("#departures");
var $rows = $("tr[id^=row_]", $departures); //

This way, jQuery won't have to traverse the DOM each time you perform a function because it'll be stored inside the object.

Then use your code as usual

var sClient = $(this).attr("id").substring(6); // trim off group_
sClient = sClient.substring(0,sClient.indexOf("_")); // trim off _row

While replacing the last line with this

$rows.not("tr[id^=row_" + sClient + "]", $departures).remove();
Marko
Thanks @marko that made a lot of sense but had no effect on the speed. Probably because the DOM of the page is dominated by the table, with just a few divs enclosing the buttons at the top of the page.
JJBaxter
A: 

I think you can try using .filter instead, like this:

var sClient = this.id.substring(6); // trim off group_

$("#table_id tr").filter(function(){
    return (this.id.indexOf('row') === 0 && this.id !== sClient);
}).remove();

Or maybe, give the rows that belongs to each client a class:

var sClient = this.id.substring(6); // trim off group_
$('#table tr.' + sClient).remove();

Neither of these are guaranteed to be faster, unlike Marko's answer above, but they are different ways to making this work, and may be faster for IE.

Yi Jiang
No sorry @YiJiang, same result.
JJBaxter
A: 

Definitely id your table and use that as your jQuery context. Also store the table jQuery object as well - though you probably won't see much improvement from that. I might try applying a class to each of your rows. For instance, give each row a class of the client they belong to. Then, this should do the trick:

var tableElement = $("#table_id"); // only do this once on page load
tableElement.find("tr:not(." + sClient + ")").hide();

No guarantee this will be faster, but it might be worth a try.

Brandon Montgomery
+1  A: 

you can first store the row for the client,

var clientRow = $('#row_' + sClient);

then empty the table

$('#table_id tbody').empty();

then insert the row back

$('#table_id tbody').append(clientRow);

this will take no loop, so its constant time

Visus Zhao
Well @VisusZhao this looks great, outside the box for me. Testing it now.
JJBaxter
The rows were saved, the table cleared but the `.append` didnt append anything. Not sure why. Still investigating.
JJBaxter
It works on my machine, see this fiddle: http://jsfiddle.net/pZ89b/2/
Visus Zhao
I've no Idea how to embed jsfiddle into the page yet, so you have to go over the link to see the result
Visus Zhao
Thank you @VisusZhao your `jsfiddle` link pointed me in the right direction. I wasnt including `tbody` or the table id. Now works so fast I dont need a "Please Wait" message. And it works with jQuery 1.4.3. Thank you to all responders
JJBaxter
A: 

I would start by adding an ID to the table:

<table id="alldepartures">

Next, for each row keep the id if you need it, but also add a CSS class in the format "client_{id}":

  <tr class="client_123">

This is ok, because you can have several rows with the same class.

Then in your code:

var sClient = $(this).attr("id").split('_')[1];
//remove all rows that don't have this class
$('#alldepartures').find('tr[class!=client_' + sClient + ']').remove();

I think the other code may be suffering especially in IE with trying to do matching based on ID as jQuery has to do extra work in IE to overcome their faulty getElementById(id) implementation.

scunliffe