From 72321cff3f02783e865f31e44cb0b0d90b82eac5 Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Mon, 27 Dec 2021 11:48:50 +0100 Subject: [PATCH] MDL-73340 theme_boost: course index opened by default --- .../tests/behat/course_courseindex.feature | 29 +++++-------------- .../behat/courseindex_completion.feature | 13 +++------ .../behat/courseindex_keyboardnav.feature | 4 ++- theme/boost/amd/build/drawers.min.js | 2 +- theme/boost/amd/build/drawers.min.js.map | 2 +- theme/boost/amd/src/drawers.js | 28 +++++++++++++----- theme/boost/layout/drawers.php | 2 +- theme/boost/scss/moodle/drawer.scss | 8 +++++ theme/boost/style/moodle.css | 10 ++++++- theme/boost/templates/drawer.mustache | 2 +- theme/classic/style/moodle.css | 10 ++++++- 11 files changed, 65 insertions(+), 45 deletions(-) diff --git a/course/format/tests/behat/course_courseindex.feature b/course/format/tests/behat/course_courseindex.feature index 0e0fac8ef1a..7349e8b1c95 100644 --- a/course/format/tests/behat/course_courseindex.feature +++ b/course/format/tests/behat/course_courseindex.feature @@ -24,6 +24,8 @@ Feature: Course index depending on role | user | course | role | | student1 | C1 | student | | teacher1 | C1 | editingteacher | + # The course index is hidden by default in small devices. + And I change window size to "large" @javascript Scenario: Course index is present on course and activities. @@ -31,19 +33,15 @@ Feature: Course index depending on role Given the "multilang" filter is "on" And the "multilang" filter applies to "content and headings" When I am on the "C1" "Course" page logged in as "teacher1" - Then I should see "Open course index" - And I am on the "Activity sample 1" "assign activity editing" page + Then I am on the "Activity sample 1" "assign activity editing" page And I set the field "Assignment name" in the "General" "fieldset" to "ActivityAktivität sample 1" And I press "Save and display" - And I should see "Open course index" - And I click on "Open course index" "button" And I should see "Activity sample 1" in the "courseindex-content" "region" @javascript Scenario: Course index as a teacher Given I log in as "teacher1" - And I am on "Course 1" course homepage - When I click on "Open course index" "button" + When I am on "Course 1" course homepage Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Topic 2" in the "courseindex-content" "region" And I should see "Topic 3" in the "courseindex-content" "region" @@ -60,8 +58,7 @@ Feature: Course index depending on role And I click on "Hide" "link" in the "Activity sample 3" activity And I log out And I log in as "teacher1" - And I am on "Course 1" course homepage - When I click on "Open course index" "button" + When I am on "Course 1" course homepage Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Topic 2" in the "courseindex-content" "region" And I should see "Topic 3" in the "courseindex-content" "region" @@ -78,8 +75,7 @@ Feature: Course index depending on role And I click on "Hide" "link" in the "Activity sample 3" activity And I log out And I log in as "student1" - And I am on "Course 1" course homepage - When I click on "Open course index" "button" + When I am on "Course 1" course homepage Then I should see "Topic 1" in the "courseindex-content" "region" And I should not see "Topic 2" in the "courseindex-content" "region" And I should see "Topic 3" in the "courseindex-content" "region" @@ -92,7 +88,6 @@ Feature: Course index depending on role Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on When I delete "Activity sample 2" activity - And I click on "Open course index" "button" Then I should not see "Activity sample 2" in the "courseindex-content" "region" @javascript @@ -100,7 +95,6 @@ Feature: Course index depending on role Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on And I turn section "2" highlighting on - And I click on "Open course index" "button" # Current section is only marked visually in the course index. And the "class" attribute of "#courseindex-content [data-for='section'][data-number='2']" "css_element" should contain "current" And I should not see "Highlighted" in the "#courseindex-content [data-for='section'][data-number='1']" "css_element" @@ -117,8 +111,7 @@ Feature: Course index depending on role | activity | name | intro | course | idnumber | section | | book | Second activity in section 1 | Test book description | C1 | sample4 | 1 | And I log in as "teacher1" - And I am on "Course 1" course homepage - When I click on "Open course index" "button" + When I am on "Course 1" course homepage # Sections should be opened by default. Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Activity sample 1" in the "courseindex-content" "region" @@ -166,8 +159,7 @@ Feature: Course index depending on role @javascript Scenario: Course index section preferences - Given I am on the "C1" "Course" page logged in as "teacher1" - When I click on "Open course index" "button" + When I am on the "C1" "Course" page logged in as "teacher1" Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Activity sample 1" in the "courseindex-content" "region" And I should see "Topic 2" in the "courseindex-content" "region" @@ -197,7 +189,6 @@ Feature: Course index depending on role And I delete section "1" And I click on "Delete" "button" in the ".modal" "css_element" And I reload the page - And I click on "Open course index" "button" And I should not see "Activity sample 1" in the "courseindex-content" "region" And I should see "Topic 1" in the "courseindex-content" "region" And I should see "Activity sample 2" in the "courseindex-content" "region" @@ -208,7 +199,6 @@ Feature: Course index depending on role Scenario: Adding section should alter the course index Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on - And I click on "Open course index" "button" When I click on "Add topic" "link" in the "Topic 4" "section" Then I should see "Topic 5" in the "courseindex-content" "region" @@ -216,7 +206,6 @@ Feature: Course index depending on role Scenario: Remove a section should alter the course index Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on - And I click on "Open course index" "button" When I delete section "4" Then I should not see "Topic 4" in the "courseindex-content" "region" @@ -224,7 +213,6 @@ Feature: Course index depending on role Scenario: Delete a previous section should alter the course index unnamed sections Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on - And I click on "Open course index" "button" When I delete section "1" And I click on "Delete" "button" in the ".modal" "css_element" Then I should not see "Topic 4" in the "courseindex-content" "region" @@ -255,7 +243,6 @@ Feature: Course index depending on role # Check course index link goes to the specific section. When I log in as "student1" And I am on "Course 1" course homepage - And I click on "Open course index" "button" And I click on "Topic 1" "link" in the "region-main" "region" And I should not see "Activity sample 3" in the "region-main" "region" And I click on "Activity sample 3" "link" in the "courseindex-content" "region" diff --git a/course/format/tests/behat/courseindex_completion.feature b/course/format/tests/behat/courseindex_completion.feature index b05050d4e89..8a842c1bcb2 100644 --- a/course/format/tests/behat/courseindex_completion.feature +++ b/course/format/tests/behat/courseindex_completion.feature @@ -22,19 +22,19 @@ Feature: Course index completion icons | user | course | role | | student1 | C1 | student | | teacher1 | C1 | editingteacher | + # The course index is hidden by default in small devices. + And I change window size to "large" @javascript Scenario: Teacher does not see completion icons. - Given I am on the "C1" "Course" page logged in as "teacher1" - When I click on "Open course index" "button" + When I am on the "C1" "Course" page logged in as "teacher1" Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Activity sample 1" in the "courseindex-content" "region" And "To do" "icon" should not exist in the "courseindex-content" "region" @javascript Scenario: User should see the completion icons - Given I am on the "C1" "Course" page logged in as "student1" - When I click on "Open course index" "button" + When I am on the "C1" "Course" page logged in as "student1" Then I should see "Topic 1" in the "courseindex-content" "region" And I should see "Activity sample 1" in the "courseindex-content" "region" And "To do" "icon" should exist in the "courseindex-content" "region" @@ -42,7 +42,6 @@ Feature: Course index completion icons @javascript Scenario: Manual completion shoudl update the course index completion Given I am on the "C1" "Course" page logged in as "student1" - And I click on "Open course index" "button" And "To do" "icon" should exist in the "courseindex-content" "region" When I press "Mark as done" And I wait until "Done" "button" exists @@ -54,7 +53,6 @@ Feature: Course index completion icons @javascript Scenario: Refresh the page should keep the completion consistent Given I am on the "C1" "Course" page logged in as "student1" - And I click on "Open course index" "button" And "To do" "icon" should exist in the "courseindex-content" "region" When I press "Mark as done" And I wait until "Done" "button" exists @@ -68,7 +66,6 @@ Feature: Course index completion icons | assign | Activity sample 2 | Test assignment description | C1 | sample2 | 1 | 1 | 1 | When I am on the "sample2" "Activity" page logged in as "student1" And I am on the "C1" "Course" page - And I click on "Open course index" "button" Then "Done" "icon" should exist in the "courseindex-content" "region" @javascript @@ -89,7 +86,6 @@ Feature: Course index completion icons | slot | response | | 1 | False | When I am on the "C1" "Course" page logged in as "student1" - And I click on "Open course index" "button" And "Failed" "icon" should exist in the "courseindex-content" "region" @javascript @@ -110,5 +106,4 @@ Feature: Course index completion icons | slot | response | | 1 | True | When I am on the "C1" "Course" page logged in as "student1" - And I click on "Open course index" "button" And "Done" "icon" should exist in the "courseindex-content" "region" diff --git a/course/format/tests/behat/courseindex_keyboardnav.feature b/course/format/tests/behat/courseindex_keyboardnav.feature index 24c0b841e2a..097463bbebe 100644 --- a/course/format/tests/behat/courseindex_keyboardnav.feature +++ b/course/format/tests/behat/courseindex_keyboardnav.feature @@ -17,11 +17,13 @@ Feature: Verify that courseindex is usable with the keyboard | book | Activity sample 2 | Test book description | C1 | sample2 | 2 | | choice | Activity sample 3 | Test choice description | C1 | sample3 | 3 | Given I am on the "C1" "Course" page logged in as "admin" + And I change window size to "large" + And I click on "Close course index" "button" And I click on "Open course index" "button" And I should see "Topic 1" in the "courseindex-content" "region" And the focused element is "[data-preference='drawer-open-index'] .drawertoggle" "css_element" And I press the tab key - Then the focused element is ".courseindex-section" "css_element" + And the focused element is ".courseindex-section" "css_element" @javascript Scenario: General focus on open course index. diff --git a/theme/boost/amd/build/drawers.min.js b/theme/boost/amd/build/drawers.min.js index 8dd4301c7ad..f0916f41ba5 100644 --- a/theme/boost/amd/build/drawers.min.js +++ b/theme/boost/amd/build/drawers.min.js @@ -1,2 +1,2 @@ -function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("theme_boost/drawers",["exports","core/modal_backdrop","core/templates","core/aria","core/event_dispatcher","core/utils","core/pending","jquery"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=k(b);c=k(c);d=j(d);g=k(g);h=k(h);function i(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;i=function(){return a};return a}function j(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=i();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function k(a){return a&&a.__esModule?a:{default:a}}function l(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function m(a,b){for(var c=0,d;c=t.large},x=function(){if(!p){p=c.default.render("core/modal_backdrop",{}).then(function(a){return new b.default(a)}).then(function(a){a.getAttachmentPoint().get(0).addEventListener("click",function(a){a.preventDefault();E.closeAllDrawers()});return a}).catch()}return p},y=function(a){var b=document.querySelector("".concat(r.OPENBTN,"[data-target=\"").concat(a,"\"]"));if(!b){b=document.querySelector("".concat(r.TOGGLEBTN,"[data-target=\"").concat(a,"\"]"))}return b},z=function(a){var b=[a.querySelector(r.CLOSEBTN),y(a.id)];b.forEach(function(a){if(!a){return}A(a)})},A=function(a,b){if(a.hasAttribute("data-original-title")){(0,h.default)(a).tooltip("disable");a.setAttribute("title",a.dataset.originalTitle)}else{a.dataset.disabledToggle=a.dataset.toggle;a.removeAttribute("data-toggle")}if(b){a.dataset.restoreTooltipOnBlur=!0}},B=function(a){var b=[a.querySelector(r.CLOSEBTN),y(a.id)];b.forEach(function(a){if(!a){return}C(a)})},C=function(a){if(a.hasAttribute("data-original-title")){(0,h.default)(a).tooltip("enable")}else if(a.dataset.disabledToggle){a.dataset.toggle=a.dataset.disabledToggle;(0,h.default)(a).tooltip()}delete a.dataset.restoreTooltipOnBlur},D=function(a){var b=a.querySelector(r.DRAWERCONTENT);if(!b){return}b.addEventListener("scroll",function(){a.classList.toggle(s.SCROLLED,0!=b.scrollTop)})},E=function(){function a(b){l(this,a);o(this,"drawerNode",null);this.drawerNode=b;if(this.drawerNode.classList.contains("show")){this.openDrawer({focusOnCloseButton:!1})}else if(1==this.drawerNode.dataset.forceopen){if(!v()){this.openDrawer({focusOnCloseButton:!1})}}else{d.hide(this.drawerNode)}if(v()){z(this.drawerNode)}D(this.drawerNode);q.set(b,this)}n(a,[{key:"dispatchEvent",value:function dispatchEvent(a){var b=1=window.innerHeight){a.classList.add(s.SCROLLED)}else{a.classList.remove(s.SCROLLED)}})}})();(function registerListeners(){document.addEventListener("click",function(a){var b=a.target.closest(r.TOGGLEBTN);if(b&&b.dataset.target){a.preventDefault();var c=document.getElementById(b.dataset.target),d=E.getDrawerInstanceForNode(c);F(b);d.toggleVisibility()}var e=a.target.closest(r.OPENBTN);if(e&&e.dataset.target){a.preventDefault();var f=document.getElementById(e.dataset.target),g=E.getDrawerInstanceForNode(f);F(b);g.openDrawer()}var h=a.target.closest(r.CLOSEBTN);if(h&&h.dataset.target){a.preventDefault();var i=document.getElementById(h.dataset.target),j=E.getDrawerInstanceForNode(i);j.closeDrawer();G(h.dataset.target)}});document.addEventListener(E.eventTypes.drawerShow,function(a){if(w()){return}E.closeOtherDrawers(a.detail.drawerInstance)});var a="".concat(r.TOGGLEBTN,", ").concat(r.OPENBTN,", ").concat(r.CLOSEBTN);document.addEventListener("focusout",function(b){var c=b.target.closest(a);if((null===c||void 0===c?void 0:c.dataset.restoreTooltipOnBlur)!==void 0){C(c)}});window.addEventListener("resize",(0,f.debounce)(function closeOnResizeListener(){if(v()){var a=!1;q.forEach(function(b){z(b.drawerNode);if(b.isOpen){if(b.closeOnResize){b.closeDrawer()}else{a=!0}}});if(a){x().then(function(a){return a.show()}).catch()}}else{q.forEach(function(a){B(a.drawerNode)});x().then(function(a){return a.hide()}).catch()}},400))})();var H=document.querySelectorAll(r.DRAWERS);H.forEach(function(a){return E.getDrawerInstanceForNode(a)});return a.default}); +function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("theme_boost/drawers",["exports","core/modal_backdrop","core/templates","core/aria","core/event_dispatcher","core/utils","core/pending","jquery"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=k(b);c=k(c);d=j(d);g=k(g);h=k(h);function i(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;i=function(){return a};return a}function j(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=i();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function k(a){return a&&a.__esModule?a:{default:a}}function l(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function m(a,b){for(var c=0,d;c=t.large},x=function(){if(!p){p=c.default.render("core/modal_backdrop",{}).then(function(a){return new b.default(a)}).then(function(a){a.getAttachmentPoint().get(0).addEventListener("click",function(a){a.preventDefault();E.closeAllDrawers()});return a}).catch()}return p},y=function(a){var b=document.querySelector("".concat(r.OPENBTN,"[data-target=\"").concat(a,"\"]"));if(!b){b=document.querySelector("".concat(r.TOGGLEBTN,"[data-target=\"").concat(a,"\"]"))}return b},z=function(a){var b=[a.querySelector(r.CLOSEBTN),y(a.id)];b.forEach(function(a){if(!a){return}A(a)})},A=function(a,b){if(a.hasAttribute("data-original-title")){(0,h.default)(a).tooltip("disable");a.setAttribute("title",a.dataset.originalTitle)}else{a.dataset.disabledToggle=a.dataset.toggle;a.removeAttribute("data-toggle")}if(b){a.dataset.restoreTooltipOnBlur=!0}},B=function(a){var b=[a.querySelector(r.CLOSEBTN),y(a.id)];b.forEach(function(a){if(!a){return}C(a)})},C=function(a){if(a.hasAttribute("data-original-title")){(0,h.default)(a).tooltip("enable")}else if(a.dataset.disabledToggle){a.dataset.toggle=a.dataset.disabledToggle;(0,h.default)(a).tooltip()}delete a.dataset.restoreTooltipOnBlur},D=function(a){var b=a.querySelector(r.DRAWERCONTENT);if(!b){return}b.addEventListener("scroll",function(){a.classList.toggle(s.SCROLLED,0!=b.scrollTop)})},E=function(){function a(b){l(this,a);o(this,"drawerNode",null);this.drawerNode=b;if(v()){this.closeDrawer({focusOnOpenButton:!1,updatePreferences:!1})}if(this.drawerNode.classList.contains(s.SHOW)){this.openDrawer({focusOnCloseButton:!1})}else if(1==this.drawerNode.dataset.forceopen){if(!v()){this.openDrawer({focusOnCloseButton:!1})}}else{d.hide(this.drawerNode)}if(v()){z(this.drawerNode)}D(this.drawerNode);q.set(b,this);b.classList.remove(s.NOTINITIALISED)}n(a,[{key:"dispatchEvent",value:function dispatchEvent(a){var b=1=window.innerHeight){a.classList.add(s.SCROLLED)}else{a.classList.remove(s.SCROLLED)}})}})();(function registerListeners(){document.addEventListener("click",function(a){var b=a.target.closest(r.TOGGLEBTN);if(b&&b.dataset.target){a.preventDefault();var c=document.getElementById(b.dataset.target),d=E.getDrawerInstanceForNode(c);F(b);d.toggleVisibility()}var e=a.target.closest(r.OPENBTN);if(e&&e.dataset.target){a.preventDefault();var f=document.getElementById(e.dataset.target),g=E.getDrawerInstanceForNode(f);F(b);g.openDrawer()}var h=a.target.closest(r.CLOSEBTN);if(h&&h.dataset.target){a.preventDefault();var i=document.getElementById(h.dataset.target),j=E.getDrawerInstanceForNode(i);j.closeDrawer();G(h.dataset.target)}});document.addEventListener(E.eventTypes.drawerShow,function(a){if(w()){return}E.closeOtherDrawers(a.detail.drawerInstance)});var a="".concat(r.TOGGLEBTN,", ").concat(r.OPENBTN,", ").concat(r.CLOSEBTN);document.addEventListener("focusout",function(b){var c=b.target.closest(a);if((null===c||void 0===c?void 0:c.dataset.restoreTooltipOnBlur)!==void 0){C(c)}});window.addEventListener("resize",(0,f.debounce)(function closeOnResizeListener(){if(v()){var a=!1;q.forEach(function(b){z(b.drawerNode);if(b.isOpen){if(b.closeOnResize){b.closeDrawer()}else{a=!0}}});if(a){x().then(function(a){return a.show()}).catch()}}else{q.forEach(function(a){B(a.drawerNode)});x().then(function(a){return a.hide()}).catch()}},400))})();var H=document.querySelectorAll(r.DRAWERS);H.forEach(function(a){return E.getDrawerInstanceForNode(a)});return a.default}); //# sourceMappingURL=drawers.min.js.map diff --git a/theme/boost/amd/build/drawers.min.js.map b/theme/boost/amd/build/drawers.min.js.map index 6fc64c89fa4..501ef5b7e7a 100644 --- a/theme/boost/amd/build/drawers.min.js.map +++ b/theme/boost/amd/build/drawers.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/drawers.js"],"names":["backdropPromise","drawerMap","Map","SELECTORS","BUTTONS","CLOSEBTN","OPENBTN","TOGGLEBTN","DRAWERS","CONTAINER","DRAWERCONTENT","CLASSES","SCROLLED","sizes","medium","large","getCurrentWidth","DomRect","document","body","getBoundingClientRect","x","width","isSmall","browserWidth","isLarge","getBackdrop","Templates","render","then","html","ModalBackdrop","modalBackdrop","getAttachmentPoint","get","addEventListener","e","preventDefault","Drawers","closeAllDrawers","catch","getDrawerOpenButton","drawerId","openButton","querySelector","disableDrawerTooltips","drawerNode","buttons","id","forEach","button","disableButtonTooltip","enableOnBlur","hasAttribute","tooltip","setAttribute","dataset","originalTitle","disabledToggle","toggle","removeAttribute","restoreTooltipOnBlur","enableDrawerTooltips","enableButtonTooltip","addInnerScrollListener","content","classList","scrollTop","contains","openDrawer","focusOnCloseButton","forceopen","Aria","hide","set","eventname","cancelable","drawerInstance","pendingPromise","Pending","showEvent","dispatchEvent","eventTypes","drawerShow","defaultPrevented","unhide","add","preference","M","util","set_user_preference","state","page","getElementById","backdrop","show","pageWrapper","style","overflow","closeButton","setTimeout","focus","resolve","drawerShown","hideEvent","drawerHide","remove","drawerHidden","closeDrawer","parseInt","closeOnResize","has","comparisonInstance","setLastUsedToggle","toggleButton","target","querySelectorAll","btn","lastused","focusLastUsedToggle","lastUsedButton","scroller","drawerLayout","window","innerHeight","registerListeners","closest","targetDrawer","getDrawerInstanceForNode","toggleVisibility","openDrawerButton","closeDrawerButton","closeOtherDrawers","detail","btnSelector","closeOnResizeListener","anyOpen","isOpen","drawers"],"mappings":"siBAsBA,OACA,OACA,OAGA,OAEA,O,8hCAEIA,CAAAA,CAAe,CAAG,I,CAEhBC,CAAS,CAAG,GAAIC,CAAAA,G,CAEhBC,CAAS,CAAG,CACdC,OAAO,CAAE,4BADK,CAEdC,QAAQ,CAAE,yDAFI,CAGdC,OAAO,CAAE,wDAHK,CAIdC,SAAS,CAAE,oDAJG,CAKdC,OAAO,CAAE,gCALK,CAMdC,SAAS,CAAE,eANG,CAOdC,aAAa,CAAE,gBAPD,C,CAUZC,CAAO,CAAG,CACZC,QAAQ,CAAE,UADE,C,CAUVC,CAAK,CAAG,CACVC,MAAM,CAAE,GADE,CAEVC,KAAK,CAAE,IAFG,C,CAWRC,CAAe,CAAG,UAAM,CAC1B,GAAMC,CAAAA,CAAO,CAAGC,QAAQ,CAACC,IAAT,CAAcC,qBAAd,EAAhB,CACA,MAAOH,CAAAA,CAAO,CAACI,CAAR,CAAYJ,CAAO,CAACK,KAC9B,C,CAQKC,CAAO,CAAG,UAAM,CAClB,GAAMC,CAAAA,CAAY,CAAGR,CAAe,EAApC,CACA,MAAOQ,CAAAA,CAAY,CAAGX,CAAK,CAACC,MAC/B,C,CAQKW,CAAO,CAAG,UAAM,CAClB,GAAMD,CAAAA,CAAY,CAAGR,CAAe,EAApC,CACA,MAAOQ,CAAAA,CAAY,EAAIX,CAAK,CAACE,KAChC,C,CAQKW,CAAW,CAAG,UAAM,CACtB,GAAI,CAAC1B,CAAL,CAAsB,CAClBA,CAAe,CAAG2B,UAAUC,MAAV,CAAiB,qBAAjB,CAAwC,EAAxC,EACjBC,IADiB,CACZ,SAAAC,CAAI,QAAI,IAAIC,UAAJ,CAAkBD,CAAlB,CAAJ,CADQ,EAEjBD,IAFiB,CAEZ,SAAAG,CAAa,CAAI,CACnBA,CAAa,CAACC,kBAAd,GAAmCC,GAAnC,CAAuC,CAAvC,EAA0CC,gBAA1C,CAA2D,OAA3D,CAAoE,SAAAC,CAAC,CAAI,CACrEA,CAAC,CAACC,cAAF,GACAC,CAAO,CAACC,eAAR,EACH,CAHD,EAIA,MAAOP,CAAAA,CACV,CARiB,EASjBQ,KATiB,EAUrB,CACD,MAAOxC,CAAAA,CACV,C,CASKyC,CAAmB,CAAG,SAACC,CAAD,CAAc,CACtC,GAAIC,CAAAA,CAAU,CAAGzB,QAAQ,CAAC0B,aAAT,WAA0BzC,CAAS,CAACG,OAApC,2BAA4DoC,CAA5D,QAAjB,CACA,GAAI,CAACC,CAAL,CAAiB,CACbA,CAAU,CAAGzB,QAAQ,CAAC0B,aAAT,WAA0BzC,CAAS,CAACI,SAApC,2BAA8DmC,CAA9D,QAChB,CACD,MAAOC,CAAAA,CACV,C,CAQKE,CAAqB,CAAG,SAACC,CAAD,CAAgB,CAC1C,GAAMC,CAAAA,CAAO,CAAG,CACZD,CAAU,CAACF,aAAX,CAAyBzC,CAAS,CAACE,QAAnC,CADY,CAEZoC,CAAmB,CAACK,CAAU,CAACE,EAAZ,CAFP,CAAhB,CAIAD,CAAO,CAACE,OAAR,CAAgB,SAAAC,CAAM,CAAI,CACtB,GAAI,CAACA,CAAL,CAAa,CACT,MACH,CACDC,CAAoB,CAACD,CAAD,CACvB,CALD,CAMH,C,CASKC,CAAoB,CAAG,SAACD,CAAD,CAASE,CAAT,CAA0B,CACnD,GAAIF,CAAM,CAACG,YAAP,CAAoB,qBAApB,CAAJ,CAAgD,CAE5C,cAAOH,CAAP,EAAeI,OAAf,CAAuB,SAAvB,EACAJ,CAAM,CAACK,YAAP,CAAoB,OAApB,CAA6BL,CAAM,CAACM,OAAP,CAAeC,aAA5C,CACH,CAJD,IAIO,CACHP,CAAM,CAACM,OAAP,CAAeE,cAAf,CAAgCR,CAAM,CAACM,OAAP,CAAeG,MAA/C,CACAT,CAAM,CAACU,eAAP,CAAuB,aAAvB,CACH,CACD,GAAIR,CAAJ,CAAkB,CACdF,CAAM,CAACM,OAAP,CAAeK,oBAAf,GACH,CACJ,C,CAQKC,CAAoB,CAAG,SAAChB,CAAD,CAAgB,CACzC,GAAMC,CAAAA,CAAO,CAAG,CACZD,CAAU,CAACF,aAAX,CAAyBzC,CAAS,CAACE,QAAnC,CADY,CAEZoC,CAAmB,CAACK,CAAU,CAACE,EAAZ,CAFP,CAAhB,CAIAD,CAAO,CAACE,OAAR,CAAgB,SAAAC,CAAM,CAAI,CACtB,GAAI,CAACA,CAAL,CAAa,CACT,MACH,CACDa,CAAmB,CAACb,CAAD,CACtB,CALD,CAMH,C,CAQKa,CAAmB,CAAG,SAACb,CAAD,CAAY,CAEpC,GAAIA,CAAM,CAACG,YAAP,CAAoB,qBAApB,CAAJ,CAAgD,CAC5C,cAAOH,CAAP,EAAeI,OAAf,CAAuB,QAAvB,CACH,CAFD,IAEO,IAAIJ,CAAM,CAACM,OAAP,CAAeE,cAAnB,CAAmC,CACtCR,CAAM,CAACM,OAAP,CAAeG,MAAf,CAAwBT,CAAM,CAACM,OAAP,CAAeE,cAAvC,CACA,cAAOR,CAAP,EAAeI,OAAf,EACH,CACD,MAAOJ,CAAAA,CAAM,CAACM,OAAP,CAAeK,oBACzB,C,CAQKG,CAAsB,CAAG,SAAClB,CAAD,CAAgB,CAC3C,GAAMmB,CAAAA,CAAO,CAAGnB,CAAU,CAACF,aAAX,CAAyBzC,CAAS,CAACO,aAAnC,CAAhB,CACA,GAAI,CAACuD,CAAL,CAAc,CACV,MACH,CACDA,CAAO,CAAC9B,gBAAR,CAAyB,QAAzB,CAAmC,UAAM,CACrCW,CAAU,CAACoB,SAAX,CAAqBP,MAArB,CACIhD,CAAO,CAACC,QADZ,CAEyB,CAArB,EAAAqD,CAAO,CAACE,SAFZ,CAIH,CALD,CAMH,C,CAmDoB7B,C,YAMjB,WAAYQ,CAAZ,CAAwB,+BAFX,IAEW,EACpB,KAAKA,UAAL,CAAkBA,CAAlB,CAEA,GAAI,KAAKA,UAAL,CAAgBoB,SAAhB,CAA0BE,QAA1B,CAAmC,MAAnC,CAAJ,CAAgD,CAC5C,KAAKC,UAAL,CAAgB,CAACC,kBAAkB,GAAnB,CAAhB,CACH,CAFD,IAEO,IAAyC,CAArC,OAAKxB,UAAL,CAAgBU,OAAhB,CAAwBe,SAA5B,CAA4C,CAC/C,GAAI,CAAChD,CAAO,EAAZ,CAAgB,CACZ,KAAK8C,UAAL,CAAgB,CAACC,kBAAkB,GAAnB,CAAhB,CACH,CACJ,CAJM,IAIA,CACHE,CAAI,CAACC,IAAL,CAAU,KAAK3B,UAAf,CACH,CAGD,GAAIvB,CAAO,EAAX,CAAe,CACXsB,CAAqB,CAAC,KAAKC,UAAN,CACxB,CAEDkB,CAAsB,CAAC,KAAKlB,UAAN,CAAtB,CAEA7C,CAAS,CAACyE,GAAV,CAAc5B,CAAd,CAA0B,IAA1B,CACH,C,uDAyFa6B,C,CAA+B,IAApBC,CAAAA,CAAoB,2DACzC,MAAO,oBACHD,CADG,CAEH,CACIE,cAAc,CAAE,IADpB,CAFG,CAKH,KAAK/B,UALF,CAMH,CACI8B,UAAU,CAAVA,CADJ,CANG,CAUV,C,+CAY4C,gEAAJ,EAAI,KAAjCN,kBAAiC,CAAjCA,CAAiC,iBAEnCQ,CAAc,CAAG,GAAIC,UAAJ,CAAY,0BAAZ,CAFkB,CAGnCC,CAAS,CAAG,KAAKC,aAAL,CAAmB3C,CAAO,CAAC4C,UAAR,CAAmBC,UAAtC,IAHuB,CAIzC,GAAIH,CAAS,CAACI,gBAAd,CAAgC,CAC5B,MACH,CAGD,eAAKtC,UAAL,CAAgBF,aAAhB,CAA8BzC,CAAS,CAACE,QAAxC,wBAAmD6D,SAAnD,CAA6DP,MAA7D,CAAoE,QAApE,KAGA,GAAIhB,CAAAA,CAAU,CAAGF,CAAmB,CAAC,KAAKK,UAAL,CAAgBE,EAAjB,CAApC,CACA,GAAIL,CAAU,EAAIA,CAAU,CAACU,YAAX,CAAwB,qBAAxB,CAAlB,CAAkE,OAE9D,wBAAOV,CAAP,wBAAoBW,OAApB,CAA4B,MAA5B,CACH,CAEDkB,CAAI,CAACa,MAAL,CAAY,KAAKvC,UAAjB,EACA,KAAKA,UAAL,CAAgBoB,SAAhB,CAA0BoB,GAA1B,CAA8B,MAA9B,EAEA,GAAMC,CAAAA,CAAU,CAAG,KAAKzC,UAAL,CAAgBU,OAAhB,CAAwB+B,UAA3C,CACA,GAAIA,CAAU,EAAI,CAAChE,CAAO,EAAtB,EAAkE,CAArC,OAAKuB,UAAL,CAAgBU,OAAhB,CAAwBe,SAAzD,CAA0E,CACtEiB,CAAC,CAACC,IAAF,CAAOC,mBAAP,CAA2BH,CAA3B,IACH,CAED,GAAMI,CAAAA,CAAK,CAAG,KAAK7C,UAAL,CAAgBU,OAAhB,CAAwBmC,KAAtC,CACA,GAAIA,CAAJ,CAAW,CACP,GAAMC,CAAAA,CAAI,CAAG1E,QAAQ,CAAC2E,cAAT,CAAwB,MAAxB,CAAb,CACAD,CAAI,CAAC1B,SAAL,CAAeoB,GAAf,CAAmBK,CAAnB,CACH,CAED,GAAIpE,CAAO,EAAX,CAAe,CACXG,CAAW,GAAGG,IAAd,CAAmB,SAAAiE,CAAQ,CAAI,CAC3BA,CAAQ,CAACC,IAAT,GAEA,GAAMC,CAAAA,CAAW,CAAG9E,QAAQ,CAAC2E,cAAT,CAAwB,cAAxB,CAApB,CACAG,CAAW,CAACC,KAAZ,CAAkBC,QAAlB,CAA6B,QAA7B,CACA,MAAOJ,CAAAA,CACV,CAND,EAOCtD,KAPD,EAQH,CAGD,GAAM2D,CAAAA,CAAW,CAAG,KAAKrD,UAAL,CAAgBF,aAAhB,CAA8BzC,CAAS,CAACE,QAAxC,CAApB,CACA,GAAIiE,CAAkB,EAAI6B,CAA1B,CAAuC,CACnChD,CAAoB,CAACgD,CAAD,IACvB,CACDC,UAAU,CAAC,UAAM,CACbD,CAAW,CAACjC,SAAZ,CAAsBP,MAAtB,CAA6B,QAA7B,KACA,GAAIW,CAAJ,CAAwB,CACpB6B,CAAW,CAACE,KAAZ,EACH,CACDvB,CAAc,CAACwB,OAAf,EACH,CANS,CAMP,GANO,CAAV,CAQA,KAAKrB,aAAL,CAAmB3C,CAAO,CAAC4C,UAAR,CAAmBqB,WAAtC,CACH,C,iDAKa,IAEJzB,CAAAA,CAAc,CAAG,GAAIC,UAAJ,CAAY,2BAAZ,CAFb,CAIJyB,CAAS,CAAG,KAAKvB,aAAL,CAAmB3C,CAAO,CAAC4C,UAAR,CAAmBuB,UAAtC,IAJR,CAKV,GAAID,CAAS,CAACpB,gBAAd,CAAgC,CAC5B,MACH,CAGD,GAAMe,CAAAA,CAAW,CAAG,KAAKrD,UAAL,CAAgBF,aAAhB,CAA8BzC,CAAS,CAACE,QAAxC,CAApB,CACA,OAAA8F,CAAW,WAAXA,SAAAA,CAAW,CAAEjC,SAAb,CAAuBP,MAAvB,CAA8B,QAA9B,KAEA,GAAIwC,CAAW,CAAC9C,YAAZ,CAAyB,qBAAzB,CAAJ,CAAqD,OAEjD,wBAAO8C,CAAP,wBAAqB7C,OAArB,CAA6B,MAA7B,CACH,CAED,GAAMiC,CAAAA,CAAU,CAAG,KAAKzC,UAAL,CAAgBU,OAAhB,CAAwB+B,UAA3C,CACA,GAAIA,CAAJ,CAAgB,CACZC,CAAC,CAACC,IAAF,CAAOC,mBAAP,CAA2BH,CAA3B,IACH,CAED,GAAMI,CAAAA,CAAK,CAAG,KAAK7C,UAAL,CAAgBU,OAAhB,CAAwBmC,KAAtC,CACA,GAAIA,CAAJ,CAAW,CACP,GAAMC,CAAAA,CAAI,CAAG1E,QAAQ,CAAC2E,cAAT,CAAwB,MAAxB,CAAb,CACAD,CAAI,CAAC1B,SAAL,CAAewC,MAAf,CAAsBf,CAAtB,CACH,CAEDnB,CAAI,CAACC,IAAL,CAAU,KAAK3B,UAAf,EACA,KAAKA,UAAL,CAAgBoB,SAAhB,CAA0BwC,MAA1B,CAAiC,MAAjC,EAEAhF,CAAW,GAAGG,IAAd,CAAmB,SAAAiE,CAAQ,CAAI,CAC3BA,CAAQ,CAACrB,IAAT,GAEA,GAAIlD,CAAO,EAAX,CAAe,CACX,GAAMyE,CAAAA,CAAW,CAAG9E,QAAQ,CAAC2E,cAAT,CAAwB,cAAxB,CAApB,CACAG,CAAW,CAACC,KAAZ,CAAkBC,QAAlB,CAA6B,MAChC,CACD,MAAOJ,CAAAA,CACV,CARD,EASCtD,KATD,GAYA,GAAIG,CAAAA,CAAU,CAAGF,CAAmB,CAAC,KAAKK,UAAL,CAAgBE,EAAjB,CAApC,CACA,GAAIL,CAAJ,CAAgB,CACZQ,CAAoB,CAACR,CAAD,IACvB,CACDyD,UAAU,CAAC,UAAM,CACb,GAAIzD,CAAJ,CAAgB,CACZA,CAAU,CAAC0D,KAAX,EACH,CACDvB,CAAc,CAACwB,OAAf,EACH,CALS,CAKP,GALO,CAAV,CAOA,KAAKrB,aAAL,CAAmB3C,CAAO,CAAC4C,UAAR,CAAmByB,YAAtC,CACH,C,2DAKkB,CACf,GAAI,KAAK7D,UAAL,CAAgBoB,SAAhB,CAA0BE,QAA1B,CAAmC,MAAnC,CAAJ,CAAgD,CAC5C,KAAKwC,WAAL,EACH,CAFD,IAEO,CACH,KAAKvC,UAAL,EACH,CACJ,C,kCA1OY,CACT,MAAO,MAAKvB,UAAL,CAAgBoB,SAAhB,CAA0BE,QAA1B,CAAmC,MAAnC,CACV,C,yCAOmB,CAChB,MAAO,CAAC,CAACyC,QAAQ,CAAC,KAAK/D,UAAL,CAAgBU,OAAhB,CAAwBsD,aAAzB,CACpB,C,4EAwD+BhE,C,CAAY,CACxC,GAAI,CAAC7C,CAAS,CAAC8G,GAAV,CAAcjE,CAAd,CAAL,CAAgC,CAC5B,GAAIR,CAAAA,CAAJ,CAAYQ,CAAZ,CACH,CAED,MAAO7C,CAAAA,CAAS,CAACiC,GAAV,CAAcY,CAAd,CACV,C,yDAsKwB,CACrB7C,CAAS,CAACgD,OAAV,CAAkB,SAAA4B,CAAc,CAAI,CAChCA,CAAc,CAAC+B,WAAf,EACH,CAFD,CAGH,C,4DAOwBI,C,CAAoB,CACzC/G,CAAS,CAACgD,OAAV,CAAkB,SAAA4B,CAAc,CAAI,CAChC,GAAIA,CAAc,GAAKmC,CAAvB,CAA2C,CACvC,MACH,CAEDnC,CAAc,CAAC+B,WAAf,EACH,CAND,CAOH,C,8BApSgBtE,C,cAwDG,CAQhB6C,UAAU,CAAE,0BARI,CAiBhBoB,WAAW,CAAE,2BAjBG,CA0BhBE,UAAU,CAAE,0BA1BI,CAmChBE,YAAY,CAAE,4BAnCE,C,KAuQlBM,CAAAA,CAAiB,CAAG,SAACC,CAAD,CAAkB,CACxC,GAAIA,CAAY,CAAC1D,OAAb,CAAqB2D,MAAzB,CAAiC,CAC7BjG,QAAQ,CAACkG,gBAAT,WAA6BjH,CAAS,CAACC,OAAvC,2BAA+D8G,CAAY,CAAC1D,OAAb,CAAqB2D,MAApF,SACClE,OADD,CACS,SAAAoE,CAAG,CAAI,CACZA,CAAG,CAAC7D,OAAJ,CAAY8D,QAAZ,GACH,CAHD,EAIAJ,CAAY,CAAC1D,OAAb,CAAqB8D,QAArB,GACH,CACJ,C,CAMKC,CAAmB,CAAG,SAACJ,CAAD,CAAY,CACpC,GAAMK,CAAAA,CAAc,CAAGtG,QAAQ,CAAC0B,aAAT,WAA0BzC,CAAS,CAACC,OAApC,2BAA4D+G,CAA5D,+BAAvB,CACA,GAAIK,CAAJ,CAAoB,CAChBA,CAAc,CAACnB,KAAf,EACH,CACJ,C,CAsFD,CA5HiB,QAAXoB,CAAAA,QAAW,EAAM,IACbtG,CAAAA,CAAI,CAAGD,QAAQ,CAAC0B,aAAT,CAAuB,MAAvB,CADM,CAEb8E,CAAY,CAAGxG,QAAQ,CAAC0B,aAAT,CAAuBzC,CAAS,CAACM,SAAjC,CAFF,CAGnB,GAAIiH,CAAJ,CAAkB,CACdA,CAAY,CAACvF,gBAAb,CAA8B,QAA9B,CAAwC,UAAM,CAC1C,GAAIuF,CAAY,CAACvD,SAAb,EAA0BwD,MAAM,CAACC,WAArC,CAAkD,CAC9CzG,CAAI,CAAC+C,SAAL,CAAeoB,GAAf,CAAmB3E,CAAO,CAACC,QAA3B,CACH,CAFD,IAEO,CACHO,CAAI,CAAC+C,SAAL,CAAewC,MAAf,CAAsB/F,CAAO,CAACC,QAA9B,CACH,CACJ,CAND,CAOH,CACJ,CAgHD,IACA,CAhF0B,QAApBiH,CAAAA,iBAAoB,EAAM,CAE5B3G,QAAQ,CAACiB,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAC,CAAI,CACpC,GAAM8E,CAAAA,CAAY,CAAG9E,CAAC,CAAC+E,MAAF,CAASW,OAAT,CAAiB3H,CAAS,CAACI,SAA3B,CAArB,CACA,GAAI2G,CAAY,EAAIA,CAAY,CAAC1D,OAAb,CAAqB2D,MAAzC,CAAiD,CAC7C/E,CAAC,CAACC,cAAF,GAD6C,GAEvC0F,CAAAA,CAAY,CAAG7G,QAAQ,CAAC2E,cAAT,CAAwBqB,CAAY,CAAC1D,OAAb,CAAqB2D,MAA7C,CAFwB,CAGvCtC,CAAc,CAAGvC,CAAO,CAAC0F,wBAAR,CAAiCD,CAAjC,CAHsB,CAI7Cd,CAAiB,CAACC,CAAD,CAAjB,CAEArC,CAAc,CAACoD,gBAAf,EACH,CAED,GAAMC,CAAAA,CAAgB,CAAG9F,CAAC,CAAC+E,MAAF,CAASW,OAAT,CAAiB3H,CAAS,CAACG,OAA3B,CAAzB,CACA,GAAI4H,CAAgB,EAAIA,CAAgB,CAAC1E,OAAjB,CAAyB2D,MAAjD,CAAyD,CACrD/E,CAAC,CAACC,cAAF,GADqD,GAE/C0F,CAAAA,CAAY,CAAG7G,QAAQ,CAAC2E,cAAT,CAAwBqC,CAAgB,CAAC1E,OAAjB,CAAyB2D,MAAjD,CAFgC,CAG/CtC,CAAc,CAAGvC,CAAO,CAAC0F,wBAAR,CAAiCD,CAAjC,CAH8B,CAIrDd,CAAiB,CAACC,CAAD,CAAjB,CAEArC,CAAc,CAACR,UAAf,EACH,CAED,GAAM8D,CAAAA,CAAiB,CAAG/F,CAAC,CAAC+E,MAAF,CAASW,OAAT,CAAiB3H,CAAS,CAACE,QAA3B,CAA1B,CACA,GAAI8H,CAAiB,EAAIA,CAAiB,CAAC3E,OAAlB,CAA0B2D,MAAnD,CAA2D,CACvD/E,CAAC,CAACC,cAAF,GADuD,GAEjD0F,CAAAA,CAAY,CAAG7G,QAAQ,CAAC2E,cAAT,CAAwBsC,CAAiB,CAAC3E,OAAlB,CAA0B2D,MAAlD,CAFkC,CAGjDtC,CAAc,CAAGvC,CAAO,CAAC0F,wBAAR,CAAiCD,CAAjC,CAHgC,CAKvDlD,CAAc,CAAC+B,WAAf,GACAW,CAAmB,CAACY,CAAiB,CAAC3E,OAAlB,CAA0B2D,MAA3B,CACtB,CACJ,CA9BD,EAiCAjG,QAAQ,CAACiB,gBAAT,CAA0BG,CAAO,CAAC4C,UAAR,CAAmBC,UAA7C,CAAyD,SAAA/C,CAAC,CAAI,CAC1D,GAAIX,CAAO,EAAX,CAAe,CACX,MACH,CACDa,CAAO,CAAC8F,iBAAR,CAA0BhG,CAAC,CAACiG,MAAF,CAASxD,cAAnC,CACH,CALD,EAQA,GAAMyD,CAAAA,CAAW,WAAMnI,CAAS,CAACI,SAAhB,cAA8BJ,CAAS,CAACG,OAAxC,cAAoDH,CAAS,CAACE,QAA9D,CAAjB,CACAa,QAAQ,CAACiB,gBAAT,CAA0B,UAA1B,CAAsC,SAACC,CAAD,CAAO,CACzC,GAAMc,CAAAA,CAAM,CAAGd,CAAC,CAAC+E,MAAF,CAASW,OAAT,CAAiBQ,CAAjB,CAAf,CACA,GAAI,QAAApF,CAAM,WAANA,SAAAA,CAAM,CAAEM,OAAR,CAAgBK,oBAAhB,UAAJ,CAAwD,CACpDE,CAAmB,CAACb,CAAD,CACtB,CACJ,CALD,EAgCAyE,MAAM,CAACxF,gBAAP,CAAwB,QAAxB,CAAkC,eAzBJ,QAAxBoG,CAAAA,qBAAwB,EAAM,CAChC,GAAIhH,CAAO,EAAX,CAAe,CACX,GAAIiH,CAAAA,CAAO,GAAX,CACAvI,CAAS,CAACgD,OAAV,CAAkB,SAAA4B,CAAc,CAAI,CAChChC,CAAqB,CAACgC,CAAc,CAAC/B,UAAhB,CAArB,CACA,GAAI+B,CAAc,CAAC4D,MAAnB,CAA2B,CACvB,GAAI5D,CAAc,CAACiC,aAAnB,CAAkC,CAC9BjC,CAAc,CAAC+B,WAAf,EACH,CAFD,IAEO,CACH4B,CAAO,GACV,CACJ,CACJ,CATD,EAWA,GAAIA,CAAJ,CAAa,CACT9G,CAAW,GAAGG,IAAd,CAAmB,SAAAiE,CAAQ,QAAIA,CAAAA,CAAQ,CAACC,IAAT,EAAJ,CAA3B,EAAgDvD,KAAhD,EACH,CACJ,CAhBD,IAgBO,CACHvC,CAAS,CAACgD,OAAV,CAAkB,SAAA4B,CAAc,CAAI,CAChCf,CAAoB,CAACe,CAAc,CAAC/B,UAAhB,CACvB,CAFD,EAGApB,CAAW,GAAGG,IAAd,CAAmB,SAAAiE,CAAQ,QAAIA,CAAAA,CAAQ,CAACrB,IAAT,EAAJ,CAA3B,EAAgDjC,KAAhD,EACH,CACJ,CAEiC,CAAgC,GAAhC,CAAlC,CACH,CAGD,IAEA,GAAMkG,CAAAA,CAAO,CAAGxH,QAAQ,CAACkG,gBAAT,CAA0BjH,CAAS,CAACK,OAApC,CAAhB,CACAkI,CAAO,CAACzF,OAAR,CAAgB,SAAAH,CAAU,QAAIR,CAAAA,CAAO,CAAC0F,wBAAR,CAAiClF,CAAjC,CAAJ,CAA1B,E","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 * Toggling the visibility of the secondary navigation on mobile.\n *\n * @module theme_boost/drawers\n * @copyright 2021 Bas Brands\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ModalBackdrop from 'core/modal_backdrop';\nimport Templates from 'core/templates';\nimport * as Aria from 'core/aria';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {debounce} from 'core/utils';\nimport Pending from 'core/pending';\n// The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.\nimport jQuery from 'jquery';\n\nlet backdropPromise = null;\n\nconst drawerMap = new Map();\n\nconst SELECTORS = {\n BUTTONS: '[data-toggler=\"drawers\"]',\n CLOSEBTN: '[data-toggler=\"drawers\"][data-action=\"closedrawer\"]',\n OPENBTN: '[data-toggler=\"drawers\"][data-action=\"opendrawer\"]',\n TOGGLEBTN: '[data-toggler=\"drawers\"][data-action=\"toggle\"]',\n DRAWERS: '[data-region=\"fixed-drawer\"]',\n CONTAINER: '#page.drawers',\n DRAWERCONTENT: '.drawercontent',\n};\n\nconst CLASSES = {\n SCROLLED: 'scrolled',\n};\n\n/**\n * Maximum sizes for breakpoints. This needs to correspond with Bootstrap\n * Breakpoints\n *\n * @private\n */\nconst sizes = {\n medium: 991,\n large: 1400\n};\n\n/**\n * Get the current body width.\n *\n * @returns {number} the current body width.\n * @private\n */\nconst getCurrentWidth = () => {\n const DomRect = document.body.getBoundingClientRect();\n return DomRect.x + DomRect.width;\n};\n\n/**\n * Check if the user uses a small size browser.\n *\n * @returns {boolean} true if the body is smaller than sizes.medium max size.\n * @private\n */\nconst isSmall = () => {\n const browserWidth = getCurrentWidth();\n return browserWidth < sizes.medium;\n};\n\n/**\n * Check if the user uses a large size browser.\n *\n * @returns {boolean} true if the body is smaller than sizes.large max size.\n * @private\n */\nconst isLarge = () => {\n const browserWidth = getCurrentWidth();\n return browserWidth >= sizes.large;\n};\n\n/**\n * Add a backdrop to the page.\n *\n * @returns {Promise} rendering of modal backdrop.\n * @private\n */\nconst getBackdrop = () => {\n if (!backdropPromise) {\n backdropPromise = Templates.render('core/modal_backdrop', {})\n .then(html => new ModalBackdrop(html))\n .then(modalBackdrop => {\n modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => {\n e.preventDefault();\n Drawers.closeAllDrawers();\n });\n return modalBackdrop;\n })\n .catch();\n }\n return backdropPromise;\n};\n\n/**\n * Get the button element to open a specific drawer.\n *\n * @param {String} drawerId the drawer element Id\n * @return {HTMLElement|undefined} the open button element\n * @private\n */\nconst getDrawerOpenButton = (drawerId) => {\n let openButton = document.querySelector(`${SELECTORS.OPENBTN}[data-target=\"${drawerId}\"]`);\n if (!openButton) {\n openButton = document.querySelector(`${SELECTORS.TOGGLEBTN}[data-target=\"${drawerId}\"]`);\n }\n return openButton;\n};\n\n/**\n * Disable drawer tooltips.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst disableDrawerTooltips = (drawerNode) => {\n const buttons = [\n drawerNode.querySelector(SELECTORS.CLOSEBTN),\n getDrawerOpenButton(drawerNode.id),\n ];\n buttons.forEach(button => {\n if (!button) {\n return;\n }\n disableButtonTooltip(button);\n });\n};\n\n/**\n * Disable the button tooltips.\n *\n * @param {HTMLElement} button the button element\n * @param {boolean} enableOnBlur if the tooltip must be re-enabled on blur.\n * @private\n */\nconst disableButtonTooltip = (button, enableOnBlur) => {\n if (button.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(button).tooltip('disable');\n button.setAttribute('title', button.dataset.originalTitle);\n } else {\n button.dataset.disabledToggle = button.dataset.toggle;\n button.removeAttribute('data-toggle');\n }\n if (enableOnBlur) {\n button.dataset.restoreTooltipOnBlur = true;\n }\n};\n\n/**\n * Enable drawer tooltips.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst enableDrawerTooltips = (drawerNode) => {\n const buttons = [\n drawerNode.querySelector(SELECTORS.CLOSEBTN),\n getDrawerOpenButton(drawerNode.id),\n ];\n buttons.forEach(button => {\n if (!button) {\n return;\n }\n enableButtonTooltip(button);\n });\n};\n\n/**\n * Enable the button tooltips.\n *\n * @param {HTMLElement} button the button element\n * @private\n */\nconst enableButtonTooltip = (button) => {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n if (button.hasAttribute('data-original-title')) {\n jQuery(button).tooltip('enable');\n } else if (button.dataset.disabledToggle) {\n button.dataset.toggle = button.dataset.disabledToggle;\n jQuery(button).tooltip();\n }\n delete button.dataset.restoreTooltipOnBlur;\n};\n\n/**\n * Add scroll listeners to a drawer element.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst addInnerScrollListener = (drawerNode) => {\n const content = drawerNode.querySelector(SELECTORS.DRAWERCONTENT);\n if (!content) {\n return;\n }\n content.addEventListener(\"scroll\", () => {\n drawerNode.classList.toggle(\n CLASSES.SCROLLED,\n content.scrollTop != 0\n );\n });\n};\n\n/**\n * The Drawers class is used to control on-screen drawer elements.\n *\n * It handles opening, and closing of drawer elements, as well as more detailed behaviours such as closing a drawer when\n * another drawer is opened, and supports closing a drawer when the screen is resized.\n *\n * Drawers are instantiated on page load, and can also be toggled lazily when toggling any drawer toggle, open button,\n * or close button.\n *\n * A range of show and hide events are also dispatched as detailed in the class\n * {@link module:theme_boost/drawers#eventTypes eventTypes} object.\n *\n * @example Standard usage\n *\n * // The module just needs to be included to add drawer support.\n * import 'theme_boost/drawers';\n *\n * @example Manually open or close any drawer\n *\n * import Drawers from 'theme_boost/drawers';\n *\n * const myDrawer = Drawers.getDrawerInstanceForNode(document.querySelector('.myDrawerNode');\n * myDrawer.closeDrawer();\n *\n * @example Listen to the before show event and cancel it\n *\n * import Drawers from 'theme_boost/drawers';\n *\n * document.addEventListener(Drawers.eventTypes.drawerShow, e => {\n * // The drawer which will be shown.\n * window.console.log(e.target);\n *\n * // The instance of the Drawers class for this drawer.\n * window.console.log(e.detail.drawerInstance);\n *\n * // Prevent this drawer from being shown.\n * e.preventDefault();\n * });\n *\n * @example Listen to the shown event\n *\n * document.addEventListener(Drawers.eventTypes.drawerShown, e => {\n * // The drawer which was shown.\n * window.console.log(e.target);\n *\n * // The instance of the Drawers class for this drawer.\n * window.console.log(e.detail.drawerInstance);\n * });\n */\nexport default class Drawers {\n /**\n * The underlying HTMLElement which is controlled.\n */\n drawerNode = null;\n\n constructor(drawerNode) {\n this.drawerNode = drawerNode;\n\n if (this.drawerNode.classList.contains('show')) {\n this.openDrawer({focusOnCloseButton: false});\n } else if (this.drawerNode.dataset.forceopen == 1) {\n if (!isSmall()) {\n this.openDrawer({focusOnCloseButton: false});\n }\n } else {\n Aria.hide(this.drawerNode);\n }\n\n // Disable tooltips in small screens.\n if (isSmall()) {\n disableDrawerTooltips(this.drawerNode);\n }\n\n addInnerScrollListener(this.drawerNode);\n\n drawerMap.set(drawerNode, this);\n }\n\n /**\n * Whether the drawer is open.\n *\n * @returns {boolean}\n */\n get isOpen() {\n return this.drawerNode.classList.contains('show');\n }\n\n /**\n * Whether the drawer should close when the window is resized\n *\n * @returns {boolean}\n */\n get closeOnResize() {\n return !!parseInt(this.drawerNode.dataset.closeOnResize);\n }\n\n /**\n * The list of event types.\n *\n * @static\n * @property {String} drawerShow See {@link event:theme_boost/drawers:show}\n * @property {String} drawerShown See {@link event:theme_boost/drawers:shown}\n * @property {String} drawerHide See {@link event:theme_boost/drawers:hide}\n * @property {String} drawerHidden See {@link event:theme_boost/drawers:hidden}\n */\n static eventTypes = {\n /**\n * An event triggered before a drawer is shown.\n *\n * @event theme_boost/drawers:show\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that will be opened.\n */\n drawerShow: 'theme_boost/drawers:show',\n\n /**\n * An event triggered after a drawer is shown.\n *\n * @event theme_boost/drawers:shown\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that was be opened.\n */\n drawerShown: 'theme_boost/drawers:shown',\n\n /**\n * An event triggered before a drawer is hidden.\n *\n * @event theme_boost/drawers:hide\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that will be hidden.\n */\n drawerHide: 'theme_boost/drawers:hide',\n\n /**\n * An event triggered after a drawer is hidden.\n *\n * @event theme_boost/drawers:hidden\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that was be hidden.\n */\n drawerHidden: 'theme_boost/drawers:hidden',\n };\n\n\n /**\n * Get the drawer instance for the specified node\n *\n * @param {HTMLElement} drawerNode\n * @returns {module:theme_boost/drawers}\n */\n static getDrawerInstanceForNode(drawerNode) {\n if (!drawerMap.has(drawerNode)) {\n new Drawers(drawerNode);\n }\n\n return drawerMap.get(drawerNode);\n }\n\n /**\n * Dispatch a drawer event.\n *\n * @param {string} eventname the event name\n * @param {boolean} cancelable if the event is cancelable\n * @returns {CustomEvent} the resulting custom event\n */\n dispatchEvent(eventname, cancelable = false) {\n return dispatchEvent(\n eventname,\n {\n drawerInstance: this,\n },\n this.drawerNode,\n {\n cancelable,\n }\n );\n }\n\n /**\n * Open the drawer.\n *\n * By default, openDrawer sets the page focus to the close drawer button. However, when a drawer is open at page\n * load, this represents an accessibility problem as the initial focus changes without any user interaction. The\n * focusOnCloseButton parameter can be set to false to prevent this behaviour.\n *\n * @param {object} args\n * @param {boolean} [args.focusOnCloseButton=true] Whether to alter page focus when opening the drawer\n */\n openDrawer({focusOnCloseButton = true} = {}) {\n\n const pendingPromise = new Pending('theme_boost/drawers:open');\n const showEvent = this.dispatchEvent(Drawers.eventTypes.drawerShow, true);\n if (showEvent.defaultPrevented) {\n return;\n }\n\n // Hide close button while the drawer is showing to prevent glitchy effects.\n this.drawerNode.querySelector(SELECTORS.CLOSEBTN)?.classList.toggle('hidden', true);\n\n // Remove open tooltip if still visible.\n let openButton = getDrawerOpenButton(this.drawerNode.id);\n if (openButton && openButton.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(openButton)?.tooltip('hide');\n }\n\n Aria.unhide(this.drawerNode);\n this.drawerNode.classList.add('show');\n\n const preference = this.drawerNode.dataset.preference;\n if (preference && !isSmall() && (this.drawerNode.dataset.forceopen != 1)) {\n M.util.set_user_preference(preference, true);\n }\n\n const state = this.drawerNode.dataset.state;\n if (state) {\n const page = document.getElementById('page');\n page.classList.add(state);\n }\n\n if (isSmall()) {\n getBackdrop().then(backdrop => {\n backdrop.show();\n\n const pageWrapper = document.getElementById('page-wrapper');\n pageWrapper.style.overflow = 'hidden';\n return backdrop;\n })\n .catch();\n }\n\n // Show close button once the drawer is fully opened.\n const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);\n if (focusOnCloseButton && closeButton) {\n disableButtonTooltip(closeButton, true);\n }\n setTimeout(() => {\n closeButton.classList.toggle('hidden', false);\n if (focusOnCloseButton) {\n closeButton.focus();\n }\n pendingPromise.resolve();\n }, 300);\n\n this.dispatchEvent(Drawers.eventTypes.drawerShown);\n }\n\n /**\n * Close the drawer.\n */\n closeDrawer() {\n\n const pendingPromise = new Pending('theme_boost/drawers:close');\n\n const hideEvent = this.dispatchEvent(Drawers.eventTypes.drawerHide, true);\n if (hideEvent.defaultPrevented) {\n return;\n }\n\n // Hide close button while the drawer is hiding to prevent glitchy effects.\n const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);\n closeButton?.classList.toggle('hidden', true);\n // Remove the close button tooltip if visible.\n if (closeButton.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(closeButton)?.tooltip('hide');\n }\n\n const preference = this.drawerNode.dataset.preference;\n if (preference) {\n M.util.set_user_preference(preference, false);\n }\n\n const state = this.drawerNode.dataset.state;\n if (state) {\n const page = document.getElementById('page');\n page.classList.remove(state);\n }\n\n Aria.hide(this.drawerNode);\n this.drawerNode.classList.remove('show');\n\n getBackdrop().then(backdrop => {\n backdrop.hide();\n\n if (isSmall()) {\n const pageWrapper = document.getElementById('page-wrapper');\n pageWrapper.style.overflow = 'auto';\n }\n return backdrop;\n })\n .catch();\n\n // Move focus to the open drawer (or toggler) button once the drawer is hidden.\n let openButton = getDrawerOpenButton(this.drawerNode.id);\n if (openButton) {\n disableButtonTooltip(openButton, true);\n }\n setTimeout(() => {\n if (openButton) {\n openButton.focus();\n }\n pendingPromise.resolve();\n }, 300);\n\n this.dispatchEvent(Drawers.eventTypes.drawerHidden);\n }\n\n /**\n * Toggle visibility of the drawer.\n */\n toggleVisibility() {\n if (this.drawerNode.classList.contains('show')) {\n this.closeDrawer();\n } else {\n this.openDrawer();\n }\n }\n\n /**\n * Close all drawers.\n */\n static closeAllDrawers() {\n drawerMap.forEach(drawerInstance => {\n drawerInstance.closeDrawer();\n });\n }\n\n /**\n * Close all drawers except for the specified drawer.\n *\n * @param {module:theme_boost/drawers} comparisonInstance\n */\n static closeOtherDrawers(comparisonInstance) {\n drawerMap.forEach(drawerInstance => {\n if (drawerInstance === comparisonInstance) {\n return;\n }\n\n drawerInstance.closeDrawer();\n });\n }\n}\n\n/**\n * Activate the scroller helper for the drawer layout.\n *\n * @private\n */\nconst scroller = () => {\n const body = document.querySelector('body');\n const drawerLayout = document.querySelector(SELECTORS.CONTAINER);\n if (drawerLayout) {\n drawerLayout.addEventListener(\"scroll\", () => {\n if (drawerLayout.scrollTop >= window.innerHeight) {\n body.classList.add(CLASSES.SCROLLED);\n } else {\n body.classList.remove(CLASSES.SCROLLED);\n }\n });\n }\n};\n\n/**\n * Set the last used attribute for the last used toggle button for a drawer.\n *\n * @param {object} toggleButton The clicked button.\n */\nconst setLastUsedToggle = (toggleButton) => {\n if (toggleButton.dataset.target) {\n document.querySelectorAll(`${SELECTORS.BUTTONS}[data-target=\"${toggleButton.dataset.target}\"]`)\n .forEach(btn => {\n btn.dataset.lastused = false;\n });\n toggleButton.dataset.lastused = true;\n }\n};\n\n/**\n * Set the focus to the last used button to open this drawer.\n * @param {string} target The drawer target.\n */\nconst focusLastUsedToggle = (target) => {\n const lastUsedButton = document.querySelector(`${SELECTORS.BUTTONS}[data-target=\"${target}\"][data-lastused=\"true\"`);\n if (lastUsedButton) {\n lastUsedButton.focus();\n }\n};\n\n/**\n * Register the event listeners for the drawer.\n *\n * @private\n */\nconst registerListeners = () => {\n // Listen for show/hide events.\n document.addEventListener('click', e => {\n const toggleButton = e.target.closest(SELECTORS.TOGGLEBTN);\n if (toggleButton && toggleButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(toggleButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n setLastUsedToggle(toggleButton);\n\n drawerInstance.toggleVisibility();\n }\n\n const openDrawerButton = e.target.closest(SELECTORS.OPENBTN);\n if (openDrawerButton && openDrawerButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(openDrawerButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n setLastUsedToggle(toggleButton);\n\n drawerInstance.openDrawer();\n }\n\n const closeDrawerButton = e.target.closest(SELECTORS.CLOSEBTN);\n if (closeDrawerButton && closeDrawerButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(closeDrawerButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n\n drawerInstance.closeDrawer();\n focusLastUsedToggle(closeDrawerButton.dataset.target);\n }\n });\n\n // Close drawer when another drawer opens.\n document.addEventListener(Drawers.eventTypes.drawerShow, e => {\n if (isLarge()) {\n return;\n }\n Drawers.closeOtherDrawers(e.detail.drawerInstance);\n });\n\n // Tooglers and openers blur listeners.\n const btnSelector = `${SELECTORS.TOGGLEBTN}, ${SELECTORS.OPENBTN}, ${SELECTORS.CLOSEBTN}`;\n document.addEventListener('focusout', (e) => {\n const button = e.target.closest(btnSelector);\n if (button?.dataset.restoreTooltipOnBlur !== undefined) {\n enableButtonTooltip(button);\n }\n });\n\n const closeOnResizeListener = () => {\n if (isSmall()) {\n let anyOpen = false;\n drawerMap.forEach(drawerInstance => {\n disableDrawerTooltips(drawerInstance.drawerNode);\n if (drawerInstance.isOpen) {\n if (drawerInstance.closeOnResize) {\n drawerInstance.closeDrawer();\n } else {\n anyOpen = true;\n }\n }\n });\n\n if (anyOpen) {\n getBackdrop().then(backdrop => backdrop.show()).catch();\n }\n } else {\n drawerMap.forEach(drawerInstance => {\n enableDrawerTooltips(drawerInstance.drawerNode);\n });\n getBackdrop().then(backdrop => backdrop.hide()).catch();\n }\n };\n\n window.addEventListener('resize', debounce(closeOnResizeListener, 400));\n};\n\nscroller();\nregisterListeners();\n\nconst drawers = document.querySelectorAll(SELECTORS.DRAWERS);\ndrawers.forEach(drawerNode => Drawers.getDrawerInstanceForNode(drawerNode));\n"],"file":"drawers.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/drawers.js"],"names":["backdropPromise","drawerMap","Map","SELECTORS","BUTTONS","CLOSEBTN","OPENBTN","TOGGLEBTN","DRAWERS","CONTAINER","DRAWERCONTENT","CLASSES","SCROLLED","SHOW","NOTINITIALISED","sizes","medium","large","getCurrentWidth","DomRect","document","body","getBoundingClientRect","x","width","isSmall","browserWidth","isLarge","getBackdrop","Templates","render","then","html","ModalBackdrop","modalBackdrop","getAttachmentPoint","get","addEventListener","e","preventDefault","Drawers","closeAllDrawers","catch","getDrawerOpenButton","drawerId","openButton","querySelector","disableDrawerTooltips","drawerNode","buttons","id","forEach","button","disableButtonTooltip","enableOnBlur","hasAttribute","tooltip","setAttribute","dataset","originalTitle","disabledToggle","toggle","removeAttribute","restoreTooltipOnBlur","enableDrawerTooltips","enableButtonTooltip","addInnerScrollListener","content","classList","scrollTop","closeDrawer","focusOnOpenButton","updatePreferences","contains","openDrawer","focusOnCloseButton","forceopen","Aria","hide","set","remove","eventname","cancelable","drawerInstance","pendingPromise","Pending","showEvent","dispatchEvent","eventTypes","drawerShow","defaultPrevented","unhide","add","preference","M","util","set_user_preference","state","page","getElementById","backdrop","show","pageWrapper","style","overflow","closeButton","setTimeout","focus","resolve","drawerShown","hideEvent","drawerHide","drawerHidden","parseInt","closeOnResize","has","comparisonInstance","setLastUsedToggle","toggleButton","target","querySelectorAll","btn","lastused","focusLastUsedToggle","lastUsedButton","scroller","drawerLayout","window","innerHeight","registerListeners","closest","targetDrawer","getDrawerInstanceForNode","toggleVisibility","openDrawerButton","closeDrawerButton","closeOtherDrawers","detail","btnSelector","closeOnResizeListener","anyOpen","isOpen","drawers"],"mappings":"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","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 * Toggling the visibility of the secondary navigation on mobile.\n *\n * @module theme_boost/drawers\n * @copyright 2021 Bas Brands\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ModalBackdrop from 'core/modal_backdrop';\nimport Templates from 'core/templates';\nimport * as Aria from 'core/aria';\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {debounce} from 'core/utils';\nimport Pending from 'core/pending';\n// The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.\nimport jQuery from 'jquery';\n\nlet backdropPromise = null;\n\nconst drawerMap = new Map();\n\nconst SELECTORS = {\n BUTTONS: '[data-toggler=\"drawers\"]',\n CLOSEBTN: '[data-toggler=\"drawers\"][data-action=\"closedrawer\"]',\n OPENBTN: '[data-toggler=\"drawers\"][data-action=\"opendrawer\"]',\n TOGGLEBTN: '[data-toggler=\"drawers\"][data-action=\"toggle\"]',\n DRAWERS: '[data-region=\"fixed-drawer\"]',\n CONTAINER: '#page.drawers',\n DRAWERCONTENT: '.drawercontent',\n};\n\nconst CLASSES = {\n SCROLLED: 'scrolled',\n SHOW: 'show',\n NOTINITIALISED: 'not-initialized',\n};\n\n/**\n * Maximum sizes for breakpoints. This needs to correspond with Bootstrap\n * Breakpoints\n *\n * @private\n */\nconst sizes = {\n medium: 991,\n large: 1400\n};\n\n/**\n * Get the current body width.\n *\n * @returns {number} the current body width.\n * @private\n */\nconst getCurrentWidth = () => {\n const DomRect = document.body.getBoundingClientRect();\n return DomRect.x + DomRect.width;\n};\n\n/**\n * Check if the user uses a small size browser.\n *\n * @returns {boolean} true if the body is smaller than sizes.medium max size.\n * @private\n */\nconst isSmall = () => {\n const browserWidth = getCurrentWidth();\n return browserWidth < sizes.medium;\n};\n\n/**\n * Check if the user uses a large size browser.\n *\n * @returns {boolean} true if the body is smaller than sizes.large max size.\n * @private\n */\nconst isLarge = () => {\n const browserWidth = getCurrentWidth();\n return browserWidth >= sizes.large;\n};\n\n/**\n * Add a backdrop to the page.\n *\n * @returns {Promise} rendering of modal backdrop.\n * @private\n */\nconst getBackdrop = () => {\n if (!backdropPromise) {\n backdropPromise = Templates.render('core/modal_backdrop', {})\n .then(html => new ModalBackdrop(html))\n .then(modalBackdrop => {\n modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => {\n e.preventDefault();\n Drawers.closeAllDrawers();\n });\n return modalBackdrop;\n })\n .catch();\n }\n return backdropPromise;\n};\n\n/**\n * Get the button element to open a specific drawer.\n *\n * @param {String} drawerId the drawer element Id\n * @return {HTMLElement|undefined} the open button element\n * @private\n */\nconst getDrawerOpenButton = (drawerId) => {\n let openButton = document.querySelector(`${SELECTORS.OPENBTN}[data-target=\"${drawerId}\"]`);\n if (!openButton) {\n openButton = document.querySelector(`${SELECTORS.TOGGLEBTN}[data-target=\"${drawerId}\"]`);\n }\n return openButton;\n};\n\n/**\n * Disable drawer tooltips.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst disableDrawerTooltips = (drawerNode) => {\n const buttons = [\n drawerNode.querySelector(SELECTORS.CLOSEBTN),\n getDrawerOpenButton(drawerNode.id),\n ];\n buttons.forEach(button => {\n if (!button) {\n return;\n }\n disableButtonTooltip(button);\n });\n};\n\n/**\n * Disable the button tooltips.\n *\n * @param {HTMLElement} button the button element\n * @param {boolean} enableOnBlur if the tooltip must be re-enabled on blur.\n * @private\n */\nconst disableButtonTooltip = (button, enableOnBlur) => {\n if (button.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(button).tooltip('disable');\n button.setAttribute('title', button.dataset.originalTitle);\n } else {\n button.dataset.disabledToggle = button.dataset.toggle;\n button.removeAttribute('data-toggle');\n }\n if (enableOnBlur) {\n button.dataset.restoreTooltipOnBlur = true;\n }\n};\n\n/**\n * Enable drawer tooltips.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst enableDrawerTooltips = (drawerNode) => {\n const buttons = [\n drawerNode.querySelector(SELECTORS.CLOSEBTN),\n getDrawerOpenButton(drawerNode.id),\n ];\n buttons.forEach(button => {\n if (!button) {\n return;\n }\n enableButtonTooltip(button);\n });\n};\n\n/**\n * Enable the button tooltips.\n *\n * @param {HTMLElement} button the button element\n * @private\n */\nconst enableButtonTooltip = (button) => {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n if (button.hasAttribute('data-original-title')) {\n jQuery(button).tooltip('enable');\n } else if (button.dataset.disabledToggle) {\n button.dataset.toggle = button.dataset.disabledToggle;\n jQuery(button).tooltip();\n }\n delete button.dataset.restoreTooltipOnBlur;\n};\n\n/**\n * Add scroll listeners to a drawer element.\n *\n * @param {HTMLElement} drawerNode the drawer main node\n * @private\n */\nconst addInnerScrollListener = (drawerNode) => {\n const content = drawerNode.querySelector(SELECTORS.DRAWERCONTENT);\n if (!content) {\n return;\n }\n content.addEventListener(\"scroll\", () => {\n drawerNode.classList.toggle(\n CLASSES.SCROLLED,\n content.scrollTop != 0\n );\n });\n};\n\n/**\n * The Drawers class is used to control on-screen drawer elements.\n *\n * It handles opening, and closing of drawer elements, as well as more detailed behaviours such as closing a drawer when\n * another drawer is opened, and supports closing a drawer when the screen is resized.\n *\n * Drawers are instantiated on page load, and can also be toggled lazily when toggling any drawer toggle, open button,\n * or close button.\n *\n * A range of show and hide events are also dispatched as detailed in the class\n * {@link module:theme_boost/drawers#eventTypes eventTypes} object.\n *\n * @example Standard usage\n *\n * // The module just needs to be included to add drawer support.\n * import 'theme_boost/drawers';\n *\n * @example Manually open or close any drawer\n *\n * import Drawers from 'theme_boost/drawers';\n *\n * const myDrawer = Drawers.getDrawerInstanceForNode(document.querySelector('.myDrawerNode');\n * myDrawer.closeDrawer();\n *\n * @example Listen to the before show event and cancel it\n *\n * import Drawers from 'theme_boost/drawers';\n *\n * document.addEventListener(Drawers.eventTypes.drawerShow, e => {\n * // The drawer which will be shown.\n * window.console.log(e.target);\n *\n * // The instance of the Drawers class for this drawer.\n * window.console.log(e.detail.drawerInstance);\n *\n * // Prevent this drawer from being shown.\n * e.preventDefault();\n * });\n *\n * @example Listen to the shown event\n *\n * document.addEventListener(Drawers.eventTypes.drawerShown, e => {\n * // The drawer which was shown.\n * window.console.log(e.target);\n *\n * // The instance of the Drawers class for this drawer.\n * window.console.log(e.detail.drawerInstance);\n * });\n */\nexport default class Drawers {\n /**\n * The underlying HTMLElement which is controlled.\n */\n drawerNode = null;\n\n constructor(drawerNode) {\n this.drawerNode = drawerNode;\n\n if (isSmall()) {\n this.closeDrawer({focusOnOpenButton: false, updatePreferences: false});\n }\n\n if (this.drawerNode.classList.contains(CLASSES.SHOW)) {\n this.openDrawer({focusOnCloseButton: false});\n } else if (this.drawerNode.dataset.forceopen == 1) {\n if (!isSmall()) {\n this.openDrawer({focusOnCloseButton: false});\n }\n } else {\n Aria.hide(this.drawerNode);\n }\n\n // Disable tooltips in small screens.\n if (isSmall()) {\n disableDrawerTooltips(this.drawerNode);\n }\n\n addInnerScrollListener(this.drawerNode);\n\n drawerMap.set(drawerNode, this);\n\n drawerNode.classList.remove(CLASSES.NOTINITIALISED);\n }\n\n /**\n * Whether the drawer is open.\n *\n * @returns {boolean}\n */\n get isOpen() {\n return this.drawerNode.classList.contains(CLASSES.SHOW);\n }\n\n /**\n * Whether the drawer should close when the window is resized\n *\n * @returns {boolean}\n */\n get closeOnResize() {\n return !!parseInt(this.drawerNode.dataset.closeOnResize);\n }\n\n /**\n * The list of event types.\n *\n * @static\n * @property {String} drawerShow See {@link event:theme_boost/drawers:show}\n * @property {String} drawerShown See {@link event:theme_boost/drawers:shown}\n * @property {String} drawerHide See {@link event:theme_boost/drawers:hide}\n * @property {String} drawerHidden See {@link event:theme_boost/drawers:hidden}\n */\n static eventTypes = {\n /**\n * An event triggered before a drawer is shown.\n *\n * @event theme_boost/drawers:show\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that will be opened.\n */\n drawerShow: 'theme_boost/drawers:show',\n\n /**\n * An event triggered after a drawer is shown.\n *\n * @event theme_boost/drawers:shown\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that was be opened.\n */\n drawerShown: 'theme_boost/drawers:shown',\n\n /**\n * An event triggered before a drawer is hidden.\n *\n * @event theme_boost/drawers:hide\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that will be hidden.\n */\n drawerHide: 'theme_boost/drawers:hide',\n\n /**\n * An event triggered after a drawer is hidden.\n *\n * @event theme_boost/drawers:hidden\n * @type {CustomEvent}\n * @property {HTMLElement} target The drawer that was be hidden.\n */\n drawerHidden: 'theme_boost/drawers:hidden',\n };\n\n\n /**\n * Get the drawer instance for the specified node\n *\n * @param {HTMLElement} drawerNode\n * @returns {module:theme_boost/drawers}\n */\n static getDrawerInstanceForNode(drawerNode) {\n if (!drawerMap.has(drawerNode)) {\n new Drawers(drawerNode);\n }\n\n return drawerMap.get(drawerNode);\n }\n\n /**\n * Dispatch a drawer event.\n *\n * @param {string} eventname the event name\n * @param {boolean} cancelable if the event is cancelable\n * @returns {CustomEvent} the resulting custom event\n */\n dispatchEvent(eventname, cancelable = false) {\n return dispatchEvent(\n eventname,\n {\n drawerInstance: this,\n },\n this.drawerNode,\n {\n cancelable,\n }\n );\n }\n\n /**\n * Open the drawer.\n *\n * By default, openDrawer sets the page focus to the close drawer button. However, when a drawer is open at page\n * load, this represents an accessibility problem as the initial focus changes without any user interaction. The\n * focusOnCloseButton parameter can be set to false to prevent this behaviour.\n *\n * @param {object} args\n * @param {boolean} [args.focusOnCloseButton=true] Whether to alter page focus when opening the drawer\n */\n openDrawer({focusOnCloseButton = true} = {}) {\n\n const pendingPromise = new Pending('theme_boost/drawers:open');\n const showEvent = this.dispatchEvent(Drawers.eventTypes.drawerShow, true);\n if (showEvent.defaultPrevented) {\n return;\n }\n\n // Hide close button while the drawer is showing to prevent glitchy effects.\n this.drawerNode.querySelector(SELECTORS.CLOSEBTN)?.classList.toggle('hidden', true);\n\n // Remove open tooltip if still visible.\n let openButton = getDrawerOpenButton(this.drawerNode.id);\n if (openButton && openButton.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(openButton)?.tooltip('hide');\n }\n\n Aria.unhide(this.drawerNode);\n this.drawerNode.classList.add(CLASSES.SHOW);\n\n const preference = this.drawerNode.dataset.preference;\n if (preference && !isSmall() && (this.drawerNode.dataset.forceopen != 1)) {\n M.util.set_user_preference(preference, true);\n }\n\n const state = this.drawerNode.dataset.state;\n if (state) {\n const page = document.getElementById('page');\n page.classList.add(state);\n }\n\n if (isSmall()) {\n getBackdrop().then(backdrop => {\n backdrop.show();\n\n const pageWrapper = document.getElementById('page-wrapper');\n pageWrapper.style.overflow = 'hidden';\n return backdrop;\n })\n .catch();\n }\n\n // Show close button once the drawer is fully opened.\n const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);\n if (focusOnCloseButton && closeButton) {\n disableButtonTooltip(closeButton, true);\n }\n setTimeout(() => {\n closeButton.classList.toggle('hidden', false);\n if (focusOnCloseButton) {\n closeButton.focus();\n }\n pendingPromise.resolve();\n }, 300);\n\n this.dispatchEvent(Drawers.eventTypes.drawerShown);\n }\n\n /**\n * Close the drawer.\n *\n * @param {object} args\n * @param {boolean} [args.focusOnOpenButton=true] Whether to alter page focus when opening the drawer\n * @param {boolean} [args.updatePreferences=true] Whether to update the user prewference\n */\n closeDrawer({focusOnOpenButton = true, updatePreferences = true} = {}) {\n\n const pendingPromise = new Pending('theme_boost/drawers:close');\n\n const hideEvent = this.dispatchEvent(Drawers.eventTypes.drawerHide, true);\n if (hideEvent.defaultPrevented) {\n return;\n }\n\n // Hide close button while the drawer is hiding to prevent glitchy effects.\n const closeButton = this.drawerNode.querySelector(SELECTORS.CLOSEBTN);\n closeButton?.classList.toggle('hidden', true);\n // Remove the close button tooltip if visible.\n if (closeButton.hasAttribute('data-original-title')) {\n // The jQuery is still used in Boostrap 4. It can we removed when MDL-71979 is integrated.\n jQuery(closeButton)?.tooltip('hide');\n }\n\n const preference = this.drawerNode.dataset.preference;\n if (preference && updatePreferences && !isSmall()) {\n M.util.set_user_preference(preference, false);\n }\n\n const state = this.drawerNode.dataset.state;\n if (state) {\n const page = document.getElementById('page');\n page.classList.remove(state);\n }\n\n Aria.hide(this.drawerNode);\n this.drawerNode.classList.remove(CLASSES.SHOW);\n\n getBackdrop().then(backdrop => {\n backdrop.hide();\n\n if (isSmall()) {\n const pageWrapper = document.getElementById('page-wrapper');\n pageWrapper.style.overflow = 'auto';\n }\n return backdrop;\n })\n .catch();\n\n // Move focus to the open drawer (or toggler) button once the drawer is hidden.\n let openButton = getDrawerOpenButton(this.drawerNode.id);\n if (openButton) {\n disableButtonTooltip(openButton, true);\n }\n setTimeout(() => {\n if (openButton && focusOnOpenButton) {\n openButton.focus();\n }\n pendingPromise.resolve();\n }, 300);\n\n this.dispatchEvent(Drawers.eventTypes.drawerHidden);\n }\n\n /**\n * Toggle visibility of the drawer.\n */\n toggleVisibility() {\n if (this.drawerNode.classList.contains(CLASSES.SHOW)) {\n this.closeDrawer();\n } else {\n this.openDrawer();\n }\n }\n\n /**\n * Close all drawers.\n */\n static closeAllDrawers() {\n drawerMap.forEach(drawerInstance => {\n drawerInstance.closeDrawer();\n });\n }\n\n /**\n * Close all drawers except for the specified drawer.\n *\n * @param {module:theme_boost/drawers} comparisonInstance\n */\n static closeOtherDrawers(comparisonInstance) {\n drawerMap.forEach(drawerInstance => {\n if (drawerInstance === comparisonInstance) {\n return;\n }\n\n drawerInstance.closeDrawer();\n });\n }\n}\n\n/**\n * Activate the scroller helper for the drawer layout.\n *\n * @private\n */\nconst scroller = () => {\n const body = document.querySelector('body');\n const drawerLayout = document.querySelector(SELECTORS.CONTAINER);\n if (drawerLayout) {\n drawerLayout.addEventListener(\"scroll\", () => {\n if (drawerLayout.scrollTop >= window.innerHeight) {\n body.classList.add(CLASSES.SCROLLED);\n } else {\n body.classList.remove(CLASSES.SCROLLED);\n }\n });\n }\n};\n\n/**\n * Set the last used attribute for the last used toggle button for a drawer.\n *\n * @param {object} toggleButton The clicked button.\n */\nconst setLastUsedToggle = (toggleButton) => {\n if (toggleButton.dataset.target) {\n document.querySelectorAll(`${SELECTORS.BUTTONS}[data-target=\"${toggleButton.dataset.target}\"]`)\n .forEach(btn => {\n btn.dataset.lastused = false;\n });\n toggleButton.dataset.lastused = true;\n }\n};\n\n/**\n * Set the focus to the last used button to open this drawer.\n * @param {string} target The drawer target.\n */\nconst focusLastUsedToggle = (target) => {\n const lastUsedButton = document.querySelector(`${SELECTORS.BUTTONS}[data-target=\"${target}\"][data-lastused=\"true\"`);\n if (lastUsedButton) {\n lastUsedButton.focus();\n }\n};\n\n/**\n * Register the event listeners for the drawer.\n *\n * @private\n */\nconst registerListeners = () => {\n // Listen for show/hide events.\n document.addEventListener('click', e => {\n const toggleButton = e.target.closest(SELECTORS.TOGGLEBTN);\n if (toggleButton && toggleButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(toggleButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n setLastUsedToggle(toggleButton);\n\n drawerInstance.toggleVisibility();\n }\n\n const openDrawerButton = e.target.closest(SELECTORS.OPENBTN);\n if (openDrawerButton && openDrawerButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(openDrawerButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n setLastUsedToggle(toggleButton);\n\n drawerInstance.openDrawer();\n }\n\n const closeDrawerButton = e.target.closest(SELECTORS.CLOSEBTN);\n if (closeDrawerButton && closeDrawerButton.dataset.target) {\n e.preventDefault();\n const targetDrawer = document.getElementById(closeDrawerButton.dataset.target);\n const drawerInstance = Drawers.getDrawerInstanceForNode(targetDrawer);\n\n drawerInstance.closeDrawer();\n focusLastUsedToggle(closeDrawerButton.dataset.target);\n }\n });\n\n // Close drawer when another drawer opens.\n document.addEventListener(Drawers.eventTypes.drawerShow, e => {\n if (isLarge()) {\n return;\n }\n Drawers.closeOtherDrawers(e.detail.drawerInstance);\n });\n\n // Tooglers and openers blur listeners.\n const btnSelector = `${SELECTORS.TOGGLEBTN}, ${SELECTORS.OPENBTN}, ${SELECTORS.CLOSEBTN}`;\n document.addEventListener('focusout', (e) => {\n const button = e.target.closest(btnSelector);\n if (button?.dataset.restoreTooltipOnBlur !== undefined) {\n enableButtonTooltip(button);\n }\n });\n\n const closeOnResizeListener = () => {\n if (isSmall()) {\n let anyOpen = false;\n drawerMap.forEach(drawerInstance => {\n disableDrawerTooltips(drawerInstance.drawerNode);\n if (drawerInstance.isOpen) {\n if (drawerInstance.closeOnResize) {\n drawerInstance.closeDrawer();\n } else {\n anyOpen = true;\n }\n }\n });\n\n if (anyOpen) {\n getBackdrop().then(backdrop => backdrop.show()).catch();\n }\n } else {\n drawerMap.forEach(drawerInstance => {\n enableDrawerTooltips(drawerInstance.drawerNode);\n });\n getBackdrop().then(backdrop => backdrop.hide()).catch();\n }\n };\n\n window.addEventListener('resize', debounce(closeOnResizeListener, 400));\n};\n\nscroller();\nregisterListeners();\n\nconst drawers = document.querySelectorAll(SELECTORS.DRAWERS);\ndrawers.forEach(drawerNode => Drawers.getDrawerInstanceForNode(drawerNode));\n"],"file":"drawers.min.js"} \ No newline at end of file diff --git a/theme/boost/amd/src/drawers.js b/theme/boost/amd/src/drawers.js index 54e1b712e80..6e83501ad32 100644 --- a/theme/boost/amd/src/drawers.js +++ b/theme/boost/amd/src/drawers.js @@ -45,6 +45,8 @@ const SELECTORS = { const CLASSES = { SCROLLED: 'scrolled', + SHOW: 'show', + NOTINITIALISED: 'not-initialized', }; /** @@ -281,7 +283,11 @@ export default class Drawers { constructor(drawerNode) { this.drawerNode = drawerNode; - if (this.drawerNode.classList.contains('show')) { + if (isSmall()) { + this.closeDrawer({focusOnOpenButton: false, updatePreferences: false}); + } + + if (this.drawerNode.classList.contains(CLASSES.SHOW)) { this.openDrawer({focusOnCloseButton: false}); } else if (this.drawerNode.dataset.forceopen == 1) { if (!isSmall()) { @@ -299,6 +305,8 @@ export default class Drawers { addInnerScrollListener(this.drawerNode); drawerMap.set(drawerNode, this); + + drawerNode.classList.remove(CLASSES.NOTINITIALISED); } /** @@ -307,7 +315,7 @@ export default class Drawers { * @returns {boolean} */ get isOpen() { - return this.drawerNode.classList.contains('show'); + return this.drawerNode.classList.contains(CLASSES.SHOW); } /** @@ -430,7 +438,7 @@ export default class Drawers { } Aria.unhide(this.drawerNode); - this.drawerNode.classList.add('show'); + this.drawerNode.classList.add(CLASSES.SHOW); const preference = this.drawerNode.dataset.preference; if (preference && !isSmall() && (this.drawerNode.dataset.forceopen != 1)) { @@ -472,8 +480,12 @@ export default class Drawers { /** * Close the drawer. + * + * @param {object} args + * @param {boolean} [args.focusOnOpenButton=true] Whether to alter page focus when opening the drawer + * @param {boolean} [args.updatePreferences=true] Whether to update the user prewference */ - closeDrawer() { + closeDrawer({focusOnOpenButton = true, updatePreferences = true} = {}) { const pendingPromise = new Pending('theme_boost/drawers:close'); @@ -492,7 +504,7 @@ export default class Drawers { } const preference = this.drawerNode.dataset.preference; - if (preference) { + if (preference && updatePreferences && !isSmall()) { M.util.set_user_preference(preference, false); } @@ -503,7 +515,7 @@ export default class Drawers { } Aria.hide(this.drawerNode); - this.drawerNode.classList.remove('show'); + this.drawerNode.classList.remove(CLASSES.SHOW); getBackdrop().then(backdrop => { backdrop.hide(); @@ -522,7 +534,7 @@ export default class Drawers { disableButtonTooltip(openButton, true); } setTimeout(() => { - if (openButton) { + if (openButton && focusOnOpenButton) { openButton.focus(); } pendingPromise.resolve(); @@ -535,7 +547,7 @@ export default class Drawers { * Toggle visibility of the drawer. */ toggleVisibility() { - if (this.drawerNode.classList.contains('show')) { + if (this.drawerNode.classList.contains(CLASSES.SHOW)) { this.closeDrawer(); } else { this.openDrawer(); diff --git a/theme/boost/layout/drawers.php b/theme/boost/layout/drawers.php index 0e6c2b0d015..19bb4aa8c7b 100644 --- a/theme/boost/layout/drawers.php +++ b/theme/boost/layout/drawers.php @@ -35,7 +35,7 @@ user_preference_allow_ajax_update('drawer-open-index', PARAM_BOOL); user_preference_allow_ajax_update('drawer-open-block', PARAM_BOOL); if (isloggedin()) { - $courseindexopen = (get_user_preferences('drawer-open-index') == true); + $courseindexopen = (get_user_preferences('drawer-open-index', true) == true); $blockdraweropen = (get_user_preferences('drawer-open-block') == true); } else { $courseindexopen = false; diff --git a/theme/boost/scss/moodle/drawer.scss b/theme/boost/scss/moodle/drawer.scss index 9d7c5300f08..f96cdeb9d22 100644 --- a/theme/boost/scss/moodle/drawer.scss +++ b/theme/boost/scss/moodle/drawer.scss @@ -171,6 +171,10 @@ $right-drawer-width: 320px; position: fixed; height: 100vh; top: 0; + + &.not-initialized { + display: none; + } } @mixin drawertypes() { @@ -220,6 +224,10 @@ $right-drawer-width: 320px; @include media-breakpoint-up(lg) { .drawer { z-index: inherit; + + &.not-initialized { + display: block; + } } } diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index 558075962b7..7487a9b5281 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -14928,6 +14928,8 @@ body.drawer-ease { @media (prefers-reduced-motion: reduce) { .drawer { transition: none; } } + .drawer.not-initialized { + display: none; } .drawer.drawer-right { width: 315px; max-width: 315px; @@ -14953,7 +14955,9 @@ body.drawer-ease { @media (min-width: 992px) { .drawer { - z-index: inherit; } } + z-index: inherit; } + .drawer.not-initialized { + display: block; } } .drawer-md, .drawer-sm { @@ -14982,6 +14986,8 @@ body.drawer-ease { transition: none; } } @media (max-width: 991.98px) { + .drawer-md.not-initialized { + display: none; } .drawer-md.drawer-right { width: 315px; max-width: 315px; @@ -15019,6 +15025,8 @@ body.drawer-ease { transition: none; } } @media (max-width: 767.98px) { + .drawer-sm.not-initialized { + display: none; } .drawer-sm.drawer-right { width: 315px; max-width: 315px; diff --git a/theme/boost/templates/drawer.mustache b/theme/boost/templates/drawer.mustache index 4766cfcb350..2bbb4791e62 100644 --- a/theme/boost/templates/drawer.mustache +++ b/theme/boost/templates/drawer.mustache @@ -27,7 +27,7 @@ } }}