diff --git a/core/misc/dialog/dialog.ajax.es6.js b/core/misc/dialog/dialog.ajax.es6.js index a6f2e71ce7..7d3452fd7a 100644 --- a/core/misc/dialog/dialog.ajax.es6.js +++ b/core/misc/dialog/dialog.ajax.es6.js @@ -132,6 +132,10 @@ response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog); } + if (ajax.hasOwnProperty('element') && ajax.element instanceof Element) { + response.dialogOptions.drupalTriggerElement = ajax.element; + } + // Bind dialogButtonsChange. $dialog.on('dialogButtonsChange', () => { const buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog); diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js index de1d3c9219..53130377a7 100644 --- a/core/misc/dialog/dialog.ajax.js +++ b/core/misc/dialog/dialog.ajax.js @@ -85,6 +85,10 @@ response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog); } + if (ajax.hasOwnProperty('element') && ajax.element instanceof Element) { + response.dialogOptions.drupalTriggerElement = ajax.element; + } + $dialog.on('dialogButtonsChange', function () { var buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog); $dialog.dialog('option', 'buttons', buttons); diff --git a/core/modules/contextual/js/contextual.es6.js b/core/modules/contextual/js/contextual.es6.js index 701ed126cb..eebbd6c30b 100644 --- a/core/modules/contextual/js/contextual.es6.js +++ b/core/modules/contextual/js/contextual.es6.js @@ -263,4 +263,30 @@ $(document).on('drupalContextualLinkAdded', (event, data) => { Drupal.ajax.bindAjaxLinks(data.$el[0]); }); + + // The contextual button for the link that opened the dialog. + let dialogLinkContextualButton; + $(window).on({ + 'dialog:beforecreate': (event, dialog, $element, settings) => { + if (settings.hasOwnProperty('drupalTriggerElement')) { + // Determine if the trigger element is a contextual link. + if ($(settings.drupalTriggerElement).closest('[data-contextual-id]').find('button').length) { + /** + * Save the contextual link button so it will be available for + * 'dialog:afterclose'. + */ + dialogLinkContextualButton = $(settings.drupalTriggerElement) + .closest('[data-contextual-id]') + .find('button') + .get(0); + } + } + }, + 'dialog:afterclose': (event, dialog, $element) => { + if (dialogLinkContextualButton) { + // Set focus to the contextual trigger button. + $(dialogLinkContextualButton).focus(); + } + }, + }); }(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage)); diff --git a/core/modules/contextual/js/contextual.js b/core/modules/contextual/js/contextual.js index ed210d070d..94bfade804 100644 --- a/core/modules/contextual/js/contextual.js +++ b/core/modules/contextual/js/contextual.js @@ -148,4 +148,20 @@ $(document).on('drupalContextualLinkAdded', function (event, data) { Drupal.ajax.bindAjaxLinks(data.$el[0]); }); + + var dialogLinkContextualButton = void 0; + $(window).on({ + 'dialog:beforecreate': function dialogBeforecreate(event, dialog, $element, settings) { + if (settings.hasOwnProperty('drupalTriggerElement')) { + if ($(settings.drupalTriggerElement).closest('[data-contextual-id]').find('button').length) { + dialogLinkContextualButton = $(settings.drupalTriggerElement).closest('[data-contextual-id]').find('button').get(0); + } + } + }, + 'dialog:afterclose': function dialogAfterclose(event, dialog, $element) { + if (dialogLinkContextualButton) { + $(dialogLinkContextualButton).focus(); + } + } + }); })(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage); \ No newline at end of file diff --git a/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php b/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php index de83692411..f8e414dbb0 100644 --- a/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php +++ b/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php @@ -80,6 +80,11 @@ public function testContextualLinksClick() { // Check to make sure that page was not reloaded. $this->assertSession()->pageTextContains($current_page_string); + // Close the dialog. + $this->getSession()->getPage()->find('css', '.ui-dialog .ui-dialog-titlebar-close')->click(); + // Confirm the contextual button has become the active element. + $this->assertJsCondition('document.activeElement === document.querySelector("#block-branding [data-contextual-id] button")'); + // Test clicking contextual link with toolbar. $this->container->get('module_installer')->install(['toolbar']); $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['access toolbar']);