<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.yuiblog.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Yahoo! User Interface Blog » Accessibility</title>
	
	<link>http://www.yuiblog.com/blog</link>
	<description>News and Articles about Designing and Developing with Yahoo! Libraries.</description>
	<lastBuildDate>Mon, 06 Jul 2009 22:28:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.yuiblog.com/yuiblog/accessibility" type="application/rss+xml" /><item>
		<title>More Accessible YUI Grids Layouts with ARIA Landmark Roles</title>
		<link>http://www.yuiblog.com/blog/2009/03/05/aria-grids/</link>
		<comments>http://www.yuiblog.com/blog/2009/03/05/aria-grids/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 00:09:43 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2009/03/05/aria-grids/</guid>
		<description><![CDATA[YUI Grids CSS has long been an important tool for developers wishing to create more accessible layouts. Through its support of source-order independent layouts, Grids enables control of the reading order of a page, allowing developers to place the most important content higher in the markup so that it can be quickly discovered by users [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.yahoo.com/yui/grids/">YUI Grids CSS</a> has long been an important tool for developers wishing to create more accessible layouts. Through its support of source-order independent layouts, Grids enables control of the reading order of a page, allowing developers to place the most important content higher in the markup so that it can be quickly discovered by users of screen readers.  However, while the role of each section of a Grid (e.g., navigation, main content, footer, etc.) is easily perceived through visual style and layout, it is not immediately perceived by users of screen readers because <code>&lt;div&gt;</code>s are inherently structural elements with no default semantic meaning.</p>
<h3 id="landmark-benefits">The Benefit of Landmark Roles</h3>
<p><a href="http://www.w3.org/TR/wai-aria/#roleattribute_inherits">ARIA Landmark Roles</a> improve the content parsability of Grids for users of screen readers.   By allowing developers to declare the intended purpose of each section of a layout, Landmark Roles provide semantic meaning to each section of a Grid, giving users of screen readers a high-level summary of how a page is organized.  In addition, Landmark Roles significantly improves a Grid&#8217;s navigability. For example, the <a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">JAWS screen reader</a> will announce all of the Landmarks when a page is loaded and allows users to quickly jump between them by pressing the semicolon key:</p>
<div><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="allowFullScreen" value="true" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=12214507&#038;vid=4561284&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7558/80857405.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" bgcolor="#000000" flashVars="id=12214507&#038;vid=4561284&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7558/80857405.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/4561284/12214507">Example Page Using YUI Grids And ARIA Landmark Roles</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></div>
<h3 id="using-landmarks">Using Landmark Roles</h3>
<p>Of all the roles defined in the <a href="http://www.w3.org/TR/wai-aria/">ARIA Specification</a>, the Landmark Roles are among the easiest to implement since they <em>don&#8217;t require JavaScript for keyboard support or state management</em>. Landmark Roles are applied to an element using the <code>role</code> attribute and can be used to improve the semantics of any section of a Grid. For example, to declare a section of a Grid as navigation, simply set the role attribute to a value of &#8220;navigation&#8221;:</p>
<pre><code>&lt;div class="yui-b" role="navigation"&gt;</code></pre>
<p>Presently the ARIA Specification defines seven different Landmark Roles:</p>
<ul>
<li><a href="http://www.w3.org/TR/wai-aria/#application"><code>application</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#banner"><code>banner</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#complementary"><code>complementary</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#contentinfo"><code>contentinfo</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#main"><code>main</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#navigation"><code>navigation</code></a></li>
<li><a href="http://www.w3.org/TR/wai-aria/#search"><code>search</code></a></li>
</ul>
<h3 id="landmark-getting-started">Getting Started Is Easy</h3>
<p>Since ARIA Landmark Roles are such a perfect complement to Grids, we&#8217;ve added built-in support to <a href="http://developer.yahoo.com/yui/grids/builder/">YUI Grids Builder</a>, added a <a href="http://developer.yahoo.com/yui/grids/#using-landmark-roles">new section on using Landmarks</a> to the Grids user guide, and created a <a href="http://developer.yahoo.com/yui/examples/grids/grids-landmarks.html">new example to highlight usage of Landmarks Roles</a> within YUI Grids CSS. Developers who are currently using Grids should definitely consider adding ARIA Landmark Roles to their markup to easily improve the accessibility of existing layouts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2009/03/05/aria-grids/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Improving Accessibility Through Focus Management</title>
		<link>http://www.yuiblog.com/blog/2009/02/23/managing-focus/</link>
		<comments>http://www.yuiblog.com/blog/2009/02/23/managing-focus/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 18:05:01 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2009/02/23/managing-focus/</guid>
		<description><![CDATA[A core requirement for developers using ARIA is to provide keyboard access for widgets, as users of screen readers rely on the keyboard to navigate web sites and applications. A large part of providing keyboard access is managing focus of a widget&#8217;s descendants (e.g., buttons in a toolbar, tabs in a tablist, menuitems in a [...]]]></description>
			<content:encoded><![CDATA[<p>A core requirement for developers using ARIA is to provide keyboard access for widgets, as users of screen readers rely on the keyboard to navigate web sites and applications. A large part of providing keyboard access is managing focus of a widget&#8217;s descendants (e.g., buttons in a toolbar, tabs in a tablist, menuitems in a menu, etc.), and the W3C guidelines provide two different approaches for doing so. This article explains both approaches and provides some practical advice for choosing between them.</p>
<h3>The Benefit of Focus Management</h3>
<p>As outlined in the <a href="http://www.w3.org/TR/wai-aria/" title="Accessible Rich Internet Applications (WAI-ARIA) Version 1.0">ARIA specification</a> and corresponding <a href="http://www.w3.org/TR/wai-aria-practices/">Best Practices</a> document, providing keyboard access requires, in part, that each widget has one tab stop by default and is responsible for discreetly managing focus for its descendants. Following these guidelines enables users to quickly navigate a page or application by using the tab key to move between widgets. Once a user has tabbed into a widget, they can then use other keys (the arrow keys for example) to move focus amongst the widget&#8217;s descendants.</p>
<h3>Two Approaches</h3>
<p>When it comes to managing focus, the WAI-ARIA Best Practices document provides two different techniques for developers: the <a href="http://www.w3.org/TR/wai-aria-practices/#focus_tabindex">Roaming TabIndex Technique</a> and use of the <a href="http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant"><code>activedescendant</code></a> property.</p>
<h3>Using the Roaming TabIndex Technique</h3>
<p>The Roaming TabIndex Technique requires each of a widget&#8217;s descendants be focusable, either through the use of natively focusable HTML elements, or by making an element focusable using the <a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex"><code>tabIndex</code></a> attribute. To use this technique, begin by setting the <code>tabIndex</code> attribute of a widget&#8217;s first descendant to a value that is equal to or greater than 0. (A value of 0 will result in the tab order of the widget being relative to its position in the page. Use a value greater than 0 to precisely control a widget&#8217;s tab order.) Next, set the <code>tabIndex</code> attribute of all remaining descendants to -1. (A value of -1 removes an element from the default tab flow, while preserving its ability to be focused via JavaScript.) This ensures that all of a widget&#8217;s descendants are focusable via JavaScript, but only one is in the default tab flow of its containing page or application, and therefore focusable by the user.</p>
<p>With these <code>tabIndex</code> values, use a  <code>keydown</code>  event handler to manage focus of the descendants once the widget is focused by the user. As the user presses the arrow keys, call the <code>focus</code> method to activate the appropriate descendant and update the <code>tabIndex</code> of the remaining descendants so that the currently focused element is the only one that is natively focusable.</p>
<p>The following menu button example illustrates how to use the Roaming TabIndex Technique to create a widget that is both keyboard and screen-reader accessible. To test this example yourself, you can use the free <a href="http://www.nvda-project.org/">NVDA Screen Reader</a> and <a href="http://www.mozilla.com/en-US/firefox/">Firefox 3</a>. Alternatively, you can watch the screen cast of the example running in Firefox 3 using the NVDA screen reader.</p>
<h4>Roaming TabIndex Example</h4>
<p><a href="http://yuiblog.com/sandbox/yui/v300pr2/examples/aria/example-1.html" target="_blank">Test Menu Roaming TabIndex Example</a></p>
<h4>Roaming TabIndex Example Screen Cast</h4>
<p><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=12030121&#038;vid=4487975&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7356/80165708.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" AllowScriptAccess="always" bgcolor="#000000" flashVars="id=12030121&#038;vid=4487975&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7356/80165708.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/4487975/12030121">Menu Button Using Roaming TabIndex Technique</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></p>
<h4>The Roaming TabIndex Technique Best Practices</h4>
<p>Having studied the WAI-ARIA Best Practices document, as well as having used the Roaming TabIndex Technique in several widget implementations, I have distilled several best practices for using this approach:</p>
<ul>
<li>I prefer using natively focusable elements instead of using the <code>tabIndex</code> attribute to make non-focusable HTML elements focusable, for better backward compatibility in browsers that don&#8217;t support the <code>tabIndex</code> attribute on all elements.</li>
<li>Use the  <code>keydown</code>  event when binding handlers used to manage focus since it is not possible to handle non-alphanumeric keys using the <code>keypress</code> event in IE.</li>
<li>In most cases it is necessary to prevent the browser&#8217;s default behavior when handling key events.</li>
<li>When setting the <code>tabIndex</code> attribute, avoid using the <code>setAttribute</code> method, to prevent case-sensitivity mistakes in IE. Setting the <code>tabIndex</code> attribute using the camel-case DOM property is both the most compact and most compatible syntax across browsers. For example: <code>myElement.tabIndex = -1;</code></li>
<li>When updating the <code>tabIndex</code> attribute of a widget&#8217;s descendants, set the attribute&#8217;s value to 0 before calling the <code>focus</code> method to ensure that the element&#8217;s default focus outline is rendered in IE.</li>
<li>When styling a descendant&#8217;s focused state, work with or augment the browser&#8217;s default rendering of focus rather than suppress it. The default rendering of focus is familiar to the user and, in many cases, consistent with the browser&#8217;s host OS. Working with the default focus model improves the learnability of the widget. If you suppress the browser&#8217;s default rendering of focus, be sure to provide a focus model that is consistent across your entire site or application so that the user only has to recognize and learn one focus model within a single context.</li>
<li>Set focus to HTML elements using both the <code>setTimeout</code> method and a <code>try/catch</code> block. Using <code>setTimeout</code> can help screen readers keep up while the focus is being changed. I have found this to be true when testing on <a href="http://www.apple.com/accessibility/voiceover/">VoiceOver</a> for the Mac. A <code>try/catch</code> block can help suppress unwanted XUL-related errors logged to the console when focusing elements in Firefox.</li>
</ul>
<h3>Using the <code>activedescendant</code> Property</h3>
<p>Unlike the Roaming TabIndex Technique, use of the <code>activedescendant</code> property doesn&#8217;t require any of a widget&#8217;s descendants to be focusable. Instead, this technique requires only that the widget&#8217;s root element be made focusable via the <code>tabIndex</code> attribute. (Note: this technique doesn&#8217;t work in the current version of Safari as it doesn&#8217;t support the <code>tabIndex</code> attribute on all HTML elements.) Using this approach, the <code>activedescendant</code> property is applied to the widget&#8217;s root element, and as the user presses the arrow keys, the value of the property is set to the id of the element that represents the user&#8217;s current selection. Since this approach doesn&#8217;t rely on focusing a widget&#8217;s descendants via the <code>focus</code> method, the browser will not provide any default rendering of the user&#8217;s current selection. Therefore, when using the <code>activedescendant</code> property the developer is responsible for rendering focus for the widget&#8217;s currently active descendant via CSS.</p>
<h4><code>activedescendant</code> Example</h4>
<p>The following example adapts the previous example to illustrate how to use the <code>activedescendant</code> property.</p>
<p><a href="http://yuiblog.com/sandbox/yui/v300pr2/examples/aria/example-2.html">Test <code>activedescendant</code> Example</a></p>
<h4><code>activedescendant</code> Example Screen Cast</h4>
<p><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=12052104&#038;vid=4497444&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7381/80255044.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" AllowScriptAccess="always" bgcolor="#000000" flashVars="id=12052104&#038;vid=4497444&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7381/80255044.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/4497444/12052104">Menu Button Using The &quot;activedescendant&quot; Property</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></p>
<p>As illustrated in the screen cast, the <code>activedescendant</code> property can provide a user experience that is identical to the Roaming TabIndex technique.</p>
<h4>Best Practices for Using the <code>activedescendant</code> Property</h4>
<ul>
<li>Depending on the browser and the attribute&#8217;s value, setting the <code>tabIndex</code> attribute on a widget&#8217;s root element can result in a focus outline being drawn around the widget. For widgets with descendants, having a focus outline surround an entire control is both unfamiliar to the user (not something you&#8217;ll see on the desktop), as well as ugly. So when using the <code>activedescendant</code> property, it is best to suppress the focus outline. This can be accomplished by setting the <a href="http://www.w3.org/TR/CSS21/ui.html#propdef-outline"><code>outline</code></a> CSS property in Firefox and IE 8, and using the <a href="http://msdn.microsoft.com/en-us/library/ms533783(VS.85).aspx"><code>hideFocus</code></a> attribute for IE 6 and 7. Unfortunately it is not possible to suppress the focus outline in the current version of Opera.</li>
<li>Use CSS to render focus for a widget&#8217;s descendants in a way that is consistent with, and/or builds on, the default browser focus, or is consistent within the scope of the site or application.</li>
</ul>
<h3>Choosing a Technique</h3>
<p>Having evaluated both the Roaming TabIndex Technique and the use of the <code>activedescendant</code> property, the Roaming TabIndex Technique is the better choice, because it is a solution that works &#8220;with the grain&#8221;. As such, it is more forward and backward compatible — especially when you are trying to support a <a href="http://developer.yahoo.com/yui/articles/gbs/index.html">wide array of browsers</a> like we are at Yahoo!. Using the <code>activedescendant</code> property requires more effort for less overall benefit and compatibility. Here are the downsides to using the <code>activedescendant</code> property:</p>
<ul>
<li>Requires browser support of the <code>tabIndex</code> attribute on all elements. Currently this not supported in Safari.</li>
<li>Suppressing the default focus outline drawn around a widget&#8217;s containing element is a slight pain in that it requires different techniques for different browsers. It turns into a bigger pain in Opera, where it is not only currently impossible but also exacerbated by Opera&#8217;s egregious focus model, illustrated in the following screen capture: <img id="opera-screen-capture" src="http://yuiblog.com/assets/managing-focus/focus-opera.png" width="157" height="120" alt="Screen capture of the focus menu from the second example running in Opera 9.6"></li>
<li>Loss of the default, familiar focus outline drawn around a widget&#8217;s descendants. The focus outline can be restored via CSS. However, developers get the focus outline for free when using the Roaming TabIndex Technique.</li>
<li>Since descendants aren&#8217;t focusable they cannot be clicked by pressing the enter key or space bar. This requires that developers listen explicitly for these key events and route the code responsible for handling the <code>click</code> event accordingly. When using the Roaming TabIndex technique, developers can simply listen for the <code>click</code> event.</li>
<li>Every descendant needs a unique id.</li>
</ul>
<p>Unlike the <code>activedescendant</code> property, the Roaming TabIndex Technique allows widgets to be both keyboard accessible and screen-reader accessible in browsers that don&#8217;t support ARIA and don&#8217;t support the <code>tabIndex</code> attribute on all elements.  For example, if a widget&#8217;s descendants are built using the set of natively focusable HTML elements, users of screen readers will still perceive them as actionable/clickable elements. Consider the following screen cast of our first example running in IE 7 (a browser without ARIA support) using JAWS 10.</p>
<p><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=12051469&#038;vid=4497181&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7381/80252536.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" AllowScriptAccess="always" bgcolor="#000000" flashVars="id=12051469&#038;vid=4497181&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/7381/80252536.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/4497181/12051469">Screen reader accessible Menu Button</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></p>
<p>In this example, while the user doesn&#8217;t perceive the button&#8217;s menu as a menu, the screen reader does announce each button in the menu as it is focused — letting the user know that each item is actionable/clickable. Additionally, since the button&#8217;s menu is built using the natively focusable <code>&lt;button&gt;</code> element, this widget will be keyboard accessible to all <a href="http://developer.yahoo.com/yui/articles/gbs/index.html">A-Grade browsers</a>, not just those that support the <code>tabIndex</code> attribute on all elements.</p>
<p>I suspect that the <code>activedescendant</code> property was developed as an alternative to the Roaming TabIndex Technique in part because the <code>focus</code> and <code>blur</code> events don&#8217;t bubble like other DOM events. This was a problem since developers need to listen for these events in order to customize how focus is drawn in a way that works cross browser, and attaching individual <code>focus</code> and <code>blur</code> event handlers to each of a widget&#8217;s focusable descendants has consequences for performance — especially for large composite widgets like trees and menus. That said, since <a href="http://yuiblog.com/blog/2008/10/07/onfocus-onblur/">we now have an easy way of listening for <code>focus</code> and <code>blur</code> in a performance-conscious way</a>, I feel like there are currently more downsides than upsides to using the <code>activedescendant</code> property.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2009/02/23/managing-focus/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WebAIM Survey Shines Light on Screen Reader Usage</title>
		<link>http://www.yuiblog.com/blog/2009/02/12/webaim-survey/</link>
		<comments>http://www.yuiblog.com/blog/2009/02/12/webaim-survey/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 01:35:53 +0000</pubDate>
		<dc:creator>Victor Tsaran</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2009/02/12/webaim-survey/</guid>
		<description><![CDATA[&#8220;What you hear is what you see&#8221;
For many developers, the screen reader is still a misunderstood assistive technology. Using a screen reader can be compared to looking at a web page through a straw because you need to explore (hear) many items in chunks and then piece them in your memory or imagination. The user [...]]]></description>
			<content:encoded><![CDATA[<h3>&#8220;What you hear is what you see&#8221;</h3>
<p>For many developers, the screen reader is still a misunderstood assistive technology. Using a screen reader can be compared to looking at a web page through a straw because you need to explore (hear) many items in chunks and then piece them in your memory or imagination. The user knows that an item is present on the screen only after they&#8217;ve heard their screen reader announce it. A different approach needs to be applied in order to successfully code for this type of technology. We shouldn&#8217;t stop at using visual cues to attract user attention, but visual attributes alone cannot be relied on when communicating important information to the user. The recent <a title="WebAIM screen reader survey" href="http://webaim.org/projects/screenreadersurvey/">WebAIM screen reader survey</a> of 1121 screen reader users is a great step towards understanding how blind, deaf-blind, or visually impaired users *actually* interact with the web.<br />
<h3>Use Headings (&lt;Hn&gt; tags)</h3>
<p>The survey results are pretty clear on this one: <a title="WebAIM survey results for headings usage" href="http://webaim.org/projects/screenreadersurvey/#headings">90% of respondents</a> use headings to navigate web pages &#8220;sometimes&#8221;, &#8220;often&#8221;, or &#8220;whenever they&#8217;re available&#8221;. WebAIM says, &#8220;It is clear that providing a heading structure is important to screen reader users&#8230;.&#8221; Most screen readers provide one or more mechanisms for a user to jump between HTML headings on the page, either through a set of shortcut keys or through a custom list of headings. Because reading with a screen reader happens in a linear fashion, headings provide a way to jump between sections of a web page in a quick and efficient way. This not only enables the user to skip over repetitive navigation menus and unwanted content, but also helps them to learn about the structure and the order of the content on the page. Proper usage of HTML headings is semantic, easy, and most of all indispensible to screen reader users.</p>
<h3>Access Keys</h3>
<p>The access key is an HTML attribute that enables any focusable element on the page to become reachable via a shortcut key. Of survey respondents, <a title="WebAIM survey results for access keys usage" href="http://webaim.org/projects/screenreadersurvey/#accesskeys">88% use access keys</a> &#8220;sometimes&#8221;, &#8220;often&#8221;, or &#8220;whenever they&#8217;re available&#8221;. I&#8217;ve always assumed that access keys are of more use to advanced users, but the survey results actually suggest that beginners will tend to use access keys more often than their advanced counterparts.</p>
<p>Here are a couple of points to keep in mind when implementing access keys:</p>
<ul>
<li>Shortcut keys are not implemented across all browsers consistently: Internet Explorer uses the ALT key as a modifier, Firefox uses ALT+SHIFT, and Safari uses CONTROL.</li>
<li>Access keys may potentially conflict with the particular browser&#8217;s built-in shortcut keys: &#8220;F&#8221; for &#8220;File&#8221; menu, &#8220;E&#8221; for &#8220;Edit&#8221; menu, etc.</li>
<li>Access keys have to be appropriate to the user&#8217;s locale in order to make them intuitive. For example, the first letter for the English word &#8220;Search&#8221; would be different than for the same word in French. And what about languages that use the Cyrilic alphabet?</li>
<li>Using numbers instead of letters for access keys makes them less intuitive because number-based shortcut keys are harder to associate with particular words.</li>
</ul>
<p>This is not to suggest that access keys should not be used at all, rather that they should be used sparingly and thoughtfully. Screen reader applications provide a lot of ways for users to reach various HTML elements on the page, so these types of users may not end up using your access keys if they are too difficult to remember. If you do implement access keys, please take care to account for the different languages of your audience as well as check for possible conflicts with browser built-in keystrokes.</p>
<h3>&#8220;Skip&#8221; links</h3>
<p><a title="WebAIM survey results for skip links usage" href="http://webaim.org/projects/screenreadersurvey/#skipnav">66% of survey respondents</a> say they use &#8220;skip to content&#8221; or &#8220;skip navigation&#8221; links &#8220;sometimes&#8221;, &#8220;often&#8221;, or &#8220;whenever they&#8217;re available&#8221;. These are internal anchor links that point to different content areas. Many screen reader applications provide a native &#8220;skip to text&#8221; feature which attempts to skip navigational links and place focus on the first text string on the page. You can not always rely on this feature because the first text on the page is not necessarily relevant content. Therefore, HTML-based &#8220;skip&#8221; links, that are embedded directly in the page, provide an extremely valuable convenience that links to the place where actual main content or content of interest begins. When deciding to implement &#8220;skip&#8221; links, keep the following points in mind:</p>
<ul>
<li>Implement &#8220;skip&#8221; links because they are quite useful for keyboard users to save excessive tabbing through repetitive menus by providing a way to quickly jump to another part of the page, e.g., the beginning of the main content.</li>
<li>Do not be ashamed of &#8220;skip&#8221; links and do not hide them off-screen. They are useful for people with motor disabilities or repetitive strain injuries, and for keyboard users in general, enabling anyone to quickly skip to the main content using their keyboard.</li>
<li>Name &#8220;skip&#8221; links to clearly indicate where you are sending users when the link is activated. Good examples are &#8220;Skip to main content&#8221; or &#8220;Skip to navigation menus&#8221;.</li>
<li>Please remember to localize &#8220;skip&#8221; links as well; they are now a part of your content.</li>
<li>Last but not least, ensure that the &#8220;skip&#8221; links actually work. (Yes, I have seen a lot of sites where they don&#8217;t.) Tab to the &#8220;skip&#8221; link and activate it, making sure that the focus moves to the intended place on the page.</li>
</ul>
<h3>Know Your Audience</h3>
<p>One of the conclusions of the recently conducted <a href="http://webaim.org/projects/screenreadersurvey/">WebAIM screen reader survey</a> is the fact that there is no one way that screen reader users interact with the web. Too often, developers, product managers, and designers tend to assume the preferences, likes, and dislikes of screen reader users without ever asking them directly for their input.</p>
<p>Screen reader applications are used by blind, deaf-blind, or visually impaired users, as well as developers who test the accessibility of their web sites, teachers who instruct their students with visual impairments, and individuals who want to simply listen to the content on the screen. They are novice and advanced users of the software, who have made many configurations or left the default preferences alone. What they have in common is that they will use known techniques to navigate web pages such as:</p>
<ul>
<li>using headings to move between different parts of the page</li>
<li>reading the whole content of the page before interacting with it</li>
<li>navigating between focusable elements (links, form fields, etc.) on the page with a TAB and SHIFT+TAB key</li>
<li>using the &#8220;find&#8221; feature of the browser or a screen reader to search for particular keywords on the page</li>
</ul>
<p>It is vitally important to know your audience and how they interact with the web in order to write more usable code. Adopting these best practices will go a long way towards making your web pages more accessible for everyone.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2009/02/12/webaim-survey/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Configuring Your Machine For Testing With A Screen Reader</title>
		<link>http://www.yuiblog.com/blog/2008/12/30/configuring-screen-readers/</link>
		<comments>http://www.yuiblog.com/blog/2008/12/30/configuring-screen-readers/#comments</comments>
		<pubDate>Wed, 31 Dec 2008 00:32:25 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/12/30/configuring-screen-readers/</guid>
		<description><![CDATA[ 		When developing using the 		WAI-ARIA Roles and States, 		you need to test your code in a screen reader to ensure everything is 		working as you expect. As a follow up to my presentation on 		Developing Accessible Widgets with ARIA 		and in the interest of helping other developers test 		their code, I thought I would [...]]]></description>
			<content:encoded><![CDATA[<p> 		When developing using the 		<a href="http://www.w3.org/TR/wai-aria/">WAI-ARIA Roles and States</a>, 		you need to test your code in a screen reader to ensure everything is 		working as you expect. As a follow up to my presentation on 		<a href="http://yuiblog.com/blog/2008/12/08/video-kloots-aria/">Developing Accessible Widgets with ARIA</a> 		and in the interest of helping other developers test 		their code, I thought I would provide some tips on how to 		configure your development environment for screen reader testing. 		</p>
<h3>Step 1: Install A Virtual Machine</h3>
<p> 		Before I install and configure screen readers I start by installing 		a virtual machine. (This is mostly out of necessity because I use a Mac 		and the most-popular screen readers run on Windows.) 		Using a virtual machine provides a couple of benefits when testing 		with a screen reader: To start, a virtual machine provides a sandboxed 		environment, so I am protected if anything goes awry when I am 		installing and configuring each screen reader. (So as not to give the 		impression that screen readers are unstable pieces of software, this 		is definitely the exception more than the rule.) 		</p>
<p> 		The second benefit to using a virtual machine is that they allow you to 		save and restore state. This is an especially helpful feature for 		efficiently testing and re-testing specific pieces or states of complex 		web applications. So, using a virtual machine 		can help save you time when testing. 		</p>
<p> 		Which virtual machine to use? If you use Windows, you can download 		and install 		<a href="http://www.microsoft.com/windows/downloads/virtualpc/default.mspx">Microsoft Virtual PC</a> 		for free. As a Mac user, I have found both 		<a href="http://www.vmware.com/products/fusion/">VMware Fusion</a> and 		<a href="http://www.parallels.com/products/desktop/">Parallels Desktop</a> 		work well. 		</p>
<h3>Step 2: Install Browsers</h3>
<p> 		It is important to remember that to work, ARIA requires a team effort 		between the browser and the screen reader. To test ARIA you&#8217;ll need to 		install browsers that both support ARIA <em>and are supported by screen 		readers that also support ARIA</em>. For example, 		<a href="http://www.opera.com/">Opera</a> has support for ARIA, but is 		not supported by screen readers. Currently only 		<a href="http://www.microsoft.com/windows/internet-explorer/beta/default.aspx">Internet Explorer 8</a> 		and <a href="http://www.mozilla.com/">Firefox 3</a> have support for 		ARIA, and are supported by several screen readers for Windows that also 		offer support for ARIA. 		</p>
<p> 		After installing each browser, be sure to save the state of the 		virtual machine. That way you&#8217;ll be able to quickly revert back to 		a clean, working state should anything go wrong during the screen 		reader installation. 		</p>
<h3>Step 3: Install &#38; Configure Screen Readers</h3>
<p> 		With the browsers installed the next step is to install and configure 		each screen reader. The two most-popular screen readers for Windows, 		<a href="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">JAWS</a> 		and <a href="http://www.gwmicro.com/Window-Eyes/">Window-Eyes</a> 		support ARIA and work with both Internet Explorer 8 and Firefox 3. 		Free, trial versions of both products are available for download from 		Freedom Scientific&#8217;s and GW Micro&#8217;s websites. 		The open-source screen reader 		<a href="http://www.nvda-project.org/">NVDA</a> also has excellent 		ARIA support and currently works with Firefox 3. Knowing that most 		visually impaired users use more than one screen reader, I recommend 		installing all three for testing. 		</p>
<p> 		As a sighted person I disable a couple of features of each screen 		reader and change some configurations so that I can test more 		efficiently. For example, most screen readers are configured to startup 		automatically when you start your computer. This is obviously not 		desirable when you have multiple screen readers installed, so I turn 		off that feature. Additionally, every screen reader uses a different 		keyboard shortcut for toggling the virtual buffer on and off. To avoid 		having to remember the keyboard shortcut for each screen reader, I 		configure them all to be the same: Ctrl + Shift + Space. (For more 		on the virtual buffer, read 		<a href="http://juicystudio.com/article/making-ajax-work-with-screen-readers.php">Making Ajax Work with Screen Readers</a>.) 		</p>
<p> 		The following sections provide step-by-step instructions for configuring 		JAWS, Window-Eyes and NVDA. 		</p>
<h4>Configuring JAWS</h4>
<h5>Changing The Virtual Buffer Toggle Keyboard Shortcut</h5>
<ol>
<li> 				Open the &#8220;Keyboard Manager&#8221; dialog by selecting &#8220;Utilities&#8221; 				&#45;&#62; &#8220;Keyboard Manager&#8221; in the JAWS application menubar. 				<img src="http://yuiblog.com/assets/aria-env/jaws-1.png" width="399" height="241" alt="Screen shot of the JAWS menubar."> 			</li>
<li>Select the &#8220;default&#8221; profile in the left, &#8220;Profile&#8221; pane.</li>
<li> 				In the right pane, sort by the &#8220;Script Name&#8221; column, then find 				and select the item named &#8220;VirtualPCCursorToggle&#8221;. 			</li>
<li> 				Open the &#8220;Change Keystroke&#8221; dialog by either right clicking on 				the &#8220;VirtualPCCursorToggle&#8221; item, or by pressing Ctrl + H. 				<img src="http://yuiblog.com/assets/aria-env/jaws-2.png" width="452" height="305" alt="Screen shot of the Keyboard Manager dialog in JAWS ."> 			</li>
<li> 				In the &#8220;Change Keystroke&#8221; dialog, choose the new keystroke by 				pressing the desired keys. (I use Ctrl + Shift + Space.) JAWS 				will warn you if the keystroke you choose in already in use. 				<img src="http://yuiblog.com/assets/aria-env/jaws-3.png" width="450" height="279" alt="Screen shot of the Change Keystroke dialog in JAWS."> 			</li>
<li>Press the &#8220;OK&#8221; button to close the dialog.</li>
</ol>
<h5>Disabling JAWS From Starting Automatically</h5>
<ol>
<li> 				Open the &#8220;Basic Settings&#8221; dialog by selecting &#8220;Options&#8221; 				&#45;&#62; &#8220;Basics&#8221; in the JAWS application menubar. 				<img src="http://yuiblog.com/assets/aria-env/jaws-4.png" width="399" height="240" alt="Screen shot of the JAWS menubar."> 			</li>
<li> 				In the &#8220;Basic Settings&#8221; dialog, make sure the checkbox labeled 				&#8220;Automatically start JAWS&#8221; in not checked. 				<img src="http://yuiblog.com/assets/aria-env/jaws-5.png" width="513" height="367" alt="Screen shot of the Basic Settings dialog in JAWS."> 			</li>
</ol>
<h4>Configuring Window-Eyes</h4>
<h5>Changing The Virtual Buffer Toggle Keyboard Shortcut</h5>
<ol>
<li> 				Open the &#8220;Browse Mode Hot Key Definitions&#8221; dialog by selecting 				&#8220;Hotkeys&#8221; &#45;&#62; &#8220;Browse Mode&#8230;&#8221; in the Window-Eyes 				application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-1.png" width="310" height="163" alt="Screen shot of the Window-Eyes menubar."> 			</li>
<li> 				In the &#8220;Browse Mode Hot Key Definitions&#8221; dialog, scroll down to 				the item named &#8220;Browse Mode&#8221; in the scrollable &#8220;Keys&#8221; list. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-2.png" width="443" height="398" alt="Screen shot of the Browse Mode Hot Key Definitions dialog in Window-Eyes."> 			</li>
<li> 				Select the &#8220;Browse Mode&#8221; item and then press the 				&#8220;Capture Key&#8221; button. 			</li>
<li> 				Press the keyboard combination you want to use. 				(I use Ctrl + Shift + Space.) 			</li>
<li>Press the &#8220;OK&#8221; button to close the dialog.</li>
<li> 				Save the configuration by selecting &#8220;File&#8221; &#45;&#62; &#8220;Save&#8221; 				&#45;&#62; &#8220;Set File and All Dictionaries&#8221; in the Window-Eyes 				application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-8.png" width="342" height="178" alt="Screen shot of the Window-Eyes menubar."> 			</li>
</ol>
<h5>Disabling The Mouse Voice</h5>
<p> 		By default Window-Eyes will speak in response to some mouse gestures. 		For example, when you press the left mouse button, Window-Eyes will 		say &#8220;left&#8221;. As a sighted person I find this feature unnecessary, so I 		disable this feature. 		</p>
<ol>
<li> 				Open the &#8220;Mouse Voice&#8221; dialog by selecting &#8220;Mouse&#8221; &#45;&#62; 				&#8220;Voice&#8221; in the Window-Eyes application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-4.png" width="355" height="162" alt="Screen shot of the Window-Eyes menubar."> 			</li>
<li> 				Select the &#8220;Off&#8221; item. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-5.png" width="417" height="261" alt="Screen shot of Mouse Voice dialog in Window-Eyes."> 			</li>
<li>Press the &#8220;OK&#8221; button to close the dialog.</li>
<li> 				Save the configuration by selecting &#8220;File&#8221; &#45;&#62; &#8220;Save&#8221; 				&#45;&#62; &#8220;Set File and All Dictionaries&#8221; in the Window-Eyes 				application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-8.png" width="342" height="178" alt="Screen shot of the Window-Eyes menubar."> 			</li>
</ol>
<h5>Disabling Window-Eyes From Starting Automatically</h5>
<ol>
<li> 				Open the &#8220;Startup Options&#8221; dialog by selecting &#8220;File&#8221; &#45;&#62; 				&#8220;Starup Options&#8230;&#8221; in the Window-Eyes application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-6.png" width="265" height="190" alt="Screen shot of the Window-Eyes menubar."> 			</li>
<li> 				In the &#8220;Startup Options&#8221; dialog:
<ul>
<li> 						Uncheck the checkbox labeled &#8220;Run Window-Eyes at the 						Login Screen&#8221;. 					</li>
<li> 						Uncheck the checkbox labeled &#8220;Run Window-Eyes after 						login for all users&#8221;. 					</li>
<li> 						Select the radio button labeled &#8220;Never&#8221; under &#8220;After 						login for Current User, Run Window-Eyes&#8221;. 					</li>
</ul>
<p> 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-7.png" width="287" height="260" alt="Screen shot of the Startup Options dialog in Window-Eyes."> 			</li>
<li>Press the &#8220;OK&#8221; button to close the dialog.</li>
<li> 				Save the configuration by selecting &#8220;File&#8221; &#45;&#62; &#8220;Save&#8221; 				&#45;&#62; &#8220;Set File and All Dictionaries&#8221; in the Window-Eyes 				application menubar. 				<img src="http://yuiblog.com/assets/aria-env/window-eyes-8.png" width="342" height="178" alt="Screen shot of the Window-Eyes menubar."> 			</li>
</ol>
<h4>Configuring NVDA</h4>
<h5>General Settings For Efficiency</h5>
<ol>
<li> 				Uncheck the checkbox labeled &#8220;Show this dialog when NVDA starts&#8221; 				that pops up the first time NVDA starts 				<img src="http://yuiblog.com/assets/aria-env/nvda-1.png" width="541" height="271" alt="Screen shot of the NVDA welcome dialog"> 			</li>
<li> 				Disable the confirmation dialog that pops up when you exit 				the application:
<ol>
<li> 						Open the &#8220;General settings&#8221; dialog by right clicking on 						the NVDA system tray icon and selecting to &#8220;Preferences&#8221; 						 &#45;&#62; &#8220;General settings&#8221; in the context menu. 						<img src="http://yuiblog.com/assets/aria-env/nvda-5.png" width="393" height="303" alt="Screen shot of the NVDA system tray context menu."> 					</li>
<li> 						In the &#8220;General settings&#8221; dialog, uncheck the checkbox 						labeled &#8220;Warn before exiting NVDA&#8221;. 						<img src="http://yuiblog.com/assets/aria-env/nvda-6.png" width="458" height="203" alt="Screen shot of the General settings dialog in NVDA."> 					</li>
<li> 						Right click on the NVDA icon in the system tray and select 						the &#8220;Save configuration&#8221; menu item in the context menu. 						<img src="http://yuiblog.com/assets/aria-env/nvda-7.png" width="233" height="162" alt="Screen shot of the NVDA system tray context menu."> 					</li>
</ol>
</li>
</ol>
<h5>Disabling the Mouse Voice</h5>
<p> 		Like Window-Eyes, by default NVDA will speak in response to some mouse 		gestures. For example, when you move the mouse NVDA will play tones 		to help the user track the position of the mouse. As a sighted person I 		find this feature unnecessary, so I disable this feature. 		</p>
<ol>
<li> 				Open the &#8220;Mouse settings&#8221; dialog by right clicking on the NVDA 				icon in the system tray and selecting &#8220;Preferences&#8221; &#45;&#62; 				&#8220;Mouse settings&#8221; from the context menu. 				<img src="http://yuiblog.com/assets/aria-env/nvda-2.png" width="395" height="306" alt="Screen shot of the NVDA system tray context menu."> 			</li>
<li> 				In the &#8220;Mouse settings&#8221; dialog, uncheck both &#8220;Report text under 				the mouse&#8221; and &#8220;play audio coordinates when the mouse moves&#8221;. 				<img src="http://yuiblog.com/assets/aria-env/nvda-3.png" width="281" height="210" alt="Screen shot of the Mouse settings dialog in NVDA."> 			</li>
<li> 				Right click on the NVDA icon in the system tray and select 				the &#8220;Save configuration&#8221; menu item in the context menu. 				<img src="http://yuiblog.com/assets/aria-env/nvda-7.png" width="233" height="162" alt="Screen shot of the NVDA system tray context menu."> 			</li>
</ol>
<h5>Changing The Virtual Buffer Toggle Keyboard Shortcut</h5>
<ol>
<li> 				Shut down NVDA &#8211; right click on the system track icon and choose 				&#8220;Exit&#8221; from the context menu. 			</li>
<li> 				Navigate to the path &#8220;C:\Program Files\NVDA\appModules&#8221;. 				<img src="http://yuiblog.com/assets/aria-env/nvda-4.png" width="355" height="443" alt="Screen capture of the contents of the appModules directory."> 			</li>
<li>Open the file named &#8220;_default_desktop.kbd&#8221;.</li>
<li>Find the line: &#8220;NVDA+space=toggleVirtualBufferPassThrough&#8221;.</li>
<li> 				Change to: &#8220;Control+Shift+space=toggleVirtualBufferPassThrough&#8221;. 			</li>
<li>Save the file.</li>
<li>Restart NVDA.</li>
</ol>
<h3>Step 4: Restart Windows &#38; Save State</h3>
<p> 		With all of the screen readers installed and configured, restart 		Windows. Once Windows is restarted, take another snapshot of the 		virtual machine&#8217;s state. If you are using the free, trial versions of 		JAWS and Window-Eyes they will require you to restart Windows after 		using either product for ~30 minutes. Using the virtual machine, you 		can revert back to using JAWS and Window-Eyes more quickly than you 		would if you had to restart Windows. 		</p>
<h3>Steps Summary</h3>
<p> 		That&#8217;s it. The steps for configuring your development environment for 		testing using a screen reader can be summarized as follows: 		</p>
<ol>
<li>Install virtualization software</li>
<li>Install browsers &#38; take a snapshot of that state</li>
<li>Install and configure screen readers</li>
<li>Restart the virtual machine &#38; take a snapshot of that state</li>
</ol>
<h3>Resources &#38; Further Reader</h3>
<ul>
<li><a href="http://yuiblog.com/blog/2008/12/08/video-kloots-aria/">Developing Accessible Widgets with ARIA</a></li>
<li><a href="http://video.yahoo.com/video/play?vid=514676">An Introduction to Screen Readers</a></li>
<li><a href="http://www.w3.org/TR/aria-role/">Roles for Accessible Rich Internet Applications (WAI-ARIA Roles) Version 1.0</a></li>
<li><a href="http://www.w3.org/TR/aria-state/">States and Properties Module for Accessible Rich Internet Applications (WAI-ARIA States and Properties) Version 1.0</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/12/30/configuring-screen-readers/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Introducing onFocus and onBlur</title>
		<link>http://www.yuiblog.com/blog/2008/10/07/onfocus-onblur/</link>
		<comments>http://www.yuiblog.com/blog/2008/10/07/onfocus-onblur/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 18:58:45 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/10/07/onfocus-onblur/</guid>
		<description><![CDATA[ Back in April, PPK authored a blog entry titled  Delegating the focus  and blur events in which he proposed a solution to the problem that neither the focus or blur  events bubble in any browser.  His solution (registering capture-phase event listeners for focus  and blur) is a blessing to [...]]]></description>
			<content:encoded><![CDATA[<p> Back in April, PPK authored a blog entry titled  <a href="http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html">Delegating the focus  and blur events</a> in which he proposed a solution to the problem that neither the focus or blur  events bubble in any browser.  His solution (registering capture-phase event listeners for focus  and blur) is a blessing to any developer wishing to avoid the code bloat and performance bottleneck  that can result from binding discrete focus and blur event handlers for focusable elements.  </p>
<p> We liked PPK&#8217;s solution and decided to answer his call and be, in his words, &#8220;&#8230;one of those  frightfully clever JavaScript librar[ies to] use this technique&#8230;&#8221;.  So for version 2.6 we&#8217;ve  rolled PPK&#8217;s solution into two methods of the Event Utility:  <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#method_addFocusListener"><code>addFocusListener</code></a>  and  <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#method_addBlurListener"><code>addBlurListener</code></a>  (or <code>onFocus</code> and <code>onBlur</code> for short).  These two new methods  encapsulate the nitty gritty of supporting this technique in all our  <a href="http://developer.yahoo.com/yui/articles/gbs/">A-Grade browsers</a>, while  delivering the sugar you&#8217;ve come to expect from the   <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#method_addListener"><code>addListener</code></a>  method of the Event Utility.  The signatures of these new methods are as follows: </p>
<p> <code>onFocus(el, fn, obj, override)</code><br /> <code>oBlur(el, fn, obj, override)</code> </p>
<p>The arguments for both methods are as follows:</p>
<dl>
<dt>el</dt>
<dd>An id, an element reference, or a collection of ids and/or elements to assign the listener to.</dd>
<dt>fn</dt>
<dd>The method the event invokes.</dd>
<dt>obj</dt>
<dd>An arbitrary object that will be passed as a parameter to the handler.</dd>
<dt>override</dt>
<dd>override  If true, the obj passed in becomes the execution scope of the listener. If an  	object, this object becomes the execution scope.</dd>
</dl>
<h3>Using onFocus and onBlur</h3>
<p> Here are several ways we&#8217;ve made use of the new <code>onFocus</code> and <code>onBlur</code>  methods in YUI 2.6:  </p>
<h4>Improving Performance of Modal Dialogs</h4>
<p> To support modality, a Dialog widget needs to direct focus back to itself when an element  that is not one of its children receives focus.  Previously this was accomplished by registering  focus event listeners on every focusable element in the document when a modal Dialog was made  visible, and removing those listeners when it has was hidden, a process that proved to be  expensive and slow.  Using PPK&#8217;s technique we&#8217;ve been able to boost the time it takes to  initially display a modal Dialog by over 50% in most browsers, and boost the time it takes to  hide a modal Dialog by over 90%.  To test, we used a page with  <a href="http://yuiblog.com/sandbox/yui/v260/examples/container/modalitytest.php">250 focusable elements</a>. Here is how the numbers break out for each browser: </p>
<table border="1">
<caption> 		Time (in milliseconds) to initially display a modal Dialog widget on a page with 250  		focusable elements in YUI 2.5.2 and YUI 2.6.0 	</caption>
<thead>
<tr>
<th>Browser</th>
<th>YUI 2.5.2</th>
<th>YUI 2.6.0</th>
<th>% Faster</th>
</tr>
</thead>
<tbody>
<tr>
<td>FF 3 Mac OS 10.4</td>
<td>245</td>
<td>107</td>
<td>56</td>
</tr>
<tr>
<td>FF 3 Win XP</td>
<td>158</td>
<td>88</td>
<td>44</td>
</tr>
<tr>
<td>FF 2 Mac OS 10.4</td>
<td>368</td>
<td>161</td>
<td>56</td>
</tr>
<tr>
<td>FF 2 Win XP</td>
<td>320</td>
<td>131</td>
<td>59</td>
</tr>
<tr>
<td>Opera 9.5 Mac OS 10.4</td>
<td>103</td>
<td>93</td>
<td>10</td>
</tr>
<tr>
<td>Opera 9.5 Win XP</td>
<td>71</td>
<td>60</td>
<td>15</td>
</tr>
<tr>
<td>IE 7</td>
<td>200</td>
<td>70</td>
<td>65</td>
</tr>
<tr>
<td>IE 6</td>
<td>220</td>
<td>121</td>
<td>45</td>
</tr>
<tr>
<td>Safari 3.1 </td>
<td>53</td>
<td>18</td>
<td>66</td>
</tr>
</tbody>
</table>
<table border="1">
<caption> 		Time (in milliseconds) to hide a modal Dialog widget on a page with 250 focusable elements  		in YUI 2.5.2 and YUI 2.6.0 	</caption>
<thead>
<tr>
<th>Browser</th>
<th>YUI 2.5.2</th>
<th>YUI 2.6.0</th>
<th>% Faster</th>
</tr>
</thead>
<tbody>
<tr>
<td>FF 3 Mac OS 10.4</td>
<td>65</td>
<td>1</td>
<td>98</td>
</tr>
<tr>
<td>FF 3 Win XP</td>
<td>57</td>
<td>1</td>
<td>98</td>
</tr>
<tr>
<td>FF 2 Mac OS 10.4</td>
<td>198</td>
<td>2</td>
<td>99</td>
</tr>
<tr>
<td>FF 2 Win XP</td>
<td>221</td>
<td>0</td>
<td>100</td>
</tr>
<tr>
<td>Opera 9.5 Mac OS 10.4</td>
<td>531</td>
<td>1</td>
<td>100</td>
</tr>
<tr>
<td>Opera 9.5 Win XP</td>
<td>380</td>
<td>0</td>
<td>100</td>
</tr>
<tr>
<td>IE 7</td>
<td>381</td>
<td>30</td>
<td>92</td>
</tr>
<tr>
<td>IE 6</td>
<td>371</td>
<td>40</td>
<td>89</td>
</tr>
<tr>
<td>Safari 3.1 </td>
<td>48</td>
<td>1</td>
<td>98</td>
</tr>
</tbody>
</table>
<h4>Improving Menu Keyboard Accessibility</h4>
<p> In keeping with the <a href="http://www.w3.org/TR/wai-aria-practices/#Menu">WAI-ARIA Best Practices  for Menus</a>, the <a href="http://developer.yahoo.com/yui/menu/">Menu widget</a> uses the  new <code>onFocus</code> method to listen for focus at the document level, so that when a popup  Menu is hidden focus can be restored to the element in the DOM that had focus before it was made visible. </p>
<h4>Providing Focus Feedback in Carousel</h4>
<p> The new <a href="http://developer.yahoo.com/yui/carousel/">Carousel widget</a> skins its next and  previous buttons by wrapping each <code>&#60;input type="button"&#62;</code> elements in a  <code>&#60;span&#62;</code>.  The <code>&#60;input&#62;</code> elements are then positioned off  screen and a background image is applied to each <code>&#60;span&#62;</code>.  While this technique  allows the next and previous buttons to remain accessible to users of screen readers, with the  actual next and previous buttons hidden off screen, sighted users don&#8217;t receive any feedback from  the UI when either button is focused.  To fix this problem, Carousel uses the <code>onFocus</code>   method to apply a class to the next and previous buttons that highlights focused buttons with an outline. </p>
<p> Of course, these are just a few places where we&#8217;ve used <code>onFocus</code> and <code>onBlur</code> &#8212; we think it will prove so useful in YUI and in YUI-based applications that we&#8217;ve added it to our  Core, making it available to any application you build on top of YUI&#8217;s Event Utility. </p>
<p class="tags">Tags: <a href="http://technorati.com/tag/onfocus" title="See the Technorati tag page for 'onfocus'." rel="tag">onfocus</a>, <a href="http://technorati.com/tag/onblur" title="See the Technorati tag page for 'onblur'." rel="tag">onblur</a>, <a href="http://technorati.com/tag/wai-aria" title="See the Technorati tag page for 'wai-aria'." rel="tag">wai-aria</a>, <a href="http://technorati.com/tag/ppk" title="See the Technorati tag page for 'ppk'." rel="tag">ppk</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/10/07/onfocus-onblur/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ARIA Plugins for YUI Widgets</title>
		<link>http://www.yuiblog.com/blog/2008/10/02/yui-aria/</link>
		<comments>http://www.yuiblog.com/blog/2008/10/02/yui-aria/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 16:12:46 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/10/02/yui-aria/</guid>
		<description><![CDATA[
For YUI 2.6, a handful of widgets have examples illustrating how to use new YUI ARIA plugins.  These
plugins make it easy to use the
WAI-ARIA Roles and States to make each widget
more interoperable with assistive technologies (AT), such as screen readers, and in turn,
more accessible to users with disabilities.  For example, the following video [...]]]></description>
			<content:encoded><![CDATA[<p>
For YUI 2.6, a handful of widgets have examples illustrating how to use new YUI ARIA plugins.  These<br />
plugins make it easy to use the<br />
<a href="http://www.w3.org/TR/wai-aria/">WAI-ARIA Roles and States</a> to make each widget<br />
more interoperable with assistive technologies (AT), such as screen readers, and in turn,<br />
more accessible to users with disabilities.  For example, the following video illustrates how the<br />
YUI ARIA Plugin for Carousel improves the user experience of the new Carousel widget for users of<br />
screen readers:</p>
<div><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.30" /><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" VALUE="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=9957126&#038;vid=3609568&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/5335/72446715.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.30" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" AllowScriptAccess="always" bgcolor="#000000" flashVars="id=9957126&#038;vid=3609568&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/5335/72446715.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/3609568/9957126">Using the Carousel ARIA Plugin</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></div>
<h3>Using the ARIA Plugins</h3>
<p>
Using the YUI ARIA Plugins is easy. Simply include the source file(s) for the ARIA plugin after the<br />
widget source file(s) as indicated on the widget&#8217;s landing page.  That&#8217;s it.  Currently, the source<br />
files for each plugin are available in the<br />
<a href="http://developer.yahoo.com/yui/download/">YUI 2.6 package on SourceForge</a>, and can<br />
also be <a href="http://yuiblog.com/sandbox/yui/v260/aria-plugins.zip">downloaded from the YUI blog<br />
sandbox</a>.  In a future release of YUI, the plugins will be served from our CDN.
</p>
<h3>Browser Support</h3>
<p>
All YUI ARIA Plugins require the user&#8217;s browser and AT support the WAI-ARIA Roles and States.<br />
Currently only <a href="http://www.mozilla.com/en-US/firefox/">Firefox 3</a> and<br />
<a href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/getitnow.mspx">Internet Explorer<br />
8</a> have support for ARIA <em>and</em> are supported by several screen readers for<br />
Windows that also offer ARIA support.  Opera also has support for ARIA as of version 9.5, but<br />
unfortunately isn&#8217;t supported by any screen readers.  For this reason the YUI ARIA Plugins are only<br />
enabled by default for Firefox 3 and IE 8.  To enable the ARIA plugin for other browsers, simply the set<br />
the <code>usearia</code> configuration property to <code>true</code>.  For example:</p>
<pre>
var oMenu = new YAHOO.widget.Menu("menu-1", { usearia: true });
</pre>
<h3>Why Plugins?</h3>
<p>Rather than integrate ARIA directly into a widget, we chose to deliver this functionality as a<br />
plugin for two main reasons:</p>
<ul>
<li><em>Performance:</em> We&#8217;ve got many extremely byte-conscious users.  And while we certainly<br />
don&#8217;t want users opting out of a more accessible interface, we need to be respectful of those<br />
developers that need to make tough choices on KB weight.
</li>
<li>
<em>The right fit:</em> For most widgets (like Menu) there is an ARIA role that is a perfect match.<br />
For some, like Carousel, or AccordionView, there either isn&#8217;t a clear match, or there are several<br />
different roles that could work depending on the circumstances.  For widgets that fall into this<br />
category we can offer several different ARIA plugins that meet the desired use case. </li>
</ul>
<h3>Widgets with ARIA Plugin Support</h3>
<p>
The following table illustrates which YUI widgets currently have an ARIA plugin, along with their<br />
corresponding WAI-ARIA Roles.
</p>
<table>
<thead>
<tr>
<th>Widget</th>
<th>ARIA Role(s)</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://developer.yahoo.com/yui/examples/button/button-ariaplugin.html">Button</a></td>
<td><a href="http://www.w3.org/TR/wai-aria/#checkbox">checkbox</a>, <a href="http://www.w3.org/TR/wai-aria/#radio">radio</a>, <a href="http://www.w3.org/TR/wai-aria/#radiogroup">radiogroup</a></td>
</tr>
<tr>
<td><a href="http://developer.yahoo.com/yui/examples/carousel/carousel-ariaplugin.html">Carousel</a></td>
<td><a href="http://www.w3.org/TR/wai-aria/#toolbar">toolbar</a>, <a href="http://www.w3.org/TR/wai-aria/#button">button</a>, <a href="http://www.w3.org/TR/wai-aria/#listbox">listbox</a>, <a href="http://www.w3.org/TR/wai-aria/#option">option</a></td>
</tr>
<tr>
<td><a href="http://developer.yahoo.com/yui/examples/container/container-ariaplugin.html">Container</a></td>
<td><a href="http://www.w3.org/TR/wai-aria/#dialog">dialog</a>, <a href="http://www.w3.org/TR/wai-aria/#alertdialog">alertdialog</a>, <a href="http://www.w3.org/TR/wai-aria/#tooltip">tooltip</a></td>
</tr>
<tr>
<td><a href="http://developer.yahoo.com/yui/examples/menu/menuwaiaria.html">Menu</a></td>
<td><a href="http://www.w3.org/TR/wai-aria/#menu">menu</a>, <a href="http://www.w3.org/TR/wai-aria/#menubar">menubar</a>, <a href="http://www.w3.org/TR/wai-aria/#menuitem">menuitem</a></td>
</tr>
<tr>
<td><a href="http://developer.yahoo.com/yui/examples/tabview/tabview-ariaplugin.html">TabView</a></td>
<td><a href="http://www.w3.org/TR/wai-aria/#tablist">tablist</a>, <a href="http://www.w3.org/TR/wai-aria/#tab">tab</a>, <a href="http://www.w3.org/TR/wai-aria/#tabpanel">tabpanel</a></td>
</tr>
</tbody>
</table>
<h3>Screen Reader Testing</h3>
<p> We&#8217;d love the community to help us test these plugins, find bugs and suggest enhancements.  As  mentioned above, each plugin requires AT that supports ARIA.  Two of the leading screen readers for  Windows,  <a href="http://www.freedomscientific.com/fs_products/software_jaws.asp">JAWS</a> and  <a href="http://www.gwmicro.com/Window-Eyes/">Window-Eyes</a>, support ARIA.  Free, trial  versions of both are available for download, but require Windows be restarted every 40 minutes. For that reason, the open-source  <a href="http://www.nvda-project.org/">NVDA Screen Reader</a> is the best option for developers  looking to test the YUI ARIA Plugins as it is both free and provides excellent support for ARIA.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/10/02/yui-aria/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reading Blinds — a YUI-powered Reading Tool</title>
		<link>http://www.yuiblog.com/blog/2008/09/30/reading-blinds/</link>
		<comments>http://www.yuiblog.com/blog/2008/09/30/reading-blinds/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 20:57:45 +0000</pubDate>
		<dc:creator>Christian Heilmann</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/09/30/reading-blinds/</guid>
		<description><![CDATA[Ever since I got upgraded to a shiny Macbook Pro and a 24 inch monitor at work I had a web experience that differed a lot from what I had before. Web sites that were easy and nice to read out of a sudden showed a massive amount of white space that actually hurt my [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since I got upgraded to a shiny Macbook Pro and a 24 inch monitor at work I had a web experience that differed a lot from what I had before. Web sites that were easy and nice to read out of a sudden showed a massive amount of white space that actually hurt my eyes. Talking to several people with visual impairments and dyslexia at <a href="http://scriptingenabled.org">Scripting Enabled</a> confirmed me that this can be a real issue.</p>
<p>This is why I thought of writing a small script that can be used as a bookmarklet to cover the screen with a dark overlay and only shows a few lines at a time. That way you can concentrate on the bit you are reading at the moment and the rest of the screen does not bother you too much. </p>
<p>Following are two screenshots of the same site with and without reading blinds:</p>
<p><img src="http://yuiblog.com/assets/blinds.jpg" width="420" height="323" alt="Browser with Reading Blinds"></p>
<p><img src="http://yuiblog.com/assets/withoutblinds.jpg" width="420" height="324" alt="Browser without Reading Blinds"></p>
<p>So how to build that?</p>
<p>The task of building a tool like that is actually pretty easy:</p>
<ul>
<li>create two DIVs with black background and 85% opacity</li>
<li>position them fixed to the top and the bottom of the screen </li>
<li>set their height to 10% and 70% to leave a gap</li>
</ul>
<p>Then I thought that I should be able to move the highlight on the page. For this I needed a bit more sophistication:</p>
<ul>
<li>Detect the mouse cursor position</li>
<li>Make the top div span from the current top of the document to a few pixels above the cursor position</li>
<li>Make the bottom div span from a few pixels below the current cursor position to the bottom of the viewport</li>
</ul>
<p>I could have had a go at it myself, but I don&#8217;t want to end in browser inconsistency hell, hence I use YUI.</p>
<p>Here&#8217;s the code:</p>
<pre>var readingblinds = function(){
  var visible = true;
  var y,top,bottom;
  var info = true;
  var size = 70;
  function generate(){
    top = document.createElement('div');
    bottom = document.createElement('div');
    document.body.appendChild(top);
    document.body.appendChild(bottom);
    styleTopBottom();
    var message = document.createElement('div');
    var note = document.createTextNode(
      'Reading Blinds - ' +
      'move mouse to highlight section to read. '
    );
    message.appendChild(note);
    top.appendChild(message);
    styleMessage(message);
    YAHOO.util.Event.on(document, "mousemove", move);
  };
  function move(e){
    y = YAHOO.util.Event.getXY(e);
    if(y[1] &gt; size){
      render(y);
    }
  };
  function render(y){
    var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
    YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
    var h = YAHOO.util.Dom.getViewportHeight()-real+size;
    YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
    YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
  };
  function styleMessage(message){
    YAHOO.util.Dom.setStyle(message,'font-size','80%');
    YAHOO.util.Dom.setStyle(message,'text-align','right');
    YAHOO.util.Dom.setStyle(message,'padding','5px');
    YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
    YAHOO.util.Dom.setStyle(message,'color','white');
  }
  function styleTopBottom(){
    YAHOO.util.Dom.batch([top,bottom],function(o){
      YAHOO.util.Dom.setStyle(o,'background','#000');
      YAHOO.util.Dom.setStyle(o,'width','100%');
      YAHOO.util.Dom.setStyle(o,'position','fixed');
      YAHOO.util.Dom.setStyle(o,'left','0');
      YAHOO.util.Dom.setStyle(o,'height','10%');
      YAHOO.util.Dom.setStyle(o,'opacity','.85');
      YAHOO.util.Dom.setStyle(o,'overflow','hidden');
    });
    YAHOO.util.Dom.setStyle(top,'top','0');
    YAHOO.util.Dom.setStyle(bottom,'bottom',0);
    YAHOO.util.Dom.setStyle(bottom,'height','70%');
  };
  return{
    init:generate
  }
}();
readingblinds.init();</pre>
<p>The interesting methods are <code>move()</code> and <code>render()</code>; the rest is more or less run-of-the-mill DOM scripting. </p>
<p>The <code>move()</code> method is an event handler that gets called by any mousemove event on the document. YUI&#8217;s Dom Collection then makes it easy for me to get the current mouse cursor position with <code>getXY()</code> and I just need to make sure that the mouse is low enough in the browser window to not cause a negative height on the top div.</p>
<p>The <code>render()</code> method then sets the appropriate heights. I determine the upper border of the browser with <code>getDocumentScrollTop()</code> and substract that one from the cursor position. To determine where to end the bottom div I use <code>getViewPortHeight()</code>. </p>
<h3>Addding dazzle with keyboard controls</h3>
<p>This was cool enough, but I wanted to be able to turn the blinds on and off and change the size of the visible part with the keyboard, too. For this, I needed to use the keylistener utility some tool methods to resize the gap or show and hide both of the cover divs. The resizing methods needed to get some boundaries to avoid div overlap or the whole viewport to be uncovered.</p>
<pre>var readingblinds = function(){
  var visible = true;
  var y,top,bottom;
  var info = true;
  var size = 70;
  function generate(){
    top = document.createElement('div');
    bottom = document.createElement('div');
    document.body.appendChild(top);
    document.body.appendChild(bottom);
    styleTopBottom();
    var message = document.createElement('div');
    var note = document.createTextNode(
      'Reading Blinds - ' +
      'move mouse to highlight section to read. ' +
      'Press "b" to show and hide, "s" to decrease size,' +
      ' "l" to increase size'
    );
    message.appendChild(note);
    top.appendChild(message);
    styleMessage(message);
    var keyspy = new YAHOO.util.KeyListener(
      document,
      { keys:66 },
      { fn:peekaboo }
    );
    keyspy.enable();
    var keyspy2 = new YAHOO.util.KeyListener(
      document,
      { keys:83 },
      { fn:smaller }
    );
    keyspy2.enable();
    var keyspy3 = new YAHOO.util.KeyListener(
      document,
      { keys:76 },
      { fn:larger }
    );
    keyspy3.enable();
    YAHOO.util.Event.on(document, "mousemove", move);
  };
  function move(e){
    y = YAHOO.util.Event.getXY(e);
    if(y[1] &gt; size){
      render(y);
    }
  };
  function render(y){
    var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
    YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
    YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
    var h = YAHOO.util.Dom.getViewportHeight()-real+size;
    YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
  };
  function styleMessage(message){
    YAHOO.util.Dom.setStyle(message,'font-size','80%');
    YAHOO.util.Dom.setStyle(message,'text-align','right');
    YAHOO.util.Dom.setStyle(message,'padding','5px');
    YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
    YAHOO.util.Dom.setStyle(message,'color','white');
  }
  function styleTopBottom(){
    YAHOO.util.Dom.batch([top,bottom],function(o){
      YAHOO.util.Dom.setStyle(o,'background','#000');
      YAHOO.util.Dom.setStyle(o,'width','100%');
      YAHOO.util.Dom.setStyle(o,'position','fixed');
      YAHOO.util.Dom.setStyle(o,'left','0');
      YAHOO.util.Dom.setStyle(o,'height','10%');
      YAHOO.util.Dom.setStyle(o,'opacity','.85');
      YAHOO.util.Dom.setStyle(o,'overflow','hidden');
    });
    YAHOO.util.Dom.setStyle(top,'top','0');
    YAHOO.util.Dom.setStyle(bottom,'bottom',0);
    YAHOO.util.Dom.setStyle(bottom,'height','70%');
  };
  function peekaboo(){
    if(visible === true){
      YAHOO.util.Dom.setStyle(top,'display','none');
      YAHOO.util.Dom.setStyle(bottom,'display','none');
      visible = false;
    } else {
      YAHOO.util.Dom.setStyle(top,'display','block');
      YAHOO.util.Dom.setStyle(bottom,'display','block');
      visible = true;
    }
  };
  function smaller(){
    if(size &gt; 10){
      size -= 5;
      render(y);
    }
  };
  function larger(){
    if(size &lt;  YAHOO.util.Dom.getViewportHeight()/2){
      size += 5;
      render(y);
    }
  };
  return{
    init:generate
  }
}();
readingblinds.init();</pre>
<p>That was pretty cool already, but as I wanted to make reading blinds a single script include or bookmarklet I had the problem of relying on the YUI. Well, there is a trick to conjure YUI from thin air by using the <a href="http://developer.yahoo.com/yui/docs/YAHOO_config.html"><code>YAHOO_config</code> object with the listener method</a> creating a script node to get the <a href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader</a>. </p>
<p>So instead of calling <code>readingblinds.init()</code> directly, I used the following magic YUI trick:</p>
<pre>if(typeof YAHOO=="undefined"||!YAHOO){
  YAHOO_config = function(){
    var s = document.createElement('script');
    s.setAttribute('type','text/javascript');
    s.setAttribute('src','http://yui.yahooapis.com/2.5.2/'+
                   'build/yuiloader/yuiloader-beta-min.js');
    document.getElementsByTagName('head')[0].appendChild(s);
    return{
      listener:function(o){
        if(o.name === 'get'){
          window.setTimeout(YAHOO_config.ready,1);
        }
      },
      ready:function(){
        var loader = new YAHOO.util.YUILoader();
        var dependencies = ['yahoo','dom','event'];
        loader.require(dependencies);
        loader.loadOptional = true;
        loader.insert({
          onSuccess:function(){
            readingblinds.init();
          }
        });
      }
    };
  }();
} else {
  readingblinds.init();
}</pre>
<p>That&#8217;s the lot. You can download <a href="http://yuiblog.com/assets/readingblinds.js">readingblinds.js<br />
</a> and include it in your site, or you can drag the following link to your links toolbar: <a href="javascript:var%20x=%20function(){var%20h=document.createElement('script');h.src='http://yuiblog.com/assets/readingblinds.js';h.type='text/javascript';document.getElementsByTagName('head')[0].appendChild(h)}();">Reading Blinds</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/09/30/reading-blinds/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Enhancing TabView Accessibility with WAI-ARIA Roles and States</title>
		<link>http://www.yuiblog.com/blog/2008/07/30/tabview-aria/</link>
		<comments>http://www.yuiblog.com/blog/2008/07/30/tabview-aria/#comments</comments>
		<pubDate>Thu, 31 Jul 2008 00:11:01 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/07/30/tabview-aria/</guid>
		<description><![CDATA[
The YUI TabView Control is built on a strong
foundation of semantic markup that provides users with some basic accessibility.  But while
TabView looks like a desktop tab control, screen readers don&#8217;t present it as an atomic
widget, leaving users to figure out how the various HTML elements that compose a TabView relate
to each other.  However, [...]]]></description>
			<content:encoded><![CDATA[<p>
The <a href="http://developer.yahoo.com/yui/tabview/">YUI TabView Control</a> is built on a strong<br />
foundation of semantic markup that provides users with some basic accessibility.  But while<br />
TabView looks like a desktop tab control, screen readers don&#8217;t present it as an atomic<br />
widget, leaving users to figure out how the various HTML elements that compose a TabView relate<br />
to each other.  However, through the application of the </p>
<p><a href="http://www.w3.org/TR/wai-aria/">WAI-ARIA Roles and States</a>, it is possible to enhance<br />
TabView&#8217;s accessibility such that users of screen readers perceive it as a desktop tab control.
</p>
<p>
A <a href="http://yuiblog.com/sandbox/yui/v252/examples/tabview/aria_tabview.html">complete<br />
example</a> of TabView using the WAI-ARIA Roles and States is available in the YUI Sandbox.<br />
<a href="http://yuiblog.com/assets/tabviewscreencast.mov">Watch a screen cast of the example<br />
running in Firefox 3 with the NVDA screen reader</a>, or<br />
<a href="http://www.nvda-project.org/wiki/Snapshots">download the latest development snapshot of<br />
NVDA</a> and try it yourself.
</p>
<div><object width="512" height="322"><param name="movie" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.16" /><param name="allowFullScreen" value="true" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=9051193&#038;vid=3199866&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/4371/69134473.jpeg&#038;embed=1" /><embed src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.16" type="application/x-shockwave-flash" width="512" height="322" allowFullScreen="true" bgcolor="#000000" flashVars="id=9051193&#038;vid=3199866&#038;lang=en-us&#038;intl=us&#038;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/p/i/bcst/videosearch/4371/69134473.jpeg&#038;embed=1" ></embed></object><br /><a href="http://video.yahoo.com/watch/3199866/9051193">YUI TabView with ARIA roles and states/Todd Kloots</a> @ <a href="http://video.yahoo.com" >Yahoo! Video</a></div>
<h3>Applying the WAI-ARIA Roles and States to TabView</h3>
<h4>Step 1: Getting Started</h4>
<p>
To start working with the WAI-ARIA Roles and States you&#8217;ll need both a browser and screen<br />
reader that support ARIA.  Both <a href="http://www.mozilla.com/en-US/firefox/">Firefox 3</a> and<br />
<a href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/getitnow.mspx">Internet Explorer<br />
8 Beta 1</a> have ARIA support.  Trial versions of the leading<br />
<a href="http://www.freedomscientific.com/fs_products/software_jaws.asp">JAWS</a> and </p>
<p><a href="http://www.gwmicro.com/Window-Eyes/">Window-Eyes</a> screen readers are available for<br />
free download.  However, the open-source <a href="http://www.nvda-project.org/">NVDA Screen<br />
Reader</a> is the best option for developers as it is both free and provides excellent support<br />
for ARIA.
</p>
<h4>Step 2: Adding Enhanced Keyboard Support</h4>
<p>
Out of the box, TabView provides basic keyboard support.  Each Tab in a TabView is represented by<br />
an <code>&#60;A&#62;</code> element whose <code>href</code> attribute is set to the id of an </p>
<p><code>&#60;DIV&#62;</code> element that contains its content.  In IE and Firefox,<br />
<code>&#60;A&#62;</code> elements are automatically placed in the browser&#8217;s default tab index,<br />
enabling the user to toggle between Tabs by pressing the tab key, and select a Tab by<br />
pressing enter.  (In Safari and Opera, <code>&#60;A&#62;</code> elements are not in the tab index<br />
by default.  Safari users can change this by going to the Safari Menu, Selecting &#8220;Preferences&#8221;,<br />
then choose the &#8220;Advanced&#8221; tab and check the &#8220;Press Tab to highlight each item on a<br />
webpage&#8221; checkbox.)
</p>
<p>
Having all of the Tabs in a TabView in the browser&#8217;s default tab index is a mixed blessing:<br />
it provides basic keyboard accessibility, but can also make navigating more tedious in that users<br />
navigating via the tab key have to tab through every Tab&#8217;s <code>&#60;A&#62;</code> as well as the<br />
content of the active Tab&#8217;s correpsonding TabPanel in order to skip past the control.  This problem<br />
can be solved by setting the <code>tabindex</code> attribute of the <code>&#60;A&#62;</code> element<br />
of the active Tab to a value of 0, and the inactive Tabs to -1.  Setting an element&#8217;s </p>
<p><code>tabindex</code> attribute to a value of -1 removes it from the browser&#8217;s default tab order,<br />
while maintaining its focusability via JavaScript.  Therefore, with this change in place it will be<br />
easier for the user to skip over a TabView widget while navigating with the keyboard.
</p>
<h5>Mac vs. Windows</h5>
<p>
With only one Tab now in the browser&#8217;s default tab index, it will be necessary to supplement the<br />
TabView with support for the arrow keys to enable the user to navigate between Tabs as they would<br />
on the desktop.  There are two different models for arrow key support for tabbed-content controls<br />
in operating systems: Mac OS X and Windows.<br />
On Windows, pressing the left or right arrow key moves focus to the next Tab and immediately<br />
displays its corresponding TabPanel.  On the Mac, with VoiceOver enabled, the arrow keys only<br />
move focus between each Tab, and the user must press the space bar to load the content of the Tab&#8217;s<br />
corresponding TabPanel.  Of the two, the Mac&#8217;s model might be considered better for a DHTML TabView.<br />
For example, if each Tab&#8217;s content is loaded via XHR, the Mac&#8217;s more intentional Tab selection<br />
model could help prevent the user from making requests for data he/she is not interested<br />
in consuming.
</p>
<h5>Supporting Multiple Orientations</h5>
<p>The <a href="http://developer.yahoo.com/yui/docs/YAHOO.widget.TabView.html#config_orientation"><code>orientation</code></a><br />
attribute of the TabView is used to render the Tabs on any of the widget&#8217;s four sides.  To provide<br />
arrow key support that will work regardless of the orientation of the Tabs, the left and up keys<br />
will move the focus to the previous Tab, while the right and down arrow keys will move the focus to<br />
the next Tab.  As an additional convenience to the user, we&#8217;ll take another cue from the Mac&#8217;s<br />
tab control implementation so that focus is automatically moved to the first or last Tab when the<br />
user has reached the beginning or end of a list of Tabs.
</p>
<p>
To apply these keyboard enhancements to TabView, we&#8217;ll define a new prototype method named<br />
<code>enhanceAccessibility</code>.   This new method is designed to provide consistent keyboard<br />
support for TabView across all of the <a href="http://developer.yahoo.com/yui/articles/gbs/">A-Grade</a><br />
browsers.  It will work regardless of how the TabView is constructed (from existing markup, or<br />
from script), its orientation, or if its content is static or loaded via XHR.
</p>
<pre>YAHOO.widget.TabView.prototype.enhanceAccessibility = function () {

	var Dom = YAHOO.util.Dom,
		Event = YAHOO.util.Event,
		UA = YAHOO.env.ua,

		oTabViewEl = this.get("element"),
		oTabList = Dom.getChildren(oTabViewEl)[0],
		aTabListItems = Dom.getChildren(oTabList),
		aTabs = this.get("tabs"),
		oTabIndexMap = {},
		oTab,
		oTabEl,
		oTabAnchor,
		oTabContentEl,
		oFocusedTabAnchor,
		sTabId,
		oActiveTab;

	//	Set the "tabIndex" attribute of each Tab's &#60;A&#62; element: The
	//	"tabIndex" of the active Tab's &#60;A&#62; element is set to 0, the others to -1.
	//	This improves the keyboard accessibility of the TabView by placing
	//	only one Tab in the browser's tab index by default, allowing the user
	//	to easily skip over the control when navigating the page with the tab key.

	Dom.batch(oTabList.getElementsByTagName("A"), function (element) {
		element.tabIndex = -1;
	});

	oActiveTab = this.get("activeTab");

	if (oActiveTab) {
		Dom.getFirstChild(oActiveTab.get("element")).tabIndex = 0;
	}

	//	Returns the &#60;A&#62; element representing each Tab in the TabView.

	var getTabAnchor = function (element) {

		var oTabAnchor;

		if (Dom.getAncestorByClassName(element, "yui-nav")) {

			if (element.nodeName.toUpperCase() === "A") {
				oTabAnchor = element;
			}
			else {
				oTabAnchor = Dom.getAncestorByTagName(element, "A");
			}

		}

		return oTabAnchor;

	};

	//	Keydown event listener for the TabView that provides support for
	//	using the arrow keys to move focus between each Tab.

	this.on("keydown", function (event) {

		var oCurrentTabAnchor = getTabAnchor(Event.getTarget(event)),
			oCurrentTabLI,
			oNextTabLI,
			oNextTabAnchor;

		if (oCurrentTabAnchor) {

			oCurrentTabLI = oCurrentTabAnchor.parentNode;

			switch (Event.getCharCode(event)) {

				case 37:	// Left
				case 38:	// Up

					oNextTabLI = Dom.getPreviousSibling(oCurrentTabLI);

					if (!oNextTabLI) {
						oNextTabLI = aTabListItems[aTabListItems.length-1];
					}

				break;

				case 39:	// Right
				case 40:	// Down

					oNextTabLI = Dom.getNextSibling(oCurrentTabLI);

					if (!oNextTabLI) {
						oNextTabLI = aTabListItems[0];
					}

				break;

			}

			oNextTabAnchor = Dom.getChildren(oNextTabLI)[0];

			if (!oFocusedTabAnchor) {
				oFocusedTabAnchor = oCurrentTabAnchor;
			}

			oFocusedTabAnchor.tabIndex = -1;
			oNextTabAnchor.tabIndex = 0;

			oNextTabAnchor.focus();

			oFocusedTabAnchor = oNextTabAnchor;

		}

	});

};</pre>
<h4>Step 3: Adding the WAI-ARIA Roles and States</h4>
<p>
With the keyboard functionality in place, we&#8217;ll proceed with the application of the WAI-ARIA Roles<br />
and States.  Once applied, assistive technologies (AT) such as a screen reader will no longer<br />
announce the HTML elements that compose the TabView as HTML elements, but as a tab control.  In<br />
this way the relationship between the WAI-ARIA Roles and States and HTML is similar to that of CSS:<br />
both enable the developer to change the presentation of markup.  And since the WAI-ARIA Roles and<br />
States enable the TabView to be presented to the user as a desktop tab control, it makes the<br />
previous work of applying desktop-like keyboard behavior all the more critical.  If users of AT are<br />
going to preceive the TabView as a desktop tab control, it needs to fulfill that expectation from a<br />
keyboard perspective.
</p>
<p>
As a best practice, apply the WAI-ARIA Roles and States via JavaScript.  Since the WAI-ARIA Roles<br />
and States depend on JavaScript-based keyboard functionality, it follows that the attributes<br />
representing the WAI-ARIA Roles and States only be applied via JavaScript.  This<br />
<a href="http://en.wikipedia.org/wiki/Progressive_enhancement">Progressive Enhancement</a><br />
strategy ensures the best possible user experience by only applying WAI-ARIA Roles and States when<br />
the browser technologies required to support them (in this case, CSS and JavaScript) are available.
</p>
<p>
Roles and states are added to a TabView&#8217;s DOM elements via the<br />
<a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-core.html#ID-F68F082"><code>setAttribute</code></a><br />
method.  At present only two browsers have WAI-ARIA support:<br />
<a href="http://www.mozilla.com/en-US/firefox/">Firefox 3</a> and<br />
<a href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/getitnow.mspx">Internet Explorer 8 Beta 1</a>.<br />
(The <a href="http://www.opera.com/docs/changelogs/windows/950/">changelog</a> for Opera 9.5<br />
mentions support for screen readers, MSAA, and ARIA, but in my testing in Opera I didn&#8217;t<br />
find ARIA to work.)  Therefore, we&#8217;ll make use of YUI&#8217;s browser detection<br />
(<a href="http://developer.yahoo.com/yui/docs/YAHOO.env.ua.html"><code>YAHOO.env.ua</code></a>) and<br />
only apply the Roles and States to browsers that support them.  The role of<br />
<a href="http://www.w3.org/TR/wai-aria/#tab"><code>tab</code></a> will be applied to each Tab&#8217;s </p>
<p><code>&#60;A&#62;</code> element, and the role of<br />
<a href="http://www.w3.org/TR/wai-aria/#tablist"><code>tablist</code></a> to their parent<br />
<code>&#60;UL&#62;</code>.  Finally, each Tab&#8217;s content element (<code>&#60;DIV&#62;</code>) will<br />
receive the role of <a href="http://www.w3.org/TR/wai-aria/#tabpanel"><code>tabpanel</code></a> and<br />
an <a href="http://www.w3.org/TR/wai-aria/#labelledby"><code>aria-labelledby</code></a> attribute<br />
with a value of the id of the <code>&#60;A&#62;</code> representing its corresponding Tab instance.<br />
The <code>aria-labelledby</code> attribute enables the screen reader to announce the label of the<br />
Tab for each TabPanel when  the first element in a TabPanel receives focus, providing the user with<br />
some context as to where they are.  The following example illustrates how the ARIA roles and<br />
properties are applied to each of the HTML elements that compose a TabView:</p>
<pre>&#60;div class="yui-navset"&#62;
	&#60;ul <em>role="tablist"</em>&#62;
		&#60;li&#62;
			&#60;a href="..." id="tab-1" <em>role="tab"</em>&#62;tab label&#60;/a&#62;

		&#60;/li&#62;
	&#60;/ul&#62;
	&#60;div clas="yui-content"&#62;
		&#60;div <em>role="tabpanel"</em> <em>aria-labelledby="tab-1"</em>&#62;tab content&#60;/div&#62;

	&#60;/div&#62;
&#60;/div&#62;</pre>
<h5>Screen-Reader Specific Tweaks</h5>
<p>
The implementation of the WAI-ARIA Roles and States is slightly different across screen readers, so<br />
it is necessary to make some additional tweaks.  A role of<br />
<a href="http://www.w3.org/TR/wai-aria/#presentation"><code>presentation</code></a> will need to be<br />
applied to the parent <code>&#60;LI&#62;</code> element of each <code>&#60;A&#62;</code>, so that<br />
the Window-Eyes screen reader recognizes that each Tab belongs to the same TabList.  For JAWS it is<br />
necessary to remove the <code>href</code> attribute of each Tab&#8217;s <code>&#60;A&#62;</code> element<br />
to prevent it from announcing the attribute&#8217;s value when focused. Ideally JAWS would behave like<br />
NVDA and Window-Eyes and allow the applied <code>role</code> attribute of </p>
<p><a href="http://www.w3.org/TR/wai-aria/#tab"><code>tab</code></a> to take precedence over the<br />
default role of the <code>&#60;A&#62;</code> element.  The following illustrates the updated<br />
markup for a TabView with the screen reader tweaks applied:
</p>
<pre>&#60;div class="yui-navset"&#62;
	&#60;ul <em>role="tablist"</em>&#62;
		&#60;li <em>role="presentation"</em>&#62;

			&#60;a id="tab-1" <em>role="tab"</em>&#62;tab label&#60;/a&#62;
		&#60;/li&#62;
	&#60;/ul&#62;
	&#60;div clas="yui-content"&#62;
		&#60;div <em>role="tabpanel"</em> <em>aria-labelledby="tab-1"</em>&#62;tab content&#60;/div&#62;

	&#60;/div&#62;
&#60;/div&#62;</pre>
<p>
With this strategy for applying the WAI-ARIA Roles and States to TabView, we can update the<br />
<code>enhanceAccessibility</code> method:
</p>
<pre>YAHOO.widget.TabView.prototype.enhanceAccessibility = function () {

	var Dom = YAHOO.util.Dom,
		Event = YAHOO.util.Event,
		UA = YAHOO.env.ua,

		oTabViewEl = this.get("element"),
		oTabList = Dom.getChildren(oTabViewEl)[0],
		aTabListItems = Dom.getChildren(oTabList),
		aTabs = this.get("tabs"),
		oTabIndexMap = {},
		oTab,
		oTabEl,
		oTabAnchor,
		oTabContentEl,
		oFocusedTabAnchor,
		sTabId,
		oActiveTab;

	//	Set the "tabIndex" attribute of each Tab's &#60;A&#62; element: The
	//	"tabIndex" of the active Tab's &#60;A&#62; element is set to 0, the others to -1.
	//	This improves the keyboard accessibility of the TabView by placing
	//	only one Tab in the browser's tab index by default, allowing the user
	//	to easily skip over the control when navigating the page with the tab key.

	Dom.batch(oTabList.getElementsByTagName("A"), function (element) {
		element.tabIndex = -1;
	});

	oActiveTab = this.get("activeTab");

	if (oActiveTab) {
		Dom.getFirstChild(oActiveTab.get("element")).tabIndex = 0;
	}

	//	Returns the &#60;A&#62; element representing each Tab in the TabView.

	var getTabAnchor = function (element) {

		var oTabAnchor;

		if (Dom.getAncestorByClassName(element, "yui-nav")) {

			if (element.nodeName.toUpperCase() === "A") {
				oTabAnchor = element;
			}
			else {
				oTabAnchor = Dom.getAncestorByTagName(element, "A");
			}

		}

		return oTabAnchor;

	};

	//	Keydown event listener for the TabView that provides support for
	//	using the arrow keys to move focus between each Tab.

	this.on("keydown", function (event) {

		var oCurrentTabAnchor = getTabAnchor(Event.getTarget(event)),
			oCurrentTabLI,
			oNextTabLI,
			oNextTabAnchor;

		if (oCurrentTabAnchor) {

			oCurrentTabLI = oCurrentTabAnchor.parentNode;

			switch (Event.getCharCode(event)) {

				case 37:	// Left
				case 38:	// Up

					oNextTabLI = Dom.getPreviousSibling(oCurrentTabLI);

					if (!oNextTabLI) {
						oNextTabLI = aTabListItems[aTabListItems.length-1];
					}

				break;

				case 39:	// Right
				case 40:	// Down

					oNextTabLI = Dom.getNextSibling(oCurrentTabLI);

					if (!oNextTabLI) {
						oNextTabLI = aTabListItems[0];
					}

				break;

			}

			oNextTabAnchor = Dom.getChildren(oNextTabLI)[0];

			if (!oFocusedTabAnchor) {
				oFocusedTabAnchor = oCurrentTabAnchor;
			}

			oFocusedTabAnchor.tabIndex = -1;
			oNextTabAnchor.tabIndex = 0;

			oNextTabAnchor.focus();

			oFocusedTabAnchor = oNextTabAnchor;

		}

	});

	//	Only apply the WAI-ARIA Roles and States for FF 3 and IE 8 since those
	//	are the only browsers that currently support ARIA.

	if ((UA.gecko &#038;&#038; UA.gecko >= 1.9) || (UA.ie &#038;&#038; UA.ie >= 8)) {

		//	Set the "role" attribute of the &#60;UL&#62; encapsulating the Tabs to "tablist"

		oTabList.setAttribute("role", "tablist");

		for (var i = 0, nLength = aTabs.length; i < nLength; i++) {

			oTab = aTabs[i];
			oTabEl = oTab.get("element");
			oTabAnchor = Dom.getChildren(oTabEl)[0];

			//	Create a map that links the ids of each Tab's &#60;A&#62; element to
			//	the Tab's "index" attribute to make it possible to retrieve a Tab
			//	instance reference by id.

			sTabId = oTabAnchor.id;

			if (!sTabId) {
				sTabId = Dom.generateId();
				oTabAnchor.id = sTabId;
			}

			oTabIndexMap[sTabId] = i;

			//	Need to set the "role" attribute of each Tab's &#60;LI&#62; element to
			//  "presentation" so that Window-Eyes recognizes that each Tab belongs to
			//	the same TabList. Without this, Window-Eyes will announce each Tab as
			//	being "1 of 1" as opposed to "1 of 3," or "2 of 3".

			oTabEl.setAttribute("role", "presentation");

			oTabAnchor.setAttribute("role", "tab");

			//	JAWS announces the value of the "href" attribute of each Tab's &#60;A&#62;
			//	element when it recieves focus.  Ideally JAWS would allow the
			//	applied "role" attribute of "tab" to take precedence over the default
			//  role of the &#60;A&#62; element like NVDA and Window-Eyes do.  It is
			//	possible to fix this problem by removing the "href" attribute from
			//	the &#60;A&#62;.

			oTabAnchor.removeAttribute("href");

			oTabContentEl = oTab.get("contentEl");

			oTabContentEl.setAttribute("role", "tabpanel");

			//	Set the "aria-labelledby" attribute for the TabPanel &#60;LI&#62; element to
			//	the id of its corresponding Tab's &#60;A&#62; element.  Doing so enables the
			//	screen reader to announce the label of the Tab for each TabPanel when
			//	the first element in a TabPanel receives focus, providing the user
			//	with some context as to where they are.

			oTabContentEl.setAttribute("aria-labelledby", sTabId);

		}

		//	Add a keypress listener that toggles the active Tab instance when the user
		//	presses the Enter key.  This is necessary because the removal of the "href"
		//	attribute from each Tab's &#60;A&#62; element (for JAWS support) causes the
		//	TabView's default Enter key support to stop working.  Support for the Space
		//	Bar is also added as an additional convience for the user.

		this.on("keypress", function (event) {

			var oTabAnchor = getTabAnchor(Event.getTarget(event)),
				nCharCode = Event.getCharCode(event);

			if (oTabAnchor &#038;&#038;
				(nCharCode === 13 || nCharCode === 32) &#038;&#038;
				(oTabAnchor.parentNode !== this.get("activeTab").get("element"))) {

					this.set("activeIndex", oTabIndexMap[oTabAnchor.id]);

			}

		});

	}

};</pre>
<h4>Step 4: Putting It All Together</h4>
<p>
To test the new <code>enhanceAccessibility</code> method, we'll use the<br />
<a href="http://developer.yahoo.com/yui/examples/tabview/datasrc.html">Getting Content from an<br />
External Source example</a> from the existing TabView examples gallery as a starting point.<br />
Once the TabView instance has been appended to the page, we'll call the new<br />
<code>enhanceAccessibility</code> method.  Next we'll use some additional WAI-ARIA Roles and States<br />
to make some example-specific tweaks.  First we'll, use the<br />
<a href="http://www.w3.org/TR/wai-aria/#describedby"><code>describedby</code></a> </p>
<p>property to provide some helpful instructional text that will be announced to the user<br />
when the TabView initially receives focus.  Since each Tab's content is loaded asynchronously, we'll<br />
also leverage<br />
<a href="http://www.w3.org/WAI/PF/aria-practices/#LiveRegions">WAI-ARIA Live Regions</a> to<br />
message users when a Tab's content is both being loaded and has finished loading.<br />
(Note: The <code>describedby</code> property and Live Regions are currently only supported in the<br />
<a href="http://www.nvda-project.org/wiki/Snapshots">latest development snapshots of NVDA</a>.)<br />
The following code snippet illustrates how it all comes together:
</p>
<pre>(function() {

	var oTabView = new YAHOO.widget.TabView();

	oTabView.addTab( new YAHOO.widget.Tab({
		label: "Opera",
		content: "&#60;p&#62;Please wait.  Content loading.&#60;/p&#62;",
		dataSrc: "news.php?query=opera+browser",
		cacheData: true,
		active: true
	}));

	oTabView.addTab( new YAHOO.widget.Tab({
		label: "Firefox",
		content: "&#60;p&#62;Please wait.  Content loading.&#60;/p&#62;",
		dataSrc: "news.php?query=firefox+browser",
		cacheData: true
	}));

	oTabView.addTab( new YAHOO.widget.Tab({
		label: "Explorer",
		content: "&#60;p&#62;Please wait.  Content loading.&#60;/p&#62;",
		dataSrc: "news.php?query=microsoft+explorer+browser",
		cacheData: true
	}));

	oTabView.addTab( new YAHOO.widget.Tab({
		label: "Safari",
		content: "&#60;p&#62;Please wait.  Content loading.&#60;/p&#62;",
		dataSrc: "news.php?query=apple+safari+browser",
		cacheData: true
	}));

	oTabView.appendTo("container");
	oTabView.enhanceAccessibility();

	var Dom = YAHOO.util.Dom,
		UA = YAHOO.env.ua,
		oActiveTab,
		oTitle,
		oTabViewEl,
		oLog,
		sInstructionalText;

	//	Only apply the WAI-ARIA Roles and States for FF 3 and IE 8 since those
	//	are the only browsers that currently support ARIA.

	if ((UA.gecko &#038;&#038; UA.gecko >= 1.9) || (UA.ie &#038;&#038; UA.ie >= 8)) {

		oActiveTab = oTabView.get("activeTab");

		//	Append some instructional text to the &#60;H2&#62;

		oTitle = Dom.get("tabview-title");

		sInstructionalText = oTitle.innerHTML;

		oTitle.innerHTML = (sInstructionalText + "&#60;em id=\"tabview-description\"&#62;Press the space bar or enter key to load the content of each tab.&#60;/em&#62;");

		//	Set the "aria-describedby" attribute of the &#60;UL&#62; with the role of "tablist"
		//	to the id of the &#60;EM&#62; inside the &#60;H2&#62;.  This will trigger the screen reader
		//	to read the text of the &#60;EM&#62; when the TabView is initially focused,
		//	providing some additional instructional text to the user.  (Currently this
		//	only works with the NVDA screen reader.)

		Dom.getChildren(oTabView.get("element"))[0].setAttribute("aria-describedby", "tabview-description");

		//	Append a live region to the TabView's root element that will be used to
		//	message users about the status of the TabView.

		oTabViewEl = oTabView.get("element");
		oLog = oTabViewEl.ownerDocument.createElement("div");

		oLog.setAttribute("role", "log");
		oLog.setAttribute("aria-live", "polite");

		oTabViewEl.appendChild(oLog);

		//	"activeTabChange" event handler used to notify the screen reader that
		//	the content of the Tab is loading.

		oTabView.on("activeTabChange", function (event) {

			var oTabEl = this.get("activeTab").get("element"),
				sTabLabel = oTabEl.textContent || oTabEl.innerText,
				oCurrentMessage = Dom.getFirstChild(oLog),
				oMessage = oLog.ownerDocument.createElement("p");

			oMessage.innerHTML = "Please wait.  Content loading for " + sTabLabel + " property page.";

			if (oCurrentMessage) {
				oLog.replaceChild(oMessage, oCurrentMessage);
			}
			else {
				oLog.appendChild(oMessage);
			}

		});	

		//	"dataLoadedChange" event handler used to notify the screen reader that
		//	the content of the Tab has finished loading.

		var onDataLoadedChange = function (event) {

			var oTabEl = this.get("element"),
				sTabLabel = oTabEl.textContent || oTabEl.innerText,
				oCurrentMessage = Dom.getFirstChild(oLog),
				oMessage = oLog.ownerDocument.createElement("p");

			oMessage.innerHTML = "Content loaded for " + sTabLabel + " property page.";

			if (oCurrentMessage) {
				oLog.replaceChild(oMessage, oCurrentMessage);
			}
			else {
				oLog.appendChild(oMessage);
			}

		};

		oTabView.getTab(0).on("dataLoadedChange", onDataLoadedChange);
		oTabView.getTab(1).on("dataLoadedChange", onDataLoadedChange);
		oTabView.getTab(2).on("dataLoadedChange", onDataLoadedChange);
		oTabView.getTab(3).on("dataLoadedChange", onDataLoadedChange);

	}

})();</pre>
<h3>Further Reading and Resources</h3>
<ul>
<li><a href="http://yuiblog.com/blog/2007/12/21/menu-waiaria/">Using WAI-ARIA Roles and States with the YUI Menu Control</a></li>
<li><a href="http://www.w3.org/TR/wai-aria/">Accessible Rich Internet Applications (WAI-ARIA) Version 1.0 W3C Specification</a></li>
<li><a href="http://www.w3.org/TR/wai-aria-practices/">WAI-ARIA Best Practices</a></li>
<li><a href="http://developer.mozilla.org/en/docs/ARIA:_Accessible_Rich_Internet_Applications/Relationship_to_HTML_FAQ">ARIA: Accessible Rich Internet Applications/Relationship to HTML FAQ</a></li>
<li><a href="http://www.mozilla.org/access/dhtml/">Accessible DHTML</a></li>
<li><a href="http://developer.mozilla.org/en/docs/Key-navigable_custom_DHTML_widgets">Key-navigable custom DHTML widgets</a></li>
<li><a href="http://www.mozilla.com/en-US/firefox/">Firefox 3</a></li>
<li><a href="http://www.microsoft.com/windows/products/winfamily/ie/ie8/getitnow.mspx">Internet Explorer 8 Beta 1</a></li>
<li><a href="http://www.nvda-project.org/">NVDA Screen Reader</a></li>
<li><a href="http://www.freedomscientific.com/fs_products/software_jaws.asp">Freedom Scientific JAWS Screen Reader</a></li>
<li><a href="http://www.gwmicro.com/Window-Eyes/">GW Micro Window-Eyes Screen Reader</a></li>
<li><a href="http://video.yahoo.com/video/play?vid=514676">An Introduction to Screen Readers</a></li>
<li><a href="http://juicystudio.com/article/making-ajax-work-with-screen-readers.php">Making Ajax Work with Screen Readers</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/07/30/tabview-aria/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
<enclosure url="http://yuiblog.com/assets/tabviewscreencast.mov" length="710785" type="video/quicktime" />
		</item>
		<item>
		<title>Context Menus and Focus in Opera</title>
		<link>http://www.yuiblog.com/blog/2008/07/17/context-menus-and-focus-in-opera/</link>
		<comments>http://www.yuiblog.com/blog/2008/07/17/context-menus-and-focus-in-opera/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 00:46:21 +0000</pubDate>
		<dc:creator>Todd Kloots</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/07/17/context-menus-and-focus-in-opera/</guid>
		<description><![CDATA[ As a JavaScript toolkit developer, there are two features lacking in Opera that have frustrated me for a while: support for the contextmenu DOM event and the ability to override the default rendering of focus via CSS.  When Opera released version 9.5, I was disappointed to see that neither of these features were [...]]]></description>
			<content:encoded><![CDATA[<p> As a JavaScript toolkit developer, there are two features lacking in Opera that have frustrated me for a while: support for the <code>contextmenu</code> DOM event and the ability to override the default rendering of focus via CSS.  When Opera released version 9.5, I was disappointed to see that neither of these features were implemented. As frontend engineers, we spend a lot of time responding to decisions made by browser manufacturers, but we don&#8217;t get much opportunity to learn the specific thought process behind those decisions. After exchanging some emails with the Opera team, I now have some insight into their decisions and the perspective that perhaps withholding such features could be beneficial to the user.</p>
<h3>Background</h3>
<p> Although the capabilities of the browser have evolved significantly in recent years, the user&#8217;s perception of the browser hasn&#8217;t necessarily evolved with it.  After the launch of Yahoo! Photos 3.0, I remember a friend of mine emailing me because she was having trouble viewing the large version of her photos.  She was repeatedly clicking on each thumbnail without success.  Eventually she figured out that she needed to double click on the thumbnails to view the full size image.  Double clicking to open a folder or a file is, of course, a natural interaction on the desktop, but for years users were trained not to expect this interaction in the context of web applications. </p>
<p> Some users still don&#8217;t expect desktop-like interaction from web applications.  I remember logging into my Yahoo! Mail not long ago and seeing checkboxes next to each message.  I paused.  What were these checkboxes, these artifacts of Web 1.0, doing in my Web 2.0 application?  I had been using the new DHTML, Outlook-like version of Yahoo! Mail since its early beta and had become used to dragging and dropping in order to move and delete messages.  But the reappearance of these checkboxes was another sign that not every user&#8217;s expectations had evolved with the capabilities of the browser. </p>
<p> As the browser has matured it has evolved it into a platform for rich application development, making it possible to deliver applications with a level of interactivity and visual fidelity of those found on the desktop.  And while the browser is now a platform, it also continues to play its original Web 1.0 role of an application, a content viewer that enables users to surf all of the news sites, blogs, etc. scattered across the eclectic Web.  But as the browser now plays these dual roles of being an application and an application development and delivery platform, how does this duality impact the user in terms of usability and accessibility?  And what user-centric features and functionality can consumers expect of a browser, especially one battling with duality?  I suspect that Opera&#8217;s answer to these questions is that not all users understand the modern browser&#8217;s dual role, and that is it necessary to render some fundamental things consistently across experiences within the browser. </p>
<h3>Context Menus</h3>
<p> <a href="http://developer.yahoo.com/yui/examples/menu/contextmenu_source.html"><img src="http://yuiblog.com/assets/klootsopera/contextmenu.gif" alt="The YUI Menu Control's ContextMenu in Safari (top) and Opera (bottom); Opera does not allow developers to customize the context menu in web applications." width="280" height="300" hspace="10" vspace="5" align="right"></a></p>
<p>Consider context menu functionality. By not implementing the <code>contextmenu</code> event, Opera does not allow frontend engineers to override the<br />
default context menu provided by the browser; all other <a href="http://developer.yahoo.com/yui/articles/gbs/">A-Grade browsers</a> support this feature. What benefit could there be to not implementing the <code>contextmenu</code> event?</p>
<p>If some users  perceive everything inside the scope of the browser as a web page, that influences the user&#8217;s expectation of what functionality will be surfaced in a context menu.  Over the years many users have come to expect that raising a context menu in the scope of a browser will surface browser-centric functionality relative to HTML content (i.e. &#8220;Open Link in New Window&#8221;), rather than functionality of the web application running within the browser.  Therefore, providing a custom context menu for a web application might not be expected or seen as helpful for users who have come to rely on functionality in the browser&#8217;s context menu.</p>
<p>The downside is that, by not allowing the developer to provide custom context menu implementations (such as those provided by the <a href="http://developer.yahoo.com/yui/menu/">YUI Menu Control</a>), Opera is in a small way preventing the user from understanding the browser as a platform for rich application development. </p>
<h3>Focus</h3>
<p>Focus could be considered as sacred as the context menu. Knowing what element has focus is fundamental to keyboard accessibility. And while most modern browsers support customization of the rendering of focus, is it a good idea to do so?  The presentation and behavior is of HTML is now so completely customizable via CSS and JavaScript that the user experience can differ drastically across sites and applications on the web.  Keeping something as fundamental as focus consistent means one less thing the user has to re-learn when navigating the across the web.  Consider the following example: </p>
<h4><a href="http://yuiblog.com/sandbox/yui/v252/examples/button/example10.html#example-1">Example 1: Anchor Elements (The Good)</a></h4>
<table>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/anchor.png" height="25" width="51" alt="Screen capture of a focused anchor in Opera 9.5 for Mac"></td>
<td>Focused anchor in Opera 9.5 (Mac)</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/link-button.png" height="34" width="69" alt="Screen capture of a focused anchor styled as a button in Opera 9.5 for Mac"></td>
<td>Focused anchor styled as a button in Opera 9.5 (Mac)</td>
</tr>
</table>
<p> This example illustrates how the focused state of an anchor element is rendered consistently in Opera regardless of how it is styled.  This consistency can be considered helpful to the user in that the familiarity of the focus outline conveys the element&#8217;s role.  Therefore, the user knows what to expect when the element is clicked regardless of how it is styled.  However, as illustrated in the following example, this benefit breaks down a little as the focus model for buttons isn&#8217;t the same as it is for anchor elements.</p>
<h4><a href="http://yuiblog.com/sandbox/yui/v252/examples/button/example10.html#example-2">Example 2: Buttons (The Bad)</a></h4>
<table>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/button-1.png" height="24" width="69" alt="Screen capture of a focused button in Opera 9.5 for Mac"></td>
<td>Focused, unstyled button in Opera 9.5 (Mac)</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/button-2.png" height="26" width="70" alt="Screen capture of a focused, styled button in Opera 9.5 for Mac"></td>
<td>Focused, styled button in Opera 9.5 (Mac)</td>
</tr>
</table>
<p> This example illustrates a potential flaw in Opera&#8217;s rendering of focus in version 9.5: unlike anchor elements, unstyled and styled buttons get two different renderings of focus, both of which are completely different, and different from the focus style applied to anchor elements.  So, in Opera 9.5 there are three different focus implementations for the user to learn: the system default, the Wii-style focus and the dotted border.  Compare Opera&#8217;s focus implementation to that of Safari or Internet Explorer, where by default focus is rendered consistently across elements of various types. </p>
<table>
<thead>
<tr>
<th>Opera</th>
<th>Safari</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/anchor.png" height="25" width="51" alt="Screen capture of a focused anchor in Opera 9.5 for Mac"></td>
<td><img src="http://yuiblog.com/assets/klootsopera/anchor-safari.png" height="25" width="51" alt="Screen capture of a focused anchor in Safari for Mac"></td>
<td>Focused, unstyled acnhor</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/link-button.png" height="34" width="69" alt="Screen capture of a focused anchor styled as a button in Opera 9.5 for Mac"></td>
<td><img src="http://yuiblog.com/assets/klootsopera/anchor-button-safari.png" height="34" width="69" alt="Screen capture of a focused anchor styled as a button in Safari for Mac"></td>
<td>Focused anchor styled as a button</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/button-1.png" height="24" width="69" alt="Screen capture of a focused, unstyled button in Opera 9.5 for Mac"></td>
<td><img src="http://yuiblog.com/assets/klootsopera/button-safari.png" height="24" width="67" alt="Screen capture of a focused, unstyled button in Safari for Mac"></td>
<td>Focused, unstyled button</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/button-2.png" height="26" width="70" alt="Screen capture of a focused, styled button in Opera 9.5 for Mac"></td>
<td><img src="http://yuiblog.com/assets/klootsopera/yuibutton-safari.png" height="34" width="81" alt="Screen capture of a focused, styled button in Safari for Mac"></td>
<td>Focused, styled button</td>
</tr>
</tbody>
</table>
<p> Since the default implementation of focus can be customized in other browsers, perhaps Opera users still fair better since learning Opera&#8217;s three, fixed focus models is ultimately better than having to learn potentially infinitely more.  That said, if Opera is going to prevent customization of focus in the interest of usability and accessibility, they could further improve the user experience by providing a consistent implementation of focus across elements. As it stands in Opera 9.5, the following mixed styles can appear together, presenting a  confusing set of visual cues:</p>
<h4><a href="http://yuiblog.com/sandbox/yui/v252/examples/button/example10.html#example-3">Example 3: Mixed types together (The Ugly)</a></h4>
<table>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/link-button.png" height="34" width="69" alt="Screen capture of a focused anchor styled as a button in Opera 9.5 for Mac"></td>
<td>Focused anchor styled as a button in Opera 9.5 (Mac)</td>
</tr>
<tr>
<td><img src="http://yuiblog.com/assets/klootsopera/button-4.png" height="26" width="70" alt="Screen capture of a focused, styled button in Opera 9.5 for Mac"></td>
<td>Focused, styled button in Opera 9.5 (Mac)</td>
</tr>
</table>
<p> As illustrated by the first and second examples, Opera has three different, yet fixed implementations of focus.  While Opera&#8217;s implementation of focus can be considered good insofar as the user only has a limited number of focus models to learn, it might also be considered bad in that it makes it harder to provide a consistent user experience within a single site or web application.  For example, if you wanted to place an anchor and button next to each other in a toolbar, but style them consistently so that they both look like buttons, each would still render focus differently in Opera, leaving the user to wonder how the difference is significant. </p>
<h3>Conclusion</h3>
<p> In Opera designers and developers lose a degree of customization, but the user gains a slightly more consistent browsing experience. In some ways this consistency benefits the user in that fundamental interactions like focus and context menus remain the same regardless of the site or web application in use.  However, by limiting certain types of customization designers and developers will find it just a bit harder to provide a consistent user experience within their site or application and to train the user to expect more from Web 2.0. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/07/17/context-menus-and-focus-in-opera/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Unobtrusive Rollovers Using YUI</title>
		<link>http://www.yuiblog.com/blog/2008/04/28/unobtrusive-rollovers-using-yui/</link>
		<comments>http://www.yuiblog.com/blog/2008/04/28/unobtrusive-rollovers-using-yui/#comments</comments>
		<pubDate>Tue, 29 Apr 2008 00:12:41 +0000</pubDate>
		<dc:creator>Eric Miraglia</dc:creator>
				<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[2tbsp.com]]></category>
		<category><![CDATA[christian heilmann]]></category>
		<category><![CDATA[rollovers]]></category>
		<category><![CDATA[unobtrusive javascript]]></category>

		<guid isPermaLink="false">http://yuiblog.com/blog/2008/04/28/unobtrusive-rollovers-using-yui/</guid>
		<description><![CDATA[
Chad at 2tbsp.com wrote up a nice tutorial last week outlining some practical fundamentals with respect to writing &#34;unobtrusive JavaScript.&#34; His example implements a standard rollover, beginning with bad-old-days obtrusive scripting, migrating to unobtrusive scripting, and concluding with an unobtrusive script that leverages YUI&#8217;s Event Utility for event attachment and the Dom Collection&#8217;s getElementsByClassName, addClass [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://2tbsp.com/node/91"><img src="http://yuiblog.com/assets/2tbsp-1.png" alt="Introduction to Unobtrusive JavaScript, DOM Scripting, and the Yahoo! User Interface (YUI) Library on 2tsp.com." width="510" height="174"></a></p>
<p>Chad at 2tbsp.com <a href="http://2tbsp.com/node/91">wrote up a nice tutorial last week</a> outlining some practical fundamentals with respect to writing &quot;unobtrusive JavaScript.&quot; His example implements a standard rollover, beginning with bad-old-days obtrusive scripting, migrating to unobtrusive scripting, and concluding with an unobtrusive script that leverages YUI&#8217;s <a href="http://developer.yahoo.com/yui/event/">Event Utility</a> for event attachment and the <a href="http://developer.yahoo.com/yui/dom/">Dom Collection</a>&#8217;s <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html#method_getElementsByClassName"><code>getElementsByClassName</code></a>, <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html#method_addClass"><code>addClass</code></a> and <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Dom.html#method_removeClass"><code>removeClass</code></a> for class management.</p>
<p><a href="http://2tbsp.com/system/files/yui-rollover.html">Click through</a> for his functioning example.</p>
<p><a href="http://2tbsp.com/system/files/yui-rollover.html"><img src="http://yuiblog.com/assets/2tbsp-2.png" alt="Click through for the functioning example." width="510" height="96"></a></p>
<p>Of course, Chad just means this as an example of some of the practical points involved in unobtrusive scripting. Others have looked at the problem more encyclopedically — for a more ambitious (and not YUI-related) analysis of the paradigm, check out Christian Heilmann&#8217;s &quot;<a href="http://icant.co.uk/articles/seven-rules-of-unobtrusive-javascript/">The seven rules of Unobtrusive JavaScript</a>&quot;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.yuiblog.com/blog/2008/04/28/unobtrusive-rollovers-using-yui/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
