Media: Remove infinite scroll from media library and modal.

Replace infinitely autoloading behavior on scroll with a user-controlled load more button. Fix a long standing accessibility issue in the media library. Infinite scroll poses a wide range of problems for accessibility, usability, and performance.

This change modifies the library to load 40 items in the initial view, with a load more button to load the next 40 items and a button to move focus from the load more region to the first of the most recently added items.

The text for communicating the jump target was broadly discussed, agreeing that the text incorporated here would most concisely and clearly convey the purpose of the button, and any further detail is learnable from use.
 
Props afercia, adamsilverstein, joedolson, audrasjb, francina 
Fixes #50105. See #40330. 
Built from https://develop.svn.wordpress.org/trunk@50829


git-svn-id: http://core.svn.wordpress.org/trunk@50438 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
joedolson 2021-05-07 23:19:03 +00:00
parent bdaca9bffc
commit 9b6710c43c
15 changed files with 504 additions and 51 deletions

View File

@ -421,7 +421,8 @@ border color while dragging a file over the uploader drop area */
.media-frame.mode-grid,
.media-frame.mode-grid .media-frame-content,
.media-frame.mode-grid .attachments-browser .attachments,
.media-frame.mode-grid .attachments-browser:not(.has-load-more) .attachments,
.media-frame.mode-grid .attachments-browser.has-load-more .attachments-wrapper,
.media-frame.mode-grid .uploader-inline-content {
position: static;
}
@ -499,7 +500,8 @@ border color while dragging a file over the uploader drop area */
border: 4px dashed #c3c4c7;
}
.media-frame.mode-select .attachments-browser.fixed .attachments {
.media-frame.mode-select .attachments-browser.fixed:not(.has-load-more) .attachments,
.media-frame.mode-select .attachments-browser.has-load-more.fixed .attachments-wrapper {
position: relative;
top: 94px; /* prevent jumping up when the toolbar becomes fixed */
padding-bottom: 94px; /* offset for above so the bottom doesn't get cut off */

File diff suppressed because one or more lines are too long

View File

@ -420,7 +420,8 @@ border color while dragging a file over the uploader drop area */
.media-frame.mode-grid,
.media-frame.mode-grid .media-frame-content,
.media-frame.mode-grid .attachments-browser .attachments,
.media-frame.mode-grid .attachments-browser:not(.has-load-more) .attachments,
.media-frame.mode-grid .attachments-browser.has-load-more .attachments-wrapper,
.media-frame.mode-grid .uploader-inline-content {
position: static;
}
@ -498,7 +499,8 @@ border color while dragging a file over the uploader drop area */
border: 4px dashed #c3c4c7;
}
.media-frame.mode-select .attachments-browser.fixed .attachments {
.media-frame.mode-select .attachments-browser.fixed:not(.has-load-more) .attachments,
.media-frame.mode-select .attachments-browser.has-load-more.fixed .attachments-wrapper {
position: relative;
top: 94px; /* prevent jumping up when the toolbar becomes fixed */
padding-bottom: 94px; /* offset for above so the bottom doesn't get cut off */

File diff suppressed because one or more lines are too long

View File

@ -2993,7 +2993,12 @@ function wp_ajax_query_attachments() {
$posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
$posts = array_filter( $posts );
wp_send_json_success( $posts );
$result = array(
'attachments' => $posts,
'totalAttachments' => $query->found_posts,
);
wp_send_json_success( $result );
}
/**

View File

@ -1189,7 +1189,8 @@
padding: 2px 8px 8px;
}
.attachments-browser .attachments,
.attachments-browser:not(.has-load-more) .attachments,
.attachments-browser.has-load-more .attachments-wrapper,
.attachments-browser .uploader-inline {
position: absolute;
top: 72px;
@ -1268,6 +1269,96 @@
padding: 2em 2em 0 0;
}
.more-loaded .attachment:not(.found-media) {
background: #dcdcde;
}
.load-more-wrapper {
clear: both;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding: 1em 0;
}
.load-more-wrapper .load-more-count {
min-width: 100%;
margin: 0 0 1em;
text-align: center;
}
.load-more-wrapper .load-more {
margin: 0;
}
/* Needs high specificity. */
.media-frame .load-more-wrapper .load-more + .spinner {
float: none;
margin: 0 10px 0 -30px;
}
/* Reset spinner margin when the button is hidden to avoid horizontal scrollbar. */
.media-frame .load-more-wrapper .load-more.hidden + .spinner {
margin: 0;
}
/* Force a new row within the flex container. */
.load-more-wrapper::after {
content: "";
min-width: 100%;
order: 1;
}
.load-more-wrapper .load-more-jump {
margin: 0 12px 0 0;
}
.attachment.new-media {
outline: 2px dotted #c3c4c7;
}
.load-more-wrapper {
clear: both;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding: 1em 0;
}
.load-more-wrapper .load-more-count {
min-width: 100%;
margin: 0 0 1em;
text-align: center;
}
.load-more-wrapper .load-more {
margin: 0;
}
/* Needs high specificity. */
.media-frame .load-more-wrapper .load-more + .spinner {
float: none;
margin: 0 10px 0 -30px;
}
/* Reset spinner margin when the button is hidden to avoid horizontal scrollbar. */
.media-frame .load-more-wrapper .load-more.hidden + .spinner {
margin: 0;
}
/* Force a new row within the flex container. */
.load-more-wrapper::after {
content: "";
min-width: 100%;
order: 1;
}
.load-more-wrapper .load-more-jump {
margin: 0 12px 0 0;
}
/**
* Progress Bar
*/
@ -2819,6 +2910,12 @@
.media-frame-content .media-toolbar .instructions {
display: none;
}
/* Change margin direction on load more button in responsive views. */
.load-more-wrapper .load-more-jump {
margin: 12px 0 0 0;
}
}
@media only screen and (min-width: 901px) and (max-height: 400px) {
@ -2827,6 +2924,12 @@
top: 0;
padding-top: 44px;
}
/* Change margin direction on load more button in responsive views. */
.load-more-wrapper .load-more-jump {
margin: 12px 0 0 0;
}
}
@media only screen and (max-width: 480px) {

File diff suppressed because one or more lines are too long

View File

@ -1188,7 +1188,8 @@
padding: 2px 8px 8px;
}
.attachments-browser .attachments,
.attachments-browser:not(.has-load-more) .attachments,
.attachments-browser.has-load-more .attachments-wrapper,
.attachments-browser .uploader-inline {
position: absolute;
top: 72px;
@ -1267,6 +1268,96 @@
padding: 2em 0 0 2em;
}
.more-loaded .attachment:not(.found-media) {
background: #dcdcde;
}
.load-more-wrapper {
clear: both;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding: 1em 0;
}
.load-more-wrapper .load-more-count {
min-width: 100%;
margin: 0 0 1em;
text-align: center;
}
.load-more-wrapper .load-more {
margin: 0;
}
/* Needs high specificity. */
.media-frame .load-more-wrapper .load-more + .spinner {
float: none;
margin: 0 -30px 0 10px;
}
/* Reset spinner margin when the button is hidden to avoid horizontal scrollbar. */
.media-frame .load-more-wrapper .load-more.hidden + .spinner {
margin: 0;
}
/* Force a new row within the flex container. */
.load-more-wrapper::after {
content: "";
min-width: 100%;
order: 1;
}
.load-more-wrapper .load-more-jump {
margin: 0 0 0 12px;
}
.attachment.new-media {
outline: 2px dotted #c3c4c7;
}
.load-more-wrapper {
clear: both;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding: 1em 0;
}
.load-more-wrapper .load-more-count {
min-width: 100%;
margin: 0 0 1em;
text-align: center;
}
.load-more-wrapper .load-more {
margin: 0;
}
/* Needs high specificity. */
.media-frame .load-more-wrapper .load-more + .spinner {
float: none;
margin: 0 -30px 0 10px;
}
/* Reset spinner margin when the button is hidden to avoid horizontal scrollbar. */
.media-frame .load-more-wrapper .load-more.hidden + .spinner {
margin: 0;
}
/* Force a new row within the flex container. */
.load-more-wrapper::after {
content: "";
min-width: 100%;
order: 1;
}
.load-more-wrapper .load-more-jump {
margin: 0 0 0 12px;
}
/**
* Progress Bar
*/
@ -2818,6 +2909,12 @@
.media-frame-content .media-toolbar .instructions {
display: none;
}
/* Change margin direction on load more button in responsive views. */
.load-more-wrapper .load-more-jump {
margin: 12px 0 0 0;
}
}
@media only screen and (min-width: 901px) and (max-height: 400px) {
@ -2826,6 +2923,12 @@
top: 0;
padding-top: 44px;
}
/* Change margin direction on load more button in responsive views. */
.load-more-wrapper .load-more-jump {
margin: 12px 0 0 0;
}
}
@media only screen and (max-width: 480px) {

File diff suppressed because one or more lines are too long

View File

@ -873,21 +873,49 @@ var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachmen
hasMore: function() {
return this.mirroring ? this.mirroring.hasMore() : false;
},
/**
* Holds the total number of attachments.
*
* @since 5.7.0
*/
totalAttachments: 0,
/**
* Gets the total number of attachments.
*
* @since 5.7.0
*
* @return {number} The total number of attachments.
*/
getTotalAttachments: function() {
return this.mirroring ? this.mirroring.totalAttachments : 0;
},
/**
* A custom Ajax-response parser.
*
* See trac ticket #24753
*
* @param {Object|Array} resp The raw response Object/Array.
* Called automatically by Backbone whenever a collection's models are returned
* by the server, in fetch. The default implementation is a no-op, simply
* passing through the JSON response. We override this to add attributes to
* the collection items.
*
* Since WordPress 5.5, the response returns the attachments under `response.attachments`
* and `response.totalAttachments` holds the total number of attachments found.
*
* @param {Object|Array} response The raw response Object/Array.
* @param {Object} xhr
* @return {Array} The array of model attributes to be added to the collection
*/
parse: function( resp, xhr ) {
if ( ! _.isArray( resp ) ) {
resp = [resp];
parse: function( response, xhr ) {
if ( ! _.isArray( response.attachments ) ) {
response = [response.attachments];
}
return _.map( resp, function( attrs ) {
this.totalAttachments = parseInt( response.totalAttachments, 10 );
return _.map( response.attachments, function( attrs ) {
var id, attachment, newAttributes;
if ( attrs instanceof Backbone.Model ) {
@ -1197,8 +1225,11 @@ Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{
options = options || {};
options.remove = false;
return this._more = this.fetch( options ).done( function( resp ) {
if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {
return this._more = this.fetch( options ).done( function( response ) {
// Since WordPress 5.5, the response returns the attachments under `response.attachments`.
var attachments = response.attachments;
if ( _.isEmpty( attachments ) || -1 === this.args.posts_per_page || attachments.length < this.args.posts_per_page ) {
query._hasMore = false;
}
});

File diff suppressed because one or more lines are too long

View File

@ -7161,7 +7161,8 @@ module.exports = EditLibrary;
var View = wp.media.View,
$ = jQuery,
Attachments;
Attachments,
infiniteScrolling = wp.media.view.settings.infiniteScrolling;
Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
tagName: 'ul',
@ -7196,6 +7197,8 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
this.el.id = _.uniqueId('__attachments-view-');
/**
* @param infiniteScrolling Whether to enable infinite scrolling or use
* the default "load more" button.
* @param refreshSensitivity The time in milliseconds to throttle the scroll
* handler.
* @param refreshThreshold The amount of pixels that should be scrolled before
@ -7210,6 +7213,7 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
* calculating the total number of columns.
*/
_.defaults( this.options, {
infiniteScrolling: infiniteScrolling || false,
refreshSensitivity: wp.media.isTouchDevice ? 300 : 200,
refreshThreshold: 3,
AttachmentView: wp.media.view.Attachment,
@ -7245,11 +7249,13 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
this.controller.on( 'library:selection:add', this.attachmentFocus, this );
// Throttle the scroll handler and bind this.
this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
if ( this.options.infiniteScrolling ) {
// Throttle the scroll handler and bind this.
this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
this.options.scrollElement = this.options.scrollElement || this.el;
$( this.options.scrollElement ).on( 'scroll', this.scroll );
this.options.scrollElement = this.options.scrollElement || this.el;
$( this.options.scrollElement ).on( 'scroll', this.scroll );
}
this.initSortable();
@ -7548,7 +7554,9 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
this.views.set( this.collection.map( this.createAttachmentView, this ) );
} else {
this.views.unset();
this.collection.more().done( this.scroll );
if ( this.options.infiniteScrolling ) {
this.collection.more().done( this.scroll );
}
}
},
@ -7561,7 +7569,9 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
* @return {void}
*/
ready: function() {
this.scroll();
if ( this.options.infiniteScrolling ) {
this.scroll();
}
},
/**
@ -8000,7 +8010,10 @@ var View = wp.media.View,
mediaTrash = wp.media.view.settings.mediaTrash,
l10n = wp.media.view.l10n,
$ = jQuery,
AttachmentsBrowser;
AttachmentsBrowser,
infiniteScrolling = wp.media.view.settings.infiniteScrolling,
__ = wp.i18n.__,
sprintf = wp.i18n.sprintf;
/**
* wp.media.view.AttachmentsBrowser
@ -8066,12 +8079,16 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
this.createUploader();
}
// Add a heading before the attachments list.
this.createAttachmentsHeading();
// Create the list of attachments.
this.createAttachments();
// Create the attachments wrapper view.
this.createAttachmentsWrapperView();
if ( ! infiniteScrolling ) {
this.$el.addClass( 'has-load-more' );
this.createLoadMoreView();
}
// For accessibility reasons, place the normal sidebar after the attachments, see ticket #36909.
if ( this.options.sidebar && 'errors' !== this.options.sidebar ) {
@ -8090,6 +8107,10 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
this.collection.on( 'add remove reset', this.updateContent, this );
if ( ! infiniteScrolling ) {
this.collection.on( 'add remove reset', this.updateLoadMoreView, this );
}
// The non-cached or cached attachments query has completed.
this.collection.on( 'attachments:received', this.announceSearchResults, this );
},
@ -8104,7 +8125,14 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
* @return {void}
*/
announceSearchResults: _.debounce( function() {
var count;
var count,
/* translators: Accessibility text. %d: Number of attachments found in a search. */
mediaFoundHasMoreResultsMessage = __( 'Number of media items displayed: %d. Click load more for more results.' );
if ( infiniteScrolling ) {
/* translators: Accessibility text. %d: Number of attachments found in a search. */
mediaFoundHasMoreResultsMessage = __( 'Number of media items displayed: %d. Scroll the page for more results.' );
}
if ( this.collection.mirroring.args.s ) {
count = this.collection.length;
@ -8115,7 +8143,7 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
}
if ( this.collection.hasMore() ) {
wp.a11y.speak( l10n.mediaFoundHasMoreResults.replace( '%d', count ) );
wp.a11y.speak( mediaFoundHasMoreResultsMessage.replace( '%d', count ) );
return;
}
@ -8390,8 +8418,10 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
noItemsView;
if ( this.controller.isModeActive( 'grid' ) ) {
// Usually the media library.
noItemsView = view.attachmentsNoResults;
} else {
// Usually the media modal.
noItemsView = view.uploader;
}
@ -8431,6 +8461,23 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
}
},
/**
* Creates the Attachments wrapper view.
*
* @since 5.7.0
*
* @return {void}
*/
createAttachmentsWrapperView: function() {
this.attachmentsWrapper = new wp.media.View( {
className: 'attachments-wrapper'
} );
// Create the list of attachments.
this.views.add( this.attachmentsWrapper );
this.createAttachments();
},
createAttachments: function() {
this.attachments = new wp.media.view.Attachments({
controller: this.controller,
@ -8449,8 +8496,7 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
this.controller.on( 'attachment:keydown:arrow', _.bind( this.attachments.arrowEvent, this.attachments ) );
this.controller.on( 'attachment:details:shift-tab', _.bind( this.attachments.restoreFocus, this.attachments ) );
this.views.add( this.attachments );
this.views.add( '.attachments-wrapper', this.attachments );
if ( this.controller.isModeActive( 'grid' ) ) {
this.attachmentsNoResults = new View({
@ -8465,6 +8511,157 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
}
},
/**
* Creates the load more button and attachments counter view.
*
* @since 5.7.0
*
* @return {void}
*/
createLoadMoreView: function() {
var view = this;
this.loadMoreWrapper = new View( {
controller: this.controller,
className: 'load-more-wrapper'
} );
this.loadMoreCount = new View( {
controller: this.controller,
tagName: 'p',
className: 'load-more-count hidden'
} );
this.loadMoreButton = new wp.media.view.Button( {
text: __( 'Load more' ),
className: 'load-more hidden',
style: 'primary',
size: '',
click: function() {
view.loadMoreAttachments();
}
} );
this.loadMoreSpinner = new wp.media.view.Spinner();
this.loadMoreJumpToFirst = new wp.media.view.Button( {
text: __( 'Jump to first loaded item' ),
className: 'load-more-jump hidden',
size: '',
click: function() {
view.jumpToFirstAddedItem();
}
} );
this.views.add( '.attachments-wrapper', this.loadMoreWrapper );
this.views.add( '.load-more-wrapper', this.loadMoreSpinner );
this.views.add( '.load-more-wrapper', this.loadMoreCount );
this.views.add( '.load-more-wrapper', this.loadMoreButton );
this.views.add( '.load-more-wrapper', this.loadMoreJumpToFirst );
},
/**
* Updates the Load More view. This function is debounced because the
* collection updates multiple times at the add, remove, and reset events.
* We need it to run only once, after all attachments are added or removed.
*
* @since 5.7.0
*
* @return {void}
*/
updateLoadMoreView: _.debounce( function() {
// Ensure the load more view elements are initially hidden at each update.
this.loadMoreButton.$el.addClass( 'hidden' );
this.loadMoreCount.$el.addClass( 'hidden' );
this.loadMoreJumpToFirst.$el.addClass( 'hidden' ).prop( 'disabled', true );
if ( ! this.collection.getTotalAttachments() ) {
return;
}
if ( this.collection.length ) {
this.loadMoreCount.$el.text(
/* translators: 1: Number of displayed attachments, 2: Number of total attachments. */
sprintf(
__( 'Showing %1$s of %2$s media items' ),
this.collection.length,
this.collection.getTotalAttachments()
)
);
this.loadMoreCount.$el.removeClass( 'hidden' );
}
/*
* Notice that while the collection updates multiple times hasMore() may
* return true when it's actually not true.
*/
if ( this.collection.hasMore() ) {
this.loadMoreButton.$el.removeClass( 'hidden' );
}
// Find the media item to move focus to. The jQuery `eq()` index is zero-based.
this.firstAddedMediaItem = this.$el.find( '.attachment' ).eq( this.firstAddedMediaItemIndex );
// If there's a media item to move focus to, make the "Jump to" button available.
if ( this.firstAddedMediaItem.length ) {
this.firstAddedMediaItem.addClass( 'new-media' );
this.loadMoreJumpToFirst.$el.removeClass( 'hidden' ).prop( 'disabled', false );
}
// If there are new items added, but no more to be added, move focus to Jump button.
if ( this.firstAddedMediaItem.length && ! this.collection.hasMore() ) {
this.loadMoreJumpToFirst.$el.trigger( 'focus' );
}
}, 10 ),
/**
* Loads more attachments.
*
* @since 5.7.0
*
* @return {void}
*/
loadMoreAttachments: function() {
var view = this;
if ( ! this.collection.hasMore() ) {
return;
}
/*
* The collection index is zero-based while the length counts the actual
* amount of items. Thus the length is equivalent to the position of the
* first added item.
*/
this.firstAddedMediaItemIndex = this.collection.length;
this.$el.addClass( 'more-loaded' );
this.collection.each( function( attachment ) {
var attach_id = attachment.attributes.id;
$( '[data-id="' + attach_id + '"]' ).addClass( 'found-media' );
});
view.loadMoreSpinner.show();
this.collection.more().done( function() {
// Within done(), `this` is the returned collection.
view.loadMoreSpinner.hide();
} );
},
/**
* Moves focus to the first new added item. .
*
* @since 5.7.0
*
* @return {void}
*/
jumpToFirstAddedItem: function() {
// Set focus on first added item.
this.firstAddedMediaItem.focus();
},
createAttachmentsHeading: function() {
this.attachmentsHeading = new wp.media.view.Heading( {
text: l10n.attachmentsList,

File diff suppressed because one or more lines are too long

View File

@ -4306,29 +4306,39 @@ function wp_enqueue_media( $args = array() ) {
);
}
/**
* Filters whether the Media Library grid has infinite scrolling. Default `false`.
*
* @since 5.7.0
*
* @param bool $value The filtered value, defaults to `false`.
*/
$infinite_scrolling = apply_filters( 'media_library_infinite_scrolling', false );
$settings = array(
'tabs' => $tabs,
'tabUrl' => add_query_arg( array( 'chromeless' => true ), admin_url( 'media-upload.php' ) ),
'mimeTypes' => wp_list_pluck( get_post_mime_types(), 0 ),
'tabs' => $tabs,
'tabUrl' => add_query_arg( array( 'chromeless' => true ), admin_url( 'media-upload.php' ) ),
'mimeTypes' => wp_list_pluck( get_post_mime_types(), 0 ),
/** This filter is documented in wp-admin/includes/media.php */
'captions' => ! apply_filters( 'disable_captions', '' ),
'nonce' => array(
'captions' => ! apply_filters( 'disable_captions', '' ),
'nonce' => array(
'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
),
'post' => array(
'post' => array(
'id' => 0,
),
'defaultProps' => $props,
'attachmentCounts' => array(
'defaultProps' => $props,
'attachmentCounts' => array(
'audio' => ( $show_audio_playlist ) ? 1 : 0,
'video' => ( $show_video_playlist ) ? 1 : 0,
),
'oEmbedProxyUrl' => rest_url( 'oembed/1.0/proxy' ),
'embedExts' => $exts,
'embedMimes' => $ext_mimes,
'contentWidth' => $content_width,
'months' => $months,
'mediaTrash' => MEDIA_TRASH ? 1 : 0,
'oEmbedProxyUrl' => rest_url( 'oembed/1.0/proxy' ),
'embedExts' => $exts,
'embedMimes' => $ext_mimes,
'contentWidth' => $content_width,
'months' => $months,
'mediaTrash' => MEDIA_TRASH ? 1 : 0,
'infiniteScrolling' => ( $infinite_scrolling ) ? 1 : 0,
);
$post = null;
@ -4412,8 +4422,8 @@ function wp_enqueue_media( $args = array() ) {
'searchLabel' => __( 'Search' ),
'searchMediaLabel' => __( 'Search media' ), // Backward compatibility pre-5.3.
'searchMediaPlaceholder' => __( 'Search media items...' ), // Placeholder (no ellipsis), backward compatibility pre-5.3.
/* translators: %d: Number of attachments found in a search. */
'mediaFound' => __( 'Number of media items found: %d' ),
'mediaFoundHasMoreResults' => __( 'Number of media items displayed: %d. Scroll the page for more results.' ),
'noMedia' => __( 'No media items found.' ),
'noMediaTryNewSearch' => __( 'No media items found. Try a different search.' ),

View File

@ -13,7 +13,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.8-alpha-50828';
$wp_version = '5.8-alpha-50829';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.