Improved Browser Paint Events Bookmarklet

John Resig posted today about a nifty new feature available in Firefox nightlies, browser paint events. He also posted an example script and bookmarklet called TrackPaint. He goes into greater depth in his post, so I won’t bother here.

I wanted something more “real-time” and closer to the Quartz Debug utility included with the Mac OS X developer tools (which essentially provides this feature for all of OS X), so I present my modified bookmarklet and code:

// modified from John Resig’s example: http://ejohn.org/apps/paint/track.js
(function(){
    var container;
    
    window.addEventListener("MozAfterPaint", log, false);
    
    if ( document.body )
        bind();
    else
        window.addEventListener("load", bind, false);
        
    function bind()
    {
        container = document.createElement("div");
        document.body.appendChild(container);
    }

    function log(e)
    {
        window.removeEventListener("MozAfterPaint", log, false);

        var rects = e.clientRects;

        for ( var i = 0; i < rects.length; i++ ) {
            var rect = rects[i];
            var div = document.createElement("div");

            with (div.style) {
                background = "red";
                opacity = "0.1";
                position = "absolute";
                top = rect.top + "px";
                left = rect.left + "px";
                width = (rect.right – rect.left) + "px";
                height = (rect.bottom – rect.top) + "px";
            }

            container.appendChild(div);
        }
        
        window.setTimeout(function() {
            while (container.firstChild)
                container.removeChild(container.firstChild);
            
            window.setTimeout(function() {
                window.addEventListener("MozAfterPaint", log, false);
            }, 0);
        }, 100);
    }
})();

Rather than recording each event and displaying them when you click, this version immediately disables the MozAfterPaint event listener (to avoid the recursion issue), shows the translucent red divs, waits 100 ms, removes the rectangles, and re-enables the MozAfterPaint event listener.

It will miss some events during the 100 ms flash, but overall it seems to work pretty well. You could modify it to re-enable the event listener between adding and removing the divs, but I’m not sure it’s worth the effort.