Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions src/js/media/views/attachments.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,11 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{

this.controller.on( 'library:selection:add', this.attachmentFocus, this );

if ( this.options.infiniteScrolling ) {
// Throttle the scroll handler and bind this.
this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
// 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();

Expand Down Expand Up @@ -422,6 +420,7 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
* server if we're {refreshThreshold} times away from the bottom.
*
* @since 3.5.0
* @since 7.1.0 Bails out when infinite scrolling is disabled.
*
* @return {void}
*/
Expand All @@ -431,6 +430,10 @@ Attachments = View.extend(/** @lends wp.media.view.Attachments.prototype */{
scrollTop = el.scrollTop,
toolbar;

if ( ! this.options.infiniteScrolling ) {
return;
}

/*
* The scroll event occurs on the document, but the element that should be
* checked is the document body.
Expand Down
146 changes: 137 additions & 9 deletions src/js/media/views/attachments/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var View = wp.media.View,
$ = jQuery,
AttachmentsBrowser,
infiniteScrolling = wp.media.view.settings.infiniteScrolling,
canToggleInfiniteScrolling = wp.media.view.settings.canToggleInfiniteScrolling,
__ = wp.i18n.__,
sprintf = wp.i18n.sprintf;

Expand Down Expand Up @@ -43,6 +44,8 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
AttachmentView: wp.media.view.Attachment.Library
});

this.infiniteScrolling = !! infiniteScrolling;

this.controller.on( 'toggle:upload:attachment', this.toggleUploader, this );
this.controller.on( 'edit:selection', this.editSelection );

Expand Down Expand Up @@ -77,7 +80,7 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
// Create the attachments wrapper view.
this.createAttachmentsWrapperView();

if ( ! infiniteScrolling ) {
if ( ! this.infiniteScrolling ) {
this.$el.addClass( 'has-load-more' );
this.createLoadMoreView();
}
Expand All @@ -89,7 +92,7 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro

this.updateContent();

if ( ! infiniteScrolling ) {
if ( ! this.infiniteScrolling ) {
this.updateLoadMoreView();
}

Expand All @@ -102,10 +105,7 @@ 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 );
}
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 );
Expand All @@ -125,7 +125,7 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
/* 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 ) {
if ( this.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.' );
}
Expand Down Expand Up @@ -472,19 +472,142 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
className: 'attachments-wrapper'
} );

// Create the list of attachments.
this.views.add( this.attachmentsWrapper );

/*
* Place the infinite scrolling toggle before the list of attachments. It
* saves the personal option, so it is only offered when wp_enqueue_media()
* reports that saving that option takes effect.
*/
if ( canToggleInfiniteScrolling ) {
this.createInfiniteScrollingToggle();
}

// Create the list of attachments.
this.createAttachments();
},

/**
* Creates the checkbox that turns infinite scrolling on and off.
*
* @since 7.1.0
*
* @return {void}
*/
createInfiniteScrollingToggle: function() {
var view = this,
id = _.uniqueId( 'media-infinite-scrolling-' ),
checkbox = $( '<input />', {
type: 'checkbox',
id: id,
checked: this.infiniteScrolling
} ),
label = $( '<label />', {
'for': id,
text: __( 'Infinite scrolling' )
} );

// Not a live region: the same message is sent to `speak()` when it changes.
this.infiniteScrollingStatus = $( '<span />', {
'class': 'media-infinite-scrolling-status'
} );

checkbox.on( 'change', function() {
view.toggleInfiniteScrolling( this.checked );
view.saveInfiniteScrolling( this.checked );
} );

this.infiniteScrollingToggle = new View( {
controller: this.controller,
className: 'media-infinite-scrolling'
} );

this.infiniteScrollingToggle.$el.append( checkbox, label, this.infiniteScrollingStatus );

this.views.add( '.attachments-wrapper', this.infiniteScrollingToggle );
},

/**
* Saves the infinite scrolling preference for the current user.
*
* @since 7.1.0
*
* @param {boolean} infiniteScrolling Whether the attachments list has infinite scrolling.
*
* @return {void}
*/
saveInfiniteScrolling: function( infiniteScrolling ) {
var view = this;

wp.ajax.post( 'save-media-infinite-scrolling', {
nonce: wp.media.view.settings.nonce.saveInfiniteScrolling,
infiniteScrolling: infiniteScrolling
} ).done( function() {
view.updateInfiniteScrollingStatus(
infiniteScrolling ?
__( 'Infinite scrolling enabled. Preference saved.' ) :
__( 'Infinite scrolling disabled. Load more button displayed. Preference saved.' )
);
} ).fail( function() {
view.updateInfiniteScrollingStatus( __( 'The infinite scrolling preference could not be saved.' ) );
} );
},

/**
* Displays and announces the result of changing the infinite scrolling preference.
*
* The controls it affects are at the end of the list of attachments, so the
* result is usually out of view when the checkbox changes.
*
* @since 7.1.0
*
* @param {string} message The message to display and announce.
*
* @return {void}
*/
updateInfiniteScrollingStatus: function( message ) {
this.infiniteScrollingStatus.text( message );
wp.a11y.speak( message );
},

/**
* Turns infinite scrolling of the attachments list on and off.
*
* When infinite scrolling is off, the "Load more" button is used instead.
*
* @since 7.1.0
*
* @param {boolean} infiniteScrolling Whether the attachments list has infinite scrolling.
*
* @return {void}
*/
toggleInfiniteScrolling: function( infiniteScrolling ) {
this.infiniteScrolling = infiniteScrolling;
this.attachments.options.infiniteScrolling = infiniteScrolling;
this.$el.toggleClass( 'has-load-more', ! infiniteScrolling );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be helpful to include some kind of visual affordance that confirms that something has happened, since all the control changes happen out of the viewport.

I also think that the control needs to save this preference for the user, so one possibility would be a notice that appears/is spoken saying "Infinite scrolling preference saved"

if ( ! this.loadMoreWrapper ) {
this.createLoadMoreView();
}

this.loadMoreWrapper.$el.toggleClass( 'hidden', infiniteScrolling );

if ( infiniteScrolling ) {
this.attachments.scroll();
} else {
this.updateLoadMoreView();
}
},

createAttachments: function() {
this.attachments = new wp.media.view.Attachments({
controller: this.controller,
collection: this.collection,
selection: this.options.selection,
model: this.model,
sortable: this.options.sortable,
scrollElement: this.options.scrollElement,
infiniteScrolling: this.infiniteScrolling,
scrollElement: this.options.scrollElement || this.attachmentsWrapper.el,
idealColumnWidth: this.options.idealColumnWidth,

// The single `Attachment` view to be used in the `Attachments` view.
Expand Down Expand Up @@ -565,10 +688,15 @@ AttachmentsBrowser = View.extend(/** @lends wp.media.view.AttachmentsBrowser.pro
* We need it to run only once, after all attachments are added or removed.
*
* @since 5.8.0
* @since 7.1.0 Bails out when infinite scrolling is enabled.
*
* @return {void}
*/
updateLoadMoreView: _.debounce( function() {
if ( this.infiniteScrolling ) {
return;
}

// Ensure the load more view elements are initially hidden at each update.
this.loadMoreButton.$el.addClass( 'hidden' );
this.loadMoreCount.$el.addClass( 'hidden' );
Expand Down
1 change: 1 addition & 0 deletions src/wp-admin/admin-ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
'send-link-to-editor',
'send-attachment-to-editor',
'save-attachment-order',
'save-media-infinite-scrolling',
'media-create-image-subsizes',
'heartbeat',
'get-revision-diffs',
Expand Down
6 changes: 2 additions & 4 deletions src/wp-admin/css/media.css
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,7 @@ 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:not(.has-load-more) .attachments,
.media-frame.mode-grid .attachments-browser.has-load-more .attachments-wrapper,
.media-frame.mode-grid .attachments-browser .attachments-wrapper,
.media-frame.mode-grid .uploader-inline-content {
position: static;
}
Expand Down Expand Up @@ -518,8 +517,7 @@ border color while dragging a file over the uploader drop area */
border: 4px dashed #c3c4c7;
}

.media-frame.mode-select .attachments-browser.fixed:not(.has-load-more) .attachments,
.media-frame.mode-select .attachments-browser.has-load-more.fixed .attachments-wrapper {
.media-frame.mode-select .attachments-browser.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 */
Expand Down
23 changes: 23 additions & 0 deletions src/wp-admin/includes/ajax-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -3317,6 +3317,29 @@ function wp_ajax_save_attachment_order() {
wp_send_json_success();
}

/**
* Handles saving the current user's Media Library infinite scrolling preference via AJAX.
*
* Writes the same personal option as the "Infinite Scrolling" checkbox on the
* profile screen, so that the preference set from the attachments browser
* persists beyond the current view.
*
* @since 7.1.0
*/
function wp_ajax_save_media_infinite_scrolling() {
check_ajax_referer( 'save-media-infinite-scrolling', 'nonce' );

if ( ! isset( $_POST['infiniteScrolling'] ) ) {
wp_send_json_error();
}

$infinite_scrolling = wp_validate_boolean( wp_unslash( $_POST['infiniteScrolling'] ) );

update_user_meta( get_current_user_id(), 'infinite_scrolling', $infinite_scrolling ? 'true' : 'false' );

wp_send_json_success();
}

/**
* Handles sending an attachment to the editor via AJAX.
*
Expand Down
31 changes: 28 additions & 3 deletions src/wp-includes/css/media-views.css
Original file line number Diff line number Diff line change
Expand Up @@ -1276,8 +1276,7 @@ select#media-attachment-filters ~ select#media-attachment-date-filters {
padding: 2px 8px 8px;
}

.attachments-browser:not(.has-load-more) .attachments,
.attachments-browser.has-load-more .attachments-wrapper,
.attachments-browser .attachments-wrapper,
.attachments-browser .uploader-inline {
position: absolute;
top: 72px;
Expand All @@ -1288,6 +1287,27 @@ select#media-attachment-filters ~ select#media-attachment-date-filters {
outline: none;
}

.attachments-browser .media-infinite-scrolling {
padding: 8px 16px 12px;
}

.attachments-browser .media-infinite-scrolling-status {
margin-left: 12px;
color: #50575e;
}

/* In the modal, the media items list scrolls: keep the toggle in view. */
.media-modal .attachments-browser .media-infinite-scrolling {
position: sticky;
top: 0;
z-index: 1;
background: #fff;
}

.attachments-browser .load-more-wrapper.hidden {
display: none;
}

.attachments-browser .uploader-inline.hidden {
display: none;
}
Expand Down Expand Up @@ -1341,7 +1361,7 @@ select#media-attachment-filters ~ select#media-attachment-date-filters {
box-shadow: 0 0 3px rgba(var(--wp-admin-theme-color--rgb, 56, 88, 233), 0.8);
}

.attachments-browser.hide-sidebar .attachments,
.attachments-browser.hide-sidebar .attachments-wrapper,
.attachments-browser.hide-sidebar .uploader-inline {
right: 0;
margin-right: 0;
Expand Down Expand Up @@ -2654,6 +2674,10 @@ select#media-attachment-filters ~ select#media-attachment-date-filters {
top: 131px;
}

.attachments-browser .media-infinite-scrolling {
padding: 14px 16px 0px;
}

.media-sidebar .setting,
.attachment-details .setting {
margin: 6px 0;
Expand Down Expand Up @@ -2758,6 +2782,7 @@ select#media-attachment-filters ~ select#media-attachment-date-filters {
font-size: 16px;
line-height: 1.625;
padding: 5px 24px 5px 8px;
margin: 0;
}

.image-details .column-image {
Expand Down
Loading
Loading