Wednesday, February 29, 2012

How I booked the flight or the curse of cancel button

Recently I booked the flight for me and my family. After some search I stopped at Rossiya airlines (Saint-Petersburg's airlines). It was new airlines for me but they offered the best option.

So I started booking and somewhere in the middle I decided to use another bank card. I pressed cancel button (instead the pay button) and it says the payment failed. No option to retry.

I tried to dial the call-center of Rossiya airlines, several times, but no any luck to ring till the bell is answered. So I wrote them email and in few minutes I got an answer:
Unfortunately you can't pay by bank card online if you rejected to do that once. But you can pay in our office, choose another payment type or book another flight.
Sure I tried to book the flight again but the price surprised me. It wasn't the best option anymore. So I decided to pay existing one and since another payment type usually assumes a noticeable fee then I said:
Ok. What is address of your office in my city.
They said:
Unfortunately we don't have offices in your city. You can try to pay by VTB-24 ATM or in VTB-24 bank office.
I asked about the fee. They said no fee. Ok, nice.

I located VTB-24 ATM near of my house and tried to pay. When I typed the payment info then the ATM said that it can't process this request. I thought maybe VTB-24 ATM can vary, thus I checked Rossiya airlines web site which ATM can be used to make this payment. Next day I tried another VTB-24 ATM. This time when I specified all payment info it said "the feature is not implemented". The farther into the forest the thicker the trees I thought.

So I came to the office of VTB-24 bank to make a payment. They said I can't pay by my bank card. Of course if that was a bank card of their bank then I could do that but otherwise they can't help me and they need a cash. So I moved to ATM of my bank and got that cache, got back to that office and oh happiness I did that.

Say me what a heck I pressed that cancel button.

Friday, February 24, 2012

Firefox 12 for AT developers

Firefox 12 is still on aurora channel and expected to enter into beta stage at 13 March. It doesn't have much "front-end" features but there's couple ones that might be interesting for AT developers. We did some under the hood work and crash fixes. Also we improved Mac accessibility support but it's still not a part of the default build.

ARIA support gained some sugar for multi-selectable widgets like ARIA list and tree. Now the selected state is exposed on list options and tree items by default, i.e. until aria-selected="false" is specified. This prevents screen readers like JAWS and NVDA to say "unselected" for many ARIA widgets on the web when the user traverse through their items. So a bit of sugar to keep users less annoyed.

We fixed NAVRELATION_EMBEDS MSAA relation on Firefox application accessible (ROLE_SYSTEM_APPLICATION/IA2_ROLE_FRAME). It failed to return a selected tab document accessible under certain circumstances, for example, when Firebug is installed.

Invisible and offscreen states

The most important change is we altered a logic how we expose MSAA INVISIBLE and OFFSCREEN states and ATK VISIBLE and SHOWING states. Let's do some background on this.

ATK VISIBLE means visible or the user can make it visible. ATK SHOWING means visible, i.e. on the screen. See the post  for the reference.

MSAA expectations are different. INVISIBLE means not visible on the screen (in either case), OFFSCREEN means it's not visible on the screen but the user can make it visible. See the post for the reference.

So based on that we'd need to do the following:
  • on the screen
    • MSAA: no INVISIBLE & no OFFSCREEN
    • ATK: VISIBLE & SHOWING
  • not on the screen
    • MSAA: INVISIBLE & OFFSCREEN
    • ATK: VISIBLE & no SHOWING
  • hidden accessible
    • MSAA: INVISIBLE & no OFFSCREEN
    • ATK: no VISIBLE & no SHOWING

However Firefox didn't expose hidden accessible this way on MSAA so we decided to not fix this and keep the logic closer to ATK spec:
  • on the screen
    • MSAA: no INVISIBLE & no OFFSCREEN
    • ATK: VISIBLE & SHOWING
  • not on the screen
    • MSAA: no INVISIBLE & OFFSCREEN
    • ATK: VISIBLE & no SHOWING
  • hidden accessible
    • MSAA: INVISIBLE & no OFFSCREEN
    • ATK: no VISIBLE & no SHOWING

Also we started to treat accessibles from the background as offscreen (previously they were exposed as invisible). The reason of doing this is usually ATs ignore invisible accessibles but they are interested in changes happening in background tab.

If you need more information on this then please refer to the bug to read discussion.

Monday, February 20, 2012

aria-hidden and role="presentation"

John Foliot pinged me about his blog post devoted to ARIA techniques used to hide the content from assistive technologies. Since I don't have straight answer then I decided to put my thoughts here.

presentation role
ARIA role="presentation" technique is intended to hide an element from AT users. A classical example is presentational images. If you place role="presentation" on the image then it gets removed from accessible tree. Also this technique can be used to remove HTML table semantics, i.e. if role="presentation" is specified on HTML table then table structure is not exposed.

ARIA role="presentation" is completely ignored if it's used on focusable element. That means the element isn't removed from accessible tree and its native semantic is exposed. For example, if you put this role on HTML button then it's revealed as normal HTML button to AT. This is reasonable because if the user focuses the button then focus doesn't get lost and screen reader announces something meaningful.

aria-hidden
The most noticeable difference from role="presentation" is aria-hidden affects on whole subtree. John gave a good use case: hide excess links from screen reader users. A common pattern is a clickable image inside HTML:a element. ARIA spec confirms this saying "Authors MAY, with caution, use aria-hidden to hide visibly rendered content from assistive technologies only if the act of hiding this content is intended to improve the experience for users of assistive technologies by removing redundant or extraneous content."

I should notice that ARIA is not designed to change visual presentation and affect on behavior. Thus if this is an ordinal link then no ARIA technique can be used to hide it from screen reader user since this contradicts to ARIA design. But if the author puts @tabindex="-1" on the link to make it unfocusable then aria-hidden looks like a proper way to achieve desired result.

Technical side
ARIA implementation guide allows to remove elements with aria-hidden from accessible tree but it doesn't require that. Also it states "If the object is in the accessibility tree, map all attributes as normal. In addition, expose object attribute hidden:true". Additionally it points that if the aria-hidden attribute is changed then the browser should emit attribute_changed event (in case of IAccessible2). That's exactly what Firefox does.

So Firefox does a minimal implementation of aria-hidden allowing a screen reader to do what it thinks it should. That means each screen readers should invent a wheel and actually that what happens (or doesn't) - check this table to see how Firefox is different depending on screen reader running.

Implementation of aria-hidden both on browser side and screen reader side is not straightforward. For example if some element having aria-hidden contains a focusable element then its *whole* subtree can't be ignored. At the first glance reasonable solution would be if the browser doesn't create an accessible for each element in subtree until the element is focusable, in other words it treats aria-hidden as role="presentation" was specified on each node in subtree. Otherwise AT needs to crawl the accessible tree to check if there's an element with aria-hidden in ancestor chain. The current Firefox implementation forces AT to do that.

Things to think about.
If the browser doesn't create an accessible for aria-hidden subtree then there is a black box having certain dimensions on the screen. Thus if the user investigates the page layout by mouse then screen reader says nothing when the mouse pointer is above that black box but if the user clicks at this area then he gets unexpected behavior.

On the other hand some screen magnifiers use dimensions of accessible objects for page zooming. No accessible then zoom is likely broken.

So at the second glance I think aria-hidden shouldn't change the tree at all. Instead the browser should expose hidden:true object attribute on every accessible from the subtree of aria-hidden element. That allows AT to decide whether they want to ignore the accessible or not and prevents AT to crawl the accessible hierarchy.

I'd say this rule should be applicable to role="presentation" as well. So if the user explorers the page by mouse then screen reader can say this is presentational image but exclude it from keyboard navigation.

Friday, February 10, 2012

DOM Inspector as accessibility tool

As you probably know DOM Inspector (aka DOMi) is Firefox add-on designed to inspect web pages and Firefox UI. In some sense it's ancestor of Firebug but perhaps not so fancy and miss some useful features like integrated JavaScript console. Nevertheless DOMi allows you to inspect Firefox UI what makes it quite different from Firebug. You may say there's ChromeBug but it has less amount of features than DOMi, for example, it doesn't allow to inspect XBL elements.

Anyway, DOMi is really nice accessibility tool also. It's not feature complete and far from ideal but it's quite powerful. And that's probably something new for you. Each platform provides set of accessibility tools like accprobe on Windows, accerciser on Linux or built-in tools on Mac. These tools have own benefits and disadvantages but main thing I dislike they don't allow me to inspect DOM. When you need to understand why your web page or your ARIA widget has accessibility issues then it's quite handy to inspect both DOM and accessible trees and what's most important to see *relation* between elements of these trees. That's what DOMi gives you.

DOM Tree

If you check 'Show Accessible Nodes' menu option then 'DOM Nodes' view of the left panel marks accessible DOM nodes by bold font. This view is good to understand where the specific accessible is located in DOM tree.


Accessible Tree

If you don't want to see inaccessible DOM nodes then you can switch to 'Accessible Tree' view of the left panel. The tree displays accessible role, name and related DOM node information for each accessible. Also you can inspect different properties and relations of interesting accessible by selecting it and choosing corresponding view in the right panel.

Also you should choose this view if you want to work with complete accessible tree. 'DOM Nodes' view doesn't always allow you to do this because accessible tree is not a strict subset of DOM tree. For example, XUL trees often don't have underlying DOM however they have rows and cells in accessible tree.


JavaScript Console

JavaScript console is available in 'Accessible Tree' view from context menu on selected accessible. It gets open in separate window (what is not super comfortable) and it doesn't have set of handy functions to help you with tree inspection but you can evaluate arbitrary JS code and call any method on selected accessible object.

 
Accessible Properties

'Accessible Properties' view of the right panel allows you to inspect accessible properties of the accessible selected in the left panel. You can inspect accessible role, name, states, object attributes i.e. standard set of accessible properties. Also it allows you to invoke accessible actions. Switch to 'Actions' tab to find it out.


Accessible Relations

'Accessible Relations' view of the right panel allows you to see accessible relations and inspect relation targets in separate window.


Accessible Events

'Accessible Events' is a super feature to inspect web pages and ARIA widgets in dynamics. It allows you to
  • watch accessible events and choose events you want to watch;
  • add custom event handlers and see output.


If you switch to 'Watched Events' tab then you can choose a number of events you'd like to listen and add custom event handlers. Custom event handlers feature provides you a set of helper functions to inspect accessible tree and accessible properties at time of event handling. For example, you can use outputTree() function to make a snapshot of accessible tree. Small help button marked by '?' is available to get a list of helper functions.


You can see custom event handler output by selecting handled event in the left panel and choosing 'Accessible Event' view in the right panel.

Accessible Event

'Accessible Event' view of the right panel is used to inspect properties of handled accessible event and contains output of custom event handlers. Here's a snapshot of accessible tree when accessible focus event was handled. Highlighted accessible in the tree is focus event target.


Wednesday, February 8, 2012

Firefox 11 for AT developers

Here's an update what's new in Firefox 11 (beta, release on March 13) for assistive technology developers.

HTML

CSS generated tables (CSS display:table style) are exposed as layout tables. Originally this piece of work was targeted to Firefox 10 but we weren't in time to make this happen.

HTML table cells (HTML th and td elements) gained new not standard axis and abbr object attributes.

The axis object attribute is direct mapping of HTML @axis attribute. This object attribute is supposed to help AT to extract semantic of rich HTML tables in the web. Granted, this HTML attribute is not wide used on the web but we wanted to break the chicken-egg problem: browsers/AT don't support it iff web authors don't use it.

The abbr object attribute is less academic than previous one and useful to pick up short accessible name for header cells, for example, it makes sense when the user traverses through table cells and screen reader announces related heading information for each cell. The user doesn't want to hear long header cell names on and on: that's what abbr object attribute is supposed to help to. This object attribute is exposed in two cases:
  • HTML abbr element is inside the table cell
  • @abbr attribute is used on table cell
Examples:
  <th id="th1"><abbr title="Social Security Number">SS#</abbr></th>
  <th id="th2" abbr="SS#">Social Security Number</th>

HTML acronym and abbr elements allow @title attribute for accessible name computation. This can be illustrated by following example:
  <input id="input">
  <label for="input"><acronym title="O A T F">OATF</acronym></label>
Accessible name of input accessible is "O A T F" now.

HMTL5

HTML5 figure and figcaption elements are now accessible.  The figure element is exposed with generic MSAA ROLE_SYSTEM_GROUPING and ATK ATK_ROLE_PANEL roles because neither IAccessible2 nor ATK provide more suitable roles. AT can rely on xml-roles:figure object attribute to detect figure element. HTML figure element picks up accessible name from figcaption element which is exposed with IA2_ROLE_CAPTION / ATK_ROLE_CAPTION role. The figure and figcaption accessible objects are linked by LABELLED_BY / LABEL_FOR relations.

The content of HTML5 canvas element is not accessible still but Firefox 11 started to expose an accessible object having IA2_ROLE_CANVAS/ATK_ROLE_CANVAS role for canvas element itself. Not big deal but it's a good first step on canvas accessibility.

ARIA

ARIA attributes used on HTML file element (input@type="file") are propagated to underlying text field and "Browse" button, i.e. accessible states defined by these attributes are inherited.

ARIA combobox (@role="combobox") fires MSAA EVENT_OBJECT_VALUECHANGE event and ATK accessible-value signal when option is changed. Here's an example of ARIA combobox widget.

Correctness

IA2_STATE_ACTIVE/ATK_STATE_ACTIVE state is exposed on active item for standard composite widgets like HTML select elements. The state can be used for example to detect the current item of the widget when the widget isn't focused. We make our implementation closer to ARIA widgets where aria-activedescendant technique is used. Another side of this code unification is IAccessible::accSelect called with SELFLAG_TAKEFOCUS flag can be used on widget items now.

Small fix for IAccessible::get_accName that returns S_FALSE when the accessible object doesn't have accessible name. Not big deal. Done for consistence and meet MSAA spec.