Media: Disable 'Insert gallery' and 'Set featured image' if nothing is queued. Converts selection toolbars to use the newer view manager. props koopersmith, fixes #22714.

git-svn-id: http://core.svn.wordpress.org/trunk@23024 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2012-12-04 16:21:57 +00:00
parent 6ad495b625
commit d2a9957ad8
4 changed files with 165 additions and 216 deletions

View File

@ -25,39 +25,50 @@
event.preventDefault(); event.preventDefault();
// If the media frame already exists, reopen it.
if ( frame ) { if ( frame ) {
frame.open(); frame.open();
return; return;
} }
// Create the media frame.
frame = wp.media({ frame = wp.media({
title: $el.data('choose'), // Set the title of the modal.
library: { title: $el.data('choose'),
// Tell the modal to show only images.
library: {
type: 'image' type: 'image'
},
// Customize the submit button.
button: {
// Set the text of the button.
text: $el.data('update'),
// Tell the button not to close the modal, since we're
// going to refresh the page when the image is selected.
close: false
} }
}); });
frame.on( 'toolbar:render:select', function( view ) { // When an image is selected, run a callback.
view.set({ frame.on( 'select', function() {
select: { // Grab the selected attachment.
style: 'primary', var attachment = frame.state().get('selection').first();
text: $el.data('update'),
click: function() { // Run an AJAX request to set the background image.
var attachment = frame.state().get('selection').first(); $.post( ajaxurl, {
$.post( ajaxurl, { action: 'set-background-image',
action: 'set-background-image', attachment_id: attachment.id,
attachment_id: attachment.id, size: 'full'
size: 'full' }).done( function() {
}, function() { // When the request completes, reload the window.
window.location.reload(); window.location.reload();
});
}
}
}); });
}); });
frame.setState('library').open(); // Finally, open the modal.
frame.open();
}); });
}); });
})(jQuery); })(jQuery);

View File

@ -18,30 +18,37 @@
var $el = $(this); var $el = $(this);
event.preventDefault(); event.preventDefault();
// Create the media frame.
frame = wp.media({ frame = wp.media({
title: $el.data('choose'), // Set the title of the modal.
library: { title: $el.data('choose'),
// Tell the modal to show only images.
library: {
type: 'image' type: 'image'
},
// Customize the submit button.
button: {
// Set the text of the button.
text: $el.data('update'),
// Tell the button not to close the modal, since we're
// going to refresh the page when the image is selected.
close: false
} }
}); });
frame.on( 'toolbar:render:select', function( view ) { // When an image is selected, run a callback.
view.set({ frame.on( 'select', function() {
select: { // Grab the selected attachment.
style: 'primary', var attachment = frame.state().get('selection').first(),
text: $el.data('update'), link = $el.data('updateLink');
click: function() { // Tell the browser to navigate to the crop step.
var attachment = frame.state().get('selection').first(), window.location = link + '&file=' + attachment.id;
link = $el.data('updateLink');
window.location = link + '&file=' + attachment.id;
}
}
});
}); });
frame.setState('library').open(); frame.open();
}); });
}); });
}(jQuery)); }(jQuery));

View File

@ -1174,6 +1174,10 @@
background: red; background: red;
} }
.media-selection .selection-view {
display: inline-block;
}
.media-selection .attachments { .media-selection .attachments {
display: inline-block; display: inline-block;
height: 48px; height: 48px;

View File

@ -389,10 +389,6 @@
}, },
activate: function() { activate: function() {
var library = this.get('library'),
selection = this.get('selection'),
mode;
if ( this.get('syncLastSelection') ) { if ( this.get('syncLastSelection') ) {
this.getLastSelection(); this.getLastSelection();
} }
@ -404,7 +400,7 @@
wp.Uploader.queue.on( 'add', this.uploading, this ); wp.Uploader.queue.on( 'add', this.uploading, this );
selection.on( 'add remove reset', this.refreshSelection, this ); this.get('selection').on( 'add remove reset', this.refreshContent, this );
this.on( 'insert', this._insertDisplaySettings, this ); this.on( 'insert', this._insertDisplaySettings, this );
@ -490,12 +486,6 @@
selection.reset( lastSelection.toArray() ).single( lastSelection.single() ); selection.reset( lastSelection.toArray() ).single( lastSelection.single() );
}, },
refreshSelection: function() {
this.frame.toolbar.get().refresh();
this.trigger( 'refresh:selection', this, this.get('selection') );
this.refreshContent();
},
refreshContent: function() { refreshContent: function() {
var selection = this.get('selection'), var selection = this.get('selection'),
frame = this.frame, frame = this.frame,
@ -1317,7 +1307,7 @@
}, },
createToolbar: function( toolbar ) { createToolbar: function( toolbar ) {
menu.view = new media.view.Toolbar({ toolbar.view = new media.view.Toolbar({
controller: this controller: this
}); });
}, },
@ -1425,7 +1415,8 @@
_.defaults( this.options, { _.defaults( this.options, {
selection: [], selection: [],
library: {}, library: {},
multiple: false multiple: false,
state: 'library'
}); });
this.createSelection(); this.createSelection();
@ -1468,8 +1459,6 @@
this.on( 'content:create:browse', this.browseContent, this ); this.on( 'content:create:browse', this.browseContent, this );
this.on( 'content:render:upload', this.uploadContent, this ); this.on( 'content:render:upload', this.uploadContent, this );
this.on( 'toolbar:create:select', this.createSelectToolbar, this ); this.on( 'toolbar:create:select', this.createSelectToolbar, this );
this.on( 'refresh:selection', this.refreshSelectToolbar, this );
}, },
// Routers // Routers
@ -1517,43 +1506,10 @@
// Toolbars // Toolbars
createSelectToolbar: function( toolbar, options ) { createSelectToolbar: function( toolbar, options ) {
options = _.defaults( options || {}, { options = options || this.options.button || {};
event: 'select', options.controller = this;
silent: false,
state: false
});
toolbar.view = new media.view.Toolbar({ toolbar.view = new media.view.Toolbar.Select( options );
controller: this,
silent: options.silent,
items: {
select: {
style: 'primary',
text: l10n.select,
priority: 80,
click: function() {
var controller = this.controller;
controller.close();
controller.state().trigger( options.event );
controller.reset();
if ( options.state )
controller.setState( options.state );
}
}
}
});
},
refreshSelectToolbar: function() {
var selection = this.state().get('selection');
if ( ! selection || 'select' !== this.toolbar.mode() )
return;
this.toolbar.get().get('select').model.set( 'disabled', ! selection.length );
} }
}); });
@ -1564,7 +1520,8 @@
initialize: function() { initialize: function() {
_.defaults( this.options, { _.defaults( this.options, {
multiple: true, multiple: true,
editing: false editing: false,
state: 'insert'
}); });
media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments ); media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments );
@ -1651,8 +1608,10 @@
bindHandlers: function() { bindHandlers: function() {
media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
this.on( 'menu:create:gallery', this.createMenu, this ); this.on( 'menu:create:gallery', this.createMenu, this );
this.on( 'toolbar:create:main-insert', this.createSelectionToolbar, this ); this.on( 'toolbar:create:main-insert', this.createToolbar, this );
this.on( 'toolbar:create:main-gallery', this.createSelectionToolbar, this ); this.on( 'toolbar:create:main-gallery', this.createToolbar, this );
this.on( 'toolbar:create:featured-image', this.featuredImageToolbar, this );
this.on( 'toolbar:create:main-embed', this.mainEmbedToolbar, this );
var handlers = { var handlers = {
menu: { menu: {
@ -1668,8 +1627,6 @@
toolbar: { toolbar: {
'main-insert': 'mainInsertToolbar', 'main-insert': 'mainInsertToolbar',
'main-gallery': 'mainGalleryToolbar', 'main-gallery': 'mainGalleryToolbar',
'main-embed': 'mainEmbedToolbar',
'featured-image': 'featuredImageToolbar',
'gallery-edit': 'galleryEditToolbar', 'gallery-edit': 'galleryEditToolbar',
'gallery-add': 'galleryAddToolbar' 'gallery-add': 'galleryAddToolbar'
} }
@ -1757,21 +1714,32 @@
}, },
// Toolbars // Toolbars
createSelectionToolbar: function( toolbar ) { selectionStatusToolbar: function( view ) {
toolbar.view = new media.view.Toolbar.Selection({ var editable = this.state().get('editable');
view.set( 'selection', new media.view.Selection({
controller: this, controller: this,
editable: this.state().get('editable') collection: this.state().get('selection'),
}); priority: -40,
// If the selection is editable, pass the callback to
// switch the content mode.
editable: editable && function() {
this.controller.content.mode('edit-selection');
}
}).render() );
}, },
mainInsertToolbar: function( view ) { mainInsertToolbar: function( view ) {
var controller = this; var controller = this;
view.button = 'insert'; this.selectionStatusToolbar( view );
view.set( 'insert', { view.set( 'insert', {
style: 'primary', style: 'primary',
priority: 80, priority: 80,
text: l10n.insertIntoPost, text: l10n.insertIntoPost,
requires: { selection: true },
click: function() { click: function() {
var state = controller.state(), var state = controller.state(),
@ -1786,11 +1754,13 @@
mainGalleryToolbar: function( view ) { mainGalleryToolbar: function( view ) {
var controller = this; var controller = this;
view.button = 'gallery'; this.selectionStatusToolbar( view );
view.set( 'gallery', { view.set( 'gallery', {
style: 'primary', style: 'primary',
text: l10n.createNewGallery, text: l10n.createNewGallery,
priority: 60, priority: 60,
requires: { selection: true },
click: function() { click: function() {
var selection = controller.state().get('selection'), var selection = controller.state().get('selection'),
@ -1807,20 +1777,17 @@
}); });
}, },
featuredImageToolbar: function() { featuredImageToolbar: function( toolbar ) {
this.toolbar.set( new media.view.Toolbar.Select({ this.createSelectToolbar( toolbar, {
controller: this, text: l10n.setFeaturedImage,
text: l10n.setFeaturedImage, state: this.options.state || 'upload'
state: this.options.state || 'upload' });
}) );
}, },
mainEmbedToolbar: function() { mainEmbedToolbar: function( toolbar ) {
this.toolbar.set( new media.view.Toolbar.Embed({ toolbar.view = new media.view.Toolbar.Embed({
controller: this controller: this
}) ); });
this.$el.removeClass('hide-toolbar');
}, },
galleryEditToolbar: function() { galleryEditToolbar: function() {
@ -1832,6 +1799,7 @@
style: 'primary', style: 'primary',
text: editing ? l10n.updateGallery : l10n.insertGallery, text: editing ? l10n.updateGallery : l10n.insertGallery,
priority: 80, priority: 80,
requires: { library: true },
click: function() { click: function() {
var controller = this.controller, var controller = this.controller,
@ -2220,53 +2188,42 @@
className: 'media-toolbar', className: 'media-toolbar',
initialize: function() { initialize: function() {
this._views = {}; var state = this.controller.state(),
this.$primary = $('<div class="media-toolbar-primary" />').prependTo( this.$el ); selection = this.selection = state.get('selection'),
this.$secondary = $('<div class="media-toolbar-secondary" />').prependTo( this.$el ); library = this.library = state.get('library');
this._views = {};
// The toolbar is composed of two `PriorityList` views.
this.primary = new media.view.PriorityList();
this.secondary = new media.view.PriorityList();
this.primary.$el.addClass('media-toolbar-primary');
this.secondary.$el.addClass('media-toolbar-secondary');
this.views.set([ this.secondary, this.primary ]);
if ( this.options.items ) if ( this.options.items )
this.set( this.options.items, { silent: true }); this.set( this.options.items, { silent: true });
if ( ! this.options.silent ) if ( ! this.options.silent )
this.render(); this.render();
selection.on( 'add remove reset', this.refresh, this );
library.on( 'add remove reset', this.refresh, this );
}, },
destroy: function() { dispose: function() {
this.remove(); this.selection.off( null, null, this );
this.library.off( null, null, this );
if ( this.model ) return media.View.prototype.dispose.apply( this, arguments );
this.model.off( null, null, this );
if ( this.collection )
this.collection.off( null, null, this );
this.controller.off( null, null, this );
_.each( this._views, function( view ) {
if ( view.destroy )
view.destroy();
});
}, },
render: function() { ready: function() {
var views = _.chain( this._views ).sortBy( function( view ) {
return view.options.priority || 10;
}).groupBy( function( view ) {
return ( view.options.priority || 10 ) > 0 ? 'primary' : 'secondary';
}).value();
// Make sure to detach the elements we want to reuse.
// Otherwise, `jQuery.html()` will unbind their events.
$( _.pluck( this._views, 'el' ) ).detach();
this.$primary.html( _.pluck( views.primary || [], 'el' ) );
this.$secondary.html( _.pluck( views.secondary || [], 'el' ) );
this.refresh(); this.refresh();
return this;
}, },
set: function( id, view, options ) { set: function( id, view, options ) {
var list;
options = options || {}; options = options || {};
// Accept an object with an `id` : `view` mapping. // Accept an object with an `id` : `view` mapping.
@ -2284,10 +2241,14 @@
view.controller = view.controller || this.controller; view.controller = view.controller || this.controller;
this._views[ id ] = view; this._views[ id ] = view;
list = view.options.priority < 0 ? 'secondary' : 'primary';
this[ list ].set( id, view, options );
} }
if ( ! options.silent ) if ( ! options.silent )
this.render(); this.refresh();
return this; return this;
}, },
@ -2297,12 +2258,34 @@
unset: function( id, options ) { unset: function( id, options ) {
delete this._views[ id ]; delete this._views[ id ];
this.primary.unset( id, options );
this.secondary.unset( id, options );
if ( ! options || ! options.silent ) if ( ! options || ! options.silent )
this.render(); this.refresh();
return this; return this;
}, },
refresh: function() {} refresh: function() {
var state = this.controller.state(),
library = state.get('library'),
selection = state.get('selection');
_.each( this._views, function( button ) {
if ( ! button.model || ! button.options || ! button.options.requires )
return;
var requires = button.options.requires,
disabled = false;
if ( requires.selection && ! selection.length )
disabled = true;
else if ( requires.library && ! library.length )
disabled = true;
button.model.set( 'disabled', disabled );
});
}
}); });
// wp.media.view.Toolbar.Select // wp.media.view.Toolbar.Select
@ -2320,7 +2303,12 @@
state: false, state: false,
reset: true, reset: true,
close: true, close: true,
text: l10n.select text: l10n.select,
// Does the button rely on the selection?
requires: {
selection: true
}
}); });
options.items = _.defaults( options.items || {}, { options.items = _.defaults( options.items || {}, {
@ -2328,7 +2316,8 @@
style: 'primary', style: 'primary',
text: options.text, text: options.text,
priority: 80, priority: 80,
click: this.clickSelect click: this.clickSelect,
requires: options.requires
} }
}); });
@ -2365,45 +2354,16 @@
this.controller.state().props.on( 'change:url', this.refresh, this ); this.controller.state().props.on( 'change:url', this.refresh, this );
}, },
refresh: function() { dispose: function() {
var url = this.controller.state().props.get('url'); this.controller.state().props.off( 'change:url', this.refresh, this );
this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) ); media.view.Toolbar.Select.prototype.dispose.apply( this, arguments );
}
});
// wp.media.view.Toolbar.Selection
// -------------------------------
media.view.Toolbar.Selection = media.view.Toolbar.extend({
button: 'insert',
initialize: function() {
var controller = this.controller;
this.options.items = _.defaults( this.options.items || {}, {
selection: new media.view.Selection({
controller: controller,
collection: controller.state().get('selection'),
priority: -40,
// If the selection is editable, pass the callback to
// switch the content mode.
editable: this.options.editable && function() {
this.controller.content.mode('edit-selection');
}
}).render()
});
media.view.Toolbar.prototype.initialize.apply( this, arguments );
}, },
refresh: function() { refresh: function() {
var selection = this.controller.state().get('selection'), var url = this.controller.state().props.get('url');
button = this.get( this.button ); this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) );
if ( ! button ) media.view.Toolbar.Select.prototype.refresh.apply( this, arguments );
return;
button.model.set( 'disabled', ! selection.length );
} }
}); });
@ -2516,8 +2476,6 @@
this.render(); this.render();
}, },
destroy: this.dispose,
set: function( id, view, options ) { set: function( id, view, options ) {
var priority, views, index; var priority, views, index;
@ -3649,24 +3607,12 @@
AttachmentView: media.view.Attachment.Selection AttachmentView: media.view.Attachment.Selection
}); });
this.views.set( '.selection-view', this.attachments );
this.collection.on( 'add remove reset', this.refresh, this ); this.collection.on( 'add remove reset', this.refresh, this );
}, },
destroy: function() { ready: function() {
this.remove();
this.collection.off( 'add remove reset', this.refresh, this );
this.attachments.destroy();
},
render: function() {
this.attachments.$el.detach();
this.attachments.render();
this.$el.html( this.template( this.options ) );
this.$('.selection-view').replaceWith( this.attachments.$el );
this.refresh(); this.refresh();
return this;
}, },
refresh: function() { refresh: function() {
@ -3728,10 +3674,6 @@
this.model.on( 'change', this.updateChanges, this ); this.model.on( 'change', this.updateChanges, this );
}, },
destroy: function() {
this.model.off( null, null, this );
},
render: function() { render: function() {
this.$el.html( this.template( _.defaults({ this.$el.html( this.template( _.defaults({
model: this.model.toJSON() model: this.model.toJSON()
@ -3934,10 +3876,6 @@
this.model.on( 'change:compat', this.render, this ); this.model.on( 'change:compat', this.render, this );
}, },
destroy: function() {
this.model.off( null, null, this );
},
render: function() { render: function() {
var compat = this.model.get('compat'); var compat = this.model.get('compat');
if ( ! compat || ! compat.item ) if ( ! compat || ! compat.item )
@ -4005,8 +3943,6 @@
settings: function( view ) { settings: function( view ) {
view.render(); view.render();
this._settings.$el.replaceWith( view.$el ); this._settings.$el.replaceWith( view.$el );
if ( this._settings.destroy )
this._settings.destroy();
this._settings.remove(); this._settings.remove();
this._settings = view; this._settings = view;
}, },
@ -4055,10 +3991,6 @@
this.model.on( 'change:url', this.render, this ); this.model.on( 'change:url', this.render, this );
}, },
destroy: function() {
this.model.off( null, null, this );
},
render: function() { render: function() {
var $input = this.$input; var $input = this.$input;
@ -4101,11 +4033,6 @@
this.model.on( 'change:url', this.updateImage, this ); this.model.on( 'change:url', this.updateImage, this );
}, },
destroy: function() {
this.model.off( null, null, this );
media.view.Settings.AttachmentDisplay.prototype.destroy.apply( this, arguments );
},
updateImage: function() { updateImage: function() {
this.$('img').attr( 'src', this.model.get('url') ); this.$('img').attr( 'src', this.model.get('url') );
} }