{"version":3,"file":"spotlight.min.js","sources":["https:\/\/moodle.sonsbeekmedia.nl\/caie_39\/mod\/teachingtools\/teachingapp\/spotlight\/amd\/src\/spotlight.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 * Load an image and let the user hover over the image to reveal a part of the image.\n *\n * @module teachingapp_spotlight\/spotlight\n * @class spotlight\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 AriaEnhance from 'mod_teachingtools\/ariaenhance';\n\nclass GameElement {\n constructor(names, rootElement) {\n this.rootElement = rootElement;\n this.storeConfig = new StoreConfigElement(names, rootElement);\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.revealButton = this.rootElement.querySelector('[data-action=\"reveal\"]');\n this.resetButton = this.rootElement.querySelector('[data-region=\"reset\"]');\n this.previewDiv = this.configuratorZone.querySelector('[data-region=\"searchimage\"]');\n this.gridContainer = null;\n this.isTeacher = this.rootElement.dataset.teacher;\n this.config = {\n radius: null,\n searchimage: null,\n animate: null,\n speed: null,\n };\n this.running = false;\n this.revealed = false;\n this.configurator();\n this.addEventListeners();\n this.render();\n AriaEnhance.addTabListener(this.rootElement);\n }\n\n async reset() {\n this.revealed = true;\n await this.configurator();\n this.running = false;\n this.render();\n }\n\n \/**\n * Load the config from the server.\n *\/\n async loadConfig() {\n this.config.radius = await this.storeConfig.getCustomData('radius');\n if (!this.config.radius) {\n this.config.radius = 5;\n }\n\n this.config.animate = await this.storeConfig.getCustomData('animate');\n if (!this.config.animate) {\n this.config.animate = false;\n }\n\n this.config.searchimage = await this.storeConfig.getCustomData('image1');\n\n this.config.speed = await this.storeConfig.getCustomData('speed');\n if (!this.config.speed) {\n this.config.speed = 50;\n }\n }\n\n \/**\n * The custom configurator for this game.\n *\/\n async configurator() {\n await this.loadConfig();\n const imageUpload = this.configuratorZone.querySelector('[data-action=\"imageupload\"]');\n\n const imageContainer = document.createElement('div');\n imageContainer.classList.add('spotlight-images', 'position-relative', 'fill-container', 'w-100');\n const fileLabel = imageUpload.closest('.custom-file').querySelector('.custom-file-label');\n\n \/\/ Load image if already set.\n if (this.config.searchimage) {\n fileLabel.innerHTML = this.config.searchimage.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.searchimage = {\n name: file.name,\n type: file.type,\n };\n\n if (this.isTeacher) {\n imageHandler.saveImage(this.rootElement.dataset.cmid, 'spotlight', 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 setRadius = this.configuratorZone.querySelector('[data-action=\"setradius\"]');\n setRadius.value = this.config.radius;\n\n if (!setRadius.dataset.listener) {\n setRadius.addEventListener('input', () => {\n this.config.radius = setRadius.value;\n });\n setRadius.addEventListener('blur', () => {\n this.storeConfig.setCustomData('radius', this.config.radius);\n });\n setRadius.dataset.listener = true;\n }\n\n const setAnimate = this.configuratorZone.querySelector('[data-action=\"animate\"]');\n setAnimate.checked = this.config.animate;\n\n if (!setAnimate.dataset.listener) {\n setAnimate.addEventListener('change', () => {\n this.config.animate = setAnimate.checked;\n this.storeConfig.setCustomData('animate', this.config.animate);\n });\n setAnimate.dataset.listener = true;\n }\n\n const setSpeed = this.configuratorZone.querySelector('[data-action=\"speed\"]');\n setSpeed.value = this.config.speed;\n\n if (!setSpeed.dataset.listener) {\n setSpeed.addEventListener('change', () => {\n this.config.speed = setSpeed.value;\n this.storeConfig.setCustomData('speed', this.config.speed);\n });\n setSpeed.dataset.listener = true;\n }\n\n }\n\n applyImage(src) {\n const previewContainer = document.createElement('div');\n previewContainer.classList.add('position-relative', 'fill-container', 'w-100');\n const previewImage = new Image();\n previewImage.src = src;\n previewImage.classList.add('img-fluid');\n previewContainer.appendChild(previewImage);\n this.previewDiv.innerHTML = '';\n this.previewDiv.append(previewContainer);\n\n const imageContainer = document.createElement('div');\n imageContainer.classList.add('spotlight-images', 'position-relative', 'fill-container', 'w-100', 'd-flex',\n 'align-items-center', 'justify-content-center');\n const img = new Image();\n img.src = src;\n img.classList.add('img-fit');\n img.style.opacity = 0;\n img.dataset.region = 'mouseoverimage';\n imageContainer.appendChild(img);\n this.drawZone.innerHTML = '';\n this.drawZone.append(imageContainer);\n img.addEventListener('load', () => {\n const spotlight = document.createElement('div');\n spotlight.classList.add('spotlight', 'position-absolute', 'h-100', 'w-100');\n spotlight.style.background = 'radial-gradient(circle at 0 0, rgba(0,0,0) 0, rgba(0,0,0) 0)';\n this.drawZone.append(spotlight);\n });\n if (this.config.searchimage.content !== src) {\n this.config.searchimage.content = src;\n this.storeConfig.setCustomData('image1', this.config.searchimage);\n }\n this.infoBox.classList.add('d-none');\n this.infoBox.classList.remove('active');\n }\n\n \/**\n * Render the game.\n * @returns {void}\n *\/\n async render() {\n await this.loadConfig();\n if (!this.config.searchimage.content) {\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.searchimage.content);\n }\n\n drawSpotlight(left, top, circlesize) {\n this.spotlight = this.drawZone.querySelector('.spotlight');\n if (!this.spotlight) {\n return;\n }\n let innerCircle = parseInt(circlesize * 8);\n let outerCircle = parseInt(circlesize * 10);\n let spotlightSize = `transparent ${innerCircle}px, rgba(0, 0, 0, 1) ${outerCircle}px)`;\n this.spotlight.style.backgroundImage = `radial-gradient(circle at ${left}% ${top}%, ${spotlightSize}`;\n }\n\n addEventListeners() {\n \/\/ Resize the grid tiles when the window is resized.\n this.rootElement.addEventListener('click', (e) => {\n if (e.target.closest('.spotlight')) {\n if (e.target.closest('button') || e.target.closest('.configurator')) {\n return;\n }\n if (this.revealed) {\n return;\n }\n this.animateSpotlight();\n }\n });\n\n this.configuratorZone.querySelector('[data-dismiss=\"configurator\"]').addEventListener('click', () => {\n this.revealed = false;\n this.render();\n });\n\n this.resetButton.addEventListener('click', () => {\n this.revealed = false;\n this.render();\n });\n\n this.left = 50;\n this.top = 50;\n this.drawZone.addEventListener('mousemove', (e) => {\n this.spotlight = this.drawZone.querySelector('.spotlight');\n if (!this.spotlight) {\n return;\n }\n if (this.revealed) {\n return;\n }\n this.mouseOverImage = this.drawZone.querySelector('[data-region=\"mouseoverimage\"]');\n this.mouseOverImage.style.opacity = 1;\n\n \/\/ Create the spotlight.\n const bounds = this.drawZone.getBoundingClientRect();\n this.left = (e.clientX - bounds.left) \/ this.drawZone.offsetWidth * 100;\n this.top = (e.pageY - bounds.top) \/ this.drawZone.offsetHeight * 100;\n\n this.drawSpotlight(this.left, this.top, this.config.radius);\n });\n \/\/ Also draw the spotlight when the user uses the keyboard to navigate.\n \/\/ Move the spotlight with the arrow keys.\n this.drawZone.addEventListener('keydown', (e) => {\n if (e.target !== this.drawZone) {\n return;\n }\n if (this.revealed) {\n return;\n }\n this.running = false;\n this.mouseOverImage = this.drawZone.querySelector('[data-region=\"mouseoverimage\"]');\n this.mouseOverImage.style.opacity = 1;\n let moveBy = 1;\n if (e.shiftKey) {\n moveBy = 10;\n }\n if (e.key === 'ArrowUp') {\n this.top -= moveBy;\n }\n if (e.key === 'ArrowDown') {\n this.top += moveBy;\n }\n if (e.key === 'ArrowLeft') {\n this.left -= moveBy;\n }\n if (e.key === 'ArrowRight') {\n this.left += moveBy;\n }\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n e.preventDefault();\n }\n if (e.key === 'Enter') {\n this.revealImage();\n }\n this.drawSpotlight(this.left, this.top, this.config.radius);\n });\n\n this.revealButton.addEventListener('click', () => {\n this.revealImage();\n });\n }\n\n \/**\n * Reveals the image.\n *\/\n revealImage() {\n this.spotlight = this.drawZone.querySelector('.spotlight');\n if (!this.spotlight) {\n return;\n }\n this.running = false;\n this.revealed = true;\n this.drawSpotlight(this.left, this.top, this.config.radius);\n let duration = 1000;\n let start = performance.now();\n let radius = parseInt(this.config.radius);\n const frame = () => {\n let now = performance.now();\n \/\/ Get numeric value of now without decimal places.\n let t = Math.min(1, (now - start) \/ duration);\n t = 3 * t * t - 2 * t * t * t; \/\/ Ease in out.\n if (t < 1) {\n this.drawSpotlight(this.left, this.top, radius + t * this.drawZone.offsetWidth \/ 3);\n requestAnimationFrame(frame);\n }\n };\n requestAnimationFrame(frame);\n }\n\n \/**\n * Animate the spotlight to bounce around the image.\n *\/\n animateSpotlight() {\n if (!this.config.animate) {\n return;\n }\n const spotlight = this.drawZone.querySelector('.spotlight');\n if (!spotlight) {\n return;\n }\n\n if (!this.running) {\n this.running = true;\n } else {\n this.running = false;\n return;\n }\n\n let x = this.left;\n let y = this.top;\n let directionX = 1;\n let directionY = 1;\n let speedx = 1.2 * (parseInt(this.config.speed) \/ 100);\n let speedy = 0.5 * (parseInt(this.config.speed) \/ 100);\n\n const frame = () => {\n if (!this.running || !this.config.animate) {\n return;\n }\n x += directionX * speedx;\n y += directionY * speedy;\n this.drawSpotlight(x, y, this.config.radius);\n if (x > 95 || x < 5) {\n directionX *= -1;\n }\n if (y > 95 || y < 5) {\n directionY *= -1;\n }\n\n requestAnimationFrame(frame);\n };\n requestAnimationFrame(frame);\n }\n\n}\n\nconst init = async(cmid) => {\n const GE = new GameEngineLoader('spotlight', 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","configuratorZone","this","querySelector","drawZone","infoBox","revealButton","resetButton","previewDiv","gridContainer","isTeacher","dataset","teacher","config","radius","searchimage","animate","speed","running","revealed","configurator","addEventListeners","render","addTabListener","getCustomData","loadConfig","imageUpload","document","createElement","classList","add","fileLabel","closest","innerHTML","name","listener","addEventListener","event","file","target","files","reader","FileReader","result","length","setTimeout","remove","type","saveImage","cmid","then","success","applyImage","fileurl","catch","Notification","exception","readAsDataURL","setRadius","value","setCustomData","setAnimate","checked","setSpeed","src","previewContainer","previewImage","Image","appendChild","append","imageContainer","img","style","opacity","region","spotlight","background","content","drawSpotlight","left","top","circlesize","innerCircle","parseInt","outerCircle","spotlightSize","backgroundImage","e","animateSpotlight","mouseOverImage","bounds","getBoundingClientRect","clientX","offsetWidth","pageY","offsetHeight","moveBy","shiftKey","key","preventDefault","revealImage","start","performance","now","frame","t","Math","min","requestAnimationFrame","x","y","directionX","directionY","speedx","speedy","init","async","GE","GameEngineLoader","load","game","run"],"mappings":"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"}