Re: Keyboard accessibility of More Options

On Mon, Dec 18, 2006 at 06:53:38PM +0000, Patrick H. Lauke wrote:
> * There seems to be no way to get to the "More Options" pseudo-link via 
> the keyboard

> * With javascript off, those "More Options" pseudo-links are still 
> present, but useless.

I don't consider myself a JavaScript expert, but I've attacked the
code to see if I could produce something that addresses this
issue. I'm not 100% happy with the result (which, BTW, is tested only
in Firefox), but I think that its an improvement, and can be built
upon.

First - changes to the template:

Previously:

   <fieldset id="extra_opt_uri" class="moreoptions">
   <p class="toggle closed" title="Show/Hide extra validation options">More Options</p>

After my changes:

   <fieldset id="extra_opt_uri" class="moreoptions alttoggle closed linkText_Show/Hide_extra_validation_options">
   <legend>More Options</legend>

The paragraph has been removed (it gets added before the fieldset
using JavaScript in my suggested changes).

A legend has been added. The DTD doesn't require a legend for
fieldsets in XHTML 1.0, but:

* HTML 4.01 does
* The change isn't documented in the list of changes in the XHTML 1.0 spec
* I'm told the RELAX schema for XHTML 1.0 requires it

... so I think its absence is a bug in the spec.

And then the  changed JavaScript:

// toggling event visibility
// v1.0 David Dorward for the W3C CSS Validation Service, 18/12/2006
// Based on v2.01 Kent Brewster, 6/8/2006 http://www.mindsack.com

// namespace protection: one global variable to rule them all
var W3C = {};
var W3C.QA = {};
var W3C.QA.Validator = {};
var W3C.QA.Validator.CSS = {};
W3C.QA.Validator.CSS.toggle = 
{	
	init : function(toggle, closed, hidden)
	{
		// three class names, fed in from init call
		this.toggleClass = toggle;
		this.toggleClosed = closed;
		this.toggleHidden = hidden;
		// crawl through the document, look for toggled elements
		this.crawl(document.body);
	},
	crawl : function(el)
	{
		// get this element's next sibling
		var nextSib = this.getNextSibling(el);
		
		// if it has a class name, the class name matches our toggle class
		if (el.className && el.className.match(this.toggleClass))
		{
			
			// Generate an element
			var paragraph = document.createElement('p');
			var link = document.createElement('a');
			var text = el.className.match(/linkText_(\S*)/)[1];
			text = text.replace("_", " ", "g");
			text = document.createTextNode(text);
			link.appendChild(text);
			link.href="#" + el.id;
			link.onclick = this.newToggleState(this,paragraph,el);
			paragraph.appendChild(link);
			el.parentNode.insertBefore(paragraph, el);

			// if the next sib ought to be hidden and it isn't already, hide it
			// you can hard-code class=hidden in the HTML if you like, and avoid the Flash of Unstyled Content
			if (el.className.match(this.toggleClosed))
			{
				el.className += ' ' + this.toggleHidden;
				//el.parentNode.className += ' ' + this.toggleClosed;
			}
		}
		
		// is there more to do? Do it, if so:
		if (el.firstChild) 
		{
    			this.crawl(el.firstChild);
  		}
		if (nextSib) 
		{
			this.crawl(nextSib);
		}
	},
	newToggleState : function(o,element,nextEl) {
		return function () { return o.toggleState(element,nextEl) };
	},
	toggleState : function(el,nextEl)
	{
		// there's got to be a way to get this without stating it explicitly
		var o = W3C.QA.Validator.CSS.toggle;
				
		// change the style of the triggering element
		if(el.className.match(o.toggleClosed))
		{
			el.className = el.className.replace(o.toggleClosed, '');
		}
		else
		{
			el.className = el.className + ' ' + o.toggleClosed;
		}
		
		// yes, we need to check if it's really there; other scripts could have removed it
		if(nextEl && nextEl.className.match('hidden'))
		{
			nextEl.className = nextEl.className.replace(o.toggleHidden, '');
		}
		else
		{
			nextEl.className += ' ' + o.toggleHidden;
		}
		return false;
	},
	getNextSibling : function(el)
	{
		var nextSib = el.nextSibling;
		
		// hack for Gecko browsers
		if (nextSib && nextSib.nodeType != 1)
		{
			nextSib = nextSib.nextSibling;
		}
		return nextSib;
	},
	getEl : function(v)
	{
		var tg = (v) ? v : event;
		var el = null;
		if (tg.target) 
		{
			el = (tg.target.nodeType == 3) ? tg.target.parentNode : tg.target;
		} 
		else 
		{ 
			el = tg.srcElement;
		}
		return el;
	}
};

// feed it the CSS class names of your choice
window.onload = function()
{ 
	W3C.QA.Validator.CSS.toggle.init('alttoggle', 'closed', 'hidden');
};


-- 
David Dorward                                      http://dorward.me.uk

Received on Monday, 18 December 2006 22:01:09 UTC