From 3910c41813e9f435435da4ba2006b5a2176c62bf Mon Sep 17 00:00:00 2001 From: Mihail Geshoski Date: Wed, 13 Oct 2021 16:32:25 +0800 Subject: [PATCH] MDL-72530 navigation: Fix the auto collapse in the more menu --- lib/amd/build/moremenu.min.js | 2 +- lib/amd/build/moremenu.min.js.map | 2 +- lib/amd/src/moremenu.js | 11 ++++------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/amd/build/moremenu.min.js b/lib/amd/build/moremenu.min.js index b89ccde8f03..9ea32763956 100644 --- a/lib/amd/build/moremenu.min.js +++ b/lib/amd/build/moremenu.min.js @@ -1,2 +1,2 @@ -define ("core/moremenu",["exports","jquery","core/menu_navigation"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}var f={regions:{moredropdown:"[data-region=\"moredropdown\"]",morebutton:"[data-region=\"morebutton\"]"},classes:{dropdownitem:"dropdown-item",dropdownmoremenu:"dropdownmoremenu",hidden:"d-none",active:"active",nav:"nav",navlink:"nav-link",observed:"observed"},attributes:{menu:"[role=\"menu\"]",dropdowntoggle:"[data-toggle=\"dropdown\"]"}},g=function(a){var b=a.parentNode.offsetHeight+1,c=a.querySelector(f.regions.moredropdown),d=a.querySelector(f.regions.morebutton);if(a.offsetHeight>b){d.classList.remove(f.classes.hidden);var e=Array.from(a.children).reverse();e.forEach(function(c){if(!c.classList.contains(f.classes.dropdownmoremenu)){if(a.offsetHeight>b){var d=a.removeChild(c);h(a,d,!0)}}})}else{if("children"in c){var j=Array.from(c.children);j.forEach(function(d){if(a.offsetHeightb){g(a)}}a.parentNode.classList.add(f.classes.observed)},h=function(a,b){var c=2b){d.classList.remove(f.classes.hidden);var e=Array.from(a.children).reverse();e.forEach(function(c){if(!c.classList.contains(f.classes.dropdownmoremenu)){if(a.offsetHeight>b){var d=a.removeChild(c);h(a,d,!0)}}})}else{if("children"in c){Array.from(c.children).forEach(function(d){if(a.offsetHeightb){g(a)}}a.parentNode.classList.add(f.classes.observed)},h=function(a,b){var c=2.\n\n/**\n * Moves wrapping navigation items into a more menu.\n *\n * @module core/moremenu\n * @copyright 2021 Moodle\n * @author Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport menu_navigation from \"core/menu_navigation\";\n/**\n * Moremenu selectors.\n */\nconst Selectors = {\n regions: {\n moredropdown: '[data-region=\"moredropdown\"]',\n morebutton: '[data-region=\"morebutton\"]'\n },\n classes: {\n dropdownitem: 'dropdown-item',\n dropdownmoremenu: 'dropdownmoremenu',\n hidden: 'd-none',\n active: 'active',\n nav: 'nav',\n navlink: 'nav-link',\n observed: 'observed',\n },\n attributes: {\n menu: '[role=\"menu\"]',\n dropdowntoggle: '[data-toggle=\"dropdown\"]'\n }\n};\n\n/**\n * Auto Collapse navigation items that wrap into a dropdown menu.\n *\n * @param {HTMLElement} menu The navbar container.\n */\nconst autoCollapse = menu => {\n\n const maxHeight = menu.parentNode.offsetHeight + 1;\n\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n\n // If the menu items wrap and the menu height is larger than the height of the\n // parent then start pushing navlinks into the moreDropdown.\n if (menu.offsetHeight > maxHeight) {\n\n moreButton.classList.remove(Selectors.classes.hidden);\n\n const menuNodes = Array.from(menu.children).reverse();\n menuNodes.forEach(item => {\n if (!item.classList.contains(Selectors.classes.dropdownmoremenu)) {\n // After moving the menu items into the moreDropdown check again\n // if the menu height is still larger then the height of the parent.\n if (menu.offsetHeight > maxHeight) {\n const lastNode = menu.removeChild(item);\n // Move this node into the more dropdown menu.\n moveIntoMoreDropdown(menu, lastNode, true);\n }\n }\n });\n } else {\n // If the menu height is smaller than the height of the parent, then try returning navlinks to the menu.\n\n if ('children' in moreDropdown) {\n const menuNodes = Array.from(moreDropdown.children);\n menuNodes.forEach(item => {\n // Don't move the node to the more menu if it is explicitly defined that\n // this node should be displayed in the more dropdown menu at all times.\n if (menu.offsetHeight < maxHeight && item.dataset.forceintomoremenu !== 'true') {\n const lastNode = moreDropdown.removeChild(item);\n // Move this node from the more dropdown menu into the main section of the menu.\n moveOutOfMoreDropdown(menu, lastNode);\n }\n });\n\n // If there are no more menuNodes in the dropdown we can hide the moreButton.\n if (menuNodes.length === 0) {\n moreButton.classList.add(Selectors.classes.hidden);\n }\n }\n\n if (menu.offsetHeight > maxHeight) {\n autoCollapse(menu);\n }\n }\n menu.parentNode.classList.add(Selectors.classes.observed);\n};\n\n/**\n * Move a node into the \"more\" dropdown menu.\n *\n * This method forces a given navigation node to be added and displayed within the \"more\" dropdown menu.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n * @param {HTMLElement} navNode The navigation node.\n * @param {boolean} prepend Whether to prepend or append the node to the content in the more dropdown menu.\n */\nconst moveIntoMoreDropdown = (menu, navNode, prepend = false) => {\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n const dropdownToggle = menu.querySelector(Selectors.attributes.dropdowntoggle);\n\n const navLink = navNode.querySelector('.' + Selectors.classes.navlink);\n // If there are navLinks that contain an active link in the moreDropdown\n // make the dropdownToggle in the moreButton active.\n if (navLink.classList.contains(Selectors.classes.active)) {\n dropdownToggle.classList.add(Selectors.classes.active);\n }\n\n // Change the styling of the navLink to a dropdownitem and push it into\n // the moreDropdown.\n navLink.classList.remove(Selectors.classes.navlink);\n navLink.classList.add(Selectors.classes.dropdownitem);\n if (prepend) {\n moreDropdown.prepend(navNode);\n } else {\n moreDropdown.append(navNode);\n }\n};\n\n/**\n * Move a node out of the \"more\" dropdown menu.\n *\n * This method forces a given node from the \"more\" dropdown menu to be displayed in the main section of the menu.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n * @param {HTMLElement} navNode The navigation node.\n */\nconst moveOutOfMoreDropdown = (menu, navNode) => {\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n const dropdownToggle = menu.querySelector(Selectors.attributes.dropdowntoggle);\n const navLink = navNode.querySelector('.' + Selectors.classes.dropdownitem);\n\n // Stop displaying the active state on the dropdownToggle if\n // the active navlink is removed.\n if (navLink.classList.contains(Selectors.classes.active)) {\n dropdownToggle.classList.remove(Selectors.classes.active);\n }\n navLink.classList.remove(Selectors.classes.dropdownitem);\n navLink.classList.add(Selectors.classes.navlink);\n menu.insertBefore(navNode, moreButton);\n};\n\n/**\n * Initialise the more menus.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n */\nexport default menu => {\n menu.firstElementChild.querySelector('[role=\"menuitem\"]').setAttribute('tabindex', '0');\n // Pre-populate the \"more\" dropdown menu with navigation nodes which are set to be displayed in this menu\n // by default at all times.\n if ('children' in menu) {\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n const menuNodes = Array.from(menu.children);\n menuNodes.forEach((item) => {\n if (!item.classList.contains(Selectors.classes.dropdownmoremenu) &&\n item.dataset.forceintomoremenu === 'true') {\n // Append this node into the more dropdown menu.\n moveIntoMoreDropdown(menu, item, false);\n // After adding the node into the more dropdown menu, make sure that the more dropdown menu button\n // is displayed.\n if (moreButton.classList.contains(Selectors.classes.hidden)) {\n moreButton.classList.remove(Selectors.classes.hidden);\n }\n }\n });\n }\n // Populate the more dropdown menu with additional nodes if necessary, depending on the current screen size.\n autoCollapse(menu);\n menu_navigation(menu);\n\n // When the screen size changes make sure the menu still fits.\n window.addEventListener('resize', () => {\n autoCollapse(menu);\n menu_navigation(menu);\n });\n\n const toggledropdown = e => {\n const innerMenu = e.target.parentNode.querySelector(Selectors.attributes.menu);\n if (innerMenu) {\n innerMenu.classList.toggle('show');\n }\n e.stopPropagation();\n };\n\n // If there are dropdowns in the MoreMenu, add a new\n // event listener to show the contents on click and prevent the\n // moreMenu from closing.\n $('.' + Selectors.classes.dropdownmoremenu).on('show.bs.dropdown', function() {\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n moreDropdown.querySelectorAll('.dropdown').forEach((dropdown) => {\n dropdown.removeEventListener('click', toggledropdown, true);\n dropdown.addEventListener('click', toggledropdown, true);\n });\n });\n};\n"],"file":"moremenu.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/moremenu.js"],"names":["Selectors","regions","moredropdown","morebutton","classes","dropdownitem","dropdownmoremenu","hidden","active","nav","navlink","observed","attributes","menu","dropdowntoggle","autoCollapse","maxHeight","parentNode","offsetHeight","moreDropdown","querySelector","moreButton","classList","remove","menuNodes","Array","from","children","reverse","forEach","item","contains","lastNode","removeChild","moveIntoMoreDropdown","dataset","forceintomoremenu","moveOutOfMoreDropdown","length","add","navNode","prepend","dropdownToggle","navLink","append","insertBefore","firstElementChild","setAttribute","window","addEventListener","toggledropdown","e","innerMenu","target","toggle","stopPropagation","on","querySelectorAll","dropdown","removeEventListener"],"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 * Moves wrapping navigation items into a more menu.\n *\n * @module core/moremenu\n * @copyright 2021 Moodle\n * @author Bas Brands \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport menu_navigation from \"core/menu_navigation\";\n/**\n * Moremenu selectors.\n */\nconst Selectors = {\n regions: {\n moredropdown: '[data-region=\"moredropdown\"]',\n morebutton: '[data-region=\"morebutton\"]'\n },\n classes: {\n dropdownitem: 'dropdown-item',\n dropdownmoremenu: 'dropdownmoremenu',\n hidden: 'd-none',\n active: 'active',\n nav: 'nav',\n navlink: 'nav-link',\n observed: 'observed',\n },\n attributes: {\n menu: '[role=\"menu\"]',\n dropdowntoggle: '[data-toggle=\"dropdown\"]'\n }\n};\n\n/**\n * Auto Collapse navigation items that wrap into a dropdown menu.\n *\n * @param {HTMLElement} menu The navbar container.\n */\nconst autoCollapse = menu => {\n\n const maxHeight = menu.parentNode.offsetHeight + 1;\n\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n\n // If the menu items wrap and the menu height is larger than the height of the\n // parent then start pushing navlinks into the moreDropdown.\n if (menu.offsetHeight > maxHeight) {\n moreButton.classList.remove(Selectors.classes.hidden);\n\n const menuNodes = Array.from(menu.children).reverse();\n menuNodes.forEach(item => {\n if (!item.classList.contains(Selectors.classes.dropdownmoremenu)) {\n // After moving the menu items into the moreDropdown check again\n // if the menu height is still larger then the height of the parent.\n if (menu.offsetHeight > maxHeight) {\n const lastNode = menu.removeChild(item);\n // Move this node into the more dropdown menu.\n moveIntoMoreDropdown(menu, lastNode, true);\n }\n }\n });\n } else {\n // If the menu height is smaller than the height of the parent, then try returning navlinks to the menu.\n if ('children' in moreDropdown) {\n // Iterate through the nodes within the more dropdown menu.\n Array.from(moreDropdown.children).forEach(item => {\n // Don't move the node to the more menu if it is explicitly defined that\n // this node should be displayed in the more dropdown menu at all times.\n if (menu.offsetHeight < maxHeight && item.dataset.forceintomoremenu !== 'true') {\n const lastNode = moreDropdown.removeChild(item);\n // Move this node from the more dropdown menu into the main section of the menu.\n moveOutOfMoreDropdown(menu, lastNode);\n }\n });\n // If there are no more nodes in the more dropdown menu we can hide the moreButton.\n if (Array.from(moreDropdown.children).length === 0) {\n moreButton.classList.add(Selectors.classes.hidden);\n }\n }\n\n if (menu.offsetHeight > maxHeight) {\n autoCollapse(menu);\n }\n }\n menu.parentNode.classList.add(Selectors.classes.observed);\n};\n\n/**\n * Move a node into the \"more\" dropdown menu.\n *\n * This method forces a given navigation node to be added and displayed within the \"more\" dropdown menu.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n * @param {HTMLElement} navNode The navigation node.\n * @param {boolean} prepend Whether to prepend or append the node to the content in the more dropdown menu.\n */\nconst moveIntoMoreDropdown = (menu, navNode, prepend = false) => {\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n const dropdownToggle = menu.querySelector(Selectors.attributes.dropdowntoggle);\n\n const navLink = navNode.querySelector('.' + Selectors.classes.navlink);\n // If there are navLinks that contain an active link in the moreDropdown\n // make the dropdownToggle in the moreButton active.\n if (navLink.classList.contains(Selectors.classes.active)) {\n dropdownToggle.classList.add(Selectors.classes.active);\n }\n\n // Change the styling of the navLink to a dropdownitem and push it into\n // the moreDropdown.\n navLink.classList.remove(Selectors.classes.navlink);\n navLink.classList.add(Selectors.classes.dropdownitem);\n if (prepend) {\n moreDropdown.prepend(navNode);\n } else {\n moreDropdown.append(navNode);\n }\n};\n\n/**\n * Move a node out of the \"more\" dropdown menu.\n *\n * This method forces a given node from the \"more\" dropdown menu to be displayed in the main section of the menu.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n * @param {HTMLElement} navNode The navigation node.\n */\nconst moveOutOfMoreDropdown = (menu, navNode) => {\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n const dropdownToggle = menu.querySelector(Selectors.attributes.dropdowntoggle);\n const navLink = navNode.querySelector('.' + Selectors.classes.dropdownitem);\n\n // Stop displaying the active state on the dropdownToggle if\n // the active navlink is removed.\n if (navLink.classList.contains(Selectors.classes.active)) {\n dropdownToggle.classList.remove(Selectors.classes.active);\n }\n navLink.classList.remove(Selectors.classes.dropdownitem);\n navLink.classList.add(Selectors.classes.navlink);\n menu.insertBefore(navNode, moreButton);\n};\n\n/**\n * Initialise the more menus.\n *\n * @param {HTMLElement} menu The navbar moremenu.\n */\nexport default menu => {\n menu.firstElementChild.querySelector('[role=\"menuitem\"]').setAttribute('tabindex', '0');\n // Pre-populate the \"more\" dropdown menu with navigation nodes which are set to be displayed in this menu\n // by default at all times.\n if ('children' in menu) {\n const moreButton = menu.querySelector(Selectors.regions.morebutton);\n const menuNodes = Array.from(menu.children);\n menuNodes.forEach((item) => {\n if (!item.classList.contains(Selectors.classes.dropdownmoremenu) &&\n item.dataset.forceintomoremenu === 'true') {\n // Append this node into the more dropdown menu.\n moveIntoMoreDropdown(menu, item, false);\n // After adding the node into the more dropdown menu, make sure that the more dropdown menu button\n // is displayed.\n if (moreButton.classList.contains(Selectors.classes.hidden)) {\n moreButton.classList.remove(Selectors.classes.hidden);\n }\n }\n });\n }\n // Populate the more dropdown menu with additional nodes if necessary, depending on the current screen size.\n autoCollapse(menu);\n menu_navigation(menu);\n\n // When the screen size changes make sure the menu still fits.\n window.addEventListener('resize', () => {\n autoCollapse(menu);\n menu_navigation(menu);\n });\n\n const toggledropdown = e => {\n const innerMenu = e.target.parentNode.querySelector(Selectors.attributes.menu);\n if (innerMenu) {\n innerMenu.classList.toggle('show');\n }\n e.stopPropagation();\n };\n\n // If there are dropdowns in the MoreMenu, add a new\n // event listener to show the contents on click and prevent the\n // moreMenu from closing.\n $('.' + Selectors.classes.dropdownmoremenu).on('show.bs.dropdown', function() {\n const moreDropdown = menu.querySelector(Selectors.regions.moredropdown);\n moreDropdown.querySelectorAll('.dropdown').forEach((dropdown) => {\n dropdown.removeEventListener('click', toggledropdown, true);\n dropdown.addEventListener('click', toggledropdown, true);\n });\n });\n};\n"],"file":"moremenu.min.js"} \ No newline at end of file diff --git a/lib/amd/src/moremenu.js b/lib/amd/src/moremenu.js index 2dc9e9a2367..bfcbf6679a1 100644 --- a/lib/amd/src/moremenu.js +++ b/lib/amd/src/moremenu.js @@ -62,7 +62,6 @@ const autoCollapse = menu => { // If the menu items wrap and the menu height is larger than the height of the // parent then start pushing navlinks into the moreDropdown. if (menu.offsetHeight > maxHeight) { - moreButton.classList.remove(Selectors.classes.hidden); const menuNodes = Array.from(menu.children).reverse(); @@ -79,10 +78,9 @@ const autoCollapse = menu => { }); } else { // If the menu height is smaller than the height of the parent, then try returning navlinks to the menu. - if ('children' in moreDropdown) { - const menuNodes = Array.from(moreDropdown.children); - menuNodes.forEach(item => { + // Iterate through the nodes within the more dropdown menu. + Array.from(moreDropdown.children).forEach(item => { // Don't move the node to the more menu if it is explicitly defined that // this node should be displayed in the more dropdown menu at all times. if (menu.offsetHeight < maxHeight && item.dataset.forceintomoremenu !== 'true') { @@ -91,9 +89,8 @@ const autoCollapse = menu => { moveOutOfMoreDropdown(menu, lastNode); } }); - - // If there are no more menuNodes in the dropdown we can hide the moreButton. - if (menuNodes.length === 0) { + // If there are no more nodes in the more dropdown menu we can hide the moreButton. + if (Array.from(moreDropdown.children).length === 0) { moreButton.classList.add(Selectors.classes.hidden); } }