{"version":3,"file":"course_mod_modal.min.js","sources":["https:\/\/kundenportal.comm-unity.at\/course\/format\/tiles\/amd\/src\/course_mod_modal.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\/* eslint space-before-function-paren: 0 *\/\n\n\/**\n * Javascript Module to handle rendering of course modules (e.g. resource\/PDF, resource\/html, page) in modal windows\n *\n * When the user clicks a PDF course module subtile or old style resource\n * if we are using modals for it (e.g. PDF) , create, populate, launch and size the modal\n *\n * @module format_tiles\/course_mod_modal\n * @copyright 2018 David Watson {@link http:\/\/evolutioncode.uk}\n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n * @since Moodle 3.3\n *\/\n\ndefine([\"jquery\", \"core\/modal_factory\", \"core\/config\", \"core\/templates\", \"core\/notification\", \"core\/ajax\",\n 'core\/fragment', \"core\/modal_events\"],\n function ($, modalFactory, config, Templates, Notification, ajax, Fragment, ModalEvents) {\n \"use strict\";\n\n \/**\n * Keep references for all modals we have already added to the page,\n * so that we can relaunch then if needed\n * @type {{}}\n *\/\n var modalStore = {};\n var loadingIconHtml;\n const win = $(window);\n var courseId;\n var tilesConfig;\n\n const Selector = {\n modal: \".modal\",\n modalDialog: \".modal-dialog\",\n modalBody: \".modal-body\",\n sectionMain: \".section.main\",\n pageContent: \"#page-content\",\n regionMain: \"#region-main\",\n completionState: \"#completion-check-\",\n cmModal: \".embed_cm_modal\",\n moodleMediaPlayer: \".mediaplugin_videojs\",\n closeBtn: \"button.close\",\n ACTIVITY: \"li.activity\",\n URLACTIVITYPOPUPLINK: \".activity.modtype_url.urlpopup a\",\n modalHeader: \".modal-header\",\n embedModuleButtons: \".embed-module-buttons\",\n iframe: \"iframe\"\n };\n\n const CLASS = {\n COMPLETION_ENABLED: \"completion-enabled\",\n COMPLETION_MANUAL: \"completion-manual\",\n COMPLETION_AUTO: \"completion-auto\", \/\/ E.g. grade based.\n COMPLETION_VIEW: \"completion-view\",\n COMPLETION_CHECK_BOX: \"completioncheckbox\",\n COMPLETION_DROPDOWN: \"completion-dropdown\"\n };\n\n const modalMinWidth = function () {\n return Math.min(win.width(), 1100);\n };\n\n \/**\n * Some modals contain videos in iframes or objects, which need to stop playing when dismissed.\n * @param {object} modal the modal which contains the video.\n *\/\n const stopAllVideosOnDismiss = function(modal) {\n modal.on(ModalEvents.hidden, function() {\n const iframes = modal.find(Selector.iframe);\n const objects = modal.find(\"object\");\n const moodleMediaPlayer = modal.find(Selector.moodleMediaPlayer);\n\n if (iframes.length || objects.length || moodleMediaPlayer.length) {\n modalStore[modal.data(\"cmid\")] = undefined;\n modal.remove();\n }\n });\n };\n \/**\n *\n * @param {number} cmId\n * @param {number} moduleContextId\n * @param {number} sectionNum\n * @param {string} title\n * @param {string} objectType\n * @param {boolean} completionEnabled\n * @param {number} existingCompletionState\n * @param {boolean} isManualCompletion\n * @param {string} descriptionHTML\n * @returns {boolean}\n *\/\n const launchCmModal = function (\n cmId, moduleContextId, sectionNum, title, objectType,\n completionEnabled, existingCompletionState, isManualCompletion, descriptionHTML\n ) {\n modalFactory.create({\n type: modalFactory.types.DEFAULT,\n title: title,\n body: loadingIconHtml\n }).done(function (modal) {\n modalStore[cmId] = modal;\n modal.setLarge();\n modal.show();\n const modalRoot = $(modal.root);\n modalRoot.attr(\"id\", \"embed_mod_modal_\" + cmId);\n modalRoot.data(\"cmid\", cmId);\n modalRoot.data(\"section\", sectionNum);\n modalRoot.addClass(\"embed_cm_modal\");\n\n \/\/ If it's a page activity, we simply add the page HTML as the modal body.\n \/\/ Otherwise, we set the body by rendering from a template.\n if (objectType === 'page') {\n modalRoot.addClass('mod_' + objectType);\n stopAllVideosOnDismiss(modalRoot);\n Fragment.loadFragment(\n 'format_tiles', `get_cm_content`, moduleContextId, {contextid: moduleContextId}\n )\n .done(function(html, js) {\n modal.setBody(html);\n Templates.runTemplateJS(js);\n });\n } else {\n \/\/ Render the modal body and set it to the page.\n \/\/ First a blank template data object.\n var templateData = {\n id: cmId,\n objectType: null,\n width: \"100%\",\n height: Math.round(win.height() - 60), \/\/ Embedded object height in modal - make as high as poss.\n cmid: cmId,\n tileid: sectionNum,\n isediting: 0,\n sesskey: config.sesskey,\n activityname: title,\n config: {wwwroot: config.wwwroot},\n completionstring: '',\n description: descriptionHTML\n };\n\n var template = null;\n if (objectType === \"html\") {\n templateData.objectType = \"text\/html\";\n template = 'format_tiles\/embed_file_modal_body';\n } else if (objectType === \"pdf\") {\n templateData.objectType = 'application\/pdf';\n template = 'format_tiles\/embed_file_modal_body';\n } else if (objectType === \"url\") {\n templateData.objectType = 'url';\n template = 'format_tiles\/embed_url_modal_body';\n }\n\n const redirectModule =\n ['pdf', 'html'].includes(objectType) ? 'resource' : objectType;\n if (template !== null) {\n Templates.render(template, templateData).done(function (html) {\n modal.setBody(html);\n modalRoot.find(Selector.modalBody).animate({\"min-height\": Math.round(win.height() - 120)}, \"fast\");\n\n if (objectType === \"html\" || objectType === 'url') {\n \/\/ HTML files only - set widths to 100% since they may contain embedded videos etc.\n modalRoot.find(Selector.modal).animate({\"max-width\": \"100%\"}, \"fast\");\n modalRoot.find(Selector.modalDialog).animate({\"max-width\": \"100%\"}, \"fast\");\n modalRoot.find(Selector.modalBody).animate({\"max-width\": \"100%\"}, \"fast\");\n stopAllVideosOnDismiss(modalRoot);\n if (objectType === 'url') {\n modalRoot.find(Selector.modalBody).addClass(\"text-center\");\n }\n } else if (objectType === \"pdf\") {\n \/\/ Otherwise (e.g. for PDF) we don't need 100% width.\n modalRoot.find(Selector.modal).animate({\"max-width\": modalMinWidth()}, \"fast\");\n \/\/ We do modal-dialog too since Moove theme uses it.\n modalRoot.find(Selector.modalDialog).animate({\"max-width\": modalMinWidth()}, \"fast\");\n }\n\n }).fail(() => {\n window.location.href = `${config.wwwroot}\/mod\/${redirectModule}\/view.php?id=${cmId}`;\n });\n } else {\n window.location.href = `${config.wwwroot}\/mod\/${redirectModule}\/view.php?id=${cmId}`;\n }\n }\n\n \/\/ Render the modal header \/ title and set it to the page.\n var headerTemplateData = {\n cmid: cmId,\n activityname: title,\n tileid: sectionNum,\n showDownload: objectType === \"pdf\" ? 1 : 0,\n showNewWindow: [\"pdf\", 'url'].includes(objectType) ? 1 : 0,\n forModal: true,\n config: {wwwroot: config.wwwroot}\n };\n if (completionEnabled) {\n headerTemplateData.istrackeduser = 1;\n headerTemplateData.hascompletion = 1;\n const oldState = existingCompletionState === 1;\n\n \/\/ Core completion button template has 'overallcomplete' arg relating to this cm.\n \/\/ See course\/templates\/completion_manual.mustache.\n headerTemplateData.overallcomplete = oldState ? 1 : 0;\n headerTemplateData.overallincomplete = oldState ? 0 : 1;\n headerTemplateData.completionIsManual = isManualCompletion;\n if (!headerTemplateData.completionIsManual) {\n \/\/ Auto completion has different vars for core template core_course\/completion_automatic.\n headerTemplateData.statuscomplete = headerTemplateData.overallcomplete;\n headerTemplateData.statusincomplete = headerTemplateData.overallincomplete;\n }\n \/\/ Trigger event to check if other items in course have updated availability.\n if (oldState !== headerTemplateData.completionstate) {\n require([\"format_tiles\/completion\"], function (completion) {\n completion.triggerCompletionChangedEvent(parseInt(sectionNum), parseInt(cmId));\n });\n }\n }\n\n Templates.render(\"format_tiles\/embed_module_modal_header_btns\", headerTemplateData).done(function (html) {\n modalRoot.find(Selector.embedModuleButtons).remove();\n modalRoot.find($('button.close')).remove();\n modalRoot.find(Selector.modalHeader).append(html);\n modalRoot.find(Selector.closeBtn).detach().appendTo(modalRoot.find(Selector.embedModuleButtons));\n const toggleCompletionSelector = '[data-action=\"toggle-manual-completion\"]';\n modalRoot.find(toggleCompletionSelector).on('click', () => {\n require([\"format_tiles\/completion\"], function (completion) {\n \/\/ In this case, core will handle the request to set the new completion value in the DB.\n \/\/ We wait a moment to allow that to get a head start.\n \/\/ Then we trigger an event which course.js will see and update section content to show new statuses.\n \/\/ Use will not notice this as they are looking at the modal, but it's ready when they dismiss modal.\n setTimeout(() => {\n completion.triggerCompletionChangedEvent(\n parseInt(modalRoot.data('section')), parseInt(modalRoot.data(\"cmid\"))\n );\n }, 300);\n });\n });\n }).fail(Notification.exception);\n\n \/\/ Allow a short delay before we resize the modal, and check a few times, as content may be loading.\n setTimeout(() => {\n modalHeightChangeWatcher(modalRoot, 3, 1000);\n }, 500);\n\n return true;\n });\n return false;\n };\n\n \/**\n * Resize the modal to account for its content.\n * @param {object} modalRoot\n *\/\n var resizeModal = function(modalRoot) {\n modalRoot.find(Selector.modal).animate({\"max-width\": modalMinWidth()}, \"fast\");\n\n var MODAL_MARGIN = 70;\n\n \/\/ If the modal contains a Moodle mediaplayer div, remove the max width css rule which Moodle applies.\n \/\/ Otherwise video will be 400px max wide.\n var mediaPlayer = $(Selector.moodleMediaPlayer);\n mediaPlayer.find(\"div\").each(function(index, child) {\n $(child).css(\"max-width\", \"\");\n });\n if (mediaPlayer.length > 0) {\n stopAllVideosOnDismiss(modalRoot);\n }\n\n \/\/ If the activity contains an iframe (e.g. is a page with a YouTube video in it, or H5P), ensure modal is big enough.\n \/\/ Do this for every iframe in the course module.\n modalRoot.find(Selector.iframe).each(function (index, iframe) {\n\n const iframeSelector = $(iframe);\n\n \/\/ Get the modal.\n var modal;\n \/\/ Boost calls the modal \"modal dialog\" so try this first.\n modal = modalRoot.find(Selector.modalDialog);\n\n \/\/ If no luck, try what Clean and Adaptable do instead.\n if (modal.length === 0) {\n modal = modalRoot.find(Selector.modal);\n }\n\n \/\/ Now check and adjust the width of the modal.\n var iframeWidth = Math.min(iframeSelector.width(), win.width());\n if (iframeWidth > modal.width() - MODAL_MARGIN) {\n modal.animate(\n {\"max-width\": Math.max(iframeWidth + MODAL_MARGIN, modalMinWidth())},\n \"fast\"\n );\n modalRoot.find(Selector.modal).animate(\n {\"max-width\": Math.max(iframeWidth + MODAL_MARGIN, modalMinWidth())},\n \"fast\"\n );\n }\n\n \/\/ Then the height of the modal body.\n var modalBody = modalRoot.find(Selector.modalBody);\n if (iframeSelector.height() > modalBody.height() - MODAL_MARGIN) {\n iframeSelector.attr('height', modalBody.height() - MODAL_MARGIN);\n }\n stopAllVideosOnDismiss(modalRoot);\n });\n };\n\n \/**\n * Check the modal height to see if the iframe in it is bigger. If it is, adjust modal height up.\n * Do this a few times so that, if iframe content is loading, we can check after it's loaded.\n * @param {object} modalRoot\n * @param {number} howManyChecks\n * @param {number}duration\n * @param {number} oldHeight\n *\/\n const modalHeightChangeWatcher = function (modalRoot, howManyChecks, duration, oldHeight = 0) {\n const iframe = modalRoot.find(Selector.modalBody);\n if (iframe) {\n const newHeight = Math.round(iframe.height());\n if (newHeight && newHeight > oldHeight + 10) {\n resizeModal(modalRoot);\n }\n if (howManyChecks > 0) {\n setTimeout(() => {\n modalHeightChangeWatcher(modalRoot, howManyChecks - 1, duration, newHeight);\n }, duration);\n }\n }\n };\n\n \/**\n * Do we need a modal for this cm?\n * @param {number} cmId course module ID\n * @param {string} url\n * @return boolean\n *\/\n const modalRequired = function(cmId, url) {\n if (tilesConfig.modalallowedmodnames === undefined) {\n return false;\n }\n if (tilesConfig.modalallowedcmids === undefined) {\n return false;\n }\n if (!(tilesConfig.modalallowedcmids).includes(cmId)) {\n return false;\n }\n\n return ((tilesConfig.modalallowedmodnames).includes('page') && url.startsWith(`${config.wwwroot}\/mod\/page\/view.php`))\n || ((tilesConfig.modalallowedmodnames).includes('url') && url.startsWith(`${config.wwwroot}\/mod\/url\/view.php`))\n || ((tilesConfig.modalallowedmodnames).includes('pdf') && url.startsWith(`${config.wwwroot}\/mod\/resource\/view.php`))\n || ((tilesConfig.modalallowedmodnames).includes('html')\n && url.startsWith(`${config.wwwroot}\/mod\/resource\/view.php`));\n };\n\n return {\n init: function (courseIdInit, isEditing, pageType, launchModalCmid, usingJsNav) {\n courseId = parseInt(courseIdInit);\n $(document).ready(function () {\n tilesConfig = $('#format-tiles-js-config').data();\n const courseIndex = $('nav#courseindex');\n\n if (['course-view-tiles', 'section-view-tiles'].includes(pageType)) {\n \/\/ We are on a main tiles page, \/course\/view.php or \/course\/section.php in Moodle 4.4+.\n \/\/ If any link in the course index on the left is clicked, check if it needs a modal.\n \/\/ If it does, launch the modal instead of following the link.\n \/\/ This isn't ideal but saves plugin re-implementing \/ maintaining large volume of course index code.\n \/\/ TODO use reactive UI - courseformat\/activity:openAnchor in course\/format\/amd\/src\/local\/courseindex.\n if (!isEditing && courseIndex.length > 0) {\n courseIndex.on('click', function(e) {\n const target = $(e.target);\n const link = target.hasClass('courseindex-link') ? target : target.find('a.courseindex-link');\n if (link && link.data('for') === 'cm_name') {\n e.preventDefault();\n const linkUrl = link.attr('href');\n if (linkUrl) {\n const cmId = link.closest('li.courseindex-item').data('id');\n ajax.call([{\n methodname: \"format_tiles_get_course_mod_info\", args: {cmid: cmId}\n }])[0].done(function (data) {\n const expandedSection = $(`li#section-${data.sectionnumber}.state-visible`);\n if (modalRequired(cmId, linkUrl)) {\n if (!data || !data.modalallowed) {\n window.location.href = linkUrl;\n return;\n }\n if (usingJsNav) {\n if (expandedSection.length === 0) {\n require([\"format_tiles\/course\"], function (course) {\n course.populateAndExpandSection(\n data.coursecontextid, data.sectionid, data.sectionnumber\n );\n });\n }\n launchCmModal(\n cmId,\n data.modulecontextid,\n data.sectionnumber,\n data.name,\n data.modaltype,\n data.completionenabled ? 1 : 0,\n data.iscomplete ? 1 : 0,\n data.ismanualcompletion,\n data.description,\n );\n } else {\n window.location.href = config.wwwroot\n + `\/course\/view.php?id=${courseId}`\n + `§ion=${data.sectionnumber}&cmid=${cmId}`;\n }\n } else {\n \/\/ Link URL may be anchor e.g. #module-138 if the item is a label.\n const isAnchorLink = link.data('anchor') || linkUrl.startsWith('#');\n if (!isAnchorLink) {\n window.location.href = linkUrl;\n } else {\n if (usingJsNav) {\n if (expandedSection.length === 0) {\n require([\"format_tiles\/course\"], function (course) {\n course.populateAndExpandSection(\n data.coursecontextid, data.sectionid, data.sectionnumber\n );\n });\n }\n } else {\n window.location.href = config.wwwroot\n + `\/course\/view.php?id=${courseId}`\n + `§ion=${data.sectionnumber}`;\n }\n }\n }\n })\n .fail(function() {\n window.location.href = linkUrl;\n });\n }\n }\n });\n }\n\n \/\/ If we are passing ?cmid=xxx in the URL this suggests we are trying to launch course mod modal.\n \/\/ This would be from clicking a course index link while in another activity.\n \/\/ E.g. from \/mod\/xxx\/view.php for another course module.\n \/\/ This isn't ideal but saves this plugin re-implementing \/ maintaining large volume of course index code.\n if (launchModalCmid) {\n ajax.call([{\n methodname: \"format_tiles_get_course_mod_info\", args: {cmid: launchModalCmid}\n }])[0].done(function (data) {\n if (data && data.modalallowed && data.courseid === courseId) {\n const expandedSection = $(`li#section-${data.sectionnumber}.state-visible`);\n if (expandedSection.length === 0) {\n if (usingJsNav) {\n require([\"format_tiles\/course\"], function (course) {\n course.populateAndExpandSection(\n data.coursecontextid, data.sectionid, data.sectionnumber\n );\n });\n }\n }\n\n launchCmModal(\n launchModalCmid,\n data.modulecontextid,\n data.sectionnumber,\n data.name,\n data.modaltype,\n data.completionenabled ? 1 : 0,\n data.iscomplete ? 1 : 0,\n data.ismanualcompletion,\n data.description,\n );\n }\n });\n }\n\n var pageContent = $(Selector.pageContent);\n if (pageContent.length === 0) {\n \/\/ Some themes e.g. RemUI do not have a #page-content div, so use #region-main.\n pageContent = $(Selector.regionMain);\n }\n\n pageContent.on(\"keydown\", `[data-action=\"launch-tiles-cm-modal\"]`, function (e) {\n const ENTER_KEY = 13;\n if (e.keyCode === ENTER_KEY) {\n \/\/ User has tabbed to a modal capable activity and pressed enter.\n \/\/ To improve accessibility, do not launch a modal but show them standard activity screen.\n e.preventDefault();\n const url = $(e.target).attr('href');\n if (url) {\n window.location.href = url;\n }\n }\n });\n\n pageContent.on(\"click\", `[data-action=\"launch-tiles-cm-modal\"]`, function (e) {\n \/\/ If click is on a completion checkbox within activity, ignore here as handled elsewhere.\n const tgt = $(e.target);\n const isExcludedControl = tgt.hasClass(CLASS.COMPLETION_CHECK_BOX)\n || tgt.parent().hasClass(CLASS.COMPLETION_CHECK_BOX)\n || tgt.hasClass(CLASS.COMPLETION_DROPDOWN)\n || tgt.parent().hasClass(CLASS.COMPLETION_DROPDOWN)\n || tgt.is(\":button\")\n || tgt.hasClass('expanded-content') \/\/ \"Show less\" link on restrictions.\n || tgt.hasClass('collapsed-content'); \/\/ \"Show more\" link on restrictions\n if (isExcludedControl) {\n return;\n }\n e.preventDefault();\n const currTgt = $(e.currentTarget);\n var clickedCmObject = currTgt.closest(\"li.activity\");\n const cmId = clickedCmObject.data('cmid');\n const moduleContextId = clickedCmObject.data('contextid');\n const sectionNum = clickedCmObject.closest(Selector.sectionMain).data('section');\n\n \/\/ If we already have this modal on the page, launch it.\n var existingModal = modalStore[cmId];\n if (typeof existingModal === \"object\") {\n existingModal.show();\n } else {\n\n \/\/ We don't already have it, so make it.\n launchCmModal(\n cmId,\n moduleContextId,\n sectionNum,\n clickedCmObject.data('title'),\n clickedCmObject.data('modal'),\n clickedCmObject.hasClass(CLASS.COMPLETION_ENABLED),\n clickedCmObject.data('completion-state')\n ? parseInt(clickedCmObject.data('completion-state')) : null,\n clickedCmObject.hasClass(CLASS.COMPLETION_MANUAL),\n clickedCmObject.find('.modal-description').html(),\n );\n }\n });\n\n \/\/ Render the loading icon and append it to body so that we can use it later.\n Templates.render(\"format_tiles\/loading\", {})\n .catch(Notification.exception)\n .done(function (html) {\n loadingIconHtml = html; \/\/ TODO get this from elsewhere.\n }).fail(Notification.exception);\n\n \/\/ If completion of a cm changes, remove it from store so that it can be re-rendered with correct heading.\n $(document).on('format-tiles-completion-changed', function(e, data) {\n if (data.cmid && modalStore[data.cmid]) {\n modalStore[data.cmid] = undefined;\n }\n });\n } else if (pageType.match('^mod-[a-z]+-view$')) {\n courseIndex.on('click', function (e) {\n const target = $(e.target);\n const link = target.hasClass('courseindex-link') ? target : target.find('a.courseindex-link');\n if (link && link.data('for') === 'cm_name') {\n e.preventDefault();\n const linkUrl = link.attr('href');\n if (linkUrl) {\n const link = $(e.target);\n const cmId = link.closest('li.courseindex-item').data('id');\n if (modalRequired(cmId, linkUrl)) {\n if (usingJsNav) {\n window.location.href = `${config.wwwroot}\/course\/view.php?id=${courseId}&cmid=${cmId}`;\n } else {\n const sectionElement = link.closest('.courseindex-section');\n const sectionNumber = sectionElement ? sectionElement.data('number') : 0;\n window.location.href = `${config.wwwroot}\/course\/view.php?id=${courseId}`\n + `§ion=${sectionNumber}&cmid=${cmId}`;\n }\n } else {\n window.location.href = linkUrl;\n }\n }\n }\n });\n }\n });\n }\n };\n }\n);\n"],"names":["define","$","modalFactory","config","Templates","Notification","ajax","Fragment","ModalEvents","loadingIconHtml","modalStore","win","window","courseId","tilesConfig","Selector","CLASS","modalMinWidth","Math","min","width","stopAllVideosOnDismiss","modal","on","hidden","iframes","find","objects","moodleMediaPlayer","length","data","undefined","remove","launchCmModal","cmId","moduleContextId","sectionNum","title","objectType","completionEnabled","existingCompletionState","isManualCompletion","descriptionHTML","create","type","types","DEFAULT","body","done","setLarge","show","modalRoot","root","attr","addClass","loadFragment","contextid","html","js","setBody","runTemplateJS","templateData","id","height","round","cmid","tileid","isediting","sesskey","activityname","wwwroot","completionstring","description","template","redirectModule","includes","render","animate","fail","location","href","headerTemplateData","showDownload","showNewWindow","forModal","istrackeduser","hascompletion","oldState","overallcomplete","overallincomplete","completionIsManual","statuscomplete","statusincomplete","completionstate","require","completion","triggerCompletionChangedEvent","parseInt","append","detach","appendTo","setTimeout","exception","modalHeightChangeWatcher","resizeModal","mediaPlayer","each","index","child","css","iframe","iframeSelector","iframeWidth","max","modalBody","howManyChecks","duration","oldHeight","newHeight","modalRequired","url","modalallowedmodnames","modalallowedcmids","startsWith","init","courseIdInit","isEditing","pageType","launchModalCmid","usingJsNav","document","ready","courseIndex","e","target","link","hasClass","preventDefault","linkUrl","closest","call","methodname","args","expandedSection","sectionnumber","modalallowed","course","populateAndExpandSection","coursecontextid","sectionid","modulecontextid","name","modaltype","completionenabled","iscomplete","ismanualcompletion","courseid","pageContent","keyCode","tgt","parent","is","clickedCmObject","currentTarget","existingModal","catch","match","sectionElement","sectionNumber"],"mappings":"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\/F,kBACnD,aAKJiG,UAAY\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"}