From 48e652623d5964ba1bcbb8d74972af421fae2761 Mon Sep 17 00:00:00 2001 From: meirzamoodle Date: Tue, 12 Nov 2024 05:50:42 +0700 Subject: [PATCH] MDL-83223 core: Use capture with addEventListener to intercept events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue is that Bootstrap’s dropdown component likely stops event propagation after the first click to manage its own dropdown behavior. This prevents your click event handler from running on subsequent clicks. To fix this, we can handle the event before Bootstrap’s code stops the propagation by using capture option with addEventListener. --- lib/amd/build/popover_region_controller.min.js | 2 +- lib/amd/build/popover_region_controller.min.js.map | 2 +- lib/amd/src/popover_region_controller.js | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/amd/build/popover_region_controller.min.js b/lib/amd/build/popover_region_controller.min.js index 923128515b1..8d02b60def8 100644 --- a/lib/amd/build/popover_region_controller.min.js +++ b/lib/amd/build/popover_region_controller.min.js @@ -8,6 +8,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 3.2 */ -define("core/popover_region_controller",["jquery","core/str","core/custom_interaction_events"],(function($,str,customEvents){var SELECTORS_CONTENT=".popover-region-content",SELECTORS_CONTENT_CONTAINER=".popover-region-content-container",SELECTORS_MENU_CONTAINER=".popover-region-container",SELECTORS_MENU_TOGGLE=".popover-region-toggle",SELECTORS_CAN_RECEIVE_FOCUS='input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',PopoverRegionController=function(element){this.root=$(element),this.content=this.root.find(SELECTORS_CONTENT),this.contentContainer=this.root.find(SELECTORS_CONTENT_CONTAINER),this.menuContainer=this.root.find(SELECTORS_MENU_CONTAINER),this.menuToggle=this.root.find(SELECTORS_MENU_TOGGLE),this.isLoading=!1,this.promises={closeHandlers:$.Deferred(),navigationHandlers:$.Deferred()},this.registerBaseEventListeners()};return PopoverRegionController.prototype.events=function(){return{menuOpened:"popoverregion:menuopened",menuClosed:"popoverregion:menuclosed",startLoading:"popoverregion:startLoading",stopLoading:"popoverregion:stopLoading"}},PopoverRegionController.prototype.getContentContainer=function(){return this.contentContainer},PopoverRegionController.prototype.getContent=function(){return this.content},PopoverRegionController.prototype.isMenuOpen=function(){return!this.root.hasClass("collapsed")},PopoverRegionController.prototype.toggleMenu=function(){this.isMenuOpen()?this.closeMenu():this.openMenu()},PopoverRegionController.prototype.closeMenu=function(){this.isMenuOpen()&&(this.root.addClass("collapsed"),this.menuContainer.attr("aria-expanded","false"),this.menuContainer.attr("aria-hidden","true"),this.updateButtonAriaLabel(),this.updateFocusItemTabIndex(),this.root.trigger(this.events().menuClosed))},PopoverRegionController.prototype.openMenu=function(){this.isMenuOpen()||(this.root.removeClass("collapsed"),this.menuContainer.attr("aria-expanded","true"),this.menuContainer.attr("aria-hidden","false"),this.updateButtonAriaLabel(),this.updateFocusItemTabIndex(),this.promises.closeHandlers.resolve(),this.promises.navigationHandlers.resolve(),this.root.trigger(this.events().menuOpened))},PopoverRegionController.prototype.updateButtonAriaLabel=function(){this.isMenuOpen()?str.get_string("hidepopoverwindow").done(function(string){this.menuToggle.attr("aria-label",string)}.bind(this)):str.get_string("showpopoverwindow").done(function(string){this.menuToggle.attr("aria-label",string)}.bind(this))},PopoverRegionController.prototype.startLoading=function(){this.isLoading=!0,this.getContentContainer().addClass("loading"),this.getContentContainer().attr("aria-busy","true"),this.root.trigger(this.events().startLoading)},PopoverRegionController.prototype.stopLoading=function(){this.isLoading=!1,this.getContentContainer().removeClass("loading"),this.getContentContainer().attr("aria-busy","false"),this.root.trigger(this.events().stopLoading)},PopoverRegionController.prototype.focusMenuToggle=function(){this.menuToggle.focus()},PopoverRegionController.prototype.contentItemHasFocus=function(){return this.getContentItemWithFocus().length>0},PopoverRegionController.prototype.getContentItemWithFocus=function(){var currentFocus=$(document.activeElement),items=this.getContent().children(),currentItem=items.filter(currentFocus);return currentItem.length||(currentItem=items.has(currentFocus)),currentItem},PopoverRegionController.prototype.focusContentItem=function(item){item.is(SELECTORS_CAN_RECEIVE_FOCUS)?item.focus():item.find(SELECTORS_CAN_RECEIVE_FOCUS).first().focus()},PopoverRegionController.prototype.focusFirstContentItem=function(){this.focusContentItem(this.getContent().children().first())},PopoverRegionController.prototype.focusLastContentItem=function(){this.focusContentItem(this.getContent().children().last())},PopoverRegionController.prototype.focusNextContentItem=function(){var currentItem=this.getContentItemWithFocus();currentItem.length&¤tItem.next()&&this.focusContentItem(currentItem.next())},PopoverRegionController.prototype.focusPreviousContentItem=function(){var currentItem=this.getContentItemWithFocus();currentItem.length&¤tItem.prev()&&this.focusContentItem(currentItem.prev())},PopoverRegionController.prototype.registerBaseEventListeners=function(){customEvents.define(this.root,[customEvents.events.activate,customEvents.events.escape]),this.root.on(customEvents.events.activate,SELECTORS_MENU_TOGGLE,function(){this.toggleMenu()}.bind(this)),this.promises.closeHandlers.done(function(){this.root.on(customEvents.events.escape,function(){this.closeMenu(),this.focusMenuToggle()}.bind(this)),$("html").click(function(e){var target=$(e.target);this.root.is(target)||this.root.has(target).length||this.closeMenu()}.bind(this)),customEvents.define(this.getContentContainer(),[customEvents.events.scrollBottom])}.bind(this))},PopoverRegionController.prototype.registerListNavigationEventListeners=function(){customEvents.define(this.root,[customEvents.events.down]),this.root.on(customEvents.events.down,function(e,data){this.isMenuOpen()?this.contentItemHasFocus()?this.focusNextContentItem():this.focusFirstContentItem():(this.openMenu(),this.focusFirstContentItem()),data.originalEvent.preventDefault()}.bind(this)),this.promises.navigationHandlers.done(function(){customEvents.define(this.root,[customEvents.events.up,customEvents.events.home,customEvents.events.end]),this.root.on(customEvents.events.up,function(e,data){this.focusPreviousContentItem(),data.originalEvent.preventDefault()}.bind(this)),this.root.on(customEvents.events.home,function(e,data){this.focusFirstContentItem(),data.originalEvent.preventDefault()}.bind(this)),this.root.on(customEvents.events.end,function(e,data){this.focusLastContentItem(),data.originalEvent.preventDefault()}.bind(this))}.bind(this))},PopoverRegionController.prototype.updateFocusItemTabIndex=function(){this.isMenuOpen()?this.menuContainer.find(SELECTORS_CAN_RECEIVE_FOCUS).removeAttr("tabindex"):this.menuContainer.find(SELECTORS_CAN_RECEIVE_FOCUS).attr("tabindex","-1")},PopoverRegionController})); +define("core/popover_region_controller",["jquery","core/str","core/custom_interaction_events"],(function($,str,customEvents){var SELECTORS_CONTENT=".popover-region-content",SELECTORS_CONTENT_CONTAINER=".popover-region-content-container",SELECTORS_MENU_CONTAINER=".popover-region-container",SELECTORS_MENU_TOGGLE=".popover-region-toggle",SELECTORS_CAN_RECEIVE_FOCUS='input:not([type="hidden"]), a[href], button, textarea, select, [tabindex]',PopoverRegionController=function(element){this.root=$(element),this.content=this.root.find(SELECTORS_CONTENT),this.contentContainer=this.root.find(SELECTORS_CONTENT_CONTAINER),this.menuContainer=this.root.find(SELECTORS_MENU_CONTAINER),this.menuToggle=this.root.find(SELECTORS_MENU_TOGGLE),this.isLoading=!1,this.promises={closeHandlers:$.Deferred(),navigationHandlers:$.Deferred()},this.registerBaseEventListeners()};return PopoverRegionController.prototype.events=function(){return{menuOpened:"popoverregion:menuopened",menuClosed:"popoverregion:menuclosed",startLoading:"popoverregion:startLoading",stopLoading:"popoverregion:stopLoading"}},PopoverRegionController.prototype.getContentContainer=function(){return this.contentContainer},PopoverRegionController.prototype.getContent=function(){return this.content},PopoverRegionController.prototype.isMenuOpen=function(){return!this.root.hasClass("collapsed")},PopoverRegionController.prototype.toggleMenu=function(){this.isMenuOpen()?this.closeMenu():this.openMenu()},PopoverRegionController.prototype.closeMenu=function(){this.isMenuOpen()&&(this.root.addClass("collapsed"),this.menuContainer.attr("aria-expanded","false"),this.menuContainer.attr("aria-hidden","true"),this.updateButtonAriaLabel(),this.updateFocusItemTabIndex(),this.root.trigger(this.events().menuClosed))},PopoverRegionController.prototype.openMenu=function(){this.isMenuOpen()||(this.root.removeClass("collapsed"),this.menuContainer.attr("aria-expanded","true"),this.menuContainer.attr("aria-hidden","false"),this.updateButtonAriaLabel(),this.updateFocusItemTabIndex(),this.promises.closeHandlers.resolve(),this.promises.navigationHandlers.resolve(),this.root.trigger(this.events().menuOpened))},PopoverRegionController.prototype.updateButtonAriaLabel=function(){this.isMenuOpen()?str.get_string("hidepopoverwindow").done(function(string){this.menuToggle.attr("aria-label",string)}.bind(this)):str.get_string("showpopoverwindow").done(function(string){this.menuToggle.attr("aria-label",string)}.bind(this))},PopoverRegionController.prototype.startLoading=function(){this.isLoading=!0,this.getContentContainer().addClass("loading"),this.getContentContainer().attr("aria-busy","true"),this.root.trigger(this.events().startLoading)},PopoverRegionController.prototype.stopLoading=function(){this.isLoading=!1,this.getContentContainer().removeClass("loading"),this.getContentContainer().attr("aria-busy","false"),this.root.trigger(this.events().stopLoading)},PopoverRegionController.prototype.focusMenuToggle=function(){this.menuToggle.focus()},PopoverRegionController.prototype.contentItemHasFocus=function(){return this.getContentItemWithFocus().length>0},PopoverRegionController.prototype.getContentItemWithFocus=function(){var currentFocus=$(document.activeElement),items=this.getContent().children(),currentItem=items.filter(currentFocus);return currentItem.length||(currentItem=items.has(currentFocus)),currentItem},PopoverRegionController.prototype.focusContentItem=function(item){item.is(SELECTORS_CAN_RECEIVE_FOCUS)?item.focus():item.find(SELECTORS_CAN_RECEIVE_FOCUS).first().focus()},PopoverRegionController.prototype.focusFirstContentItem=function(){this.focusContentItem(this.getContent().children().first())},PopoverRegionController.prototype.focusLastContentItem=function(){this.focusContentItem(this.getContent().children().last())},PopoverRegionController.prototype.focusNextContentItem=function(){var currentItem=this.getContentItemWithFocus();currentItem.length&¤tItem.next()&&this.focusContentItem(currentItem.next())},PopoverRegionController.prototype.focusPreviousContentItem=function(){var currentItem=this.getContentItemWithFocus();currentItem.length&¤tItem.prev()&&this.focusContentItem(currentItem.prev())},PopoverRegionController.prototype.registerBaseEventListeners=function(){customEvents.define(this.root,[customEvents.events.activate,customEvents.events.escape]),this.root.on(customEvents.events.activate,SELECTORS_MENU_TOGGLE,function(){this.toggleMenu()}.bind(this)),this.promises.closeHandlers.done(function(){this.root.on(customEvents.events.escape,function(){this.closeMenu(),this.focusMenuToggle()}.bind(this)),document.addEventListener("click",(e=>{const target=e.target;this.root.is(target)||this.root.has(target).length||this.closeMenu()}),!0),customEvents.define(this.getContentContainer(),[customEvents.events.scrollBottom])}.bind(this))},PopoverRegionController.prototype.registerListNavigationEventListeners=function(){customEvents.define(this.root,[customEvents.events.down]),this.root.on(customEvents.events.down,function(e,data){this.isMenuOpen()?this.contentItemHasFocus()?this.focusNextContentItem():this.focusFirstContentItem():(this.openMenu(),this.focusFirstContentItem()),data.originalEvent.preventDefault()}.bind(this)),this.promises.navigationHandlers.done(function(){customEvents.define(this.root,[customEvents.events.up,customEvents.events.home,customEvents.events.end]),this.root.on(customEvents.events.up,function(e,data){this.focusPreviousContentItem(),data.originalEvent.preventDefault()}.bind(this)),this.root.on(customEvents.events.home,function(e,data){this.focusFirstContentItem(),data.originalEvent.preventDefault()}.bind(this)),this.root.on(customEvents.events.end,function(e,data){this.focusLastContentItem(),data.originalEvent.preventDefault()}.bind(this))}.bind(this))},PopoverRegionController.prototype.updateFocusItemTabIndex=function(){this.isMenuOpen()?this.menuContainer.find(SELECTORS_CAN_RECEIVE_FOCUS).removeAttr("tabindex"):this.menuContainer.find(SELECTORS_CAN_RECEIVE_FOCUS).attr("tabindex","-1")},PopoverRegionController})); //# sourceMappingURL=popover_region_controller.min.js.map \ No newline at end of file diff --git a/lib/amd/build/popover_region_controller.min.js.map b/lib/amd/build/popover_region_controller.min.js.map index a5ef8dc22c1..27589575f0e 100644 --- a/lib/amd/build/popover_region_controller.min.js.map +++ b/lib/amd/build/popover_region_controller.min.js.map @@ -1 +1 @@ -{"version":3,"file":"popover_region_controller.min.js","sources":["../src/popover_region_controller.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 * Controls the popover region element.\n *\n * See template: core/popover_region\n *\n * @module core/popover_region_controller\n * @copyright 2015 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.2\n */\ndefine(['jquery', 'core/str', 'core/custom_interaction_events'],\n function($, str, customEvents) {\n\n var SELECTORS = {\n CONTENT: '.popover-region-content',\n CONTENT_CONTAINER: '.popover-region-content-container',\n MENU_CONTAINER: '.popover-region-container',\n MENU_TOGGLE: '.popover-region-toggle',\n CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n };\n\n /**\n * Constructor for the PopoverRegionController.\n *\n * @param {jQuery} element object root element of the popover\n */\n var PopoverRegionController = function(element) {\n this.root = $(element);\n this.content = this.root.find(SELECTORS.CONTENT);\n this.contentContainer = this.root.find(SELECTORS.CONTENT_CONTAINER);\n this.menuContainer = this.root.find(SELECTORS.MENU_CONTAINER);\n this.menuToggle = this.root.find(SELECTORS.MENU_TOGGLE);\n this.isLoading = false;\n this.promises = {\n closeHandlers: $.Deferred(),\n navigationHandlers: $.Deferred(),\n };\n\n // Core event listeners to open and close.\n this.registerBaseEventListeners();\n };\n\n /**\n * The collection of events triggered by this controller.\n *\n * @returns {object}\n */\n PopoverRegionController.prototype.events = function() {\n return {\n menuOpened: 'popoverregion:menuopened',\n menuClosed: 'popoverregion:menuclosed',\n startLoading: 'popoverregion:startLoading',\n stopLoading: 'popoverregion:stopLoading',\n };\n };\n\n /**\n * Return the container element for the content element.\n *\n * @method getContentContainer\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContentContainer = function() {\n return this.contentContainer;\n };\n\n /**\n * Return the content element.\n *\n * @method getContent\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContent = function() {\n return this.content;\n };\n\n /**\n * Checks if the popover is displayed.\n *\n * @method isMenuOpen\n * @return {bool}\n */\n PopoverRegionController.prototype.isMenuOpen = function() {\n return !this.root.hasClass('collapsed');\n };\n\n /**\n * Toggle the visibility of the popover.\n *\n * @method toggleMenu\n */\n PopoverRegionController.prototype.toggleMenu = function() {\n if (this.isMenuOpen()) {\n this.closeMenu();\n } else {\n this.openMenu();\n }\n };\n\n /**\n * Hide the popover.\n *\n * Note: This triggers the menuClosed event.\n *\n * @method closeMenu\n */\n PopoverRegionController.prototype.closeMenu = function() {\n // We're already closed.\n if (!this.isMenuOpen()) {\n return;\n }\n\n this.root.addClass('collapsed');\n this.menuContainer.attr('aria-expanded', 'false');\n this.menuContainer.attr('aria-hidden', 'true');\n this.updateButtonAriaLabel();\n this.updateFocusItemTabIndex();\n this.root.trigger(this.events().menuClosed);\n };\n\n /**\n * Show the popover.\n *\n * Note: This triggers the menuOpened event.\n *\n * @method openMenu\n */\n PopoverRegionController.prototype.openMenu = function() {\n // We're already open.\n if (this.isMenuOpen()) {\n return;\n }\n\n this.root.removeClass('collapsed');\n this.menuContainer.attr('aria-expanded', 'true');\n this.menuContainer.attr('aria-hidden', 'false');\n this.updateButtonAriaLabel();\n this.updateFocusItemTabIndex();\n // Resolve the promises to allow the handlers to be added\n // to the DOM, if they have been requested.\n this.promises.closeHandlers.resolve();\n this.promises.navigationHandlers.resolve();\n this.root.trigger(this.events().menuOpened);\n };\n\n /**\n * Set the appropriate aria label on the popover toggle.\n *\n * @method updateButtonAriaLabel\n */\n PopoverRegionController.prototype.updateButtonAriaLabel = function() {\n if (this.isMenuOpen()) {\n str.get_string('hidepopoverwindow').done(function(string) {\n this.menuToggle.attr('aria-label', string);\n }.bind(this));\n } else {\n str.get_string('showpopoverwindow').done(function(string) {\n this.menuToggle.attr('aria-label', string);\n }.bind(this));\n }\n };\n\n /**\n * Set the loading state on this popover.\n *\n * Note: This triggers the startLoading event.\n *\n * @method startLoading\n */\n PopoverRegionController.prototype.startLoading = function() {\n this.isLoading = true;\n this.getContentContainer().addClass('loading');\n this.getContentContainer().attr('aria-busy', 'true');\n this.root.trigger(this.events().startLoading);\n };\n\n /**\n * Undo the loading state on this popover.\n *\n * Note: This triggers the stopLoading event.\n *\n * @method stopLoading\n */\n PopoverRegionController.prototype.stopLoading = function() {\n this.isLoading = false;\n this.getContentContainer().removeClass('loading');\n this.getContentContainer().attr('aria-busy', 'false');\n this.root.trigger(this.events().stopLoading);\n };\n\n /**\n * Sets the focus on the menu toggle.\n *\n * @method focusMenuToggle\n */\n PopoverRegionController.prototype.focusMenuToggle = function() {\n this.menuToggle.focus();\n };\n\n /**\n * Check if a content item has focus.\n *\n * @method contentItemHasFocus\n * @return {bool}\n */\n PopoverRegionController.prototype.contentItemHasFocus = function() {\n return this.getContentItemWithFocus().length > 0;\n };\n\n /**\n * Return the currently focused content item.\n *\n * @method getContentItemWithFocus\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContentItemWithFocus = function() {\n var currentFocus = $(document.activeElement);\n var items = this.getContent().children();\n var currentItem = items.filter(currentFocus);\n\n if (!currentItem.length) {\n currentItem = items.has(currentFocus);\n }\n\n return currentItem;\n };\n\n /**\n * Focus the given content item or the first focusable element within\n * the content item.\n *\n * @method focusContentItem\n * @param {object} item The content item jQuery element\n */\n PopoverRegionController.prototype.focusContentItem = function(item) {\n if (item.is(SELECTORS.CAN_RECEIVE_FOCUS)) {\n item.focus();\n } else {\n item.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n }\n };\n\n /**\n * Set focus on the first content item in the list.\n *\n * @method focusFirstContentItem\n */\n PopoverRegionController.prototype.focusFirstContentItem = function() {\n this.focusContentItem(this.getContent().children().first());\n };\n\n /**\n * Set focus on the last content item in the list.\n *\n * @method focusLastContentItem\n */\n PopoverRegionController.prototype.focusLastContentItem = function() {\n this.focusContentItem(this.getContent().children().last());\n };\n\n /**\n * Set focus on the content item after the item that currently has focus\n * in the list.\n *\n * @method focusNextContentItem\n */\n PopoverRegionController.prototype.focusNextContentItem = function() {\n var currentItem = this.getContentItemWithFocus();\n\n if (currentItem.length && currentItem.next()) {\n this.focusContentItem(currentItem.next());\n }\n };\n\n /**\n * Set focus on the content item preceding the item that currently has focus\n * in the list.\n *\n * @method focusPreviousContentItem\n */\n PopoverRegionController.prototype.focusPreviousContentItem = function() {\n var currentItem = this.getContentItemWithFocus();\n\n if (currentItem.length && currentItem.prev()) {\n this.focusContentItem(currentItem.prev());\n }\n };\n\n /**\n * Register the minimal amount of listeners for the popover to function.\n *\n * @method registerBaseEventListeners\n */\n PopoverRegionController.prototype.registerBaseEventListeners = function() {\n customEvents.define(this.root, [\n customEvents.events.activate,\n customEvents.events.escape,\n ]);\n\n // Toggle the popover visibility on activation (click/enter/space) of the toggle button.\n this.root.on(customEvents.events.activate, SELECTORS.MENU_TOGGLE, function() {\n this.toggleMenu();\n }.bind(this));\n\n // Delay the binding of these handlers until the region has been opened.\n this.promises.closeHandlers.done(function() {\n // Close the popover if escape is pressed.\n this.root.on(customEvents.events.escape, function() {\n this.closeMenu();\n this.focusMenuToggle();\n }.bind(this));\n\n // Close the popover if any other part of the page is clicked.\n $('html').click(function(e) {\n var target = $(e.target);\n if (!this.root.is(target) && !this.root.has(target).length) {\n this.closeMenu();\n }\n }.bind(this));\n\n customEvents.define(this.getContentContainer(), [\n customEvents.events.scrollBottom\n ]);\n }.bind(this));\n };\n\n /**\n * Set up the event listeners for keyboard navigating a list of content items.\n *\n * @method registerListNavigationEventListeners\n */\n PopoverRegionController.prototype.registerListNavigationEventListeners = function() {\n customEvents.define(this.root, [\n customEvents.events.down\n ]);\n\n // If the down arrow is pressed then open the menu and focus the first content\n // item or focus the next content item if the menu is open.\n this.root.on(customEvents.events.down, function(e, data) {\n if (!this.isMenuOpen()) {\n this.openMenu();\n this.focusFirstContentItem();\n } else {\n if (this.contentItemHasFocus()) {\n this.focusNextContentItem();\n } else {\n this.focusFirstContentItem();\n }\n }\n\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Delay the binding of these handlers until the region has been opened.\n this.promises.navigationHandlers.done(function() {\n customEvents.define(this.root, [\n customEvents.events.up,\n customEvents.events.home,\n customEvents.events.end,\n ]);\n\n // Shift focus to the previous content item if the up key is pressed.\n this.root.on(customEvents.events.up, function(e, data) {\n this.focusPreviousContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Jump focus to the first content item if the home key is pressed.\n this.root.on(customEvents.events.home, function(e, data) {\n this.focusFirstContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Jump focus to the last content item if the end key is pressed.\n this.root.on(customEvents.events.end, function(e, data) {\n this.focusLastContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n }.bind(this));\n };\n\n /**\n * Set the appropriate tabindex attribute on the popover toggle.\n *\n * @method updateFocusItemTabIndex\n */\n PopoverRegionController.prototype.updateFocusItemTabIndex = function() {\n if (this.isMenuOpen()) {\n this.menuContainer.find(SELECTORS.CAN_RECEIVE_FOCUS).removeAttr('tabindex');\n } else {\n this.menuContainer.find(SELECTORS.CAN_RECEIVE_FOCUS).attr('tabindex', '-1');\n }\n };\n\n return PopoverRegionController;\n});\n"],"names":["define","$","str","customEvents","SELECTORS","PopoverRegionController","element","root","content","this","find","contentContainer","menuContainer","menuToggle","isLoading","promises","closeHandlers","Deferred","navigationHandlers","registerBaseEventListeners","prototype","events","menuOpened","menuClosed","startLoading","stopLoading","getContentContainer","getContent","isMenuOpen","hasClass","toggleMenu","closeMenu","openMenu","addClass","attr","updateButtonAriaLabel","updateFocusItemTabIndex","trigger","removeClass","resolve","get_string","done","string","bind","focusMenuToggle","focus","contentItemHasFocus","getContentItemWithFocus","length","currentFocus","document","activeElement","items","children","currentItem","filter","has","focusContentItem","item","is","first","focusFirstContentItem","focusLastContentItem","last","focusNextContentItem","next","focusPreviousContentItem","prev","activate","escape","on","click","e","target","scrollBottom","registerListNavigationEventListeners","down","data","originalEvent","preventDefault","up","home","end","removeAttr"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"popover_region_controller.min.js","sources":["../src/popover_region_controller.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 * Controls the popover region element.\n *\n * See template: core/popover_region\n *\n * @module core/popover_region_controller\n * @copyright 2015 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.2\n */\ndefine(['jquery', 'core/str', 'core/custom_interaction_events'],\n function($, str, customEvents) {\n\n var SELECTORS = {\n CONTENT: '.popover-region-content',\n CONTENT_CONTAINER: '.popover-region-content-container',\n MENU_CONTAINER: '.popover-region-container',\n MENU_TOGGLE: '.popover-region-toggle',\n CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n };\n\n /**\n * Constructor for the PopoverRegionController.\n *\n * @param {jQuery} element object root element of the popover\n */\n var PopoverRegionController = function(element) {\n this.root = $(element);\n this.content = this.root.find(SELECTORS.CONTENT);\n this.contentContainer = this.root.find(SELECTORS.CONTENT_CONTAINER);\n this.menuContainer = this.root.find(SELECTORS.MENU_CONTAINER);\n this.menuToggle = this.root.find(SELECTORS.MENU_TOGGLE);\n this.isLoading = false;\n this.promises = {\n closeHandlers: $.Deferred(),\n navigationHandlers: $.Deferred(),\n };\n\n // Core event listeners to open and close.\n this.registerBaseEventListeners();\n };\n\n /**\n * The collection of events triggered by this controller.\n *\n * @returns {object}\n */\n PopoverRegionController.prototype.events = function() {\n return {\n menuOpened: 'popoverregion:menuopened',\n menuClosed: 'popoverregion:menuclosed',\n startLoading: 'popoverregion:startLoading',\n stopLoading: 'popoverregion:stopLoading',\n };\n };\n\n /**\n * Return the container element for the content element.\n *\n * @method getContentContainer\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContentContainer = function() {\n return this.contentContainer;\n };\n\n /**\n * Return the content element.\n *\n * @method getContent\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContent = function() {\n return this.content;\n };\n\n /**\n * Checks if the popover is displayed.\n *\n * @method isMenuOpen\n * @return {bool}\n */\n PopoverRegionController.prototype.isMenuOpen = function() {\n return !this.root.hasClass('collapsed');\n };\n\n /**\n * Toggle the visibility of the popover.\n *\n * @method toggleMenu\n */\n PopoverRegionController.prototype.toggleMenu = function() {\n if (this.isMenuOpen()) {\n this.closeMenu();\n } else {\n this.openMenu();\n }\n };\n\n /**\n * Hide the popover.\n *\n * Note: This triggers the menuClosed event.\n *\n * @method closeMenu\n */\n PopoverRegionController.prototype.closeMenu = function() {\n // We're already closed.\n if (!this.isMenuOpen()) {\n return;\n }\n\n this.root.addClass('collapsed');\n this.menuContainer.attr('aria-expanded', 'false');\n this.menuContainer.attr('aria-hidden', 'true');\n this.updateButtonAriaLabel();\n this.updateFocusItemTabIndex();\n this.root.trigger(this.events().menuClosed);\n };\n\n /**\n * Show the popover.\n *\n * Note: This triggers the menuOpened event.\n *\n * @method openMenu\n */\n PopoverRegionController.prototype.openMenu = function() {\n // We're already open.\n if (this.isMenuOpen()) {\n return;\n }\n\n this.root.removeClass('collapsed');\n this.menuContainer.attr('aria-expanded', 'true');\n this.menuContainer.attr('aria-hidden', 'false');\n this.updateButtonAriaLabel();\n this.updateFocusItemTabIndex();\n // Resolve the promises to allow the handlers to be added\n // to the DOM, if they have been requested.\n this.promises.closeHandlers.resolve();\n this.promises.navigationHandlers.resolve();\n this.root.trigger(this.events().menuOpened);\n };\n\n /**\n * Set the appropriate aria label on the popover toggle.\n *\n * @method updateButtonAriaLabel\n */\n PopoverRegionController.prototype.updateButtonAriaLabel = function() {\n if (this.isMenuOpen()) {\n str.get_string('hidepopoverwindow').done(function(string) {\n this.menuToggle.attr('aria-label', string);\n }.bind(this));\n } else {\n str.get_string('showpopoverwindow').done(function(string) {\n this.menuToggle.attr('aria-label', string);\n }.bind(this));\n }\n };\n\n /**\n * Set the loading state on this popover.\n *\n * Note: This triggers the startLoading event.\n *\n * @method startLoading\n */\n PopoverRegionController.prototype.startLoading = function() {\n this.isLoading = true;\n this.getContentContainer().addClass('loading');\n this.getContentContainer().attr('aria-busy', 'true');\n this.root.trigger(this.events().startLoading);\n };\n\n /**\n * Undo the loading state on this popover.\n *\n * Note: This triggers the stopLoading event.\n *\n * @method stopLoading\n */\n PopoverRegionController.prototype.stopLoading = function() {\n this.isLoading = false;\n this.getContentContainer().removeClass('loading');\n this.getContentContainer().attr('aria-busy', 'false');\n this.root.trigger(this.events().stopLoading);\n };\n\n /**\n * Sets the focus on the menu toggle.\n *\n * @method focusMenuToggle\n */\n PopoverRegionController.prototype.focusMenuToggle = function() {\n this.menuToggle.focus();\n };\n\n /**\n * Check if a content item has focus.\n *\n * @method contentItemHasFocus\n * @return {bool}\n */\n PopoverRegionController.prototype.contentItemHasFocus = function() {\n return this.getContentItemWithFocus().length > 0;\n };\n\n /**\n * Return the currently focused content item.\n *\n * @method getContentItemWithFocus\n * @return {jQuery} object\n */\n PopoverRegionController.prototype.getContentItemWithFocus = function() {\n var currentFocus = $(document.activeElement);\n var items = this.getContent().children();\n var currentItem = items.filter(currentFocus);\n\n if (!currentItem.length) {\n currentItem = items.has(currentFocus);\n }\n\n return currentItem;\n };\n\n /**\n * Focus the given content item or the first focusable element within\n * the content item.\n *\n * @method focusContentItem\n * @param {object} item The content item jQuery element\n */\n PopoverRegionController.prototype.focusContentItem = function(item) {\n if (item.is(SELECTORS.CAN_RECEIVE_FOCUS)) {\n item.focus();\n } else {\n item.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n }\n };\n\n /**\n * Set focus on the first content item in the list.\n *\n * @method focusFirstContentItem\n */\n PopoverRegionController.prototype.focusFirstContentItem = function() {\n this.focusContentItem(this.getContent().children().first());\n };\n\n /**\n * Set focus on the last content item in the list.\n *\n * @method focusLastContentItem\n */\n PopoverRegionController.prototype.focusLastContentItem = function() {\n this.focusContentItem(this.getContent().children().last());\n };\n\n /**\n * Set focus on the content item after the item that currently has focus\n * in the list.\n *\n * @method focusNextContentItem\n */\n PopoverRegionController.prototype.focusNextContentItem = function() {\n var currentItem = this.getContentItemWithFocus();\n\n if (currentItem.length && currentItem.next()) {\n this.focusContentItem(currentItem.next());\n }\n };\n\n /**\n * Set focus on the content item preceding the item that currently has focus\n * in the list.\n *\n * @method focusPreviousContentItem\n */\n PopoverRegionController.prototype.focusPreviousContentItem = function() {\n var currentItem = this.getContentItemWithFocus();\n\n if (currentItem.length && currentItem.prev()) {\n this.focusContentItem(currentItem.prev());\n }\n };\n\n /**\n * Register the minimal amount of listeners for the popover to function.\n *\n * @method registerBaseEventListeners\n */\n PopoverRegionController.prototype.registerBaseEventListeners = function() {\n customEvents.define(this.root, [\n customEvents.events.activate,\n customEvents.events.escape,\n ]);\n\n // Toggle the popover visibility on activation (click/enter/space) of the toggle button.\n this.root.on(customEvents.events.activate, SELECTORS.MENU_TOGGLE, function() {\n this.toggleMenu();\n }.bind(this));\n\n // Delay the binding of these handlers until the region has been opened.\n this.promises.closeHandlers.done(function() {\n // Close the popover if escape is pressed.\n this.root.on(customEvents.events.escape, function() {\n this.closeMenu();\n this.focusMenuToggle();\n }.bind(this));\n\n // Close the popover if any other part of the page is clicked.\n document.addEventListener('click', (e) => {\n const target = e.target;\n // Check if the click is outside the root element.\n if (!this.root.is(target) && !this.root.has(target).length) {\n this.closeMenu();\n }\n }, true); // `true` makes it a capture phase event listener.\n\n customEvents.define(this.getContentContainer(), [\n customEvents.events.scrollBottom\n ]);\n }.bind(this));\n };\n\n /**\n * Set up the event listeners for keyboard navigating a list of content items.\n *\n * @method registerListNavigationEventListeners\n */\n PopoverRegionController.prototype.registerListNavigationEventListeners = function() {\n customEvents.define(this.root, [\n customEvents.events.down\n ]);\n\n // If the down arrow is pressed then open the menu and focus the first content\n // item or focus the next content item if the menu is open.\n this.root.on(customEvents.events.down, function(e, data) {\n if (!this.isMenuOpen()) {\n this.openMenu();\n this.focusFirstContentItem();\n } else {\n if (this.contentItemHasFocus()) {\n this.focusNextContentItem();\n } else {\n this.focusFirstContentItem();\n }\n }\n\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Delay the binding of these handlers until the region has been opened.\n this.promises.navigationHandlers.done(function() {\n customEvents.define(this.root, [\n customEvents.events.up,\n customEvents.events.home,\n customEvents.events.end,\n ]);\n\n // Shift focus to the previous content item if the up key is pressed.\n this.root.on(customEvents.events.up, function(e, data) {\n this.focusPreviousContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Jump focus to the first content item if the home key is pressed.\n this.root.on(customEvents.events.home, function(e, data) {\n this.focusFirstContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Jump focus to the last content item if the end key is pressed.\n this.root.on(customEvents.events.end, function(e, data) {\n this.focusLastContentItem();\n data.originalEvent.preventDefault();\n }.bind(this));\n }.bind(this));\n };\n\n /**\n * Set the appropriate tabindex attribute on the popover toggle.\n *\n * @method updateFocusItemTabIndex\n */\n PopoverRegionController.prototype.updateFocusItemTabIndex = function() {\n if (this.isMenuOpen()) {\n this.menuContainer.find(SELECTORS.CAN_RECEIVE_FOCUS).removeAttr('tabindex');\n } else {\n this.menuContainer.find(SELECTORS.CAN_RECEIVE_FOCUS).attr('tabindex', '-1');\n }\n };\n\n return PopoverRegionController;\n});\n"],"names":["define","$","str","customEvents","SELECTORS","PopoverRegionController","element","root","content","this","find","contentContainer","menuContainer","menuToggle","isLoading","promises","closeHandlers","Deferred","navigationHandlers","registerBaseEventListeners","prototype","events","menuOpened","menuClosed","startLoading","stopLoading","getContentContainer","getContent","isMenuOpen","hasClass","toggleMenu","closeMenu","openMenu","addClass","attr","updateButtonAriaLabel","updateFocusItemTabIndex","trigger","removeClass","resolve","get_string","done","string","bind","focusMenuToggle","focus","contentItemHasFocus","getContentItemWithFocus","length","currentFocus","document","activeElement","items","children","currentItem","filter","has","focusContentItem","item","is","first","focusFirstContentItem","focusLastContentItem","last","focusNextContentItem","next","focusPreviousContentItem","prev","activate","escape","on","addEventListener","e","target","scrollBottom","registerListNavigationEventListeners","down","data","originalEvent","preventDefault","up","home","end","removeAttr"],"mappings":"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"} \ No newline at end of file diff --git a/lib/amd/src/popover_region_controller.js b/lib/amd/src/popover_region_controller.js index d709835302b..6837f02dc37 100644 --- a/lib/amd/src/popover_region_controller.js +++ b/lib/amd/src/popover_region_controller.js @@ -326,12 +326,13 @@ define(['jquery', 'core/str', 'core/custom_interaction_events'], }.bind(this)); // Close the popover if any other part of the page is clicked. - $('html').click(function(e) { - var target = $(e.target); + document.addEventListener('click', (e) => { + const target = e.target; + // Check if the click is outside the root element. if (!this.root.is(target) && !this.root.has(target).length) { this.closeMenu(); } - }.bind(this)); + }, true); // `true` makes it a capture phase event listener. customEvents.define(this.getContentContainer(), [ customEvents.events.scrollBottom