Skip to content

Commit

Permalink
ucfopen#30 Fleshed out keyboard instructions and an intro dialog, cle…
Browse files Browse the repository at this point in the history
…aned up dialog styles and management in general. Added accessibility metadata to install.yaml.
  • Loading branch information
FrenjaminBanklin committed Aug 1, 2023
1 parent 10b9c25 commit 147abd4
Show file tree
Hide file tree
Showing 7 changed files with 336 additions and 104 deletions.
Binary file added src/assets/intro/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/intro/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/intro/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ score:
is_scorable: Yes
score_module: WordSearch
meta_data:
accessibility_keyboard: Full
accessibility_reader: None
accessibility_description: >
Includes custom controls that may override standard navigation.
These controls are communicated visually.
features:
- Customizable
- Scorable
Expand Down
90 changes: 71 additions & 19 deletions src/player.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Namespace('WordSearch').Engine = do ->
# track puzzle information
_letterArray = []

_introDismissed = false

# Called by Materia.Engine when your widget Engine should start the user experience.
start = (instance, qset, version = '1') ->
# local variable contexts
Expand Down Expand Up @@ -80,16 +82,61 @@ Namespace('WordSearch').Engine = do ->
document.addEventListener('MSPointerMove', _mouseMoveEvent, false)
document.onselectstart = (e) -> false

document.getElementById('intro-instructions').addEventListener 'keypress', ->
_showKeyboardInstructions()
document.getElementById('tutorial-dismiss').focus()
document.getElementById('intro-instructions').addEventListener 'click', _showKeyboardInstructions

document.getElementById('intro-dismiss').addEventListener 'keypress', (e) ->
e.preventDefault()
e.stopPropagation()
_introDismissed = true
_makeBoardUsable()
# questionable timeout to avoid this keypress being picked up by the board after it receives focus
setTimeout (->
document.getElementById('board').focus()
), 100

document.getElementById('intro-dismiss').addEventListener 'click', () ->
_introDismissed = true
_makeBoardUsable()

document.getElementById('tutorial-dismiss').addEventListener 'keypress', (e) ->
e.preventDefault()
e.stopPropagation()
_hideKeyboardInstructions()
document.getElementById('intro-instructions').focus()

document.getElementById('tutorial-dismiss').addEventListener 'click', _hideKeyboardInstructions

document.getElementById('board').addEventListener 'keyup', _handleBoardKeyupEvent

document.getElementById('checkbtn').addEventListener 'click', _confirmDone
document.getElementById('checkbtn').addEventListener 'keyup', _doneButtonKeyupEvent

document.getElementById('okbtn').addEventListener 'click', () ->
_hideConfirmationDialog()
_submitAnswers()
document.getElementById('cancelbtn').addEventListener 'click', _hideConfirmationDialog
document.getElementById('cancelbtn').addEventListener 'keyup', _cancelButtonKeyupEvent

# once everything is drawn, set the height of the player
Materia.Engine.setHeight()

_showKeyboardInstructions = ->
document.getElementById('tutorial').removeAttribute('inert')
document.getElementById('tutorial').classList.add 'show'

# this isn't strictly necessary but doing it every time doesn't hurt
document.getElementById('intro').setAttribute('inert', 'true')

_hideKeyboardInstructions = ->
if _introDismissed
_makeBoardUsable
else
document.getElementById('intro').removeAttribute 'inert'
_hideById 'tutorial'

# show confirmation menu and autofocus the cancel button
_doneButtonKeyupEvent = (e) ->
if e.code == 'Space' or e.code == 'Enter'
Expand All @@ -98,14 +145,14 @@ Namespace('WordSearch').Engine = do ->

_cancelButtonKeyupEvent = (e) ->
if e.code == 'Space' or e.code == 'Enter'
_hideAlert(e)
_hideConfirmationDialog(e)

_handleBoardKeyupEvent = (e) ->
switch e.code
when 'Tab'
# should indicate a keyboard user tabbing in; do nothing but redraw the board for keyboard
break
when 'Space', 'Enter'
when 'Space'
# we're toggling from 'selecting' to 'not selecting', check to see if there's a word highlighted
if _keyboardIsSelecting
# have to add 1 to the y coordinate because we index those from 1 instead of 0 for some reason
Expand Down Expand Up @@ -192,7 +239,7 @@ Namespace('WordSearch').Engine = do ->

# loop through all positions that words occupy in the puzzle
for i in positions
word = ""
word = ''

# loop over the positions
while 1
Expand Down Expand Up @@ -255,24 +302,29 @@ Namespace('WordSearch').Engine = do ->

# show the "are you done" warning
_confirmDone = ->
document.getElementById('alertbox').removeAttribute('inert')
document.getElementById('board').setAttribute('inert', 'true')
document.getElementById('sidebar').setAttribute('inert', 'true')
document.getElementById('alertbox').classList.add 'show'
document.getElementById('game').setAttribute('inert', 'true')
_showbyId 'confirm'

_showbyId = (targetId) ->
document.getElementById(targetId).removeAttribute 'inert'
document.getElementById(targetId).classList.add 'show'
document.getElementById('backgroundcover').classList.add 'show'
document.querySelector('#alertbox #okbtn').addEventListener 'click', () ->
_hideAlert()
_submitAnswers()
document.querySelector('#alertbox #cancelbtn').addEventListener 'click', () ->
_hideAlert()

# hide it
_hideAlert = (e) ->
document.getElementById('board').removeAttribute('inert')
document.getElementById('sidebar').removeAttribute('inert')
document.getElementById('alertbox').setAttribute('inert', 'true')
document.getElementById('alertbox').classList.remove 'show'

_hideById = (targetId) ->
document.getElementById(targetId).setAttribute('inert', 'true')
document.getElementById(targetId).classList.remove 'show'

_makeBoardUsable = ->
document.getElementById('game').removeAttribute('inert')
# rather than have multiple functions to do the same thing, inert all the dialogs
_hideById 'confirm'
_hideById 'intro'
_hideById 'tutorial'

document.getElementById('backgroundcover').classList.remove 'show'

_hideConfirmationDialog = (e) ->
_makeBoardUsable()
# a keyboard event triggered this, autofocus the 'done' button
if e and e.type == 'keyup'
document.getElementById('checkbtn').focus()
Expand Down
109 changes: 89 additions & 20 deletions src/player.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,103 @@

</head>
<body>
<div id='title'></div>
<div id="board"
class='main-element'
tabindex='0'>
<canvas id='canvas' width=620 height=550></canvas>
</div>
<div id='sidebar' class='main-element'>
<h1>Terms</h1>
<div id='terms'></div>
<div id='checkbtn' tabindex='0'>Done</div>
</div>
<div id='backgroundcover' class='fade'></div>
<div id='alertbox' class='fade' inert='true'>
<div id='alertcaption'>Are you ready to submit your score?</div>
<input id='cancelbtn' class='cancel button' type='button' value='Not yet.'>
<input id='okbtn' class='submit button' type='button' value='Yep!'>
<section id='game' inert='true'>
<div id='title'></div>
<div id="board"
class='main-element'
tabindex='0'>
<canvas id='canvas' width=620 height=550></canvas>
</div>
<div id='sidebar' class='main-element'>
<h1>Terms</h1>
<div id='terms'></div>
<div id='checkbtn'
class='action-button'
tabindex='0'>
Done
</div>
</div>
</section>
<div id='backgroundcover' class='fade show'>
<dialog id='intro' class='show'>
<header>How to Play Word Search</header>
<div class='content'>
<div class='caption'>
<p>
The Terms list on the right contains a list of words hidden in the puzzle on the right.
</p>
<p>
Click and drag across letters in the puzzle to select them.
The selection will follow the cursor to the nearest valid letter.
</p>
<p>
Once a word from the list is found, it will be stricken through.
</p>
<p>
Find all words to finish the game.
</p>
</div>
<aside class='image-frame'>
<img id='intro-img-1' src='assets/intro/1.png' alt='Word search demo image 1 of 3' />
<img id='intro-img-2' src='assets/intro/2.png' alt='Word search demo image 2 of 3' />
<img id='intro-img-3' src='assets/intro/3.png' alt='Word search demo image 3 of 3' />
</aside>
</div>
<button id='intro-instructions' class='cancel'>
Keyboard instructions
</button>
<button id='intro-dismiss' class='submit action-button'>
Let's Go
</button>
</dialog>
<dialog id='tutorial'>
<div class='caption'>
<header>Keyboard Controls</header>
<p>
Use the <span class='bold'>tab</span> key to move between the game board and the 'Done' button.
</p>
<p>
With the board selected, use the <span class='bold'>arrow keys</span> to move the cursor.
</p>
<p>
Press <span class='bold'>space</span> to start selecting.
This will set the currently circled letter as the start location for the selection and change the cursor.
</p>
<p>
While selecting, the <span class='bold'>arrow keys</span> will move the cursor and adjust the selection based on the cursor's location.
</p>
<p>
When you have selected a range of letters, press <span class='bold'>space</span> again to finalize the selection.
If the selected range corresponds to one of the words in the term list, it will be marked as complete.
</p>
</div>
<button id='tutorial-dismiss' class='submit action-button'>
Okay
</button>
</dialog>
<dialog id='confirm'
class='fade'
inert='true'>
<div class='caption'>Are you ready to submit your score?</div>
<button id='cancelbtn' class='cancel'>
Not yet
</button>
<button id='okbtn' class='submit action-button'>
Yep!
</button>
</dialog>
</div>

<div class="error-notice-container">
<div class="error-notice">
<div class='error-notice-container'>
<div class='error-notice'>
<h1>This widget uses features that your browser doesn't support</h1>
<h2>Upgrade your browser to use this widget</h2>
</div>
</div>

<!-- INITIALIZE -->
<script src="puzzle.js"></script>
<script src="player.js"></script>
<script src='puzzle.js'></script>
<script src='player.js'></script>
<script>
WebFont.load({
active: function() {
Expand Down
Loading

0 comments on commit 147abd4

Please sign in to comment.