Media grid:

* Introduce the concept of bulk editing via a separate mode. Like the list view, only bulk deleting is available. The UI is a little funky, especially with the field display toggles there, but refinements will come.
* Up the max thumbnail size from 120px to 150px.
* Slide-down panel for the add new uploader. Known issue: it doesn't close again.
* Remove the toolbar region in the EditAttachment frame.
* Defer a function call so the grid fills available space.
* Give feedback when no results are found. Also needs styling.

props ericlewis. see #24716.

Built from https://develop.svn.wordpress.org/trunk@29056


git-svn-id: http://core.svn.wordpress.org/trunk@28844 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Helen Hou-Sandí 2014-07-10 03:50:17 +00:00
parent 5853905b35
commit 89dff37759
9 changed files with 240 additions and 99 deletions

View File

@ -228,7 +228,6 @@
.media-toolbar-secondary > .media-button,
.media-toolbar-secondary > .media-button-group {
margin-left: 10px;
float: right;
margin-top: 15px;
}
@ -996,6 +995,25 @@
bottom: 0;
overflow: auto;
outline: none;
-webkit-transition: 1s ease-in-out;
transition: 1s ease-in-out;
}
.attachments-browser .uploader-inline:not(.hidden) + .attachments {
-webkit-transform: translateY( 300px );
-ms-transform: translateY( 300px );
transform: translateY( 300px );
}
.attachments-browser .uploader-inline.hidden {
display: block;
-webkit-transform: translateY( -100% );
-ms-transform: translateY( -100% );
transform: translateY( -100% );
}
.attachments-browser .uploader-inline-content {
top: 0;
}
.inline-toolbar {
@ -1081,7 +1099,8 @@ video#inline-media-node {
right: 0;
}
.attachments-browser.hide-sidebar .attachments {
.attachments-browser.hide-sidebar .attachments,
.attachments-browser.hide-sidebar .uploader-inline {
left: 0;
margin-left: 0;
}
@ -2657,6 +2676,11 @@ video#inline-media-node {
right: 0;
}
.edit-attachment-frame .media-frame-content {
border-bottom: none;
bottom: 0;
}
/* Hiding this for the moment instead of removing it from the template. */
.edit-attachment-frame h3 {
display: none;

File diff suppressed because one or more lines are too long

View File

@ -228,7 +228,6 @@
.media-toolbar-secondary > .media-button,
.media-toolbar-secondary > .media-button-group {
margin-right: 10px;
float: left;
margin-top: 15px;
}
@ -996,6 +995,25 @@
bottom: 0;
overflow: auto;
outline: none;
-webkit-transition: 1s ease-in-out;
transition: 1s ease-in-out;
}
.attachments-browser .uploader-inline:not(.hidden) + .attachments {
-webkit-transform: translateY( 300px );
-ms-transform: translateY( 300px );
transform: translateY( 300px );
}
.attachments-browser .uploader-inline.hidden {
display: block;
-webkit-transform: translateY( -100% );
-ms-transform: translateY( -100% );
transform: translateY( -100% );
}
.attachments-browser .uploader-inline-content {
top: 0;
}
.inline-toolbar {
@ -1081,7 +1099,8 @@ video#inline-media-node {
left: 0;
}
.attachments-browser.hide-sidebar .attachments {
.attachments-browser.hide-sidebar .attachments,
.attachments-browser.hide-sidebar .uploader-inline {
right: 0;
margin-right: 0;
}
@ -2657,6 +2676,11 @@ video#inline-media-node {
left: 0;
}
.edit-attachment-frame .media-frame-content {
border-bottom: none;
bottom: 0;
}
/* Hiding this for the moment instead of removing it from the template. */
.edit-attachment-frame h3 {
display: none;

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,6 @@
menu: false,
router: 'edit-metadata',
content: 'edit-metadata',
toolbar: 'toolbar',
url: ''
},
@ -34,10 +33,6 @@
media.controller._State.prototype.initialize.apply( this, arguments );
},
activate: function() {
this.listenTo( this.frame, 'toolbar:render:edit-image', this.toolbar );
},
_postActivate: function() {
this._content();
this._router();
@ -47,30 +42,6 @@
this.stopListening( this.frame );
},
toolbar: function() {
var frame = this.frame,
lastState = frame.lastState(),
previous = lastState && lastState.id;
frame.toolbar.set( new media.view.Toolbar({
controller: frame,
items: {
back: {
style: 'primary',
text: l10n.back,
priority: 20,
click: function() {
if ( previous ) {
frame.setState( previous );
} else {
frame.close();
}
}
}
}
}) );
},
/**
* @access private
*/
@ -125,12 +96,13 @@
modal: false,
selection: [],
library: {},
multiple: false,
multiple: 'add',
state: 'library',
uploader: true,
mode: [ 'grid', 'edit' ]
});
$(document).on( 'click', '.add-new-h2', _.bind( this.addNewClickHandler, this ) );
// Ensure core and media grid view UI is enabled.
this.$el.addClass('wp-core-ui media-grid-view');
@ -186,24 +158,33 @@
},
createStates: function() {
var options = this.options;
var options = this.options,
libraryState;
if ( this.options.states ) {
return;
}
libraryState = new media.controller.Library({
library: media.query( options.library ),
multiple: options.multiple,
title: options.title,
priority: 20,
toolbar: false,
router: false,
content: 'browse',
filterable: 'mime-types'
});
libraryState._renderTitle = function( view ) {
var text = this.get('title') || '';
view.$el.addClass( 'wrap' );
text += '<a class="add-new-h2">Add New</a>';
view.$el.html( text );
};
// Add the default states.
this.states.add([
new media.controller.Library({
library: media.query( options.library ),
multiple: options.multiple,
title: options.title,
priority: 20,
toolbar: false,
router: false,
content: 'browse',
filterable: 'mime-types'
})
libraryState
]);
},
@ -217,6 +198,10 @@
this.on( 'edit:attachment:previous', this.editPreviousAttachment, this );
},
addNewClickHandler: function() {
this.trigger( 'show:upload:attachment' );
},
editPreviousAttachment: function( currentModel ) {
var library = this.state().get('library'),
currentModelIndex = library.indexOf( currentModel );
@ -233,26 +218,17 @@
* Open the Edit Attachment modal.
*/
editAttachment: function( model ) {
var library = this.state().get('library'), hasPrevious, hasNext;
if ( library.indexOf( model ) > 0 ) {
hasPrevious = true;
}
else {
hasPrevious = false;
}
if ( library.indexOf( model ) < library.length - 1 ) {
hasNext = true;
}
else {
hasNext = false;
}
var library = this.state().get('library');
new media.view.Frame.EditAttachment({
hasPrevious: hasPrevious,
hasNext: hasNext,
model: model,
gridController: this
// Create a new EditAttachment frame, passing along the library and the attachment model.
this.editAttachmentFrame = new media.view.Frame.EditAttachment({
library: library,
model: model
});
// Listen to events on the edit attachment frame for triggering pagination callback handlers.
this.listenTo( this.editAttachmentFrame, 'edit:attachment:next', this.editNextAttachment );
this.listenTo( this.editAttachmentFrame, 'edit:attachment:previous', this.editPreviousAttachment );
},
/**
@ -363,6 +339,9 @@
this.on( 'router:render', this.browseRouter, this );
}
this.options.hasPrevious = ( this.options.library.indexOf( this.options.model ) > 0 ) ? true : false;
this.options.hasNext = ( this.options.library.indexOf( this.options.model ) < this.options.library.length - 1 ) ? true : false;
// Initialize modal container view.
if ( this.options.modal ) {
this.modal = new media.view.Modal({
@ -471,7 +450,7 @@
if ( ! this.options.hasPrevious )
return;
this.modal.close();
this.options.gridController.trigger( 'edit:attachment:previous', this.model );
this.trigger( 'edit:attachment:previous', this.model );
},
/**
@ -481,9 +460,8 @@
if ( ! this.options.hasNext )
return;
this.modal.close();
this.options.gridController.trigger( 'edit:attachment:next', this.model );
this.trigger( 'edit:attachment:next', this.model );
}
});
media.view.GridFieldOptions = media.View.extend({
@ -514,4 +492,58 @@
}
});
media.view.BulkSelectionToggleButton = media.view.Button.extend({
initialize: function() {
media.view.Button.prototype.initialize.apply( this, arguments );
this.listenTo( this.controller, 'bulk-edit:activate bulk-edit:deactivate', _.bind( this.toggleBulkEditHandler, this ) );
},
click: function() {
var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
media.view.Button.prototype.click.apply( this, arguments );
if ( bulkEditActive ) {
this.controller.deactivateMode( 'bulk-edit' );
this.controller.activateMode( 'edit' );
} else {
this.controller.deactivateMode( 'edit' );
this.controller.activateMode( 'bulk-edit' );
}
},
toggleBulkEditHandler: function() {
var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
if ( bulkEditActive ) {
this.$el.addClass( 'button-primary' );
} else {
this.$el.removeClass( 'button-primary' );
this.controller.state().get('selection').reset();
}
}
});
media.view.BulkDeleteButton = media.view.Button.extend({
initialize: function() {
media.view.Button.prototype.initialize.apply( this, arguments );
this.$el.hide();
this.listenTo( this.controller, 'bulk-edit:activate bulk-edit:deactivate', _.bind( this.visibility, this ) );
},
click: function() {
media.view.Button.prototype.click.apply( this, arguments );
while (this.controller.state().get('selection').length > 0) {
this.controller.state().get('selection').at(0).destroy();
}
},
visibility: function() {
var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
if ( bulkEditActive ) {
this.$el.show();
} else {
this.$el.hide();
}
}
});
}(jQuery, _, Backbone, wp));

File diff suppressed because one or more lines are too long

View File

@ -665,7 +665,7 @@
}
if ( ! this.get('edge') ) {
this.set( 'edge', 120 );
this.set( 'edge', 150 );
}
if ( ! this.get('gutter') ) {
@ -1785,14 +1785,13 @@
* @global wp.Uploader
*/
initialize: function() {
media.view.Frame.prototype.initialize.apply( this, arguments );
_.defaults( this.options, {
title: '',
modal: true,
uploader: true,
mode: ['select']
mode: [ 'select' ]
});
// Ensure core UI is enabled.
@ -1808,6 +1807,14 @@
this.modal.content( this );
}
// Store active "modes" that the frame is in. Unrelated to region modes.
this.activeModes = new Backbone.Collection();
this.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );
_.each( this.options.mode, function( mode ) {
this.activeModes.add( new Backbone.Model( { id: mode } ) );
}, this );
// Force the uploader off if the upload limit has been exceeded or
// if the browser isn't supported.
if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {
@ -1972,6 +1979,42 @@
window.tb_remove = this._tb_remove;
delete this._tb_remove;
},
/**
* Map activeMode collection events to the frame.
*/
triggerModeEvents: function( model, collection, options ) {
var collectionEvent,
modeEventMap = {
add: 'activate',
remove: 'deactivate'
},
eventToTrigger;
// Probably a better way to do this.
_.each( options, function( value, key ) {
if ( value ) {
collectionEvent = key;
}
} );
if ( ! _.has( modeEventMap, collectionEvent ) )
return;
eventToTrigger = model.get('id') + ':' + modeEventMap[collectionEvent];
this.trigger( eventToTrigger );
},
activateMode: function( mode ) {
this.activeModes.add( [ { id: mode } ] );
this.trigger( mode + ':activate' );
},
deactivateMode: function( mode ) {
// Bail if the mode isn't active.
if ( ! this.activeModes.where( { id: mode } ).length ) {
return;
}
this.activeModes.remove( this.activeModes.where( { id: mode } ) );
this.trigger( mode + ':deactivate' );
}
});
@ -4673,7 +4716,7 @@
}
// In the grid view, bubble up an edit:attachment event to the controller.
if ( _.contains( this.controller.options.mode, 'grid' ) ) {
if ( this.controller.activeModes.where( { id: 'edit' } ).length ) {
this.controller.trigger( 'edit:attachment', this.model );
return;
}
@ -5081,7 +5124,10 @@
if ( this.options.resize ) {
$(window).on( 'resize.attachments', this._resizeCss );
}
this.css();
// Call this.css() after this view has been rendered in the DOM so
// attachments get proper width applied.
_.defer( this.css, this );
},
dispose: function() {
@ -5531,7 +5577,10 @@
AttachmentView: media.view.Attachment.Library
});
this.listenTo( this.controller, 'show:upload:attachment', _.bind( this.showUploader, this ) );
this.createToolbar();
this.createUploader();
this.createAttachments();
this.updateContent();
if ( this.options.sidebar ) {
this.createSidebar();
@ -5568,7 +5617,7 @@
// Feels odd to bring the global media library switcher into the Attachment
// browser view. Is this a use case for doAction( 'add:toolbar-items:attachments-browser', this.toolbar );
// which the controller can tap into and add this view?
if ( _.contains( this.controller.options.mode, 'grid' ) ) {
if ( this.controller.activeModes.where( { id: 'grid' } ).length ) {
LibraryViewSwitcher = media.View.extend({
className: 'view-switch media-grid-view-switch',
template: media.template( 'media-library-view-switcher')
@ -5578,6 +5627,18 @@
priority: -90
}).render() );
this.toolbar.set( 'bulkSelectionToggleButton', new media.view.BulkSelectionToggleButton({
text: 'Bulk Edit',
controller: this.controller,
priority: -70
}).render() );
this.toolbar.set( 'BulkDeleteButton', new media.view.BulkDeleteButton({
text: 'Bulk Delete',
controller: this.controller,
priority: -69
}).render() );
this.toolbar.set( 'gridFieldOptions', new media.view.GridFieldOptions({
controller: this.controller,
priority: -50
@ -5635,48 +5696,38 @@
updateContent: function() {
var view = this;
if( ! this.attachments ) {
this.createAttachments();
}
if ( ! this.collection.length ) {
this.toolbar.get( 'spinner' ).show();
this.collection.more().done(function() {
if ( ! view.collection.length ) {
view.createUploader();
view.attachmentsNoResults.$el.removeClass( 'hidden' );
} else {
view.attachmentsNoResults.$el.addClass( 'hidden' );
}
view.toolbar.get( 'spinner' ).hide();
});
} else {
this.attachmentsNoResults.$el.addClass( 'hidden' );
view.toolbar.get( 'spinner' ).hide();
}
},
removeContent: function() {
_.each(['attachments','uploader'], function( key ) {
if ( this[ key ] ) {
this[ key ].remove();
delete this[ key ];
}
}, this );
},
createUploader: function() {
this.removeContent();
this.uploader = new media.view.UploaderInline({
controller: this.controller,
status: false,
message: l10n.noItemsFound
});
this.uploader.$el.addClass( 'hidden' );
this.views.add( this.uploader );
},
createAttachments: function() {
this.removeContent();
showUploader: function() {
this.uploader.$el.removeClass( 'hidden' );
},
createAttachments: function() {
this.attachments = new media.view.Attachments({
controller: this.controller,
collection: this.collection,
@ -5690,6 +5741,17 @@
});
this.views.add( this.attachments );
this.attachmentsNoResults = new media.View({
controller: this.controller
});
this.attachmentsNoResults.$el.addClass( 'hidden' );
this.attachmentsNoResults.$el.html( 'No media found.' );
this.views.add( this.attachmentsNoResults );
},
createSidebar: function() {

File diff suppressed because one or more lines are too long

View File

@ -276,7 +276,6 @@ function wp_print_media_templates() {
</div>
<div class="media-frame-router"></div>
<div class="media-frame-content"></div>
<div class="media-frame-toolbar"></div>
</script>
<script type="text/html" id="tmpl-attachment-details-two-column">
@ -447,7 +446,7 @@ function wp_print_media_templates() {
<div class="{{ className }} data-{{ field }}"><#
if ( 'uploadedTo' === field ) {
if ( data[ field ] ) {
#><?php _e( 'Uploaded To: ' ) ?>{{ data.uploadedToTitle }}<#
#><?php _e( 'Uploaded To: ' ) ?><a href="{{ data.uploadedToLink }}">{{ data.uploadedToTitle }}</a><#
} else {
#><?php _e( 'Unattached' ) ?><#
}