{"version":3,"file":"moremenu.min.js","sources":["https:\/\/lms.mgt.sjp.ac.lk\/lib\/amd\/src\/moremenu.js"],"sourcesContent":["\/\/ This file is part of Moodle - http:\/\/moodle.org\/\n\/\/\n\/\/ Moodle is free software: you can redistribute it and\/or modify\n\/\/ it under the terms of the GNU General Public License as published by\n\/\/ the Free Software Foundation, either version 3 of the License, or\n\/\/ (at your option) any later version.\n\/\/\n\/\/ Moodle is distributed in the hope that it will be useful,\n\/\/ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\/\/ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\/\/ GNU General Public License for more details.\n\/\/\n\/\/ You should have received a copy of the GNU General Public License\n\/\/ along with Moodle. If not, see .\n\n\/**\n * 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\nlet isTabListMenu = false;\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 dropdownToggle.setAttribute('tabindex', '0');\n navLink.setAttribute('tabindex', '-1'); \/\/ So that we don't have a single tabbable menu item.\n \/\/ Remove aria-selected if the more menu is rendered as a tab list.\n if (isTabListMenu) {\n navLink.removeAttribute('aria-selected');\n }\n navLink.setAttribute('aria-current', 'true');\n }\n\n \/\/ This will become a menu item instead of a tab.\n navLink.setAttribute('role', 'menuitem');\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 \/\/ If the more menu is rendered as a tab list,\n \/\/ this will become a tab instead of a menuitem when moved out of the more menu dropdown.\n if (isTabListMenu) {\n navLink.setAttribute('role', 'tab');\n }\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 dropdownToggle.setAttribute('tabindex', '-1');\n navLink.setAttribute('tabindex', '0');\n if (isTabListMenu) {\n \/\/ Replace aria selection state when necessary.\n navLink.removeAttribute('aria-current');\n navLink.setAttribute('aria-selected', 'true');\n }\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 isTabListMenu = menu.getAttribute('role') === 'tablist';\n\n \/\/ Select the first menu item if there's nothing initially selected.\n const hash = window.location.hash;\n if (!hash) {\n const itemRole = isTabListMenu ? 'tab' : 'menuitem';\n const menuListItem = menu.firstElementChild;\n const roleSelector = `[role=${itemRole}]`;\n const menuItem = menuListItem.querySelector(roleSelector);\n const ariaAttribute = isTabListMenu ? 'aria-selected' : 'aria-current';\n if (!menu.querySelector(`[${ariaAttribute}='true']`)) {\n menuItem.setAttribute(ariaAttribute, 'true');\n menuItem.setAttribute('tabindex', '0');\n }\n }\n\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"],"names":["Selectors","moredropdown","morebutton","dropdownitem","dropdownmoremenu","hidden","active","nav","navlink","observed","menu","dropdowntoggle","isTabListMenu","autoCollapse","maxHeight","parentNode","offsetHeight","moreDropdown","querySelector","moreButton","classList","remove","Array","from","children","reverse","forEach","item","contains","lastNode","removeChild","moveIntoMoreDropdown","dataset","forceintomoremenu","moveOutOfMoreDropdown","length","add","navNode","prepend","dropdownToggle","navLink","setAttribute","removeAttribute","append","insertBefore","getAttribute","window","location","hash","itemRole","menuListItem","firstElementChild","roleSelector","menuItem","ariaAttribute","addEventListener","toggledropdown","e","innerMenu","target","toggle","stopPropagation","on","querySelectorAll","dropdown","removeEventListener"],"mappings":"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"}