Start improving accessibility

pull/30/head^2
Frode Petterson 2017-06-20 16:47:07 +02:00
parent aead8728d8
commit 196c112243
3 changed files with 126 additions and 16 deletions

86
card.js
View File

@ -7,10 +7,11 @@
* @extends H5P.EventDispatcher
* @param {Object} image
* @param {number} id
* @param {string} alt
* @param {string} [description]
* @param {Object} [styles]
*/
MemoryGame.Card = function (image, id, description, styles) {
MemoryGame.Card = function (image, id, alt, description, styles) {
/** @alias H5P.MemoryGame.Card# */
var self = this;
@ -18,7 +19,7 @@
EventDispatcher.call(self);
var path = H5P.getPath(image.path, id);
var width, height, margin, $card;
var width, height, margin, $card, $wrapper, removedState, flippedState;
if (image.width !== undefined && image.height !== undefined) {
if (image.width > image.height) {
@ -40,6 +41,7 @@
self.flip = function () {
$card.addClass('h5p-flipped');
self.trigger('flip');
flippedState = true;
};
/**
@ -47,6 +49,7 @@
*/
self.flipBack = function () {
$card.removeClass('h5p-flipped');
flippedState = false;
};
/**
@ -54,6 +57,7 @@
*/
self.remove = function () {
$card.addClass('h5p-matched');
removedState = true;
};
/**
@ -88,27 +92,85 @@
*/
self.appendTo = function ($container) {
// TODO: Translate alt attr
$card = $('<li class="h5p-memory-wrap"><div class="h5p-memory-card" role="button" tabindex="1">' +
$wrapper = $('<li class="h5p-memory-wrap" tabindex="-1" role="button"><div class="h5p-memory-card">' +
'<div class="h5p-front"' + (styles && styles.front ? styles.front : '') + '>' + (styles && styles.backImage ? '' : '<span></span>') + '</div>' +
'<div class="h5p-back"' + (styles && styles.back ? styles.back : '') + '>' +
'<img src="' + path + '" alt="Memory Card" style="width:' + width + ';height:' + height + '"/>' +
'<img src="' + path + '" alt="' + (alt || 'Memory Image') + '" style="width:' + width + ';height:' + height + '"/>' +
'</div>' +
'</div></li>')
.appendTo($container)
.children('.h5p-memory-card')
.children('.h5p-front')
.click(function () {
self.flip();
})
.end();
.on('keydown', function (event) {
switch (event.which) {
case 13: // Enter
case 32: // Space
if (!flippedState) {
self.flip();
event.preventDefault();
}
return;
case 39: // Right
case 40: // Down
// Move focus forward
self.trigger('next');
event.preventDefault();
return;
case 37: // Left
case 38: // Up
// Move focus back
self.trigger('prev');
event.preventDefault();
return;
}
});
$card = $wrapper.children('.h5p-memory-card')
.children('.h5p-front')
.click(function () {
self.flip();
})
.end();
};
/**
* Re-append to parent container
*/
self.reAppend = function () {
var parent = $card[0].parentElement.parentElement;
parent.appendChild($card[0].parentElement);
var parent = $wrapper[0].parentElement;
parent.appendChild($wrapper[0]);
};
/**
*
*/
self.makeTabbable = function () {
if ($wrapper) {
$wrapper.attr('tabindex', '0');
}
};
/**
*
*/
self.makeUntabbable = function () {
if ($wrapper) {
$wrapper.attr('tabindex', '-1');
}
};
/**
*
*/
self.setFocus = function () {
self.makeTabbable();
if ($wrapper) {
$wrapper.focus();
}
};
/**
*
*/
self.isFlipped = function () {
return flippedState;
};
};

View File

@ -220,6 +220,38 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
counter.increment();
});
/**
* @private
* @param {number} direction
*/
var createCardChangeFocusHandler = function (direction) {
return function () {
// Locate next card
for (var i = 0; i < cards.length; i++) {
if (cards[i] === card) {
// Found current card
var nextCard, fails = 0;
do {
fails++;
nextCard = cards[i + (direction * fails)];
if (!nextCard) {
return; // No more cards
}
}
while (nextCard.isFlipped());
card.makeUntabbable();
nextCard.setFocus();
return;
}
}
};
};
card.on('next', createCardChangeFocusHandler(1));
card.on('prev', createCardChangeFocusHandler(-1));
cards.push(card);
};
@ -277,16 +309,16 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
var cardParams = cardsToUse[i];
if (MemoryGame.Card.isValid(cardParams)) {
// Create first card
var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.description, cardStyles);
var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, cardParams.description, cardStyles);
if (MemoryGame.Card.hasTwoImages(cardParams)) {
// Use matching image for card two
cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.description, cardStyles);
cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.matchAlt, cardParams.description, cardStyles);
cardOne.hasTwoImages = cardTwo.hasTwoImages = true;
}
else {
// Add two cards with the same image
cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.description, cardStyles);
cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, cardParams.description, cardStyles);
}
// Add cards to card list for shuffeling
@ -314,6 +346,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
for (var i = 0; i < cards.length; i++) {
cards[i].appendTo($list);
}
cards[0].makeTabbable();
if ($list.children().length) {
$list.appendTo($container);

View File

@ -26,6 +26,13 @@
"importance": "high",
"ratio": 1
},
{
"name": "imageAlt",
"type": "text",
"label": "Alternative text for Image",
"importance": "high",
"description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users."
},
{
"name": "match",
"type": "image",
@ -35,6 +42,14 @@
"description": "An optional image to match against instead of using two cards with the same image.",
"ratio": 1
},
{
"name": "matchAlt",
"type": "text",
"label": "Alternative text for Matching Image",
"importance": "low",
"optional": true,
"description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users."
},
{
"name": "description",
"type": "text",
@ -146,7 +161,7 @@
"importance": "low",
"name": "tryAgain",
"type": "text",
"default": "Try again?"
"default": "Reset"
},
{
"label": "Close button label",