What I want to do is to filter a table to only show the tbody that contains a given value against a value entered into a textbox, and to show the filtered rows in a zebra stripe pattern.
The zebra striping is fast, the filtering is generally fast, except on the first filter on a table with a lot of tbodys (say 2000 tbody? … I haven’t measured for the first visible slowdown, and haven’t tested for speed by the number, but it’s slow in Firefox AND Chrome)
First the JS:
//filter results based on query
function filter(selector, query) {
var regex = new RegExp( query, "i" ); // I did this from memory, may be incorrect, but I know the thing works, the problem is the next part, cos on 5 rows it's fast
$(selector).each(function() {
( regex.test( $(this).text() ) ) < 0) ? $(this).hide().removeClass('visible') : $(this).show().addClass('visible');
});
}
// then after this I recall the zebra function, which is fast.
Then the sample data:
<table>
<thead>
<tr>
<th>value to find 1</th>
<th>value to find 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>12345</td>
<td>67890</td>
</tr>
<tr>
<td>empty for now, while testing</td>
<td>may contain other info later</td>
</tr>
</tbody>
<tbody>
<tr>
<td>23456</td>
<td>78901</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>45678</td>
<td>90123</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
... /ad nauseum, for 2000 rows +
<tfoot>
</tfoot>
</table>
So for instance, trying to match value 123 would return the first and third rows of this sample data, but I think you already figured that out …
HELP?
Any time you work with this many DOM elements your main performance hit is generally rendering since every time you modify something in the DOM a browser will re-render the page. This will turn your rendering performance into O(n^2) unless you modify the elements outside of the DOM. There are a few ways to do this like cloning and DOM arrays. To use cloning you
clonethe elements you wish to modify, modify the cloned elements and then insert them into the DOM withreplaceWith. DOM arrays are just standard JavaScript arrays holding DOM elements. You can pass an array of DOM elements to jQuery instead of a selector. Here’s the output of my test using copies of your html. I’m using jQuery 1.4.2.Other modern browsers have different performance characteristics.
You can see how the O(n^2) rendering really starts to add up. Here’s my test program minus the thousands of copied html elements.
Another option if you don’t want to clone is to detach the elements you’re working on and then reattach them once your done. See detach.