diff --git a/card.js b/card.js index 38d1ffe..28718f7 100644 --- a/card.js +++ b/card.js @@ -8,10 +8,11 @@ * @param {Object} image * @param {number} id * @param {string} alt + * @param {Object} l10n Localization * @param {string} [description] * @param {Object} [styles] */ - MemoryGame.Card = function (image, id, alt, description, styles) { + MemoryGame.Card = function (image, id, alt, l10n, description, styles) { /** @alias H5P.MemoryGame.Card# */ var self = this; @@ -47,13 +48,13 @@ self.updateLabel = function (isMatched, announce, reset) { // Determine new label from input params - var label = (reset ? 'Unturned' : alt); + var label = (reset ? l10n.cardUnturned : alt); if (isMatched) { - label = 'Match found. ' + label; // TODO l10n + label = l10n.cardMatched + ' ' + label; } // Update the card's label - $wrapper.attr('aria-label', 'Card ' + ($wrapper.index() + 1) + ': ' + label); // TODO l10n + $wrapper.attr('aria-label', l10n.cardPrefix.replace('%num', $wrapper.index() + 1) + ' ' + label); // Update disabled property $wrapper.attr('aria-disabled', reset ? null : 'true'); @@ -155,9 +156,20 @@ self.trigger('prev'); event.preventDefault(); return; + case 35: + // Move to last card + self.trigger('last'); + event.preventDefault(); + return; + case 36: + // Move to first card + self.trigger('first'); + event.preventDefault(); + return; } }); - $wrapper.attr('aria-label', 'Card ' + ($wrapper.index() + 1) + ': Unturned.'); // TODO l10n + + $wrapper.attr('aria-label', l10n.cardPrefix.replace('%num', $wrapper.index() + 1) + ' ' + l10n.cardUnturned); $card = $wrapper.children('.h5p-memory-card') .children('.h5p-front') .click(function () { diff --git a/language/ar.json b/language/ar.json index 0f2a1fa..b1c7fd2 100644 --- a/language/ar.json +++ b/language/ar.json @@ -1,6 +1,11 @@ { "semantics": [ { + "widgets": [ + { + "label": "Default" + } + ], "label": "البطاقات", "entity": "بطاقة", "field": { @@ -10,53 +15,53 @@ "label": "الصورة" }, { - "englishLabel": "Matching Image", "label": "Matching Image", - "englishDescription": "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." }, { "label": "الوصف", "description": "نص قصير يتم عرضه مرة واحدة علي اثنين من البطاقات متساوية" + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Behavioural settings", - "englishDescription": "These options will let you control how the game behaves.", "description": "These options will let you control how the game behaves.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Position the cards in a square", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container." }, { - "englishLabel": "Number of cards to use", "label": "Number of cards to use", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Add button for retrying when the game is over" } ] }, { - "englishLabel": "Look and feel", - "englishDescription": "Control the visuals of the game.", + "label": "Look and feel", + "description": "Control the visuals of the game.", "fields": [ { - "englishLabel": "Theme Color", - "englishDescription": "Choose a color to create a theme for your card game." + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090" }, { - "englishLabel": "Card Back", - "englishDescription": "Use a custom back for your cards." + "label": "Card Back", + "description": "Use a custom back for your cards." } ] }, @@ -64,23 +69,46 @@ "label": "الأقلمة", "fields": [ { - "label": "نص تدوير البطاقة" + "label": "نص تدوير البطاقة", + "default": "Card turns" }, { - "label": "نص التوقيت الزمني" + "label": "نص التوقيت الزمني", + "default": "Time spent" }, { - "label": "نص الملاحظات" + "label": "نص الملاحظات", + "default": "Good work!" }, { - "englishLabel": "Try again button text", - "englishDefault": "Try again?" + "label": "Try again button text", + "default": "Reset" }, { - "englishLabel": "Close button label", - "englishDefault": "Close" + "label": "Close button label", + "default": "Close" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/language/bs.json b/language/bs.json index c97e6ca..780bbed 100644 --- a/language/bs.json +++ b/language/bs.json @@ -1,6 +1,11 @@ { "semantics": [ { + "widgets": [ + { + "label": "Default" + } + ], "label": "Karte", "entity": "karte", "field": { @@ -10,53 +15,53 @@ "label": "Slika" }, { - "englishLabel": "Matching Image", "label": "Ista slika", - "englishDescription": "An optional image to match against instead of using two cards with the same image.", "description": "Opcionalna slika koja se koristi umjestodvije iste slike." }, { "label": "Opis", "description": "Kratak tekst koji će biti prikazan čim se pronađu dvije iste karte." + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Podešavanje ponašanja", - "englishDescription": "These options will let you control how the game behaves.", "description": "These options will let you control how the game behaves.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Poredaj karte u redove ", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container." }, { - "englishLabel": "Number of cards to use", "label": "Broj karata za upotrebu", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Add button for retrying when the game is over" } ] }, { - "englishLabel": "Look and feel", - "englishDescription": "Control the visuals of the game.", + "label": "Look and feel", + "description": "Control the visuals of the game.", "fields": [ { - "englishLabel": "Theme Color", - "englishDescription": "Choose a color to create a theme for your card game." + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090" }, { - "englishLabel": "Poleđina karata", - "englishDescription": "Koristi standardnu pozadinu za karte." + "label": "Card Back", + "description": "Use a custom back for your cards." } ] }, @@ -76,16 +81,34 @@ "default": "BRAVO!" }, { - "englishLabel": "Try again button text", "label": "Tekst na dugmetu pokušaj ponovo", - "englishDefault": "Try again?", "default": "Pokušaj ponovo?" }, { - "englishLabel": "Close button label", - "englishDefault": "Close" + "label": "Close button label", + "default": "Close" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/language/de.json b/language/de.json index 9abf453..68deed0 100644 --- a/language/de.json +++ b/language/de.json @@ -1,6 +1,11 @@ { "semantics": [ { + "widgets": [ + { + "label": "Default" + } + ], "label": "Karten", "entity": "karte", "field": { @@ -10,53 +15,53 @@ "label": "Bild" }, { - "englishLabel": "Matching Image", "label": "Matching Image", - "englishDescription": "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." }, { "label": "Beschreibung", "description": "Ein kurzer Text, der angezeigt wird, sobald zwei identische Karten gefunden werden." + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Behavioural settings", - "englishDescription": "These options will let you control how the game behaves.", "description": "These options will let you control how the game behaves.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Position the cards in a square", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container." }, { - "englishLabel": "Number of cards to use", "label": "Number of cards to use", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Add button for retrying when the game is over" } ] }, { - "englishLabel": "Look and feel", - "englishDescription": "Control the visuals of the game.", + "label": "Look and feel", + "description": "Control the visuals of the game.", "fields": [ { - "englishLabel": "Theme Color", - "englishDescription": "Choose a color to create a theme for your card game." + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090" }, { - "englishLabel": "Card Back", - "englishDescription": "Use a custom back for your cards." + "label": "Card Back", + "description": "Use a custom back for your cards." } ] }, @@ -76,14 +81,34 @@ "default": "Gute Arbeit!" }, { - "englishLabel": "Try again button text", - "englishDefault": "Try again?" + "label": "Try again button text", + "default": "Reset" }, { - "englishLabel": "Close button label", - "englishDefault": "Close" + "label": "Close button label", + "default": "Close" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/language/fr.json b/language/fr.json index 204a6d9..05771c5 100644 --- a/language/fr.json +++ b/language/fr.json @@ -1,6 +1,11 @@ { "semantics": [ { + "widgets": [ + { + "label": "Default" + } + ], "label": "Cartes", "entity": "carte", "field": { @@ -10,53 +15,53 @@ "label": "Image" }, { - "englishLabel": "Matching Image", "label": "Matching Image", - "englishDescription": "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." }, { "label": "Description", "description": "Petit texte affiché quand deux cartes identiques sont trouvées." + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Behavioural settings", - "englishDescription": "These options will let you control how the game behaves.", "description": "These options will let you control how the game behaves.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Position the cards in a square", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container." }, { - "englishLabel": "Number of cards to use", "label": "Number of cards to use", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Add button for retrying when the game is over" } ] }, { - "englishLabel": "Look and feel", - "englishDescription": "Control the visuals of the game.", + "label": "Look and feel", + "description": "Control the visuals of the game.", "fields": [ { - "englishLabel": "Theme Color", - "englishDescription": "Choose a color to create a theme for your card game." + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090" }, { - "englishLabel": "Card Back", - "englishDescription": "Use a custom back for your cards." + "label": "Card Back", + "description": "Use a custom back for your cards." } ] }, @@ -76,14 +81,34 @@ "default": "Bien joué !" }, { - "englishLabel": "Try again button text", - "englishDefault": "Try again?" + "label": "Try again button text", + "default": "Reset" }, { - "englishLabel": "Close button label", - "englishDefault": "Close" + "label": "Close button label", + "default": "Close" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/language/it.json b/language/it.json index 1137a03..ccdb254 100644 --- a/language/it.json +++ b/language/it.json @@ -1,6 +1,11 @@ { "semantics": [ { + "widgets": [ + { + "label": "Default" + } + ], "label": "Carte", "entity": "carta", "field": { @@ -10,53 +15,53 @@ "label": "Immagine" }, { - "englishLabel": "Matching Image", "label": "Matching Image", - "englishDescription": "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." }, { "label": "Descrizione", "description": "Breve testo visualizzato quando due carte uguali vengono trovate." + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Behavioural settings", - "englishDescription": "These options will let you control how the game behaves.", "description": "These options will let you control how the game behaves.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Position the cards in a square", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container." }, { - "englishLabel": "Number of cards to use", "label": "Number of cards to use", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Add button for retrying when the game is over" } ] }, { - "englishLabel": "Look and feel", - "englishDescription": "Control the visuals of the game.", + "label": "Look and feel", + "description": "Control the visuals of the game.", "fields": [ { - "englishLabel": "Theme Color", - "englishDescription": "Choose a color to create a theme for your card game." + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090" }, { - "englishLabel": "Card Back", - "englishDescription": "Use a custom back for your cards." + "label": "Card Back", + "description": "Use a custom back for your cards." } ] }, @@ -64,23 +69,46 @@ "label": "Localizzazione", "fields": [ { - "label": "Testo Gira carta" + "label": "Testo Gira carta", + "default": "Card turns" }, { - "label": "Testo Tempo trascorso" + "label": "Testo Tempo trascorso", + "default": "Time spent" }, { - "label": "Testo Feedback" + "label": "Testo Feedback", + "default": "Good work!" }, { - "englishLabel": "Try again button text", - "englishDefault": "Try again?" + "label": "Try again button text", + "default": "Reset" }, { - "englishLabel": "Close button label", - "englishDefault": "Close" + "label": "Close button label", + "default": "Close" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/language/nb.json b/language/nb.json index 53e6ccc..29e2a49 100644 --- a/language/nb.json +++ b/language/nb.json @@ -1,112 +1,114 @@ { "semantics": [ { - "englishLabel": "Cards", + "widgets": [ + { + "label": "Default" + } + ], "label": "Kort", - "englishEntity": "card", "entity": "kort", "field": { - "englishLabel": "Card", "label": "Kort", "fields": [ { - "englishLabel": "Image", "label": "Bilde" }, { - "englishLabel": "Matching Image", "label": "Tilhørende bilde", - "englishDescription": "An optional image to match against instead of using two cards with the same image.", "description": "Et valgfritt bilde som brukes av kort nummer to istedenfor å bruke to kort med samme bilde." }, { - "englishLabel": "Description", "label": "Beskrivelse", - "englishDescription": "An optional short text that will pop up once the two matching cards are found.", "description": "En valgfri kort tekst som spretter opp når kort-paret er funnet." + }, + { + "label": "Alternative text for Matching Image", + "description": "Describe what can be seen in the photo. The text is read by text-to-speech tools needed by visually impaired users." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." } ] } }, { - "englishLabel": "Behavioural settings", "label": "Innstillinger for oppførsel", - "englishDescription": "These options will let you control how the game behaves.", "description": "Disse instillingene lar deg bestemme hvordan spillet skal oppføre seg.", "fields": [ { - "englishLabel": "Position the cards in a square", "label": "Plasser kortene i en firkant", - "englishDescription": "Will try to match the number of columns and rows when laying out the cards. Afterward, the cards will be scaled to fit the container.", "description": "Vil forsøk å samsvare antall kolonner og rader når kortene legges ut. Etterpå vil kortene bli skalert til å passe beholderen." }, { - "englishLabel": "Number of cards to use", "label": "Antall kort som skal brukes", - "englishDescription": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards.", "description": "Ved å sette antallet høyere enn 2 vil spillet plukke tilfeldige kort fra listen over kort." }, { - "englishLabel": "Add button for retrying when the game is over", "label": "Legg til knapp for å prøve på nytt når spillet er over" } ] }, { - "englishLabel": "Look and feel", "label": "Tilpass utseende", - "englishDescription": "Control the visuals of the game.", "description": "Kontroller de visuelle aspektene ved spillet.", "fields": [ { - "englishLabel": "Theme Color", "label": "Temafarge", - "englishDescription": "Choose a color to create a theme for your card game.", - "description": "Velg en farge for å skape et tema over kortspillet ditt." + "description": "Velg en farge for å skape et tema over kortspillet ditt.", + "default": "#909090" }, { - "englishLabel": "Card Back", "label": "Kortbaksiden", - "englishDescription": "Use a custom back for your cards.", "description": "Bruk en tilpasset kortbakside for kortene dine." } ] }, { - "englishLabel": "Localization", "label": "Oversettelser", "fields": [ { - "englishLabel": "Card turns text", "label": "Etikett for antall vendte kort", - "englishDefault": "Card turns", "default": "Kort vendt" }, { - "englishLabel": "Time spent text", "label": "Etikett for tid brukt", - "englishDefault": "Time spent", "default": "Tid brukt" }, { - "englishLabel": "Feedback text", "label": "Tilbakemeldingstekst", - "englishDefault": "Good work!", "default": "Godt jobbet!" }, { - "englishLabel": "Try again button text", "label": "Prøv på nytt-tekst", - "englishDefault": "Try again?", "default": "Prøv på nytt?" }, { - "englishLabel": "Close button label", "label": "Lukk knapp-merkelapp", - "englishDefault": "Close", "default": "Lukk" + }, + { + "label": "Game label", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "default": "Unturned." + }, + { + "label": "Card matched label", + "default": "Match found." } ] } ] -} +} \ No newline at end of file diff --git a/memory-game.css b/memory-game.css index 4d61392..67e4b9a 100644 --- a/memory-game.css +++ b/memory-game.css @@ -194,9 +194,6 @@ margin: 0 1em 0 0; font-weight: bold; } -.h5p-memory-game .h5p-status > dt:after { - content: ":"; -} .h5p-memory-game .h5p-status > dd { margin: 0; } @@ -314,3 +311,6 @@ transform: translate(-50%,-450%) scale(0) rotate(360deg); opacity: 0; } +.h5p-memory-complete { + display: none; +} diff --git a/memory-game.js b/memory-game.js index a0cb033..7c61076 100644 --- a/memory-game.js +++ b/memory-game.js @@ -22,13 +22,29 @@ H5P.MemoryGame = (function (EventDispatcher, $) { // Initialize event inheritance EventDispatcher.call(self); - var flipped, timer, counter, popup, $bottom, $feedback, $wrapper, maxWidth, numCols; + var flipped, timer, counter, popup, $bottom, $taskComplete, $feedback, $wrapper, maxWidth, numCols; var cards = []; var flipBacks = []; // Que of cards to be flipped back var numFlipped = 0; var removed = 0; numInstances++; + // Add defaults + parameters = $.extend(true, { + l10n: { + cardTurns: 'Card turns', + timeSpent: 'Time spent', + feedback: 'Good work!', + tryAgain: 'Reset', + closeLabel: 'Close', + label: 'Memory Game. Find the matching cards.', + done: 'All of the cards have been found.', + cardPrefix: 'Card %num: ', + cardUnturned: 'Unturned.', + cardMatched: 'Match found.' + } + }, parameters); + /** * Check if these two cards belongs together. * @@ -69,7 +85,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) { if (card.hasTwoImages) { imgs.push(mate.getImage()); } - popup.show(desc, imgs, cardStyles ? cardStyles.back : undefined, function () { + popup.show(desc, imgs, cardStyles ? cardStyles.back : undefined, function (refocus) { if (isFinished) { // Game done card.makeUntabbable(); @@ -78,6 +94,10 @@ H5P.MemoryGame = (function (EventDispatcher, $) { else { // Popup is closed, continue. timer.play(); + + if (refocus) { + card.setFocus(); + } } }); } @@ -94,6 +114,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) { */ var finished = function () { timer.stop(); + $taskComplete.show(); $feedback.addClass('h5p-show'); // Announce $bottom.focus(); @@ -140,6 +161,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) { // Remove feedback $feedback[0].classList.remove('h5p-show'); + $taskComplete.hide(); // Reset timer and counter timer.reset(); @@ -196,6 +218,14 @@ H5P.MemoryGame = (function (EventDispatcher, $) { */ var addCard = function (card, mate) { card.on('flip', function () { + + // Always return focus to the card last flipped + for (var i = 0; i < cards.length; i++) { + cards[i].makeUntabbable(); + } + card.makeTabbable(); + + popup.close(); self.triggerXAPI('interacted'); // Keep track of time spent timer.play(); @@ -232,8 +262,12 @@ H5P.MemoryGame = (function (EventDispatcher, $) { }); /** + * Create event handler for moving focus to the next or the previous + * card on the table. + * * @private - * @param {number} direction + * @param {number} direction +1/-1 + * @return {function} */ var createCardChangeFocusHandler = function (direction) { return function () { @@ -261,8 +295,38 @@ H5P.MemoryGame = (function (EventDispatcher, $) { }; }; + // Register handlers for moving focus to next and previous card card.on('next', createCardChangeFocusHandler(1)); card.on('prev', createCardChangeFocusHandler(-1)); + + /** + * Create event handler for moving focus to the first or the last card + * on the table. + * + * @private + * @param {number} direction +1/-1 + * @return {function} + */ + var createEndCardFocusHandler = function (direction) { + return function () { + var focusSet = false; + for (var i = 0; i < cards.length; i++) { + var j = (direction === -1 ? cards.length - (i + 1) : i); + if (!focusSet && !cards[j].isRemoved()) { + cards[j].setFocus(); + focusSet = true; + } + else if (cards[j] === card) { + card.makeUntabbable(); + } + } + }; + }; + + // Register handlers for moving focus to first and last card + card.on('first', createEndCardFocusHandler(1)); + card.on('last', createEndCardFocusHandler(-1)); + cards.push(card); }; @@ -320,16 +384,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.imageAlt, cardParams.description, cardStyles); + var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, parameters.l10n, cardParams.description, cardStyles); if (MemoryGame.Card.hasTwoImages(cardParams)) { // Use matching image for card two - cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.matchAlt, cardParams.description, cardStyles); + cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.matchAlt, parameters.l10n, cardParams.description, cardStyles); cardOne.hasTwoImages = cardTwo.hasTwoImages = true; } else { // Add two cards with the same image - cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, cardParams.description, cardStyles); + cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, parameters.l10n, cardParams.description, cardStyles); } // Add cards to card list for shuffeling @@ -366,7 +430,7 @@ H5P.MemoryGame = (function (EventDispatcher, $) { $('
', { id: 'h5p-intro-' + numInstances, 'class': 'h5p-memory-hidden-read', - html: 'Memory Game. Find the matching cards.', // TODO: l10n + html: parameters.l10n.label, appendTo: $container }); $list.appendTo($container); @@ -375,9 +439,9 @@ H5P.MemoryGame = (function (EventDispatcher, $) { tabindex: '-1', appendTo: $container }); - $('
', { - 'class': 'h5p-memory-hidden-read', - html: 'All of the cards have been found.', // TODO: l10n + $taskComplete = $('
', { + 'class': 'h5p-memory-complete h5p-memory-hidden-read', + html: parameters.l10n.done, appendTo: $bottom }); @@ -385,13 +449,13 @@ H5P.MemoryGame = (function (EventDispatcher, $) { // Add status bar var $status = $('
' + - '
' + parameters.l10n.timeSpent + '
' + - '
0:00
' + // TODO: Add hidden dot ? - '
' + parameters.l10n.cardTurns + '
' + - '
0
' + + '
' + parameters.l10n.timeSpent + ':
' + + '
.
' + + '
' + parameters.l10n.cardTurns + ':
' + + '
0.
' + '
').appendTo($bottom); - timer = new MemoryGame.Timer($status.find('.h5p-time-spent')[0]); + timer = new MemoryGame.Timer($status.find('time')[0]); counter = new MemoryGame.Counter($status.find('.h5p-card-turns')); popup = new MemoryGame.Popup($container, parameters.l10n); diff --git a/popup.js b/popup.js index 24b2b46..3f07631 100644 --- a/popup.js +++ b/popup.js @@ -13,16 +13,16 @@ var closed; - var $popup = $('
').appendTo($container); + var $popup = $('').appendTo($container); var $desc = $popup.find('.h5p-memory-desc'); var $top = $popup.find('.h5p-memory-top'); // Hook up the close button $popup.find('.h5p-memory-close').on('click', function () { - self.close(); + self.close(true); }).on('keypress', function (event) { if (event.which === 13 || event.which === 32) { - self.close(); + self.close(true); event.preventDefault(); } }); @@ -41,22 +41,26 @@ $('
').append(imgs[i]).appendTo($top); } $popup.show(); + $desc.focus(); closed = done; }; /** * Close the popup. + * + * @param {boolean} refocus Sets focus after closing the dialog */ - self.close = function () { + self.close = function (refocus) { if (closed !== undefined) { $popup.hide(); - closed(); + closed(refocus); closed = undefined; } }; /** * Sets popup size relative to the card size + * * @param {number} fontSize */ self.setSize = function (fontSize) { diff --git a/semantics.json b/semantics.json index 52a1f10..0333ce0 100644 --- a/semantics.json +++ b/semantics.json @@ -169,7 +169,42 @@ "name": "closeLabel", "type": "text", "default": "Close" + }, + { + "label": "Game label", + "importance": "low", + "name": "label", + "type": "text", + "default": "Memory Game. Find the matching cards." + }, + { + "label": "Game finished label", + "importance": "low", + "name": "done", + "type": "text", + "default": "All of the cards have been found." + }, + { + "label": "Card indexing label", + "importance": "low", + "name": "cardPrefix", + "type": "text", + "default": "Card %num:" + }, + { + "label": "Card unturned label", + "importance": "low", + "name": "cardUnturned", + "type": "text", + "default": "Unturned." + }, + { + "label": "Card matched label", + "importance": "low", + "name": "cardMatched", + "type": "text", + "default": "Match found." } ] } -] +] \ No newline at end of file diff --git a/timer.js b/timer.js index 339392e..4af4caf 100644 --- a/timer.js +++ b/timer.js @@ -28,6 +28,11 @@ var minutes = Timer.extractTimeElement(time, 'minutes'); var seconds = Timer.extractTimeElement(time, 'seconds') % 60; + + // Update duration attribute + element.setAttribute('datetime', 'PT' + minutes + 'M' + seconds + 'S'); + + // Add leading zero if (seconds < 10) { seconds = '0' + seconds; }