Focusable Elements with tabindex

By  on  

I was recently debugging a Dojo-fueled web application that features a "Tree" dijit (much like Christoph Pojer's MooTools Tree Component). The tree's container had a fixed width and an CSS "overflow" property of "hidden" to avoid scrolling. The problem I was encountering was that when I clicked a tree item, the item would receive focus and, if it were too long, the left side of the container would get "cut off." Of course I could add overflow:auto to the container but the goal was to avoid scrolling with the element.

I spent hours trying to figure out how to avoid this "left-side cutoff." I tried using different CSS positioning, display types, and floating. I tried using Dojo to listen to tree item focus events and quick scroll back to the left -- that didn't work either. After hours of researching and testing, I found a method within the Dijit TreeNode class called setFocusable:

setFocusable: function(/*Boolean*/ selected){
	// summary:
	//		A Tree has a (single) node that's focusable.
	//		Mark that this node is/isn't that currently focsuable node.
	// description:
	//		In particular, setting a node as selected involves setting tabIndex
	//		so that when user tabs to the tree, focus will go to that node (only).

	this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
},

The method modifies the tabindex attribute of the element. Initially I didn't think it could be possible that this was the problem. After a few quick tests, however, it was apparent that tabindex was causing the problem. I did a quick search and hit Jonathan Snook's Making Elements Focusable with tabindex post. Snook explains:

The tabindex value can allow for some interesting behaviour.

  • If given a value of "-1", the element can't be tabbed to but focus can be given to the element programmatically (using element.focus()).
  • If given a value of 0, the element can be focused via the keyboard and falls into the tabbing flow of the document.
  • Values greater than 0 create a priority level with 1 being the most important.

After a bunch more testing (...and cursing) I realized just how powerful tabindex can be. For those of you who prefer to read code, here's an example usage:

<a href="https://davidwalsh.name">Some Link</a>
<!-- ...tabs to.... -->
<span id="my-span" tabindex="0">Some Span</span>

And I can use JavaScript to focus on it!

document.getElementById('my-span').focus();

The A element wouldn't usually tab to the SPAN element but thanks to tabindex, it does. Imagine how much more powerful tabindex can be when used with JavaScript, as evidenced by the original Dojo snippet. I can programitically give or remove the ability for any element to receive focus by modifying its tabindex attribute. Sweet!

Part of me feels like I should have known about tabindex with focus() sooner -- the other part of me feels like it's a quirk that's not very commonly used. What do you think?

Recent Features

  • By
    Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() - this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

  • By
    9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

Incredible Demos

  • By
    Create a Simple Dojo Accordion

    Let's be honest:  even though we all giggle about how cheap of a thrill JavaScript accordions have become on the web, they remain an effective, useful widget.  Lots of content, small amount of space.  Dojo's Dijit library provides an incredibly simply method by which you can...

  • By
    Create Digg URLs Using PHP

    Digg recently came out with a sweet new feature that allows users to create Tiny Digg URLs which show a Digg banner at the top allowing easy access to vote for the article from the page. While I love visiting Digg every once in a...

Discussion

  1. CTuLT

    \(^O^)/ You finally learned Dojo! Still much more to learn, but you learned the basics! I have been using Dojo for 4 years and I still don’t know it all.

  2. MLaZz

    I used tabindex on my MultiSelect plugin (http://mootools.net/forge/p/mutiselect) to allow for keyboard navigation. Other than that i0ve never used it before, never needed..

  3. Luke

    I never realised that setting tabindex to -1 or 0 performed that behaviour… What I read when I first started learning HTML…going back a while XD, is that 0 is the start… now that just tells me I learnt from an in-accurate source, what they also said is that tabindex should take a value from 0-x, which also left me in the dark about using -1 to ignore an element. What you said is exactly right that tabindex is alot more powerful than it first appears and I think it opens quite a few door ways to custom and/or complex kayboard navigation.

  4. Great tutorial !
    I test with jQuery , it’s work:
    `document.getElementById(‘focusi’).focus();`
    I suggest you add in the github

  5. Pat Nellesen

    Thanks for the info about tabindex – I wasn’t aware of that behavior either (and I’ve been doing this stuff for a very long time ;) )

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!