408 lines
9.5 KiB
HTML
408 lines
9.5 KiB
HTML
|
<html>
|
||
|
<head>
|
||
|
<style type="text/css">
|
||
|
ul.radiogroup {
|
||
|
margin: 0;
|
||
|
padding: 0;
|
||
|
}
|
||
|
|
||
|
ul.radiogroup li {
|
||
|
padding: 0;
|
||
|
margin: 0;
|
||
|
margin-left: 1em;
|
||
|
padding: 4px;
|
||
|
list-style: none;
|
||
|
width: 6em;
|
||
|
}
|
||
|
|
||
|
ul.radiogroup li:hover {
|
||
|
padding: 2px;
|
||
|
border: gray 2px solid;
|
||
|
}
|
||
|
|
||
|
ul.radiogroup li.selected {
|
||
|
padding: 2px;
|
||
|
border: black 2px solid;
|
||
|
}
|
||
|
|
||
|
.offscreen {
|
||
|
position: absolute;
|
||
|
left: -200em;
|
||
|
top: -20em;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
|
||
|
<div role="application">
|
||
|
|
||
|
<h3 id="rg1_label">Lunch Options</h3>
|
||
|
|
||
|
<ul class="radiogroup" id="rg1" role="radiogroup" aria-labelledby="rg1_label">
|
||
|
<li id="r1" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Thai
|
||
|
</li>
|
||
|
<li id="r2" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Subway
|
||
|
</li>
|
||
|
<li id="r3" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Jimmy Johns
|
||
|
</li>
|
||
|
<li id="r4" tabindex="0" role="radio" aria-checked="true">
|
||
|
<img role="presentation" src="radio-checked.gif" alt="">
|
||
|
Radio Maria
|
||
|
</li>
|
||
|
<li id="r5" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Rainbow Gardens
|
||
|
</li>
|
||
|
</ul>
|
||
|
<h3 id="rg2_label">Drink Options</h3>
|
||
|
|
||
|
<ul id="rg2" class="radiogroup" role="radiogroup" aria-labelledby="rg2_label">
|
||
|
<li id="r6" tabindex="0" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Water
|
||
|
</li>
|
||
|
<li id="r7" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Tea
|
||
|
</li>
|
||
|
<li id="r8" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Coffee
|
||
|
</li>
|
||
|
<li id="r9" tabindex="-1" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Cola
|
||
|
</li>
|
||
|
<li id="r10" tabindex="0" role="radio" aria-checked="false">
|
||
|
<img role="presentation" src="radio-unchecked.gif" alt="">
|
||
|
Ginger Ale
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
</div>
|
||
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
||
|
<script type="text/javascript">
|
||
|
$(document).ready(function() {
|
||
|
|
||
|
var group1 = new radioGroup('rg1');
|
||
|
var group2 = new radioGroup('rg2');
|
||
|
|
||
|
}); // end ready
|
||
|
|
||
|
function keyCodes () {
|
||
|
// Define values for keycodes
|
||
|
this.enter = 13;
|
||
|
this.space = 32;
|
||
|
|
||
|
this.left = 37;
|
||
|
this.up = 38;
|
||
|
this.right = 39;
|
||
|
this.down = 40;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function radioGroup() is a class to define an ARIA-enabled radiogroup widget.
|
||
|
//
|
||
|
// This widget attaches to an unordered list and makes each list entry a group
|
||
|
// of radio buttons.
|
||
|
//
|
||
|
// @param (id object) id is the html id of the <ul> to attach to
|
||
|
//
|
||
|
// @return N/A
|
||
|
//
|
||
|
function radioGroup(id) {
|
||
|
|
||
|
var thisObj = this;
|
||
|
|
||
|
///////// define widget properties ///////////////
|
||
|
|
||
|
this.$id = $('#' + id);
|
||
|
|
||
|
// find all list items with a role of radio
|
||
|
this.$buttons = this.$id.find('li').filter('[role=radio]');
|
||
|
|
||
|
// Store the currently checked item
|
||
|
this.$checked = this.$buttons.filter('[aria-checked=true]');
|
||
|
|
||
|
this.checkButton = true; // set to false during ctrl+arrow operations;
|
||
|
|
||
|
this.$active = null; // the selected button (may not be checked)
|
||
|
|
||
|
this.keys = new keyCodes();
|
||
|
|
||
|
///////////// Bind Event handlers ////////////////
|
||
|
|
||
|
this.$buttons.click(function(e) {
|
||
|
return thisObj.handleClick(e, $(this));
|
||
|
});
|
||
|
|
||
|
this.$buttons.keydown(function(e) {
|
||
|
return thisObj.handleKeyDown(e, $(this));
|
||
|
});
|
||
|
|
||
|
this.$buttons.keypress(function(e) {
|
||
|
return thisObj.handleKeyPress(e, $(this));
|
||
|
});
|
||
|
|
||
|
this.$buttons.focus(function(e) {
|
||
|
return thisObj.handleFocus(e, $(this));
|
||
|
});
|
||
|
|
||
|
this.$buttons.blur(function(e) {
|
||
|
return thisObj.handleBlur(e, $(this));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function selectButton() is a member function to select and possibly check a button in the
|
||
|
// radioGroup.
|
||
|
//
|
||
|
// @param ($id object) $id is the jQuery object of the button to select
|
||
|
//
|
||
|
// @return N/A
|
||
|
//
|
||
|
radioGroup.prototype.selectButton = function($id) {
|
||
|
|
||
|
if (this.checkButton == true) {
|
||
|
// checking the button
|
||
|
|
||
|
// remove the checked image from the previously checked button
|
||
|
this.$checked.find('img').attr('src', 'radio-unchecked.gif');
|
||
|
|
||
|
// update the button image
|
||
|
$id.find('img').attr('src', 'radio-checked.gif');
|
||
|
|
||
|
if (this.$checked.length == 0) { // no previously checked group buttons
|
||
|
// the first and last items in the group will have
|
||
|
// tabindex=0. Remove them both from the tab order.
|
||
|
this.$buttons.first().attr('tabindex', '-1');
|
||
|
|
||
|
this.$buttons.last().attr('tabindex', '-1');
|
||
|
}
|
||
|
else {
|
||
|
// remove the previously checked item from
|
||
|
// the tab order and modify it's aria attributes accordingly
|
||
|
this.$checked.attr('tabindex', '-1').attr('aria-checked', 'false');
|
||
|
}
|
||
|
|
||
|
// Place this button in the tab order and modify it's aria attributes
|
||
|
$id.attr('tabindex', '0').attr('aria-checked', 'true');
|
||
|
|
||
|
// update the stored $checked object
|
||
|
this.$checked = $id;
|
||
|
}
|
||
|
|
||
|
// update the stored $active object
|
||
|
this.$active = $id;
|
||
|
|
||
|
// give this button the selected class
|
||
|
$id.addClass('selected');
|
||
|
|
||
|
// Reset checkButton flag - in case it was false
|
||
|
this.checkButton = true;
|
||
|
|
||
|
} // end selectButton()
|
||
|
|
||
|
//
|
||
|
// Function handleClick() is a member function to process keydown events for the radioGroup.
|
||
|
//
|
||
|
// @param (e object) e is the event object
|
||
|
//
|
||
|
// @param ($id object) $is is the jquery object of the triggering element
|
||
|
//
|
||
|
// @return (boolean) Returns false if consuming event; true if propagating
|
||
|
//
|
||
|
radioGroup.prototype.handleClick = function(e, $id) {
|
||
|
|
||
|
if (e.altKey || e.ctrlKey || e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// simply consume the event - browser calls focus()
|
||
|
|
||
|
e.stopPropagation();
|
||
|
return false;
|
||
|
|
||
|
} // end handleClick()
|
||
|
|
||
|
//
|
||
|
// Function handleKeyDown() is a member function to process keydown events for the radioGroup.
|
||
|
//
|
||
|
// @param (e object) e is the event object
|
||
|
//
|
||
|
// @param ($id object) $is is the jquery object of the triggering element
|
||
|
//
|
||
|
// @return (boolean) Returns false if consuming event; true if propagating
|
||
|
//
|
||
|
radioGroup.prototype.handleKeyDown = function(e, $id) {
|
||
|
|
||
|
if (e.altKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
switch (e.keyCode) {
|
||
|
case this.keys.space:
|
||
|
case this.keys.enter: {
|
||
|
if (e.ctrlkey || e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// select and check the button
|
||
|
this.selectButton($id);
|
||
|
|
||
|
e.stopPropagation();
|
||
|
return false;
|
||
|
}
|
||
|
case this.keys.left:
|
||
|
case this.keys.up: {
|
||
|
|
||
|
var $prev = $id.prev(); // the previous button
|
||
|
|
||
|
if (e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// if this was the first item
|
||
|
// select the last one in the group.
|
||
|
if ($id.index() == 0) {
|
||
|
$prev = this.$buttons.last();
|
||
|
}
|
||
|
|
||
|
if (e.ctrlKey) {
|
||
|
// set checkButton to false so
|
||
|
// focus does not check button
|
||
|
this.checkButton = false;
|
||
|
}
|
||
|
|
||
|
// select the previous button
|
||
|
$prev[0].focus();
|
||
|
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
return false;
|
||
|
}
|
||
|
case this.keys.right:
|
||
|
case this.keys.down: {
|
||
|
|
||
|
var $next = $id.next(); // the next button
|
||
|
|
||
|
if (e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// if this was the last item,
|
||
|
// select the first one in the group.
|
||
|
if ($id.index() == this.$buttons.length - 1) {
|
||
|
$next = this.$buttons.first();
|
||
|
}
|
||
|
|
||
|
if (e.ctrlKey) {
|
||
|
// set checkButton to false so
|
||
|
// focus does not check button
|
||
|
this.checkButton = false;
|
||
|
}
|
||
|
|
||
|
// select the next button
|
||
|
$next[0].focus();
|
||
|
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
return false;
|
||
|
}
|
||
|
} // end switch
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end handleKeyDown()
|
||
|
|
||
|
//
|
||
|
// Function handleKeyPress() is a member function to process keydown events for the radioGroup.
|
||
|
// This is needed to prevent browsers that process window events on keypress (such as Opera) from
|
||
|
// performing unwanted scrolling of the window, etc.
|
||
|
//
|
||
|
// @param (e object) e is the event object
|
||
|
//
|
||
|
// @param ($id object) $is is the jquery object of the triggering element
|
||
|
//
|
||
|
// @return (boolean) Returns false if consuming event; true if propagating
|
||
|
//
|
||
|
radioGroup.prototype.handleKeyPress = function(e, $id) {
|
||
|
|
||
|
if (e.altKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
switch (e.keyCode) {
|
||
|
case this.keys.space:
|
||
|
case this.keys.enter: {
|
||
|
if (e.ctrlKey || e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
case this.keys.left:
|
||
|
case this.keys.up:
|
||
|
case this.keys.right:
|
||
|
case this.keys.down: {
|
||
|
if (e.shiftKey) {
|
||
|
// do nothing
|
||
|
return true;
|
||
|
}
|
||
|
e.stopPropagation();
|
||
|
return false;
|
||
|
}
|
||
|
} // end switch
|
||
|
|
||
|
return true;
|
||
|
|
||
|
} // end handleKeyPress()
|
||
|
|
||
|
//
|
||
|
// Function handleFocus() is a member function to process focus events for the radioGroup.
|
||
|
//
|
||
|
// @param (e object) e is the event object
|
||
|
//
|
||
|
// @param ($id object) $is is the jquery object of the triggering element
|
||
|
//
|
||
|
// @return (boolean) Returns false if consuming event; true if propagating
|
||
|
//
|
||
|
radioGroup.prototype.handleFocus = function(e, $id) {
|
||
|
|
||
|
// select the button
|
||
|
this.selectButton($id);
|
||
|
|
||
|
return true;
|
||
|
} // end handleFocus()
|
||
|
|
||
|
//
|
||
|
// Function handleBlur() is a member function to process blur events for the radioGroup.
|
||
|
//
|
||
|
// @param (e object) e is the event object
|
||
|
//
|
||
|
// @param ($id object) $is is the jquery object of the triggering element
|
||
|
//
|
||
|
// @return (boolean) Returns false if consuming event; true if propagating
|
||
|
//
|
||
|
radioGroup.prototype.handleBlur = function(e, $id) {
|
||
|
|
||
|
// remove the focus styling from this buttons
|
||
|
$id.removeClass('selected');
|
||
|
|
||
|
return true;
|
||
|
} // end handleBlur()
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|