SlideShare a Scribd company logo
1 of 4
Download to read offline
.net technique javascript



 JavaScript create                                                                                                                                                l CD




a tabbed interface
                                                                                                                                                  Your essentia uire
                                                                                                                                                            ’ll req
                                                                                                                                                  All the files you
                                                                                                                                                                  al can be
                                                                                                                                                  for this tutori
                                                                                                                                                                   issue’s CD.
                                                                                                                                                  found on this




Part two In the last issue, Aaron Gustafson explained how to create a tabbed interface using
CSS and JavaScript. Now he focuses on making the JavaScript more flexible and accessible

Knowledge needed Basic JavaScript, (x)HTML, CSS                                        worked great for handling shorter headings, so we can keep that, but we also
Requires Text editor                                                                   need to be able to handle the new title-based tab labels, so we should tuck that
                                                                                       into a conditional statement. If the heading has a title we’ll use that, but if it
Project time 30-45 minutes
                                                                                       doesn’t, we’ll default to the old method of grabbing the heading content.

         In the last issue, I walked you through how to create a very                  heading = folder.getElementsByTagName( _tag )[0];
          simple tabbed interface from semantically marked-up content                  addClassName( heading, ‘hidden’ );
          (if you missed issue 194, there’s a PDF of part one on the CD).              tab = _els.li.cloneNode( true );
Now, we’ll revisit the JavaScript we wrote with a focus on making it more              tab.setAttribute( ‘id’, _id + ‘-’ + i + ‘-tab’ );
flexible and more accessible.                                                          tab.onclick = swap;
   As you recall, the script we wrote segments content based on the natural            tab.innerHTML = heading.innerHTML;
language breaks created by headings. And, in the case of our example recipe,           heading = folder.getElementsByTagName( _tag )[0];
the script functioned perfectly because the headings were short and sweet –            if ( heading.getAttribute( ‘title’ ) ){
‘Ingredients’, ‘Directions’, etc. But if this same script is applied to content with    tab.innerHTML = heading.getAttribute( ‘title’ );
lengthier headings, the results would not be pretty (as the screengrab below           } else {
shows). It would be simple for us to brush this off and require short titles from       tab.innerHTML = heading.innerHTML;
those who want to use the script, but that isn’t very accommodating. In order           addClassName( heading, ‘hidden’ );
to be truly useful, our script should offer a way for content authors to write         }
without sacrificing the clarity of their prose, while simultaneously ensuring
that the tabbed interface itself doesn’t become unusable.                                  Note: In the case of the alternate tab label, the redundancy of having a
   Looking at the problem from the perspective of a content author and a               matching tab label and heading is no longer a concern, so we won’t need to
semanticist, the solution is clear: we need to provide an alternate label for the      add a class of hidden to the real heading in that instance.
associated tab. That label is, in essence, advisory information about the section,         We now have a much more flexible version of TabInterface, but we haven’t
and HTML just so happens to include an attribute – title – that serves that            explored the accessibility of this widget beyond the use of positioning to hide
very function. Placing a title on the various heading levels grants authors full       content. Most devs would stop at this point, pat themselves on the back and
control over both the prose and the interface.                                         go out for a pint, assuming that most users of assistive technologies surf with
   With a clear plan to accommodate alternate content for the tabs, we can             JavaScript turned off and that those who don’t would be accommodated by the
adjust our script to take advantage of it. In our original script, we have code that   content-hiding method we employed. I’m not so easily satisfied. Are you?
                                                                                           When JavaScript-based interactivity began spreading across the web like
                                                                                       wildfire (thanks in no small part to the advent of Ajax), several people within
                                                                                       the accessibility community began to realise that JavaScript and accessibility
                                                                                       need not be mutually exclusive; in fact some, most notably Derek Featherstone,
                                                                                       began evangelising that JavaScript could even improve accessibility.
                                                                                           The key to making assistive technology and JavaScript get along was
                                                                                       finding a mechanism by which the markup could declare how it was being
                                                                                       used so that screen readers and other devices would be capable of letting the
                                                                                       user know what was happening and how to interact with various JavaScript-
                                                                                       driven widgets. At the W3C, this concept was realised in the Web Accessibility
                                                                                       Initiative’s Accessible Rich Internet Applications (WAI-ARIA) spec. And one of the
                                                                                       standard widget types addressed in the spec just so happens to be a tabbed
                                                                                       interface. (Fancy that.)

                                                                                       Role playing
                                                                                       To make TabInterface WAI-ARIA-savvy, we need to use what the spec refers to
                                                                                       as ‘roles’ and ‘states’. Both terms mean exactly what you’d assume: roles are the
                                                                                       parts elements are playing within the document and states indicate what each
                                                                                       one is doing. In terms of the tabbed interface, we’ll deal primarily with the
                                                                                       following roles (indicated using the role attribute):
                                                                                             application: identifies the page as being an application, which tells
Title inflation Nothing destroys our nice tabbed interface quite as quickly as long          assistive devices to allow JavaScript to manage keystroke events
headings, so we need to provide an alternate label for the associated tab                    tab: denotes that the element is acting as a tab within a tabbed interface



90     .net november 2009
.net technique javascript


                                                                                         In depth Shawn Henry
                                                                                         on how WAI-ARIA can help
                                                                                         make our sites accessible
                                                                                                            Shawn Henry
                                                                                                           Job title Web accessibility evangelist
                                                                                                           Sites www.uiaccess.com
                                                                                                           About Shawn Shawn leads worldwide education and
                                                                                                           outreach activities at the W3C Web Accessibility Initiative


                                                                                         Websites are increasingly using functionality that’s not available to
                                                                                         some users with disabilities, especially people who rely on screen
                                                                                         readers and people who can’t use a mouse. Tree controls for site
                                                                                         navigation, drag-and-drop and other complex user interface controls
                                                                                         can be difficult or impossible to use because of limitations in today’s
                                                                                         development technologies.
Information provider The title attribute is a simple way to provide advisory                A new technology to address this problem is on the horizon from the
information that can be used as the text for our tabs
                                                                                         W3C: WAI-ARIA for Accessible Rich Internet Applications. WAI-ARIA defines
                                                                                         a way to make websites and web applications more accessible to people
     tablist: denotes the element contains tabs that are part of a tabbed interface      with disabilities. It especially helps with dynamic content and advanced
     tabpanel: denotes the element is a panel of content within a tabbed interface       user interface controls developed with Ajax.
   These roles provide the assistive device with the various players in our                 A key aspect of WAI-ARIA is defining new ways for functionality to be
production, but don’t tell the whole story. Without some sort of indication, we          provided to screen readers and other assistive technologies. WAI-ARIA
have no idea which tab is associated with which tabpanel. Thankfully, WAI-ARIA           techniques apply to widgets such as buttons, drop-down lists, calendar
has that covered with two additional state-related attributes:                           functions, tree controls, and others.
     aria-labelledby: an id reference to the associated tab, placed on the tabpanel         Another aspect of WAI-ARIA is providing robust and consistent keyboard
     aria-describedby: an id reference to the associated tabpanel, placed on the tab     access. Some people cannot use a mouse and use only a keyboard. Even
                                                                                         relatively simple websites can be difficult if they require extensive

 To make TabInterface WAI-                                                               keystrokes to navigate. (Try using your website without a mouse.)
                                                                                            WAI-ARIA describes new navigation techniques to mark menus, primary
                                                                                         content, secondary content, banner information and other types of regions
 ARIA-savvy, we need to use                                                              and web structures. Developers can then identify regions of pages and
                                                                                         enable keyboard users to easily move among regions, rather than having
 ‘roles’ and ‘states’                                                                    to press tab repeatedly.
                                                                                            Web applications developed with Ajax, DHTML and other technologies
                                                                                         can also have accessibility barriers. For example, if the content of a web
To indicate the current state of the tabbed interface, we’ll also need these:            page changes in response to user actions or time- or event-based updates,
     aria-hidden: denotes whether or not the element is visible; takes a value           that new content may not be available to some people, such as people
     of true or false                                                                    who are blind or who have cognitive disabilities and rely on a screen
     aria-selected: denotes whether or not the element is currently activated;           reader. WAI-ARIA includes technologies to map controls, Ajax live regions
     takes a value of true or false                                                      and events to accessibility APIs, including custom controls.
     aria-activedescendant: placed on the containing element, this is an id                 For making advanced web applications accessible and usable to people
     reference to the currently active tabpanel                                          with disabilities, developers and users alike are singing the praises of WAI-
                                                                                         ARIA. Check out www.w3.org/WAI/intro/aria.
Set the properties
Setting these properties in the code is rather straightforward – just use
the setAttribute() on the corresponding elements.                                      folder.setAttribute( ‘id’, _id + ‘-’ + i );
    We’ll get things rolling by adding the basics near the beginning                   folder.setAttribute( ‘aria-labelledby’, _id + ‘-’ + i + ‘-tab’ );
of initialize():                                                                       ...
                                                                                       tab.setAttribute( ‘id’, _id + ‘-’ + i + ‘-tab’ );
if( !_cabinet.getAttribute( ‘id’ ) ) _cabinet.setAttribute( ‘id’, _id );               tab.setAttribute( ‘aria-describedby’, _id + ‘-’ + i );
// set the ARIA roles
_cabinet.setAttribute( ‘role’, ‘application’ );                                            Further on still, in the bit of code that establishes the first content chunk as
_index.setAttribute( ‘role’, ‘tablist’ );                                              the active one, we set the aria-hidden attribute to false (remember, it was true
_els.div.setAttribute( ‘role’, ‘tabpanel’ );                                           in the prototype element) and set the remaining states:
_els.div.setAttribute( ‘aria-hidden’, ‘true’ );
_els.li.setAttribute( ‘role’, ‘tab’ );                                                 addClassName( folder, ‘visible’ );
_els.li.setAttribute( ‘aria-selected’, ‘false’ );                                      folder.setAttribute( ‘aria-hidden’, ‘false’ );
                                                                                       tab.setAttribute( ‘aria-selected’, ‘true’ );
   This puts us in a good position from the get-go by applying the                     _active = folder.getAttribute( ‘id’ );
necessary attributes to the various players, including our prototyped                  _cabinet.setAttribute(‘aria-activedescendant’,_active);
elements (remember that cloneNode() clones the attributes as well as the
element when supplied an argument of true).                                            Last but not least, we need to update the swap method to handle changing
   Further down in the code, we’ll need to associate the tabs and tab panels           the requisite WAI-ARIA properties when closing one tab and opening
that are being generated:                                                              another. In the interests of time, I’ll leave that as an exercise for you



                                                                                                                                    .net november 2009        91     next>
.net technique javascript


        because, while we may be close, we’re not quite done yet. To truly make     _els.div.setAttribute( ‘aria-hidden’, ‘true’ );
        this widget accessible, we need to make it keyboard-aware.                  _els.div.setAttribute( ‘tabindex’, ‘-1’ );
                                                                                    _els.li.setAttribute( ‘role’, ‘tab’ );
Thinking beyond the mouse                                                           _els.li.setAttribute( ‘aria-selected’, ‘false’ );
Not everyone uses a mouse. People with disabilities are an obvious example,         _els.li.setAttribute( ‘tabindex’, ‘-1’ );
but power users often prefer the speed of a keyboard (hence the popularity of       ...
keystroke-based helper apps such as Enso and LaunchBar).                             if( i === 0 ){
    When it comes to keyboard events, WAI-ARIA recommends trying to mimic               ...
the desktop experience as much as possible. In our case, that means users               folder.removeAttribute( ‘aria-hidden’ );
need to be able to move into the tab list using the tab key. Once on a tab, they        folder.setAttribute( ‘tabindex’, ‘0’ );
should be able to hit the tab key again to move into the associated tab panel           tab.setAttribute( ‘aria-selected’, ‘true’ );
(in order to have the content read to them) or navigate between the tabs using          tab.setAttribute( ‘tabindex’, ‘0’ );
the arrow keys and other common commands (Home, End etc).
    Movement from content block to content block is handled using the                 As with the application of the WAI-ARIA states, we also need to modify
tabindex attribute: to remove an element from the tab order on a page, you          swap() to update the tabindex of the formerly and newly active elements.
can set its tabindex to -1; to establish its position within the source (and make   Again, I’ll leave that to you. With the tabindex bit taken care of, we can move
it focusable), you use a value of 0. This technique is often referred to as the
‘roaming tabindex’. In the case of our tabs and tab panels, we need to remove
their prototypes from the tab order by default and then reintroduce the active       To truly make this widget
ones when they’re activated:
                                                                                     accessible, we need to make
  In depth Glenda Sims                                                               it keyboard-aware
  invites you to a meeting of                                                       on to actually addressing the keyboard events. We’ll start by adding two new
  JavaScripters Anonymous                                                           event handlers to each tab:

                   Glenda Sims                                                      tab.onclick = swap;
                   Job title Senior systems analyst, University of Texas            tab.onkeydown = moveFocus;
                                                                                    tab.onfocus = swap;
                   Sites www.utexas.edu
                   About Glenda is an accessibility and web standards
                                                                                        The first event handler captures all keystrokes, passing them to moveFocus(),
                  evangelist for UT, webstandards.org and knowbility.org
                                                                                    a method we’ll define in a moment. The second new event handler triggers
                                                                                    swap() whenever a tab receives focus. As we’ve taken all but the first tab out
  Do you suffer from compulsive use of JavaScript? Symptoms include:                of the tab order, this won’t be invoked yet, but it’s there to capture events we’ll
         being frustrated by the limitations imposed by mobile browsers and         trigger shortly. Reading a user’s keystrokes is quite simple once you get past the
         assistive technology when exploring the edges of JavaScript                discrepancies between the standard W3C method of reading the keys and the
         using JavaScript “just for fun” (even when it isn’t necessary)             Internet Explorer method. Thankfully, the spanner IE throws into the works isn’t
         cursing while resuscitating JavaScript that ceased functioning after a     too large and it can be handled easily in a few lines of code:
         new browser release
         living by the motto “No JavaScript. No Service”                            function moveFocus( e )
         finding accessibility laws and guidelines overwhelming                     {
         decrying the inability of search engine spiders to handle JavaScript        e = ( e ) ? e : event;
  Is it possible for JavaScript to coexist peacefully with user environment          var
  demands and accessibility requirements? Yes! The answer is progressive
  enhancement. Web Standards Project co-founder Steve Champeon defines
  this as “a viable (web development) approach that enables the delivery of
  information as demanded by the users, while embracing accessibility,
  future compatibility, and determining user experience based on the
  capabilities of new devices” (bit.ly/RYIEv).
      Imagine your site is like fine coffee. The raw content is the coffee
  beans. Your semantically marked-up content is the brewed coffee. CSS is
  the sugar and JavaScript is the cream. Using progressive enhancement,
  you start developing with quality content (beans) then build functional
  semantic code (coffee) that works for everyone and on everything.
      Once your no-frills site works, you focus on presentation (sugar) and
  JavaScript (cream), which provide the rich user experience. No matter how
  good your creamy JavaScript and sweet CSS are, you must begin with
  quality coffee code.
      The core of this approach is the philosophy of ‘universal design’. As my
  colleague James Craig puts it, we should “design so thoughtfully it works
  for everyone from the start.” By making your site universally satisfying you’ll
  offer an experience that adapts to all customers’ taste. This gives you the
  freedom to add JavaScript while achieving delicious SEO, sweet accessibility,
  hot mobile performance, and robust compatibility with future technologies.        Access all areas The YUI (Yahoo User Interface Library) team is working on
                                                                                    implementing WAI-ARIA throughout its widget library




<prev     92     .net november 2009
.net technique javascript

 tab = e.target || e.srcElement,
 key = e.keyCode || e.charCode,
 pass = true;
 // keystroke handling goes here
 if ( ! pass )
 {
   return cancel( e );
 }
}

In this humble beginning to the moveFocus method, we’ve evened out the event
models, as we did in swap(), before identifying the key that was pressed and the
tab that currently has focus. We’ve also declared a variable, pass, that will define
whether we should trap the keystroke or pass it on to other event handlers.
By default we’ll pass the keystroke on to be handled however it should be, but
when we trap a keystroke we’ll call another new method, cancel, that stops the
event from bubbling (in a cross-browser-compatible way). You can check out
the code for cancel() on the CD. Before we get to the actual handling of the
keystrokes, let’s define another method to control the movement (since that’s
most of what will be happening with each keystroke anyway):                            Standards bearer Dojo (whose TabContainer is part of the Dijits widget library) was
                                                                                       one of the first JavaScript libraries to implement WAI-ARIA
function move( tab, direction, complete )
{                                                                                      on the keystroke and will be influenced by the direction argument). With that
 if ( complete )                                                                       method in place, we can return to moveFocus() and set it up to handle the
 {                                                                                     necessary keystrokes.
   if ( direction == ‘previous’ )                                                         We’ll handle them with a simple switch statement:
   {
     tab.parentNode.childNodes[0].focus();                                             switch ( key )
   }                                                                                   {
   else                                                                                 case 37:
   {                                                                                    case 38:
     tab.parentNode.childNodes[tab.parentNode.childNodes.length-1].focus();              move( tab, ‘previous’, false );
   }                                                                                     pass = false;
 }                                                                                       break;
 else                                                                                   case 27:
 {                                                                                       tab.blur();
   var target = direction == ‘previous’ ? tab.previousSibling                            pass = false;
                             : tab.nextSibling;                                          break;
   if ( target )                                                                       }
   {
     target.focus();                                                                   The above statement sets the actions for the left and up arrows (key codes 37
   }                                                                                   and 38, respectively) and Escape (27). Both arrows will trigger move() to focus
 }                                                                                     on the previous tab (if it exists) and trap the key press. Escape will remove focus
}                                                                                      from the current tab and will, likewise, trap the key press.
                                                                                          Following this model, you should be able to create additional cases for the
move() takes three arguments: the current tab (which we know), the direction           right and down arrows (39 and 40, respectively), Home (36) and End (35). Once
(which we’ll define, based on the keystroke), and whether or not the movement          complete, give the script a spin in your favourite browser and see how the
is intended to be made to the end of the tab list (which we’ll also define based       whole thing works when using only your keyboard.


 Resources Where to find out more                                                      Vigilance!
                                                                                       When programming in JavaScript (or any language for that matter), it’s
                                                                                       important to remember that each key you press affects a user’s experience.
                                                                                       Will you wield your power for good by engaging in progressive enhancement,
                                                                                       keeping your scripts flexible and paying attention to accessibility concerns?
                                                                                       I certainly hope so. But, if nothing else, perhaps this short series has opened
                                                                                       your eyes up to how easy it can be to do the right thing.
                                                                                           Note: TabInterface is available under the liberal MIT licence. The latest
                                                                                       version of the script can be downloaded from GitHub: easy-designs.github.
                                                                                       com/tabinterface.js l

   Developing Accessible Widgets           WAI-ARIA Best Practices                                          About the author
   Using ARIA                              w3.org/TR/wai-aria-practices/
                                                                                                            Name Aaron Gustafson
   video.yahoo.com/                        ‘The Roadmap for Accessible Rich
   watch/4073211/10996186                  Internet Applications’. The most                                 Site easy-designs.net
   Watch Todd Kloots give a fantastic      recent version of the W3C’s guide                                Areas of expertise Front/back-end development, strategy
   presentation on how to integrate        to working with ARIA can always                                  Clients Brighter Planet, Yahoo, Artbox.com
   WAI-ARIA into UI widgets.               be found at this URL.                                            Which cancelled TV show would you most like to see
                                                                                                            brought back? Pushing Daisies




                                                                                                                                            .net november 2009          93

More Related Content

Similar to Create A Tabbed Interface Part 2

A Content Repository for TYPO3 5.0
A Content Repository for TYPO3 5.0A Content Repository for TYPO3 5.0
A Content Repository for TYPO3 5.0Karsten Dambekalns
 
CSS Adaptive Layouts with Media Queries
CSS Adaptive Layouts with Media QueriesCSS Adaptive Layouts with Media Queries
CSS Adaptive Layouts with Media QueriesAaron Gustafson
 
Desingning reusable web components
Desingning reusable web componentsDesingning reusable web components
Desingning reusable web componentsjojule
 
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...Adam Khan
 
Your java script library
Your java script libraryYour java script library
Your java script libraryjasfog
 
Java Script - A New Look
Java Script - A New LookJava Script - A New Look
Java Script - A New Lookrumsan
 
An Introduction to WAI-ARIA
An Introduction to WAI-ARIAAn Introduction to WAI-ARIA
An Introduction to WAI-ARIAIWMW
 
How would you implement multiple inheritance in java
How would you implement multiple inheritance in javaHow would you implement multiple inheritance in java
How would you implement multiple inheritance in javaTyagi2636
 
Desingning reusable web components
Desingning reusable web componentsDesingning reusable web components
Desingning reusable web componentsJoonas Lehtinen
 
Principled io in_scala_2019_distribution
Principled io in_scala_2019_distributionPrincipled io in_scala_2019_distribution
Principled io in_scala_2019_distributionRaymond Tay
 
Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksThomas Fuchs
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptLotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptBill Buchan
 
High Performance on Drupal 7
High Performance on Drupal 7High Performance on Drupal 7
High Performance on Drupal 7Exove
 
Java Collections Framework
Java  Collections  FrameworkJava  Collections  Framework
Java Collections Frameworkguestd8c458
 

Similar to Create A Tabbed Interface Part 2 (20)

A Content Repository for TYPO3 5.0
A Content Repository for TYPO3 5.0A Content Repository for TYPO3 5.0
A Content Repository for TYPO3 5.0
 
CSS Adaptive Layouts with Media Queries
CSS Adaptive Layouts with Media QueriesCSS Adaptive Layouts with Media Queries
CSS Adaptive Layouts with Media Queries
 
Desingning reusable web components
Desingning reusable web componentsDesingning reusable web components
Desingning reusable web components
 
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...
Between a SPA and a JAMstack: Building Web Sites with Nuxt/Vue, Strapi and wh...
 
Javanotes
JavanotesJavanotes
Javanotes
 
Your java script library
Your java script libraryYour java script library
Your java script library
 
Java Script - A New Look
Java Script - A New LookJava Script - A New Look
Java Script - A New Look
 
An Introduction to WAI-ARIA
An Introduction to WAI-ARIAAn Introduction to WAI-ARIA
An Introduction to WAI-ARIA
 
How would you implement multiple inheritance in java
How would you implement multiple inheritance in javaHow would you implement multiple inheritance in java
How would you implement multiple inheritance in java
 
DSLs in JavaScript
DSLs in JavaScriptDSLs in JavaScript
DSLs in JavaScript
 
Desingning reusable web components
Desingning reusable web componentsDesingning reusable web components
Desingning reusable web components
 
Remix
RemixRemix
Remix
 
Principled io in_scala_2019_distribution
Principled io in_scala_2019_distributionPrincipled io in_scala_2019_distribution
Principled io in_scala_2019_distribution
 
Zepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-FrameworksZepto and the rise of the JavaScript Micro-Frameworks
Zepto and the rise of the JavaScript Micro-Frameworks
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptLotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
 
Fewd week4 slides
Fewd week4 slidesFewd week4 slides
Fewd week4 slides
 
High Performance on Drupal 7
High Performance on Drupal 7High Performance on Drupal 7
High Performance on Drupal 7
 
ART164_tut_dw
ART164_tut_dwART164_tut_dw
ART164_tut_dw
 
ART164_tut_dw
ART164_tut_dwART164_tut_dw
ART164_tut_dw
 
Java Collections Framework
Java  Collections  FrameworkJava  Collections  Framework
Java Collections Framework
 

More from Aaron Gustafson

Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Aaron Gustafson
 
Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Aaron Gustafson
 
Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Aaron Gustafson
 
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Aaron Gustafson
 
Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Aaron Gustafson
 
Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Aaron Gustafson
 
Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Aaron Gustafson
 
Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Aaron Gustafson
 
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Aaron Gustafson
 
PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]Aaron Gustafson
 
Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Aaron Gustafson
 
Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Aaron Gustafson
 
Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Aaron Gustafson
 
The Web Should Just Work for Everyone
The Web Should Just Work for EveryoneThe Web Should Just Work for Everyone
The Web Should Just Work for EveryoneAaron Gustafson
 
Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Aaron Gustafson
 
Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Aaron Gustafson
 
Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Aaron Gustafson
 
Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Aaron Gustafson
 
Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Aaron Gustafson
 
Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Aaron Gustafson
 

More from Aaron Gustafson (20)

Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]
 
Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]
 
Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]
 
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
 
Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?
 
Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]
 
Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]
 
Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]
 
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
 
PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]
 
Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]
 
Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]
 
Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]
 
The Web Should Just Work for Everyone
The Web Should Just Work for EveryoneThe Web Should Just Work for Everyone
The Web Should Just Work for Everyone
 
Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]
 
Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]
 
Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2
 
Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1
 
Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]
 
Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]
 

Recently uploaded

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 

Recently uploaded (20)

"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 

Create A Tabbed Interface Part 2

  • 1. .net technique javascript JavaScript create l CD a tabbed interface Your essentia uire ’ll req All the files you al can be for this tutori issue’s CD. found on this Part two In the last issue, Aaron Gustafson explained how to create a tabbed interface using CSS and JavaScript. Now he focuses on making the JavaScript more flexible and accessible Knowledge needed Basic JavaScript, (x)HTML, CSS worked great for handling shorter headings, so we can keep that, but we also Requires Text editor need to be able to handle the new title-based tab labels, so we should tuck that into a conditional statement. If the heading has a title we’ll use that, but if it Project time 30-45 minutes doesn’t, we’ll default to the old method of grabbing the heading content. In the last issue, I walked you through how to create a very heading = folder.getElementsByTagName( _tag )[0]; simple tabbed interface from semantically marked-up content addClassName( heading, ‘hidden’ ); (if you missed issue 194, there’s a PDF of part one on the CD). tab = _els.li.cloneNode( true ); Now, we’ll revisit the JavaScript we wrote with a focus on making it more tab.setAttribute( ‘id’, _id + ‘-’ + i + ‘-tab’ ); flexible and more accessible. tab.onclick = swap; As you recall, the script we wrote segments content based on the natural tab.innerHTML = heading.innerHTML; language breaks created by headings. And, in the case of our example recipe, heading = folder.getElementsByTagName( _tag )[0]; the script functioned perfectly because the headings were short and sweet – if ( heading.getAttribute( ‘title’ ) ){ ‘Ingredients’, ‘Directions’, etc. But if this same script is applied to content with tab.innerHTML = heading.getAttribute( ‘title’ ); lengthier headings, the results would not be pretty (as the screengrab below } else { shows). It would be simple for us to brush this off and require short titles from tab.innerHTML = heading.innerHTML; those who want to use the script, but that isn’t very accommodating. In order addClassName( heading, ‘hidden’ ); to be truly useful, our script should offer a way for content authors to write } without sacrificing the clarity of their prose, while simultaneously ensuring that the tabbed interface itself doesn’t become unusable. Note: In the case of the alternate tab label, the redundancy of having a Looking at the problem from the perspective of a content author and a matching tab label and heading is no longer a concern, so we won’t need to semanticist, the solution is clear: we need to provide an alternate label for the add a class of hidden to the real heading in that instance. associated tab. That label is, in essence, advisory information about the section, We now have a much more flexible version of TabInterface, but we haven’t and HTML just so happens to include an attribute – title – that serves that explored the accessibility of this widget beyond the use of positioning to hide very function. Placing a title on the various heading levels grants authors full content. Most devs would stop at this point, pat themselves on the back and control over both the prose and the interface. go out for a pint, assuming that most users of assistive technologies surf with With a clear plan to accommodate alternate content for the tabs, we can JavaScript turned off and that those who don’t would be accommodated by the adjust our script to take advantage of it. In our original script, we have code that content-hiding method we employed. I’m not so easily satisfied. Are you? When JavaScript-based interactivity began spreading across the web like wildfire (thanks in no small part to the advent of Ajax), several people within the accessibility community began to realise that JavaScript and accessibility need not be mutually exclusive; in fact some, most notably Derek Featherstone, began evangelising that JavaScript could even improve accessibility. The key to making assistive technology and JavaScript get along was finding a mechanism by which the markup could declare how it was being used so that screen readers and other devices would be capable of letting the user know what was happening and how to interact with various JavaScript- driven widgets. At the W3C, this concept was realised in the Web Accessibility Initiative’s Accessible Rich Internet Applications (WAI-ARIA) spec. And one of the standard widget types addressed in the spec just so happens to be a tabbed interface. (Fancy that.) Role playing To make TabInterface WAI-ARIA-savvy, we need to use what the spec refers to as ‘roles’ and ‘states’. Both terms mean exactly what you’d assume: roles are the parts elements are playing within the document and states indicate what each one is doing. In terms of the tabbed interface, we’ll deal primarily with the following roles (indicated using the role attribute): application: identifies the page as being an application, which tells Title inflation Nothing destroys our nice tabbed interface quite as quickly as long assistive devices to allow JavaScript to manage keystroke events headings, so we need to provide an alternate label for the associated tab tab: denotes that the element is acting as a tab within a tabbed interface 90 .net november 2009
  • 2. .net technique javascript In depth Shawn Henry on how WAI-ARIA can help make our sites accessible Shawn Henry Job title Web accessibility evangelist Sites www.uiaccess.com About Shawn Shawn leads worldwide education and outreach activities at the W3C Web Accessibility Initiative Websites are increasingly using functionality that’s not available to some users with disabilities, especially people who rely on screen readers and people who can’t use a mouse. Tree controls for site navigation, drag-and-drop and other complex user interface controls can be difficult or impossible to use because of limitations in today’s development technologies. Information provider The title attribute is a simple way to provide advisory A new technology to address this problem is on the horizon from the information that can be used as the text for our tabs W3C: WAI-ARIA for Accessible Rich Internet Applications. WAI-ARIA defines a way to make websites and web applications more accessible to people tablist: denotes the element contains tabs that are part of a tabbed interface with disabilities. It especially helps with dynamic content and advanced tabpanel: denotes the element is a panel of content within a tabbed interface user interface controls developed with Ajax. These roles provide the assistive device with the various players in our A key aspect of WAI-ARIA is defining new ways for functionality to be production, but don’t tell the whole story. Without some sort of indication, we provided to screen readers and other assistive technologies. WAI-ARIA have no idea which tab is associated with which tabpanel. Thankfully, WAI-ARIA techniques apply to widgets such as buttons, drop-down lists, calendar has that covered with two additional state-related attributes: functions, tree controls, and others. aria-labelledby: an id reference to the associated tab, placed on the tabpanel Another aspect of WAI-ARIA is providing robust and consistent keyboard aria-describedby: an id reference to the associated tabpanel, placed on the tab access. Some people cannot use a mouse and use only a keyboard. Even relatively simple websites can be difficult if they require extensive To make TabInterface WAI- keystrokes to navigate. (Try using your website without a mouse.) WAI-ARIA describes new navigation techniques to mark menus, primary content, secondary content, banner information and other types of regions ARIA-savvy, we need to use and web structures. Developers can then identify regions of pages and enable keyboard users to easily move among regions, rather than having ‘roles’ and ‘states’ to press tab repeatedly. Web applications developed with Ajax, DHTML and other technologies can also have accessibility barriers. For example, if the content of a web To indicate the current state of the tabbed interface, we’ll also need these: page changes in response to user actions or time- or event-based updates, aria-hidden: denotes whether or not the element is visible; takes a value that new content may not be available to some people, such as people of true or false who are blind or who have cognitive disabilities and rely on a screen aria-selected: denotes whether or not the element is currently activated; reader. WAI-ARIA includes technologies to map controls, Ajax live regions takes a value of true or false and events to accessibility APIs, including custom controls. aria-activedescendant: placed on the containing element, this is an id For making advanced web applications accessible and usable to people reference to the currently active tabpanel with disabilities, developers and users alike are singing the praises of WAI- ARIA. Check out www.w3.org/WAI/intro/aria. Set the properties Setting these properties in the code is rather straightforward – just use the setAttribute() on the corresponding elements. folder.setAttribute( ‘id’, _id + ‘-’ + i ); We’ll get things rolling by adding the basics near the beginning folder.setAttribute( ‘aria-labelledby’, _id + ‘-’ + i + ‘-tab’ ); of initialize(): ... tab.setAttribute( ‘id’, _id + ‘-’ + i + ‘-tab’ ); if( !_cabinet.getAttribute( ‘id’ ) ) _cabinet.setAttribute( ‘id’, _id ); tab.setAttribute( ‘aria-describedby’, _id + ‘-’ + i ); // set the ARIA roles _cabinet.setAttribute( ‘role’, ‘application’ ); Further on still, in the bit of code that establishes the first content chunk as _index.setAttribute( ‘role’, ‘tablist’ ); the active one, we set the aria-hidden attribute to false (remember, it was true _els.div.setAttribute( ‘role’, ‘tabpanel’ ); in the prototype element) and set the remaining states: _els.div.setAttribute( ‘aria-hidden’, ‘true’ ); _els.li.setAttribute( ‘role’, ‘tab’ ); addClassName( folder, ‘visible’ ); _els.li.setAttribute( ‘aria-selected’, ‘false’ ); folder.setAttribute( ‘aria-hidden’, ‘false’ ); tab.setAttribute( ‘aria-selected’, ‘true’ ); This puts us in a good position from the get-go by applying the _active = folder.getAttribute( ‘id’ ); necessary attributes to the various players, including our prototyped _cabinet.setAttribute(‘aria-activedescendant’,_active); elements (remember that cloneNode() clones the attributes as well as the element when supplied an argument of true). Last but not least, we need to update the swap method to handle changing Further down in the code, we’ll need to associate the tabs and tab panels the requisite WAI-ARIA properties when closing one tab and opening that are being generated: another. In the interests of time, I’ll leave that as an exercise for you .net november 2009 91 next>
  • 3. .net technique javascript because, while we may be close, we’re not quite done yet. To truly make _els.div.setAttribute( ‘aria-hidden’, ‘true’ ); this widget accessible, we need to make it keyboard-aware. _els.div.setAttribute( ‘tabindex’, ‘-1’ ); _els.li.setAttribute( ‘role’, ‘tab’ ); Thinking beyond the mouse _els.li.setAttribute( ‘aria-selected’, ‘false’ ); Not everyone uses a mouse. People with disabilities are an obvious example, _els.li.setAttribute( ‘tabindex’, ‘-1’ ); but power users often prefer the speed of a keyboard (hence the popularity of ... keystroke-based helper apps such as Enso and LaunchBar). if( i === 0 ){ When it comes to keyboard events, WAI-ARIA recommends trying to mimic ... the desktop experience as much as possible. In our case, that means users folder.removeAttribute( ‘aria-hidden’ ); need to be able to move into the tab list using the tab key. Once on a tab, they folder.setAttribute( ‘tabindex’, ‘0’ ); should be able to hit the tab key again to move into the associated tab panel tab.setAttribute( ‘aria-selected’, ‘true’ ); (in order to have the content read to them) or navigate between the tabs using tab.setAttribute( ‘tabindex’, ‘0’ ); the arrow keys and other common commands (Home, End etc). Movement from content block to content block is handled using the As with the application of the WAI-ARIA states, we also need to modify tabindex attribute: to remove an element from the tab order on a page, you swap() to update the tabindex of the formerly and newly active elements. can set its tabindex to -1; to establish its position within the source (and make Again, I’ll leave that to you. With the tabindex bit taken care of, we can move it focusable), you use a value of 0. This technique is often referred to as the ‘roaming tabindex’. In the case of our tabs and tab panels, we need to remove their prototypes from the tab order by default and then reintroduce the active To truly make this widget ones when they’re activated: accessible, we need to make In depth Glenda Sims it keyboard-aware invites you to a meeting of on to actually addressing the keyboard events. We’ll start by adding two new JavaScripters Anonymous event handlers to each tab: Glenda Sims tab.onclick = swap; Job title Senior systems analyst, University of Texas tab.onkeydown = moveFocus; tab.onfocus = swap; Sites www.utexas.edu About Glenda is an accessibility and web standards The first event handler captures all keystrokes, passing them to moveFocus(), evangelist for UT, webstandards.org and knowbility.org a method we’ll define in a moment. The second new event handler triggers swap() whenever a tab receives focus. As we’ve taken all but the first tab out Do you suffer from compulsive use of JavaScript? Symptoms include: of the tab order, this won’t be invoked yet, but it’s there to capture events we’ll being frustrated by the limitations imposed by mobile browsers and trigger shortly. Reading a user’s keystrokes is quite simple once you get past the assistive technology when exploring the edges of JavaScript discrepancies between the standard W3C method of reading the keys and the using JavaScript “just for fun” (even when it isn’t necessary) Internet Explorer method. Thankfully, the spanner IE throws into the works isn’t cursing while resuscitating JavaScript that ceased functioning after a too large and it can be handled easily in a few lines of code: new browser release living by the motto “No JavaScript. No Service” function moveFocus( e ) finding accessibility laws and guidelines overwhelming { decrying the inability of search engine spiders to handle JavaScript e = ( e ) ? e : event; Is it possible for JavaScript to coexist peacefully with user environment var demands and accessibility requirements? Yes! The answer is progressive enhancement. Web Standards Project co-founder Steve Champeon defines this as “a viable (web development) approach that enables the delivery of information as demanded by the users, while embracing accessibility, future compatibility, and determining user experience based on the capabilities of new devices” (bit.ly/RYIEv). Imagine your site is like fine coffee. The raw content is the coffee beans. Your semantically marked-up content is the brewed coffee. CSS is the sugar and JavaScript is the cream. Using progressive enhancement, you start developing with quality content (beans) then build functional semantic code (coffee) that works for everyone and on everything. Once your no-frills site works, you focus on presentation (sugar) and JavaScript (cream), which provide the rich user experience. No matter how good your creamy JavaScript and sweet CSS are, you must begin with quality coffee code. The core of this approach is the philosophy of ‘universal design’. As my colleague James Craig puts it, we should “design so thoughtfully it works for everyone from the start.” By making your site universally satisfying you’ll offer an experience that adapts to all customers’ taste. This gives you the freedom to add JavaScript while achieving delicious SEO, sweet accessibility, hot mobile performance, and robust compatibility with future technologies. Access all areas The YUI (Yahoo User Interface Library) team is working on implementing WAI-ARIA throughout its widget library <prev 92 .net november 2009
  • 4. .net technique javascript tab = e.target || e.srcElement, key = e.keyCode || e.charCode, pass = true; // keystroke handling goes here if ( ! pass ) { return cancel( e ); } } In this humble beginning to the moveFocus method, we’ve evened out the event models, as we did in swap(), before identifying the key that was pressed and the tab that currently has focus. We’ve also declared a variable, pass, that will define whether we should trap the keystroke or pass it on to other event handlers. By default we’ll pass the keystroke on to be handled however it should be, but when we trap a keystroke we’ll call another new method, cancel, that stops the event from bubbling (in a cross-browser-compatible way). You can check out the code for cancel() on the CD. Before we get to the actual handling of the keystrokes, let’s define another method to control the movement (since that’s most of what will be happening with each keystroke anyway): Standards bearer Dojo (whose TabContainer is part of the Dijits widget library) was one of the first JavaScript libraries to implement WAI-ARIA function move( tab, direction, complete ) { on the keystroke and will be influenced by the direction argument). With that if ( complete ) method in place, we can return to moveFocus() and set it up to handle the { necessary keystrokes. if ( direction == ‘previous’ ) We’ll handle them with a simple switch statement: { tab.parentNode.childNodes[0].focus(); switch ( key ) } { else case 37: { case 38: tab.parentNode.childNodes[tab.parentNode.childNodes.length-1].focus(); move( tab, ‘previous’, false ); } pass = false; } break; else case 27: { tab.blur(); var target = direction == ‘previous’ ? tab.previousSibling pass = false; : tab.nextSibling; break; if ( target ) } { target.focus(); The above statement sets the actions for the left and up arrows (key codes 37 } and 38, respectively) and Escape (27). Both arrows will trigger move() to focus } on the previous tab (if it exists) and trap the key press. Escape will remove focus } from the current tab and will, likewise, trap the key press. Following this model, you should be able to create additional cases for the move() takes three arguments: the current tab (which we know), the direction right and down arrows (39 and 40, respectively), Home (36) and End (35). Once (which we’ll define, based on the keystroke), and whether or not the movement complete, give the script a spin in your favourite browser and see how the is intended to be made to the end of the tab list (which we’ll also define based whole thing works when using only your keyboard. Resources Where to find out more Vigilance! When programming in JavaScript (or any language for that matter), it’s important to remember that each key you press affects a user’s experience. Will you wield your power for good by engaging in progressive enhancement, keeping your scripts flexible and paying attention to accessibility concerns? I certainly hope so. But, if nothing else, perhaps this short series has opened your eyes up to how easy it can be to do the right thing. Note: TabInterface is available under the liberal MIT licence. The latest version of the script can be downloaded from GitHub: easy-designs.github. com/tabinterface.js l Developing Accessible Widgets WAI-ARIA Best Practices About the author Using ARIA w3.org/TR/wai-aria-practices/ Name Aaron Gustafson video.yahoo.com/ ‘The Roadmap for Accessible Rich watch/4073211/10996186 Internet Applications’. The most Site easy-designs.net Watch Todd Kloots give a fantastic recent version of the W3C’s guide Areas of expertise Front/back-end development, strategy presentation on how to integrate to working with ARIA can always Clients Brighter Planet, Yahoo, Artbox.com WAI-ARIA into UI widgets. be found at this URL. Which cancelled TV show would you most like to see brought back? Pushing Daisies .net november 2009 93