diff --git a/core/lib/Drupal/Core/Render/Element/RenderElement.php b/core/lib/Drupal/Core/Render/Element/RenderElement.php index 47c84024c696e0e4685485ec94b6492c055cce08..b6f95bcd6cc7c2df28966c1d3448a48f2929c69f 100644 --- a/core/lib/Drupal/Core/Render/Element/RenderElement.php +++ b/core/lib/Drupal/Core/Render/Element/RenderElement.php @@ -269,6 +269,11 @@ public static function preRenderAjaxForm($element) { return $element; } + // Add a data attribute to disable automatic refocus after ajax call. + if (!empty($element['#ajax']['disable-refocus'])) { + $element['#attributes']['data-disable-refocus'] = "true"; + } + // Add a reasonable default event handler if none was specified. if (isset($element['#ajax']) && !isset($element['#ajax']['event'])) { switch ($element['#type']) { diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 2a6616dc760a28f9a91e07e78f8caf8dcedf552f..b63bc0344360af59e66a5a3081061a4a3231d989 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -735,9 +735,36 @@ } $(this.element).prop('disabled', false); + // Save element's ancestors tree so if the element is removed from the dom + // we can try to refocus one of its parents. Using addBack reverse the + // result array, meaning that index 0 is the highest parent in the hierarchy + // in this situation it is usually a
element. + var elementParents = $(this.element).parents('[data-drupal-selector]').addBack().toArray(); + + // Track if any command is altering the focus so we can avoid changing the + // focus set by the Ajax command. + var focusChanged = false; for (var i in response) { if (response.hasOwnProperty(i) && response[i].command && this.commands[response[i].command]) { this.commands[response[i].command](this, response[i], status); + if (response[i].command === 'invoke' && response[i].method === 'focus') { + focusChanged = true; + } + } + } + + // If the focus hasn't be changed by the ajax commands, try to refocus the + // triggering element or one of its parents if that element does not exist + // anymore. + if (!focusChanged && this.element && !$(this.element).data('disable-refocus')) { + var target = false; + + for (var n = elementParents.length - 1; !target && n > 0; n--) { + target = document.querySelector('[data-drupal-selector="' + elementParents[n].getAttribute('data-drupal-selector') + '"]'); + } + + if (target) { + $(target).trigger('focus'); } } diff --git a/core/modules/views_ui/src/ViewPreviewForm.php b/core/modules/views_ui/src/ViewPreviewForm.php index 7ec8f4de1206a7569bbebf126891f989025862c2..d87f593d1f266274d7a58aa27ae119e5e4be6b01 100644 --- a/core/modules/views_ui/src/ViewPreviewForm.php +++ b/core/modules/views_ui/src/ViewPreviewForm.php @@ -94,6 +94,7 @@ protected function actions(array $form, FormStateInterface $form_state) { 'event' => 'click', 'progress' => array('type' => 'fullscreen'), 'method' => 'replaceWith', + 'disable-refocus' => TRUE, ), ), );