Re: Tricks for ARIA on the iPad/iOS

December 2nd, 2010

Brad Neuberg has a post up about ARIA on the iPad and some of the tricks he’s used to bend it to his will. Blogger won’t accept my OpenID to comment on the post for some reason so I’ll add some thoughts here.

tabindex

As Brad notes, you can set tabindex=”-1” to prevent an item in HTML from appearing in the tab order. Also as Brad notes, this won’t stop the VoiceOver cursor from moving to that element. It’s important to remember that the VoiceOver cursor is not linked to the keyboard focus, it’s linked to what is being read out to the user. This can be very confusing but it’s an important concept, allowing you to review parts of a document without losing the current caret position where you want to continue editing. Most screen readers seem to have this distinction between the text input focus and the screen reader cursor.

tabindex=”-1” also won’t prevent the user from moving keyboard focus to an element by means other than the tab key. For example, clicking on a textarea will move the keyboard focus to it even if it has a tabindex of -1.

aria-hidden

As a work-around to try and prevent VoiceOver from focusing an element, Brad then added aria-hidden=”true”. To his credit, Brad notes this isn’t a good situation and indeed it’s not. Now we have an element which is available to sighted users, but completely hidden to the screen reader. This is almost never what you want.

If something shouldn’t be a landmark, it probably shouldn’t be a heading element and if it shouldn’t be read by a screen reader it should generally be either not there at all or both aria-hidden=”true” and display:none; That way the element disappears for everyone, not just those using a screen reader.

I’m not quite sure what Brad was trying to achieve so I can’t really suggest the right workaround for his use case but it sounds like there may be a need to go back and get the basic semantics of the HTML right.

aria-labelledby

I’m not entirely sure what Brad’s aiming for here again but it’s a bit unusual to try and add extra audible information to a heading which isn’t available to sighted users. Normally labelledby would be used for form elements to link them with the text that describes what they’re for. My first thought here is to adjust the HTML to make it more semantic rather than trying to fix it up with ARIA. For the example HTML:

<div aria-labelledby="testH1 testH2 testDIV1">
<h1 id="testH1" tabindex="-1">
This is an H1
</h1>
<h2 id="testH2" tabindex="-1">
This is an H2
</h2>
<div id="testDIV1" tabindex="-1">
This is a div
</div>
</div>

I would say the right thing is to not have any ARIA attributes (or tabindex) at all. h1,h2 and div all default to the equivalent of tabindex=”-1” anyway and if a sighted user would see this as two separate headings and a normal paragraph, a screen ready probably should too. If it’s intended to be read as a single sentence then as a signted user, I’d appreciate it being laid out that way.

aria-label

As a side note, aria-lablledby is only one option for adding information and it’s useful if the extra information you need to present is already available in a textual form somewhere on the page. However, if the content isn’t available (for example because it’s using an icon instead of text) you can use aria-label=”The label you want” to directly specify the label text rather than referring to some other HTML element.

More Info?

It would be great to get some better background information on what’s being attempted here so that better solutions could be proposed. Right now it looks a bit like trying to use ARIA to hammer a square peg into a round hole which not surprisingly isn’t a lot of fun and doesn’t work very well.

The bottom line is that ARIA isn’t the answer to accessibility, it’s just a smattering of extra information to help out in complex cases where HTML and JavaScript are being used to create custom widgets. The first and most important tool for creating accessible web pages is still to use appropriate semantic HTML – especially for the “document” parts of a page as opposed to interactive widgets. If that foundation isn’t set, ARIA won’t save you.

Controlling Focus in Firefox

November 24th, 2010

I have a bunch of JavaScript unit tests and for some of them I need to trigger a real keypress – one that activates the browser’s default functionality, not just triggers the JavaScript listeners. To do that, I have a simple signed applet that uses the AWT Robot to programmatically trigger the keypresses. Mostly, this works brilliantly.

The problem I’m having is that about 1 time in 10, the focus goes AWOL and the key events generated by the robot simply aren’t delivered anywhere. It’s generally not reliable, though I have got a setup now where I can make it happen within a few minutes of running the tests on a loop.

The problem is specific to Firefox 3.6 – I’ve never seen it fail on anything else. I’m testing against Firefox 2.0, 3.0, 3.6 and 4.0 beta 6. 3.6.3 and 3.6.12 to be precise. It fails on all the OS’s I’ve tried: Linux (Ubuntu 10.10), Mac OS X (10.6) and Windows Vista.

The Simple Question

Is there a sure-fire way in JavaScript to force focus to a specific element?

The normal Element.focus() doesn’t seem to be strong enough as I’m already calling that (and I’ve tried oh so many variations of it). I’m even ok with requiring that element to be of a specific type (e.g. a text input). JavaScript is ideal but if it can be done with a signed Java applet I’m ok with that too. Config options, browser plugins and maybe even native code would all be a possibility.

The Simple Answer (Update)

It turns out that the ineffectiveness of Element.focus() is a usability/security feature of Firefox which is configurable. In the “Content” tab of preferences, click the “Advanced…” button beside JavaScript and then ensure that “Raise or lower windows” is checked. Annoyingly simple after the amount of effort it took to work out what was going wrong.

Firefox advanced JavaScript preferences window

The Detail

Here’s what I know:

  • The test runner framework loads the actual test pages inside an iframe.
    • The signed applet is inside this iframe.
  • The test that is giving me trouble uses TinyMCE, which itself uses an iframe, so we have an iframe inside an iframe and that’s where we need to get focus.
  • To make sure that the actual browser pane has focus (rather than the URL bar etc), when the page first loads the applet clicks just above itself (thus moving focus to the actual test page inside the first iframe).
    • I can watch this happen so I know the click is in the right place.
  • The page is definitely fully loaded before the problematic test runs. It’s not the first test in that file but it is the first test that actually uses the robot (the click still happens on page load). I can’t remember a failure where it wasn’t the first test using the robot that failed but can’t be 100% certain of that.
  • I’m using the JavaScript focus() method to move focus to the element I’m targeting.
    • I’ve found I need to focus the main window, then each nested iframe window and document body and then finally the element I want to target to make sure that the focus is on the right frame.
    • I can check that document.activeElement is pointing to the right place.
  • When the focus gets lost, even manually typing keys does nothing.
    • But typing tab will move the focus back to the right spot and then typing the key the test was expecting will make the test pass correctly.
  • The key event is definitely firing from the AWT robot, because if that key is the tab key, it correctly moves the focus back to where it should be (but I have no way to know programmatically that I need to repeat the keystroke).

Why Not Selenium?

Just to cover this off, there are a few reasons that this project isn’t using Selenium:

  1. It was an existing project which already had tests using QUnit and most of the tests don’t need this Robot functionality so can be done in pure JS.
  2. It’s a pure JS project so it’s really nice to also write the tests in JavaScript (the robot has a nice JS wrapper).
  3. This approach lets me run the tests in any browser without requiring any setup at all. No need to install and configure anything – you could very likely walk up to a computer in an internet cafe and have the tests pass which makes life so much easier.
  4. It should work damn it! I want to know why it doesn’t and why Selenium, which also uses the AWT Robot doesn’t hit the same problem (or maybe it does?).

Murphy’s Law

Just before starting to write this post (some 30 minutes ago due to distractions), I had the crazy idea to add a java.awt.TextField to the applet and make the applet a little bit bigger (150x40px instead of 10x10px). The tests have been running continuously with that new configuration since then without a single failure. The text area is never used in any way, but for some reason just having it there seems to make life better. I don’t get it.

Due to a power outage I can’t run it on the actual build servers until tomorrow so I’m going to post this anyway since you just know it will start failing again just as soon as I think I’ve got it fixed.

Update 10 seconds after posting: Yep, there it goes, failed again.

Apple-Scented Coffee Beans are Accurate

November 12th, 2010

So Apple have announced that they will be contributing large swaths of code to the OpenJDK project and that from Java 7 onwards, Java will be a separate download from Oracle, much like Flash is now a separate download from Adobe. This really shouldn’t be unexpected for anyone who was paying attention to what was going on rather than just running around thinking the sky was falling.

This is fantastic news for Java developers of all types. Mac Java developers have been asking for Java to be separated from the OS for many, many years so that multiple versions of Java are more manageable and especially to decouple Java releases from the OS release timeline.

Since the main JVM for OS X will now be open source, intrepid developers can dive in and fix issues they run into or at least dig into the code to understand it better and find work-arounds they can use. Apple has historically been quite innovative with it’s JVM port as well, bringing some great stuff to the JVM on OS X first1. It should now be easier to share those innovations across platforms which is great for all Java users.

It’s also nice to know that Java 6 will continue to be bundled with the OS in OS X 10.7 Lion. That gives a nice ramp-up for Apple and developers to transition to an optionally installed JVM and ensure things work smoothly either by applications bundling a JVM with the app or the installer or through auto-install methods for applets and webstart etc.

Finally, this should mean that JDK7 development on Mac will be done in the open, giving developers earlier and far greater access to try it out and report any issues back.

Seems like a huge win all round to me.

1 – for example the ability to share the core classes between JVM instances, but also a lot of stuff in how swing works and integrates with the OS

On the DVD vs in Software Update

October 27th, 2010

James Turner gives a week in review and mentions the deprecated Java on OS X issue1. One thing to correct:

Deprecation basically means that neither package will be delivered as part of the installation DVDs, and updates will not come via the Apple update mechanisms. It doesn't mean they won't be available anymore, it just means you'll have to download them directly from Oracle and Adobe.

Firstly, there’s nothing to suggest that Java won’t come from Apple but not be part of the standard OS X package.

Secondly, just because something isn’t on the OS X install DVD doesn’t mean it’s not updated via Software Update. Aperture for example is a separately purchased product but updates come through Apple Software Update automatically. On Lion, software update is likely to open up further since it’s the obvious conduit to deliver updates for apps on the Mac App Store.

Of course, if the JVM winds up coming from Oracle, I wouldn’t hold your breath for updates via Software Update.

1 – I’m not sure how deprecated Java counts as lost in the hubbub of Back to the Mac, from where I’m sitting it looks a lot like the other way around but anyway.

Reading the Apple-Scented Coffee Beans

October 26th, 2010

It’s interesting to see how many people are jumping to conclusions around the very carefully worded deprecation notice for Java in OS X. Read it carefully and pay careful attention to what it actually says:

As of the release of Java for Mac OS X 10.6 Update 3, the Java runtime ported by Apple and that ships with Mac OS X is deprecated. Developers should not rely on the Apple-supplied Java runtime being present in future versions of Mac OS X.

Most notably the note only refers to the Apple ported JVM that ships with OS X. This leaves the door open for an Apple ported JVM that ships as a separate download and for a non-Apple JVM that ships with OS X.

If you can drown out all the screaming and gnashing of teeth and pay attention to the Apple Java-Dev list you’d also notice:

  1. A huge amount of effort went into this release, especially setting things up to support multiple JVMs from multiple vendors. In the past, there was only one JVM available on an OS X install, it was upgraded with the OS and provided by Apple1.
  2. Even after this release, the Apple engineers who post to the list are still talking about their long term plans for the JVM (one example).

No one outside of Apple knows for sure what the future of Java on OS X is, and those inside who do know aren’t allowed to talk, but given the currently available evidence it seems at least as likely that Apple will continue to provide a JVM but as a separate download (or possibly just an optional install) as it is that they’ll abandon Java entirely.

Yes, there is a chance that Apple will just walk away from Java and leave a gaping void, but I don’t see indications that it’s a corporate strategy of Apple. Remember that Apple isn’t a company that sends a lot of mixed messages. They can turn a marketing message on a dime and they don’t pull punches. They’re also small enough and tightly managed enough that it’s rare for one part of the company to be off doing something that’s not inline with the company direction. If people are still building improvements to Java on OS X rather than moving to maintenance mode, that’s a strong signal that there is a future of some kind.

The real problem here is the same one that always happens with Apple – they’re not communicating their plans so developers can plan accordingly and not panic. But if you haven’t learnt to roll with the punches that approach delivers, you’re not a real Mac developer.

1 – A situation which caused most of the complaints on the java-dev list.