Breaking changes in recent versions of jQuery - focus handling

Antranig Basman antranig.basman at colorado.edu
Thu Dec 19 20:13:08 EST 2013


Continuing with my FLUID-5185 work upgrading our core framework dependency, I can report on some more issues 
which we need to be aware of working with current versions of jQuery, and other bugs. It seems that we have 
good consensus on our approach to $.browser, which I have now implemented (thanks, Colin). Note that 
"FluidDocument.js" is now a required dependency for every Infusion page using the framework - it should 
appear immediately after Fluid.js.

A crucial change in newer jQueries (most likely post 1.9) relates to propagation of focus events. In fact, 
this change sheds light on some oddities that we noticed over the past 5 years but never investigated 
completely - these led me, for example, to insert a new jqUnit.simulateFocus method into my IE compatibility 
pull request which can be seen here:
https://github.com/fluid-project/infusion/pull/437/files
(this pull request is independent of and predates the jQuery upgrade work).

It seems that the jQuery change directly impacts this area - the fidelity of relay in synthesised focus and 
blur events. It appears that historically, jQuery has relayed these events "synthetically" - that is, with a 
direct relay within the jQuery event system between firers and listeners. The change is that these events 
are now relayed "natively" - that is, jQuery makes no extra attempt beyond what the browser does to relay 
the event - a trigger of "focus" relays to a native "focus" which the browser may or may not then relay to a 
listener attached to "focus". You can currently investigate the old behaviour, for example, by browsing to

http://build.fluidproject.org/infusion/tests/component-tests/uploader/html/HTML5UploaderSupport-test.html?testNumber=4
and setting a breakpoint in the onBlur handler - HTML5UploaderSupport.js line 271 - if you look down the 
stack, you will see that we are directly connected to the site of the "blur" call in the test case, " 
inputs.eq(1).blur();" at line 308. In the new jQuery this will no longer be the case - if we reach this 
site, the browser's event engine will be at the base of the stack.

Whilst these changes are in theory helpful, they are in general very disruptive to our test cases which have 
been written with various assumptions which are now no longer valid. In particular there are two important 
kinds of change to be aware of:

i) focus and blur events for DOM nodes which are not visible are now in general not relayed. This implies 
that display: none needs to be taken off the remainder of our markup fixtures (this has been generally been 
being removed in any case)
ii) focus and blur events in general now may well not be relayed synchronously between firers and listeners 
- since these now pass through the browser's event dispatching engine. Thankfully in the meantime we have 
now acquired the "IoC Testing framework" which allows us to rewrite some of these tests in a way which 
abstracts over the presence or absence of asynchrony, without which we would be in a nasty "callback hell".

In addition to these points, the exposure of "native focus relay" has itself exposed a clear browser bug, in 
Firefox's handling of focus events on file upload controls. It appears that a "blur" for this kind of 
control is never honoured by Firefox at all. Previously, jQuery would paper over this issue for us as a 
result of its "direct framework relay" of the blur event, making us believe it had been honoured. I've 
uploaded a very minimal test case for this issue here:

http://ponder.org.uk/public/VerySimpleTest.html

This should be reported upstream to Mozilla in due course.

In the meantime, the workaround is to produce a dummy control onto which we transfer focus when a "blur" is 
required on the primary control. Firefox is able to service a "blur" when focus is pushed onto this element, 
even if it can't service a "blur" directly. In order to write the test cases reliably, I've also had to 
expose a dedicated "focus" event from the browse control, without which it is impossible to sequence the 
tests properly - we may find ourselves doing this in a lot of components as we write a11y tests for them. 
The remaining "unexpected failures" are in InlineEdit which I will look at this evening, and I expect the 
causes to be quite similar - if they are not, I'll write a further report.

In general, the take-home message is captured in points i) and ii) above - i) don't expect focus tests to 
work any more on markup which is not visible, and further, keyboard-a11y-tests.js has been added to the 
existing collection of tests which will not run correctly if the browser window is not top level (since 
native focus events will not be delivered in that case either), and ii) be prepared to write focus-aware 
tests using the IoC testing framework, and to expose additional events from these components to let these 
tests be sequenced properly. Here's a sample in my rewrite of one of the HTML5 Uploader support tests:

https://github.com/amb26/infusion/blob/f1f501d2ca66986050002284d55a8f78a24804d1/src/tests/component-tests/uploader/js/HTML5UploaderSupportTests.js#L280

Sorry for another long posting, but simulation of focus in our tests is a crucial area where we require 
reliability as an a11y community, and this upgrade of one of our core framework dependencies has forced some 
of these portability annoyances into visibility.

Cheers,
A


More information about the fluid-work mailing list