Start improving accessibility
parent
aead8728d8
commit
196c112243
76
card.js
76
card.js
|
@ -7,10 +7,11 @@
|
||||||
* @extends H5P.EventDispatcher
|
* @extends H5P.EventDispatcher
|
||||||
* @param {Object} image
|
* @param {Object} image
|
||||||
* @param {number} id
|
* @param {number} id
|
||||||
|
* @param {string} alt
|
||||||
* @param {string} [description]
|
* @param {string} [description]
|
||||||
* @param {Object} [styles]
|
* @param {Object} [styles]
|
||||||
*/
|
*/
|
||||||
MemoryGame.Card = function (image, id, description, styles) {
|
MemoryGame.Card = function (image, id, alt, description, styles) {
|
||||||
/** @alias H5P.MemoryGame.Card# */
|
/** @alias H5P.MemoryGame.Card# */
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
EventDispatcher.call(self);
|
EventDispatcher.call(self);
|
||||||
|
|
||||||
var path = H5P.getPath(image.path, id);
|
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 !== undefined && image.height !== undefined) {
|
||||||
if (image.width > image.height) {
|
if (image.width > image.height) {
|
||||||
|
@ -40,6 +41,7 @@
|
||||||
self.flip = function () {
|
self.flip = function () {
|
||||||
$card.addClass('h5p-flipped');
|
$card.addClass('h5p-flipped');
|
||||||
self.trigger('flip');
|
self.trigger('flip');
|
||||||
|
flippedState = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,6 +49,7 @@
|
||||||
*/
|
*/
|
||||||
self.flipBack = function () {
|
self.flipBack = function () {
|
||||||
$card.removeClass('h5p-flipped');
|
$card.removeClass('h5p-flipped');
|
||||||
|
flippedState = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +57,7 @@
|
||||||
*/
|
*/
|
||||||
self.remove = function () {
|
self.remove = function () {
|
||||||
$card.addClass('h5p-matched');
|
$card.addClass('h5p-matched');
|
||||||
|
removedState = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,14 +92,37 @@
|
||||||
*/
|
*/
|
||||||
self.appendTo = function ($container) {
|
self.appendTo = function ($container) {
|
||||||
// TODO: Translate alt attr
|
// 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-front"' + (styles && styles.front ? styles.front : '') + '>' + (styles && styles.backImage ? '' : '<span></span>') + '</div>' +
|
||||||
'<div class="h5p-back"' + (styles && styles.back ? styles.back : '') + '>' +
|
'<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>' +
|
||||||
'</div></li>')
|
'</div></li>')
|
||||||
.appendTo($container)
|
.appendTo($container)
|
||||||
.children('.h5p-memory-card')
|
.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')
|
.children('.h5p-front')
|
||||||
.click(function () {
|
.click(function () {
|
||||||
self.flip();
|
self.flip();
|
||||||
|
@ -107,8 +134,43 @@
|
||||||
* Re-append to parent container
|
* Re-append to parent container
|
||||||
*/
|
*/
|
||||||
self.reAppend = function () {
|
self.reAppend = function () {
|
||||||
var parent = $card[0].parentElement.parentElement;
|
var parent = $wrapper[0].parentElement;
|
||||||
parent.appendChild($card[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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,38 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
|
||||||
counter.increment();
|
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);
|
cards.push(card);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -277,16 +309,16 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
|
||||||
var cardParams = cardsToUse[i];
|
var cardParams = cardsToUse[i];
|
||||||
if (MemoryGame.Card.isValid(cardParams)) {
|
if (MemoryGame.Card.isValid(cardParams)) {
|
||||||
// Create first card
|
// 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)) {
|
if (MemoryGame.Card.hasTwoImages(cardParams)) {
|
||||||
// Use matching image for card two
|
// 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;
|
cardOne.hasTwoImages = cardTwo.hasTwoImages = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Add two cards with the same image
|
// 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
|
// Add cards to card list for shuffeling
|
||||||
|
@ -314,6 +346,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) {
|
||||||
for (var i = 0; i < cards.length; i++) {
|
for (var i = 0; i < cards.length; i++) {
|
||||||
cards[i].appendTo($list);
|
cards[i].appendTo($list);
|
||||||
}
|
}
|
||||||
|
cards[0].makeTabbable();
|
||||||
|
|
||||||
if ($list.children().length) {
|
if ($list.children().length) {
|
||||||
$list.appendTo($container);
|
$list.appendTo($container);
|
||||||
|
|
|
@ -26,6 +26,13 @@
|
||||||
"importance": "high",
|
"importance": "high",
|
||||||
"ratio": 1
|
"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",
|
"name": "match",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
|
@ -35,6 +42,14 @@
|
||||||
"description": "An optional image to match against instead of using two cards with the same image.",
|
"description": "An optional image to match against instead of using two cards with the same image.",
|
||||||
"ratio": 1
|
"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",
|
"name": "description",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -146,7 +161,7 @@
|
||||||
"importance": "low",
|
"importance": "low",
|
||||||
"name": "tryAgain",
|
"name": "tryAgain",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"default": "Try again?"
|
"default": "Reset"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Close button label",
|
"label": "Close button label",
|
||||||
|
|
Loading…
Reference in New Issue