{"version":3,"file":"content.min.js","sources":["https:\/\/moodle.tau.ac.il\/2023\/course\/format\/multitopic\/amd\/src\/courseformat\/content.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 * Course index main component.\n *\n * @module format_multitopic\/courseformat\/content\n * @class format_multitopic\/courseformat\/content\n * @copyright 2022 James Calder and Otago Polytechnic\n * @copyright based on work by 2020 Ferran Recio \n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n *\/\n\nimport BaseComponent from 'core_courseformat\/local\/content';\nimport {getCurrentCourseEditor} from 'core_courseformat\/courseeditor';\nimport inplaceeditable from 'core\/inplace_editable';\nimport Section from 'format_multitopic\/courseformat\/content\/section';\nimport CmItem from 'format_multitopic\/courseformat\/content\/section\/cmitem';\nimport Templates from 'core\/templates';\n\nexport default class Component extends BaseComponent {\n\n \/**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @param {number} sectionReturn the content section return\n * @return {Component}\n *\/\n static init(target, selectors, sectionReturn) {\n return new this({ \/\/ CHANGED.\n element: document.getElementById(target),\n reactive: getCurrentCourseEditor(),\n selectors,\n sectionReturn,\n });\n }\n\n \/**\n * Initial state ready method.\n *\n * @param {Object} state the state data\n *\/\n stateReady(state) {\n super.stateReady(state);\n\n \/\/ Set the initial state of collapsible sections.\n this.fmtCollapseOnHashChange();\n\n \/\/ Capture clicks on course section links.\n window.addEventListener(\"hashchange\", this.fmtCollapseOnHashChange.bind(this));\n\n }\n\n \/**\n * Expand, and scroll to, the section specified in the URL bar.\n *\n * @param {HashChangeEvent?} event The triggering event, if any\n *\/\n \/* eslint-disable no-unused-vars *\/\n fmtCollapseOnHashChange(event) {\n \/* eslint-enable no-unused-vars *\/\n\n \/\/ Find the specified section.\n let anchor = window.location.hash;\n if (!anchor.match(\/^#sectionid-\\d+(?:-title)?$\/)) {\n return;\n }\n let oldStyle = false;\n if (anchor.match(\/^#sectionid-\\d+$\/)) {\n anchor = anchor + \"-title\";\n oldStyle = true;\n history.replaceState(history.state, \"\", anchor);\n }\n const selSectionHeaderDom =\n document.querySelector(\".course-content ul.sections li.section.section-topic .sectionname\" + anchor);\n\n \/\/ Exit if there is no recognised section.\n if (!selSectionHeaderDom) {\n return;\n }\n\n const selSectionDom = selSectionHeaderDom.closest(\"li.section.section-topic\");\n const sectionId = selSectionDom.getAttribute('data-id');\n const section = this.reactive.get('section', sectionId);\n\n \/\/ Expand, if appropriate.\n if (selSectionDom.matches(\".section-topic-collapsible\")\n && (selSectionDom.querySelector(\".course-section-header .icons-collapse-expand.collapsed\")\n || section.contentcollapsed)) {\n this.reactive.dispatch(\n 'sectionContentCollapsed',\n [sectionId],\n false\n );\n }\n\n \/\/ Scroll to the specified section.\n if (oldStyle) {\n selSectionDom.scrollIntoView();\n }\n\n }\n\n \/**\n * Handle the collapse\/expand all sections button.\n *\n * Toggler click is delegated to the main course content element because new sections can\n * appear at any moment and this way we prevent accidental double bindings.\n *\n * @param {Event} event the triggered event\n *\/\n _allSectionToggler(event) {\n event.preventDefault();\n\n const target = event.target.closest(this.selectors.TOGGLEALL);\n const isAllCollapsed = target.classList.contains(this.classes.COLLAPSED);\n\n \/\/ CHANGED.\n let sectionlist = [];\n const sectionlistDom = this.element.querySelectorAll(\".course-section.section-topic-collapsible[data-fmtonpage='1']\");\n for (let sectionCount = 0; sectionCount < sectionlistDom.length; sectionCount++) {\n sectionlist.push(sectionlistDom[sectionCount].dataset.id);\n }\n \/\/ END CHANGED.\n\n this.reactive.dispatch(\n 'sectionContentCollapsed',\n sectionlist, \/\/ CHANGED.\n !isAllCollapsed\n );\n }\n\n \/**\n * Refresh the collapse\/expand all sections element.\n *\n * @param {Object} state The state data\n *\/\n _refreshAllSectionsToggler(state) {\n const target = this.getElement(this.selectors.TOGGLEALL);\n if (!target) {\n return;\n }\n \/\/ Check if we have all sections collapsed\/expanded.\n let allcollapsed = true;\n let allexpanded = true;\n \/\/ ADDED.\n let sectionCollapsible = {};\n const sectionlistDom = this.element.querySelectorAll(\".course-section.section-topic-collapsible[data-fmtonpage='1']\");\n for (let sectionCount = 0; sectionCount < sectionlistDom.length; sectionCount++) {\n sectionCollapsible[sectionlistDom[sectionCount].dataset.id] = true;\n }\n \/\/ END ADDED.\n state.section.forEach(\n section => {\n if (sectionCollapsible[section.id]) { \/\/ ADDED.\n allcollapsed = allcollapsed && section.contentcollapsed;\n allexpanded = allexpanded && !section.contentcollapsed;\n }\n }\n );\n target.style.display = (allexpanded && allcollapsed) ? \"none\" : \"block\"; \/\/ ADDED.\n if (allcollapsed) {\n target.classList.add(this.classes.COLLAPSED);\n target.setAttribute('aria-expanded', false);\n }\n if (allexpanded) {\n target.classList.remove(this.classes.COLLAPSED);\n target.setAttribute('aria-expanded', true);\n }\n }\n\n \/**\n * Update a course section when the section number changes.\n *\n * The courseActions module used for most course section tools still depends on css classes and\n * section numbers (not id). To prevent inconsistencies when a section is moved, we need to refresh\n * the\n *\n * Course formats can override the section title rendering so the frontend depends heavily on backend\n * rendering. Luckily in edit mode we can trigger a title update using the inplace_editable module.\n *\n * @param {Object} param\n * @param {Object} param.element details the update details.\n *\/\n _refreshSectionNumber({element}) {\n \/\/ Find the element.\n const target = this.getElement(this.selectors.SECTION, element.id);\n if (!target) {\n \/\/ Job done. Nothing to refresh.\n return;\n }\n \/\/ Update section numbers in all data, css and YUI attributes.\n target.id = `section-${element.number}`;\n \/\/ YUI uses section number as section id in data-sectionid, in principle if a format use components\n \/\/ don't need this sectionid attribute anymore, but we keep the compatibility in case some plugin\n \/\/ use it for legacy purposes.\n target.dataset.sectionid = element.number;\n \/\/ The data-number is the attribute used by components to store the section number.\n target.dataset.number = element.number;\n\n \/\/ Update title and title inplace editable, if any.\n const inplace = inplaceeditable.getInplaceEditable(target.querySelector(this.selectors.SECTION_ITEM));\n if (inplace) {\n \/\/ The course content HTML can be modified at any moment, so the function need to do some checkings\n \/\/ to make sure the inplace editable still represents the same itemid.\n const currentvalue = inplace.getValue();\n const currentitemid = inplace.getItemId();\n \/\/ Unnamed sections must be recalculated.\n if (inplace.getValue() === '' || element.timed) { \/\/ CHANGED.\n \/\/ The value to send can be an empty value if it is a default name.\n if (currentitemid == element.id\n && (currentvalue != element.rawtitle || element.rawtitle == '' || element.timed)) { \/\/ CHANGED.\n inplace.setValue(element.rawtitle);\n }\n }\n }\n }\n\n \/**\n * Refresh the section list.\n *\n * @param {Object} param\n * @param {Object} param.element details the update details.\n *\/\n _refreshCourseSectionlist({element}) {\n super._refreshCourseSectionlist({element});\n const sectionsDom = this.element.querySelectorAll(this.selectors.SECTION);\n for (let sdi = 0; sdi < sectionsDom.length; sdi++) {\n const sectionDom = sectionsDom[sdi];\n const section = this.reactive.get(\"section\", sectionDom.dataset.id);\n if (!section) {\n continue;\n }\n let refreshCms = false;\n const pageSectionDom = this.element.querySelector(\".course-section[data-id='\" + section.pageid + \"']\");\n const pageSectionDisplay = pageSectionDom.dataset.fmtonpage;\n if (sectionDom.dataset.fmtonpage != pageSectionDisplay) {\n sectionDom.dataset.fmtonpage = pageSectionDisplay;\n sectionDom.style.display = (pageSectionDisplay == \"1\") ? \"block\" : \"none\";\n if (pageSectionDisplay == \"1\") {\n refreshCms = true;\n }\n }\n if (section.visible == sectionDom.classList.contains(\"hidden\")) {\n const badgeDom = sectionDom.querySelector(\"span.badge[data-type='hiddenfromstudents']\");\n if (section.visible) {\n sectionDom.classList.remove(\"hidden\");\n badgeDom.classList.add(\"d-none\");\n } else {\n sectionDom.classList.add(\"hidden\");\n badgeDom.classList.remove(\"d-none\");\n }\n if (sectionDom.dataset.fmtonpage == \"1\") {\n refreshCms = true;\n }\n }\n if (refreshCms) {\n \/\/ Note: Visibility state doesn't get updated for CMs already rendered.\n this._refreshSectionCmlist({element: section});\n }\n const menuDom = sectionDom.querySelector(\".course-section-header .section_action_menu\");\n Templates.render(\"core_courseformat\/local\/content\/section\/controlmenu\", section.controlmenu).done(function(html) {\n Templates.replaceNode(menuDom, html, \"\");\n });\n }\n this._refreshAllSectionsToggler(this.reactive.stateManager.state);\n }\n\n \/**\n * Regenerate content indexes.\n *\n * This method is used when a legacy action refresh some content element.\n *\/\n _indexContents() {\n \/\/ Find unindexed sections.\n this._scanIndex(\n this.selectors.SECTION,\n this.sections,\n (item) => {\n return new Section(item); \/\/ CHANGED.\n }\n );\n\n \/\/ Find unindexed cms.\n this._scanIndex(\n this.selectors.CM,\n this.cms,\n (item) => {\n return new CmItem(item); \/\/ CHANGED.\n }\n );\n }\n\n}"],"names":["Component","BaseComponent","target","selectors","sectionReturn","this","element","document","getElementById","reactive","stateReady","state","fmtCollapseOnHashChange","window","addEventListener","bind","event","anchor","location","hash","match","oldStyle","history","replaceState","selSectionHeaderDom","querySelector","selSectionDom","closest","sectionId","getAttribute","section","get","matches","contentcollapsed","dispatch","scrollIntoView","_allSectionToggler","preventDefault","isAllCollapsed","TOGGLEALL","classList","contains","classes","COLLAPSED","sectionlist","sectionlistDom","querySelectorAll","sectionCount","length","push","dataset","id","_refreshAllSectionsToggler","getElement","allcollapsed","allexpanded","sectionCollapsible","forEach","style","display","add","setAttribute","remove","_refreshSectionNumber","SECTION","number","sectionid","inplace","inplaceeditable","getInplaceEditable","SECTION_ITEM","currentvalue","getValue","currentitemid","getItemId","timed","rawtitle","setValue","_refreshCourseSectionlist","sectionsDom","sdi","sectionDom","refreshCms","pageSectionDisplay","pageid","fmtonpage","visible","badgeDom","_refreshSectionCmlist","menuDom","render","controlmenu","done","html","replaceNode","stateManager","_indexContents","_scanIndex","sections","item","Section","CM","cms","CmItem"],"mappings":";;;;;;;;;iUAgCqBA,kBAAkBC,6BAUvBC,OAAQC,UAAWC,sBACpB,IAAIC,KAAK,CACZC,QAASC,SAASC,eAAeN,QACjCO,UAAU,0CACVN,UAAAA,UACAC,cAAAA,gBASRM,WAAWC,aACDD,WAAWC,YAGZC,0BAGLC,OAAOC,iBAAiB,aAAcT,KAAKO,wBAAwBG,KAAKV,OAU5EO,wBAAwBI,WAIhBC,OAASJ,OAAOK,SAASC,SACxBF,OAAOG,MAAM,0CAGdC,UAAW,EACXJ,OAAOG,MAAM,sBACbH,QAAkB,SAClBI,UAAW,EACXC,QAAQC,aAAaD,QAAQX,MAAO,GAAIM,eAEtCO,oBACFjB,SAASkB,cAAc,oEAAsER,YAG5FO,iCAICE,cAAgBF,oBAAoBG,QAAQ,4BAC5CC,UAAYF,cAAcG,aAAa,WACvCC,QAAUzB,KAAKI,SAASsB,IAAI,UAAWH,WAGzCF,cAAcM,QAAQ,gCACdN,cAAcD,cAAc,4DACzBK,QAAQG,wBACdxB,SAASyB,SACV,0BACA,CAACN,YACD,GAKJP,UACAK,cAAcS,iBAatBC,mBAAmBpB,OACfA,MAAMqB,uBAGAC,eADStB,MAAMd,OAAOyB,QAAQtB,KAAKF,UAAUoC,WACrBC,UAAUC,SAASpC,KAAKqC,QAAQC,eAG1DC,YAAc,SACZC,eAAiBxC,KAAKC,QAAQwC,iBAAiB,qEAChD,IAAIC,aAAe,EAAGA,aAAeF,eAAeG,OAAQD,eAC7DH,YAAYK,KAAKJ,eAAeE,cAAcG,QAAQC,SAIrD1C,SAASyB,SACV,0BACAU,aACCN,gBASTc,2BAA2BzC,aACjBT,OAASG,KAAKgD,WAAWhD,KAAKF,UAAUoC,eACzCrC,kBAIDoD,cAAe,EACfC,aAAc,EAEdC,mBAAqB,SACnBX,eAAiBxC,KAAKC,QAAQwC,iBAAiB,qEAChD,IAAIC,aAAe,EAAGA,aAAeF,eAAeG,OAAQD,eAC7DS,mBAAmBX,eAAeE,cAAcG,QAAQC,KAAM,EAGlExC,MAAMmB,QAAQ2B,SACV3B,UACQ0B,mBAAmB1B,QAAQqB,MAC3BG,aAAeA,cAAgBxB,QAAQG,iBACvCsB,YAAcA,cAAgBzB,QAAQG,qBAIlD\/B,OAAOwD,MAAMC,QAAWJ,aAAeD,aAAgB,OAAS,QAC5DA,eACApD,OAAOsC,UAAUoB,IAAIvD,KAAKqC,QAAQC,WAClCzC,OAAO2D,aAAa,iBAAiB,IAErCN,cACArD,OAAOsC,UAAUsB,OAAOzD,KAAKqC,QAAQC,WACrCzC,OAAO2D,aAAa,iBAAiB,IAiB7CE,gCAAsBzD,QAACA,oBAEbJ,OAASG,KAAKgD,WAAWhD,KAAKF,UAAU6D,QAAS1D,QAAQ6C,QAC1DjD,cAKLA,OAAOiD,qBAAgB7C,QAAQ2D,QAI\/B\/D,OAAOgD,QAAQgB,UAAY5D,QAAQ2D,OAEnC\/D,OAAOgD,QAAQe,OAAS3D,QAAQ2D,aAG1BE,QAAUC,0BAAgBC,mBAAmBnE,OAAOuB,cAAcpB,KAAKF,UAAUmE,kBACnFH,QAAS,OAGHI,aAAeJ,QAAQK,WACvBC,cAAgBN,QAAQO,aAEH,KAAvBP,QAAQK,YAAqBlE,QAAQqE,SAEjCF,eAAiBnE,QAAQ6C,IACrBoB,cAAgBjE,QAAQsE,UAAgC,IAApBtE,QAAQsE,WAAkBtE,QAAQqE,OAC1ER,QAAQU,SAASvE,QAAQsE,YAYzCE,qCAA0BxE,QAACA,qBACjBwE,0BAA0B,CAACxE,QAAAA,gBAC3ByE,YAAc1E,KAAKC,QAAQwC,iBAAiBzC,KAAKF,UAAU6D,aAC5D,IAAIgB,IAAM,EAAGA,IAAMD,YAAY\/B,OAAQgC,MAAO,OACzCC,WAAaF,YAAYC,KACzBlD,QAAUzB,KAAKI,SAASsB,IAAI,UAAWkD,WAAW\/B,QAAQC,QAC3DrB,qBAGDoD,YAAa,QAEXC,mBADiB9E,KAAKC,QAAQmB,cAAc,4BAA8BK,QAAQsD,OAAS,MACvDlC,QAAQmC,aAC9CJ,WAAW\/B,QAAQmC,WAAaF,qBAChCF,WAAW\/B,QAAQmC,UAAYF,mBAC\/BF,WAAWvB,MAAMC,QAAiC,KAAtBwB,mBAA6B,QAAU,OACzC,KAAtBA,qBACAD,YAAa,IAGjBpD,QAAQwD,SAAWL,WAAWzC,UAAUC,SAAS,UAAW,OACtD8C,SAAWN,WAAWxD,cAAc,8CACtCK,QAAQwD,SACRL,WAAWzC,UAAUsB,OAAO,UAC5ByB,SAAS\/C,UAAUoB,IAAI,YAEvBqB,WAAWzC,UAAUoB,IAAI,UACzB2B,SAAS\/C,UAAUsB,OAAO,WAEM,KAAhCmB,WAAW\/B,QAAQmC,YACnBH,YAAa,GAGjBA,iBAEKM,sBAAsB,CAAClF,QAASwB,gBAEnC2D,QAAUR,WAAWxD,cAAc,kEAC\/BiE,OAAO,sDAAuD5D,QAAQ6D,aAAaC,MAAK,SAASC,yBAC7FC,YAAYL,QAASI,KAAM,YAGxCzC,2BAA2B\/C,KAAKI,SAASsF,aAAapF,OAQ\/DqF,sBAESC,WACD5F,KAAKF,UAAU6D,QACf3D,KAAK6F,UACJC,MACU,IAAIC,iBAAQD,aAKtBF,WACD5F,KAAKF,UAAUkG,GACfhG,KAAKiG,KACJH,MACU,IAAII,gBAAOJ"}