Grid Example 2: E-mail with Buttons in the Headers to Reorder List
Validate DOM (HTML5)
Keyboard Shortcuts
- Tab: Move focus between web 2.0 widgets, links and form controls.
- Up Arrow: Move focus to previous message
- Down Arrow: Move focus to next message
- Left Arrow: Move focus one column to the left.
- Right Arrow: Move focus one column to the right.
- Space Bar: When in message list, it selects or unselects the current message.
- Space Bar: When the headers, it reorders the list of messages based on that column data.
ARIA Roles and Properties used
-
Roles:
role="application"
role="button"
role="grid"
role="group"
role="gridcell"
- States and properties:
aria-selected
aria-labeledby
aria-describedby
Note: The idrefs for labelledby and describedby are configurable by the user.
HTML Source Code
Show HTML Source Code: grid2_inline.inc
<div role="application">
<script type="text/javascript">
var grid1 = new ComplexEmailGrid("grid1");
widgets.add(grid1);
</script>
<table id="grid1"
class="email"
role="grid"
tabindex="0"
aria-labelledby="grid1_label"
border="2px"
cellpadding="2px"
>
<caption id="grid1_label">Grade List Sorted by Date</caption>
<thead>
<tr>
<th id="sel" role="button" tabindex=-1">Sel</th>
<th id="msg" role="button" tabindex=-1">Msg</th>
<th id="sta" role="button" tabindex=-1">Status</th>
<th id="att" role="button" tabindex=-1">Att</th>
<th id="pri" role="button" tabindex=-1" aria-haspopup="true">Pri</th>
<th id="fro" role="button" tabindex=-1" aria-haspopup="true">From</th>
<th id="sub" role="button" tabindex=-1" aria-haspopup="true">Subject</th>
<th id="dat" role="button" tabindex=-1" aria-haspopup="true">Date</th>
<th id="siz" role="button" tabindex=-1" aria-haspopup="true">Size</th>
</tr>
</thead>
<tbody>
<tr id="email_01"
role="group"
tabindex="-1">
<td headers="sel" role="presentation"><input name="email_01" type="checkbox"/></td>
<td headers="msg" role="gridcell" tabindex="-1">1</td>
<td headers="sta" role="gridcell" tabindex="-1">false</td>
<td headers="att" role="gridcell" tabindex="-1">false</td>
<td headers="pri" role="gridcell" tabindex="-1">1</td>
<td headers="fro" role="gridcell" tabindex="-1">John Smith</td>
<td headers="sub" role="gridcell" tabindex="-1">Trip to Florida</td>
<td headers="dat" role="gridcell" tabindex="-1">2007-10-03</td>
<td headers="siz" role="gridcell" tabindex="-1">2K</td>
</tr>
<tr id="email_02"
role="group"
tabindex="-1">
<td headers="sel" role="presentation"><input name="email_02" type="checkbox"/></td>
<td headers="msg" role="gridcell" tabindex="-1">2</td>
<td headers="sta" role="gridcell" tabindex="-1">true</td>
<td headers="att" role="gridcell" tabindex="-1">false</td>
<td headers="pri" role="gridcell" tabindex="-1">2</td>
<td headers="fro" role="gridcell" tabindex="-1">Fred Jones</td>
<td headers="sub" role="gridcell" tabindex="-1">Lunch on Friday</td>
<td headers="dat" role="gridcell" tabindex="-1">2007-12-03</td>
<td headers="siz" role="gridcell" tabindex="-1">1K</td>
</tr>
<tr id="email_03"
role="group"
tabindex="-1">
<td headers="sel" role="presentation"><input name="email_03" type="checkbox"/></td>
<td headers="msg" role="gridcell" tabindex="-1">3</td>
<td headers="sta" role="gridcell" tabindex="-1">true</td>
<td headers="att" role="gridcell" tabindex="-1">true</td>
<td headers="pri" role="gridcell" tabindex="-1">3</td>
<td headers="fro" role="gridcell" tabindex="-1">Jane Johnson</td>
<td headers="sub" role="gridcell" tabindex="-1">Proposal for you to review</td>
<td headers="dat" role="gridcell" tabindex="-1">2007-16-03</td>
<td headers="siz" role="gridcell" tabindex="-1">12K</td>
</tr>
<tr id="email_04"
role="group"
tabindex="-1">
<td headers="sel" role="presentation"><input name="email_03" type="checkbox"/></td>
<td headers="msg" role="gridcell" tabindex="-1">4</td>
<td headers="sta" role="gridcell" tabindex="-1">false</td>
<td headers="att" role="gridcell" tabindex="-1">true</td>
<td headers="pri" role="gridcell" tabindex="-1">4</td>
<td headers="fro" role="gridcell" tabindex="-1">Bill Smith</td>
<td headers="sub" role="gridcell" tabindex="-1">Information on weekend</td>
<td headers="dat" role="gridcell" tabindex="-1">2007-19-03</td>
<td headers="siz" role="gridcell" tabindex="-1">122K</td>
</tr>
<tr id="email_05"
role="group"
tabindex="-1">
<td headers="sel" role="presentation"><input name="email_03" type="checkbox"/></td>
<td headers="msg" role="gridcell" tabindex="-1">5</td>
<td headers="sta" role="gridcell" tabindex="-1">true</td>
<td headers="att" role="gridcell" tabindex="-1">false</td>
<td headers="pri" role="gridcell" tabindex="-1">5</td>
<td headers="fro" role="gridcell" tabindex="-1">Skip Roland</td>
<td headers="sub" role="gridcell" tabindex="-1">Opportunity to participate</td>
<td headers="dat" role="gridcell" tabindex="-1">2007-20-03</td>
<td headers="siz" role="gridcell" tabindex="-1">4K</td>
</tr>
</tbody>
</table>
<p>
<input type="button" onclick="handleConfigurationToggleClickEvent(event, 'config1')" value="Show Labelledby and Describedby settings for messages"/>
<input type="button" onclick="handleSimpleEmailGridApplyClickEvent( event, grid1 )" value="Apply new Labelledby and Describedby settings"/>
</p>
<div id="config1">
<fieldset>
<legend>Configure ARIA <code>labelledby</code> attribute for messages</legend>
<ul style="list-style: none">
<li><label><input id="selected_l" type="checkbox" checked=""/>Selected</label></li>
<li><label><input id="message_l" type="checkbox" checked=""/>Message Number</label></li>
<li><label><input id="status_l" type="checkbox" checked=""/>Read/Unread</label></li>
<li><label><input id="attachment_l" type="checkbox" checked=""/>Attchement</label></li>
<li><label><input id="priority_l" type="checkbox" checked=""/>Priority</label></li>
<li><label><input id="from_l" type="checkbox" checked=""/>From</label></li>
<li><label><input id="subject_l" type="checkbox" checked=""/>Subject</label></li>
<li><label><input id="date_l" type="checkbox"/>Date</label></li>
<li><label><input id="size_l" type="checkbox"/>Size</label></li>
</ul>
</fieldset>
<fieldset>
<legend>Configure ARIA <code>describedby</code> attribute for messages</legend>
<ul style="list-style: none">
<li><label><input id="selected_d" type="checkbox" checked=""/>Selected</label></li>
<li><label><input id="message_d" type="checkbox" checked=""/>Message Number</label></li>
<li><label><input id="status_d" type="checkbox" checked=""/>Read/Unread</label></li>
<li><label><input id="attachment_d" type="checkbox" checked=""/>Attchement</label></li>
<li><label><input id="priority_d" type="checkbox" checked=""/>Priority</label></li>
<li><label><input id="from_d" type="checkbox" checked=""/>From</label></li>
<li><label><input id="subject_d" type="checkbox" checked=""/>Subject</label></li>
<li><label><input id="date_d" type="checkbox"/>Date</label></li>
<li><label><input id="size_d" type="checkbox"/>Size</label></li>
</ul>
</fieldset>
</div>
</div>
Javascript Source Code
Show Javascript Source Code: globals.js
<script type="text/javascript">
/**
*
* The Globale Variables
*/
if (!window.Node) {
var Node = { // If there is no Node object, define one
ELEMENT_NODE: 1, // with the following properties and values.
ATTRIBUTE_NODE: 2, // Note that these are HTML node types only.
TEXT_NODE: 3, // For XML-specific nodes, you need to add
COMMENT_NODE: 8, // other constants here.
DOCUMENT_NODE: 9,
DOCUMENT_FRAGMENT_NODE: 11
}
}
var KEY_PAGEUP = 33;
var KEY_PAGEDOWN = 34;
var KEY_END = 35;
var KEY_HOME = 36;
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var KEY_SPACE = 32;
var KEY_TAB = 9;
var KEY_BACKSPACE = 8;
var KEY_DELETE = 46;
var KEY_ENTER = 13;
var KEY_INSERT = 45;
var KEY_ESCAPE = 27;
var KEY_F1 = 112;
var KEY_F2 = 113;
var KEY_F3 = 114;
var KEY_F4 = 115;
var KEY_F5 = 116;
var KEY_F6 = 117;
var KEY_F7 = 118;
var KEY_F8 = 119;
var KEY_F9 = 120;
var KEY_F10 = 121;
var KEY_M = 77;
var NS_XHTML = "http://www.w3.org/1999/xhtml"
var NS_STATE = "http://www.w3.org/2005/07/aaa";
// **********************************************
// *
// * Commonly used helper functions
// *
// **********************************************
/**
*
* nextSiblingElement
*
* @contructor
*/
function nextSiblingElement( node ) {
var next_node = node.nextSibling;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.nextSibling;
} // endwhile
return next_node;
}
/**
*
* previousSiblingElement
*
* @param ( node ) node object for which you are looking for the next sibling element node
*
* @return ( node) next sibling or "null"
*/
function previousSiblingElement( node ) {
var next_node = node.previousSibling;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.previousSibling;
} // endwhile
return next_node;
}
/**
*
* firstChildElement
*
* @param ( node ) node object for which you are looking for the first child element node
*
* @return ( node) next sibling or "null"
*/
function firstChildElement( node ) {
var next_node = node.firstChild;
while( next_node
&& (next_node.nodeType != Node.ELEMENT_NODE) ) {
next_node = next_node.nextSibling;
} // endwhile
return next_node;
}
/**
*
* getTextContentOfNode
*
* @contructor
*/
function getTextContentOfNode( node ) {
var next_node = node.firstChild;
var str = "";
while( next_node ) {
if( (next_node.nodeType == Node.TEXT_NODE ) &&
(next_node.length > 0 )
)
str += next_node.data;
next_node = next_node.nextSibling;
} // endwhile
return str;
}
/**
*
* setTextContentOfNode
*
* @contructor
*/
function setTextContentOfNode( node, text ) {
// Generate a new text node with the text value
var text_node = document.createTextNode(text);
// Remove child nodes to remove text
while (node.firstChild) {
node.removeChild(node.firstChild);
} // while
// Append new text to the container element
node.appendChild( text_node );
}
</script>
Show Javascript Source Code: widgets_inline.js
<script type="text/javascript">
// JavaScript Document
if (!window.Node) {
var Node = { // If there is no Node object, define one
ELEMENT_NODE: 1, // with the following properties and values.
ATTRIBUTE_NODE: 2, // Note that these are HTML node types only.
TEXT_NODE: 3, // For XML-specific nodes, you need to add
COMMENT_NODE: 8, // other constants here.
DOCUMENT_NODE: 9,
DOCUMENT_FRAGMENT_NODE: 11
}
}
var ARIA_STATE = "aria-";
/**
* Widgets Object is used to initialize a set of controls
* and provide a conveinence fuction to cancel event propagration
* @construtor
*/
function Widgets() {
this.widgets = new Array();
}
/**
* add is member of the Widgets Object
* and used add a widget ot the list of widgets to be intitialized
* as part of the onload event
* The controls array is the list of controls to initialize
* @member Enable
* @return none
*/
Widgets.prototype.add = function(obj) {
this.widgets[this.widgets.length] = obj;
}
/**
* init is member of the Widgets Object
* and is called by the onload event to initialize widgets in the web resource
* The controls array is the list of controls to initialize
* @member Enable
* @return none
*/
Widgets.prototype.init = function() {
for(var i = 0; i < this.widgets.length; i++ )
this.widgets[i].init();
}
//
// convience function for getting the node based on id
function _$( id ) {
return document.getElementById( id );
}
//
// WebBrowser object to abstract accessibility API differences between web standards supporting browsers and Internet Explorer 7.0
//
// The state variable keeps track of current state of checkbox
function WebBrowser() {
}
//
// keyCode is a function to get the keycode from a keypress event
//
// @param ( event object) event is an event object
//
// @return ( keycode )
WebBrowser.prototype.keyCode = function( event ) {
var e = event || window.event;
return e.keyCode;
}
/**
* OnClick Event Simulator
*
* @param ( node ) DOM node object
* @return nothing
*/
if( document.createEvent ) {
// If a web standards based browser implement this function
WebBrowser.prototype.simulateOnClickEvent = function( node ) {
// W3C DOM Events way to trigger a "click" event
var e = document.createEvent('MouseEvents');
e.initEvent( 'click', true, true );
node.dispatchEvent( e );
}
} else {
// If a Microsoft IE based browser implement this function
WebBrowser.prototype.simulateOnClickEvent = function( node ) {
var e = document.createEventObject();
node.fireEvent( "onclick", e );
} // endif
}
if ( document.addEventListener ) {
// If a web standards based browser implement this function
WebBrowser.prototype.setMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( clickHandler )
document.addEventListener( "click", clickHandler, true );
if( downHandler )
document.addEventListener( "mousedown", downHandler, true );
if( moveHandler )
document.addEventListener( "mousemove", moveHandler, true );
if( upHandler)
document.addEventListener( "mouseup", upHandler, true );
}
WebBrowser.prototype.releaseMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( upHandler)
document.removeEventListener( "mouseup", upHandler, true );
if( moveHandler )
document.removeEventListener( "mousemove", moveHandler, true );
if( downHandler )
document.removeEventListener( "mousedown", downHandler, true );
if( clickHandler )
document.removeEventListener( "click", clickHandler, true );
}
} else {
// If a Microsoft IE based browser implement this function
WebBrowser.prototype.setMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
node.setCapture();
if( clickHandler)
node.attachEvent( "onclick", clickHandler );
if( downHandler)
node.attachEvent( "onmousedown", downHandler );
if( moveHandler )
node.attachEvent( "onmousemove", moveHandler );
if( upHandler )
node.attachEvent( "onmouseup", upHandler );
} // endif
WebBrowser.prototype.releaseMouseCapture = function( node, clickHandler, downHandler, moveHandler, upHandler ) {
if( upHandler )
node.detachEvent( "onmouseup", upHandler );
if( moveHandler )
node.detachEvent( "onmousemove", moveHandler );
if( downHandler)
node.detachEvent( "onmousedown", downHandler );
if( clickHandler)
node.detachEvent( "onclick", clickHandler );
node.releaseCapture();
} // endif
}
if (typeof document.documentElement.setAttributeNS != 'undefined') {
WebBrowser.prototype.stopPropagation = function( event ) {
event.stopPropagation();
event.preventDefault();
return false;
}
WebBrowser.prototype.target = function( event ) {
return event.target;
}
WebBrowser.prototype.attrName = function( event ) {
return event.attrName
}
WebBrowser.prototype.charCode = function(event) {
return event.charCode;
}
WebBrowser.prototype.calculateOffsetLeft = function( node ) {
return node.offsetLeft;
}
WebBrowser.prototype.calculateOffsetTop = function( node ) {
return node.offsetTop;
}
WebBrowser.prototype.pageX = function( e ) {
return e.pageX;
}
WebBrowser.prototype.pageY = function( e ) {
return e.pageY;
}
WebBrowser.prototype.setNodePosition = function(node,left,top) {
node.style.left = left+"px";
node.style.top = top+"px";
}
} else {
WebBrowser.prototype.stopPropagation = function( event ) {
event.cancelBubble = true;
event.returnValue = false;
return false;
}
WebBrowser.prototype.charCode = function(event) {
return window.browser.keyCode( event );
}
WebBrowser.prototype.target = function( event ) {
return event.srcElement;
}
WebBrowser.prototype.attrName = function( event ) {
return event.propertyName;
}
WebBrowser.prototype.calculateOffsetLeft = function(node) {
var offset = 0;
while( node ) {
offset += node.offsetLeft;
node = node.offsetParent;
}
return offset;
}
WebBrowser.prototype.calculateOffsetTop = function(node) {
var offset = 0;
while( node ) {
offset = offset + node.offsetTop;
node = node.offsetParent;
}
return offset;
}
WebBrowser.prototype.pageX = function( e ) {
return e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
}
WebBrowser.prototype.pageY = function( e ) {
return e.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
}
WebBrowser.prototype.setNodePosition = function(node,left,top) {
offsetx = 0;
offsety = 0;
nnode = node.offsetParent
while( nnode ) {
offsetx = offsetx + nnode.offsetLeft;
offsety = offsety + nnode.offsetTop;
nnode = nnode.offsetParent;
}
node.style.left = left-offsetx+"px";
node.style.top = top-offsety+"px";
}
};
if (document.addEventListener) {
// Functions for W3C Standards compliant implementation of adding event handlers
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
elmTarget.addEventListener(sEventName, fCallback, false);
returnValue = true;
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
elmTarget.removeEventListener(sEventName, fCallback, false);
returnValue = true;
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
elmTarget.addEventListener("DOMAttrModified", fCallback, false);
returnValue = true;
};
} else {
if(document.attachEvent) {
// IE Specific Event handler functions
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
returnValue = elmTarget.attachEvent('on' + sEventName, fCallback);
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
returnValue = elmTarget.detachEvent('on' + sEventName, fCallback);
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
returnValue = elmTarget.attachEvent("onpropertychange", fCallback);
};
} else {
// For browsers that do not support W3C or IE event functions
WebBrowser.prototype.addEvent = function(elmTarget, sEventName, fCallback) {
return false;
};
WebBrowser.prototype.removeEvent = function(elmTarget, sEventName, fCallback) {
return false;
};
WebBrowser.prototype.addChangeEvent = function(elmTarget, fCallback) {
return false;
};
}
}
widgets_flag = true;
var widgets = new Widgets();
var browser = new WebBrowser();
function initApp() {
widgets.init();
}
</script>
Show Javascript Source Code: grid2.js
<script type="text/javascript">
// JavaScript Document
var focus_count = 0;
var blur_count = 0;
var blur_array = new Array();
var STATUS_UNREAD = 0;
var STATUS_READ = 1;
var PRIORITY_LOWEST = 1;
var PRIORITY_LOW = 2;
var PRIORITY_NORMAL = 3;
var PRIORITY_HIGH = 4;
var PRIORITY_HIGHEST = 5;
var MESSAGE_SELECTED = 0;
var MESSAGE_ID = 1;
var MESSAGE_STATUS = 2;
var MESSAGE_ATTACHMENT = 3;
var MESSAGE_PRIORITY = 4;
var MESSAGE_FROM = 5;
var MESSAGE_SUBJECT = 6;
var MESSAGE_DATE = 7;
var MESSAGE_SIZE = 8;
var MESSAGE_HIGHLIGHT = 9;
var SORT_ASCENDING = 1;
var SORT_DESCENDING = 2;
// This arrray used for calaculating ids and labels to give id somewhoat huan readable ids
var type_label = new Array();
type_label[MESSAGE_SELECTED] = "sel";
type_label[MESSAGE_ID] = "id";
type_label[MESSAGE_STATUS] = "read";
type_label[MESSAGE_ATTACHMENT] = "attch";
type_label[MESSAGE_PRIORITY] = "prior";
type_label[MESSAGE_FROM] = "from";
type_label[MESSAGE_SUBJECT] = "subj";
type_label[MESSAGE_DATE] = "date";
type_label[MESSAGE_SIZE] = "size";
// This array is used to detemine which columns to render and in what order
var message_order = new Array(MESSAGE_SELECTED,
MESSAGE_ID,
MESSAGE_STATUS,
MESSAGE_ATTACHMENT,
MESSAGE_PRIORITY,
MESSAGE_FROM,
MESSAGE_SUBJECT,
MESSAGE_DATE,
MESSAGE_SIZE);
/**
*
* checkLabelledbyConfiguration
* test to see if any of the configuration checkboxes are checked
*
* @return ( boolean ) flag indicates whether one or more of the labelledby checkboxes is checked
*
*/
function checkLabelledbyConfiguration() {
var flag = document.getElementById("selected_l").checked ||
document.getElementById("message_l").checked ||
document.getElementById("status_l").checked ||
document.getElementById("attachment_l").checked ||
document.getElementById("priority_l").checked ||
document.getElementById("from_l").checked ||
document.getElementById("subject_l").checked ||
document.getElementById("date_l").checked ||
document.getElementById("size_l").checked;
return flag;
}
/**
*
* getlablledbyForMessage
* Generate a list of ids for the labelledby of a messafe
*
* @param ( complexEmailGrid object ) grid is s grid
* @param ( integer ) message the index of the image in the list
*
* @return ( string ) a list of ids separated by spaces
*/
function getLablledbyForMessage( grid, message ) {
var idrefs = "";
if( document.getElementById("selected_l").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_SELECTED ) + " ";
if( document.getElementById("message_l").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_ID ) + " ";
if( document.getElementById("status_l").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_STATUS ) + " ";
if( document.getElementById("attachment_l").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_ATTACHMENT ) + " ";
if( document.getElementById("priority_l").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_PRIORITY ) + " ";
if( document.getElementById("from_l").checked) {
idrefs += calcHeaderCellId( grid, MESSAGE_FROM ) + " ";
idrefs += calcGridcellId( grid, message, MESSAGE_FROM ) + " ";
} // endif
if( document.getElementById("subject_l").checked) {
idrefs += calcHeaderCellId( grid, MESSAGE_SUBJECT ) + " ";
idrefs += calcGridcellId( grid, message, MESSAGE_SUBJECT ) + " ";
}
if( document.getElementById("date_l").checked) {
idrefs += calcHeaderCellId( grid, MESSAGE_DATE ) + " ";
idrefs += calcGridcellId( grid, message, MESSAGE_DATE ) + " ";
} // endif
if( document.getElementById("size_l").checked) {
idrefs += calcHeaderCellId( grid, MESSAGE_SIZE ) + " ";
idrefs += calcGridcellId( grid, message, MESSAGE_SIZE );
} // endif
return idrefs;
}
/**
*
* checkDescribedbyConfiguration
* test to see if any of the configuration checkboxes are checked
*
* @return ( boolean ) flag indicates whether one or more of the labelledby checkboxes is checked
*
*/
function checkDescribedbyConfiguration() {
var flag = document.getElementById("selected_d").checked ||
document.getElementById("message_d").checked ||
document.getElementById("status_d").checked ||
document.getElementById("attachment_d").checked ||
document.getElementById("priority_d").checked ||
document.getElementById("from_d").checked ||
document.getElementById("subject_d").checked ||
document.getElementById("date_d").checked ||
document.getElementById("size_d").checked;
return flag;
}
/**
*
* getDescribedbyForMessage
* Generate a list of ids for the describedby
*
* @param ( complexEmailGrid object ) grid is s grid
* @param ( integer ) message the index of the image in the list
*
* @return ( string ) a list of ids separated by spaces
*/
function getDescribedbyForMessage( grid, message ) {
var idrefs = "";
if( document.getElementById("selected_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_SELECTED ) + " ";
if( document.getElementById("message_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_ID ) + " ";
if( document.getElementById("status_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_STATUS ) + " ";
if( document.getElementById("attachment_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_ATTACHMENT ) + " ";
if( document.getElementById("priority_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_PRIORITY ) + " ";
if( document.getElementById("from_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_FROM ) + " ";
if( document.getElementById("subject_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_SUBJECT ) + " ";
if( document.getElementById("date_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_DATE ) + " ";
if( document.getElementById("size_d").checked)
idrefs += calcGridcellId( grid, message, MESSAGE_SIZE );
return idrefs;
}
/**
*
* The calcGridcellId
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( integer ) message index of the message list
*
* @return ( string ) the unique id for a message container (TR element)
*/
function calcMessageId( grid, message ) {
return grid.id + "_message" + message;
}
/**
*
* The calcHeaderRowId
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
*
* @return ( string ) the unique id for a message container (TR element)
*/
function calcHeaderRowId( grid ) {
return grid.id + "_header";
}
/**
*
* The calcGridcellId
* Create a table cell node for the grid cell
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( integer ) message_num is the current message number
* @param ( integer ) data_type itentifies the type of message data in the cell
*
* @retuen ( string ) the return value is the id for the cell
*/
function calcGridcellId( grid, message_num, data_type ) {
return grid.id + "_message" + message_num + "_" + type_label[data_type];
}
/**
*
* The calcHeaderCellId
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( integer ) data_type itentifies the type of message data
*
* @retuen ( string ) the return value is the id for the cell
*/
function calcHeaderCellId( grid, data_type ) {
return grid.id + "_" + type_label[data_type];
}
/**
*
* The complexEmailHeader
* Create a table header cell node for the column heading
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( string ) text for the heade cell
* @param ( string ) css_style will be used to style content using CSS
*
* @return ( node ) return DOM node with the header cell
*/
function complexEmailHeader( email_grid, type, text, abbr, css_style ) {
var node_th = document.createElement("th");
browser.addEvent( node_th, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_th, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
if( (type != MESSAGE_ID) && (type != MESSAGE_SELECTED) ) {
browser.addEvent( node_th, "click", function(event) {handleComplexEmailGridHeaderClickEvent(event, email_grid, type);}, false);
browser.addEvent( node_th, "keydown", function(event) {handleComplexEmailGridHeaderKeyDownEvent(event, email_grid, type);}, false);
node_th.setAttribute("role", "button");
} else {
node_th.setAttribute("role", "gridcell");
} // endif
node_th.id = calcHeaderCellId( email_grid, type );
if( css_style != "" )
node_th.className = css_style;
// Set ARIA Properties
node_th.tabIndex = -1;
if( abbr ) {
var node_text = document.createTextNode(text);
var node_abbr = document.createElement("abbr");
node_abbr.setAttribute("title", abbr );
node_abbr.appendChild( node_text );
node_th.appendChild( node_abbr );
} else {
var node_text = document.createTextNode(text);
node_th.appendChild( node_text );
}
return node_th;
}
/**
*
* The complexEmailHeaders object contains information about the current e-mail message
* and methods to render the headers
*
* @contructor
*/
function complexEmailHeaders() {
this.cellMarkup = new Array();
this.label = new Array();
this.label[MESSAGE_SELECTED] = "Selected";
this.cellMarkup[MESSAGE_SELECTED] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_SELECTED, "Sel", "Selected", "" );
} // end function
this.label[MESSAGE_ID] = "Message Number";
this.cellMarkup[MESSAGE_ID] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_ID, "Mes", "Message", "" );
} // end function
this.label[MESSAGE_STATUS] = "Status";
this.cellMarkup[MESSAGE_STATUS] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_STATUS, "Status", "", "" );
} // end function
this.label[MESSAGE_ATTACHMENT] = "Attachment";
this.cellMarkup[MESSAGE_ATTACHMENT] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_ATTACHMENT, "Att", "Attchment", "" );
} // end function
this.label[MESSAGE_PRIORITY] = "Priority";
this.cellMarkup[MESSAGE_PRIORITY] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_PRIORITY, "Pri", "Priority", "" );
} // end function
this.label[MESSAGE_FROM] = "From";
this.cellMarkup[MESSAGE_FROM] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_FROM, "From", "", "" );
} // end function
this.label[MESSAGE_SUBJECT] = "Subject";
this.cellMarkup[MESSAGE_SUBJECT] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_SUBJECT, "Subject", "", "" );
} // end function
this.label[MESSAGE_DATE] = "Date";
this.cellMarkup[MESSAGE_DATE] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_DATE, "Date", "", "" );
} // end function
this.label[MESSAGE_SIZE] = "Size";
this.cellMarkup[MESSAGE_SIZE] = function( grid ) {
return complexEmailHeader( grid, MESSAGE_SIZE, "Size", "", "" );
} // end function
}
/**
*
* The complexEmailMessageText
* Create a table cell node for the grid cell
*
* @param ( complexEmailGrid Object ) emil_grid object contraining the messages
* @param ( integer ) message is the number of the message
* @param ( integer ) type is the type of message data in this cell
* @param ( string ) text for the text node
* @param ( string ) css_style is the class name for the td element
*
* @return ( node ) DOM node for grid cell
*/
function complexEmailMessageText( email_grid, message, type, text, css_style ) {
var node_td = document.createElement("td");
node_td.id = calcGridcellId( email_grid, message, type );
node_td.className = css_style;
// Add event handlers to update visual styling when grid cell receives and looses focus
browser.addEvent( node_td, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_td, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
// Set ARIA Properties
node_td.setAttribute("role", "gridcell");
node_td.tabIndex = -1;
node_td.setAttribute("aria-labelledby", calcHeaderCellId(email_grid, type ) + " " + node_td.id );
var node_text = document.createTextNode(text);
node_td.appendChild( node_text );
return node_td;
}
/**
*
* The complexEmailMessageImage
* Create a table cell node for the grid cell
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( integer ) message is the number of the message
* @param ( integer ) type is the type of message data in this cell
* @param ( src ) uri the uri to the image
* @param ( text ) alt is a text equivalent for the image
* @param ( string ) css_style will be used to style content using CSS
*
* @return ( node ) DOM node for grid cell
*/
function complexEmailMessageImage( email_grid, message, type, src, alt, css_style ) {
var node_td = document.createElement("td");
node_td.id = calcGridcellId( email_grid, message, type );
node_td.className = css_style;
// Add event handlers to update visual styling when grid cell receives and looses focus
browser.addEvent( node_td, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_td, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
// Add ARIA information
node_td.setAttribute("role", "gridcell");
node_td.tabIndex = -1;
node_td.setAttribute("aria-labelledby", calcHeaderCellId(email_grid, type ) + " " + node_td.id );
var node_img = document.createElement("img");
node_img.setAttribute( "src", src );
node_img.setAttribute( "alt", alt );
node_td.appendChild( node_img );
return node_td;
}
/**
*
* The complexEmailMessageCheckbox
* Create a table cell node for the grid cell
*
* @param ( complexEmailGrid Object ) grid object contraining the messages
* @param ( integer ) message is the number of the message
* @param ( integer ) type is the type of message data in this cell
* @param ( boolean ) flag indicates if the message is selected
* @param ( string ) label for the checkbox form control
* @param ( string ) css_style will be used to style content using CSS
*/
function complexEmailMessageCheckbox( email_grid, message, type, flag, label, css_style ) {
var node_td = document.createElement("td");
node_td.id = calcGridcellId( email_grid, message, type );
node_td.className = css_style;
// Add event handlers to update visual styling when grid cell receives and looses focus
browser.addEvent( node_td, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_td, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
// Add ARIA information
node_td.setAttribute("role", "gridcell");
node_td.tabIndex = -1;
node_td.setAttribute("aria-labelledby", calcHeaderCellId(email_grid, type ) + " " + node_td.id );
var node_input = document.createElement("input");
node_input.setAttribute("type", "checkbox");
node_input.setAttribute("name", "selected_" + message );
node_input.setAttribute("title", label);
// Removed checkbox from TAB order
node_input.tabIndex = -1;
node_input.checked = flag;
node_td.appendChild( node_input );
return node_td;
}
/**
*
* The ComplexEmailMessage object contains information about the current e-mail message
* and methods to render the message
*
* @contructor
*/
function ComplexEmailMessage() {
this.data = new Array();
this.cellMarkup = new Array();
this.id = null;
this.highlight = false;
this.selected = false;
// function to update checkbox when the item is selected
this.checkboxId = null;
// id
this.data[MESSAGE_ID] = null;
// add fuction for creating markup for rendering id
this.cellMarkup[MESSAGE_ID] = function( grid, message ) {
return complexEmailMessageText( grid, message, MESSAGE_ID, grid.messages[message].data[MESSAGE_ID], "center");
} // end function
// Selected state information
this.data[MESSAGE_SELECTED] = false;
// add fuction for creating markup for rendering selected infotmation
this.cellMarkup[MESSAGE_SELECTED] = function( grid, message) {
grid.messages[message].checkboxId = calcGridcellId( grid, message, MESSAGE_SELECTED );
return complexEmailMessageCheckbox( grid, message, MESSAGE_SELECTED, grid.messages[message].data[MESSAGE_SELECTED], "Email " + message + " Selected","");
} // end function
// Status of being read
this.data[MESSAGE_STATUS] = STATUS_UNREAD;
// add fuction for creating markup for rendering information about a message being read
this.cellMarkup[MESSAGE_STATUS] = function( grid, message) {
if( grid.messages[message].data[MESSAGE_STATUS] )
return complexEmailMessageImage( grid, message, MESSAGE_STATUS, "http://test.cita.uiuc.edu/aria/grid/images/read.gif", "Read message" ,"center");
else
return complexEmailMessageImage( grid, message, MESSAGE_STATUS, "http://test.cita.uiuc.edu/aria/grid/images/unread.gif", "New message" ,"center");
} // end function
// Attachment
this.data[MESSAGE_ATTACHMENT] = false;
// add fuction for creating markup for rendering information about a message being read
this.cellMarkup[MESSAGE_ATTACHMENT] = function( grid, message) {
if( grid.messages[message].data[MESSAGE_ATTACHMENT] )
return complexEmailMessageImage( grid, message, MESSAGE_ATTACHMENT, "http://test.cita.uiuc.edu/aria/grid/images/attach.gif", "Attachment" ,"center");
else
return complexEmailMessageImage( grid, message, MESSAGE_ATTACHMENT, "http://test.cita.uiuc.edu/aria/grid/images/noattach.gif", "None" ,"center");
} // end function
// Email priority
this.data[MESSAGE_PRIORITY] = PRIORITY_NORMAL;
// add fuction for creating markup for rendering information about a message being read
this.cellMarkup[MESSAGE_PRIORITY] = function( grid, message) {
switch( grid.messages[message].data[MESSAGE_PRIORITY] ) {
case PRIORITY_LOWEST:
return complexEmailMessageImage( grid, message, MESSAGE_PRIORITY, "http://test.cita.uiuc.edu/aria/grid/images/priority_lowest.gif", "Lowest priority" ,"center");
break;
case PRIORITY_LOW:
return complexEmailMessageImage( grid, message, MESSAGE_PRIORITY, "http://test.cita.uiuc.edu/aria/grid/images/priority_low.gif", "Low priority" ,"center");
break;
case PRIORITY_HIGH:
return complexEmailMessageImage( grid, message, MESSAGE_PRIORITY, "http://test.cita.uiuc.edu/aria/grid/images/priority_high.gif", "High priority" ,"center");
break;
case PRIORITY_HIGHEST:
return complexEmailMessageImage( grid, message, MESSAGE_PRIORITY, "http://test.cita.uiuc.edu/aria/grid/images/priority_highest.gif", "Highest priority" ,"center");
break;
default:
return complexEmailMessageImage( grid, message, MESSAGE_PRIORITY, "http://test.cita.uiuc.edu/aria/grid/images/priority_none.gif", "" ,"center");
break;
} // end switch
} // end function
// Email From
this.data[MESSAGE_FROM] = "Unkown";
// add fuction for creating markup for rendering the message is from
this.cellMarkup[MESSAGE_FROM] = function( grid, message) {
return complexEmailMessageText( grid, message, MESSAGE_FROM, grid.messages[message].data[MESSAGE_FROM], "");
} // end function
// Email Subject
this.data[MESSAGE_SUBJECT] = "No subject";
// add fuction for creating markup for rendering the subject of the message
this.cellMarkup[MESSAGE_SUBJECT] = function( grid, message) {
return complexEmailMessageText( grid, message, MESSAGE_SUBJECT, grid.messages[message].data[MESSAGE_SUBJECT], "");
} // end function
// Email Date
this.data[MESSAGE_DATE] = "No date";
// add fuction for creating markup for rendering the subject of the message
this.cellMarkup[MESSAGE_DATE] = function( grid, message ) {
return complexEmailMessageText( grid, message, MESSAGE_DATE, grid.messages[message].data[MESSAGE_DATE], "");
} // end function
// Email Size
this.data[MESSAGE_SIZE] = "No size";
// add fuction for creating markup for rendering who the size of the message
this.cellMarkup[MESSAGE_SIZE] = function( grid, message) {
return complexEmailMessageText( grid, message, MESSAGE_SIZE, grid.messages[message].data[MESSAGE_SIZE], "");
} // end function
}
/**
*
* The ComplexEmailGrid object is used to maintain information about a e-mail list widget
*
* @contructor
*/
function ComplexEmailGrid( id ) {
this.id = id;
this.in_headers = false;
this.current_message = -1;
this.current_column = -1;
this.last_node = null;
this.messages = new Array();
this.current_sort = MESSAGE_DATE;
this.sort_direction = SORT_ASCENDING;
}
/**
* init is a subclass of complexEmailGrid and is used to initialize data
* the event handlers and for complexEmailGrid
*
* @member complexEmailGrid
*
* @return nothing
*/
ComplexEmailGrid.prototype.init = function() {
this.node = document.getElementById( this.id );
// Initialize data model for the grid
// TBODY contains the information on all the current e-mail messages
var message_data = this.node.getElementsByTagName("tbody")[0];
// if there is a TBODY element extract e-mail data
if( message_data ) {
var message_rows = message_data.getElementsByTagName("tr");
for(var row = 0; row < message_rows.length; row++ ) {
var message_data = message_rows[row].getElementsByTagName("td");
// see if message data is complete
if( message_data.length == 9) {
var message = new ComplexEmailMessage( row );
// Get selected
message.data[MESSAGE_SELECTED] = message_data[0].getElementsByTagName("input")[0].checked;
// Get message id
message.data[MESSAGE_ID] = getTextContentOfNode(message_data[1]);
// Has message been read?
message.data[MESSAGE_STATUS] = getTextContentOfNode(message_data[2]).match(/true/) >= 0;
// Attachment
message.data[MESSAGE_ATTACHMENT] = getTextContentOfNode(message_data[3]).match(/true/) >= 0;
// Email priority
message.data[MESSAGE_PRIORITY] = parseInt(getTextContentOfNode(message_data[4]));
// From
message.data[MESSAGE_FROM] = getTextContentOfNode(message_data[5]);
// Subject
message.data[MESSAGE_SUBJECT] = getTextContentOfNode(message_data[6]);
// Date
message.data[MESSAGE_DATE] = getTextContentOfNode(message_data[7]);
// Size
message.data[MESSAGE_SIZE] = getTextContentOfNode(message_data[8]);;
// Highlight
message.data[MESSAGE_HIGHLIGHT] = false;
// Add the message to the list
this.messages[this.messages.length] = message;
} // endif
} // endfor
} // endif
// Render E-mail headers using javascript
this.headers = new complexEmailHeaders();
complexEmailGridRenderHeaders( this );
// Render E-mail data using javascript
complexEmailGridRenderMessages( this );
var obj = this;
// Add event handlers for selecting a email grid
browser.addEvent(this.node, "keydown", function(event) {handleComplexEmailGridKeyDownEvent(event, obj);}, false);
browser.addEvent(this.node, "focus", function(event) {handleComplexEmailGridTableFocusEvent(event, obj);}, false);
browser.addEvent(this.node, "click", function(event) {handleComplexEmailGridClickEvent(event, obj );}, false);
}
/**
* complexEmailGridSetHeaderFocus
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
* @param ( integer ) column of the column to highlight
*
* @return nothing
*/
function complexEmailGridSetHeaderFocus( email_grid, column ) {
if( column >= message_order.length )
column = message_order.length - 1;
if( ( column >= 0 ) &&
( column < message_order.length ) )
{
// do this if one of the columns is selected
email_grid.current_column = column;
email_grid.last_node = document.getElementById(calcHeaderCellId(email_grid, message_order[column]));
} else {
//
// do this if no column is selected
email_grid.last_node = document.getElementById(calcHeaderRowId( email_grid ));
} // endif
email_grid.last_node.focus();
}
/**
* complexEmailGridSetFocus
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
* @param ( integer ) message of the message to highlight
* @param ( integer ) column of the column to highlight
*
* @return nothing
*/
function complexEmailGridSetFocus( email_grid, message, column ) {
if( column >= message_order.length )
column = message_order.length - 1;
if( (message >= 0 ) &&
(message < email_grid.messages.length)
) {
if( ( column >= 0 ) &&
( column < message_order.length ) )
{
// do this if one of the columns is selected
email_grid.current_message = message;
email_grid.current_column = column;
email_grid.last_node = document.getElementById(calcGridcellId(email_grid, message, message_order[column]));
} else {
//
// do this if no column is selected
email_grid.current_message = message;
email_grid.last_node = document.getElementById(email_grid.messages[message].id);
} // endif
email_grid.last_node.focus();
} // endif
}
/**
* complexEmailGridSelected
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
* @param ( integer ) message of the message to highlight
* @param ( boolean ) boolean value on whether to highlight or to remove
*
* @return nothing
*/
function complexEmailGridSetSelected( email_grid, message, flag ) {
if( (message >= 0 ) && ( message < email_grid.messages.length ) ) {
email_grid.messages[message].selected = flag;
document.getElementById(email_grid.messages[message].checkboxId).getElementsByTagName("input")[0].checked = flag;
var node = document.getElementById(email_grid.messages[message].id);
// set ARIA flags
if( flag ) {
node.setAttribute("aria-selected", "true");
if( node.className.search(/selected/i) < 0) {
node.className += " selected";
}
} else {
node.setAttribute("aria-selected", "false");
// remove selected from current node
node.className = email_grid.last_node.className.replace(/selected/i,"");
} // endif
} // endif
}
/**
* complexEmailGridToggledSelected
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
*
* @return nothing
*/
function complexEmailGridToggleSelected( email_grid ) {
if( email_grid.messages[email_grid.current_message].selected )
complexEmailGridSetSelected( email_grid, email_grid.current_message, false );
else
complexEmailGridSetSelected( email_grid, email_grid.current_message, true );
}
/**
* complexEmailGridRenderHeaders
* creates a dom node with renderable HTML mark up of current header cells
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
*
* @return nothing
*/
function complexEmailGridRenderHeaders( email_grid ) {
var node_new_header = document.createElement("thead");
var node_headings = document.createElement("tr");
browser.addEvent( node_headings, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_headings, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
// Make the row keyboard focusable using tabindex attribute
node_headings.tabIndex = -1;
// Add a id
node_headings.id = calcHeaderRowId( email_grid );
// Set the role of the role to grid cell
node_headings.setAttribute("role","group");
// add new table row markup
node_new_header.appendChild( node_headings );
for(var j = 0; j < message_order.length; j++ ) {
var node = email_grid.headers.cellMarkup[message_order[j]]( email_grid );
node_headings.appendChild( node);
} // endfor
var node_data = email_grid.node.getElementsByTagName("thead")[0];
// remove current grid information on messages
email_grid.node.removeChild( node_data );
// add updated rendering information on about messages
email_grid.node.appendChild( node_new_header );
complexEmailGridUpdateHeaderStyling( email_grid );
}
/**
* complexEmailGridUpdateHeaderStyling
* creates a dom node with renderable HTML mark up for current messages
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
*
* @return nothing
*/
function complexEmailGridUpdateHeaderStyling( email_grid ) {
// reset styling of ascending or descending for the header cells
for(var j = 0; j < message_order.length; j++ ) {
var node = document.getElementById(calcHeaderCellId(email_grid, message_order[j]));
if( node.className.search(/descending/) >= 0 )
node.className = node.className.replace(/descending/i,"");
if( node.className.search(/ascending/) >= 0 )
node.className = node.className.replace(/ascending/i,"");
if( email_grid.current_sort == message_order[j] ) {
if( email_grid.sort_direction == SORT_ASCENDING ) {
node.className += " ascending";
var text = "Messages Sorted by " + email_grid.headers.label[message_order[j]] + ": Ascending Order";
} else {
node.className += " descending";
var text = "Messages Sorted by " + email_grid.headers.label[message_order[j]] + ": Descending Order";
} // endif
email_grid.node.deleteCaption();
var text_node = document.createTextNode( text );
email_grid.node.createCaption().appendChild( text_node );
} // endif
} // endfor
}
/**
* complexEmailGridRenderMessages
* creates a dom node with renderable HTML mark up for current messages
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to render
*
* @return nothing
*/
function complexEmailGridRenderMessages( email_grid ) {
var node_new_data = document.createElement("tbody");
for(var i = 0; i < email_grid.messages.length; i++ ) {
var node_message = document.createElement("tr");
// Focus and blur events update visual styling of the node with focus
browser.addEvent( node_message, "focus", function(event) {handleComplexEmailGridFocusEvent(event, email_grid);}, false);
browser.addEvent( node_message, "blur", function(event) {handleComplexEmailGridBlurEvent(event, email_grid);}, false);
// Make the row keyboard focusable using tabindex attribute
node_message.tabIndex = -1;
// Set the role of the role to grid cell
node_message.setAttribute("role","group");
// Set the labelledby of message if any of the confurgation controls is set
if( checkLabelledbyConfiguration() )
node_message.setAttribute("aria-labelledby", getLablledbyForMessage( email_grid, i ));
// Set the labelledby of message if any of the confurgation controls is set
if( checkDescribedbyConfiguration() )
node_message.setAttribute("aria-describedby", getDescribedbyForMessage( email_grid, i ));
// set the id of the grid cell
node_message.id = calcMessageId( email_grid, i );
// save the id as part of the message data
email_grid.messages[i].id = node_message.id;
for( var j = 0; j < message_order.length; j++ ) {
var node = email_grid.messages[i].cellMarkup[message_order[j]]( email_grid, i );
node_message.appendChild( node);
} // endfor
node_new_data.appendChild( node_message );
} // endfor
var node_data = email_grid.node.getElementsByTagName("tbody")[0];
// remove current grid information on messages
email_grid.node.removeChild( node_data );
// add updated rendering information on about messages
email_grid.node.appendChild( node_new_data );
}
/**
* complexEmailGridUpdateMessageLabels
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object to update labeling
*/
function complexEmailGridUpdateMessageLabels( email_grid ) {
for(var i = 0; i < email_grid.messages.length; i++ ) {
// Set the labelledby of message if any of the confurgation controls is set
if( checkLabelledbyConfiguration() )
document.getElementById(email_grid.messages[i].id).setAttribute("aria-labelledby", getLablledbyForMessage( email_grid, i ));
else
document.getElementById(email_grid.messages[i].id).setAttribute("aria-labelledby", "");
// Set the labelledby of message if any of the confurgation controls is set
if( checkDescribedbyConfiguration() )
document.getElementById(email_grid.messages[i].id).setAttribute("aria-describedby", getDescribedbyForMessage( email_grid, i ));
else
document.getElementById(email_grid.messages[i].id).setAttribute("aria-describedby", "");
} // endfor
}
/**
* complexEmailGridSortAscending
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that will be sorted
* @param ( integer ) type is the data type to sort by
*
* @return false if keyboard event was used by the Email grid, else true
*/
function complexEmailGridSortAscending( email_grid, type ) {
for(var i = 0; i < email_grid.messages.length; i ++ ) {
for(var j = i + 1; j < email_grid.messages.length; j++ ) {
if( email_grid.messages[i].data[type] > email_grid.messages[j].data[type] ) {
var temp = email_grid.messages[i] ;
email_grid.messages[i] = email_grid.messages[j];
email_grid.messages[j] = temp;
email_grid.messages[i].data[MESSAGE_ID] = i;
} // endif
} // endif
} // endfor
}
/**
* complexEmailGridSortDescending
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that will be sorted
* @param ( integer ) type is the data type to sort by
*
* @return false if keyboard event was used by the Email grid, else true
*/
function complexEmailGridSortDescending( email_grid, type ) {
for(var i = 0; i < email_grid.messages.length; i ++ ) {
for(var j = i + 1; j < email_grid.messages.length; j++ ) {
if( email_grid.messages[i].data[type] < email_grid.messages[j].data[type] ) {
var temp = email_grid.messages[i] ;
email_grid.messages[i] = email_grid.messages[j];
email_grid.messages[j] = temp;
email_grid.messages[i].data[MESSAGE_ID] = i;
} // endif
} // endif
} // endfor
}
/**
* complexEmailGridSortType
*
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that will be sorted
* @param ( integer ) type is the data type to sort by
*
* @return false if keyboard event was used by the Email grid, else true
*/
function complexEmailGridSortType( email_grid, type ) {
if( email_grid.current_sort == type ) {
if( email_grid.sort_direction == SORT_ASCENDING ) {
complexEmailGridSortDescending( email_grid, type );
email_grid.sort_direction = SORT_DESCENDING;
} else {
complexEmailGridSortAscending( email_grid, type );
email_grid.sort_direction = SORT_ASCENDING;
} // endif
} else {
complexEmailGridSortAscending( email_grid, type );
email_grid.current_sort = type;
email_grid.sort_direction = SORT_ASCENDING;
} // endif
complexEmailGridUpdateHeaderStyling( email_grid);
complexEmailGridRenderMessages( email_grid );
}
/**
* handleComplexEmailGridKeyDownEvent processes keys associated with a radio button group
*
* @param ( event ) event is the event handler for the event
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that is the target of the keyboard event
*
* @return false if keyboard event was used by the Email grid, else true
*/
function handleComplexEmailGridKeyDownEvent( event, email_grid ) {
var e = event || windows.event;
switch( e.keyCode ) {
case KEY_DOWN:
if( email_grid.in_headers ) {
complexEmailGridSetFocus( email_grid, 0, email_grid.current_column);
email_grid.in_headers = false;
} else {
complexEmailGridSetFocus( email_grid, email_grid.current_message + 1, email_grid.current_column);
} // endif
return browser.stopPropagation(event);
break;
case KEY_UP:
if( !email_grid.in_headers && (email_grid.current_message > 0 ) ) {
complexEmailGridSetFocus( email_grid, email_grid.current_message - 1, email_grid.current_column);
} else {
email_grid.current_message = -1;
email_grid.in_headers = true;
complexEmailGridSetHeaderFocus( email_grid, email_grid.current_column);
} // endif
return browser.stopPropagation(event);
break;
case KEY_LEFT:
if( email_grid.in_headers ) {
if( email_grid.current_column > 0 )
complexEmailGridSetHeaderFocus( email_grid, email_grid.current_column - 1);
else
complexEmailGridSetHeaderFocus( email_grid, 0 );
} else {
if( email_grid.current_column > 0 )
complexEmailGridSetFocus( email_grid, email_grid.current_message, email_grid.current_column - 1 );
else
complexEmailGridSetFocus( email_grid, email_grid.current_message, 0 );
} // endif
return browser.stopPropagation(event);
break;
case KEY_RIGHT:
if( email_grid.in_headers ) {
if( email_grid.current_column >= 0 )
complexEmailGridSetHeaderFocus( email_grid, email_grid.current_column + 1 );
else
complexEmailGridSetHeaderFocus( email_grid, 0 );
} else {
if( email_grid.current_column >= 0 )
complexEmailGridSetFocus( email_grid, email_grid.current_message, email_grid.current_column + 1 );
else
complexEmailGridSetFocus( email_grid, email_grid.current_message, 0 );
} // endif
return browser.stopPropagation(event);
break;
case KEY_SPACE:
if( !email_grid.in_headers )
if( e.ctrlKey ) {
email_grid.current_column = -1;
complexEmailGridSetFocus( email_grid, email_grid.current_message, -1 );
} else {
complexEmailGridToggleSelected( email_grid );
} // endif
return browser.stopPropagation(event);
break;
}
return true;
}
/**
* handleComplexEmailGridTableFocusEvent
*
* @param ( event ) event is the event handler for the event
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that is the target of the pointer event
*
* @return false if poiner event was used by radio group, else true
*/
function handleComplexEmailGridTableFocusEvent( event, email_grid ) {
var node = browser.target( event );
if( node.id == email_grid.node.id ) {
email_grid.node.className = "emailfocus";
email_grid.node.tabIndex = -1;
if( email_grid.last_node == null )
complexEmailGridSetFocus( email_grid, 0, -1 );
else
complexEmailGridSetFocus( email_grid, email_grid.current_message, email_grid.current_column );
} // endif
}
/**
* handleComplexEmailGridFocusEvent
*
* @param ( event ) event is the event handler for the event
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that is the target of the pointer event
* @return false if poiner event was used by radio group, else true
*/
function handleComplexEmailGridFocusEvent( event, email_grid ) {
var node = browser.target( event );
email_grid.node.className = "emailfocus";
if( node.id != email_grid.node.id ) {
// if highlight is already set don't set again
if( node.className.search(/highlight/i) < 0)
node.className += " highlight";
node.tabIndex = 0;
} // endif
/*
focus_count++;
document.getElementById("focusc").value = focus_count;
blur_array[blur_array.length] = "FOCUS " + focus_count + ": " + node.id + " " + email_grid.node.id + " " + node.className;
*/
}
/**
* handleComplexEmailGridBlurEvent
*
* @param ( event ) event is the event handler for the event
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that is the target of the pointer event
*
* @return nothing
*/
function handleComplexEmailGridBlurEvent( event, email_grid ) {
var node = browser.target( event );
email_grid.node.className = "email";
if( node != email_grid.node ) {
// remove highlight from current node
node.className = node.className.replace(/highlight/i,"");
node.tabIndex = -1;
email_grid.node.tabIndex = 0;
/*
blur_count++;
document.getElementById("blurc").value = blur_count;
blur_array[blur_array.length] = "BLUR " + blur_count + ": " + event.target.id + " " + node.className;
*/
} // endif
}
/**
* handleComplexEmailGridClickEvent processes pointer click events with in the complexEmailGrid widget
*
* @param ( event ) event is the event handler for the event
* @param ( complexEmailGrid object ) email_grid is the complexEmailGrid object that is the target of the pointer event
*
* @return false if poiner event was used by radio group, else true
*/
function handleComplexEmailGridClickEvent( event, email_grid ) {
var node = browser.target( event );
while( node &&
( node.tagName.search(/tr/i) < 0 )
) {
node = node.parentNode;
}
if( node ) {
// find message number
var result = node.id.match(/(message)([d])/);
if( result && result[2] ) {
var message = new Number(result[2]);
email_grid.in_headers = false;
complexEmailGridSetFocus( email_grid, message, -1 );
complexEmailGridToggleSelected( email_grid );
} else {
email_grid.current_message = -1;
email_grid.in_headers = true;
complexEmailGridSetHeaderFocus( email_grid, -1);
} // endif
} // endif
}
/**
* handleConfigurationToggleClickEvent
* Show and hide configuration information
*
* @param ( event ) event is the event handler for the event
* @param ( id ) id of the content to show or hide
*
* @return false to prevent event bubbling
*/
function handleConfigurationToggleClickEvent( event, id ) {
if( document.getElementById( id ).style.display == "block" ) {
document.getElementById( id ).style.display = "none";
event.target.value = "Show Labelledby and Describedby settings for messages";
} else {
document.getElementById( id ).style.display = "block";
event.target.value = "Hide Labelledby and Describedby settings for messages";
} // endif
return false;
}
/**
* handleComplexEmailGridApplyClickEvent
* Show and hide configuration information
*
* @param ( event ) event is the event handler for the event
* @param ( grid object ) id of the content to show or hide
*
* @return false to prevent event bubbling
*/
function handleComplexEmailGridApplyClickEvent( event, email_grid ) {
// Render E-mail data using javascript
complexEmailGridUpdateMessageLabels( email_grid );
return false;
}
/**
* handleComplexEmailGridHeaderClickEvent
* Show and hide configuration information
*
* @param ( event ) event is the event handler for the event
* @param ( ComplexEmailGrid object ) id of the content to show or hide
* @param ( integer ) type is the data type of the header
*
* @return false to prevent event bubbling
*/
function handleComplexEmailGridHeaderClickEvent(event, email_grid, type) {
complexEmailGridSortType( email_grid, type );
email_grid.in_headers = true;
this.current_message = -1;
// calculate what column contains the type of message
var i = 0;
while( (i < message_order.length ) && (message_order[i] != type) )
i++;
if( i < message_order.length )
email_grid.current_column = i;
else
email_grid.current_column = -1;
email_grid.last_node = browser.target( event );
return browser.stopPropagation(event);
}
/**
* handleComplexEmailGridHeaderKeyDownEvent
* Show and hide configuration information
*
* @param ( event ) event is the event handler for the event
* @param ( ComplexEmailGrid object ) id of the content to show or hide
* @param ( integer ) type is the data type of the header
*
* @return false to prevent event bubbling
*/
function handleComplexEmailGridHeaderKeyDownEvent(event, email_grid, type) {
var e = event || windows.event;
if( e.keyCode == KEY_SPACE ) {
complexEmailGridSortType( email_grid, type );
browser.stopPropagation( event );
return false;
} else {
return true;
}// endif
}
</script>
CSS Source Code
Show CSS Source Code: grid2.css
<style type="text/css">
body {
font-size: medium;
font-family: sans-serif;
}
.warning {
color: red;
font-weight: bold;
}
table.email {
border: gray solid 2px;
}
table.emailfocus {
border: black solid 2px;
}
tr.selected {
background-color: #C0A080;
color: white;
}
tr.highlightcolumn {
background-color: #A0C0C0;
color: black;
}
th, td {
padding: .3em;
}
th {
text-align: center;
font-weight: bold;
}
thead tr {
background-color:#80A0A0;
color: #F0F0F0;
}
tr.highlight,
td.highlight,
th.highlight {
background-color: #C0E0E0;
color: #202020;
}
th.ascending {
background-image: url(http://test.cita.uiuc.edu/aria/grid/images/arrowup-blk.gif);
background-position: top center;
background-repeat: no-repeat;
}
th.descending {
background-image: url(http://test.cita.uiuc.edu/aria/grid/images/arrowdown-blk.gif);
background-position: bottom center;
background-repeat: no-repeat;
}
.center {
text-align: center;
}
label.hidden {
position: absolute;
left: -200em;
top: -20em;
}
h3 {
margin: 0;
padding: 0;
font-weight: normal;
font-size: medium;
}
code {
font-size: large;
font-family: monospace;
font-weight: bold;
}
div#config1 {
display: none;
}
</style>