From 067138aab477c511e4ed23920356f44853da05fd Mon Sep 17 00:00:00 2001 From: Laurent David Date: Mon, 7 Apr 2025 11:21:45 +0200 Subject: [PATCH] MDL-81702 core_message: Add focustrap and backdrop * Add focustrap and backdrop to message drawer. --- lib/templates/drawer.mustache | 5 +- message/amd/build/message_drawer.min.js | 2 +- message/amd/build/message_drawer.min.js.map | 2 +- message/amd/build/message_popover.min.js | 2 +- message/amd/build/message_popover.min.js.map | 2 +- message/amd/src/message_drawer.js | 88 +++++++++++++++++++- message/amd/src/message_popover.js | 1 - message/templates/message_drawer.mustache | 6 ++ 8 files changed, 98 insertions(+), 10 deletions(-) diff --git a/lib/templates/drawer.mustache b/lib/templates/drawer.mustache index 82ecf775c45..2c2d9f3a395 100644 --- a/lib/templates/drawer.mustache +++ b/lib/templates/drawer.mustache @@ -36,8 +36,9 @@ class="{{$drawerclasses}}{{/drawerclasses}} drawer bg-white {{^show}}hidden{{/show}}" {{^show}}aria-hidden="true"{{/show}} data-region="right-hand-drawer" - role="region" - tabindex="0" + role="{{$role}}region{{/role}}" + tabindex="{{$tabindex}}0{{/tabindex}}" + {{$drawerattributes}}{{/drawerattributes}} > {{$drawercontent}}{{/drawercontent}} diff --git a/message/amd/build/message_drawer.min.js b/message/amd/build/message_drawer.min.js index 9933e49eaab..37c38d36029 100644 --- a/message/amd/build/message_drawer.min.js +++ b/message/amd/build/message_drawer.min.js @@ -5,6 +5,6 @@ * @copyright 2018 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("core_message/message_drawer",["jquery","core/custom_interaction_events","core/pubsub","core_message/message_drawer_view_contact","core_message/message_drawer_view_contacts","core_message/message_drawer_view_conversation","core_message/message_drawer_view_group_info","core_message/message_drawer_view_overview","core_message/message_drawer_view_search","core_message/message_drawer_view_settings","core_message/message_drawer_router","core_message/message_drawer_routes","core_message/message_drawer_events","core_message/message_drawer_helper","core/pending","core/drawer"],(function($,CustomEvents,PubSub,ViewContact,ViewContacts,ViewConversation,ViewGroupInfo,ViewOverview,ViewSearch,ViewSettings,Router,Routes,Events,Helper,Pending,Drawer){var SELECTORS_DRAWER='[data-region="right-hand-drawer"]',SELECTORS_JUMPTO='.popover-region [data-region="jumpto"]',SELECTORS_PANEL_BODY_CONTAINER='[data-region="panel-body-container"]',SELECTORS_PANEL_HEADER_CONTAINER='[data-region="panel-header-container"]',SELECTORS_VIEW_CONTACT='[data-region="view-contact"]',SELECTORS_VIEW_CONTACTS='[data-region="view-contacts"]',SELECTORS_VIEW_CONVERSATION='[data-region="view-conversation"]',SELECTORS_VIEW_GROUP_INFO='[data-region="view-group-info"]',SELECTORS_VIEW_OVERVIEW='[data-region="view-overview"]',SELECTORS_VIEW_SEARCH='[data-region="view-search"]',SELECTORS_VIEW_SETTINGS='[data-region="view-settings"]',SELECTORS_ROUTES="[data-route]",SELECTORS_ROUTES_BACK="[data-route-back]",SELECTORS_HEADER_CONTAINER='[data-region="header-container"]',SELECTORS_BODY_CONTAINER='[data-region="body-container"]',SELECTORS_FOOTER_CONTAINER='[data-region="footer-container"]',SELECTORS_CLOSE_BUTTON='[data-action="closedrawer"]',routes=[[Routes.VIEW_CONTACT,SELECTORS_VIEW_CONTACT,ViewContact.show,ViewContact.description],[Routes.VIEW_CONTACTS,SELECTORS_VIEW_CONTACTS,ViewContacts.show,ViewContacts.description],[Routes.VIEW_CONVERSATION,SELECTORS_VIEW_CONVERSATION,ViewConversation.show,ViewConversation.description],[Routes.VIEW_GROUP_INFO,SELECTORS_VIEW_GROUP_INFO,ViewGroupInfo.show,ViewGroupInfo.description],[Routes.VIEW_OVERVIEW,SELECTORS_VIEW_OVERVIEW,ViewOverview.show,ViewOverview.description],[Routes.VIEW_SEARCH,SELECTORS_VIEW_SEARCH,ViewSearch.show,ViewSearch.description],[Routes.VIEW_SETTINGS,SELECTORS_VIEW_SETTINGS,ViewSettings.show,ViewSettings.description]],createRoutes=function(namespace,root){routes.forEach((function(route){Router.add(namespace,route[0],function(namespace,root,selector){var header=root.find(SELECTORS_HEADER_CONTAINER).find(selector);header.length||(header=root.find(SELECTORS_PANEL_HEADER_CONTAINER).find(selector));var body=root.find(SELECTORS_BODY_CONTAINER).find(selector);body.length||(body=root.find(SELECTORS_PANEL_BODY_CONTAINER).find(selector));var footer=root.find(SELECTORS_FOOTER_CONTAINER).find(selector);return[namespace,header.length?header:null,body.length?body:null,footer.length?footer:null]}(namespace,root,route[1]),route[2],route[3])}))},show=function(namespace,root){root.attr("data-shown")||(Router.go(namespace,Routes.VIEW_OVERVIEW),root.attr("data-shown",!0));var drawerRoot=Drawer.getDrawerRoot(root);drawerRoot.length&&Drawer.show(drawerRoot)},hide=function(root){var drawerRoot=Drawer.getDrawerRoot(root);drawerRoot.length&&Drawer.hide(drawerRoot)},setJumpFrom=function(buttonid){$(SELECTORS_DRAWER).attr("data-origin",buttonid)},registerEventListeners=function(namespace,root,alwaysVisible){CustomEvents.define(root,[CustomEvents.events.activate]);var paramRegex=/^data-route-param-?(\d*)$/;root.on(CustomEvents.events.activate,SELECTORS_ROUTES,(function(e,data){for(var element=$(e.target).closest(SELECTORS_ROUTES),route=element.attr("data-route"),attributes=[],i=0;i1?aParts[1]:0,bIndex=bParts.length>1?bParts[1]:0;return aIndexnew ModalBackdrop(html))));const backdropWithAdjustments=backdropPromise.then((modalBackdrop=>{const messageDrawerZIndex=window.getComputedStyle(drawerRoot[0]).zIndex;return messageDrawerZIndex&&modalBackdrop.setZIndex(messageDrawerZIndex-1),modalBackdrop.getAttachmentPoint().get(0).addEventListener("click",(e=>{PubSub.publish(Events.HIDE,{}),e.preventDefault()})),modalBackdrop}));hasFocus?(FocusLock.trapFocus(root[0]),backdropWithAdjustments.then((modalBackdrop=>{if(modalBackdrop){modalBackdrop.show();document.getElementById("page").style.overflow="hidden";var closeButton=root.find(SELECTORS_CLOSE_BUTTON);closeButton.length&&closeButton.focus()}return modalBackdrop}))):backdropWithAdjustments.then((modalBackdrop=>{if(modalBackdrop){FocusLock.untrapFocus();var button=$(SELECTORS_DRAWER).attr("data-origin");button&&$("#"+button).focus(),modalBackdrop.hide();document.getElementById("page").style.overflow="visible"}return modalBackdrop}))},show=function(namespace,root){root.attr("data-shown")||(Router.go(namespace,Routes.VIEW_OVERVIEW),root.attr("data-shown",!0));var drawerRoot=Drawer.getDrawerRoot(root);drawerRoot.length&&(setFocus(root,!0),Drawer.show(drawerRoot))},hide=function(root){var drawerRoot=Drawer.getDrawerRoot(root);drawerRoot.length&&(setFocus(root,!1),Drawer.hide(drawerRoot))},setJumpFrom=function(buttonid){$(SELECTORS_DRAWER).attr("data-origin",buttonid)},registerEventListeners=function(namespace,root,alwaysVisible){CustomEvents.define(root,[CustomEvents.events.activate,CustomEvents.events.escape]);var paramRegex=/^data-route-param-?(\d*)$/;root.on(CustomEvents.events.activate,SELECTORS_ROUTES,(function(e,data){for(var element=$(e.target).closest(SELECTORS_ROUTES),route=element.attr("data-route"),attributes=[],i=0;i1?aParts[1]:0,bIndex=bParts.length>1?bParts[1]:0;return aIndex.\n\n/**\n * Controls the message drawer.\n *\n * @module core_message/message_drawer\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_view_contact',\n 'core_message/message_drawer_view_contacts',\n 'core_message/message_drawer_view_conversation',\n 'core_message/message_drawer_view_group_info',\n 'core_message/message_drawer_view_overview',\n 'core_message/message_drawer_view_search',\n 'core_message/message_drawer_view_settings',\n 'core_message/message_drawer_router',\n 'core_message/message_drawer_routes',\n 'core_message/message_drawer_events',\n 'core_message/message_drawer_helper',\n 'core/pending',\n 'core/drawer',\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n ViewContact,\n ViewContacts,\n ViewConversation,\n ViewGroupInfo,\n ViewOverview,\n ViewSearch,\n ViewSettings,\n Router,\n Routes,\n Events,\n Helper,\n Pending,\n Drawer\n) {\n\n var SELECTORS = {\n DRAWER: '[data-region=\"right-hand-drawer\"]',\n JUMPTO: '.popover-region [data-region=\"jumpto\"]',\n PANEL_BODY_CONTAINER: '[data-region=\"panel-body-container\"]',\n PANEL_HEADER_CONTAINER: '[data-region=\"panel-header-container\"]',\n VIEW_CONTACT: '[data-region=\"view-contact\"]',\n VIEW_CONTACTS: '[data-region=\"view-contacts\"]',\n VIEW_CONVERSATION: '[data-region=\"view-conversation\"]',\n VIEW_GROUP_INFO: '[data-region=\"view-group-info\"]',\n VIEW_OVERVIEW: '[data-region=\"view-overview\"]',\n VIEW_SEARCH: '[data-region=\"view-search\"]',\n VIEW_SETTINGS: '[data-region=\"view-settings\"]',\n ROUTES: '[data-route]',\n ROUTES_BACK: '[data-route-back]',\n HEADER_CONTAINER: '[data-region=\"header-container\"]',\n BODY_CONTAINER: '[data-region=\"body-container\"]',\n FOOTER_CONTAINER: '[data-region=\"footer-container\"]',\n CLOSE_BUTTON: '[data-action=\"closedrawer\"]'\n };\n\n /**\n * Get elements for route.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n * @param {string} selector The route container.\n *\n * @return {array} elements Found route container objects.\n */\n var getParametersForRoute = function(namespace, root, selector) {\n\n var header = root.find(SELECTORS.HEADER_CONTAINER).find(selector);\n if (!header.length) {\n header = root.find(SELECTORS.PANEL_HEADER_CONTAINER).find(selector);\n }\n var body = root.find(SELECTORS.BODY_CONTAINER).find(selector);\n if (!body.length) {\n body = root.find(SELECTORS.PANEL_BODY_CONTAINER).find(selector);\n }\n var footer = root.find(SELECTORS.FOOTER_CONTAINER).find(selector);\n\n return [\n namespace,\n header.length ? header : null,\n body.length ? body : null,\n footer.length ? footer : null\n ];\n };\n\n var routes = [\n [Routes.VIEW_CONTACT, SELECTORS.VIEW_CONTACT, ViewContact.show, ViewContact.description],\n [Routes.VIEW_CONTACTS, SELECTORS.VIEW_CONTACTS, ViewContacts.show, ViewContacts.description],\n [Routes.VIEW_CONVERSATION, SELECTORS.VIEW_CONVERSATION, ViewConversation.show, ViewConversation.description],\n [Routes.VIEW_GROUP_INFO, SELECTORS.VIEW_GROUP_INFO, ViewGroupInfo.show, ViewGroupInfo.description],\n [Routes.VIEW_OVERVIEW, SELECTORS.VIEW_OVERVIEW, ViewOverview.show, ViewOverview.description],\n [Routes.VIEW_SEARCH, SELECTORS.VIEW_SEARCH, ViewSearch.show, ViewSearch.description],\n [Routes.VIEW_SETTINGS, SELECTORS.VIEW_SETTINGS, ViewSettings.show, ViewSettings.description]\n ];\n\n /**\n * Create routes.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n */\n var createRoutes = function(namespace, root) {\n routes.forEach(function(route) {\n Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);\n });\n };\n\n /**\n * Show the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n */\n var show = function(namespace, root) {\n if (!root.attr('data-shown')) {\n Router.go(namespace, Routes.VIEW_OVERVIEW);\n root.attr('data-shown', true);\n }\n\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n Drawer.show(drawerRoot);\n }\n };\n\n /**\n * Hide the message drawer.\n *\n * @param {Object} root The message drawer container.\n */\n var hide = function(root) {\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n Drawer.hide(drawerRoot);\n }\n };\n\n /**\n * Check if the drawer is visible.\n *\n * @param {Object} root The message drawer container.\n * @return {boolean}\n */\n var isVisible = function(root) {\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n return Drawer.isVisible(drawerRoot);\n }\n return true;\n };\n\n /**\n * Set Jump from button\n *\n * @param {String} buttonid The originating button id\n */\n var setJumpFrom = function(buttonid) {\n $(SELECTORS.DRAWER).attr('data-origin', buttonid);\n };\n\n /**\n * Listen to and handle events for routing, showing and hiding the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n * @param {bool} alwaysVisible Is this messaging app always shown?\n */\n var registerEventListeners = function(namespace, root, alwaysVisible) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n var paramRegex = /^data-route-param-?(\\d*)$/;\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {\n var element = $(e.target).closest(SELECTORS.ROUTES);\n var route = element.attr('data-route');\n var attributes = [];\n\n for (var i = 0; i < element[0].attributes.length; i++) {\n attributes.push(element[0].attributes[i]);\n }\n\n var paramAttributes = attributes.filter(function(attribute) {\n var name = attribute.nodeName;\n var match = paramRegex.test(name);\n return match;\n });\n paramAttributes.sort(function(a, b) {\n var aParts = paramRegex.exec(a.nodeName);\n var bParts = paramRegex.exec(b.nodeName);\n var aIndex = aParts.length > 1 ? aParts[1] : 0;\n var bIndex = bParts.length > 1 ? bParts[1] : 0;\n\n if (aIndex < bIndex) {\n return -1;\n } else if (bIndex < aIndex) {\n return 1;\n } else {\n return 0;\n }\n });\n\n var params = paramAttributes.map(function(attribute) {\n return attribute.nodeValue;\n });\n\n var routeParams = [namespace, route].concat(params);\n\n Router.go.apply(null, routeParams);\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES_BACK, function(e, data) {\n Router.back(namespace);\n\n data.originalEvent.preventDefault();\n });\n\n // These are theme-specific to help us fix random behat fails.\n // These events target those events defined in BS3 and BS4 onwards.\n root.on('hide.bs.collapse', '.collapse', function(e) {\n var pendingPromise = new Pending();\n $(e.target).one('hidden.bs.collapse', function() {\n pendingPromise.resolve();\n });\n });\n\n root.on('show.bs.collapse', '.collapse', function(e) {\n var pendingPromise = new Pending();\n $(e.target).one('shown.bs.collapse', function() {\n pendingPromise.resolve();\n });\n });\n\n $(SELECTORS.JUMPTO).focus(function() {\n var firstInput = root.find(SELECTORS.CLOSE_BUTTON);\n if (firstInput.length) {\n firstInput.focus();\n } else {\n $(SELECTORS.HEADER_CONTAINER).find(SELECTORS.ROUTES_BACK).focus();\n }\n });\n\n $(SELECTORS.DRAWER).focus(function() {\n var button = $(this).attr('data-origin');\n if (button) {\n $('#' + button).focus();\n }\n });\n\n if (!alwaysVisible) {\n PubSub.subscribe(Events.SHOW, function() {\n show(namespace, root);\n });\n\n PubSub.subscribe(Events.HIDE, function() {\n hide(root);\n });\n\n PubSub.subscribe(Events.TOGGLE_VISIBILITY, function(buttonid) {\n const buttonElement = document.getElementById(buttonid);\n if (isVisible(root)) {\n hide(root);\n buttonElement?.setAttribute('aria-expanded', false);\n $(SELECTORS.JUMPTO).attr('tabindex', -1);\n } else {\n show(namespace, root);\n buttonElement?.setAttribute('aria-expanded', true);\n setJumpFrom(buttonid);\n $(SELECTORS.JUMPTO).attr('tabindex', 0);\n }\n });\n }\n\n PubSub.subscribe(Events.SHOW_CONVERSATION, function(args) {\n setJumpFrom(args.buttonid);\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, args.conversationid);\n });\n\n var closebutton = root.find(SELECTORS.CLOSE_BUTTON);\n closebutton.on(CustomEvents.events.activate, function(e, data) {\n data.originalEvent.preventDefault();\n\n var button = $(SELECTORS.DRAWER).attr('data-origin');\n if (button) {\n $('#' + button).focus();\n }\n PubSub.publish(Events.TOGGLE_VISIBILITY, button);\n });\n\n PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(args) {\n setJumpFrom(args.buttonid);\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, null, 'create', args.userid);\n });\n\n PubSub.subscribe(Events.SHOW_SETTINGS, function() {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_SETTINGS);\n });\n\n PubSub.subscribe(Events.PREFERENCES_UPDATED, function(preferences) {\n var filteredPreferences = preferences.filter(function(preference) {\n return preference.type == 'message_entertosend';\n });\n var enterToSendPreference = filteredPreferences.length ? filteredPreferences[0] : null;\n\n if (enterToSendPreference) {\n var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);\n viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);\n }\n });\n };\n\n /**\n * Initialise the message drawer.\n *\n * @param {Object} root The message drawer container.\n * @param {String} uniqueId Unique identifier for the Routes\n * @param {bool} alwaysVisible Should we show the app now, or wait for the user?\n * @param {Object} route\n */\n var init = function(root, uniqueId, alwaysVisible, route) {\n root = $(root);\n createRoutes(uniqueId, root);\n registerEventListeners(uniqueId, root, alwaysVisible);\n\n if (alwaysVisible) {\n show(uniqueId, root);\n\n if (route) {\n var routeParams = route.params || [];\n routeParams = [uniqueId, route.path].concat(routeParams);\n Router.go.apply(null, routeParams);\n }\n }\n\n // Mark the drawer as ready.\n Helper.markDrawerReady();\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CustomEvents","PubSub","ViewContact","ViewContacts","ViewConversation","ViewGroupInfo","ViewOverview","ViewSearch","ViewSettings","Router","Routes","Events","Helper","Pending","Drawer","SELECTORS","routes","VIEW_CONTACT","show","description","VIEW_CONTACTS","VIEW_CONVERSATION","VIEW_GROUP_INFO","VIEW_OVERVIEW","VIEW_SEARCH","VIEW_SETTINGS","createRoutes","namespace","root","forEach","route","add","selector","header","find","length","body","footer","getParametersForRoute","attr","go","drawerRoot","getDrawerRoot","hide","setJumpFrom","buttonid","registerEventListeners","alwaysVisible","events","activate","paramRegex","on","e","data","element","target","closest","attributes","i","push","paramAttributes","filter","attribute","name","nodeName","test","sort","a","b","aParts","exec","bParts","aIndex","bIndex","params","map","nodeValue","routeParams","concat","apply","originalEvent","preventDefault","back","pendingPromise","one","resolve","focus","firstInput","button","this","subscribe","SHOW","HIDE","TOGGLE_VISIBILITY","buttonElement","document","getElementById","isVisible","setAttribute","SHOW_CONVERSATION","args","conversationid","publish","CREATE_CONVERSATION_WITH_USER","userid","SHOW_SETTINGS","PREFERENCES_UPDATED","preferences","filteredPreferences","preference","type","enterToSendPreference","value","init","uniqueId","path","markDrawerReady"],"mappings":";;;;;;;AAsBAA,qCACA,CACI,SACA,iCACA,cACA,2CACA,4CACA,gDACA,8CACA,4CACA,0CACA,4CACA,qCACA,qCACA,qCACA,qCACA,eACA,gBAEJ,SACIC,EACAC,aACAC,OACAC,YACAC,aACAC,iBACAC,cACAC,aACAC,WACAC,aACAC,OACAC,OACAC,OACAC,OACAC,QACAC,YAGIC,iBACQ,oCADRA,iBAEQ,yCAFRA,+BAGsB,uCAHtBA,iCAIwB,yCAJxBA,uBAKc,+BALdA,wBAMe,gCANfA,4BAOmB,oCAPnBA,0BAQiB,kCARjBA,wBASe,gCATfA,sBAUa,8BAVbA,wBAWe,gCAXfA,iBAYQ,eAZRA,sBAaa,oBAbbA,2BAckB,mCAdlBA,yBAegB,iCAfhBA,2BAgBkB,mCAhBlBA,uBAiBc,8BAgCdC,OAAS,CACT,CAACN,OAAOO,aAAcF,uBAAwBb,YAAYgB,KAAMhB,YAAYiB,aAC5E,CAACT,OAAOU,cAAeL,wBAAyBZ,aAAae,KAAMf,aAAagB,aAChF,CAACT,OAAOW,kBAAmBN,4BAA6BX,iBAAiBc,KAAMd,iBAAiBe,aAChG,CAACT,OAAOY,gBAAiBP,0BAA2BV,cAAca,KAAMb,cAAcc,aACtF,CAACT,OAAOa,cAAeR,wBAAyBT,aAAaY,KAAMZ,aAAaa,aAChF,CAACT,OAAOc,YAAaT,sBAAuBR,WAAWW,KAAMX,WAAWY,aACxE,CAACT,OAAOe,cAAeV,wBAAyBP,aAAaU,KAAMV,aAAaW,cAShFO,aAAe,SAASC,UAAWC,MACnCZ,OAAOa,SAAQ,SAASC,OACpBrB,OAAOsB,IAAIJ,UAAWG,MAAM,GAtCR,SAASH,UAAWC,KAAMI,cAE9CC,OAASL,KAAKM,KAAKnB,4BAA4BmB,KAAKF,UACnDC,OAAOE,SACRF,OAASL,KAAKM,KAAKnB,kCAAkCmB,KAAKF,eAE1DI,KAAOR,KAAKM,KAAKnB,0BAA0BmB,KAAKF,UAC/CI,KAAKD,SACNC,KAAOR,KAAKM,KAAKnB,gCAAgCmB,KAAKF,eAEtDK,OAAST,KAAKM,KAAKnB,4BAA4BmB,KAAKF,gBAEjD,CACHL,UACAM,OAAOE,OAASF,OAAS,KACzBG,KAAKD,OAASC,KAAO,KACrBC,OAAOF,OAASE,OAAS,MAsBOC,CAAsBX,UAAWC,KAAME,MAAM,IAAKA,MAAM,GAAIA,MAAM,QAUtGZ,KAAO,SAASS,UAAWC,MACtBA,KAAKW,KAAK,gBACX9B,OAAO+B,GAAGb,UAAWjB,OAAOa,eAC5BK,KAAKW,KAAK,cAAc,QAGxBE,WAAa3B,OAAO4B,cAAcd,MAClCa,WAAWN,QACXrB,OAAOI,KAAKuB,aAShBE,KAAO,SAASf,UACZa,WAAa3B,OAAO4B,cAAcd,MAClCa,WAAWN,QACXrB,OAAO6B,KAAKF,aAuBhBG,YAAc,SAASC,UACvB9C,EAAEgB,kBAAkBwB,KAAK,cAAeM,WAUxCC,uBAAyB,SAASnB,UAAWC,KAAMmB,eACnD/C,aAAaF,OAAO8B,KAAM,CAAC5B,aAAagD,OAAOC,eAC3CC,WAAa,4BAEjBtB,KAAKuB,GAAGnD,aAAagD,OAAOC,SAAUlC,kBAAkB,SAASqC,EAAGC,cAC5DC,QAAUvD,EAAEqD,EAAEG,QAAQC,QAAQzC,kBAC9Be,MAAQwB,QAAQf,KAAK,cACrBkB,WAAa,GAERC,EAAI,EAAGA,EAAIJ,QAAQ,GAAGG,WAAWtB,OAAQuB,IAC9CD,WAAWE,KAAKL,QAAQ,GAAGG,WAAWC,QAGtCE,gBAAkBH,WAAWI,QAAO,SAASC,eACzCC,KAAOD,UAAUE,gBACTd,WAAWe,KAAKF,SAGhCH,gBAAgBM,MAAK,SAASC,EAAGC,OACzBC,OAASnB,WAAWoB,KAAKH,EAAEH,UAC3BO,OAASrB,WAAWoB,KAAKF,EAAEJ,UAC3BQ,OAASH,OAAOlC,OAAS,EAAIkC,OAAO,GAAK,EACzCI,OAASF,OAAOpC,OAAS,EAAIoC,OAAO,GAAK,SAEzCC,OAASC,QACD,EACDA,OAASD,OACT,EAEA,SAIXE,OAASd,gBAAgBe,KAAI,SAASb,kBAC/BA,UAAUc,aAGjBC,YAAc,CAAClD,UAAWG,OAAOgD,OAAOJ,QAE5CjE,OAAO+B,GAAGuC,MAAM,KAAMF,aAEtBxB,KAAK2B,cAAcC,oBAGvBrD,KAAKuB,GAAGnD,aAAagD,OAAOC,SAAUlC,uBAAuB,SAASqC,EAAGC,MACrE5C,OAAOyE,KAAKvD,WAEZ0B,KAAK2B,cAAcC,oBAKvBrD,KAAKuB,GAAG,mBAAoB,aAAa,SAASC,OAC1C+B,eAAiB,IAAItE,QACzBd,EAAEqD,EAAEG,QAAQ6B,IAAI,sBAAsB,WAClCD,eAAeE,gBAIvBzD,KAAKuB,GAAG,mBAAoB,aAAa,SAASC,OAC1C+B,eAAiB,IAAItE,QACzBd,EAAEqD,EAAEG,QAAQ6B,IAAI,qBAAqB,WACjCD,eAAeE,gBAIvBtF,EAAEgB,kBAAkBuE,OAAM,eAClBC,WAAa3D,KAAKM,KAAKnB,wBACvBwE,WAAWpD,OACXoD,WAAWD,QAEXvF,EAAEgB,4BAA4BmB,KAAKnB,uBAAuBuE,WAIlEvF,EAAEgB,kBAAkBuE,OAAM,eAClBE,OAASzF,EAAE0F,MAAMlD,KAAK,eACtBiD,QACAzF,EAAE,IAAMyF,QAAQF,WAInBvC,gBACD9C,OAAOyF,UAAU/E,OAAOgF,MAAM,WAC1BzE,KAAKS,UAAWC,SAGpB3B,OAAOyF,UAAU/E,OAAOiF,MAAM,WAC1BjD,KAAKf,SAGT3B,OAAOyF,UAAU/E,OAAOkF,mBAAmB,SAAShD,gBAC1CiD,cAAgBC,SAASC,eAAenD,WApH1C,SAASjB,UACjBa,WAAa3B,OAAO4B,cAAcd,aAClCa,WAAWN,QACJrB,OAAOmF,UAAUxD,YAkHhBwD,CAAUrE,OAKVV,KAAKS,UAAWC,MAChBkE,MAAAA,eAAAA,cAAeI,aAAa,iBAAiB,GAC7CtD,YAAYC,UACZ9C,EAAEgB,kBAAkBwB,KAAK,WAAY,KAPrCI,KAAKf,MACLkE,MAAAA,eAAAA,cAAeI,aAAa,iBAAiB,GAC7CnG,EAAEgB,kBAAkBwB,KAAK,YAAa,QAUlDtC,OAAOyF,UAAU/E,OAAOwF,mBAAmB,SAASC,MAChDxD,YAAYwD,KAAKvD,UACjB3B,KAAKS,UAAWC,MAChBnB,OAAO+B,GAAGb,UAAWjB,OAAOW,kBAAmB+E,KAAKC,mBAGtCzE,KAAKM,KAAKnB,wBAChBoC,GAAGnD,aAAagD,OAAOC,UAAU,SAASG,EAAGC,MACrDA,KAAK2B,cAAcC,qBAEfO,OAASzF,EAAEgB,kBAAkBwB,KAAK,eAClCiD,QACAzF,EAAE,IAAMyF,QAAQF,QAEpBrF,OAAOqG,QAAQ3F,OAAOkF,kBAAmBL,WAG7CvF,OAAOyF,UAAU/E,OAAO4F,+BAA+B,SAASH,MAC5DxD,YAAYwD,KAAKvD,UACjB3B,KAAKS,UAAWC,MAChBnB,OAAO+B,GAAGb,UAAWjB,OAAOW,kBAAmB,KAAM,SAAU+E,KAAKI,WAGxEvG,OAAOyF,UAAU/E,OAAO8F,eAAe,WACnCvF,KAAKS,UAAWC,MAChBnB,OAAO+B,GAAGb,UAAWjB,OAAOe,kBAGhCxB,OAAOyF,UAAU/E,OAAO+F,qBAAqB,SAASC,iBAC9CC,oBAAsBD,YAAY9C,QAAO,SAASgD,kBACxB,uBAAnBA,WAAWC,QAElBC,sBAAwBH,oBAAoBzE,OAASyE,oBAAoB,GAAK,KAE9EG,uBAC6BnF,KAAKM,KAAKnB,4BAA4BmB,KAAKnB,6BACjDwB,KAAK,qBAAsBwE,sBAAsBC,iBAgC7E,CACHC,KApBO,SAASrF,KAAMsF,SAAUnE,cAAejB,UAC/CF,KAAO7B,EAAE6B,MACTF,aAAawF,SAAUtF,MACvBkB,uBAAuBoE,SAAUtF,KAAMmB,eAEnCA,gBACA7B,KAAKgG,SAAUtF,MAEXE,OAAO,KACH+C,YAAc/C,MAAM4C,QAAU,GAClCG,YAAc,CAACqC,SAAUpF,MAAMqF,MAAMrC,OAAOD,aAC5CpE,OAAO+B,GAAGuC,MAAM,KAAMF,aAK9BjE,OAAOwG"} \ No newline at end of file +{"version":3,"file":"message_drawer.min.js","sources":["../src/message_drawer.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 message drawer.\n *\n * @module core_message/message_drawer\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_view_contact',\n 'core_message/message_drawer_view_contacts',\n 'core_message/message_drawer_view_conversation',\n 'core_message/message_drawer_view_group_info',\n 'core_message/message_drawer_view_overview',\n 'core_message/message_drawer_view_search',\n 'core_message/message_drawer_view_settings',\n 'core_message/message_drawer_router',\n 'core_message/message_drawer_routes',\n 'core_message/message_drawer_events',\n 'core_message/message_drawer_helper',\n 'core/pending',\n 'core/drawer',\n 'core/toast',\n 'core/str',\n 'core/config',\n 'core/ajax',\n 'core/local/aria/focuslock',\n 'core/modal_backdrop',\n 'core/templates',\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n ViewContact,\n ViewContacts,\n ViewConversation,\n ViewGroupInfo,\n ViewOverview,\n ViewSearch,\n ViewSettings,\n Router,\n Routes,\n Events,\n Helper,\n Pending,\n Drawer,\n Toast,\n Str,\n Config,\n Ajax,\n FocusLock,\n ModalBackdrop,\n Templates,\n) {\n\n var SELECTORS = {\n DRAWER: '[data-region=\"right-hand-drawer\"]',\n JUMPTO: '.popover-region [data-region=\"jumpto\"]',\n PANEL_BODY_CONTAINER: '[data-region=\"panel-body-container\"]',\n PANEL_HEADER_CONTAINER: '[data-region=\"panel-header-container\"]',\n VIEW_CONTACT: '[data-region=\"view-contact\"]',\n VIEW_CONTACTS: '[data-region=\"view-contacts\"]',\n VIEW_CONVERSATION: '[data-region=\"view-conversation\"]',\n VIEW_GROUP_INFO: '[data-region=\"view-group-info\"]',\n VIEW_OVERVIEW: '[data-region=\"view-overview\"]',\n VIEW_SEARCH: '[data-region=\"view-search\"]',\n VIEW_SETTINGS: '[data-region=\"view-settings\"]',\n ROUTES: '[data-route]',\n ROUTES_BACK: '[data-route-back]',\n HEADER_CONTAINER: '[data-region=\"header-container\"]',\n BODY_CONTAINER: '[data-region=\"body-container\"]',\n FOOTER_CONTAINER: '[data-region=\"footer-container\"]',\n CLOSE_BUTTON: '[data-action=\"closedrawer\"]'\n };\n\n /**\n * Get elements for route.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n * @param {string} selector The route container.\n *\n * @return {array} elements Found route container objects.\n */\n var getParametersForRoute = function(namespace, root, selector) {\n\n var header = root.find(SELECTORS.HEADER_CONTAINER).find(selector);\n if (!header.length) {\n header = root.find(SELECTORS.PANEL_HEADER_CONTAINER).find(selector);\n }\n var body = root.find(SELECTORS.BODY_CONTAINER).find(selector);\n if (!body.length) {\n body = root.find(SELECTORS.PANEL_BODY_CONTAINER).find(selector);\n }\n var footer = root.find(SELECTORS.FOOTER_CONTAINER).find(selector);\n\n return [\n namespace,\n header.length ? header : null,\n body.length ? body : null,\n footer.length ? footer : null\n ];\n };\n\n var routes = [\n [Routes.VIEW_CONTACT, SELECTORS.VIEW_CONTACT, ViewContact.show, ViewContact.description],\n [Routes.VIEW_CONTACTS, SELECTORS.VIEW_CONTACTS, ViewContacts.show, ViewContacts.description],\n [Routes.VIEW_CONVERSATION, SELECTORS.VIEW_CONVERSATION, ViewConversation.show, ViewConversation.description],\n [Routes.VIEW_GROUP_INFO, SELECTORS.VIEW_GROUP_INFO, ViewGroupInfo.show, ViewGroupInfo.description],\n [Routes.VIEW_OVERVIEW, SELECTORS.VIEW_OVERVIEW, ViewOverview.show, ViewOverview.description],\n [Routes.VIEW_SEARCH, SELECTORS.VIEW_SEARCH, ViewSearch.show, ViewSearch.description],\n [Routes.VIEW_SETTINGS, SELECTORS.VIEW_SETTINGS, ViewSettings.show, ViewSettings.description]\n ];\n\n /**\n * Create routes.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n */\n var createRoutes = function(namespace, root) {\n routes.forEach(function(route) {\n Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);\n });\n };\n\n let backdropPromise = null;\n\n /**\n * Set the focus on the drawer.\n *\n * This method also creates or destroy any necessary backdrop zone and focus trap.\n *\n * @param {Object} root The message drawer container.\n * @param {Boolean} hasFocus Whether the drawer has focus or not.\n */\n var setFocus = function(root, hasFocus) {\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (!drawerRoot.length) {\n return;\n }\n if (!backdropPromise) {\n backdropPromise = Templates.render('core/modal_backdrop', {})\n .then(html => new ModalBackdrop(html));\n }\n const backdropWithAdjustments = backdropPromise.then(modalBackdrop => {\n const messageDrawerZIndex = window.getComputedStyle(drawerRoot[0]).zIndex;\n if (messageDrawerZIndex) {\n modalBackdrop.setZIndex(messageDrawerZIndex - 1);\n }\n modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => {\n PubSub.publish(Events.HIDE, {});\n e.preventDefault();\n });\n return modalBackdrop;\n });\n if (hasFocus) {\n FocusLock.trapFocus(root[0]);\n // eslint-disable-next-line promise/catch-or-return\n backdropWithAdjustments.then(modalBackdrop => {\n if (modalBackdrop) {\n modalBackdrop.show();\n const pageWrapper = document.getElementById('page');\n pageWrapper.style.overflow = 'hidden';\n // Set the focus on the close button so when we press enter, it closes the drawer as it did before\n var closeButton = root.find(SELECTORS.CLOSE_BUTTON);\n if (closeButton.length) {\n closeButton.focus();\n }\n }\n return modalBackdrop;\n });\n } else {\n // eslint-disable-next-line promise/catch-or-return\n backdropWithAdjustments.then(modalBackdrop => {\n if (modalBackdrop) {\n FocusLock.untrapFocus();\n var button = $(SELECTORS.DRAWER).attr('data-origin');\n if (button) {\n $('#' + button).focus();\n }\n modalBackdrop.hide();\n const pageWrapper = document.getElementById('page');\n pageWrapper.style.overflow = 'visible';\n }\n return modalBackdrop;\n });\n }\n };\n /**\n * Show the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n */\n var show = function(namespace, root) {\n if (!root.attr('data-shown')) {\n Router.go(namespace, Routes.VIEW_OVERVIEW);\n root.attr('data-shown', true);\n }\n\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n setFocus(root, true);\n Drawer.show(drawerRoot);\n }\n };\n\n /**\n * Hide the message drawer.\n *\n * @param {Object} root The message drawer container.\n */\n var hide = function(root) {\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n setFocus(root, false);\n Drawer.hide(drawerRoot);\n }\n };\n\n /**\n * Check if the drawer is visible.\n *\n * @param {Object} root The message drawer container.\n * @return {boolean}\n */\n var isVisible = function(root) {\n var drawerRoot = Drawer.getDrawerRoot(root);\n if (drawerRoot.length) {\n return Drawer.isVisible(drawerRoot);\n }\n return true;\n };\n\n /**\n * Set Jump from button\n *\n * @param {String} buttonid The originating button id\n */\n var setJumpFrom = function(buttonid) {\n $(SELECTORS.DRAWER).attr('data-origin', buttonid);\n };\n\n /**\n * Listen to and handle events for routing, showing and hiding the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n * @param {bool} alwaysVisible Is this messaging app always shown?\n */\n var registerEventListeners = function(namespace, root, alwaysVisible) {\n CustomEvents.define(root, [CustomEvents.events.activate, CustomEvents.events.escape]);\n var paramRegex = /^data-route-param-?(\\d*)$/;\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {\n var element = $(e.target).closest(SELECTORS.ROUTES);\n var route = element.attr('data-route');\n var attributes = [];\n\n for (var i = 0; i < element[0].attributes.length; i++) {\n attributes.push(element[0].attributes[i]);\n }\n\n var paramAttributes = attributes.filter(function(attribute) {\n var name = attribute.nodeName;\n var match = paramRegex.test(name);\n return match;\n });\n paramAttributes.sort(function(a, b) {\n var aParts = paramRegex.exec(a.nodeName);\n var bParts = paramRegex.exec(b.nodeName);\n var aIndex = aParts.length > 1 ? aParts[1] : 0;\n var bIndex = bParts.length > 1 ? bParts[1] : 0;\n\n if (aIndex < bIndex) {\n return -1;\n } else if (bIndex < aIndex) {\n return 1;\n } else {\n return 0;\n }\n });\n\n var params = paramAttributes.map(function(attribute) {\n return attribute.nodeValue;\n });\n\n var routeParams = [namespace, route].concat(params);\n\n Router.go.apply(null, routeParams);\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES_BACK, function(e, data) {\n Router.back(namespace);\n\n data.originalEvent.preventDefault();\n });\n\n // These are theme-specific to help us fix random behat fails.\n // These events target those events defined in BS3 and BS4 onwards.\n root.on('hide.bs.collapse', '.collapse', function(e) {\n var pendingPromise = new Pending();\n $(e.target).one('hidden.bs.collapse', function() {\n pendingPromise.resolve();\n });\n });\n\n root.on('show.bs.collapse', '.collapse', function(e) {\n var pendingPromise = new Pending();\n $(e.target).one('shown.bs.collapse', function() {\n pendingPromise.resolve();\n });\n });\n\n $(SELECTORS.JUMPTO).focus(function() {\n var firstInput = root.find(SELECTORS.CLOSE_BUTTON);\n if (firstInput.length) {\n firstInput.focus();\n } else {\n $(SELECTORS.HEADER_CONTAINER).find(SELECTORS.ROUTES_BACK).focus();\n }\n });\n\n $(SELECTORS.DRAWER).focus(function() {\n var button = $(this).attr('data-origin');\n if (button) {\n $('#' + button).focus();\n }\n });\n\n if (!alwaysVisible) {\n PubSub.subscribe(Events.SHOW, function() {\n show(namespace, root);\n });\n\n PubSub.subscribe(Events.HIDE, function() {\n hide(root);\n });\n\n PubSub.subscribe(Events.TOGGLE_VISIBILITY, function(buttonid) {\n const buttonElement = document.getElementById(buttonid);\n if (isVisible(root)) {\n hide(root);\n buttonElement?.setAttribute('aria-expanded', false);\n $(SELECTORS.JUMPTO).attr('tabindex', -1);\n } else {\n show(namespace, root);\n buttonElement?.setAttribute('aria-expanded', true);\n setJumpFrom(buttonid);\n $(SELECTORS.JUMPTO).attr('tabindex', 0);\n }\n });\n root.on(CustomEvents.events.escape, function() {\n PubSub.publish(Events.HIDE, {});\n });\n }\n\n PubSub.subscribe(Events.SHOW_CONVERSATION, function(args) {\n setJumpFrom(args.buttonid);\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, args.conversationid);\n });\n\n var closebutton = root.find(SELECTORS.CLOSE_BUTTON);\n closebutton.on(CustomEvents.events.activate, function(e, data) {\n data.originalEvent.preventDefault();\n setFocus(root, false);\n var button = $(SELECTORS.DRAWER).attr('data-origin');\n if (button) {\n $('#' + button).focus();\n }\n PubSub.publish(Events.TOGGLE_VISIBILITY, button);\n });\n\n PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(args) {\n setJumpFrom(args.buttonid);\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, null, 'create', args.userid);\n });\n\n PubSub.subscribe(Events.SHOW_SETTINGS, function() {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_SETTINGS);\n });\n\n PubSub.subscribe(Events.PREFERENCES_UPDATED, function(preferences) {\n var filteredPreferences = preferences.filter(function(preference) {\n return preference.type == 'message_entertosend';\n });\n var enterToSendPreference = filteredPreferences.length ? filteredPreferences[0] : null;\n\n if (enterToSendPreference) {\n var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);\n viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);\n }\n });\n };\n\n /**\n * Initialise the message drawer.\n *\n * @param {Object} root The message drawer container.\n * @param {String} uniqueId Unique identifier for the Routes\n * @param {bool} alwaysVisible Should we show the app now, or wait for the user?\n * @param {Object} route\n */\n var init = function(root, uniqueId, alwaysVisible, route) {\n root = $(root);\n createRoutes(uniqueId, root);\n registerEventListeners(uniqueId, root, alwaysVisible);\n\n if (alwaysVisible) {\n show(uniqueId, root);\n\n if (route) {\n var routeParams = route.params || [];\n routeParams = [uniqueId, route.path].concat(routeParams);\n Router.go.apply(null, routeParams);\n }\n }\n\n // Mark the drawer as ready.\n Helper.markDrawerReady();\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CustomEvents","PubSub","ViewContact","ViewContacts","ViewConversation","ViewGroupInfo","ViewOverview","ViewSearch","ViewSettings","Router","Routes","Events","Helper","Pending","Drawer","Toast","Str","Config","Ajax","FocusLock","ModalBackdrop","Templates","SELECTORS","routes","VIEW_CONTACT","show","description","VIEW_CONTACTS","VIEW_CONVERSATION","VIEW_GROUP_INFO","VIEW_OVERVIEW","VIEW_SEARCH","VIEW_SETTINGS","createRoutes","namespace","root","forEach","route","add","selector","header","find","length","body","footer","getParametersForRoute","backdropPromise","setFocus","hasFocus","drawerRoot","getDrawerRoot","render","then","html","backdropWithAdjustments","modalBackdrop","messageDrawerZIndex","window","getComputedStyle","zIndex","setZIndex","getAttachmentPoint","get","addEventListener","e","publish","HIDE","preventDefault","trapFocus","document","getElementById","style","overflow","closeButton","focus","untrapFocus","button","attr","hide","go","setJumpFrom","buttonid","registerEventListeners","alwaysVisible","events","activate","escape","paramRegex","on","data","element","target","closest","attributes","i","push","paramAttributes","filter","attribute","name","nodeName","test","sort","a","b","aParts","exec","bParts","aIndex","bIndex","params","map","nodeValue","routeParams","concat","apply","originalEvent","back","pendingPromise","one","resolve","firstInput","this","subscribe","SHOW","TOGGLE_VISIBILITY","buttonElement","isVisible","setAttribute","SHOW_CONVERSATION","args","conversationid","CREATE_CONVERSATION_WITH_USER","userid","SHOW_SETTINGS","PREFERENCES_UPDATED","preferences","filteredPreferences","preference","type","enterToSendPreference","value","init","uniqueId","path","markDrawerReady"],"mappings":";;;;;;;AAsBAA,qCACA,CACI,SACA,iCACA,cACA,2CACA,4CACA,gDACA,8CACA,4CACA,0CACA,4CACA,qCACA,qCACA,qCACA,qCACA,eACA,cACA,aACA,WACA,cACA,YACA,4BACA,sBACA,mBAEJ,SACIC,EACAC,aACAC,OACAC,YACAC,aACAC,iBACAC,cACAC,aACAC,WACAC,aACAC,OACAC,OACAC,OACAC,OACAC,QACAC,OACAC,MACAC,IACAC,OACAC,KACAC,UACAC,cACAC,eAGIC,iBACQ,oCADRA,iBAEQ,yCAFRA,+BAGsB,uCAHtBA,iCAIwB,yCAJxBA,uBAKc,+BALdA,wBAMe,gCANfA,4BAOmB,oCAPnBA,0BAQiB,kCARjBA,wBASe,gCATfA,sBAUa,8BAVbA,wBAWe,gCAXfA,iBAYQ,eAZRA,sBAaa,oBAbbA,2BAckB,mCAdlBA,yBAegB,iCAfhBA,2BAgBkB,mCAhBlBA,uBAiBc,8BAgCdC,OAAS,CACT,CAACb,OAAOc,aAAcF,uBAAwBpB,YAAYuB,KAAMvB,YAAYwB,aAC5E,CAAChB,OAAOiB,cAAeL,wBAAyBnB,aAAasB,KAAMtB,aAAauB,aAChF,CAAChB,OAAOkB,kBAAmBN,4BAA6BlB,iBAAiBqB,KAAMrB,iBAAiBsB,aAChG,CAAChB,OAAOmB,gBAAiBP,0BAA2BjB,cAAcoB,KAAMpB,cAAcqB,aACtF,CAAChB,OAAOoB,cAAeR,wBAAyBhB,aAAamB,KAAMnB,aAAaoB,aAChF,CAAChB,OAAOqB,YAAaT,sBAAuBf,WAAWkB,KAAMlB,WAAWmB,aACxE,CAAChB,OAAOsB,cAAeV,wBAAyBd,aAAaiB,KAAMjB,aAAakB,cAShFO,aAAe,SAASC,UAAWC,MACnCZ,OAAOa,SAAQ,SAASC,OACpB5B,OAAO6B,IAAIJ,UAAWG,MAAM,GAtCR,SAASH,UAAWC,KAAMI,cAE9CC,OAASL,KAAKM,KAAKnB,4BAA4BmB,KAAKF,UACnDC,OAAOE,SACRF,OAASL,KAAKM,KAAKnB,kCAAkCmB,KAAKF,eAE1DI,KAAOR,KAAKM,KAAKnB,0BAA0BmB,KAAKF,UAC/CI,KAAKD,SACNC,KAAOR,KAAKM,KAAKnB,gCAAgCmB,KAAKF,eAEtDK,OAAST,KAAKM,KAAKnB,4BAA4BmB,KAAKF,gBAEjD,CACHL,UACAM,OAAOE,OAASF,OAAS,KACzBG,KAAKD,OAASC,KAAO,KACrBC,OAAOF,OAASE,OAAS,MAsBOC,CAAsBX,UAAWC,KAAME,MAAM,IAAKA,MAAM,GAAIA,MAAM,YAItGS,gBAAkB,SAUlBC,SAAW,SAASZ,KAAMa,cACtBC,WAAanC,OAAOoC,cAAcf,UACjCc,WAAWP,cAGXI,kBACDA,gBAAkBzB,UAAU8B,OAAO,sBAAuB,IACrDC,MAAKC,MAAQ,IAAIjC,cAAciC,eAElCC,wBAA0BR,gBAAgBM,MAAKG,sBAC3CC,oBAAsBC,OAAOC,iBAAiBT,WAAW,IAAIU,cAC/DH,qBACAD,cAAcK,UAAUJ,oBAAsB,GAElDD,cAAcM,qBAAqBC,IAAI,GAAGC,iBAAiB,SAASC,IAChE/D,OAAOgE,QAAQtD,OAAOuD,KAAM,IAC5BF,EAAEG,oBAECZ,iBAEPP,UACA7B,UAAUiD,UAAUjC,KAAK,IAEzBmB,wBAAwBF,MAAKG,mBACrBA,cAAe,CACfA,cAAc9B,OACM4C,SAASC,eAAe,QAChCC,MAAMC,SAAW,aAEzBC,YAActC,KAAKM,KAAKnB,wBACxBmD,YAAY/B,QACZ+B,YAAYC,eAGbnB,kBAIXD,wBAAwBF,MAAKG,mBACrBA,cAAe,CACfpC,UAAUwD,kBACNC,OAAS7E,EAAEuB,kBAAkBuD,KAAK,eAClCD,QACA7E,EAAE,IAAM6E,QAAQF,QAEpBnB,cAAcuB,OACMT,SAASC,eAAe,QAChCC,MAAMC,SAAW,iBAE1BjB,kBAUf9B,KAAO,SAASS,UAAWC,MACtBA,KAAK0C,KAAK,gBACXpE,OAAOsE,GAAG7C,UAAWxB,OAAOoB,eAC5BK,KAAK0C,KAAK,cAAc,QAGxB5B,WAAanC,OAAOoC,cAAcf,MAClCc,WAAWP,SACXK,SAASZ,MAAM,GACfrB,OAAOW,KAAKwB,cAShB6B,KAAO,SAAS3C,UACZc,WAAanC,OAAOoC,cAAcf,MAClCc,WAAWP,SACXK,SAASZ,MAAM,GACfrB,OAAOgE,KAAK7B,cAuBhB+B,YAAc,SAASC,UACvBlF,EAAEuB,kBAAkBuD,KAAK,cAAeI,WAUxCC,uBAAyB,SAAShD,UAAWC,KAAMgD,eACnDnF,aAAaF,OAAOqC,KAAM,CAACnC,aAAaoF,OAAOC,SAAUrF,aAAaoF,OAAOE,aACzEC,WAAa,4BAEjBpD,KAAKqD,GAAGxF,aAAaoF,OAAOC,SAAU/D,kBAAkB,SAAS0C,EAAGyB,cAC5DC,QAAU3F,EAAEiE,EAAE2B,QAAQC,QAAQtE,kBAC9Be,MAAQqD,QAAQb,KAAK,cACrBgB,WAAa,GAERC,EAAI,EAAGA,EAAIJ,QAAQ,GAAGG,WAAWnD,OAAQoD,IAC9CD,WAAWE,KAAKL,QAAQ,GAAGG,WAAWC,QAGtCE,gBAAkBH,WAAWI,QAAO,SAASC,eACzCC,KAAOD,UAAUE,gBACTb,WAAWc,KAAKF,SAGhCH,gBAAgBM,MAAK,SAASC,EAAGC,OACzBC,OAASlB,WAAWmB,KAAKH,EAAEH,UAC3BO,OAASpB,WAAWmB,KAAKF,EAAEJ,UAC3BQ,OAASH,OAAO/D,OAAS,EAAI+D,OAAO,GAAK,EACzCI,OAASF,OAAOjE,OAAS,EAAIiE,OAAO,GAAK,SAEzCC,OAASC,QACD,EACDA,OAASD,OACT,EAEA,SAIXE,OAASd,gBAAgBe,KAAI,SAASb,kBAC/BA,UAAUc,aAGjBC,YAAc,CAAC/E,UAAWG,OAAO6E,OAAOJ,QAE5CrG,OAAOsE,GAAGoC,MAAM,KAAMF,aAEtBxB,KAAK2B,cAAcjD,oBAGvBhC,KAAKqD,GAAGxF,aAAaoF,OAAOC,SAAU/D,uBAAuB,SAAS0C,EAAGyB,MACrEhF,OAAO4G,KAAKnF,WAEZuD,KAAK2B,cAAcjD,oBAKvBhC,KAAKqD,GAAG,mBAAoB,aAAa,SAASxB,OAC1CsD,eAAiB,IAAIzG,QACzBd,EAAEiE,EAAE2B,QAAQ4B,IAAI,sBAAsB,WAClCD,eAAeE,gBAIvBrF,KAAKqD,GAAG,mBAAoB,aAAa,SAASxB,OAC1CsD,eAAiB,IAAIzG,QACzBd,EAAEiE,EAAE2B,QAAQ4B,IAAI,qBAAqB,WACjCD,eAAeE,gBAIvBzH,EAAEuB,kBAAkBoD,OAAM,eAClB+C,WAAatF,KAAKM,KAAKnB,wBACvBmG,WAAW/E,OACX+E,WAAW/C,QAEX3E,EAAEuB,4BAA4BmB,KAAKnB,uBAAuBoD,WAIlE3E,EAAEuB,kBAAkBoD,OAAM,eAClBE,OAAS7E,EAAE2H,MAAM7C,KAAK,eACtBD,QACA7E,EAAE,IAAM6E,QAAQF,WAInBS,gBACDlF,OAAO0H,UAAUhH,OAAOiH,MAAM,WAC1BnG,KAAKS,UAAWC,SAGpBlC,OAAO0H,UAAUhH,OAAOuD,MAAM,WAC1BY,KAAK3C,SAGTlC,OAAO0H,UAAUhH,OAAOkH,mBAAmB,SAAS5C,gBAC1C6C,cAAgBzD,SAASC,eAAeW,WApH1C,SAAS9C,UACjBc,WAAanC,OAAOoC,cAAcf,aAClCc,WAAWP,QACJ5B,OAAOiH,UAAU9E,YAkHhB8E,CAAU5F,OAKVV,KAAKS,UAAWC,MAChB2F,MAAAA,eAAAA,cAAeE,aAAa,iBAAiB,GAC7ChD,YAAYC,UACZlF,EAAEuB,kBAAkBuD,KAAK,WAAY,KAPrCC,KAAK3C,MACL2F,MAAAA,eAAAA,cAAeE,aAAa,iBAAiB,GAC7CjI,EAAEuB,kBAAkBuD,KAAK,YAAa,OAQ9C1C,KAAKqD,GAAGxF,aAAaoF,OAAOE,QAAQ,WAChCrF,OAAOgE,QAAQtD,OAAOuD,KAAM,QAIpCjE,OAAO0H,UAAUhH,OAAOsH,mBAAmB,SAASC,MAChDlD,YAAYkD,KAAKjD,UACjBxD,KAAKS,UAAWC,MAChB1B,OAAOsE,GAAG7C,UAAWxB,OAAOkB,kBAAmBsG,KAAKC,mBAGtChG,KAAKM,KAAKnB,wBAChBkE,GAAGxF,aAAaoF,OAAOC,UAAU,SAASrB,EAAGyB,MACrDA,KAAK2B,cAAcjD,iBACnBpB,SAASZ,MAAM,OACXyC,OAAS7E,EAAEuB,kBAAkBuD,KAAK,eAClCD,QACA7E,EAAE,IAAM6E,QAAQF,QAEpBzE,OAAOgE,QAAQtD,OAAOkH,kBAAmBjD,WAG7C3E,OAAO0H,UAAUhH,OAAOyH,+BAA+B,SAASF,MAC5DlD,YAAYkD,KAAKjD,UACjBxD,KAAKS,UAAWC,MAChB1B,OAAOsE,GAAG7C,UAAWxB,OAAOkB,kBAAmB,KAAM,SAAUsG,KAAKG,WAGxEpI,OAAO0H,UAAUhH,OAAO2H,eAAe,WACnC7G,KAAKS,UAAWC,MAChB1B,OAAOsE,GAAG7C,UAAWxB,OAAOsB,kBAGhC/B,OAAO0H,UAAUhH,OAAO4H,qBAAqB,SAASC,iBAC9CC,oBAAsBD,YAAYvC,QAAO,SAASyC,kBACxB,uBAAnBA,WAAWC,QAElBC,sBAAwBH,oBAAoB/F,OAAS+F,oBAAoB,GAAK,KAE9EG,uBAC6BzG,KAAKM,KAAKnB,4BAA4BmB,KAAKnB,6BACjDuD,KAAK,qBAAsB+D,sBAAsBC,iBAgC7E,CACHC,KApBO,SAAS3G,KAAM4G,SAAU5D,cAAe9C,UAC/CF,KAAOpC,EAAEoC,MACTF,aAAa8G,SAAU5G,MACvB+C,uBAAuB6D,SAAU5G,KAAMgD,eAEnCA,gBACA1D,KAAKsH,SAAU5G,MAEXE,OAAO,KACH4E,YAAc5E,MAAMyE,QAAU,GAClCG,YAAc,CAAC8B,SAAU1G,MAAM2G,MAAM9B,OAAOD,aAC5CxG,OAAOsE,GAAGoC,MAAM,KAAMF,aAK9BrG,OAAOqI"} \ No newline at end of file diff --git a/message/amd/build/message_popover.min.js b/message/amd/build/message_popover.min.js index 9647468aed2..fdcebfec230 100644 --- a/message/amd/build/message_popover.min.js +++ b/message/amd/build/message_popover.min.js @@ -5,6 +5,6 @@ * @copyright 2018 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("core_message/message_popover",["jquery","core/custom_interaction_events","core/pubsub","core_message/message_drawer_events"],(function($,CustomEvents,PubSub,MessageDrawerEvents){var SELECTORS_COUNT_CONTAINER='[data-region="count-container"]',handleDecrementConversationCount=function(button){return function(){var countContainer=button.find(SELECTORS_COUNT_CONTAINER),count=parseInt(countContainer.text(),10);isNaN(count)||!count||count<2?countContainer.addClass("hidden"):(count-=1,countContainer.text(count))}},registerEventListeners=function(button){CustomEvents.define(button,[CustomEvents.events.activate]),button.on(CustomEvents.events.activate,(function(e,data){var buttonid;buttonid=button.attr("id"),PubSub.publish(MessageDrawerEvents.TOGGLE_VISIBILITY,buttonid),button.focus(),data.originalEvent.preventDefault()})),PubSub.subscribe(MessageDrawerEvents.CONVERSATION_READ,handleDecrementConversationCount(button)),PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED,handleDecrementConversationCount(button)),PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED,handleDecrementConversationCount(button))};return{init:function(button){button=$(button),registerEventListeners(button)}}})); +define("core_message/message_popover",["jquery","core/custom_interaction_events","core/pubsub","core_message/message_drawer_events"],(function($,CustomEvents,PubSub,MessageDrawerEvents){var SELECTORS_COUNT_CONTAINER='[data-region="count-container"]',handleDecrementConversationCount=function(button){return function(){var countContainer=button.find(SELECTORS_COUNT_CONTAINER),count=parseInt(countContainer.text(),10);isNaN(count)||!count||count<2?countContainer.addClass("hidden"):(count-=1,countContainer.text(count))}},registerEventListeners=function(button){CustomEvents.define(button,[CustomEvents.events.activate]),button.on(CustomEvents.events.activate,(function(e,data){var buttonid;buttonid=button.attr("id"),PubSub.publish(MessageDrawerEvents.TOGGLE_VISIBILITY,buttonid),data.originalEvent.preventDefault()})),PubSub.subscribe(MessageDrawerEvents.CONVERSATION_READ,handleDecrementConversationCount(button)),PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED,handleDecrementConversationCount(button)),PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED,handleDecrementConversationCount(button))};return{init:function(button){button=$(button),registerEventListeners(button)}}})); //# sourceMappingURL=message_popover.min.js.map \ No newline at end of file diff --git a/message/amd/build/message_popover.min.js.map b/message/amd/build/message_popover.min.js.map index 541236926a2..30cbc31d4ec 100644 --- a/message/amd/build/message_popover.min.js.map +++ b/message/amd/build/message_popover.min.js.map @@ -1 +1 @@ -{"version":3,"file":"message_popover.min.js","sources":["../src/message_popover.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 message popover in the nav bar.\n *\n * @module core_message/message_popover\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_events'\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n MessageDrawerEvents\n) {\n var SELECTORS = {\n COUNT_CONTAINER: '[data-region=\"count-container\"]'\n };\n\n /**\n * Toggle the message drawer visibility.\n *\n * @param {String} buttonid The button id for the popover.\n */\n var toggleMessageDrawerVisibility = function(buttonid) {\n PubSub.publish(MessageDrawerEvents.TOGGLE_VISIBILITY, buttonid);\n };\n\n /**\n * Decrement the unread conversation count in the nav bar if a conversation\n * is read. When there are no unread conversations then hide the counter.\n *\n * @param {Object} button The button element for the popover.\n * @return {Function}\n */\n var handleDecrementConversationCount = function(button) {\n return function() {\n var countContainer = button.find(SELECTORS.COUNT_CONTAINER);\n var count = parseInt(countContainer.text(), 10);\n\n if (isNaN(count)) {\n countContainer.addClass('hidden');\n } else if (!count || count < 2) {\n countContainer.addClass('hidden');\n } else {\n count = count - 1;\n countContainer.text(count);\n }\n };\n };\n\n /**\n * Add events listeners for when the popover icon is clicked and when conversations\n * are read.\n *\n * @param {Object} button The button element for the popover.\n */\n var registerEventListeners = function(button) {\n CustomEvents.define(button, [CustomEvents.events.activate]);\n\n button.on(CustomEvents.events.activate, function(e, data) {\n toggleMessageDrawerVisibility(button.attr('id'));\n button.focus();\n data.originalEvent.preventDefault();\n });\n\n PubSub.subscribe(MessageDrawerEvents.CONVERSATION_READ, handleDecrementConversationCount(button));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, handleDecrementConversationCount(button));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, handleDecrementConversationCount(button));\n };\n\n /**\n * Initialise the message popover.\n *\n * @param {Object} button The button element for the popover.\n */\n var init = function(button) {\n button = $(button);\n registerEventListeners(button);\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CustomEvents","PubSub","MessageDrawerEvents","SELECTORS","handleDecrementConversationCount","button","countContainer","find","count","parseInt","text","isNaN","addClass","registerEventListeners","events","activate","on","e","data","buttonid","attr","publish","TOGGLE_VISIBILITY","focus","originalEvent","preventDefault","subscribe","CONVERSATION_READ","CONTACT_REQUEST_ACCEPTED","CONTACT_REQUEST_DECLINED","init"],"mappings":";;;;;;;AAsBAA,sCACA,CACI,SACA,iCACA,cACA,uCAEJ,SACIC,EACAC,aACAC,OACAC,yBAEIC,0BACiB,kCAmBjBC,iCAAmC,SAASC,eACrC,eACCC,eAAiBD,OAAOE,KAAKJ,2BAC7BK,MAAQC,SAASH,eAAeI,OAAQ,IAExCC,MAAMH,SAEEA,OAASA,MAAQ,EADzBF,eAAeM,SAAS,WAIxBJ,OAAgB,EAChBF,eAAeI,KAAKF,UAW5BK,uBAAyB,SAASR,QAClCL,aAAaF,OAAOO,OAAQ,CAACL,aAAac,OAAOC,WAEjDV,OAAOW,GAAGhB,aAAac,OAAOC,UAAU,SAASE,EAAGC,MApCpB,IAASC,SAAAA,SAqCPd,OAAOe,KAAK,MApC9CnB,OAAOoB,QAAQnB,oBAAoBoB,kBAAmBH,UAqClDd,OAAOkB,QACPL,KAAKM,cAAcC,oBAGvBxB,OAAOyB,UAAUxB,oBAAoByB,kBAAmBvB,iCAAiCC,SACzFJ,OAAOyB,UAAUxB,oBAAoB0B,yBAA0BxB,iCAAiCC,SAChGJ,OAAOyB,UAAUxB,oBAAoB2B,yBAA0BzB,iCAAiCC,gBAa7F,CACHyB,KANO,SAASzB,QAChBA,OAASN,EAAEM,QACXQ,uBAAuBR"} \ No newline at end of file +{"version":3,"file":"message_popover.min.js","sources":["../src/message_popover.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 message popover in the nav bar.\n *\n * @module core_message/message_popover\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_events'\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n MessageDrawerEvents\n) {\n var SELECTORS = {\n COUNT_CONTAINER: '[data-region=\"count-container\"]'\n };\n\n /**\n * Toggle the message drawer visibility.\n *\n * @param {String} buttonid The button id for the popover.\n */\n var toggleMessageDrawerVisibility = function(buttonid) {\n PubSub.publish(MessageDrawerEvents.TOGGLE_VISIBILITY, buttonid);\n };\n\n /**\n * Decrement the unread conversation count in the nav bar if a conversation\n * is read. When there are no unread conversations then hide the counter.\n *\n * @param {Object} button The button element for the popover.\n * @return {Function}\n */\n var handleDecrementConversationCount = function(button) {\n return function() {\n var countContainer = button.find(SELECTORS.COUNT_CONTAINER);\n var count = parseInt(countContainer.text(), 10);\n\n if (isNaN(count)) {\n countContainer.addClass('hidden');\n } else if (!count || count < 2) {\n countContainer.addClass('hidden');\n } else {\n count = count - 1;\n countContainer.text(count);\n }\n };\n };\n\n /**\n * Add events listeners for when the popover icon is clicked and when conversations\n * are read.\n *\n * @param {Object} button The button element for the popover.\n */\n var registerEventListeners = function(button) {\n CustomEvents.define(button, [CustomEvents.events.activate]);\n\n button.on(CustomEvents.events.activate, function(e, data) {\n toggleMessageDrawerVisibility(button.attr('id'));\n data.originalEvent.preventDefault();\n });\n\n PubSub.subscribe(MessageDrawerEvents.CONVERSATION_READ, handleDecrementConversationCount(button));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, handleDecrementConversationCount(button));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, handleDecrementConversationCount(button));\n };\n\n /**\n * Initialise the message popover.\n *\n * @param {Object} button The button element for the popover.\n */\n var init = function(button) {\n button = $(button);\n registerEventListeners(button);\n };\n\n return {\n init: init,\n };\n});\n"],"names":["define","$","CustomEvents","PubSub","MessageDrawerEvents","SELECTORS","handleDecrementConversationCount","button","countContainer","find","count","parseInt","text","isNaN","addClass","registerEventListeners","events","activate","on","e","data","buttonid","attr","publish","TOGGLE_VISIBILITY","originalEvent","preventDefault","subscribe","CONVERSATION_READ","CONTACT_REQUEST_ACCEPTED","CONTACT_REQUEST_DECLINED","init"],"mappings":";;;;;;;AAsBAA,sCACA,CACI,SACA,iCACA,cACA,uCAEJ,SACIC,EACAC,aACAC,OACAC,yBAEIC,0BACiB,kCAmBjBC,iCAAmC,SAASC,eACrC,eACCC,eAAiBD,OAAOE,KAAKJ,2BAC7BK,MAAQC,SAASH,eAAeI,OAAQ,IAExCC,MAAMH,SAEEA,OAASA,MAAQ,EADzBF,eAAeM,SAAS,WAIxBJ,OAAgB,EAChBF,eAAeI,KAAKF,UAW5BK,uBAAyB,SAASR,QAClCL,aAAaF,OAAOO,OAAQ,CAACL,aAAac,OAAOC,WAEjDV,OAAOW,GAAGhB,aAAac,OAAOC,UAAU,SAASE,EAAGC,MApCpB,IAASC,SAAAA,SAqCPd,OAAOe,KAAK,MApC9CnB,OAAOoB,QAAQnB,oBAAoBoB,kBAAmBH,UAqClDD,KAAKK,cAAcC,oBAGvBvB,OAAOwB,UAAUvB,oBAAoBwB,kBAAmBtB,iCAAiCC,SACzFJ,OAAOwB,UAAUvB,oBAAoByB,yBAA0BvB,iCAAiCC,SAChGJ,OAAOwB,UAAUvB,oBAAoB0B,yBAA0BxB,iCAAiCC,gBAa7F,CACHwB,KANO,SAASxB,QAChBA,OAASN,EAAEM,QACXQ,uBAAuBR"} \ No newline at end of file diff --git a/message/amd/src/message_drawer.js b/message/amd/src/message_drawer.js index a69c9ad8e9d..dd6cf9c2dce 100644 --- a/message/amd/src/message_drawer.js +++ b/message/amd/src/message_drawer.js @@ -38,6 +38,13 @@ define( 'core_message/message_drawer_helper', 'core/pending', 'core/drawer', + 'core/toast', + 'core/str', + 'core/config', + 'core/ajax', + 'core/local/aria/focuslock', + 'core/modal_backdrop', + 'core/templates', ], function( $, @@ -55,7 +62,14 @@ function( Events, Helper, Pending, - Drawer + Drawer, + Toast, + Str, + Config, + Ajax, + FocusLock, + ModalBackdrop, + Templates, ) { var SELECTORS = { @@ -129,6 +143,69 @@ function( }); }; + let backdropPromise = null; + + /** + * Set the focus on the drawer. + * + * This method also creates or destroy any necessary backdrop zone and focus trap. + * + * @param {Object} root The message drawer container. + * @param {Boolean} hasFocus Whether the drawer has focus or not. + */ + var setFocus = function(root, hasFocus) { + var drawerRoot = Drawer.getDrawerRoot(root); + if (!drawerRoot.length) { + return; + } + if (!backdropPromise) { + backdropPromise = Templates.render('core/modal_backdrop', {}) + .then(html => new ModalBackdrop(html)); + } + const backdropWithAdjustments = backdropPromise.then(modalBackdrop => { + const messageDrawerZIndex = window.getComputedStyle(drawerRoot[0]).zIndex; + if (messageDrawerZIndex) { + modalBackdrop.setZIndex(messageDrawerZIndex - 1); + } + modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => { + PubSub.publish(Events.HIDE, {}); + e.preventDefault(); + }); + return modalBackdrop; + }); + if (hasFocus) { + FocusLock.trapFocus(root[0]); + // eslint-disable-next-line promise/catch-or-return + backdropWithAdjustments.then(modalBackdrop => { + if (modalBackdrop) { + modalBackdrop.show(); + const pageWrapper = document.getElementById('page'); + pageWrapper.style.overflow = 'hidden'; + // Set the focus on the close button so when we press enter, it closes the drawer as it did before + var closeButton = root.find(SELECTORS.CLOSE_BUTTON); + if (closeButton.length) { + closeButton.focus(); + } + } + return modalBackdrop; + }); + } else { + // eslint-disable-next-line promise/catch-or-return + backdropWithAdjustments.then(modalBackdrop => { + if (modalBackdrop) { + FocusLock.untrapFocus(); + var button = $(SELECTORS.DRAWER).attr('data-origin'); + if (button) { + $('#' + button).focus(); + } + modalBackdrop.hide(); + const pageWrapper = document.getElementById('page'); + pageWrapper.style.overflow = 'visible'; + } + return modalBackdrop; + }); + } + }; /** * Show the message drawer. * @@ -143,6 +220,7 @@ function( var drawerRoot = Drawer.getDrawerRoot(root); if (drawerRoot.length) { + setFocus(root, true); Drawer.show(drawerRoot); } }; @@ -155,6 +233,7 @@ function( var hide = function(root) { var drawerRoot = Drawer.getDrawerRoot(root); if (drawerRoot.length) { + setFocus(root, false); Drawer.hide(drawerRoot); } }; @@ -190,7 +269,7 @@ function( * @param {bool} alwaysVisible Is this messaging app always shown? */ var registerEventListeners = function(namespace, root, alwaysVisible) { - CustomEvents.define(root, [CustomEvents.events.activate]); + CustomEvents.define(root, [CustomEvents.events.activate, CustomEvents.events.escape]); var paramRegex = /^data-route-param-?(\d*)$/; root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) { @@ -293,6 +372,9 @@ function( $(SELECTORS.JUMPTO).attr('tabindex', 0); } }); + root.on(CustomEvents.events.escape, function() { + PubSub.publish(Events.HIDE, {}); + }); } PubSub.subscribe(Events.SHOW_CONVERSATION, function(args) { @@ -304,7 +386,7 @@ function( var closebutton = root.find(SELECTORS.CLOSE_BUTTON); closebutton.on(CustomEvents.events.activate, function(e, data) { data.originalEvent.preventDefault(); - + setFocus(root, false); var button = $(SELECTORS.DRAWER).attr('data-origin'); if (button) { $('#' + button).focus(); diff --git a/message/amd/src/message_popover.js b/message/amd/src/message_popover.js index 52b7fa0b4e3..df2f81d75cd 100644 --- a/message/amd/src/message_popover.js +++ b/message/amd/src/message_popover.js @@ -80,7 +80,6 @@ function( button.on(CustomEvents.events.activate, function(e, data) { toggleMessageDrawerVisibility(button.attr('id')); - button.focus(); data.originalEvent.preventDefault(); }); diff --git a/message/templates/message_drawer.mustache b/message/templates/message_drawer.mustache index 5fc2ae261f0..ca8a7883a6f 100644 --- a/message/templates/message_drawer.mustache +++ b/message/templates/message_drawer.mustache @@ -34,6 +34,12 @@ }} {{< core/drawer}} + {{$tabindex}}-1{{/tabindex}} + {{$role}}dialog{{/role}} + {{$drawerattributes}} + aria-modal="true" + aria-labelledby="message-drawer-header-{{uniqid}}" + {{/drawerattributes}} {{$drawercontent}}

{{#str}} messagingcategory,admin {{/str}}