From 762fcae92c4391821f1f4a8ba0cc5cd3adcf9d18 Mon Sep 17 00:00:00 2001 From: Lauri Eskola <lauri.eskola@acquia.com> Date: Tue, 5 Dec 2023 10:58:11 +0200 Subject: [PATCH] Issue #3397785 by yash.rode, srishtiiee, lauriii, smustgrave: Dialog focus is returned to dialog instead of first tabbable element on dialog AJAX update --- core/misc/dialog/dialog.ajax.js | 15 ++++++++++----- .../FunctionalJavascriptTests/Ajax/DialogTest.php | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js index 809b287456be..fac064c17d16 100644 --- a/core/misc/dialog/dialog.ajax.js +++ b/core/misc/dialog/dialog.ajax.js @@ -38,11 +38,16 @@ $dialog.trigger('dialogButtonsChange'); } - // If the body element has focus, it means focus was effectively lost. - // In these instances, force focus on the dialog. - if (document.activeElement === document.body) { - $dialog.dialog('widget').trigger('focus'); - } + setTimeout(function () { + // Account for pre-existing focus handling that may have already moved + // the focus inside the dialog. + if (!$dialog[0].contains(document.activeElement)) { + // Move focus to the first focusable element in the next event loop + // to allow dialog buttons to be changed first. + $dialog.dialog('instance')._focusedElement = null; + $dialog.dialog('instance')._focusTabbable(); + } + }, 0); } const originalClose = settings.dialog.close; diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php index 005233266219..5d10e3f0693a 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php @@ -167,8 +167,12 @@ public function testDialog() { // Press buttons in the dialog to ensure there are no AJAX errors. $this->assertSession()->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Hello world'); $this->assertSession()->assertWaitOnAjaxRequest(); + $has_focus_text = $this->getSession()->evaluateScript('document.activeElement.textContent'); + $this->assertEquals('Do it', $has_focus_text); $this->assertSession()->elementExists('css', '.ui-dialog-buttonpane')->pressButton('Preview'); $this->assertSession()->assertWaitOnAjaxRequest(); + $has_focus_text = $this->getSession()->evaluateScript('document.activeElement.textContent'); + $this->assertEquals('Do it', $has_focus_text); // Reset: close the form. $form_dialog->findButton('Close')->press(); -- GitLab