Media JS: Improve handling of single attachments in selections.

* Adds `wp.media.model.Selection.single()` to specify a single item used in a multi-item selection.
* Fixes a bug where the `details` class would not be removed when "Clear Selection" was clicked.

see #21390.


git-svn-id: http://core.svn.wordpress.org/trunk@22335 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Daryl Koopersmith 2012-10-30 23:15:16 +00:00
parent b502e1e0c2
commit 640edbdfbc
3 changed files with 54 additions and 33 deletions

View File

@ -244,7 +244,6 @@
text-shadow: 0 1px 0 rgba( 0, 0, 0, 0.5 );
background: #777;
border: 1px solid #fff;
/*border-width: 0 1px 1px 0;*/
border-width: 0 0 1px 1px;
box-shadow: -1px 1px 0 rgba( 0, 0, 0, 0.1 );
}

View File

@ -622,6 +622,11 @@ window.wp = window.wp || {};
initialize: function( models, options ) {
Attachments.prototype.initialize.apply( this, arguments );
this.multiple = options && options.multiple;
// Refresh the `single` model whenever the selection changes.
// Binds `single` instead of using the context argument to ensure
// it receives no parameters.
this.on( 'add remove reset', _.bind( this.single, this ) );
},
// Override the selection's add method.
@ -638,14 +643,16 @@ window.wp = window.wp || {};
// Removes all models from the selection.
clear: function( options ) {
return this.remove( this.models, options );
this.remove( this.models, options ).single();
return this;
},
// Override the selection's reset method.
// Always direct items through add and remove,
// as we need them to fire.
reset: function( models, options ) {
return this.clear( options ).add( models, options );
this.clear( options ).add( models, options ).single();
return this;
},
// Create selection.has, which determines if a model
@ -653,6 +660,31 @@ window.wp = window.wp || {};
// instead of direct comparison.
has: function( attachment ) {
return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
},
single: function( model ) {
var previous = this._single;
// If a `model` is provided, use it as the single model.
if ( model )
this._single = model;
// If the single model isn't in the selection, remove it.
if ( this._single && ! this.has( this._single ) )
delete this._single;
this._single = this._single || this.last();
// If single has changed, fire an event.
if ( this._single !== previous ) {
if ( this._single )
this._single.trigger( 'selection:single', this._single, this );
if ( previous )
previous.trigger( 'selection:unsingle', previous, this );
}
// Return the single model, or the last model as a fallback.
return this._single;
}
});

View File

@ -212,7 +212,7 @@
},
details: function( options ) {
var model = this.get('details'),
var model = this.get('selection').single(),
view;
if ( model ) {
@ -232,34 +232,18 @@
},
toggleSelection: function( model ) {
var details = this.get('details'),
selection = this.get('selection'),
selected = selection.has( model );
var selection = this.get('selection');
if ( ! selection )
return;
if ( ! selected )
selection.add( model );
// If the model is not the same as the details model,
// it now becomes the details model. If the model is
// in the selection, it is not removed.
if ( details !== model ) {
this.set( 'details', 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();
}
// The model is the details model.
// Removed it from the selection.
selection.remove( model );
// Show the last selected item, or clear the details view.
if ( selection.length )
this.set( 'details', selection.last() );
else
this.unset('details');
return this;
}
});
@ -1087,14 +1071,14 @@
this.select();
// Update the model's details view.
this.controller.state().on( 'change:details', this.details, this );
this.model.on( 'selection:single selection:unsingle', this.details, this );
this.details();
return this;
},
destroy: function() {
this.controller.state().off( 'change:details', this.details, this );
this.model.off( 'single', this.details, this );
},
progress: function() {
@ -1136,8 +1120,14 @@
this.$el.removeClass('selected');
},
details: function() {
var details = this.controller.state().get('details');
details: function( model, collection ) {
var selection = this.controller.state().get('selection'),
details;
if ( selection !== collection )
return;
details = selection.single();
this.$el.toggleClass( 'details', details === this.model );
},