{"version":3,"file":"imagereveal.min.js","sources":["https:\/\/moodle.sonsbeekmedia.nl\/caie_39\/mod\/teachingtools\/teachingapp\/imagereveal\/amd\/src\/imagereveal.js"],"sourcesContent":["\/* eslint-disable max-len *\/\n\/\/ This file is part of Moodle - http:\/\/moodle.org\/\n\/\/\n\/\/ Moodle is free software: you can redistribute it and\/or modify\n\/\/ it under the terms of the GNU General Public License as published by\n\/\/ the Free Software Foundation, either version 3 of the License, or\n\/\/ (at your option) any later version.\n\/\/\n\/\/ Moodle is distributed in the hope that it will be useful,\n\/\/ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\/\/ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\/\/ GNU General Public License for more details.\n\/\/\n\/\/ You should have received a copy of the GNU General Public License\n\/\/ along with Moodle. If not, see .\n\n\/**\n * Cut an image into tiles, and reveal them by clicking on them.\n *\n * @module teachingapp_imagereveal\/imagereveal\n * @class imagereveal\n * @copyright 2023 Sonsbeekmedia\n * @author Bas Brands \n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n *\/\n\nimport GameEngineLoader from 'mod_teachingtools\/game_engine';\nimport StoreConfigElement from 'mod_teachingtools\/names\/store_config_element';\nimport imageHandler from 'mod_teachingtools\/imagehandler';\nimport Notification from 'core\/notification';\nimport Templates from 'core\/templates';\n\nclass GameElement {\n constructor(names, rootElement) {\n this.rootElement = rootElement;\n this.storeConfig = new StoreConfigElement(names, rootElement);\n this.colors = ['#ffadad', '#ffd6a5', '#fdffb6', '#e9ffe4', '#cdfbff', '#a0c4ff', '#e7e7e7', '#c9c9c9'];\n this.configuratorZone = this.rootElement.querySelector('[data-region=\"configurator\"]');\n this.drawZone = this.rootElement.querySelector('[data-region=\"draw-zone\"]');\n this.infoBox = this.rootElement.querySelector('[data-region=\"infobox\"]');\n this.previewDiv = this.configuratorZone.querySelector('[data-region=\"reveal\"]');\n this.resetButton = this.rootElement.querySelector('[data-region=\"reset\"]');\n this.gridContainer = null;\n this.isTeacher = this.rootElement.dataset.teacher;\n this.config = {};\n this.config.rows = null;\n this.config.columns = null;\n this.config.reveal = null;\n this.config.randomclick = null;\n this.config.tileBorder = 2;\n this.configurator();\n this.addEventListeners();\n this.render();\n }\n\n async reset() {\n this.configurator();\n this.render();\n }\n\n \/**\n * Loat the config from the server.\n *\/\n async loadConfig() {\n this.config.rows = await this.storeConfig.getCustomData('rows');\n if (!this.config.rows) {\n this.config.rows = 5;\n }\n\n this.config.columns = await this.storeConfig.getCustomData('columns');\n if (!this.config.columns) {\n this.config.columns = 5;\n }\n\n this.config.randomclick = await this.storeConfig.getCustomData('randomclick');\n if (!this.config.randomclick) {\n this.config.randomclick = false;\n }\n\n this.config.reveal = await this.storeConfig.getCustomData('image1');\n return true;\n }\n\n applyImage(src) {\n const imageContainer = document.createElement('div');\n imageContainer.classList.add('position-relative', 'fill-container', 'w-100', 'h-100', 'imagereveal-images');\n const img = new Image();\n img.src = src;\n img.classList.add('img-fluid', 'opacity-0');\n imageContainer.appendChild(img);\n\n const previewContainer = imageContainer.cloneNode(true);\n this.previewDiv.innerHTML = '';\n this.previewDiv.classList.add('hasimage');\n this.previewDiv.append(previewContainer);\n this.drawZone.innerHTML = '';\n this.drawZone.append(imageContainer);\n img.addEventListener('load', () => {\n this.createGridTiles(imageContainer);\n this.createGridTiles(previewContainer);\n if (this.config.reveal.content !== src) {\n this.config.reveal.content = src;\n this.storeConfig.setCustomData('image1', this.config.reveal);\n img.classList.remove('opacity-0');\n }\n });\n }\n\n async configurator() {\n await this.loadConfig();\n const imageUpload = this.configuratorZone.querySelector('[data-action=\"imageupload\"]');\n\n const fileLabel = imageUpload.closest('.custom-file').querySelector('.custom-file-label');\n\n \/\/ Load image if already set.\n if (this.config.reveal) {\n fileLabel.innerHTML = this.config.reveal.name;\n }\n\n if (!imageUpload.dataset.listener) {\n imageUpload.addEventListener('change', (event) => {\n const file = event.target.files[0];\n const reader = new FileReader();\n fileLabel.innerHTML = file.name;\n reader.addEventListener('load', () => {\n \/\/ Check if the image is not bigger than 2MB.\n if (reader.result.length > 25000000) {\n this.infoBox.innerHTML = 'Image is too big, please upload a smaller image';\n this.infoBox.classList.add('active');\n setTimeout(() => {\n this.infoBox.classList.remove('active');\n }, 5000);\n return;\n }\n\n this.config.reveal = {\n name: file.name,\n type: file.type,\n };\n\n if (this.isTeacher) {\n imageHandler.saveImage(this.rootElement.dataset.cmid, 'image1', file, reader.result).then((result) => {\n if (result.success) {\n this.applyImage(result.fileurl);\n } else {\n this.applyImage(reader.result);\n }\n return '';\n }).catch(Notification.exception);\n } else {\n this.applyImage(reader.result);\n }\n });\n reader.readAsDataURL(file);\n });\n imageUpload.dataset.listener = true;\n }\n\n const setRows = this.configuratorZone.querySelector('[data-action=\"setrows\"]');\n setRows.value = this.config.rows;\n\n if (!setRows.dataset.listener) {\n setRows.addEventListener('input', () => {\n this.config.rows = setRows.value;\n if (this.config.reveal) {\n this.createGridTiles(this.configuratorZone.querySelector('.imagereveal-images'));\n }\n });\n setRows.addEventListener('blur', () => {\n this.storeConfig.setCustomData('rows', this.config.rows);\n });\n setRows.dataset.listener = true;\n }\n\n const setColumns = this.configuratorZone.querySelector('[data-action=\"setcolumns\"]');\n setColumns.value = this.config.columns;\n\n if (!setColumns.dataset.listener) {\n setColumns.addEventListener('input', () => {\n this.config.columns = setColumns.value;\n if (this.config.reveal) {\n this.createGridTiles(this.configuratorZone.querySelector('.imagereveal-images'));\n }\n });\n setColumns.addEventListener('blur', () => {\n this.storeConfig.setCustomData('columns', this.config.columns);\n });\n setColumns.dataset.listener = true;\n }\n\n const setRandom = this.configuratorZone.querySelector('[data-action=\"setrandom\"]');\n setRandom.checked = this.config.randomclick;\n if (!setRandom.dataset.listener) {\n setRandom.addEventListener('change', () => {\n this.config.randomclick = setRandom.checked;\n this.storeConfig.setCustomData('randomclick', this.config.randomclick);\n });\n setRandom.dataset.listener = true;\n }\n }\n\n \/**\n * Render the game.\n * @returns {void}\n *\/\n async render() {\n await this.loadConfig();\n if (!this.config.reveal) {\n this.infoBox.innerHTML = 'Please upload an image first';\n this.infoBox.classList.remove('d-none');\n this.infoBox.classList.add('active');\n return;\n }\n this.drawZone.innerHTML = '';\n this.infoBox.classList.remove('active');\n\n this.applyImage(this.config.reveal.content);\n }\n\n addEventListeners() {\n \/\/ Resize the grid tiles when the window is resized.\n window.addEventListener('resize', () => {\n this.applyImage(this.config.reveal.content);\n });\n document.addEventListener('AppFullscreenChange', () => {\n this.applyImage(this.config.reveal.content);\n });\n this.resetButton.addEventListener('click', () => {\n this.applyImage(this.config.reveal.content);\n });\n\n const toolWrapper = document.querySelector('[data-region=\"toolwrapper\"]');\n if (!toolWrapper) {\n return;\n }\n\n this.drawZone.addEventListener('keydown', (e) => {\n if (e.key === 'Tab') {\n this.drawZone.classList.add('tab');\n }\n if (e.key === 'Enter') {\n if (e.target.dataset.region === 'tile') {\n e.target.classList.toggle('flip');\n }\n e.preventDefault();\n }\n this.keyBoardNav(e);\n });\n this.drawZone.addEventListener('mousedown', () => {\n this.drawZone.classList.remove('tab');\n });\n\n this.drawZone.addEventListener('focusin', (e) => {\n if (e.target.dataset.region === 'tile') {\n e.target.classList.add('focus');\n }\n });\n this.drawZone.addEventListener('focusout', (e) => {\n if (e.target.dataset.region === 'tile') {\n e.target.classList.remove('focus');\n }\n });\n\n this.rootElement.addEventListener('click', (e) => {\n if (e.target.closest('[data-region=\"tile\"]')) {\n if (this.config.randomclick) {\n const tiles = this.drawZone.querySelectorAll('.imagereveal-grid-tile:not(.flip)');\n const randomTile = tiles[Math.floor(Math.random() * tiles.length)];\n randomTile.classList.add('flip');\n } else {\n const tile = e.target.closest('.imagereveal-grid-tile');\n if (tile.classList.contains('imagereveal-grid-tile')) {\n \/\/ Flip the tile.\n tile.classList.toggle('flip');\n }\n }\n }\n \/\/ FIX THIS FOR THE NEW TOOLCHANGER.\n if (e.target.closest('[data-dismiss=\"configurator\"]')) {\n this.render();\n }\n if (e.target.closest('[data-action=\"reveal\"]')) {\n const tiles = this.drawZone.querySelectorAll('.imagereveal-grid-tile');\n tiles.forEach((tile) => {\n tile.classList.add('flip');\n });\n }\n });\n }\n\n \/**\n * Move the focus on keyboard navigation.\n * @param {Event} e The event.\n *\/\n keyBoardNav(e) {\n const tile = e.target;\n const currentRow = Number(tile.dataset.row);\n const currentCol = Number(tile.dataset.column);\n const tileDown = this.drawZone.querySelector(`[data-row=\"${currentRow + 1}\"][data-column=\"${currentCol}\"]`);\n const tileUp = this.drawZone.querySelector(`[data-row=\"${currentRow - 1}\"][data-column=\"${currentCol}\"]`);\n const tileLeft = this.drawZone.querySelector(`[data-row=\"${currentRow}\"][data-column=\"${currentCol - 1}\"]`);\n const tileRight = this.drawZone.querySelector(`[data-row=\"${currentRow}\"][data-column=\"${currentCol + 1}\"]`);\n\n if (e.key === 'ArrowUp') {\n if (tileUp) {\n tileUp.focus();\n }\n e.preventDefault();\n }\n if (e.key === 'ArrowDown') {\n if (tileDown) {\n tileDown.focus();\n }\n e.preventDefault();\n }\n if (e.key === 'ArrowLeft') {\n if (tileLeft) {\n tileLeft.focus();\n }\n e.preventDefault();\n }\n if (e.key === 'ArrowRight') {\n if (tileRight) {\n tileRight.focus();\n }\n }\n }\n\n \/**\n * Create the grid tiles.\n * @param {HTMLElement} imageContainer - The image container.\n * @param {number} tileBorder - The border size of the tiles.\n * @returns {void}\n *\/\n createGridTiles(imageContainer, tileBorder = null) {\n const image = imageContainer.querySelector('img');\n\n const gridContainer = document.createElement('div');\n gridContainer.classList.add('imagereveal-grid-container', 'position-absolute', 'fill-container');\n gridContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';\n imageContainer.append(gridContainer);\n\n const numTiles = this.config.rows * this.config.columns;\n const tiles = [];\n\n for (let i = 0; i < numTiles; i++) {\n const tile = {\n id: i,\n image: image.src,\n alt: 'Revealed tile image ' + i,\n };\n tiles.push(tile);\n }\n Templates.render('teachingapp_imagereveal\/tiles', {tiles: tiles}).then((html) => {\n gridContainer.innerHTML = html;\n this.setTileSizeAndPosition(gridContainer, tileBorder);\n return '';\n }).catch(Notification.exception);\n }\n\n \/**\n * Set the tile size and position.\n * @param {HTMLElement} gridContainer - The grid container.\n * @param {number} tileBorder - The border size of the tiles.\n *\/\n setTileSizeAndPosition(gridContainer, tileBorder) {\n const bounds = gridContainer.getBoundingClientRect();\n if (tileBorder === null) {\n tileBorder = this.config.tileBorder;\n }\n\n const tileWidth = (bounds.width - (this.config.columns * tileBorder)) \/ this.config.columns;\n const tileHeight = (bounds.height - (this.config.rows * tileBorder)) \/ this.config.rows;\n const tiles = gridContainer.querySelectorAll('.imagereveal-grid-tile');\n tiles.forEach((tile, index) => {\n tile.style.width = tileWidth + 'px';\n tile.style.height = tileHeight + 'px';\n tile.style.left = (index % this.config.columns) * (tileWidth + tileBorder) + 'px';\n tile.style.top = Math.floor(index \/ this.config.columns) * (tileHeight + tileBorder) + 'px';\n tile.dataset.row = Math.floor(index \/ this.config.columns);\n tile.dataset.column = index % this.config.columns;\n\n \/\/ Set the image position.\n const backImage = tile.querySelector('img');\n const x = (index % this.config.columns) * (tileWidth + tileBorder);\n const y = Math.floor(index \/ this.config.columns) * (tileHeight + tileBorder);\n backImage.style.left = `-${x}px`;\n backImage.style.top = `-${y}px`;\n backImage.style.width = `${bounds.width}px`;\n backImage.style.height = `${bounds.height}px`;\n\n const front = tile.querySelector('.front');\n \/\/ Get a random color from the colors array.\n const randomColor = this.colors[Math.floor(Math.random() * this.colors.length)];\n front.style.backgroundColor = randomColor;\n front.innerHTML = index;\n });\n }\n}\n\nconst init = async(cmid) => {\n const GE = new GameEngineLoader('imagereveal', cmid);\n await GE.load();\n const game = new GameElement(GE.names, GE.rootElement);\n GE.run(game);\n};\n\nexport default {\n init: init,\n GameElement\n};\n"],"names":["GameElement","constructor","names","rootElement","storeConfig","StoreConfigElement","colors","configuratorZone","this","querySelector","drawZone","infoBox","previewDiv","resetButton","gridContainer","isTeacher","dataset","teacher","config","rows","columns","reveal","randomclick","tileBorder","configurator","addEventListeners","render","getCustomData","applyImage","src","imageContainer","document","createElement","classList","add","img","Image","appendChild","previewContainer","cloneNode","innerHTML","append","addEventListener","createGridTiles","content","setCustomData","remove","loadConfig","imageUpload","fileLabel","closest","name","listener","event","file","target","files","reader","FileReader","result","length","setTimeout","type","saveImage","cmid","then","success","fileurl","catch","Notification","exception","readAsDataURL","setRows","value","setColumns","setRandom","checked","window","e","key","region","toggle","preventDefault","keyBoardNav","tiles","querySelectorAll","Math","floor","random","tile","contains","forEach","currentRow","Number","row","currentCol","column","tileDown","tileUp","tileLeft","tileRight","focus","image","style","backgroundColor","numTiles","i","id","alt","push","html","setTileSizeAndPosition","bounds","getBoundingClientRect","tileWidth","width","tileHeight","height","index","left","top","backImage","x","y","front","randomColor","init","async","GE","GameEngineLoader","load","game","run"],"mappings":"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"}