W3C home > Mailing lists > Public > wai-xtech@w3.org > July 2007

Re: Accessible custom contextmenu

From: Chris Blouch <cblouch@aol.com>
Date: Tue, 24 Jul 2007 14:49:50 -0400
Message-ID: <46A649CE.5050508@aol.com>
To: joshue.oconnor@cfit.ie
CC: kiran.kaja@sap.com, wai-xtech@w3.org
I generally use my own focus move function which takes care of this. It 
checks to see what kind of object it is and if it's nor normally 
focusable it checks for a tabindex. If there is no tabindex then I add 
tabindex="-1". So depending on what your particular implementation is  
you might not want to add tabindex="-1" but typically I don't see DIVs 
with tabindex set on them.

Maybe this is diving into too much implementation detail but to make 
things a bit easier, here is the commented version of my focus move 
function. It is part of a larger accessibility library we're promoting 
within AOL.

------------------------------
//Version 1.0.3
//July 23 2007
//C. Blouch

var axs={
// Move focus to any item in the DOM passed in.
// obj-DOM node to focus on
// tv-tabindex value to set on the object. Default is -1.
focus:function(obj,tv){
    //These items don't need tabindex added. It first checks to make 
sure we don't need to bother modifying attributes
    var 
focus_exceptions={A:1,AREA:1,BUTTON:1,INPUT:1,OBJECT:1,SELECT:1,TEXTAREA:1};
    //Four checks here
    //1. If we are passed in a tab value then go right ahead and set the 
tabindex
    //2. If we are not given a tabindex then we need to make sure the 
object even needs one at all
    //by verifying that it's not on the focus_exceptions list otherwise 
go on and check for an existing tabindex
    //so we don't clobber one that is already assigned.
    //3. Firefox check
    //getAttribute("tabIndex") returns a null when there is no tabIndex, 
so go ahead and add it
    //If it isn't null then there is a an existing tabIndex so leave 
things alone.
    //Doing a getAttributeNode().specified in FF on a null node breaks, 
but why would somebody move focus to nothing?
    //4. IE check
    //In IE getAttribute("tabIndex") returns a 0 even when there is no 
tabIndex so we don't know if tabIndex DNE or
    //if it was previously set to 0. So getAttribute should fail in IE 
because 0!=null. The getAttributeNode checks whether the
    //tabIndex value was specified or is just a default value. We first 
have to check if the getAttributeNode method exists
    //because IE5.5 and below lack this. If the method exists we use it 
to check if tabIndex is not specified.
    //If true we go ahead and add a tabIndex.
    //Also note that "tabIndex" must have the capital I to work in IE, 
even though the html is specified as "tabindex"
    if(
        tv ||
        !focus_exceptions[obj.nodeName] && 
(obj.getAttribute("tabIndex")==null ||
        (obj.getAttributeNode && 
!obj.getAttributeNode("tabIndex").specified))
    )
    {
        //If we aren't passed in a value to set tabindex to then default 
to -1
        if(!tv)tv=-1;
        obj.setAttribute("tabIndex",tv);
    }
    //We check that the .focus method is available before invoking it to 
protect older browser from JS errors
    if(obj.focus)obj.focus();
}
}
-----------------------------------------
Without comments it's about 370 bytes uncompressed which isn't even 
worth a separate JS fetch. Here is the relevant snippet from my 
documentation (which loses its nice HTML formatting in this email but 
it's still readable).

axs.focus(obj, tv)
Parameters
    obj - The DOM object you want focus moved to
    tv - [optional] Integer tab value to assign
Purpose
    After updating some part of the screen through Ajax or other DOM 
manipulations you should move focus to the object that contains the new 
content so folks with screen readers of other accessible technology will 
know there is a change.
Implementation
    This method will move the browser's focus to the object you specify. 
If the object is normally focusable, such as a link or an input, focus 
is simply moved there. If the object is not normally focusable we add a 
tabindex of -1 which makes it focusable. If the object already has a 
tabindex we leave it alone. If you pass in a tabindex value then we use 
that as the tabindex to assign to the object.
Example
    //Get object we want to focus on
    var bob=axs.id("myDivID");
    //Move focus to bob and give it a tab index of 5
    axs.focus(bob,5);

We've been using this for quite a while and it seems to work well. Hope 
others find it useful.

CB

joshue.oconnor@cfit.ie wrote:
> Chris Blouch wrote:
>   
>> You will need to put tabindex="-1" to make the div focusable. 
>>     
>
> But won't that take that div out of the existing tab order? And if the
> user needs to get back to it will they have difficulty? Unless there is
> a Combobox or some other form element embedded within the div that the
> user can easily access via the Virtual HTML Features within JAWS or
> other virtualisation features within screen readers (or by using quick
> keys). The form element would also have to be continually exposed to the
> screen reader even if it is to be hidden from a sighted suers, via some
> Javascript show/hide mechanism, in order for it to be 'constant' as
> such, even if hidden from sighted users. Especially after that function
> has been revealed to the user.
>
> I am not sure of *best* practice myself in these cases, especially if
> there are several dynamic widgets within the page that alternately need
> focus, and I know this is something that WAI-ARIA and the DHTML Roadmap
> are trying to address. At the moment the best techniques on offer are hacks.
>
> Josh
>
>   
Received on Tuesday, 24 July 2007 18:50:18 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Friday, 27 April 2012 13:15:43 GMT