diff --git a/card.js b/card.js index 9b1aa90..660a9bf 100644 --- a/card.js +++ b/card.js @@ -8,8 +8,9 @@ * @param {Object} image * @param {number} id * @param {string} [description] + * @param {Object} [styles] */ - MemoryGame.Card = function (image, id, description) { + MemoryGame.Card = function (image, id, description, styles) { /** @alias H5P.MemoryGame.Card# */ var self = this; @@ -88,8 +89,8 @@ self.appendTo = function ($container) { // TODO: Translate alt attr $card = $('
  • ' + - '
    ' + - '
    ' + + '
    ' + (styles && styles.backImage ? '' : '') + '
    ' + + '
    ' + 'Memory Card' + '
    ' + '
  • ') @@ -141,4 +142,83 @@ params.match.path !== undefined); }; + /** + * Determines the theme for how the cards should look + * + * @param {string} color The base color selected + * @param {number} invertShades Factor used to invert shades in case of bad contrast + */ + MemoryGame.Card.determineStyles = function (color, invertShades, backImage) { + var styles = { + front: '', + back: '', + backImage: !!backImage + }; + + // Create color theme + if (color) { + var frontColor = shade(color, 43.75 * invertShades); + var backColor = shade(color, 56.25 * invertShades); + + styles.front += 'color:' + color + ';' + + 'background-color:' + frontColor + ';' + + 'border-color:' + frontColor +';'; + styles.back += 'color:' + color + ';' + + 'background-color:' + backColor + ';' + + 'border-color:' + frontColor +';'; + } + + // Add back image for card + if (backImage) { + var backgroundImage = 'background-image:url(' + backImage + ')'; + + styles.front += backgroundImage; + styles.back += backgroundImage; + } + + // Prep style attribute + if (styles.front) { + styles.front = ' style="' + styles.front + '"'; + } + if (styles.back) { + styles.back = ' style="' + styles.back + '"'; + } + + return styles; + }; + + /** + * Convert hex color into shade depending on given percent + * + * @private + * @param {string} color + * @param {number} percent + * @return {string} new color + */ + var shade = function (color, percent) { + var newColor = '#'; + + // Determine if we should lighten or darken + var max = (percent < 0 ? 0 : 255); + + // Always stay positive + if (percent < 0) { + percent *= -1; + } + percent /= 100; + + for (var i = 1; i < 6; i += 2) { + // Grab channel and convert from hex to dec + var channel = parseInt(color.substr(i, 2), 16); + + // Calculate new shade and convert back to hex + channel = (Math.round((max - channel) * percent) + channel).toString(16); + + // Make sure to always use two digits + newColor += (channel.length < 2 ? '0' + channel : channel); + } + + return newColor; + }; + })(H5P.MemoryGame, H5P.EventDispatcher, H5P.jQuery); diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000..48edea1 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /language/.en.json + translation: /language/%two_letters_code%.json diff --git a/language/.en.json b/language/.en.json new file mode 100644 index 0000000..8f501f2 --- /dev/null +++ b/language/.en.json @@ -0,0 +1,87 @@ +{ + "semantics": [ + { + "widgets": [ + { + "label": "Default" + } + ], + "label": "Cards", + "entity": "card", + "field": { + "label": "Card", + "fields": [ + { + "label": "Image" + }, + { + "label": "Matching Image", + "description": "An optional image to match against instead of using two cards with the same image." + }, + { + "label": "Description", + "description": "An optional short text that will pop up once the two matching cards are found." + } + ] + } + }, + { + "label": "Behavioural settings", + "description": "These options will let you control how the game behaves.", + "fields": [ + { + "label": "Position the cards in a square", + "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." + }, + { + "label": "Number of cards to use", + "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." + }, + { + "label": "Add button for retrying when the game is over" + } + ] + }, + { + "label": "Look and feel", + "description": "Control the visuals of the game.", + "fields": [ + { + "label": "Theme Color", + "description": "Choose a color to create a theme for your card game.", + "default": "#909090", + "spectrum": {} + }, + { + "label": "Card Back", + "description": "Use a custom back for your cards." + } + ] + }, + { + "label": "Localization", + "fields": [ + { + "label": "Card turns text", + "default": "Card turns" + }, + { + "label": "Time spent text", + "default": "Time spent" + }, + { + "label": "Feedback text", + "default": "Good work!" + }, + { + "label": "Try again button text", + "default": "Try again?" + }, + { + "label": "Close button label", + "default": "Close" + } + ] + } + ] +} \ No newline at end of file diff --git a/language/ar.json b/language/ar.json index 3ef63b3..a61cb4e 100644 --- a/language/ar.json +++ b/language/ar.json @@ -10,9 +10,7 @@ "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." }, { @@ -23,29 +21,28 @@ } }, { - "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" } ] }, + { + "fields": [ + {}, + {} + ] + }, { "label": "الأقلمة", "fields": [ @@ -58,13 +55,9 @@ { "label": "نص الملاحظات" }, - { - "englishLabel": "Try again button text", - "label": "Try again button text", - "englishDefault": "Try again?", - "default": "Try again?" - } + {}, + {} ] } ] -} +} \ No newline at end of file diff --git a/language/bs.json b/language/bs.json new file mode 100644 index 0000000..9a6c016 --- /dev/null +++ b/language/bs.json @@ -0,0 +1,69 @@ +{ + "semantics": [ + { + "label": "Karte", + "entity": "karte", + "field": { + "label": "Karte", + "fields": [ + { + "label": "Slika" + }, + { + "label": "Ista slika", + "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": "Podešavanje ponašanja", + "description": "These options will let you control how the game behaves.", + "fields": [ + { + "label": "Poredaj karte u redove ", + "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." + }, + { + "label": "Broj karata za upotrebu", + "description": "Setting this to a number greater than 2 will make the game pick random cards from the list of cards." + }, + { + "label": "Add button for retrying when the game is over" + } + ] + }, + { + "fields": [ + {}, + {} + ] + }, + { + "label": "Prijevod", + "fields": [ + { + "label": "Tekst kad se okrene karta ", + "default": "Okrenuta karta" + }, + { + "label": "Tekst za provedeno vrijeme", + "default": "Provedeno vrijeme" + }, + { + "label": "Feedback tekst", + "default": "BRAVO!" + }, + { + "label": "Tekst na dugmetu pokušaj ponovo", + "default": "Pokušaj ponovo?" + }, + {} + ] + } + ] +} \ No newline at end of file diff --git a/language/de.json b/language/de.json index d776e7c..533d1d3 100644 --- a/language/de.json +++ b/language/de.json @@ -10,9 +10,7 @@ "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." }, { @@ -23,29 +21,28 @@ } }, { - "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" } ] }, + { + "fields": [ + {}, + {} + ] + }, { "label": "Übersetzung", "fields": [ @@ -61,13 +58,9 @@ "label": "Text als Rückmeldung", "default": "Gute Arbeit!" }, - { - "englishLabel": "Try again button text", - "label": "Try again button text", - "englishDefault": "Try again?", - "default": "Try again?" - } + {}, + {} ] } ] -} +} \ No newline at end of file diff --git a/language/fr.json b/language/fr.json index 41f9217..22313fc 100644 --- a/language/fr.json +++ b/language/fr.json @@ -10,9 +10,7 @@ "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." }, { @@ -23,29 +21,28 @@ } }, { - "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" } ] }, + { + "fields": [ + {}, + {} + ] + }, { "label": "Interface", "fields": [ @@ -61,13 +58,9 @@ "label": "Texte de l'appréciation finale", "default": "Bien joué !" }, - { - "englishLabel": "Try again button text", - "label": "Try again button text", - "englishDefault": "Try again?", - "default": "Try again?" - } + {}, + {} ] } ] -} +} \ No newline at end of file diff --git a/language/it.json b/language/it.json index 697442b..1484e25 100644 --- a/language/it.json +++ b/language/it.json @@ -10,9 +10,7 @@ "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." }, { @@ -23,29 +21,28 @@ } }, { - "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" } ] }, + { + "fields": [ + {}, + {} + ] + }, { "label": "Localizzazione", "fields": [ @@ -58,13 +55,9 @@ { "label": "Testo Feedback" }, - { - "englishLabel": "Try again button text", - "label": "Try again button text", - "englishDefault": "Try again?", - "default": "Try again?" - } + {}, + {} ] } ] -} +} \ No newline at end of file diff --git a/language/nb.json b/language/nb.json index 5633b0d..5905bb6 100644 --- a/language/nb.json +++ b/language/nb.json @@ -1,86 +1,80 @@ { "semantics": [ { - "englishLabel": "Cards", "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." } ] } }, { - "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": "Localization", + "label": "Tilpass utseende", + "description": "Kontroller de visuelle aspektene ved spillet.", + "fields": [ + { + "label": "Temafarge", + "description": "Velg en farge for å skape et tema over kortspillet ditt." + }, + { + "label": "Kortbaksiden", + "description": "Bruk en tilpasset kortbakside for kortene dine." + } + ] + }, + { "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?" + }, + { + "label": "Lukk knapp-merkelapp", + "default": "Lukk" } ] } ] -} +} \ No newline at end of file diff --git a/library.json b/library.json index bac360c..a396e92 100644 --- a/library.json +++ b/library.json @@ -3,7 +3,7 @@ "description": "See how many cards you can remember!", "majorVersion": 1, "minorVersion": 2, - "patchVersion": 2, + "patchVersion": 3, "runnable": 1, "author": "Joubel", "license": "MIT", @@ -35,6 +35,23 @@ "machineName": "H5P.Timer", "majorVersion": 0, "minorVersion": 4 + }, + { + "machineName": "FontAwesome", + "majorVersion": 4, + "minorVersion": 5 + } + ], + "editorDependencies": [ + { + "machineName": "H5PEditor.ColorSelector", + "majorVersion": 1, + "minorVersion": 2 + }, + { + "machineName": "H5PEditor.VerticalTabs", + "majorVersion": 1, + "minorVersion": 3 } ] -} \ No newline at end of file +} diff --git a/memory-game.css b/memory-game.css index cb3f9ef..199a07b 100644 --- a/memory-game.css +++ b/memory-game.css @@ -25,6 +25,7 @@ display: inline-block !important; margin: auto !important; vertical-align: middle; + position: relative; } .h5p-memory-game .h5p-memory-wrap { float: left; @@ -55,6 +56,7 @@ width: 100%; height: 100%; background: #cfcfcf; + background-size: cover; border: 2px solid #d0d0d0; box-sizing: border-box; -moz-box-sizing: border-box; @@ -75,14 +77,32 @@ .h5p-memory-game .h5p-memory-card .h5p-front { cursor: pointer; text-align: center; + color: #909090; } -.h5p-memory-game .h5p-memory-card .h5p-front:hover { - background: #dfdfdf; +.h5p-memory-game .h5p-memory-card .h5p-front:before, +.h5p-memory-game .h5p-memory-card .h5p-back:before, +.h5p-memory-game .h5p-memory-image:before { + position: absolute; + display: block; + content: ""; + width: 100%; + height: 100%; + background: #fff; + opacity: 0; } -.h5p-memory-game .h5p-memory-card .h5p-front:before { +.h5p-memory-game.h5p-invert-shades .h5p-memory-card .h5p-front:before, +.h5p-memory-game.h5p-invert-shades .h5p-memory-card .h5p-back:before, +.h5p-memory-game.h5p-invert-shades .h5p-memory-image:before { + background: #000; +} + +.h5p-memory-game .h5p-memory-card .h5p-front:hover:before { + opacity: 0.4; +} +.h5p-memory-game .h5p-memory-card .h5p-front > span:before { + position: relative; content: "?"; font-size: 3.75em; - color: #909090; line-height: 1.67em; } .h5p-memory-game .h5p-memory-card .h5p-front:after { @@ -100,15 +120,19 @@ background-image: radial-gradient(ellipse closest-side, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0) 100%); } .h5p-memory-game .h5p-memory-card .h5p-back { - line-height: 5.9em; + line-height: 5.83em; text-align: center; - background: #f0f0f0; + background-color: #f0f0f0; -webkit-transform: rotateY(-180deg); -moz-transform: rotateY(-180deg); transform: rotateY(-180deg); filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -ms-transform: scale(0,1.1); } +.h5p-memory-game .h5p-memory-card .h5p-back:before, +.h5p-memory-game .h5p-memory-image:before { + opacity: 0.5; +} .h5p-memory-game .h5p-memory-card.h5p-flipped .h5p-back { -webkit-transform: rotateY(0deg); -moz-transform: rotateY(0deg); @@ -124,6 +148,8 @@ } .h5p-memory-game .h5p-memory-card.h5p-matched { opacity: 0.3; +} +.h5p-memory-game .h5p-memory-card.h5p-matched img { filter: grayscale(100%); } @@ -170,19 +196,32 @@ .h5p-memory-game .h5p-memory-pop { display: none; background: #fff; - padding: 1em; - width: 20em; + padding: 0.25em; + width: 24em; max-width: 90%; position: absolute; top: 50%; left: 50%; - box-shadow: 0 0 1em #666; + box-shadow: 0 0 2em #666; + border-radius: 0.25em; -webkit-transform: translate(-50%,-50%); -moz-transform: translate(-50%,-50%); transform: translate(-50%,-50%); } +.h5p-memory-game .h5p-memory-top { + padding: 0em 1em; + background-color: #f0f0f0; + background-size: cover; + text-align: center; + margin-bottom: 1.75em; + border-bottom: 1px solid #d0d0d0; +} .h5p-memory-game .h5p-memory-image { - float: left; + display: inline-block; + line-height: 5.83em; + position: relative; + top: 1.5em; + left: -0.5em; border: 2px solid #d0d0d0; box-sizing: border-box; -moz-box-sizing: border-box; @@ -191,24 +230,79 @@ width: 6.25em; height: 6.25em; text-align: center; + overflow: hidden; + box-shadow: 0 0 1em rgba(125,125,125,0.5); + background-size: cover; +} +.h5p-memory-game .h5p-memory-image:first-child { + top: 1em; + left: 0; +} +.h5p-memory-game .h5p-memory-two-images .h5p-memory-image:first-child { + left: 0.5em; } .h5p-memory-game .h5p-row-break { clear: left; } .h5p-memory-game .h5p-memory-desc { - margin-left: 7em; + padding: 1em; + margin-bottom: 0.5em; + text-align: center; +} +.h5p-memory-game .h5p-memory-close { + cursor: pointer; + position: absolute; + top: 0.5em; + right: 0.5em; + font-size: 2em; + width: 1em; + height: 1em; + text-align: center; + color: #888; +} +.h5p-memory-game .h5p-memory-close:before { + content: "\00D7" +} +.h5p-memory-game .h5p-memory-close:hover { + color: #666; +} +.h5p-memory-game .h5p-memory-close:focus { + outline: 2px dashed pink; } .h5p-memory-reset { position: absolute; top: 50%; left: 50%; - transform: translate(-50%,-50%); + transform: translate(-50%,-50%) scale(1) rotate(0); cursor: pointer; - font-style: italic; - text-shadow: 0 0 0.5em white; - padding: 0.125em 0.25em; - line-height: 1; + line-height: 1.2; + padding: 0.5em 1.25em; + border-radius: 2em; + background: #1a73d9; + color: #ffffff; + box-shadow: 0 0.5em 1em #999; + opacity: 1; + transition: box-shadow 200ms linear, margin 200ms linear, transform 300ms ease-out, opacity 300ms ease-out; +} +.h5p-memory-reset:before { + font-family: 'H5PFontAwesome4'; + content: "\f01e"; + margin-right: 0.5em; +} +.h5p-memory-reset:hover, +.h5p-memory-reset:focus { + background: #1356a3; + box-shadow: 0 1em 1.5em #999; + margin-top: -0.2em; } .h5p-memory-reset:focus { - outline: dashed pink; + outline: 2px dashed pink; +} +.h5p-memory-transin { + transform: translate(-50%,-50%) scale(0) rotate(180deg); + opacity: 0; +} +.h5p-memory-transout { + transform: translate(-50%,-450%) scale(0) rotate(360deg); + opacity: 0; } diff --git a/memory-game.js b/memory-game.js index 2e2cd2f..a0029f6 100644 --- a/memory-game.js +++ b/memory-game.js @@ -60,14 +60,14 @@ H5P.MemoryGame = (function (EventDispatcher, $) { var isFinished = (removed === cards.length); var desc = card.getDescription(); - if (isFinished) { - self.triggerXAPIScored(1, 1, 'completed'); - } - if (desc !== undefined) { // Pause timer and show desciption. timer.pause(); - popup.show(desc, card.getImage(), function () { + var imgs = [card.getImage()]; + if (card.hasTwoImages) { + imgs.push(mate.getImage()); + } + popup.show(desc, imgs, cardStyles ? cardStyles.back : undefined, function () { if (isFinished) { // Game done finished(); @@ -91,19 +91,34 @@ H5P.MemoryGame = (function (EventDispatcher, $) { var finished = function () { timer.stop(); $feedback.addClass('h5p-show'); + + // Create and trigger xAPI event 'completed' + var completedEvent = self.createXAPIEventTemplate('completed'); + completedEvent.setScoredResult(1, 1, self, true, true); + completedEvent.data.statement.result.duration = 'PT' + (Math.round(timer.getTime() / 10) / 100) + 'S'; + self.trigger(completedEvent); + if (parameters.behaviour && parameters.behaviour.allowRetry) { // Create retry button - var retryButton = createButton('reset', parameters.l10n.tryAgain || 'Try again?', function () { + var retryButton = createButton('reset', parameters.l10n.tryAgain || 'Reset', function () { // Trigger handler (action) - resetGame(); + retryButton.classList.add('h5p-memory-transout'); + setTimeout(function () { + // Remove button on nextTick to get transition effect + $wrapper[0].removeChild(retryButton); + }, 300); - // Remove button from DOM - $wrapper[0].removeChild(this); + resetGame(); }); + retryButton.classList.add('h5p-memory-transin'); + setTimeout(function () { + // Remove class on nextTick to get transition effect + retryButton.classList.remove('h5p-memory-transin'); + }, 0); // Same size as cards - retryButton.style.fontSize = $wrapper.children('ul')[0].style.fontSize; + retryButton.style.fontSize = (parseFloat($wrapper.children('ul')[0].style.fontSize) * 0.75) + 'px'; $wrapper[0].appendChild(retryButton); // Add to DOM } @@ -247,21 +262,31 @@ H5P.MemoryGame = (function (EventDispatcher, $) { return cardsToUse; }; + var cardStyles, invertShades; + if (parameters.lookNFeel) { + // If the contrast between the chosen color and white is too low we invert the shades to create good contrast + invertShades = (parameters.lookNFeel.themeColor && + getContrast(parameters.lookNFeel.themeColor) < 1.7 ? -1 : 1); + var backImage = (parameters.lookNFeel.cardBack ? H5P.getPath(parameters.lookNFeel.cardBack.path, id) : null); + cardStyles = MemoryGame.Card.determineStyles(parameters.lookNFeel.themeColor, invertShades, backImage); + } + // Initialize cards. var cardsToUse = getCardsToUse(); for (var i = 0; i < cardsToUse.length; i++) { var cardParams = cardsToUse[i]; if (MemoryGame.Card.isValid(cardParams)) { // Create first card - var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.description); + var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.description, cardStyles); if (MemoryGame.Card.hasTwoImages(cardParams)) { // Use matching image for card two - cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.description); + cardTwo = new MemoryGame.Card(cardParams.match, id, 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); + cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.description, cardStyles); } // Add cards to card list for shuffeling @@ -280,6 +305,9 @@ H5P.MemoryGame = (function (EventDispatcher, $) { this.triggerXAPI('attempted'); // TODO: Only create on first attach! $wrapper = $container.addClass('h5p-memory-game').html(''); + if (invertShades === -1) { + $container.addClass('h5p-invert-shades'); + } // Add cards to list var $list = $('