Accessibility Examples
Test Start
50
750
Test End
Rule References
| Rule | Pass IDs | Fail IDs |
|---|---|---|
| Rule 84 |
|
none |
| Rule 85 |
|
none |
| Rule 86 |
|
none |
| Rule 87 |
|
none |
| Rule 90 |
|
none |
| Rule 91 |
|
none |
| Rule 92 |
|
none |
| Rule 93 |
|
none |
| Rule 94 |
|
none |
| Rule 95 |
|
none |
Calculations
No calculations for test 134
Test Description
- This test implements a simple ARIA spinbutton widget
Keyboard shortcuts (based on recommended shortcuts specified by the DHTML Style Guide Working Group):
* Right and Up Arrows: increase the value
* Left and Down Arrows decrease the value
* Home and End key: move to the maximum or minimum values
* Page Up and Page Down: incrementally increase or decrease the value
* Note: Focus should remain on the edit field
Test Markup
- ARIA 1.0: [aria-labelledby]
- ARIA 1.0: [aria-valuemax]
- ARIA 1.0: [aria-valuemin]
- ARIA 1.0: [aria-valuenow]
- ARIA 1.0: [role="button"]
- ARIA 1.0: [role="presentation"]
- ARIA 1.0: [role="spinbutton"]
User Agent Implementation
No user agent implementation information.
HTML Source Code
<div id="application" role="application">
<label id="sb1_label" class="sbLabel" for="sb1">Choose a number between 0 and 100</label>
<div class="spinControl">
<div id="sb1" class="spinbutton" role="spinbutton"
aria-labelledby="sb1_label"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
tabindex="0">
50
</div>
<div id="sb1_up" class="button" role="button" title="Increase Value">
<img id="sb1_up_img" src="http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up.png" role="presentation">
</div>
<div id="sb1_down" class="button" role="button" title="Decrease Value">
<img id="sb1_down_img" src="http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down.png" role="presentation">
</div>
</div>
<label id="sb2_label" class="sbLabel" for="sb2">Choose a number between 500 and 1000</label>
<div class="spinControl">
<div id="sb2" class="spinbutton" role="spinbutton"
aria-labelledby="sb2_label"
aria-valuemin="500"
aria-valuemax="1000"
aria-valuenow="750"
tabindex="0">
750
</div>
<div id="sb2_up" class="button" role="button" title="Increase Value">
<img id="sb2_up_img" src="http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up.png" role="presentation">
</div>
<div id="sb2_down" class="button" role="button" title="Decrease Value">
<img id="sb2_down_img" src="http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down.png" role="presentation">
</div>
</div>
</div>
CSS Code
div.spinControl {
margin: 20px;
margin-left: 40px;
width: 100px;
height: 44px;
border: 1px solid black;
}
div.spinbutton {
float: left;
display: inline;
margin: 1px;
text-align: right;
font-weight: bold;
font-size: 1.6em;
padding: 7px 10px 7px 0;
width: 65px;
height: 28px;
background-color: #faf7f0;
}
div.spinbutton:active,
div.spinbutton:hover,
div.spinbutton.focus {
margin: 0;
background-color: #faf7f0;
border: 1px solid red;
}
div.button {
margin: 0;
margin-left: 77px;
padding: 0;
height: 22px;
}
div.button img {
margin: 0;
padding: 0;
border-left: 1px solid black;
}
label.sbLabel {
font-weight: bold;
font-size: 1.2em;
}
Javascript Source Code
$(document).ready(function () {
var spin1 = new spinbutton('sb1', 'sb1_up', 'sb1_down', 10);
var spin2 = new spinbutton('sb2', 'sb2_up', 'sb2_down', 50);
}); // end ready
//
// Function spinbutton() is a constructor for an ARIA spinbutton widget. The widget
// binds to an element with role='spinbutton'.
//
// @param (id string) id is the html id of the spinbutton element
//
// @param (upID string) upID is the html id of the spinbutton control's increase value button
//
// @param (downID string) downID is the html id of the spinbutton control's decrease value button
//
// @param (skipVal integer) skipVal is the amount to change the control by for pgUp/pgDown
// @return N/A
//
function spinbutton(id, upID, downID, skipVal) {
// define widget attributes
this.$id = $('#' + id);
this.upID = upID;
this.$upButton = $('#' + upID);
this.downID = downID;
this.$downButton = $('#' + downID);
this.skipVal = skipVal;
this.valMin = parseInt(this.$id.attr('aria-valuemin'));
this.valMax = parseInt(this.$id.attr('aria-valuemax'));
this.valNow = parseInt(this.$id.attr('aria-valuenow'));
this.keys = {
pageup: 33,
pagedown: 34,
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40
};
// bind event handlers
this.bindHandlers();
}
// Function bindHandlers() is a member function to bind event handlers for the spinbutton control
//
// @return N/A
//
spinbutton.prototype.bindHandlers = function() {
var thisObj = this;
//////// bind mouse event handlers to the up button //////////////
this.$upButton.mousedown(function(e) {
return thisObj.handleMouseDown(e, $(this));
});
this.$upButton.mouseup(function(e) {
return thisObj.handleMouseUp(e, $(this));
});
this.$upButton.mouseenter(function(e) {
return thisObj.handleMouseEnter(e, $(this));
});
this.$upButton.mouseout(function(e) {
return thisObj.handleMouseOut(e, $(this));
});
this.$upButton.click(function(e) {
return thisObj.handleClick(e, $(this));
});
//////// bind mouse event handlers to the down button //////////////
this.$downButton.mousedown(function(e) {
return thisObj.handleMouseDown(e, $(this));
});
this.$downButton.mouseup(function(e) {
return thisObj.handleMouseUp(e, $(this));
});
this.$downButton.mouseenter(function(e) {
return thisObj.handleMouseEnter(e, $(this));
});
this.$downButton.mouseout(function(e) {
return thisObj.handleMouseOut(e, $(this));
});
this.$downButton.focus(function(e) {
return thisObj.handleFocus(e, $(this));
});
this.$downButton.click(function(e) {
return thisObj.handleClick(e, $(this));
});
//////// bind event handlers to the spinbutton //////////////
this.$id.keydown(function(e) {
return thisObj.handleKeyDown(e);
});
this.$id.keypress(function(e) {
return thisObj.handleKeyPress(e);
});
this.$id.focus(function(e) {
return thisObj.handleFocus(e);
});
this.$id.blur(function(e) {
return thisObj.handleBlur(e);
});
this.$id.parent().focusout(function(e) {
return thisObj.handleBlur(e);
});
} // end bindHandlers()
//
// Function handleClick() is a member function to handle click events for the control
// buttons
//
// @param (e object) e is the event object
//
// @param ($button object) $button is the jQuery object of the button clicked
//
// @return (boolean) Returns false
//
spinbutton.prototype.handleClick = function(e, $button) {
if ($button.attr('id') == this.upID) {
// if valuemax isn't met, increment valnow
if (this.valNow < this.valMax) {
this.valNow++;
this.$id.text(this.valNow);
this.$id.attr('aria-valuenow', this.valNow);
}
}
else {
// if valuemax isn't met, decrement valnow
if (this.valNow > this.valMin) {
this.valNow--;
this.$id.text(this.valNow);
this.$id.attr('aria-valuenow', this.valNow);
}
}
// set focus on the spinbutton
this.$id.focus();
e.stopPropagation();
return false;
} // end handleClick()
//
// Function handleMouseDown() is a member function to handle mousedown events for the control
// buttons
//
// @param (e object) e is the event object
//
// @param ($button object) $button is the jQuery object of the button clicked
//
// @return (boolean) Returns false
//
spinbutton.prototype.handleMouseDown = function(e, $button) {
var $img = $button.find('img');
if ($button.attr('id') == this.upID) {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up-pressed-hl.png");
}
else {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down-pressed-hl.png");
}
e.stopPropagation();
return false;
} // end handleMouseDown()
//
// Function handleMouseUp() is a member function to handle mouseup events for the control
// buttons
//
// @param (e object) e is the event object
//
// @param ($button object) $button is the jQuery object of the button clicked
//
// @return (boolean) Returns false
//
spinbutton.prototype.handleMouseUp = function(e, $button) {
var $img = $button.find('img');
if ($button.attr('id') == this.upID) {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up-hl.png");
}
else {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down-hl.png");
}
e.stopPropagation();
return false;
} // end handleMouseUp()
//
// Function handleMouseEnter() is a member function to handle mouseenter events for the control
// buttons
//
// @param (e object) e is the event object
//
// @param ($button object) $button is the jQuery object of the button
//
// @return (boolean) Returns false
//
spinbutton.prototype.handleMouseEnter = function(e, $button) {
var $img = $button.find('img');
if ($button.attr('id') == this.upID) {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up-hl.png");
}
else {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down-hl.png");
}
e.stopPropagation();
return false;
} // end handleMouseOutEnter()
//
// Function handleMouseOut() is a member function to handle mouseout events for the control
// buttons
//
// @param (e object) e is the event object
//
// @param ($button object) $button is the jQuery object of the button
//
// @return (boolean) Returns false
//
spinbutton.prototype.handleMouseOut = function(e, $button) {
var $img = $button.find('img');
if ($button.attr('id') == this.upID) {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-up.png");
}
else {
$img.attr('src', "http://www.oaa-acessibility.org/media/testsuite/images/button-arrow-down.png");
}
e.stopPropagation();
return false;
} // end handleMouseOutUp()
//
// Function handleKeyDown() is a member function to handle keydown events for the control.
//
// @param (e object) e is the event object
//
// @return (boolean) Returns false if consuming; true if propagating
//
spinbutton.prototype.handleKeyDown = function(e) {
if (e.altKey || e.ctrlKey || e.shiftKey) {
// do nothing
return true;
}
switch(e.keyCode) {
case this.keys.pageup: {
if (this.valNow < this.valMax) {
// if valnow is small enough, increase by the skipVal,
// otherwise just set to valmax
if (this.valNow < this.valMax - this.skipVal) {
this.valNow += this.skipVal;
}
else {
this.valNow = this.valMax;
}
// update the control
this.$id.attr('aria-valuenow', this.valNow);
this.$id.html(this.valNow);
}
e.stopPropagation();
return false;
}
case this.keys.pagedown: {
if (this.valNow > this.valMin) {
// if valNow is big enough, decrease by the skipVal,
// otherwise just set to valmin
if (this.valNow > this.valMin + this.skipVal) {
this.valNow -= this.skipVal;
}
else {
this.valNow = this.valMin;
}
// update the control
this.$id.attr('aria-valuenow', this.valNow);
this.$id.html(this.valNow);
}
e.stopPropagation();
return false;
}
case this.keys.home: {
if (this.valNow < this.valMax) {
this.valNow = this.valMax;
this.$id.attr('aria-valuenow', this.valNow);
this.$id.html(this.valNow);
}
e.stopPropagation();
return false;
}
case this.keys.end: {
if (this.valNow > this.valMin) {
this.valNow = this.valMin;
this.$id.attr('aria-valuenow', this.valNow);
this.$id.html(this.valNow);
}
e.stopPropagation();
return false;
}
case this.keys.right:
case this.keys.up: {
// if valuemin isn't met, increment valnow
if (this.valNow < this.valMax) {
this.valNow++;
this.$id.text(this.valNow);
this.$id.attr('aria-valuenow', this.valNow);
}
e.stopPropagation();
return false;
}
case this.keys.left:
case this.keys.down: {
// if valuemax isn't met, decrement valnow
if (this.valNow > this.valMin) {
this.valNow--;
this.$id.text(this.valNow);
this.$id.attr('aria-valuenow', this.valNow);
}
e.stopPropagation();
return false;
}
}
return true;
} // end handleKeyDown()
//
// Function handleKeyPress() is a member function to handle keypress events for the control.
// This function is required to prevent browser that manipulate the window on keypress (such as Opera)
// from performing unwanted scrolling.
//
// @param (e object) e is the event object
//
// @return (boolean) Returns false if consuming; true if propagating
//
spinbutton.prototype.handleKeyPress = function(e) {
if (e.altKey || e.ctrlKey || e.shiftKey) {
// do nothing
return true;
}
switch(e.keyCode) {
case this.keys.pageup:
case this.keys.pagedown:
case this.keys.home:
case this.keys.end:
case this.keys.left:
case this.keys.up:
case this.keys.right:
case this.keys.down: {
// consume the event
e.stopPropagation();
return false;
}
}
return true;
} // end handleKeyPress()
//
// Function handleFocus() is a member function to handle focus events for the control.
//
// @param (e object) e is the event object
//
// @return (boolean) Returns true
//
spinbutton.prototype.handleFocus = function(e) {
// add the focus styling class to the control
this.$id.addClass('focus');
return true;
} // end handleFocus()
//
// Function handleBlur() is a member function to handle blur events for the control.
//
// @param (e object) e is the event object
//
// @return (boolean) Returns true
//
spinbutton.prototype.handleBlur = function(e) {
// Remove the focus styling class from the control
this.$id.removeClass('focus');
return true;
} // end handleBlur()