2011-06-24

You have failed me for the last time, Firefox

In my last post, I mentioned that Firefox was causing issues with my custom on/off control. I solved that problem, but now I have a new one.

When the on/off control renders, it renders with an onclick attribute that calls the function that moves the slider and sets the value of the control in a hidden field. If I want to add any more actions to the control (a common one is to change its color when the value is changed), I use the jQuery .click() function to attach a JavaScript function to its click event.

On a page with several on/off controls, I have bound click events to change their color and enable a save button on change. It's worked every other time I've done this, and it works in this case as well — except for Firefox. For some reason, the last group of controls (which happen to be rendered in an ASP Repeater) do not fire the jQuery click event. What's worse, even though clicking on them does in fact slide the button from one value to the other, it apparently is not setting the hidden form field to change the value — and all that code is being run from JavaScript called in the onclick attribute.

I have found numerous references to jQuery click events not being fired in Firefox, but none of the solutions will help me here. I can't move my code into the onclick event, since I need to register the click handlers from different places; and nothing is apparently wrong with the code as it works as-is not only in other browsers, but in the same browser elsewhere on the same page.

I have spent the better part of a day trying to find where this click event is being "swallowed", and why this code that works perfectly on IE, Opera, and Chrome is not functioning in Firefox. I'm done. It's an internal tool, and we have the luxury to mandate our users' browser choice to some degree.

Firefox, I don't know what your problem is, but I am tired of wasting days of development time trying to find solutions for problems that only exist in Firefox. You are the weakest link. Goodbye.

2011-06-17

Firefox, jQuery, and RegisterStartupScript

I have created a control for the web project I'm working on at work. It's an On/Off slider control, very similar in appearance to the one used by iOS, that uses jQuery to animate the sliding switch on click. Over time, I've added more features and support to it as requirements have come in — its message text is configurable, it can raise its own postback events, and it even works in AJAX postbacks. Someday, I might have to publish the code (maybe when I get rid of its dependence on images and make it size-adjustable as well).

When the control is first rendered, the slider switch is centered halfway between "On" and "Off", and I call Page.ClientScript.RegisterClientScriptBlock that calls that control's "set" function to slide the switch to the correct position. (The control's client click event sets the control's value property and calls this same function to slide the switch back and forth on demand.) It works great on IE, Opera, Chrome… but not Firefox. It would render the first few correctly, but somewhere halfway down the page (depending on how many switches were involved — my particular example page had 10), the slider switches would remain in their centered, "unset" state.

This is getting to be a theme.

I found that, if I added an alert() call before every SetSlider call, then every switch would be set, except the last one. If I reversed the calls so the alert() came second, all the switches would be set.

I was able to solve the problem by wrapping each SetSlider call in a jQuery ready function (i.e., $(function(){ … });). Because the control is self-contained and has no knowledge of other sliders on the page, that's a lot of ready functions; but jQuery seems to handle it without incident. The only other thing I had to deal with was to ensure any startup functions I had to alter the switches' states must come after those SetSlider functions — in my case, moving the code to the page's PreRenderComplete event (because, according to MSDN, the controls' PreRender events, where I registered the SetSlider methods, get called after the page's).

It works, but it still took a couple hours out of my day to find it and then fix it. Thanks again, Firefox.