//
// Function liveRegion() is a constructor to define an ARIA live region widget. The widget binds to a div
// on the page and accepts a callback function that is triggered at a specified interval.
//
// By default, the live region's alert level is polite, it's updates are non-atomic, additions are relevant,
// and it uses the general channel. These default values may be overridden by either specifying different
// values in the html markup or by calling the widget's corresponding update functions.
//
// @param (id string) id is the html id of the div to bind to.
//
// @param (func callback) func is the callback function to execute at the specified interval
//
// @param (interval integer) interval is the initial update interval
//
// @return N/A
//
function liveRegion(id, func, interval) {
// define widget properties
this.$id = $('#' + id); // the jquery object of the live region
this.func = func; // the callback to execute after each interval
this.interval = interval; // the interval to use for the timer
this.timer = null; // the interval timer object
// set the initial live region aria attributes. Check if the user
// has specified values in the html markup. If so, use those
// values.
this.busy = false; // set to true while the region is updating
// create the update timer
this.createTimer();
} // end liveRegion constructor
//
// Function createTimer() is a member function to create an interval timer for
// the live region widget.
//
// @return N/A
//
liveRegion.prototype.createTimer = function() {
if (this.timer != null) {
// destroy the existing timer
this.destroyTimer();
}
//
// Function destroyTimer() is a member function to remove the interval timer for
// the live region widget.
//
// @return N/A
//
liveRegion.prototype.destroyTimer = function() {
if (this.timer != null) {
clearInterval(this.timer);
this.timer = null;
}
} // end createTimer()
//
// Function setInterval() is a member function to change the update interval
// of the live region. This function stores the new interval, clears the current
// interval timer and creates new one with the specified interval.
//
// @param (interval integer) interval is the new interval, in minutes, to set
//
// @return N/A
//
liveRegion.prototype.setInterval = function(interval) {
this.interval = interval;
this.createTimer();
} // end setInterval()
//
// Function setPoliteness() is a member function to set the aria-polite attribute of
// the live region.
//
// @param (val string) val is one of three possible states: 'off', 'polite', 'assertive';
//
// @return N/A
//
liveRegion.prototype.setPoliteness = function(val) {
this.$id.attr('aria-live', val);
} // end setPoliteness()
//
// Function setAtomic() is a member function to set the aria-atomic attribute of
// the live region.
//
// @param (val boolean) val is true if live region updates should be atomic
//
// @return N/A
//
liveRegion.prototype.setAtomic = function(val) {
this.$id.attr('aria-atomic', val);
} // end setAtomic()
//
// Function setRelevant() is a member function to set the aria-relevant attribute of
// the live region.
//
// @param (val string) val may be 'additions', 'removals', or 'text'. It may also be a
// space seperated combination of these.
//
// @return N/A
//
liveRegion.prototype.setRelevant = function(val) {
<script type="text/javascript">
var g_msg1 = {
msgArray: new Array("0","1","2","3","4","5","6","7","8","9"),
index: 0
};
var g_msg2 = {
msgArray: new Array(
"The birch canoe slid on the smooth planks.",
"Glue the sheet to the dark blue background.",
"It's easy to tell the depth of a well.",
"These days a chicken leg is a rare dish.",
"Rice is often served in round bowls.",
"The juice of lemons makes fine punch.",
"The box was thrown beside the parked truck.",
"The hogs were fed chopped corn and garbage.",
"Four hours of steady work faced us.",
"Large size in stockings is hard to sell."
),
index: 0
};
var g_msg1index = 0;
var g_msg2index = 0;
$(document).ready(function() {
var live1 = new liveRegion('liveregion1', function() {updateRegion('liveregion1', g_msg1, false);}, 1000);
var live2 = new liveRegion('liveregion2', function() {updateRegion('liveregion2', g_msg2, true);}, 5000);
// initialize the selects to ensure that their selected values match the markup
init();
///////////////// Bind event handlers for live1 controls //////////////////////////
// bind a change event handler for the interval select
$('#time1').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the interval
live1.setInterval($newItem.text()*1000);
e.stopPropagation();
return false;
});
// bind a change event handler for the politeness select
$('#politeness1').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the politeness
live1.setPoliteness($newItem.text());
e.stopPropagation();
return false;
});
// bind a change event handler for the atomic select
$('#atomic1').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the politeness
live1.setAtomic($newItem.text());
e.stopPropagation();
return false;
});
// bind a change event handler for the update relevance select
$('#relevant1').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the update revelance setting
live1.setRelevant($newItem.text());
e.stopPropagation();
return false;
});
///////////////// Bind event handlers for live2 controls //////////////////////////
$('#time2').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the interval
live2.setInterval($newItem.text()*1000);
e.stopPropagation();
return false;
});
// bind a change event handler for the politeness select
$('#politeness2').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the politeness
live2.setPoliteness($newItem.text());
e.stopPropagation();
return false;
});
// bind a change event handler for the atomic select
$('#atomic2').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the politeness
live2.setAtomic($newItem.text());
e.stopPropagation();
return false;
});
// bind a change event handler for the update relevance select
$('#relevant2').change(function(e) {
// select the new item
var $newItem = selectItem($(this), $(this).find('option'), $(this).val());
// set the update revelance setting
live2.setRelevant($newItem.text());
e.stopPropagation();
return false;
});
}); // end ready()
//
// Function init() is a function to initialize the select elements to match their activedescendant values. This
// ensures that any page reloads do not introduce erroneous aria attribute values
function init() {
var elems = new Array('time1', 'politeness1', 'atomic1', 'relevant1', 'time2', 'politeness2', 'atomic2', 'relevant2');
var $id = null;
var val = null;
for (ndx in elems) {
// get the jQuery object of select to set
$id = $('#' + elems[ndx]);
// get the value of the active descendant
val = $('#' + $id.attr('aria-activedescendant')).text();
// set the value of the select
$id.val(val);
}
} // end init()
//
// Function selectItem() is a function to iterate through an option list to find a new option and select it.
// The function also updates the aria-seleced attribute of the items.
//
// @param ($select object) $select is the jquery object of the select that the option list is part of.
//
// @param ($list object) $list is the list of options to iterate through.
//
// @param (val string) val is the value to find in the list.
//
// @return (object) returns the jquery object of the new item selected. Returns NULL if not found.
//
function selectItem($select, $list, val) {
var $prevItem = $('#' + $select.attr('aria-activedescendant'));
var $newItem = null;
// find the list item associated with the new value
$list.each(function() {
if ($(this).text() == val) {
$newItem = $(this);
}
});
if ($newItem == null) {
// no new item found
return null;
}
// set the aria-selected attribute to false for the previously selected item
$prevItem.attr('aria-selected', 'false');
// set the aria-selected attribute to true for the new item
$newItem.attr('aria-selected', 'true')
// update the active descendent of the select
$select.attr('aria-activedescendant', $newItem.attr('id'));
// return the new item selected
return $newItem;
} // end selectItem()
//
// The function updateRegion() is called by a liveRegion timer to updates the live region
// with new content based on the passed messageArray.
//
// @param (live_region object) LiveRegion is the liveRegion widget object
//
// @param (msgArray array) msgArray is an array of messages to use for the update
//
// @param (append boolean) append is true if messages should be appended, false if message should
// replace live region content
//
// @return N/A
//
function updateRegion (region, msgObj, append) {
var $regionID = $('#' + region);
var msg = '';
if (msgObj.index == msgObj.msgArray.length) {
// We've reached the end of the array, reset the index.
msgObj.index = 0;
// clear the region
$regionID.empty();
}
if (append == false) {
msg = msgObj.msgArray[msgObj.index];
// messages should replace live region contents.
// Empty the live region
$regionID.empty();
}
else {
msg = msgObj.msgArray[msgObj.index] + '<br/>';
}
// append the new message to the live region
$regionID.append(msg);
if (append == true) {
$regionID.scrollTop($regionID.attr('scrollHeight'));
}