I'm using a jquery plugin which fixes the headers on a html table that I generate. Unfortunately the performance of the plugin is very slow and I've narrowed it down to the following code:
var $tbl = $(this);
var $tblhfixed = $tbl.find("thead");
$tblhfixed.find("th").each(function ()
$(this).css("width", $(this).width());
});
This is taking about 40 seconds on a table with 2,000 rows in ie. Does anyone know why it's so slow and more importantly how can I make this faster? I've tried many other plugins and this is the only one which works how I want it to. Thanks for any help
I guess you faced with the same problem that I had some time ago. It called a "Recalculate layout" or something.
Try to separate this script onto two loops, like this:
var $tbl = $(this);
var $tblhfixed = $tbl.find("thead");
var widths = [];
// 1.
$tblhfixed.find("th").each(function ()
widths.push($(this).width());
});
// 2.
$tblhfixed.find("th").each(function (index, element)
$(this).css("width", widths[index]);
});
First one will calculate all the widths. Second one will apply them to TH's
UPD: You may increase performance by placing this code between 1. and 2.:
$tblhfixed.hide();
and show it again after 2.:
$tblhfixed.show();
the culprit is probably the .each
.
The reason is that when you iterate using .each
instead of a normal loop, you call a function for each iteration. a function call has a pretty big overhead in this case, since a new callstack has to be created for each iteration.
To make it faster change
$tblhfixed.find("th").each(function ()
$(this).css("width", $(this).width());
});
to
var elms = $tblhfixed.find("th");
for(var i=0, elm;elm = elms[i];i++) {
elm.css("width", elm.width());
}
First, you should use find()
only when you need to pass through all nested nodes. Right here you can use children()
.
Second, each time $(this)
creates new instance of jQuery object, while you can create it once:
var $this = $(this);
Each time $(this).width()
is recalculated. Make sure that you need it to be recalculated. Or do:
var tableWidth = $this.width();
And third, according to @Martin Jespersen, each iteration the function
object is created.
Also you don't need jQuery here at all. You can access DOM directly:
var tableWidth = ...; // get the table width the way you want
var thead = this.tHead;
var thRow = thead.rows[0];
for (var i = 0; i < thRow.length; ++i) {
thRow.cells[i].style.width = tableWidth + "px";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With