Test Start

List of Messages

Test End

Rule References

Rule Pass IDs Fail IDs
Rule 84
  • id1
  • button1
  • t1
  • close1
  • button2
  • t2
  • close2
  • button3
  • t3
  • close3
  • button4
  • t4
  • close4
none
Rule 85
  • t1
  • t2
  • t3
  • t4
none
Rule 86
  • t1
  • t2
  • t3
  • t4
none
Rule 87
  • t1
  • t2
  • t3
  • t4
none
Rule 92
  • id1
  • button1
  • t1
  • close1
  • button2
  • t2
  • close2
  • button3
  • t3
  • close3
  • button4
  • t4
  • close4
none
Rule 93
  • t1
  • t2
  • t3
  • t4
none
Rule 95
  • button1
  • close1
  • button2
  • close2
  • button3
  • close3
  • button4
  • close4
none

Calculations

No calculations for test 125

Test Description

  • This test implements a simple hide/show widget for an ARIA region that does not follow its contolling button in the DOM.

Keyboard shortcuts:
* Tab: Move between button items and text area.
* Enter or space: Toggle display of region. If focus is on region close button, collapse region and move focus to the region’s controlling button.

Test Markup

User Agent Implementation

No user agent implementation information.

HTML Source Code


<div id="id1" role="application">
   <h2>List of Messages</h2>

   <ul class="msglist">
     <li>
         <button id="open1" class="buttonControl" aria-controls="m1">
               <span>Show</span>
               Message 1
         </button>
     </li>
     <li>
         <button id="open2" class="buttonControl" aria-controls="m2">
              <span>Show</span>
              Message 2
         </button>
     </li>
     <li>
         <button id="open3" class="buttonControl" aria-controls="m3">
              <span>Show</span>
              Message 3
         </button>
     </li>
     <li>
         <button id="open4" class="buttonControl" aria-controls="m4">
              <span>Show</span>
              Message 4
         </button>
     </li>
   </ul>

   <div id="m1" class="message" tabindex="-1" role="region" aria-labelledby="m1-label" aria-expanded="false">
       <h2 id="m1-label">Message 1</h2>
       <p>Message 1 is all about being message 1 and has nothing to do with any other messages.</p>
       <p>
           <button id="close1" class="buttonControl" aria-controls="m1">
                Close
                <span class="hidden">Message 1</span>
           </button>
       </p>
   </div>

   <div id="m2" class="message" role="region" aria-labelledby="m2-label" tabindex="-1" aria-expanded="false">
         <h2 id="m2-label">Message 2</h2>
         <p>Message 2 is all about being message 2 and has nothing to do with any other messages.</p>
         <p>
           <button id="close2" class="buttonControl" aria-controls="m2">
               Close
               <span class="hidden">Message 2</span>
           </button>
       </p>
   </div>

   <div id="m3" class="message" role="region" aria-labelledby="m3-label" tabindex="-1" aria-expanded="false">
          <h2 id="m3-label">Message 3</h2>
          <p>Message 3 is all about being message 3 and has nothing to do with any other messages.</p>
          <p>
            <button id="close3" class="buttonControl" aria-controls="m3">
               Close
               <span class="hidden">Message 3</span>
            </button>
          </p>
   </div>

   <div id="m4" class="message" role="region" aria-labelledby="m4-label" tabindex="-1" aria-expanded="false">
          <h2 id="m4-label">Message 4</h2>
          <p>Message 4 is all about being message 4 and has nothing to do with any other messages.</p>
          <p>
            <button id="close4" class="buttonControl" aria-controls="m4">
               Close
               <span class="hidden">Message 4</span>
            </button>
          </p>
   </div>
</div>

CSS Code


.hidden {
    display: none;
}

ul.msglist {
   list-style: none;
}
div.message
{
  display: none;
  margin: .5em;
  padding: .5em;
  border: 2px solid #880000;
  width: 40em;
}

div#m1 {
  background-color: #ffefef;
}

div#m2 {
  background-color: #efffef;
}

div#m3 {
  background-color: #efefff;
}

div#m4 {
  background-color: #efffff;
}

a.buttonControl {
  color: #004400;
  text-decoration: none;
  border-bottom: 1px solid #004400;
}

a.buttonControl:hover,
a.buttonControl:active,
a.buttonControl:focus {
  color: #880000;
  border-bottom: 2px solid #880000;
}

Javascript Source Code


$(document).ready(function() {

   var hs1 = new hideShow('open1', 'close1');
   var hs2 = new hideShow('open2', 'close2');
   var hs3 = new hideShow('open3', 'close3');
   var hs4 = new hideShow('open4', 'close4');
  
}); // end ready()

//
// function hideShow() is the constructor for a hideShow widget. It accepts two html IDs:
//
// 1. the button to toggle the region
// 2. A close button within the region to hide it and return focus to the toggle button
//
// The widget moves focus to the region when expanding it, and returns focus to the toggle button
// when closing it.
//
// @param(toggleID string) toggleID is the html ID of the toggle button to attach to
//
// @param(closeID string) closeID is the html ID of the close button to attach to
//
// @return N/A
//
function hideShow(toggleID, closeID) {

   this.$toggle = $('#' + toggleID);
   this.$close = $('#' + closeID);
   this.$region = $('#' + this.$toggle.attr('aria-controls'));

   this.keys = {
               enter: 13,
               space: 32
               };

   this.toggleSpeed = 100;

   // bind handlers
   this.bindHandlers();

} // end hidShow() constructor

//
// Function bindHandlers() is a member function to bind event handlers to the hideShow region
//
// return N/A
//
hideShow.prototype.bindHandlers = function() {

   var thisObj = this;

   this.$toggle.click(function(e) {

      thisObj.toggleRegion();

      e.stopPropagation();
      return false;
   });

   this.$toggle.keydown(function(e) {

      if (e.altKey||e.ctrlKey||e.shiftKey) {
         // do nothing
      }
      else if (e.keyCode == thisObj.keys.enter || e.keyCode == thisObj.keys.space) {

         thisObj.toggleRegion();

         e.stopPropagation();
         return false;
      }

      return true;
   });

   this.$close.click(function(e) {

      thisObj.hideRegion();

      e.stopPropagation();
      return false;
   });

   this.$close.keydown(function(e) {

      if (e.altKey||e.ctrlKey||e.shiftKey) {
         // do nothing
      }
      else if (e.keyCode == thisObj.keys.enter || e.keyCode == thisObj.keys.space) {

         thisObj.hideRegion();

         e.stopPropagation();
         return false;
      }

      return true;
   });
}

// Function hideRegion() is a member function to hide an expanded region and return focus to
// the toggle button
//
// return N/A
//
hideShow.prototype.hideRegion = function() {

   // hide the region and update the aria-expanded attribute
   this.$region.hide().attr('aria-expanded', 'false');

   // update the button label
   this.$toggle.find('span').html('Show');

   // return focus to the toggle button
   this.$toggle.focus();

} // end hideRegion()

//
// Function toggleRegion() is a member function to toggle the display of the hideShow region
//
// return N/A
//
hideShow.prototype.toggleRegion = function() {

      var thisObj = this;

    // toggle the region
    this.$region.slideToggle(this.toggleSpeed, function() {

      if ($(this).attr('aria-expanded') == 'false') { // region is collapsed

        // update the aria-expanded attribute of the region
        $(this).attr('aria-expanded', 'true');

        // move focus to the region
        $(this).focus();

        // update the button label
        thisObj.$toggle.find('span').html('Hide');

      }
      else { // region is expanded

        // update the aria-expanded attribute of the region
        $(this).attr('aria-expanded', 'false');

        // update the button label
        thisObj.$toggle.find('span').html('Show');
      }
    });

} // End toggleRegion()