cthulhu/test/html/aria-alert-dialog.html

651 lines
17 KiB
HTML

<html>
<head>
<style type="text/css">
div.guess {
border: thick double black;
padding: 1em;
width: 50%;
font-family: Arial, Helvetica, sans-serif;
}
div.guess h2 {
margin: 0;
padding: 0;
text-align: center;
margin-left: 1em;
margin-right: 1em;
}
div.guess input {
font-size: 100%;
}
div.guess p.input {
margin: 0;
padding: 0;
font-size: 150%;
margin-top: .5em;
margin-bottom: .5em;
text-align: center;
margin-left: 1em;
margin-right: 1em;
}
div.guess input.button {
margin: 0;
padding: 0;
display: inline;
padding-left: .5em;
padding-right: .5em;
padding-top: .25em;
padding-bottom: .25em;
}
div#alert1 {
position: absolute;
width: 25%;
border:medium solid black;
display: none;
background-color: white;
color: black;
text-align: center;
padding-bottom: 1em;
font-family: Arial, Helvetica, sans-serif;
}
div#alert1 p.title {
margin: 0;
padding: 0;
color: white;
background-color: black;
text-align: center;
font-weight: bold;
border-top: thin solid white;
border-left: thin solid white;
border-right: thin solid white;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var guess1 = new guess(1, 10, 'guess1', 'guess1_text', 'guess1_check', 'guess1_again', 'alert1');
});
//
// keyCodes is an object that defines keycodes for the key handlers
//
function keyCodes () {
// Define values for keycodes
this.tab = 9;
this.enter = 13;
this.esc = 27;
this.space = 32;
}
//
// alertDlg() is a class to implement a modal alert dialog
//
// @param (alert_id string) alert_id is the id of the dialog to create
//
// @param (game_id string) game_id is the id to attach the dialog to
// @return N/A
//
function alertDlg(alert_id, game_id) {
var dlg = '<div id="' + alert_id + '" role="alertdialog" tabindex="-1" aria-hidden="true" aria-labeledby="' +
alert_id + '_title"><p id="' + alert_id + '_title" class="title">Alert Box</p><p id="' +
alert_id + '_message">No Message</p><input id="' +
alert_id + '_close" type="button" value="Close" /></div>';
// append the dialog to the document
$('div#' + game_id).append(dlg);
// Define the object properties
this.$dlg = $('#' + alert_id); // the object pointer of the dialog
this.$game = $('#' + game_id); // the object pointer of the containing div for the game
this.$msg = $('#' + alert_id + '_message'); // the object pointer of the alert message area
this.$button = $('#' + alert_id + '_close'); // the object pointer of the alert close button
this.$focus; // the object pointer of a page element to give focus to on dialog dismissal
this.keys = new keyCodes();
// bind handlers
this.bindHandlers();
} // end alertDlg constructor
//
// showMsg() is a member function to set the message text of the alertDlg
//
// @param (msg string) msg is the message to display in the dialog box.
//
// @param (focusId string) focusId is the id of the element to give focus to when the dialog is dismissed.
//
// @return N/A
//
alertDlg.prototype.showMsg = function (msg, $focus) {
// Store the focus ID
this.$focus = $focus;
// Set the message text
this.$msg.html(msg);
// Show the dialog
this.showDlg();
} // end showMsg()
//
// bindHandlers() is a member function to bind event handlers to the modal alert dialog
//
// @return N/A
//
alertDlg.prototype.bindHandlers = function () {
var thisObj = this; // store the this pointer
// bind a keydown handler
this.$dlg.keydown(function(e) {
return thisObj.handleDlgKeyDown(e);
});
// bind a keypress handler
this.$dlg.keypress(function(e) {
return thisObj.handleDlgKeyPress(e);
});
// bind a click handler
this.$button.click(function(e) {
return thisObj.handleCloseClick(e);
});
} // end bindhandlers()
//
// handleDlgKeyDown() is a member function to process keydown events for the alert dialog
//
// @param (evt obj) evt is the event object associated with the keydown event
//
// @return (boolean) true if propagating; false if consuming event
//
alertDlg.prototype.handleDlgKeyDown = function(evt) {
if (evt.ctrlKey || evt.AltKey) {
// do nothing
return true;
}
switch (evt.keyCode) {
case this.keys.tab: {
// Consume the tab event and do nothing
evt.stopPropagation;
return false;
}
case this.keys.enter:
case this.keys.esc:
case this.keys.space: {
// hide the dialog
this.hideDlg();
evt.stopPropagation;
return false;
break;
}
} // end switch
return true;
} // end handleDlgKeyDown()
//
// handleDlgKeyPress() is a member function to consume keypress events for the alert dialog
//
// @param (evt obj) evt is the event object associated with the keydown event
//
// @return (boolean) true if propagating; false if consuming event
//
alertDlg.prototype.handleDlgKeyPress = function(evt) {
if (evt.ctrlKey || evt.AltKey) {
// do nothing
return true;
}
switch (evt.keyCode) {
case this.keys.tab:
case this.keys.enter:
case this.keys.esc:
case this.keys.space: {
evt.stopPropagation;
return false;
break;
}
} // end switch
return true;
} // end handleDlgKeyPress()
//
// handleCloseClick() is a member function to process click events for the alert dialog close button
//
// @param (evt obj) evt is the event object associated with the click event
//
// @return (boolean) true if propagating; false if consuming event
//
alertDlg.prototype.handleCloseClick = function(evt) {
if (evt.shiftKey || evt.ctrlKey || evt.AltKey) {
// do nothing
return true;
}
// Hide the dialog
this.hideDlg();
evt.stopPropagation;
return false;
} // end handleCloseClick()
//
// showDlg() is a member function to show the alert dialog and give it focus
//
// @return N/A
//
alertDlg.prototype.showDlg = function() {
var thisObj = this;
// Bind an event listener to the document to capture all mouse events to make dialog modal
$(document).bind('click mousedown mouseup mousemove mouseover', function(e) {
//ensure focus remains on the dialog
thisObj.$dlg.focus();
// Consume all mouse events and do nothing
e.stopPropagation;
return false;
});
// Position the dialog centered in the containing div
this.$dlg.css('left', (this.$game.width() - this.$dlg.width()) / 2 + this.$game.offset().left + 'px');
this.$dlg.css('top', (this.$game.height() - this.$dlg.height()) / 2 + this.$game.offset().top + 'px');
// Display the dialog
this.$dlg.show();
this.$dlg.attr('aria-hidden', 'false');
// Give the dialog focus
this.$dlg.attr('tabindex', '0');
this.$dlg.focus();
} // end showDlg()
//
// hideDlg() is a member function to hide the alert dialog and return focus to the page
//
// @return N/A
//
alertDlg.prototype.hideDlg = function() {
// set aria hidden attribute and remove dialog from tab order
this.$dlg.attr('aria-hidden', 'true');
this.$dlg.attr('tabindex', '-1');
// hide the dialog
this.$dlg.hide();
// Unbind the document mouse event listeners
$(document).unbind('click mousedown mouseup mousemove');
// return focus to the specified page element
if (this.$focus) {
this.$focus.focus();
}
} // end hideDlg()
///////////////////////////////////////////////////////////////////////////////////////////
//
// guess() is a class to implement a simple number guessing game
//
// @param (game_id) game_id is the id to attach the instance of the game to.
//
// @param (max integer) min is the maximum number to guess.
//
// @param (text_id string) text_id is the id of the text box where player enters a guess.
//
// @param (check_id string) check_id is the id of the check guess button.
//
// @param (again_id string) again_id is the id of the play again button.
//
// @param (alertObj) alertObj is the modal dialog object where game messages will be printed.
//
// @return N/A
//
function guess(min, max, game_id, text_id, check_id, again_id, alert_id) {
// define class properties
this.minGuess = min; // the minimum number to guess
this.maxGuess = max; // the maximum number to guess
this.$text = $('#' + text_id); // the jQuery object pointer to the text box
this.$check = $('#' + check_id); // the jQuery object pointer to the check guess button
this.$again = $('#' + again_id); // the jQuery object pointer to the play again button
this.alertDlg = new alertDlg('alert1', game_id); // the modal alert dialog to be displayed during the game
this.guessVal = -1; // the number for the player to guess
this.guessCount = 0; // the number of attempts the player has made
this.keys = new keyCodes();
// bind event handlers
this.bindHandlers();
// initialize the game
this.newGame();
} // end guess object constructor
//
// newGame() is a member function to set up a new game. The function chooses a number
// between 1 and the max number specified at instantiation, sets the guess count to 0, and
// show the user a message to make a guess.
//
// @return N/A
guess.prototype.newGame = function () {
// get a new random number for the player to guess
this.guessVal = Math.floor(Math.random()*(this.maxGuess - this.minGuess + 1)) + this.minGuess;
// reset the guess count
this.guessCount = 0;
// reset the guess text box
this.$text.val('');
this.$text.attr('aria-invalid', 'false');
// Re-enable the buttons
this.$text.removeAttr('disabled');
this.$check.removeAttr('disabled');
// Set focus on the guess text box
this.$text.focus();
} // end newGame
//
// bindHandlers() is a function to bind the event handlers for the game controls
//
// @return N/A
//
guess.prototype.bindHandlers = function () {
var thisObj = this; // Store the this pointer
// bind a focus handler for the guess text box
this.$text.focus(function (e) {
thisObj.handleTextFocus(e);
return true;
});
// bind a keydown handler for the guess text box
this.$text.keydown(function (e) {
return thisObj.handleTextKeyDown(e);
});
// bind a keypress handler for the guess text box
this.$text.keypress(function (e) {
return thisObj.handleTextKeyPress(e);
});
// bind a click handler for the check guess button
this.$check.click(function (e) {
return thisObj.handleCheckClick(e);
});
// bind a click handler for the play again button
this.$again.click(function (e) {
return thisObj.handleAgainClick(e);
});
} // end bindHandlers()
//
// handleTextFocus() is a member function to process focus events for the guess text box
//
// @input (evt obj) evt is the event object associated with the keydown event
//
// @return N/A
//
guess.prototype.handleTextFocus = function(evt) {
// Select any text in the text box
this.$text.select();
} // end handleTextFocus()
//
// handleTextKeyDown() is a member function to process keydown events for the guess text box
//
// @input (evt obj) evt is the event object associated with the keydown event
//
// @return (boolean) false if consuming event, true if propagating
//
guess.prototype.handleTextKeyDown = function(evt) {
// do nothing if shift, alt, or ctrl key pressed.
if (evt.shiftKey || evt.altKey || evt.ctrlKey) {
return true;
}
if (evt.keyCode == this.keys.enter) {
// validate the guess
if (this.validateGuess() == true) {
// increment the guess count
this.guessCount++;
// see if the player has won
if (this.checkGuess() == true) {
// disable the guess text box and the check guess button
this.$text.attr('disabled', 'true');
this.$check.attr('disabled', 'true');
}
}
evt.stopPropagation;
return false;
}
return true;
} // end handleTextKeyDown()
//
// handleTextKeyPress() is a member function to process keypress events for the guess text box. This function
// is included to handle browsers that perform window scrolling, etc. on keypress rather than keydown.
//
// @input (evt obj) evt is the event object associated with the keypress event
//
// @return (boolean) false if consuming event, true if propagating
//
guess.prototype.handleTextKeyPress = function(evt) {
// do nothing if shift, alt, or ctrl key pressed.
if (evt.shiftKey || evt.altKey || evt.ctrlKey) {
return true;
}
if (evt.keyCode == this.enterKey) {
// consume the event
evt.stopPropagation;
return false;
}
return true;
} // end handleTextKeyPress()
//
// handleCheckClick() is a member function to process click events for the check guess button
//
// @input (evt obj) evt is the event object associated with the click event
//
// @return (boolean) false if consuming event, true if propagating
//
guess.prototype.handleCheckClick = function(evt) {
// do nothing if shift, alt, or ctrl key pressed.
if (evt.shiftKey || evt.altKey || evt.ctrlKey) {
return true;
}
// validate the guess
if (this.validateGuess() == true) {
// increment the guess count
this.guessCount++;
// see if the player has won
if (this.checkGuess() == true) {
// disable the guess text box and the check guess button
this.$text.attr('disabled', 'true');
this.$check.attr('disabled', 'true');
}
}
evt.stopPropagation;
return false;
} // end handleCheckClick()
//
// handleAgainClick() is a member function to process click events for the play again button
//
// @input (evt obj) evt is the event object associated with the click event
//
// @return (boolean) false if consuming event, true if propagating
//
guess.prototype.handleAgainClick = function(evt) {
// do nothing if shift, alt, or ctrl key pressed.
if (evt.shiftKey || evt.altKey || evt.ctrlKey) {
return true;
}
// Setup a new game
this.newGame();
evt.stopPropagation;
return false;
} // end handleTextKeyDown()
//
// validateGuess() is a member function to validate a player's guess. If the guess is not a number, is less than
// the minimum allowed guess, or is greater than the maximum allowed guess, the user is warned that the guess is invalid
//
// @return (boolean) true if guess is valid; false if guess is invalid
//
guess.prototype.validateGuess = function() {
var val = this.$text.val();
if (this.$text.val() == '') {
// guess is empty
this.$text.attr('aria-invalid', 'true');
this.alertDlg.showMsg('You must enter a number!', this.$text);
return false;
}
else if (isNaN(val) == true) {
// guess is not a number
this.$text.attr('aria-invalid', 'true');
this.alertDlg.showMsg('\'' + this.$text.val() + '\' is not a number!', this.$text);
return false;
}
else if (val < this.minGuess || val > this.maxGuess) {
// guess is out of range
this.$text.attr('aria-invalid', 'true');
this.alertDlg.showMsg('You must choose a number between ' + this.minGuess + ' and ' + this.maxGuess + '!', this.$text);
return false;
}
this.$text.attr('aria-invalid', 'false');
return true;
} // end validateGuess()
//
// checkGuess() is a member function to check the player's guess to see if he or she has won the game
//
// @return (boolean) true if the player has won; false if not
guess.prototype.checkGuess = function() {
var guess = this.$text.val();
if (guess == this.guessVal) {
// The player has won. Tell the player how many tries it took
if (this.guessCount == 1) {
this.alertDlg.showMsg('\'' + guess + '\' is right. You got it on your first try!', this.$again);
}
else {
this.alertDlg.showMsg('\'' + guess + '\' is right. It only took you ' + this.guessCount + ' tries!', this.$again);
}
return true;
}
// Player did not guess the correct number. Tell the player if he or she is too high or too low
if (guess < this.guessVal) {
this.alertDlg.showMsg('\'' + guess + '\' is too low. Try a higher number.', this.$text);
}
else {
this.alertDlg.showMsg('\'' + guess + '\' is too high. Try a lower number.', this.$text);
}
return false;
} // end checkGuess()
</script>
</head>
<body>
<div role="application">
<div id="guess1" class="guess">
<h2>Number Guessing Game</h2>
<p><strong>Instructions:</strong> In this game you guess a number between 1 an 10 and then press the "Check My Guess" button to check your responses.
An <abbr title="Accessible Rich Internet Application">ARIA</abbr> dialog box will display the results of your guess. To start over again to press the "Play Again" button.</p>
<p class="input">
<label id="guess1_label" for="guess1_text">Guess a number between 1 and 10</label>
<input type="text" id="guess1_text" size="3" aria-labelledby="guess1_label" aria-invalid="false">
</p>
<p class="input">
<input class="button" id="guess1_check" type="button" value="Check My Guess"/>
<input class="button" id="guess1_again" type="button" value="Play Again"/>
</p>
</div>
</div>
</body>
</html>