Loading core/misc/dialog/dialog.ajax.js +23 −2 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * Extends the Drupal AJAX functionality to integrate the dialog API. */ (function ($, Drupal) { (function ($, Drupal, { focusable }) { /** * Initialize dialogs for Ajax purposes. * Loading Loading @@ -46,6 +46,27 @@ // Overwrite the close method to remove the dialog on closing. settings.dialog.close = function (event, ...args) { originalClose.apply(settings.dialog, [event, ...args]); // Check if the opener element is inside an AJAX container. const $element = $(event.target); const ajaxContainer = $element.data('uiDialog') ? $element .data('uiDialog') .opener.closest('[data-drupal-ajax-container]') : []; // If the opener element was in an ajax container, and focus is on the // body element, we can assume focus was lost. To recover, focus is moved // to the first focusable element in the container. if ( ajaxContainer.length && (document.activeElement === document.body || $(document.activeElement).not(':visible')) ) { const focusableChildren = focusable(ajaxContainer[0]); if (focusableChildren.length > 0) { focusableChildren[0].focus(); } } $(event.target).remove(); }; }, Loading Loading @@ -246,4 +267,4 @@ $(window).on('dialog:beforeclose', (e, dialog, $element) => { $element.off('.dialog'); }); })(jQuery, Drupal); })(jQuery, Drupal, window.tabbable); core/modules/block/tests/src/Functional/Views/DisplayBlockTest.php +2 −2 Original line number Diff line number Diff line Loading @@ -393,8 +393,8 @@ public function testBlockContextualLinks() { $cached_id_token = Crypt::hmacBase64($cached_id, Settings::getHashSalt() . $this->container->get('private_key')->get()); // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() // Check existence of the contextual link placeholders. $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $id, 'data-contextual-token' => $id_token]) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $cached_id, 'data-contextual-token' => $cached_id_token]) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $id, 'data-contextual-token' => $id_token, 'data-drupal-ajax-container' => '']) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $cached_id, 'data-contextual-token' => $cached_id_token, 'data-drupal-ajax-container' => '']) . '></div>'); // Get server-rendered contextual links. // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks() Loading core/modules/contextual/src/Element/ContextualLinksPlaceholder.php +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public static function preRenderPlaceholder(array $element) { $attribute = new Attribute([ 'data-contextual-id' => $element['#id'], 'data-contextual-token' => $token, 'data-drupal-ajax-container' => '', ]); $element['#markup'] = new FormattableMarkup('<div@attributes></div>', ['@attributes' => $attribute]); Loading core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php +8 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,14 @@ public function testContextualLinksClick() { $this->clickContextualLink('#block-branding', 'Test Link with Ajax'); $this->assertNotEmpty($this->assertSession()->waitForElementVisible('css', '#drupal-modal')); $this->assertSession()->elementContains('css', '#drupal-modal', 'Everything is contextual!'); $this->getSession()->getPage()->pressButton('Close'); $this->assertSession()->assertNoElementAfterWait('css', 'ui.dialog'); // When the dialog is closed, the opening contextual link is now inside a // collapsed container, so focus should be routed to the contextual link // toggle button. $this->assertJsCondition('document.activeElement === document.querySelector("#block-branding button.trigger")'); // Check to make sure that page was not reloaded. $this->assertSession()->pageTextContains($current_page_string); Loading core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.routing.yml +8 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,11 @@ dialog_renderer_test.modal_content_input: _title: 'Thing 3' requirements: _access: 'TRUE' dialog_renderer_test.collapsed_opener: path: '/dialog_renderer-collapsed-opener' defaults: _controller: '\Drupal\dialog_renderer_test\Controller\TestController::collapsedOpener' _title: 'Collapsed Openers' requirements: _access: 'TRUE' Loading
core/misc/dialog/dialog.ajax.js +23 −2 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * Extends the Drupal AJAX functionality to integrate the dialog API. */ (function ($, Drupal) { (function ($, Drupal, { focusable }) { /** * Initialize dialogs for Ajax purposes. * Loading Loading @@ -46,6 +46,27 @@ // Overwrite the close method to remove the dialog on closing. settings.dialog.close = function (event, ...args) { originalClose.apply(settings.dialog, [event, ...args]); // Check if the opener element is inside an AJAX container. const $element = $(event.target); const ajaxContainer = $element.data('uiDialog') ? $element .data('uiDialog') .opener.closest('[data-drupal-ajax-container]') : []; // If the opener element was in an ajax container, and focus is on the // body element, we can assume focus was lost. To recover, focus is moved // to the first focusable element in the container. if ( ajaxContainer.length && (document.activeElement === document.body || $(document.activeElement).not(':visible')) ) { const focusableChildren = focusable(ajaxContainer[0]); if (focusableChildren.length > 0) { focusableChildren[0].focus(); } } $(event.target).remove(); }; }, Loading Loading @@ -246,4 +267,4 @@ $(window).on('dialog:beforeclose', (e, dialog, $element) => { $element.off('.dialog'); }); })(jQuery, Drupal); })(jQuery, Drupal, window.tabbable);
core/modules/block/tests/src/Functional/Views/DisplayBlockTest.php +2 −2 Original line number Diff line number Diff line Loading @@ -393,8 +393,8 @@ public function testBlockContextualLinks() { $cached_id_token = Crypt::hmacBase64($cached_id, Settings::getHashSalt() . $this->container->get('private_key')->get()); // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() // Check existence of the contextual link placeholders. $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $id, 'data-contextual-token' => $id_token]) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $cached_id, 'data-contextual-token' => $cached_id_token]) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $id, 'data-contextual-token' => $id_token, 'data-drupal-ajax-container' => '']) . '></div>'); $this->assertSession()->responseContains('<div' . new Attribute(['data-contextual-id' => $cached_id, 'data-contextual-token' => $cached_id_token, 'data-drupal-ajax-container' => '']) . '></div>'); // Get server-rendered contextual links. // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks() Loading
core/modules/contextual/src/Element/ContextualLinksPlaceholder.php +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public static function preRenderPlaceholder(array $element) { $attribute = new Attribute([ 'data-contextual-id' => $element['#id'], 'data-contextual-token' => $token, 'data-drupal-ajax-container' => '', ]); $element['#markup'] = new FormattableMarkup('<div@attributes></div>', ['@attributes' => $attribute]); Loading
core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php +8 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,14 @@ public function testContextualLinksClick() { $this->clickContextualLink('#block-branding', 'Test Link with Ajax'); $this->assertNotEmpty($this->assertSession()->waitForElementVisible('css', '#drupal-modal')); $this->assertSession()->elementContains('css', '#drupal-modal', 'Everything is contextual!'); $this->getSession()->getPage()->pressButton('Close'); $this->assertSession()->assertNoElementAfterWait('css', 'ui.dialog'); // When the dialog is closed, the opening contextual link is now inside a // collapsed container, so focus should be routed to the contextual link // toggle button. $this->assertJsCondition('document.activeElement === document.querySelector("#block-branding button.trigger")'); // Check to make sure that page was not reloaded. $this->assertSession()->pageTextContains($current_page_string); Loading
core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.routing.yml +8 −0 Original line number Diff line number Diff line Loading @@ -29,3 +29,11 @@ dialog_renderer_test.modal_content_input: _title: 'Thing 3' requirements: _access: 'TRUE' dialog_renderer_test.collapsed_opener: path: '/dialog_renderer-collapsed-opener' defaults: _controller: '\Drupal\dialog_renderer_test\Controller\TestController::collapsedOpener' _title: 'Collapsed Openers' requirements: _access: 'TRUE'