2011-08-02

Firefox, jQuery, and event binding, revisited

While I had decided for myself that I didn't want to support Firefox anymore, the company that signs my paychecks respectfully disagreed. Because my project is an internal admin tool, we were able to tell our user base not to use Firefox for the time being and assign the bug a relatively low priority — but, it was something that should be revisited and fixed. Having completed my tasks well ahead of schedule, the time was at hand.

The bug had to do with Firefox failing to fire off a jQuery click event handler. I had long since installed the Firebug extension, but all it could tell me for certain was that the event handler code was not being called. I was fortunate, in my searching, to find another extension, FireQuery, which extends Firebug by adding jQuery information to the debug panels. Installing that and viewing the HTML, I could see that the jQuery click event handler simply wasn't there on the switches that weren't working.

Using the development version of jQuery, I stepped through the code that attaches the event handler, and I could find no difference in code execution between the switches that worked and the ones that didn't (unsurprising, since I attached to all of them at once).

The solution, surprisingly, came about when I started mucking around with elements and styles, substituting divs for lis in a desperate attempt to find the cause. To make a long story short, it was the fact that, later in the code, I called a jQuery plugin called "text-overflow" that emulated the text-overflow: ellipsis stylesheet directive that every browser but Firefox supports.

The problem with the code is that, in order to emulate the feature, the plugin creates a cloned copy of the node to "ellipsify" and progressively removes characters until the width of the cloned node fits in the desired width of the original. Then, it sets the contents to be the new text, and destroys the copy. Unfortunately, there are a couple side effects:

  1. If no truncation happens, the contained elements lose their event bindings, since they end up not being the original elements, but copies.
  2. If truncation does happen, when the contents are replaced with the new text, any other elements contained therein (i.e. hidden form fields holding data for a form post) are wiped out.

The first problem might have been overcome by using jQuery's own clone method which clones nodes and any events associated to them. (This was added after the plugin was written, so I don't fault the author for oversight). To be safe, though, I changed the class on the switches' containers and excluded them from my .ellipsis() call. That successfully kept the slider click event handlers from disappearing.

The second problem was the source of another bug, where a jQuery function attempting to look up values from hidden form fields was failing to find the data on elements that were truncated by the text-overflow plugin. I moved the hidden form fields outside of the elements targeted by the function call, and that, too, was magically fixed.

Internet Explorer has a bad (and well-deserved) reputation for needing special development time to do the same thing that other browsers do (although, in my experience, a lot of this would be unnecessary if it weren't for a requirement, usually from an upper-level executive or, worse, marketing, mandating pixel-perfect replication across all browsers), but I've found lately that the pendulum has swung far the other way to deal with the quirks in Firefox.

No comments: