diff --git a/core/misc/ajax.es6.js b/core/misc/ajax.es6.js index 6da787bba8..d8fe6e8783 100644 --- a/core/misc/ajax.es6.js +++ b/core/misc/ajax.es6.js @@ -980,10 +980,43 @@ }; /** - * Provide a wrapper for multiple root elements via Ajax loading. + * Provide a wrapper for new content via Ajax. + * + * @param {jQuery} $newContent + * Response elements after parsing. + * @param {Drupal.Ajax} ajax + * {@link Drupal.Ajax} object created by {@link Drupal.ajax}. + * @param {object} response + * The response from the Ajax request. + */ + Drupal.theme.ajaxWrapperNewContent = ($newContent, ajax, response) => { + let typeEffect = response.effect || ajax.effect; + if ($newContent.length > 1 && typeEffect !== 'none') { + let countEffectElements = $newContent.length; + // Exclude all nodes not participating in the animation effect. + for (let i = 0; i < $newContent.length; i++) { + if ( + ($newContent[i].nodeName === '#comment') || + ($newContent[i].nodeName === '#text' && /^(\s|\n|\r)*$/.test($newContent[i].textContent)) + ) { + countEffectElements--; + } + } + if (countEffectElements > 1) { + $newContent = Drupal.theme('ajaxWrapperMultipleRootElements', $newContent); + } + } + return $newContent; + }; + + /** + * Provide a wrapper for multiple root elements via Ajax. + * + * @param {jQuery} $elements + * Response elements after parsing. */ - Drupal.theme.ajaxWrapperMultipleRootElements = (elements) => { - return elements; + Drupal.theme.ajaxWrapperMultipleRootElements = ($elements) => { + return $('
').append($elements); }; /** @@ -1045,10 +1078,7 @@ // Parse response.data into an element collection. let $newContent = $('').html(response.data).contents(); - // @todo: Remove after provide cool animation for single/multiple root. - if ($newContent.length > 1) { - $newContent = Drupal.theme('ajaxWrapperMultipleRootElements', $newContent); - } + $newContent = Drupal.theme('ajaxWrapperNewContent', $newContent, ajax, response); // If removing content from the wrapper, detach behaviors first. switch (method) { diff --git a/core/misc/ajax.js b/core/misc/ajax.js index f4e199fe97..d614a61d0a 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -478,8 +478,25 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr throw new Drupal.AjaxError(xmlhttprequest, uri, customMessage); }; - Drupal.theme.ajaxWrapperMultipleRootElements = function (elements) { - return elements; + Drupal.theme.ajaxWrapperNewContent = function ($newContent, ajax, response) { + var typeEffect = response.effect || ajax.effect; + if ($newContent.length > 1 && typeEffect !== 'none') { + var countEffectElements = $newContent.length; + + for (var i = 0; i < $newContent.length; i++) { + if ($newContent[i].nodeName === '#comment' || $newContent[i].nodeName === '#text' && /^(\s|\n|\r)*$/.test($newContent[i].textContent)) { + countEffectElements--; + } + } + if (countEffectElements > 1) { + $newContent = Drupal.theme('ajaxWrapperMultipleRootElements', $newContent); + } + } + return $newContent; + }; + + Drupal.theme.ajaxWrapperMultipleRootElements = function ($elements) { + return $('').append($elements); }; Drupal.AjaxCommands = function () {}; @@ -492,10 +509,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr var settings = response.settings || ajax.settings || drupalSettings; var $newContent = $('').html(response.data).contents(); - - if ($newContent.length > 1) { - $newContent = Drupal.theme('ajaxWrapperMultipleRootElements', $newContent); - } + $newContent = Drupal.theme('ajaxWrapperNewContent', $newContent, ajax, response); switch (method) { case 'html': diff --git a/core/modules/system/tests/modules/ajax_test/js/insert-ajax.es6.js b/core/modules/system/tests/modules/ajax_test/js/insert-ajax.es6.js index e7fb3f212b..d25552a8bd 100644 --- a/core/modules/system/tests/modules/ajax_test/js/insert-ajax.es6.js +++ b/core/modules/system/tests/modules/ajax_test/js/insert-ajax.es6.js @@ -15,6 +15,7 @@ base: false, element: false, method: event.currentTarget.getAttribute('data-method'), + effect: event.currentTarget.getAttribute('data-effect'), }; const myAjaxObject = Drupal.ajax(ajaxSettings); myAjaxObject.execute(); diff --git a/core/modules/system/tests/modules/ajax_test/js/insert-ajax.js b/core/modules/system/tests/modules/ajax_test/js/insert-ajax.js index c261bca80a..0f96097313 100644 --- a/core/modules/system/tests/modules/ajax_test/js/insert-ajax.js +++ b/core/modules/system/tests/modules/ajax_test/js/insert-ajax.js @@ -15,7 +15,8 @@ wrapper: 'ajax-target', base: false, element: false, - method: event.currentTarget.getAttribute('data-method') + method: event.currentTarget.getAttribute('data-method'), + effect: event.currentTarget.getAttribute('data-effect') }; var myAjaxObject = Drupal.ajax(ajaxSettings); myAjaxObject.execute(); diff --git a/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php b/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php index 9b6a9e2cef..24de8b00a1 100644 --- a/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php +++ b/core/modules/system/tests/modules/ajax_test/src/Controller/AjaxTestController.php @@ -56,10 +56,11 @@ public function renderTypes($type) { '#title' => 'AJAX Dialog & contents', 'content' => [ '#type' => 'inline_template', - '#template' => $this->getRenderTypes()[$type], + '#template' => $this->getRenderTypes()[$type]['render'], ], ]; + $content['effect'] = 'fade'; return $content; } @@ -85,7 +86,7 @@ public function insertLinksBlockWrapper() { ], ]; foreach ($methods as $method) { - foreach (array_keys($this->getRenderTypes()) as $type) { + foreach ($this->getRenderTypes() as $type => $item) { $class = 'ajax-insert'; $build['links']['links']['#links']["$method-$type"] = [ 'title' => "Link $method $type", @@ -93,6 +94,7 @@ public function insertLinksBlockWrapper() { 'attributes' => [ 'class' => [$class], 'data-method' => $method, + 'data-effect' => $item['effect'], ], ]; } @@ -122,7 +124,7 @@ public function insertLinksInlineWrapper() { ], ]; foreach ($methods as $method) { - foreach (array_keys($this->getRenderTypes()) as $type) { + foreach ($this->getRenderTypes() as $type => $item) { $class = 'ajax-insert-inline'; $build['links']['links']['#links']["$method-$type"] = [ 'title' => "Link $method $type", @@ -130,6 +132,7 @@ public function insertLinksInlineWrapper() { 'attributes' => [ 'class' => [$class], 'data-method' => $method, + 'data-effect' => $item['effect'], ], ]; } @@ -324,7 +327,7 @@ public function dialogClose() { * Render types. */ protected function getRenderTypes() { - return [ + $render_types = [ 'pre-wrapped-div' => '