Test Start

Live Region 1: Simple Counter

:

:

:

:

:
XXX

Live Region 2: Text Log

:

:

:

:

Test End

Rule References

Rule Pass IDs Fail IDs
Rule 84
  • application
  • time1
  • time1_opt1
  • rgn1_button
  • liveregion1
  • rgn2_button
  • liveregion2
none
Rule 85
  • time1
  • time1_opt1
  • rgn1_button
  • liveregion1
  • rgn2_button
  • liveregion2
none
Rule 86
  • time1
  • rgn1_button
  • liveregion1
  • rgn2_button
  • liveregion2
none
Rule 87
  • time1_opt1
  • politeness1
  • rgn1_button
  • rgn2_button
none
Rule 88
  • rgn1_button
  • rgn2_button
none
Rule 92
  • application
  • time1_opt1
  • rgn1_button
  • liveregion1
  • rgn2_button
  • liveregion2
none
Rule 93
  • time1
  • time1_opt1
  • rgn1_button
  • liveregion1
  • rgn2_button
  • liveregion2
none
Rule 94
  • time1
  • politeness1
  • atomic1
  • rgn1_button
  • rgn2_button
none
Rule 95
  • time1
  • politeness1
  • atomic1
  • rgn1_button
  • rgn2_button
none

Calculations

No calculations for test 126

Test Description

  • This test implements a simple aria-live region with a counter and log

Keyboard shortcuts:
* Tab: Move between controls
* Enter or space: Toggle region updates

Test Markup

User Agent Implementation

No user agent implementation information.

HTML Source Code


<div id="application" role="application">
   <div class="controls">
      <h2>Live Region 1: Simple Counter</h2>
      <p><label id="time1Label" for="time1">Change Interval (seconds)</label>:
         <select id="time1" aria-labelledby="time1Label" aria-activedescendant="time1_opt1">
            <option id="time1_opt1" role="option" aria-selected="true" selected>1</option>
            <option id="time1_opt2" role="option" aria-selected="false">2</option>
            <option id="time1_opt3" role="option" aria-selected="false">3</option>
            <option id="time1_opt4" role="option" aria-selected="false">4</option>
            <option id="time1_opt5" role="option" aria-selected="false">5</option>
            <option id="time1_opt6" role="option" aria-selected="false">6</option>
            <option id="time1_opt7" role="option" aria-selected="false">7</option>
            <option id="time1_opt8" role="option" aria-selected="false">8</option>
            <option id="time1_opt9" role="option" aria-selected="false">9</option>
            <option id="time1_opt10" role="option" aria-selected="false">10</option>
         </select>
      </p>

      <p><label id="politeness1Label" for="politeness1">Live Property Value</label>:
         <select id="politeness1" aria-labelledby="politeness1Label" aria-activedescendant="polite1_opt3">
            <option id="polite1_opt1" role="option" aria-selected="false">off</option>
            <option id="polite1_opt2" role="option" aria-selected="false">polite</option>
            <option id="polite1_opt3" role="option" aria-selected="true" selected>assertive</option>
            <option id="polite1_opt4" role="option" aria-selected="false">rude</option>
         </select>
      </p>

      <p><label id="atomic1Label" for="atomic1">Atomic Property Value</label>:
         <select id="atomic1" aria-labelledby="atomic1Label" aria-activedescendant="atomic1_opt1">
            <option id="atomic1_opt1" role="option" aria-selected="true" selected>true</option>
            <option id="atomic1_opt2" role="option" aria-selected="false">false</option>
         </select>
      </p>

      <p><label id="relevant1Label" for="relevant1">Relevant Property Value</label>:
         <select id="relevant1" aria-labelledby="relevant1Label" aria-activedescendant="relevant1_opt4">
            <option id="relevant1_opt1" role="option" aria-selected="false">additions</option>
            <option id="relevant1_opt2" role="option" aria-selected="false">removals</option>
            <option id="relevant1_opt3" role="option" aria-selected="false">text</option>
            <option id="relevant1_opt4" role="option" aria-selected="true" selected>all</option>
          </select>
      </p>
      <button id="rgn1_button" aria-controls="liveregion1" aria-pressed="false">Start Counter</button>
   </div>
   <div class="example">
      <div id="region1Container">
         <label id="live1Label" for="liveregion1">Changing value</label>:
         <div id="liveregion1"
            class="region"  
            role="timer"
            aria-labelledby="live1Label"
            aria-live="assertive"
            aria-atomic="true"
            aria-relevant="all">XXX
         </div>
      </div>
   </div>
   <div class="controls">
      <h2>Live Region 2: Text Log</h2>
      <p><label id="time2Label" for="time2">Change Interval (in seconds)</label>:
         <select id="time2" aria-labelledby-"time2Label" aria-activedescendant="time2_opt5">
            <option id="time2_opt1" role="option" aria-selected="false">1</option>
            <option id="time2_opt2" role="option" aria-selected="false">2</option>
            <option id="time2_opt3" role="option" aria-selected="false">3</option>
            <option id="time2_opt4" role="option" aria-selected="false">4</option>
            <option id="time2_opt5" role="option" aria-selected="true" selected>5</option>
            <option id="time2_opt6" role="option" aria-selected="false">6</option>
            <option id="time2_opt7" role="option" aria-selected="false">7</option>
            <option id="time2_opt8" role="option" aria-selected="false">8</option>
            <option id="time2_opt9" role="option" aria-selected="false">9</option>
            <option id="time2_opt10" role="option" aria-selected="false">10</option>
         </select>
      </p>

      <p><label id="politeness2Label" for="politeness2">Live Property Value</label>:
         <select id="politeness2" aria-labelledby="politeness2Label" aria-activedescendant="polite2_opt2">
            <option id="polite2_opt1" role="option" aria-selected="false">off</option>
            <option id="polite2_opt2" role="option" aria-selected="true" selected>polite</option>
            <option id="polite2_opt3" role="option" aria-selected="false">assertive</option>
            <option id="polite2_opt4" role="option" aria-selected="false">rude</option>
         </select>
      </p>

      <p><label id="atomic2Label" for="atomic2">Atomic Property Value</label>:
         <select id="atomic2" aria-labelledby="atomic2Label" aria-activedescendant="atomic2_opt2">
            <option id="atomic2_opt1" role="option" aria-selected="false">true</option>
            <option id="atomic2_opt2" role="option" aria-selected="true" selected>false</option>
         </select>
      </p>

      <p><label id="relevant2Label" for="relevant2">Relevant Property Value</label>:
         <select id="relevant2" aria-labelledby="relevant2Label" aria-activedescendant="relevant2_opt1">
            <option id="relevant2_opt1" role="option" aria-selected="true" selected>additions</option>
            <option id="relevant2_opt2" role="option" aria-selected="false">removals</option>
            <option id="relevant2_opt3" role="option" aria-selected="false">text</option>
            <option id="relevant2_opt4" role="option" aria-selected="false">all</option>
         </select>
      </p>
      <button id="rgn2_button" aria-controls="liveregion2" aria-pressed="false">Start Log</button>
   </div>

   <div class="example">
      <label id="region2Label" for="liveregion2">Log Text</label>

      <div id="liveregion2"
         class="region"
         role="log"
         aria-labelledby="region2Label"
         aria-live="polite"
         aria-atomic="false"
         aria-relevant="additions">
      </div>
   </div>
</div>

CSS Code


div#application {
  height: 30em;
}
div.controls {
  margin-left: 10px;
  padding: 5px 10px;
  width: 21em;
  float: left;
  clear: both;
  border-bottom: 1px solid #008;
}
button,
select {
  float: right;
}
h2 {
  clear: both;
}
div.example {
  margin-top: 50px;
  margin-left: 30px;
  width: 22em;
  float: left;
}
div#region1Container {
  margin-left: 4em;
  padding: 10px;
  width: 11em;
  height: 1.6em;
  float: left;
}
div#region1Container label {
  padding-top: 10px;
  font-weight: bold;
}
div#liveregion1 {
  margin: 0;
  padding: 2px 5px;
  float: right;
  width: 2em;
  text-align: right;
  border: 1px solid black;
}
label#region2Label {
  font-weight: bold;
  font-size: 1.2em;
}
div#liveregion2 {
  padding: 2px 5px;
  width: 22em;
  border: 1px solid black;
  height: 9em;
  overflow: auto;
}

Javascript Source Code


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, true);
  var live2 = new liveRegion('liveregion2', function() {updateRegion('liveregion2', g_msg2, true);}, 5000, true);

   var rgn1Stopped = true;
   var rgn2Stopped = true;

  // 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 a click handler for the start/stop button
  $('#rgn1_button').click(function(e) {

    // toggle the region updates
    live1.toggleUpdates();

      if (rgn1Stopped == false) {
         $('#liveregion1').html('XXX');
         $(this).html('Start Counter');
         rgn1Stopped = true;
      }
      else {
         $(this).html('Stop Counter');
         rgn1Stopped = false;
      }

    e.stopImmediatePropagation();
    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;
  });

  // bind a click handler for the start/stop button
  $('#rgn2_button').click(function(e) {

    // toggle the region updates
    live2.toggleUpdates();

      if (rgn2Stopped == false) {
         $(this).html('Start Log');
         rgn2Stopped = true;
      }
      else {
         rgn2Stopped = false;
         $(this).html('Stop Log');
      }

    e.stopImmediatePropagation();
    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'));
  }

  // increment the message index
  msgObj.index++;
  

}