I've been working on some bugs in the Calendar extender from the ASP.NET AJAX Control Toolkit and have been resolving some of the focus/blur events. I've been trying to make the calendar work consistently across all of the browsers and found some frustrating differences in event firing order between the browsers.
Here are a list of some of the DOM events supported by the various browsers I tested:
IE: Internet Explorer 7.0FF: Firefox 220.127.116.11OP: Opera 9.23SF: Safari 3.03 Beta (Windows)*: Implemented on any element1: Implemented only on specific elements2: IE-only implementation
Internet Explorer uses activate/focusin/focusout instead of DOMActivate/DOMFocusIn/DOMFocusOut for events. Interestingly only IE and Safari support DOMActivate/activate on any element. Another thing I saw was that IE is the only browser which fires focus/blur events for any element. Other browsers can support the focus/blur events on any element that has a tab index however.
The next version of Calendar needs to support the following activation scenarios depending on whether it is also associated with a button:
The issue is that when the textbox or button loses focus the popup should hide unless the focus is being directed at the popup itself. The problem is that only IE recognizes a focus event on the popup's DIV tag when the popup is not part of the tab order (and we don't want the popup in the tab order). I was curious the order of DOM events fired in each browser so I wrote a small test page and stepped through for each. The results are as follows:
Immediately a few things become obvious. First, I obviously cannot rely on focus/blur on the other browsers. IE would allow me to capture focusin on the DIV before the blur fires on the INPUT but that's just IE. Second, on all browsers except Opera the mousedown event of the DIV fires before the blur event of the INPUT. There's no clean sequential way to handle the focus transition in all browsers.
In the current version of Calendar we're making use of a "threading" class I created for the toolkit called DeferredOperation. DeferredOperation wraps a delegate and executes it asynchronously using setTimout. It has some built-in synchronization semantics and was used to handle the focus changes while the popup DIV was part of the tab order (which again, we don't really want). This introduces a subtle delay between activation requests and is problematic on Safari (we had to wait a full second before processing the deferred operation to let safari to catch up).
What I've opted for now is to do the best I can in three out of four of the browsers. I track mousedown/mouseup using a flag and in Internet Explorer, Firefox, and Safari and monitor the flag in the blur event of the textbox. To handle the Opera inconsistency I again use a DeferredOperation to asynchronously handle the blur event which fixes the issue in that browser.
The final issue I discovered was that in all browsers, clicking on the popup causes the textbox (or button) to lose focus which again causes problems with the tab order. On the new Calendar I reset the focus to the textbox (or button) on mouseup on the popup.
Hopefully these changes should make the next toolkit release so keep an eye out for the next update.