Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds keyboard instructions. #31

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified src/assets/font/icomoon.eot
100755 → 100644
Binary file not shown.
10 changes: 6 additions & 4 deletions src/assets/font/icomoon.svg
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/font/icomoon.ttf
100755 → 100644
Binary file not shown.
Binary file modified src/assets/font/icomoon.woff
100755 → 100644
Binary file not shown.
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.
10 changes: 5 additions & 5 deletions src/creator.scss
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ body {
content: ' ';
}
&:after {
content: "\e600";
content: "\e984";
font-family: 'icomoon';
position:absolute;
top: 50%;
Expand Down Expand Up @@ -221,11 +221,11 @@ h1 {
}

.icon-spinner2:before {
content: "\e600";
content: "\e984";
}
.icon-close {
&:before {
content: "\e602";
content: "\ea0f";
font-size: 20px;
}

Expand All @@ -237,7 +237,7 @@ h1 {
}
}
.icon-plus:before {
content: "\e601";
content: "\ea0a";
}

div.criticism {
Expand Down Expand Up @@ -608,4 +608,4 @@ input[type=checkbox]:checked + label.checktoggle {
100% {
transform: translate(0px,0px);
}
}
}
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
104 changes: 85 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,75 @@ Namespace('WordSearch').Engine = do ->
document.addEventListener('MSPointerMove', _mouseMoveEvent, false)
document.onselectstart = (e) -> false

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

document.getElementById('intro-dismiss').addEventListener 'keypress', ->
_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('instructions-dismiss').addEventListener 'keypress', ->
_hideKeyboardInstructions()
if _introDismissed
document.getElementById('show-instructions').focus()
else
document.getElementById('intro-instructions').focus()

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

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

document.getElementById('show-intro').addEventListener 'keypress', ->
_showIntro()
document.getElementById('intro-instructions').focus()
document.getElementById('show-intro').addEventListener 'click', _showIntro

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

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()

_showIntro = ->
_introDismissed = false
_showbyId 'intro'

_showKeyboardInstructions = ->
# document.getElementById('instructions').removeAttribute('inert')
# document.getElementById('instructions').classList.add 'show'
_showbyId 'instructions'

# 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 'instructions'

# show confirmation menu and autofocus the cancel button
_doneButtonKeyupEvent = (e) ->
if e.code == 'Space' or e.code == 'Enter'
Expand All @@ -98,14 +159,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 +253,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 +316,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'
_showbyId 'confirm'

_showbyId = (targetId) ->
document.getElementById('game').setAttribute('inert', 'true')
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 = ->
# rather than have multiple functions to do the same thing, hide/inert all the dialogs
_hideById 'confirm'
_hideById 'intro'
_hideById 'instructions'
document.getElementById('backgroundcover').classList.remove 'show'

document.getElementById('game').removeAttribute('inert')

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

</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'>
<div>
<button id='show-intro'
class='icon-tutorial'>
</button>
<button id='show-instructions'
class='icon-keyboard'>
</button>
</div>
<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='instructions'>
<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 found.
</p>
</div>
<button id='instructions-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
Loading