{"version":3,"file":"swipe.min.js","sources":["https:\/\/moodle.sonsbeekmedia.nl\/caie_test\/mod\/teachingtools\/teachingapp\/swipe\/amd\/src\/swipe.js"],"sourcesContent":["\/\/ 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 * The simple drag and drop app.\n *\n * @module teachingapp_swipe\/swipe\n * @class swipe\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 Templates from 'core\/templates';\nimport Notification from 'core\/notification';\nimport $ from 'jquery';\nimport '.\/transform';\nimport '.\/tinder';\n\nclass GameElement {\n\n constructor(names, rootElement) {\n this.names = names;\n this.rootElement = rootElement;\n this.drawZone = this.rootElement.querySelector('[data-region=\"swipe-draw-zone\"]');\n this.addEventListeners();\n }\n\n update(names) {\n const wrapper = this.rootElement.querySelector('[data-region=\"swipe-wrapper\"]');\n wrapper.innerHTML = '';\n\n \/\/ Creat a new tinder slider.\n const newTinder = document.createElement('div');\n newTinder.classList.add('tinderslide');\n\n \/\/ Results will be displayed here.\n const endOfDeck = document.createElement('div');\n endOfDeck.classList.add('endofdeck', 'd-none');\n endOfDeck.setAttribute('aria-hidden', 'true');\n endOfDeck.setAttribute('aria-label', 'Swipe results');\n endOfDeck.setAttribute('role', 'region');\n endOfDeck.setAttribute('tabindex', '0');\n endOfDeck.textContent = 'End of deck';\n endOfDeck.dataset.region = 'endofdeck';\n\n \/\/ Cards will be added here.\n const newList = document.createElement('ul');\n wrapper.appendChild(endOfDeck);\n newTinder.appendChild(newList);\n newTinder.dataset.region = 'tinderslide';\n wrapper.appendChild(newTinder);\n\n const namesmap = names.map((name, i) => {\n const last = i === names.length - 1;\n const newName = {\n text: name,\n index: i,\n last: last,\n first: i === 0,\n modurl: M.cfg.wwwroot + '\/mod\/teachingtools\/teachingapp\/swipe\/pix\/'\n };\n return newName;\n });\n\n namesmap.reverse();\n\n const resultRows = [...namesmap];\n\n const templateResults = {\n cards: resultRows.reverse()\n };\n\n Templates.render('teachingapp_swipe\/endofdeck', templateResults).then((html) => {\n endOfDeck.innerHTML = html;\n return '';\n }).catch(Notification.exception);\n\n const template = {\n cards: namesmap\n };\n Templates.render('teachingapp_swipe\/cards', template).then((html) => {\n newList.innerHTML = html;\n setTimeout(() => {\n this.tinder();\n const firstCard = this.rootElement.querySelector('[data-card-id=\"0\"]');\n this.updateTabIndex(firstCard);\n }, 1000);\n this.updateEndOfDeck();\n return '';\n }).catch(Notification.exception);\n }\n\n updateEndOfDeck(card, liked) {\n const endOfDeck = this.rootElement.querySelector('[data-region=\"endofdeck\"]');\n const cardActions = this.rootElement.querySelector('[data-region=\"cardactions\"]');\n const slider = this.rootElement.querySelector('[data-region=\"tinderslide\"]');\n if (card) {\n const cardIndex = card[0].dataset.cardId;\n const currentRow = endOfDeck.querySelector(`[data-index=\"${cardIndex}\"]`);\n if (currentRow.dataset.set === 'true') {\n return;\n }\n const likedIconContainer = currentRow.querySelector('[data-region=\"liked\"]');\n const dislikedIconContainer = currentRow.querySelector('[data-region=\"disliked\"]');\n if (liked) {\n likedIconContainer.classList.remove('d-none');\n } else {\n dislikedIconContainer.classList.remove('d-none');\n }\n currentRow.dataset.set = 'true';\n }\n\n \/\/ Show end of deck if all rows are set.\n const allRows = endOfDeck.querySelectorAll('[data-index]');\n let allSet = false;\n allRows.forEach((row) => {\n if (row.dataset.set === 'true') {\n allSet = true;\n } else {\n allSet = false;\n }\n });\n if (allSet) {\n endOfDeck.classList.remove('d-none');\n endOfDeck.setAttribute('aria-hidden', 'false');\n cardActions.classList.add('d-none');\n slider.classList.add('d-none');\n } else {\n endOfDeck.classList.add('d-none');\n endOfDeck.setAttribute('aria-hidden', 'true');\n cardActions.classList.remove('d-none');\n slider.classList.remove('d-none');\n }\n }\n\n tinder() {\n const tinderSlider = this.rootElement.querySelector('[data-region=\"tinderslide\"]');\n if (tinderSlider.dataset.initialized === 'true') {\n return;\n }\n $(tinderSlider).jTinder({\n \/\/ Dislike callback.\n onDislike: (card) => {\n this.updateEndOfDeck(card, false);\n },\n \/\/ Like callback.\n onLike: (card) => {\n this.updateEndOfDeck(card, true);\n },\n onSwipeDone: (card) => {\n this.updateAriaLive(card[0]);\n this.updateTabIndex(card[0]);\n },\n animationRevertSpeed: 200,\n animationSpeed: 400,\n threshold: 1,\n likeSelector: '.like',\n dislikeSelector: '.dislike'\n });\n const likeButton = this.rootElement.querySelector('[data-action=\"like\"]');\n const dislikeButton = this.rootElement.querySelector('[data-action=\"dislike\"]');\n\n if (!likeButton.dataset.initialized) {\n likeButton.addEventListener('click', (e) => {\n $(tinderSlider).jTinder('like');\n e.preventDefault();\n });\n likeButton.dataset.initialized = 'true';\n }\n\n if (!dislikeButton.dataset.initialized) {\n dislikeButton.addEventListener('click', (e) => {\n $(tinderSlider).jTinder('dislike');\n e.preventDefault();\n });\n dislikeButton.dataset.initialized = 'true';\n }\n\n this.rootElement.addEventListener('keydown', (e) => {\n if (!e.target.closest('.tinderslide li')) {\n return;\n }\n if (e.key === 'ArrowRight') {\n this.focusCard = true;\n $(tinderSlider).jTinder('like');\n e.preventDefault();\n }\n if (e.key === 'ArrowLeft') {\n this.focusCard = true;\n $(tinderSlider).jTinder('dislike');\n e.preventDefault();\n }\n });\n\n tinderSlider.dataset.initialized = 'true';\n }\n\n \/**\n * Update the tab index of the current card and set the tab index of the other cards to -1.\n * @param {HTMLElement} card The current card.\n *\/\n updateTabIndex(card) {\n const allCards = this.rootElement.querySelectorAll('.tinderslide li');\n allCards.forEach((actioncard) => {\n actioncard.setAttribute('tabindex', '-1');\n });\n card.setAttribute('tabindex', '0');\n if (this.focusCard) {\n card.focus();\n this.focusCard = false;\n }\n }\n\n \/**\n * Updates an ARIA live region with information about the current card.\n * @param {HTMLElement} card The current card.\n *\/\n updateAriaLive(card) {\n if (!this.ariaLive) {\n this.createAriaLive();\n }\n let cardText = '';\n cardText = 'A new swipe card is shown: ' + card.querySelector('.innertext').textContent;\n this.ariaLive.textContent = cardText;\n }\n\n \/**\n * Creates an ARIA live region for announcing dynamic updates to screen readers.\n *\/\n createAriaLive() {\n const ariaLive = document.createElement('div');\n ariaLive.setAttribute('aria-live', 'polite');\n ariaLive.setAttribute('aria-atomic', 'true');\n ariaLive.setAttribute('aria-relevant', 'additions');\n ariaLive.classList.add('sr-only');\n this.rootElement.appendChild(ariaLive);\n this.ariaLive = ariaLive;\n }\n\n \/**\n * Add event listeners.\n *\/\n addEventListeners() {\n \/\/ Initialize the reset button.\n this.rootElement.addEventListener('click', (e) => {\n if (e.target.closest('[data-action=\"reset\"]')) {\n this.update(this.names.names);\n e.preventDefault();\n }\n });\n this.rootElement.addEventListener('keydown', (e) => {\n if (e.key === 'Tab') {\n this.drawZone.classList.add('tab');\n }\n });\n this.rootElement.addEventListener('mousedown', () => {\n this.drawZone.classList.remove('tab');\n });\n }\n}\n\nconst init = async(cmid) => {\n const GE = new GameEngineLoader('swipe', 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","drawZone","this","querySelector","addEventListeners","update","wrapper","innerHTML","newTinder","document","createElement","classList","add","endOfDeck","setAttribute","textContent","dataset","region","newList","appendChild","namesmap","map","name","i","text","index","last","length","first","modurl","M","cfg","wwwroot","reverse","templateResults","cards","render","then","html","catch","Notification","exception","template","setTimeout","tinder","firstCard","updateTabIndex","updateEndOfDeck","card","liked","cardActions","slider","cardIndex","cardId","currentRow","set","likedIconContainer","dislikedIconContainer","remove","allRows","querySelectorAll","allSet","forEach","row","tinderSlider","initialized","jTinder","onDislike","onLike","onSwipeDone","updateAriaLive","animationRevertSpeed","animationSpeed","threshold","likeSelector","dislikeSelector","likeButton","dislikeButton","addEventListener","e","preventDefault","target","closest","key","focusCard","actioncard","focus","ariaLive","createAriaLive","cardText","init","async","GE","GameEngineLoader","cmid","load","game","run"],"mappings":";;;;;;;;;uRAgCMA,YAEFC,YAAYC,MAAOC,kBACVD,MAAQA,WACRC,YAAcA,iBACdC,SAAWC,KAAKF,YAAYG,cAAc,wCAC1CC,oBAGTC,OAAON,aACGO,QAAUJ,KAAKF,YAAYG,cAAc,iCAC\/CG,QAAQC,UAAY,SAGdC,UAAYC,SAASC,cAAc,OACzCF,UAAUG,UAAUC,IAAI,qBAGlBC,UAAYJ,SAASC,cAAc,OACzCG,UAAUF,UAAUC,IAAI,YAAa,UACrCC,UAAUC,aAAa,cAAe,QACtCD,UAAUC,aAAa,aAAc,iBACrCD,UAAUC,aAAa,OAAQ,UAC\/BD,UAAUC,aAAa,WAAY,KACnCD,UAAUE,YAAc,cACxBF,UAAUG,QAAQC,OAAS,kBAGrBC,QAAUT,SAASC,cAAc,MACvCJ,QAAQa,YAAYN,WACpBL,UAAUW,YAAYD,SACtBV,UAAUQ,QAAQC,OAAS,cAC3BX,QAAQa,YAAYX,iBAEdY,SAAWrB,MAAMsB,KAAI,CAACC,KAAMC,KAEd,CACZC,KAAMF,KACNG,MAAOF,EACPG,KAJSH,IAAMxB,MAAM4B,OAAS,EAK9BC,MAAa,IAANL,EACPM,OAAQC,EAAEC,IAAIC,QAAU,gDAKhCZ,SAASa,gBAIHC,gBAAkB,CACpBC,MAHe,IAAIf,UAGDa,8BAGZG,OAAO,8BAA+BF,iBAAiBG,MAAMC,OACnEzB,UAAUN,UAAY+B,KACf,MACRC,MAAMC,sBAAaC,iBAEhBC,SAAW,CACbP,MAAOf,6BAEDgB,OAAO,0BAA2BM,UAAUL,MAAMC,OACxDpB,QAAQX,UAAY+B,KACpBK,YAAW,UACFC,eACCC,UAAY3C,KAAKF,YAAYG,cAAc,2BAC5C2C,eAAeD,aACrB,UACEE,kBACE,MACRR,MAAMC,sBAAaC,WAG1BM,gBAAgBC,KAAMC,aACZpC,UAAYX,KAAKF,YAAYG,cAAc,6BAC3C+C,YAAchD,KAAKF,YAAYG,cAAc,+BAC7CgD,OAASjD,KAAKF,YAAYG,cAAc,kCAC1C6C,KAAM,OACAI,UAAYJ,KAAK,GAAGhC,QAAQqC,OAC5BC,WAAazC,UAAUV,qCAA8BiD,oBAC5B,SAA3BE,WAAWtC,QAAQuC,iBAGjBC,mBAAqBF,WAAWnD,cAAc,yBAC9CsD,sBAAwBH,WAAWnD,cAAc,4BACnD8C,MACAO,mBAAmB7C,UAAU+C,OAAO,UAEpCD,sBAAsB9C,UAAU+C,OAAO,UAE3CJ,WAAWtC,QAAQuC,IAAM,aAIvBI,QAAU9C,UAAU+C,iBAAiB,oBACvCC,QAAS,EACbF,QAAQG,SAASC,MAETF,OADoB,SAApBE,IAAI\/C,QAAQuC,OAMhBM,QACAhD,UAAUF,UAAU+C,OAAO,UAC3B7C,UAAUC,aAAa,cAAe,SACtCoC,YAAYvC,UAAUC,IAAI,UAC1BuC,OAAOxC,UAAUC,IAAI,YAErBC,UAAUF,UAAUC,IAAI,UACxBC,UAAUC,aAAa,cAAe,QACtCoC,YAAYvC,UAAU+C,OAAO,UAC7BP,OAAOxC,UAAU+C,OAAO,WAIhCd,eACUoB,aAAe9D,KAAKF,YAAYG,cAAc,kCACX,SAArC6D,aAAahD,QAAQiD,uCAGvBD,cAAcE,QAAQ,CAEpBC,UAAYnB,YACHD,gBAAgBC,MAAM,IAG\/BoB,OAASpB,YACAD,gBAAgBC,MAAM,IAE\/BqB,YAAcrB,YACLsB,eAAetB,KAAK,SACpBF,eAAeE,KAAK,KAE7BuB,qBAAsB,IACtBC,eAAgB,IAChBC,UAAW,EACXC,aAAc,QACdC,gBAAiB,mBAEfC,WAAa1E,KAAKF,YAAYG,cAAc,wBAC5C0E,cAAgB3E,KAAKF,YAAYG,cAAc,2BAEhDyE,WAAW5D,QAAQiD,cACpBW,WAAWE,iBAAiB,SAAUC,wBAChCf,cAAcE,QAAQ,QACxBa,EAAEC,oBAENJ,WAAW5D,QAAQiD,YAAc,QAGhCY,cAAc7D,QAAQiD,cACvBY,cAAcC,iBAAiB,SAAUC,wBACnCf,cAAcE,QAAQ,WACxBa,EAAEC,oBAENH,cAAc7D,QAAQiD,YAAc,aAGnCjE,YAAY8E,iBAAiB,WAAYC,IACrCA,EAAEE,OAAOC,QAAQ,qBAGR,eAAVH,EAAEI,WACGC,WAAY,sBACfpB,cAAcE,QAAQ,QACxBa,EAAEC,kBAEQ,cAAVD,EAAEI,WACGC,WAAY,sBACfpB,cAAcE,QAAQ,WACxBa,EAAEC,sBAIVhB,aAAahD,QAAQiD,YAAc,OAOvCnB,eAAeE,MACM9C,KAAKF,YAAY4D,iBAAiB,mBAC1CE,SAASuB,aACdA,WAAWvE,aAAa,WAAY,SAExCkC,KAAKlC,aAAa,WAAY,KAC1BZ,KAAKkF,YACLpC,KAAKsC,aACAF,WAAY,GAQzBd,eAAetB,MACN9C,KAAKqF,eACDC,qBAELC,SAAW,GACfA,SAAW,8BAAgCzC,KAAK7C,cAAc,cAAcY,iBACvEwE,SAASxE,YAAc0E,SAMhCD,uBACUD,SAAW9E,SAASC,cAAc,OACxC6E,SAASzE,aAAa,YAAa,UACnCyE,SAASzE,aAAa,cAAe,QACrCyE,SAASzE,aAAa,gBAAiB,aACvCyE,SAAS5E,UAAUC,IAAI,gBAClBZ,YAAYmB,YAAYoE,eACxBA,SAAWA,SAMpBnF,yBAESJ,YAAY8E,iBAAiB,SAAUC,IACpCA,EAAEE,OAAOC,QAAQ,gCACZ7E,OAAOH,KAAKH,MAAMA,OACvBgF,EAAEC,0BAGLhF,YAAY8E,iBAAiB,WAAYC,IAC5B,QAAVA,EAAEI,UACGlF,SAASU,UAAUC,IAAI,eAG\/BZ,YAAY8E,iBAAiB,aAAa,UACtC7E,SAASU,UAAU+C,OAAO,wBAY5B,CACXgC,KARSC,MAAAA,aACHC,GAAK,IAAIC,qBAAiB,QAASC,YACnCF,GAAGG,aACHC,KAAO,IAAInG,YAAY+F,GAAG7F,MAAO6F,GAAG5F,aAC1C4F,GAAGK,IAAID,OAKPnG,YAAAA"}