In jQuery, using the :visible selector can be dangerous

14 September 2010   0 comments   Javascript

Mind That Age!

This blog post is 7 years old! Most likely, its content is outdated. Especially if it's technical.

Powered by Fusion×

In jQuery, using the :visible selector can be dangerous And by "dangerous" I mean super slow to the point of making your browser shake of over exhaustion.

I have a big fat table where on the left hand side of each row there's a little toggle to open up an initially hidden sub-table. And there are toggles for those sub-tables to open up further sub-tables. It might sound complicated but it works great. The code for each toggle looks something like this:

$('a.toggle-order-on').click(function() {
   var tbody_parent = $(this).parents('tbody');

   $('tr.printdisplay:hidden', tbody_parent).show();
   $('tr.outdoor-marketing:hidden', tbody_parent).show();
   $('tr.digital:hidden', tbody_parent).show();

   // expand the little table too
   $('a.toggle-printdisplay-on', tbody_parent).click();

   var td_parent = $(this).parents('td');
   $(this).hide();
   $('a.toggle-order-off:hidden', td_parent).show();

   return false;
});

Note the heavy use of the super useful :hidden selector which is basically a reversing wrapper on the :visisble selector

What I then needed was a way to open up every single row in the whole table with one click. Here was the code I wrote:

$('a.toggle-order-on:visible').trigger('click');

See? Makes sense does it?

Problem with this was that when the table was big sometimes clicking this would make my otherwise fast browser (Chrome or Firefox) stutter and sometimes stall or at worst the alert pop-up about "a script is slowing this page down" would appear.

So I started the Firebug Profiler and clicked a couple of times and collected some numbers. On average it took 3-4.5 seconds!! and about 20,000-35,000 calls to complete the full expansion. Yikes! About 90% of the time spent by jQuery was on the visisble() function.

Solution: Instead of using the click trigger I simply just called the .show() effect on all things manually without using any :visible or :hidden operators. Here's the new code:

$('tr.printdisplay').show();
$('tr.outdoor-marketing').show();
$('tr.digital').show();
$('tr.printdisplaydetail').show();

$('a.toggle-order-off').show();
$('a.toggle-order-on').hide();

$('a.toggle-printdisplay-off').show();
$('a.toggle-printdisplay-on').hide();

This time, with the profile again, I it took on average 0.2-0.3 seconds and required about 2000-4000 calls. HUGE difference.

So, remember that next time. Don't just re-use working code en mass if it's using a much of :visible or :hidden selectors somewhere in there.

Follow @peterbe on Twitter

Comments

Thank you for posting a comment

Your email will never ever be published


Related posts

Previous:
wkhtmltopdf and font size shrinkage 10 September 2010
Next:
Local Django development with Nginx 11 October 2010
Related by Keyword:
Some tips on learning React 04 August 2015
mincss version 0.8 is much much faster 27 February 2013
Difference between $.data('foo') and $.attr('data-foo') in jQuery 10 June 2012
QUnit testing my jQuery Mobile site in full swing 17 March 2011
Why I gave up on JQuery UI's autocomplete 20 October 2010
Related by Text:
To sub-select or not sub-select in PostgreSQL 31 August 2009
table-layout: fixed 13 October 2005
How I deal with deferred image loading in Javascript 08 June 2012
crontabber now supports locking, both high- and low-level 04 March 2017
Visual speed comparison of AngularJS and ReactJS 20 July 2015