diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css index 0fa96e7c34..9fa98ee3e6 100644 --- a/wp-includes/css/media-views.css +++ b/wp-includes/css/media-views.css @@ -811,10 +811,33 @@ font-weight: bold; } -.media-selection .clear-selection { +.media-selection .selection-info a { display: block; - text-decoration: none; + float: left; + padding: 1px 8px; + margin: 1px 8px 1px -8px; line-height: 16px; + text-decoration: none; + border-right: 1px solid #dfdfdf; + color: #21759B; +} + +.media-selection .selection-info a:hover { + background: #21759B; + color: #fff; + border-color: transparent; +} + +.media-selection .selection-info a:last-child { + border-right: 0; +} + +.media-selection .selection-info .clear-selection { + color: red; +} + +.media-selection .selection-info .clear-selection:hover { + background: red; } .media-selection .attachments { @@ -825,11 +848,17 @@ vertical-align: top; } -.media-selection .selected.attachment { +.attachment.selection.selected { box-shadow: none; } -.media-selection .details.attachment { +.attachment.selection.details { + box-shadow: + 0 0 0 1px #fff, + 0 0 0 4px #1e8cbe; +} + +.media-selection .attachment.selection.details { box-shadow: 0 0 0 1px #fff, 0 0 0 3px #1e8cbe; diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js index b2e762f396..95f1aa6f76 100644 --- a/wp-includes/js/media-views.js +++ b/wp-includes/js/media-views.js @@ -372,32 +372,20 @@ }, refreshSelection: function() { + var selection = this.get('selection'), + mode = this.frame.content.mode(); + this.frame.toolbar.view().refresh(); - this.trigger( 'refresh:selection', this, this.get('selection') ); + this.trigger( 'refresh:selection', this, selection ); + + if ( ! selection.length && 'browse' !== mode && 'upload' !== mode ) + this.content(); }, selectUpload: function( attachment ) { this.get('selection').add( attachment ); }, - toggleSelection: function( model ) { - var selection = this.get('selection'); - - if ( ! model ) - return; - - if ( selection.has( model ) ) { - // If the model is the single model, remove it. - // If it is not the same as the single model, - // it now becomes the single model. - selection[ selection.single() === model ? 'remove' : 'single' ]( model ); - } else { - selection.add( model ).single(); - } - - return this; - }, - buildComposite: function() { var original = this.get('_library'), exclude = this.get('exclude'), @@ -518,7 +506,7 @@ // The single `Attachment` view to be used in the `Attachments` view. if ( ! this.get('AttachmentView') ) - this.set( 'AttachmentView', media.view.Attachment.Gallery ); + this.set( 'AttachmentView', media.view.Attachment.EditLibrary ); media.controller.Library.prototype.initialize.apply( this, arguments ); }, @@ -867,6 +855,7 @@ this.content.view( new media.view.AttachmentsBrowser({ controller: this, collection: state.get('library'), + selection: state.get('selection'), model: state, sortable: state.get('sortable'), search: state.get('searchable'), @@ -980,6 +969,7 @@ main = { multiple: this.options.multiple, menu: 'main', + sidebar: 'attachment-settings', // Update user settings when users adjust the // attachment display settings. @@ -1058,12 +1048,13 @@ var handlers = { menu: { - batch: 'batchMenu', - gallery: 'galleryMenu' + 'batch': 'batchMenu', + 'gallery': 'galleryMenu' }, content: { - embed: 'embedContent' + 'embed': 'embedContent', + 'edit-selection': 'editSelectionContent' }, sidebar: { @@ -1086,19 +1077,6 @@ }, this ); }, this ); - _.each(['library', 'upload'], function( id ) { - this.get( id ).on( 'refresh:selection', function( state, selection ) { - var sidebar = this.sidebar; - - if ( ! selection.length ) - sidebar.mode('clear'); - else if ( selection.length === 1 ) - sidebar.mode('attachment-settings'); - else - sidebar.mode('settings'); - }, this ); - }, this ); - this.sidebar.on( 'gallery-settings', this.onSidebarGallerySettings, this ); }, @@ -1204,6 +1182,35 @@ view.url.focus(); }, + editSelectionContent: function() { + var state = this.state(), + selection = state.get('selection'), + view; + + view = new media.view.AttachmentsBrowser({ + controller: this, + collection: selection, + selection: selection, + model: state, + sortable: true, + search: false, + + AttachmentView: media.view.Attachment.EditSelection + }).render(); + + view.toolbar.set( 'backToLibrary', { + text: l10n.returnToLibrary, + priority: -100, + + click: function() { + this.controller.content.mode('browse'); + } + }); + + // Browse our library of attachments. + this.content.view( view ); + }, + // Sidebars onSidebarGallerySettings: function( options ) { var library = this.state().get('library'); @@ -1761,7 +1768,11 @@ selection: new media.view.Selection({ controller: controller, collection: selection, - priority: -40 + priority: -40, + + editable: function() { + this.controller.content.mode('edit-selection'); + } }).render(), insert: { @@ -1771,8 +1782,7 @@ click: function() { controller.close(); - controller.state().trigger( 'insert', selection ); - selection.clear(); + controller.state().trigger( 'insert', selection ).reset(); } }, @@ -1782,12 +1792,6 @@ click: selectionToLibrary('gallery-edit', function( selection ) { return selection.where({ type: 'image' }); }) - }, - - batch: { - text: l10n.batchInsert, - priority: 60, - click: selectionToLibrary('batch-edit') } }); @@ -1800,16 +1804,10 @@ this.get('insert').model.set( 'disabled', ! selection.length ); - // Check if every attachment in the selection is an image. + // Check if any attachment in the selection is an image. this.get('gallery').$el.toggle( count > 1 && selection.any( function( attachment ) { return 'image' === attachment.get('type'); }) ); - - // Batch insert shows for multiple selected attachments. - this.get('batch').$el.toggle( count > 1 ); - - // Insert only shows for single attachments. - this.get('insert').$el.toggle( count <= 1 ); } }); @@ -2075,7 +2073,8 @@ 'change [data-setting]': 'updateSetting', 'change [data-setting] input': 'updateSetting', 'change [data-setting] select': 'updateSetting', - 'change [data-setting] textarea': 'updateSetting' + 'change [data-setting] textarea': 'updateSetting', + 'click .close': 'removeFromLibrary' }, buttons: {}, @@ -2147,17 +2146,30 @@ }, toggleSelection: function( event ) { - this.controller.state().toggleSelection( this.model ); + var selection = this.options.selection, + model = this.model; + + if ( ! selection ) + return; + + if ( selection.has( model ) ) { + // If the model is the single model, remove it. + // If it is not the same as the single model, + // it now becomes the single model. + selection[ selection.single() === model ? 'remove' : 'single' ]( model ); + } else { + selection.add( model ).single(); + } }, selected: function() { - var selection = this.controller.state().get('selection'); + var selection = this.options.selection; if ( selection ) return selection.has( this.model ); }, select: function( model, collection ) { - var selection = this.controller.state().get('selection'); + var selection = this.options.selection; // Check if a selection exists and if it's the collection provided. // If they're not the same collection, bail; we're in another @@ -2169,7 +2181,7 @@ }, deselect: function( model, collection ) { - var selection = this.controller.state().get('selection'); + var selection = this.options.selection; // Check if a selection exists and if it's the collection provided. // If they're not the same collection, bail; we're in another @@ -2181,7 +2193,7 @@ }, details: function( model, collection ) { - var selection = this.controller.state().get('selection'), + var selection = this.options.selection, details; if ( selection !== collection ) @@ -2220,6 +2232,13 @@ return; this.model.save( $setting.data('setting'), event.target.value ); + }, + + removeFromLibrary: function( event ) { + // Stop propagation so the model isn't selected. + event.stopPropagation(); + + this.collection.remove( this.model ); } }); @@ -2231,24 +2250,11 @@ }); /** - * wp.media.view.Attachment.Gallery + * wp.media.view.Attachment.EditLibrary */ - media.view.Attachment.Gallery = media.view.Attachment.extend({ + media.view.Attachment.EditLibrary = media.view.Attachment.extend({ buttons: { close: true - }, - - events: (function() { - var events = _.clone( media.view.Attachment.prototype.events ); - events['click .close'] = 'removeFromGallery'; - return events; - }()), - - removeFromGallery: function( event ) { - // Stop propagation so the model isn't selected. - event.stopPropagation(); - - this.controller.state().get('library').remove( this.model ); } }); @@ -2388,7 +2394,9 @@ this.$el.html( this.collection.map( function( attachment ) { return new this.options.AttachmentView({ controller: this.controller, - model: attachment + model: attachment, + collection: this.collection, + selection: this.options.selection }).render().$el; }, this ) ); @@ -2404,7 +2412,9 @@ view = new this.options.AttachmentView({ controller: this.controller, - model: attachment + model: attachment, + collection: this.collection, + selection: this.options.selection }).render(); children = this.$el.children(); @@ -2521,6 +2531,7 @@ this.attachments = new media.view.Attachments({ controller: this.controller, collection: this.collection, + selection: this.options.selection, model: this.model, sortable: this.options.sortable, @@ -2603,11 +2614,13 @@ template: media.template('media-selection'), events: { + 'click .edit-selection': 'edit', 'click .clear-selection': 'clear' }, initialize: function() { _.defaults( this.options, { + editable: false, clearable: true }); @@ -2615,6 +2628,7 @@ this.attachments = new media.view.Attachments({ controller: this.controller, collection: this.collection, + selection: this.collection, sortable: true, model: new Backbone.Model({ edge: 40, @@ -2655,6 +2669,12 @@ this.$('.count').text( this.collection.length + ' ' + l10n.selected ); }, + edit: function( event ) { + event.preventDefault(); + if ( this.options.editable ) + this.options.editable.call( this, this.collection ); + }, + clear: function( event ) { event.preventDefault(); this.collection.clear(); @@ -2666,10 +2686,18 @@ * wp.media.view.Attachment.Selection */ media.view.Attachment.Selection = media.view.Attachment.extend({ + className: 'attachment selection', + // On click, just select the model, instead of removing the model from // the selection. toggleSelection: function() { - this.controller.state().get('selection').single( this.model ); + this.options.selection.single( this.model ); + } + }); + + media.view.Attachment.EditSelection = media.view.Attachment.Selection.extend({ + buttons: { + close: true } }); diff --git a/wp-includes/media.php b/wp-includes/media.php index d9551e341d..4eed29dec4 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -1355,6 +1355,7 @@ function wp_enqueue_media( $args = array() ) { 'mediaLibraryTitle' => __( 'Media Library' ), 'createNewGallery' => __( 'Create a new gallery' ), 'insertIntoPost' => __( 'Insert into post' ), + 'returnToLibrary' => __( '← Return to library' ), // Embed 'embedFromUrlTitle' => __( 'Embed From URL' ), @@ -1522,6 +1523,9 @@ function wp_print_media_templates( $attachment ) {