Accessibility Examples
Example Start
Sandwich Condiments
-
All condiments
-
Lettuce
-
Tomato
-
Mustard
-
Sprouts
Not your average lettuce
Organically grown beef steak tomatos
Brown and spicy mustard
Fresh alfalfa sprouts, organically grown
Example End
Example Description
Type: Best Practice
Simple example of a checkbox group using inline images to display the visual state of the boxes in the group.
Keyboard Support
- Tab: Move between button items and text area.
- Enter or space: Toggle aria-checked state of checkbox with keyboard focus.
Example Markup
- ARIA 1.0: [aria-checked]
- ARIA 1.0: [aria-describedby]
- ARIA 1.0: [aria-labelledby]
- ARIA 1.0: [role="checkbox"]
- ARIA 1.0: [role="group"]
- ARIA 1.0: [role="presentation"]
Browser Compatibility
- osx: Firefox 3.6 (C)
- osx: Opera 11.0 (C)
- osx: Safari 5.0 (C)
- win: Firefox 3.6 (C)
- win: Internet Explorer 8.0 (C)
- win: Opera 11.0 (C)
- win: Safari 5.0 (C)
HTML Source Code
<div role="application">
<h3 id="cond">Sandwich Condiments</h3>
<ul id="cb1" class="checkboxes" role="group" aria-labelledby="cond">
<li id="cb1all"
role="checkbox"
class="groupbox"
aria-checked="mixed"
tabindex="0">
<img src="http://www.oaa-accessibility.org/media/examples/images/checkbox-mixed-black.png" role="presentation">
All condiments
</li>
<li id="cb1a"
role="checkbox"
class="checkbox"
aria-checked="false"
aria-describedby="desc1"
tabindex="0">
<img src="http://www.oaa-accessibility.org/media/examples/images/checkbox-unchecked-black.png" role="presentation">
Lettuce
</li>
<li id="cb1b"
role="checkbox"
class="checkbox"
aria-checked="true"
aria-describedby="desc2"
tabindex="0">
<img src="http://www.oaa-accessibility.org/media/examples/images/checkbox-checked-black.png" role="presentation">
Tomato
</li>
<li id="cb1c"
role="checkbox"
class="checkbox"
aria-checked="true"
aria-describedby="desc3"
tabindex="0">
<img src="http://www.oaa-accessibility.org/media/examples/images/checkbox-checked-black.png" role="presentation">
Mustard
</li>
<li id="cb1d"
role="checkbox"
class="checkbox"
aria-checked="true"
aria-describedby="desc4"
tabindex="0">
<img src="http://www.oaa-accessibility.org/media/examples/images/checkbox-checked-black.png" role="presentation">
Sprouts
</li>
</ul>
<p id="desc1" class="hidden">Not your average lettuce</p>
<p id="desc2" class="hidden">Organically grown beef steak tomatos</p>
<p id="desc3" class="hidden">Brown and spicy mustard</p>
<p id="desc4" class="hidden">Fresh alfalfa sprouts, organically grown</p>
</div>
CSS Code
ul.checkboxes {
margin: 0;
padding: 0;
}
ul.checkboxes li img {
margin-right: .5em;
}
li.groupbox {
margin-left: 1em;
padding: 0;
padding-left: .5em;
list-style: none;
width: 7.5em;
border: 2px solid transparent;
}
li.checkbox {
margin-left: 2.5em;
padding: 0;
padding-left: .5em;
list-style: none;
width: 7em;
border: 2px solid transparent;
}
li.hover {
border: 2px solid #777;
}
li.focus {
border: 2px solid black;
}
.hidden {
position: absolute;
top: -30em;
left: -300em;
}
Javascript Source Code
var KEY_SPACE = 32;
$(document).ready(function() {
var checkboxGroupApp = new checkboxGroup("cb1");
}); // end ready event
//
// Function keyCodes() is an object to contain keycodes needed for the application
//
function keyCodes() {
this.space = 32;
}
//
// Function checkboxGroup() is a class constructor for the implementation of a checkbox group widget.
// checkboxGroup() requires an unordered list structure, with the first list entry being the group
// checkbox and the remaining entries being the checkboxes controlled by the group. Each list entry
// must contain an image tag that will be used to display the state of the checkbox.
//
// @param(list string) list is the id of the unordered list that checkboxgroup is to be bound to
//
// @return N/A
//
function checkboxGroup(list) {
// define object properties
this.$id = $('#' + list);
this.keys = new keyCodes();
this.unchecked = 0;
this.checked = 1;
this.mixed = 2;
this.$groupBox = this.$id.find('li').first();
this.$checkboxes = this.$groupBox.siblings();
this.checkedCount = 0; // set to the number of checkboxes that are checked
// initialize the checkboxGroup object
this.init();
// bind event handlers
this.bindHandlers();
} // end checkboxGroup() constructor
// Function init() is a member function to initialize the checkboxGroup object. Initial checkbox
// states are set according to the aria-checked property of the checkboxes in the group.
//
// return N/A
//
checkboxGroup.prototype.init = function() {
var thisObj = this;
this.$checkboxes.each(function() {
if ($(this).attr('aria-checked') == 'true') {
thisObj.adjCheckedCount(true);
}
});
} // end init()
//
// Function bindHandlers() is a member function to bind event handlers to the checkboxes in the
// checkbox group.
//
// @return N/A
//
checkboxGroup.prototype.bindHandlers = function() {
var thisObj = this;
/////////// Bind groupbox handlers ////////////////
// bind a click handler
this.$groupBox.click(function(e) {
return thisObj.handleGroupboxClick($(this), e);
});
// bind a keydown handler
this.$groupBox.keydown(function(e) {
return thisObj.handleGroupboxKeyDown($(this), e);
});
// bind a keypress handler
this.$groupBox.keypress(function(e) {
return thisObj.handleBoxKeyPress($(this), e);
});
// bind a mouseover handler
this.$groupBox.mouseover(function(e) {
return thisObj.handleBoxMouseOver($(this), e);
});
// bind a mouseout handler
this.$groupBox.mouseout(function(e) {
return thisObj.handleBoxMouseOut($(this), e);
});
// bind a focus handler
this.$groupBox.focus(function(e) {
return thisObj.handleBoxFocus($(this), e);
});
// bind a blur handler
this.$groupBox.blur(function(e) {
return thisObj.handleBoxBlur($(this), e);
});
/////////// Bind checkbox handlers ////////////////
// bind a click handler
this.$checkboxes.click(function(e) {
return thisObj.handleCheckboxClick($(this), e);
});
// bind a keydown handler
this.$checkboxes.keydown(function(e) {
return thisObj.handleCheckboxKeyDown($(this), e);
});
// bind a keypress handler
this.$checkboxes.keypress(function(e) {
return thisObj.handleBoxKeyPress($(this), e);
});
// bind a mouseover handler
this.$checkboxes.mouseover(function(e) {
return thisObj.handleBoxMouseOver($(this), e);
});
// bind a mouseout handler
this.$checkboxes.mouseout(function(e) {
return thisObj.handleBoxMouseOut($(this), e);
});
// bind a focus handler
this.$checkboxes.focus(function(e) {
return thisObj.handleBoxFocus($(this), e);
});
// bind a blur handler
this.$checkboxes.blur(function(e) {
return thisObj.handleBoxBlur($(this), e);
});
} // end bindHandlers()
// Function setBoxState() is a member function to set a checkbox state. This function sets the
// aria-checked property to the passed state value and changes the box image to display the new
// box state.
//
// @param($boxID object) $boxID is the jquery object of the checkbox to manipulate
//
// @param(state integer) state is the check state to set the box
//
// @return N/A
//
checkboxGroup.prototype.setBoxState = function($boxID, state) {
var $img = $boxID.find('img');
switch (state) {
case this.unchecked: {
$boxID.attr('aria-checked', 'false');
$img.attr('src','http://www.oaa-accessibility.org/media/examples/images/checkbox-unchecked-black.png');
break;
}
case this.checked: {
$boxID.attr('aria-checked', 'true');
$img.attr('src','http://www.oaa-accessibility.org/media/examples/images/checkbox-checked-black.png');
break;
}
case this.mixed: {
$boxID.attr('aria-checked', 'mixed');
$img.attr('src','http://www.oaa-accessibility.org/media/examples/images/checkbox-mixed-black.png');
break;
}
} // end switch
} // end setBoxState()
//
// Function adjCheckedCount() is a member function to increment or decrement the count of checked
// boxes. The function modifies the checkes state of the group box accordingly.
//
// @param(inc boolean) inc is true if incrementing the checked count, false if decrementing
//
// @return N/A
//
checkboxGroup.prototype.adjCheckedCount = function(inc) {
// increment or decrement the count
if (inc == true) {
this.checkedCount++;
}
else {
this.checkedCount--;
}
// modify the group box state
if (this.checkedCount == this.$checkboxes.length) {
// all the boxes are checked
this.setBoxState(this.$groupBox, this.checked);
}
else if (this.checkedCount > 0) {
// some of the boxes are checked
this.setBoxState(this.$groupBox, this.mixed);
}
else {
// all boxes are unchecked
this.setBoxState(this.$groupBox, this.unchecked);
}
} // end adjCheckedCount()
/////////////////////// Groupbox event handlers /////////////////////////////////
//
// Function handleGroupboxClick() is a member function to handle click events for group checkbox
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the keydown event
//
// @return (boolean) Returns false if processing; true of doing nothing
//
checkboxGroup.prototype.handleGroupboxClick = function($id, e) {
var thisObj = this;
if (e.altkey || e.ctrlKey || e.shiftKey) {
// do nothing;
return true;
}
switch ($id.attr('aria-checked')) {
case 'true' : {
// uncheck the group
// clear the groupbox
this.setBoxState($id, this.unchecked);
// clear all the checkboxes in the group
this.$checkboxes.each(function() {
// clear the groupbox
thisObj.setBoxState($(this), thisObj.unchecked);
});
// reset the checked count
this.checkedCount = 0;
break;
}
case 'mixed' :
case 'false' : {
// check the group
// set the groupbox to checked
this.setBoxState($id, this.checked);
// check all the checkboxes in the group
this.$checkboxes.each(function() {
// clear the groupbox
thisObj.setBoxState($(this), thisObj.checked);
});
// set the checked count
this.checkedCount = this.$checkboxes.length;
break;
}
} // end switch
e.stopPropagation();
return false;
} // end handleGroupboxClick()
//
// Function handleGroupboxKeyDown() is a member function to handle keydown events for the group checkbox
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the keydown event
//
// @return (boolean) Returns false if processing; true of doing nothing
//
checkboxGroup.prototype.handleGroupboxKeyDown = function($id, e) {
var thisObj = this;
if (e.altkey || e.ctrlKey || e.shiftKey) {
// do nothing;
return true;
}
if( e.keyCode == this.keys.space ) {
switch ($id.attr('aria-checked')) {
case 'true' : {
// uncheck the group
// clear the groupbox
this.setBoxState($id, this.unchecked);
// clear all the checkboxes in the group
this.$checkboxes.each(function() {
// clear the groupbox
thisObj.setBoxState($(this), thisObj.unchecked);
});
// reset the checked count
this.checkedCount = 0;
break;
}
case 'mixed' :
case 'false' : {
// check the group
// set the groupbox to checked
this.setBoxState($id, this.checked);
// check all the checkboxes in the group
this.$checkboxes.each(function() {
// clear the groupbox
thisObj.setBoxState($(this), thisObj.checked);
});
// set the checked count
this.checkedCount = this.$checkboxes.length;
break;
}
} // end switch
e.stopPropagation();
return false;
} // endif
return true;
} // end handleGroupboxKeyDown()
/////////////////////// Checkbox event handlers /////////////////////////////////
//
// Function handleCheckboxClick() is a member function to handle click events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the keydown event
//
// @return (boolean) Returns false if processing; true of doing nothing
//
checkboxGroup.prototype.handleCheckboxClick = function($id, e) {
if (e.altkey || e.ctrlKey || e.shiftKey) {
// do nothing;
return true;
}
// toggle the checkbox state
if($id.attr('aria-checked') == 'true') {
this.setBoxState($id, this.unchecked);
this.adjCheckedCount(false);
} else {
this.setBoxState($id, this.checked);
this.adjCheckedCount(true);
} // endif
e.stopPropagation();
return false;
} // end handleCheckboxClick()
//
// Function handleCheckboxKeyDown() is a member function to handle keydown events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the keydown event
//
// @return (boolean) Returns false if processing; true of doing nothing
//
checkboxGroup.prototype.handleCheckboxKeyDown = function($id, e) {
if (e.altkey || e.ctrlKey || e.shiftKey) {
// do nothing;
return true;
}
if( e.keyCode == this.keys.space ) {
// toggle the checkbox state
if($id.attr('aria-checked') == 'true') {
this.setBoxState($id, this.unchecked);
this.adjCheckedCount(false);
} else {
this.setBoxState($id, this.checked);
this.adjCheckedCount(true);
} // endif
e.stopPropagation();
return false;
} // endif
return true;
} // end handleCheckboxKeyDown()
////////////////////////////////// Common event handlers ///////////////////////////////////
//
// Function handleBoxKeyPress() is a member function to handle keypress events for checkboxes
// This function is needed to consume events for browsers, such as Opera, that perform window
// manipulation on keypress events.
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the keydown event
//
// @return (boolean) Returns false if processing; true of doing nothing
//
checkboxGroup.prototype.handleBoxKeyPress = function($id, e) {
if (e.altkey || e.ctrlKey || e.shiftKey) {
// do nothing;
return true;
}
if( e.keyCode == this.keys.space ) {
// consume the event
e.stopPropagation();
return false;
} // endif
return true;
} // end handleBoxKeyPress()
//
// Function handleBoxMouseOver() is a member function to handle mouseover events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the mouseover event
//
// @return (boolean) Returns false;
//
checkboxGroup.prototype.handleBoxMouseOver = function($id, e) {
// if the box does not have the focus class add the hover highlight
if ($id.not('.focus')) {
$id.addClass('hover');
}
e.stopPropagation();
return false;
} // end handleBoxMouseOver()
//
// Function handleBoxMouseOut() is a member function to handle mouseout events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the mouseout event
//
// @return (boolean) Returns false;
//
checkboxGroup.prototype.handleBoxMouseOut = function($id, e) {
$id.removeClass('hover');
e.stopPropagation();
return false;
} // end handleBoxMouseOut()
//
// Function handleBoxFocus() is a member function to handle focus events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the focus event
//
// @return (boolean) Returns true;
//
checkboxGroup.prototype.handleBoxFocus = function($id, e) {
$id.addClass('focus');
// remove the hover class if it is applied
$id.removeClass('hover');
return true;
} // end handleBoxFocus()
//
// Function handleBoxBlur() is a member function to handle blur events for checkboxes
//
// @param ($id object) $id is the jquery object of the checkbox
//
// @param (e object) e is the event object associated with the blur event
//
// @return (boolean) Returns true;
//
checkboxGroup.prototype.handleBoxBlur = function($id, e) {
$id.removeClass('focus');
return true;
} // end handleBoxBlur()