diff --git a/core/modules/media_library/css/media_library.theme.css b/core/modules/media_library/css/media_library.theme.css index 8bd3c1964d..6f50e0b608 100644 --- a/core/modules/media_library/css/media_library.theme.css +++ b/core/modules/media_library/css/media_library.theme.css @@ -257,6 +257,7 @@ /* Media library item table styles. */ .media-library-item--table img { max-width: 100px; + height: auto; } /* Media library entity view display styles. */ diff --git a/core/modules/media_library/js/media_library.ui.es6.js b/core/modules/media_library/js/media_library.ui.es6.js index feec6840f2..653a331c06 100644 --- a/core/modules/media_library/js/media_library.ui.es6.js +++ b/core/modules/media_library/js/media_library.ui.es6.js @@ -166,6 +166,8 @@ e.stopPropagation(); const $link = $(e.currentTarget); + const displayAnnouncement = $link.data('display-announcement'); + const loadingAnnouncement = $link.data('loading-announcement'); // Replace the library view. const ajaxObject = Drupal.ajax({ @@ -174,25 +176,34 @@ dialogType: 'ajax', progress: { type: 'fullscreen', - message: Drupal.t('Please wait...'), + message: loadingAnnouncement || Drupal.t('Please wait...'), }, }); // Override the AJAX success callback to announce the updated content // to screen readers. - const success = ajaxObject.success; - ajaxObject.success = function(response, status) { - success.bind(this)(response, status); - const displayAnnouncement = $link.data('display-announcement'); - if (displayAnnouncement) { + // @todo Replace custom announcement when + // https://www.drupal.org/project/drupal/issues/2973140 is in. + if (displayAnnouncement) { + const success = ajaxObject.success; + ajaxObject.success = function (response, status) { + success.bind(this)(response, status); + // The AJAX link replace the whole view, including the clicked + // link. Move the focus back to the clicked link when the view is + // replaced. + $(`#${$link.attr('id')}`).focus(); Drupal.announce(displayAnnouncement); - } else { - Drupal.announce(Drupal.t('Media library content changed.')); - } - }; + }; + } + ajaxObject.execute(); - Drupal.announce(Drupal.t('Loading media library content.')); + // Announce the new view is being loaded to screen readers. + // @todo Replace custom announcement when + // https://www.drupal.org/project/drupal/issues/2973140 is in. + if (loadingAnnouncement) { + Drupal.announce(loadingAnnouncement); + } }); }, }; diff --git a/core/modules/media_library/js/media_library.ui.js b/core/modules/media_library/js/media_library.ui.js index 89ae470683..e746edfde9 100644 --- a/core/modules/media_library/js/media_library.ui.js +++ b/core/modules/media_library/js/media_library.ui.js @@ -82,6 +82,8 @@ e.stopPropagation(); var $link = $(e.currentTarget); + var displayAnnouncement = $link.data('display-announcement'); + var loadingAnnouncement = $link.data('loading-announcement'); var ajaxObject = Drupal.ajax({ wrapper: 'media-library-view', @@ -89,23 +91,25 @@ dialogType: 'ajax', progress: { type: 'fullscreen', - message: Drupal.t('Please wait...') + message: loadingAnnouncement || Drupal.t('Please wait...') } }); - var success = ajaxObject.success; - ajaxObject.success = function (response, status) { - success.bind(this)(response, status); - var displayAnnouncement = $link.data('display-announcement'); - if (displayAnnouncement) { + if (displayAnnouncement) { + var success = ajaxObject.success; + ajaxObject.success = function (response, status) { + success.bind(this)(response, status); + + $('#' + $link.attr('id')).focus(); Drupal.announce(displayAnnouncement); - } else { - Drupal.announce(Drupal.t('Media library content changed.')); - } - }; + }; + } + ajaxObject.execute(); - Drupal.announce(Drupal.t('Loading media library content.')); + if (loadingAnnouncement) { + Drupal.announce(loadingAnnouncement); + } }); } }; diff --git a/core/modules/media_library/media_library.libraries.yml b/core/modules/media_library/media_library.libraries.yml index b7e0408d2f..8d5e70682e 100644 --- a/core/modules/media_library/media_library.libraries.yml +++ b/core/modules/media_library/media_library.libraries.yml @@ -36,5 +36,6 @@ ui: js/media_library.ui.js: {} dependencies: - core/drupal.ajax + - core/drupal.announce - media_library/view - core/jquery.once diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module index 217ad305e8..7d3c4265c7 100644 --- a/core/modules/media_library/media_library.module +++ b/core/modules/media_library/media_library.module @@ -86,14 +86,25 @@ function media_library_link_alter(&$variables) { $is_view_display_link = isset($options['view'], $options['target_display_id']); if ($is_view_display_link && $options['view']->id() === 'media_library' && strpos($options['view']->current_display, 'widget') === 0) { $options['attributes']['class'][] = 'js-media-library-view-display-link'; + + // The AJAX link replace the whole view, including the clicked link. After + // the page is updated with the new view, the focus needs to be returned to + // the clicked link, so we add an ID to target the link. + // @see Drupal.behaviors.MediaLibraryViewsDisplay + $options['attributes']['id'] = 'views-media-library-display-link-' . $options['target_display_id']; + // Add announcements for screen readers in a data attribute so they can be // announced when the AJAX content had loaded. // @see Drupal.behaviors.MediaLibraryViewsDisplay + // @todo Replace the custom announcements when + // https://www.drupal.org/project/drupal/issues/2973140 is in. if ($options['target_display_id'] === 'widget') { - $options['attributes']['data-display-announcement'] = t('Media library content changed to grid view.'); + $options['attributes']['data-display-announcement'] = t('Changed to grid view.'); + $options['attributes']['data-loading-announcement'] = t('Loading grid view.'); } if ($options['target_display_id'] === 'widget_table') { - $options['attributes']['data-display-announcement'] = t('Media library content changed to table view.'); + $options['attributes']['data-display-announcement'] = t('Changed to table view.'); + $options['attributes']['data-loading-announcement'] = t('Loading table view.'); } } } diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php index 1cf6b5963b..bdd0c211be 100644 --- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php +++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php @@ -204,7 +204,6 @@ public function testWidget() { $assert_session->pageTextContains('Media library'); $this->assertFalse($assert_session->elementExists('css', '.media-library-select-all')->isVisible()); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert that the media type menu is available when more than 1 type is // configured for the field. @@ -216,7 +215,6 @@ public function testWidget() { $assert_session->elementExists('named', ['link', 'Type Three'], $menu); $assert_session->elementNotExists('named', ['link', 'Type Four'], $menu); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert that the media type menu is not available when only 1 type is // configured for the field. @@ -231,7 +229,6 @@ public function testWidget() { $assert_session->elementTextContains('css', '.media-library-selected-count', '1 of 1 item selected'); $assert_session->elementNotExists('css', '.media-library-menu'); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert the menu links can be sorted through the widget configuration. $assert_session->elementExists('css', '.media-library-open-button[href*="field_twin_media"]')->click(); @@ -262,7 +259,6 @@ public function testWidget() { }, $page->findAll('css', '.media-library-menu a')); $this->assertSame($link_titles, ['Type One (active tab)', 'Type Three', 'Type Four', 'Type Two']); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert media is only visible on the tab for the related media type. $assert_session->elementExists('css', '.media-library-open-button[href*="field_unlimited_media"]')->click(); @@ -277,7 +273,6 @@ public function testWidget() { $assert_session->pageTextNotContains('Bear'); $assert_session->pageTextNotContains('Turtle'); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert the media library contains header links to switch between the grid // and table display. @@ -290,21 +285,19 @@ public function testWidget() { $assert_session->buttonNotExists('Apply filters', $button_pane); $page->hasLink('Show as grid'); $page->clickLink('Show as table'); - $assert_session->assertWaitOnAjaxRequest(); + $assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--table'); + $assert_session->elementNotExists('css', '.media-library-view .media-library-item--grid'); $assert_session->buttonExists('Select media', $button_pane); $assert_session->buttonNotExists('Apply filters', $button_pane); $assert_session->pageTextContains('Dog'); $assert_session->pageTextContains('Bear'); $assert_session->pageTextNotContains('Turtle'); - $assert_session->elementNotExists('css', '.media-library-view .media-library-item--grid'); - $assert_session->elementExists('css', '.media-library-view .media-library-item--table'); $assert_session->pageTextContains('Dog'); $assert_session->pageTextContains('Bear'); $assert_session->pageTextNotContains('Turtle'); $page->hasLink('Show as table'); $page->clickLink('Show as grid'); - $assert_session->assertWaitOnAjaxRequest(); - $assert_session->elementExists('css', '.media-library-view .media-library-item--grid'); + $assert_session->waitForElementVisible('css', '.media-library-view .media-library-item--grid'); $assert_session->elementNotExists('css', '.media-library-view .media-library-item--table'); $assert_session->pageTextContains('Dog'); $assert_session->pageTextContains('Bear'); @@ -312,7 +305,6 @@ public function testWidget() { $page->hasLink('Show as grid'); $page->hasLink('Show as table'); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert the exposed name filter of the view. $assert_session->elementExists('css', '.media-library-open-button[href*="field_unlimited_media"]')->click(); @@ -329,7 +321,6 @@ public function testWidget() { $assert_session->pageTextContains('Dog'); $assert_session->pageTextContains('Bear'); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Assert the selection is persistent in the media library modal, and // the number of selected items is displayed correctly. @@ -452,7 +443,6 @@ public function testWidget() { $this->assertFalse($checkboxes[3]->isChecked()); // Close the dialog, reopen it and assert not is selected again. $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); $assert_session->elementExists('css', '.media-library-open-button[href*="field_unlimited_media"]')->click(); $assert_session->assertWaitOnAjaxRequest(); $checkboxes = $page->findAll('css', '.media-library-view .js-click-to-select-checkbox input'); @@ -461,7 +451,6 @@ public function testWidget() { $this->assertFalse($checkboxes[2]->isChecked()); $this->assertFalse($checkboxes[3]->isChecked()); $page->find('css', '.ui-dialog-titlebar-close')->click(); - $assert_session->assertWaitOnAjaxRequest(); // Finally, save the form. $assert_session->elementExists('css', '.js-media-library-widget-toggle-weight')->click();