diff --git a/card.js b/card.js index 867d405..9919018 100644 --- a/card.js +++ b/card.js @@ -12,30 +12,71 @@ * @param {string} [description] * @param {Object} [styles] */ - MemoryGame.Card = function (image, id, alt, l10n, description, styles) { + MemoryGame.Card = function (image, id, alt, l10n, description, styles, audio) { /** @alias H5P.MemoryGame.Card# */ var self = this; // Initialize event inheritance EventDispatcher.call(self); - var path = H5P.getPath(image.path, id); - var width, height, $card, $wrapper, removedState, flippedState; + var path, width, height, $card, $wrapper, removedState, flippedState, audioPlayer; alt = alt || 'Missing description'; // Default for old games - if (image.width !== undefined && image.height !== undefined) { - if (image.width > image.height) { - width = '100%'; - height = 'auto'; + if (image && image.path) { + path = H5P.getPath(image.path, id); + + if (image.width !== undefined && image.height !== undefined) { + if (image.width > image.height) { + width = '100%'; + height = 'auto'; + } + else { + height = '100%'; + width = 'auto'; + } } else { - height = '100%'; - width = 'auto'; + width = height = '100%'; } } - else { - width = height = '100%'; + + if (audio) { + // Check if browser supports audio. + audioPlayer = document.createElement('audio'); + if (audioPlayer.canPlayType !== undefined) { + // Add supported source files. + for (var i = 0; i < audio.length; i++) { + if (audioPlayer.canPlayType(audio[i].mime)) { + var source = document.createElement('source'); + source.src = H5P.getPath(audio[i].path, id); + source.type = audio[i].mime; + audioPlayer.appendChild(source); + } + } + } + + if (!audioPlayer.children.length) { + audioPlayer = null; // Not supported + } + else { + audioPlayer.controls = false; + audioPlayer.preload = 'auto'; + + var handlePlaying = function () { + if ($card) { + $card.addClass('h5p-memory-audio-playing'); + } + }; + var handleStopping = function () { + if ($card) { + $card.removeClass('h5p-memory-audio-playing'); + } + }; + audioPlayer.addEventListener('play', handlePlaying); + audioPlayer.addEventListener('ended', handleStopping); + audioPlayer.addEventListener('pause', handleStopping); + } } /** @@ -74,6 +115,10 @@ return; } + if (audioPlayer) { + audioPlayer.play(); + } + $card.addClass('h5p-flipped'); self.trigger('flip'); flippedState = true; @@ -83,6 +128,11 @@ * Flip card back. */ self.flipBack = function () { + if (audioPlayer) { + audioPlayer.pause(); + audioPlayer.currentTime = 0; + } + self.updateLabel(null, null, true); // Reset card label $card.removeClass('h5p-flipped'); flippedState = false; @@ -100,6 +150,11 @@ * Reset card to natural state */ self.reset = function () { + if (audioPlayer) { + audioPlayer.pause(); + audioPlayer.currentTime = 0; + } + self.updateLabel(null, null, true); // Reset card label flippedState = false; removedState = false; @@ -133,7 +188,7 @@ $wrapper = $('
  • ' + '
    ' + (styles && styles.backImage ? '' : '') + '
    ' + '
    ' + - '' + alt + '' + + (path ? '' + alt + '' + (audioPlayer ? '
    ' : '') : '') + '
    ' + '
  • ') .appendTo($container) @@ -176,6 +231,19 @@ self.flip(); }) .end(); + + if (audioPlayer) { + $card.children('.h5p-back') + .click(function () { + if ($card.hasClass('h5p-memory-audio-playing')) { + audioPlayer.pause(); + audioPlayer.currentTime = 0; + } + else { + audioPlayer.play(); + } + }) + } }; /** @@ -236,8 +304,9 @@ */ MemoryGame.Card.isValid = function (params) { return (params !== undefined && - params.image !== undefined && - params.image.path !== undefined); + (params.image !== undefined && + params.image.path !== undefined) || + params.audio); }; /** @@ -249,8 +318,9 @@ */ MemoryGame.Card.hasTwoImages = function (params) { return (params !== undefined && - params.match !== undefined && - params.match.path !== undefined); + (params.match !== undefined && + params.match.path !== undefined) || + params.matchAudio); }; /** diff --git a/library.json b/library.json index 16b8145..9092305 100644 --- a/library.json +++ b/library.json @@ -2,8 +2,8 @@ "title": "Memory Game", "description": "See how many cards you can remember!", "majorVersion": 1, - "minorVersion": 2, - "patchVersion": 12, + "minorVersion": 3, + "patchVersion": 0, "runnable": 1, "author": "Joubel", "license": "MIT", @@ -54,4 +54,4 @@ "minorVersion": 3 } ] -} \ No newline at end of file +} diff --git a/memory-game.css b/memory-game.css index c188210..1b53971 100644 --- a/memory-game.css +++ b/memory-game.css @@ -318,3 +318,28 @@ .h5p-memory-game .h5p-programatically-focusable { outline: none; } +.h5p-memory-audio-instead-of-image { + font-family: 'H5PFontAwesome4'; + width: 100%; + height: 100%; + font-style: normal; + color: #404040; + font-size: 2em; +} +.h5p-memory-audio-button { + position: absolute; + top: 0; + right: 0; + font-family: 'H5PFontAwesome4'; + width: 1em; + height: 1em; + line-height: 1; +} +.h5p-memory-audio-instead-of-image:before, +.h5p-memory-audio-button:before { + content: "\f026"; +} +.h5p-memory-audio-playing .h5p-memory-audio-instead-of-image:before, +.h5p-memory-audio-playing .h5p-memory-audio-button:before { + content: "\f028"; +} diff --git a/memory-game.js b/memory-game.js index 38829de..07bbd0d 100644 --- a/memory-game.js +++ b/memory-game.js @@ -384,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, parameters.l10n, cardParams.description, cardStyles); + var cardTwo, cardOne = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, parameters.l10n, cardParams.description, cardStyles, cardParams.audio); if (MemoryGame.Card.hasTwoImages(cardParams)) { // Use matching image for card two - cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.matchAlt, parameters.l10n, cardParams.description, cardStyles); + cardTwo = new MemoryGame.Card(cardParams.match, id, cardParams.matchAlt, parameters.l10n, cardParams.description, cardStyles, cardParams.matchAudio); cardOne.hasTwoImages = cardTwo.hasTwoImages = true; } else { // Add two cards with the same image - cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, parameters.l10n, cardParams.description, cardStyles); + cardTwo = new MemoryGame.Card(cardParams.image, id, cardParams.imageAlt, parameters.l10n, cardParams.description, cardStyles, cardParams.audio); } // Add cards to card list for shuffeling diff --git a/semantics.json b/semantics.json index 0333ce0..4108971 100644 --- a/semantics.json +++ b/semantics.json @@ -33,6 +33,15 @@ "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." }, + { + "state": "new", + "name": "audio", + "type": "audio", + "importance": "high", + "label": "Audio Track", + "description": "An optional sound that plays when the card is turned.", + "optional": true + }, { "name": "match", "type": "image", @@ -50,6 +59,15 @@ "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." }, + { + "state": "new", + "name": "matchAudio", + "type": "audio", + "importance": "low", + "label": "Matching Audio Track", + "description": "An optional sound that plays when the second card is turned.", + "optional": true + }, { "name": "description", "type": "text", @@ -207,4 +225,4 @@ } ] } -] \ No newline at end of file +]