aria Modal - focus trap - last focus
Modal
by ian_smithz
HTML
<section role="main">
<center>
<table id="elements" role="grid">
<tbody>
<tr role="row">
<td class="name" role="gridcell" aria-label="Name"><a href="javascript:;"><span>aria-describedat</span></a></td>
<td class="role" role="gridcell" aria-label="Role Modifiers"><a href="javascript:;"><span>aria-sort</span></a></td>
<td class="role" role="gridcell" aria-label="Role Modifiers"><a href="javascript:;"><span>aria-rowspan</span></a></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="state" role="gridcell" aria-label="State"><a href="javascript:;"><span>aria-active-descendant</span></a></td>
<td class="state" role="gridcell" aria-label="State"><a href="javascript:;"><span>aria-grabbed</span></a></td>
<td class="value" role="gridcell" aria-label="Value"><a href="javascript:;"><span>aria-level</span></a></td>
</tr>
<tr role="row">
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
<td class="invisible" role="presentation"></td>
</tr>
</tbody></table>
</center>
<h3>Legend</h3>
<ul id="legend" class="clearfix">
<li class="name"><div class="icon"></div>Name</li>
<li class="role"><div class="icon"></div>Role Modifiers</li>
<li class="state"><div class="icon"></div>State</li>
<li class="interactive"><div class="icon"></div>Interactive</li>
...
CSS
body {
padding-top: 20px;
padding-left: 20px;
background-color: #fff;
color: #000;
font-family:Tahoma, Verdana, Arial, sans-serif;
}
h1, h3 {
text-align:center;
}
h1 {
font-family: "Temporarium", "Palatino Linotype", "Book Antiqua", Palatino, serif;
font-size:2.5em;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 1);
}
h3 {
margin-top:.25em;
margin-bottom:.25em;
font-size: .67em;
}
td a {
text-decoration: none;
color:black;
}
.style0
{text-align:general;
vertical-align:bottom;
white-space:nowrap;
color:windowtext;
font-size:10.0pt;
font-weight:400;
font-style:normal;
text-decoration:none;
font-family:Verdana;
border:none;}
#elements td {
font-size:11px;
font-weight:normal;
font-style:normal;
text-decoration:none;
color: #000;
text-align:general;
vertical-align:bottom;
white-space:normal;
border-radius: 10px;
width:5em;
height: 5em;
overflow:wrap;
text-align:center;
vertical-align:middle;
border:2px solid black;
}
#elements td.invisible {
border:2px solid transparent;
}
table#elements {
text-align:center;
min-width:800px;
}
/* Legend */
ul#legend .icon {
cursor: pointer;
font-size: 0.9em;
margin: 0;
opacity: 0.8;
padding: 0;
overflow: hidden;
text-align: center;
position: relative;
border-radius: 0.5em;
-o-border-radius: 0.5em;
-moz-border-radius: 0.5em;
-webkit-border-radius: 0.5em;
}
ul#legend {
width:75%;
color: black;
margin: 0;
padding-left: 0;
list-style: none;
}
ul#legend li {
float: left;
font-size:12px;
width: 24%;
padding: 0.125em 0;
}
ul#legend .icon {
height: 1.5em;
width: 1.5em;
display: inline-block;
margin: 0 0.5em;
vertical-align: middle;
border:1px solid black;
}
fieldset {
width:20%;
display:inline-block;
border:none;
font-size:12px;
vertical-align:top;
border: 2px solid #eee;
border-radius:10px;
}
.clearfix:after {
content: ".";
display: block;
clear:...
JavaScript
var preStyles = {
"line-height": "1.4",
"font-family": "Monaco, 'Courier New', Courier",
"font-size": "0.75em",
"border-top-style": "solid",
"border-right-style": "solid",
"border-bottom-style": "solid",
"border-left-style": "solid",
"border-top-width": "1px",
"border-right-width": "1px",
"border-bottom-width": "1px",
"border-left-width": "1px",
"border-top-color": "rgb(153, 153, 153)",
"border-right-color": "rgb(153, 153, 153)",
"border-bottom-color": "rgb(153, 153, 153)",
"border-left-color": "rgb(153, 153, 153)",
"border-image-source": "initial",
"border-image-slice": "initial",
"border-image-width": "initial",
"border-image-outset": "initial",
"border-image-repeat": "initial",
"background-color": "rgb(252, 252, 252)",
"margin-top": "1em",
"margin-right": "0px",
"margin-bottom": "1em",
"margin-left": "0px",
"padding-top": "0.5em",
"padding-right": "0.8em",
"padding-bottom": "0.5em",
"padding-left": "0.8em",
"overflow-x":"scroll"
};
jQuery(document).ready(function () {
jQuery('td')
.each(function(index, value) {
var descText = jQuery('li.' + value.className).text();
if(descText.length) {
jQuery(value).attr('aria-label', descText);
}
})
.on('keydown', function (e) {
var handled = false;
var keyCode = e.which || e.keyCode;
var $this = jQuery(this);
var $nextTd, $nextRow;
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) {
return;
}
switch(keyCode) {
case 37: // LEFT
handled = true;
$nextTd = $this.prev('td');
break;
case 38: // UP
handled = true;
$nextRow = $this.parent().prev('tr');
$nextTd = $nextRow.find('td').eq($this[0].cellIndex);
break;
case 39: // RIGHT
handled = true;
$nextTd = $this.next('td');
break;
case 40: // DOWN
handled = true;
$nextRow = $this.parent().next('tr');
...