Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clientWidth Performance in IE8

I have some legacy javascript that freezes the tfoot/thead of a table and lets the body scroll, it works fine except in IE8 its very slow.

I traced the problem to reading the clientWidth property of a cell in the tfoot/thead... in ie6/7 and FireFox 1.5-3 it takes around 3ms to read the clientWidth property... in IE8 it takes over 200ms and longer when the number of cells in the table is increased.

Is this a known bug ? is there any work around or solution ?

like image 930
Element Avatar asked Apr 29 '09 02:04

Element


2 Answers

I've solved this problem if you are still interested. The solution is quite complex. Basically, you need to attach a simple HTC to the element and cache its clientWidth/Height.

The simple HTC looks like this:

<component lightweight="true">
<script>
window.clientWidth2[uniqueID]=clientWidth;
window.clientHeight2[uniqueID]=clientHeight;
</script>
</component>

You need to attach the HTC using CSS:

.my-table td {behavior: url(simple.htc);}

Remember that you only need to attach the behavior for IE8!

You then use some JavaScript to create getters for the cached values:

var WIDTH = "clientWidth",
    HEIGHT = "clientHeight";

if (8 == document.documentMode) {

  window.clientWidth2 = {};
  Object.defineProperty(Element.prototype, "clientWidth2", {
    get: function() {
      return window.clientWidth2[this.uniqueID] || this.clientWidth;
    }
  });

  window.clientHeight2 = {};
  Object.defineProperty(Element.prototype, "clientHeight2", {
    get: function() {
      return window.clientHeight2[this.uniqueID] || this.clientHeight;
    }
  });

  WIDTH = "clientWidth2";
  HEIGHT = "clientHeight2";
}

Notice that I created the constants WIDTH/HEIGHT. You should use these to get the width/height of your elements:

var width = element[WIDTH];

It's complicated but it works. I had the same problem as you, accessing clientWidth was incredibly slow. This solves the problem very well. It is still not as fast IE7 but it is back to being usable again.

like image 71
Dean Edwards Avatar answered Sep 21 '22 19:09

Dean Edwards


I was unable to find any documentation that this is a known bug. To improve performance, why not cache the clientWidth property and update the cache periodically? I.E if you code was:

var someValue = someElement.clientWidth + somethingElse;

Change that to:

// Note the following 3 lines use prototype
// To do this without prototype, create the function,
// create a closure out of it, and have the function
// repeatedly call itself using setTimeout() with a timeout of 1000
// milliseconds (or more/less depending on performance you need)
var updateCache = function() {
   this. clientWidthCache = $('someElement').clientWidth;
};
new PeriodicalExecuter(updateCache.bind(this),1);

var someValue = this.clientWidthCache + somethingElse
like image 27
Josh Avatar answered Sep 21 '22 19:09

Josh