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:
parent
5853905b35
commit
89dff37759
|
@ -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
|
@ -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
|
@ -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,15 +158,14 @@
|
|||
},
|
||||
|
||||
createStates: function() {
|
||||
var options = this.options;
|
||||
var options = this.options,
|
||||
libraryState;
|
||||
|
||||
if ( this.options.states ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the default states.
|
||||
this.states.add([
|
||||
new media.controller.Library({
|
||||
libraryState = new media.controller.Library({
|
||||
library: media.query( options.library ),
|
||||
multiple: options.multiple,
|
||||
title: options.title,
|
||||
|
@ -203,7 +174,17 @@
|
|||
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([
|
||||
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
|
@ -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
|
@ -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' ) ?><#
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue