Grid Navigation Menu
Grid Example 4: JQuery
ARIA Enabled Travel Reimbursement Form Example
| Date |
Departed From |
Arrived At |
Automobile Miles |
Mileage Reimbursement |
Transportation |
Lodging |
Meals |
Miscellaneous |
Daily Total |
| Location |
Time |
Location |
Time |
Air, Rails, etc.. |
Car Rental |
Taxi, Parking, Tolls, etc.. |
| Total Travel Expenses |
- |
- |
- |
- |
- |
- |
- |
- |
| Messages: | |
Keyboard Shortcuts
Based on the keyboard shortcuts defined in the AOL DHTML Style guide for grid
- Tab (standard mode): Move focus between grid, links and form controls.
- Tab (actionable mode): Move focus.
- ENTER or F2 (standard mode): Edit contents of gridcell.
- ENTER or F2 (Actionable mode): Update the contents of the gridcell.
- ESC (Actionable mode): Move to standard mode, do not update the contents of the gridcell.
- Up Arrow: Move focus to gridcell in previous row
- Down Arrow: Move focus to gridcell in next row
- Left Arrow: Move focus one gridcell to the left.
- Right Arrow: Move focus one gridcell to the right.
- Home: Move focus to first gridcell in the row.
- End: Move focus to the last gridcell to the row.
- Page Up: Move focus to the first gridcell in the columm.
- Page Down: Move focus to the last gridcell in the column.
ARIA Roles and Properties used
role="application"
role="grid"
role="gridcell"
role="alert"
- States and properties:
aria-labeledby
aria-describedby
aria-live
Other ARIA Features
- Date is checked for format and reformatted to standard date format, date errors are reported using
role="alert"
- Cells that only take numbers are filtered and an error is reported when non-numbers are entered using
role="alert".
- The total cost cell uses the
aria-live="polite" property.
HTML Source Code
Show HTML Source Code: grid4.inc
<div role="application">
<table id="expense" role="grid" summary="ARIA Enabled Travel Reimbursement Form Example">
<caption>ARIA Enabled Travel Reimbursement Form Example</caption>
<tr>
<th id="date" rowspan="2">Date</th>
<th id="from" colspan="2">Departed From</th>
<th id="arrv" colspan="2">Arrived At</th>
<th id="auto" rowspan="2">Automobile<br/> Miles</th>
<th id="mile" rowspan="2">Mileage <br/>Reimbursement</th>
<th id="tran" colspan="3">Transportation</th>
<th id="lodg" rowspan="2">Lodging</th>
<th id="meal" rowspan="2">Meals</th>
<th id="misc" rowspan="2">Miscellaneous</th>
<th id="tota" rowspan="2">Daily<br/>Total</th>
</tr>
<tr>
<th id="loca1">Location</th>
<th id="time1">Time</th>
<th id="loca2">Location</th>
<th id="time2">Time</th>
<th id="tran1">Air, Rails, etc..</th>
<th id="tran2">Car Rental</th>
<th id="tran3">Taxi, Parking, Tolls, etc..</th>
</tr>
<tbody id="data">
</tbody>
<tr role="row">
<td id="row-CT-col-05" role="gridcell" colspan="6">Total Travel Expenses</td>
<td id="row-CT-col-06" role="gridcell" aria-label="Total Mileage">-</td>
<td id="row-CT-col-07" role="gridcell" aria-label="Total air or rail transportation">-</td>
<td id="row-CT-col-08" role="gridcell" aria-label="Total car rental">-</td>
<td id="row-CT-col-09" role="gridcell" aria-label="Total taxi, parking and tolls">-</td>
<td id="row-CT-col-10" role="gridcell" aria-label="Total lodging">-</td>
<td id="row-CT-col-11" role="gridcell" aria-label="Total meals">-</td>
<td id="row-CT-col-12" role="gridcell" aria-label="Total miscellaneous">-</td>
<td id="row-CT-col-13" role="gridcell" aria-labelledby="row-CT-col-05" aria-live="polite">-</td>
</tr>
<tr>
<th id="msg">Messages: </th><td headers="msg" colspan="13" id="alert" role="alert"> </td>
</tr>
</table>
<div id="debug"></div>
<div id="row_numbers" class="offscreen"></div>
</div>
Javascript Source Code
Show Javascript Source Code: grid4.js
<script type="text/javascript">
function Keycodes() {
this.SPACE = 32;
this.PAGEUP = 33;
this.PAGEDOWN = 34;
this.END = 35;
this.HOME = 36;
this.LEFT = 37;
this.UP = 38;
this.RIGHT = 39;
this.DOWN = 40;
this.SPACE = 32;
this.TAB = 9;
this.BACKSPACE = 8;
this.DELETE = 46;
this.ENTER = 13;
this.INSERT = 45;
this.ESCAPE = 27;
this.ZERO = 48;
this.NINE = 57;
this.PERIOD = 190;
this.F2 = 113;
};
function TravelCalc() {
// Constants
this.DIRECTION_UP = 1;
this.DIRECTION_DOWN = 2;
this.DIRECTION_HOME = 3;
this.DIRECTION_END = 4;
this.DIRECTION_PGUP = 5;
this.DIRECTION_PGDN = 6;
this.DIRECTION_FIRST = 7;
this.DIRECTION_LAST = 8;
this.row_max = 0;
};
TravelCalc.prototype.findCellID = function( node, direction ) {
var row = node.id.slice(4,6);
var col = node.id.slice(11,13);
if( node.id[4] == '0' )
row = node.id.slice(5,6);
if( node.id[11] == '0' )
col = node.id.slice(12,13);
switch ( direction ) {
case this.DIRECTION_UP:
if( row == "CT") {
row = this.row_max - 1;
} else {
row = parseInt(row);
if( row > 0 ) {
row--;
} // endif
} // endif
return this.getCellID(row, col);
break;
case this.DIRECTION_DOWN:
row = parseInt(row);
row++;
if( row >= this.row_max ) {
row = "CT";
} // endif
return this.getCellID(row, col);
break;
case this.DIRECTION_HOME:
if( row == "CT") {
col = 6;
} else {
col = 0;
} // endif
return this.getCellID(row, col);
case this.DIRECTION_END:
col = 13;
return this.getCellID(row, col);
break;
case this.DIRECTION_PGUP:
row = 0;
return this.getCellID(row, col);
case this.DIRECTION_PGDN:
if( col > 5 ) {
row = "CT";
} else {
row = this.row_max - 1;
} // endif
return this.getCellID(row, col);
} // end switch
return this.getCellID(row, col);
}
TravelCalc.prototype.getCellID = function( row, col ) {
var row_value;
var col_value;
var str;
if( row == "CT" ) {
row_value = "CT";
} else {
if( parseInt(row) < 10 ) {
row_value = "0" + parseInt(row);
} else {
row_value = row;
} // endif
} // endif
if( parseInt(col) < 10 ) {
col_value = "0" + parseInt(col);
} else {
col_value = col;
} // endif
str = "row-" + row_value + "-col-" + col_value;
return str;
}
TravelCalc.prototype.addRow = function() {
var row_id;
if( this.row_max < 10 ) {
row_id = "0" + this.row_max;
} else {
row_id = this.row_max;
} // endif
$('table tbody#data').append('<tr role="row" id="row' + row_id + '"></tr>');
var row = $('table tbody#data tr:last');
var row_numbers = $('div #row_numbers');
var cid00 = this.getCellID(this.row_max, 0);
var cid01 = this.getCellID(this.row_max, 1);
var cid02 = this.getCellID(this.row_max, 2);
var cid03 = this.getCellID(this.row_max, 3);
var cid04 = this.getCellID(this.row_max, 4);
var cid05 = this.getCellID(this.row_max, 5);
var cid06 = this.getCellID(this.row_max, 6);
var cid07 = this.getCellID(this.row_max, 7);
var cid08 = this.getCellID(this.row_max, 8);
var cid09 = this.getCellID(this.row_max, 9);
var cid10 = this.getCellID(this.row_max, 10);
var cid11 = this.getCellID(this.row_max, 11);
var cid12 = this.getCellID(this.row_max, 12);
var cid13 = this.getCellID(this.row_max, 13);
row_numbers.append('<div id="r' + this.row_max + '"class="offscreen">Row ' + (this.row_max + 1 ) + '</div>');
var label = 'aria-labelledby="date r' + this.row_max +'"';
row.append('<td id="' + cid00 + '" role="gridcell" class="date" ' + label + '><span></span><input class="date" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="from loca1 r' + this.row_max +'"';
row.append('<td id="' + cid01 + '" role="gridcell" class="location" ' + label + '><span></span><div role="combobox"><input class="location" type="text" size="12" ' + label + '/></div></td>');
label = 'aria-labelledby="from time1 r' + this.row_max +'"';
row.append('<td id="' + cid02 + '" role="gridcell" class="time" ' + label + '><span></span><input type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="arrv loca2 r' + this.row_max +'"';
row.append('<td id="' + cid03 + '" role="gridcell" class="location" ' + label + '><span></span><div role="combobox"><input class="location" type="text" size="12" ' + label + '/></div></td>');
label = 'aria-labelledby="arrv time2 r' + this.row_max +'"';
row.append('<td id="' + cid04 + '" role="gridcell" class="time" ' + label + '><span></span><input type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="auto r' + this.row_max +'"';
row.append('<td id="' + cid05 + '" role="gridcell" ' + label + '><span class="mileage"></span><input class="mileage" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="mile r' + this.row_max +'"';
row.append('<td id="' + cid06 + '" role="gridcell" class="expense mileage" ' + label + '><span></span></td>');
label = 'aria-labelledby="tran tran1 r' + this.row_max +'"';
row.append('<td id="' + cid07 + '" role="gridcell" class="expense air" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="tran tran2 r' + this.row_max +'"';
row.append('<td id="' + cid08 + '" role="gridcell" class="expense car" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="tran tran3 r' + this.row_max +'"';
row.append('<td id="' + cid09 + '" role="gridcell" class="expense taxi" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="lodg r' + this.row_max +'"';
row.append('<td id="' + cid10 + '" role="gridcell" class="expense lodging" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="meal r' + this.row_max +'"';
row.append('<td id="' + cid11 + '" role="gridcell" class="expense meals" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="misc r' + this.row_max +'"';
row.append('<td id="' + cid12 + '" role="gridcell" class="expense misc" ' + label + '><span></span><input class="number" type="text" size="6" ' + label + '/></td>');
label = 'aria-labelledby="tota r' + this.row_max +'"';
row.append('<td id="' + cid13 + '" role="gridcell" class="rowtotal" ' + label + '>-</td>');
this.row_max++;
};
TravelCalc.prototype.getRowFromID = function( id_value ) {
var row = id_value.slice(4,6);
if( id_value[4] == '0' ) {
row = id_value.slice(5,6);
} // endif
return row;
}
TravelCalc.prototype.getColFromID = function( id_value ) {
var col = id_value.slice(11,13);
if( id_value[11] == '0' ) {
col = id_value.slice(12,13);
} // endif
return col;
}
TravelCalc.prototype.nextInputControl = function( input_node ) {
var cell;
var cell_id;
var input;
var node = input_node.parentNode;
var row = this.getRowFromID(node.id);
var col = this.getColFromID(node.id);
row = parseInt( row );
col = parseInt( col );
do {
col++;
if( col > 13 ) {
col = 0;
row++;
if( row >= this.row_max ) {
row = 0;
} // endif
} // endif
cell_id = this.getCellID(row, col);
cell = document.getElementById( cell_id );
input = cell.getElementsByTagName("input")[0];
} while ( !input );
return input;
};
TravelCalc.prototype.prevInputControl = function( input_node ) {
var cell_id;
var cell;
var input;
var node = input_node.parentNode;
var row = this.getRowFromID(node.id);
var col = this.getColFromID(node.id);
col = parseInt( col );
row = parseInt( row );
do {
col--;
if( col < 0 ) {
col = 12;
row--;
if( row < 0 ) {
row = this.row_max - 1;
} // endif
} // endif
cell_id = this.getCellID(row, col);
cell = document.getElementById( cell_id );
input = cell.getElementsByTagName("input")[0];
} while ( !input );
return input;
};
TravelCalc.prototype.editCell = function( cell ) {
cell.find('span').css('display', 'none');
cell.find('input').css('display', 'block');
cell.find('input').val(cell.find('span').text());
cell.find('input').focus();
};
TravelCalc.prototype.showData = function( input ) {
if( $(input).hasClass('date') ) {
var msg = this.validateDate( input );
if( this.validateDate( input ) == "" ) {
$('td#alert').text(' ');
} else {
$('td#alert').text(msg);
input.val("");
};
} // endif
input.parent().find('span').text(input.val());
input.parent().find('span').css('display', 'inline');
input.css('display', 'none');
if( $(input).hasClass('number') ) {
this.rowSummFromInput( input );
this.colSummFromInput( input );
this.totalSumm();
} // endif
if( $(input).hasClass('mileage') ) {
this.updateMileageFromInput( input );
this.totalMileage();
this.rowSummFromInput( input );
this.totalSumm();
} // endif
};
TravelCalc.prototype.validateDate = function( input ) {
var errorMessage = "Date needs to be in date format, such as 1/31/2001.";
if (input.val() != "") {
// try parsing as date using JavaScript Date constructor
var dateValue = new Date(input.val().replace(/-/g, "/"));
if (isFinite(dateValue)) {
// if two-digit year, guess at correct century
if (input.val().match(/Dd{1,2}$/) && dateValue.getFullYear() < (new Date().getFullYear() - 96)) {
dateValue.setFullYear(dateValue.getFullYear() + 100);
}
// format as mm/dd/yyyy
input.val( (dateValue.getMonth() + 1) + "/" + dateValue.getDate() + "/" + dateValue.getFullYear() );
return "";
}
else {
return errorMessage;
}
}
return "";
}
TravelCalc.prototype.rowSummFromInput = function( input ) {
var row = this.getRowFromID($(input).parent().attr('id'));
this.rowSumm( row );
}
TravelCalc.prototype.rowSumm = function( row ) {
var row_id = "row" + parseInt( row );
if( parseInt( row ) < 10 ) {
var row_id = "row0" + parseInt( row );
} // endif
var row_cells = document.getElementById( row_id );
var value;
var summ = 0;
$( row_cells ).find('td[role="gridcell"]').each(
function() {
if( $(this).hasClass('expense') ) {
value = $(this).find('span').text();
if( value == "" ) {
value = 0;
}
if( value == parseFloat(value) ) {
summ = summ + parseInt(value*100.0);
} // endif
} // endif
} // end each function
) // end each
var total = document.getElementById( this.getCellID( row, 13 ) );
if( summ == 0 ) {
$(total).text( '-' );
} else {
summ = summ.toString();
summ = summ.substr(0, (summ.length-2)) + "." + summ.substr( (summ.length-2), (summ.length-1));
$(total).text( "$" + summ );
} // endif
};
TravelCalc.prototype.colSummFromInput = function( input ) {
var grid_cell = $(input).parent();
var value;
var summ = 0;
col_num = this.getColFromID(grid_cell.attr('id'));
for(var i = 0; i < this.row_max; i++ ) {
grid_cell = document.getElementById( this.getCellID( i, col_num ) );
value = $(grid_cell).find('span').text();
if( value == "" ) {
value = 0;
}
if( value == parseFloat(value) ) {
summ = summ + parseInt(value*100.0);
} // endif
} // endfor
var total = document.getElementById( this.getCellID( "CT", col_num ) );
if( summ == 0 ) {
$(total).text( '-' );
} else {
summ = summ.toString();
summ = summ.substr(0, (summ.length-2)) + "." + summ.substr( (summ.length-2), (summ.length-1));
$(total).text( "$" + summ );
} // endif
};
TravelCalc.prototype.totalSumm = function() {
var grid_cell;
var value;
var summ = 0;
col_num = 13;
for(var i = 0; i < this.row_max; i++ ) {
grid_cell = document.getElementById( this.getCellID( i, col_num ) );
value = $(grid_cell).text();
value = value.replace("$", "");
if( value == parseFloat(value) ) {
summ = summ + parseInt(value*100.0);
} // endif
} // endfor
var total = document.getElementById( this.getCellID( "CT", col_num ) );
summ = summ.toString();
summ = summ.substr(0, (summ.length-2)) + "." + summ.substr( (summ.length-2), (summ.length-1));
$(total).text( "$" + summ );
};
TravelCalc.prototype.updateMileageFromInput = function( input ) {
var grid_cell = $(input).parent();
if( $(input).val() == "" ) {
value = 0;
} else {
var value = 44 * parseInt($(input).val());
value = value.toString();
value = value.substr(0, (value.length-2)) + "." + value.substr( (value.length-2), (value.length-1));
}
var mileage_span = $( grid_cell ).next('td[role="gridcell"]').find('span');
if( value == 0 ) {
$(mileage_span).text( '-' );
} else {
$(mileage_span).text( value );
} // endif
};
TravelCalc.prototype.totalMileage = function() {
var grid_cell;
var value;
var summ = 0.0;
col_num = 6;
for(var i = 0; i < this.row_max; i++ ) {
grid_cell = document.getElementById( this.getCellID( i, col_num ) );
value = $(grid_cell).text();
if( value == parseFloat(value) ) {
summ = summ + parseInt(value*100.0);
} // endif
} // endfor
var total = document.getElementById( this.getCellID( "CT", col_num ) );
if( summ == 0 ) {
$(total).text( '-' );
} else {
summ = summ.toString();
summ = summ.substr(0, (summ.length-2)) + "." + summ.substr( (summ.length-2), (summ.length-1));
$(total).text( "$" + summ );
} // endif
};
$(document).ready(
function() {
var KEY_CODE = new Keycodes();
var travel_calc = new TravelCalc();
travel_calc.addRow();
travel_calc.addRow();
travel_calc.addRow();
travel_calc.addRow();
$('table#expense input').css('display', 'none');
$('table#expense td[role="gridcell"]').attr('tabindex', '-1');
$('table#expense td[role="gridcell"]:first').attr('tabindex', '0');
$('table#expense td[role="gridcell"]').each(
function() {
$(this).keydown (
function(e) {
var cell;
// Do not process key if the control, shift or alt key are pressed
if ( e.ctrlKey || e.altKey || e.shiftKey ) {
return true;
} // endif
switch( e.keyCode ) {
case KEY_CODE.LEFT:
cell = $(e.target).prev('td');
if( $(cell).attr('id') ) {
$(e.target).attr('tabindex', '-1');
$(cell).focus();
$(cell).attr('tabindex', '0');
}
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.RIGHT:
cell = $(e.target).next('td');
if( $(cell).attr('id') ) {
$(e.target).attr('tabindex', '-1');
$(cell).focus();
$(cell).attr('tabindex', '0');
}
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.UP:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_UP));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.DOWN:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_DOWN));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.HOME:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_HOME));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.END:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_END));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.PAGEUP:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_PGUP));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
case KEY_CODE.PAGEDOWN:
cell = document.getElementById(travel_calc.findCellID( e.target, travel_calc.DIRECTION_PGDN));
if( cell ) {
$(e.target).attr('tabindex', '-1');
cell.tabIndex = 0;
cell.focus();
} // endif
e.stopPropagation();
e.preventDefault();
return false;
break;
default:
break;
} // end switch
} // end keydown function
); // end keydown event handler
$(this).click(
function( e ) {
travel_calc.editCell( $(this) );
$('table#expense td[role="gridcell"]').attr('tabindex', '-1');
this.tabIndex = 0;
} // end on click function
); // endif on click event handler
} // end each function
); // end each
$('table#expense input').parent().each(
function() {
$(this).keydown (
function(e) {
// Do not process key if the control, shift or alt key are pressed
if ( e.ctrlKey || e.altKey || e.shiftKey ) {
return true;
} // endif
if( e.keyCode == KEY_CODE.ENTER ||
e.keyCode == KEY_CODE.F2) {
travel_calc.editCell( $(this) );
e.preventDefault();
e.stopPropagation();
return false;
} else {
return true;
} // endif
} // endif keydown event handler function
); // end keydown event handler
} // end each function
); // end each
$('table#expense input').each(
function() {
$(this).blur(
function () {
travel_calc.showData( $(this) );
} // end input blur function
); // end input blur event
$(this).keydown(
function (e) {
var control;
// Do not process key if the control or alt key are pressed
if ( e.ctrlKey || e.altKey ) {
return true;
} // endif
if( (e.keyCode == KEY_CODE.ESCAPE) && !e.shiftKey) {
$(e.target).val($(e.target).parent().find('span').text());
travel_calc.showData( $(e.target));
$(e.target).parent().focus();
e.preventDefault();
e.stopPropagation();
return false;
};
if(( e.keyCode == KEY_CODE.ENTER) && !e.shiftKey ) {
travel_calc.showData( $(e.target));
$(e.target).parent().focus();
e.preventDefault();
e.stopPropagation();
return false;
}
if( (e.keyCode == KEY_CODE.TAB) && !e.shiftKey ) {
travel_calc.showData( $(e.target) );
control = travel_calc.nextInputControl( e.target );
travel_calc.editCell( $(control.parentNode) );
e.target.parentNode.tabIndex = -1;
control.parentNode.tabIndex = 0;
e.preventDefault();
e.stopPropagation();
return false;
}
if( (e.keyCode == KEY_CODE.TAB) && e.shiftKey ) {
travel_calc.showData( $(e.target) );
control = travel_calc.prevInputControl( e.target );
travel_calc.editCell( $(control.parentNode) );
e.target.parentNode.tabIndex = -1;
control.parentNode.tabIndex = 0;
e.preventDefault();
e.stopPropagation();
return false;
}
return true;
} // end input keydown function
); // end input keydown event
$(this).keyup(
function (e) {
// test for number input only
if( $(e.target).hasClass('number') || $(e.target).hasClass('mileage')) {
// filter out non-number keys
var str1 = $(e.target).val();
var str2 = "";
for(var i=0; i < str1.length; i++ ) {
if( ((str1[i] >= '0') && (str1[i] <= '9')) || (str1[i] == '.')) {
str2 = str2 + str1[i];
} // endif
} // endfor
$(e.target).val(str2);
if( str1.length != str2.length ) {
$('td#alert').text('You can only enter numbers in to this cell!');
} else {
$('td#alert').text(" ");
} // endif
} else {
$('td#alert').text(" ");
} // endif
return true;
} // end input keyup function
); // end input keyup event
} // end each function
); // end each
} // end ready function
); // end ready event </script>
CSS Source Code
Show CSS Source Code: grid4.css
<style type="text/css">
/* Example 1 CSS
// This example uses CSS background-image to visual display checkbox status
*/
table#expense {
border: black solid 2px;
border-spacing: 1px;
}
th, td {
border: black solid 1px;
padding: 3px;
}
td:focus,
td:hover,
td:active {
border: #002277 solid 2px;
padding: 2px;
background-color: #F8F8F8;
outline: #FFFFFF dotted medium;
}
th {
font-weight: bold;
background-color: #EEEEEE;
color: #002277;
}
td {
text-align: right;
}
td input {
text-align: center;
}
caption {
border-top: black solid 2px;
border-left: black solid 2px;
border-right: black solid 2px;
font-size: 125%;
font-weight: bold;
background-color: #EEEEEE;
color: #002277;
}
td#alert {
color: red;
font-weight: bold;
text-align: left;
}
.offscreen {
position: absolute;
left: -200em;
top: -20em;
}
</style>
W3C Validation of HTML5