return deferred.promise();
};
- /**
- * ========================================================================
- * CONTROLLERS
- * ========================================================================
- */
-
/**
* wp.media.controller.Region
*
- * @constructor
- * @augments Backbone.Model
+ * A region is a persistent application layout area.
+ *
+ * A region assumes one mode at any time, and can be switched to another.
+ *
+ * When mode changes, events are triggered on the region's parent view.
+ * The parent view will listen to specific events and fill the region with an
+ * appropriate view depending on mode. For example, a frame listens for the
+ * 'browse' mode t be activated on the 'content' view and then fills the region
+ * with an AttachmentsBrowser view.
*
- * @param {Object} [options={}]
+ * @class
+ *
+ * @param {object} options Options hash for the region.
+ * @param {string} options.id Unique identifier for the region.
+ * @param {Backbone.View} options.view A parent view the region exists within.
+ * @param {string} options.selector jQuery selector for the region within the parent view.
*/
media.controller.Region = function( options ) {
_.extend( this, _.pick( options || {}, 'id', 'view', 'selector' ) );
/**
* Activate a mode.
*
+ * @since 3.5.0
+ *
* @param {string} mode
*
* @fires this.view#{this.id}:activate:{this._mode}
/**
* Render a mode.
*
+ * @since 3.5.0
+ *
* @param {string} mode
*
* @fires this.view#{this.id}:create:{this._mode}
/**
* Get the region's view.
*
+ * @since 3.5.0
+ *
* @returns {wp.media.View}
*/
get: function() {
/**
* Set the region's view as a subview of the frame.
*
+ * @since 3.5.0
+ *
* @param {Array|Object} views
* @param {Object} [options={}]
* @returns {wp.Backbone.Subviews} Subviews is returned to allow chaining
/**
* Trigger regional view events on the frame.
*
+ * @since 3.5.0
+ *
* @param {string} event
* @returns {undefined|wp.media.controller.Region} Returns itself to allow chaining.
*/
/**
* wp.media.controller.StateMachine
*
- * @constructor
+ * A state machine keeps track of state. It is in one state at a time,
+ * and can change from one state to another.
+ *
+ * States are stored as models in a Backbone collection.
+ *
+ * @since 3.5.0
+ *
+ * @class
* @augments Backbone.Model
* @mixin
* @mixes Backbone.Events
* @param {Array} states
*/
media.controller.StateMachine = function( states ) {
+ // @todo This is dead code. The states collection gets created in media.view.Frame._createStates.
this.states = new Backbone.Collection( states );
};
* Ensure that the `states` collection exists so the `StateMachine`
* can be used as a mixin.
*
+ * @since 3.5.0
+ *
* @param {string} id
* @returns {wp.media.controller.State} Returns a State model
* from the StateMachine collection
* created the `states` collection, or are trying to select a state
* that does not exist.
*
+ * @since 3.5.0
+ *
* @param {string} id
*
* @fires wp.media.controller.State#deactivate
* Call the `state()` method with no parameters to retrieve the current
* active state.
*
+ * @since 3.5.0
+ *
* @returns {wp.media.controller.State} Returns a State model
* from the StateMachine collection
*/
* wp.media.controller.State
*
* A state is a step in a workflow that when set will trigger the controllers
- * for the regions to be updated as specified in the frame. This is the base
- * class that the various states used in wp.media extend.
+ * for the regions to be updated as specified in the frame.
+ *
+ * A state has an event-driven lifecycle:
*
- * @constructor
+ * 'ready' triggers when a state is added to a state machine's collection.
+ * 'activate' triggers when a state is activated by a state machine.
+ * 'deactivate' triggers when a state is deactivated by a state machine.
+ * 'reset' is not triggered automatically. It should be invoked by the
+ * proper controller to reset the state to its default.
+ *
+ * @class
* @augments Backbone.Model
*/
media.controller.State = Backbone.Model.extend({
+ /**
+ * Constructor.
+ *
+ * @since 3.5.0
+ */
constructor: function() {
this.on( 'activate', this._preActivate, this );
this.on( 'activate', this.activate, this );
this.on( 'change:menu', this._updateMenu, this );
},
/**
+ * Ready event callback.
+ *
* @abstract
+ * @since 3.5.0
*/
ready: function() {},
+
/**
+ * Activate event callback.
+ *
* @abstract
+ * @since 3.5.0
*/
activate: function() {},
+
/**
+ * Deactivate event callback.
+ *
* @abstract
+ * @since 3.5.0
*/
deactivate: function() {},
+
/**
+ * Reset event callback.
+ *
* @abstract
+ * @since 3.5.0
*/
reset: function() {},
+
/**
* @access private
+ * @since 3.5.0
*/
_ready: function() {
this._updateMenu();
},
+
/**
* @access private
+ * @since 3.5.0
*/
_preActivate: function() {
this.active = true;
},
+
/**
* @access private
+ * @since 3.5.0
*/
_postActivate: function() {
this.on( 'change:menu', this._menu, this );
this._content();
this._router();
},
+
/**
* @access private
+ * @since 3.5.0
*/
_deactivate: function() {
this.active = false;
this.off( 'change:content', this._content, this );
this.off( 'change:toolbar', this._toolbar, this );
},
+
/**
* @access private
+ * @since 3.5.0
*/
_title: function() {
this.frame.title.render( this.get('titleMode') || 'default' );
},
+
/**
* @access private
+ * @since 3.5.0
*/
_renderTitle: function( view ) {
view.$el.text( this.get('title') || '' );
},
+
/**
* @access private
+ * @since 3.5.0
*/
_router: function() {
var router = this.frame.router,
view.select( this.frame.content.mode() );
}
},
+
/**
* @access private
+ * @since 3.5.0
*/
_menu: function() {
var menu = this.frame.menu,
view.select( this.id );
}
},
+
/**
* @access private
+ * @since 3.5.0
*/
_updateMenu: function() {
var previous = this.previous('menu'),
this.frame.on( 'menu:render:' + menu, this._renderMenu, this );
}
},
+
/**
+ * Create a view in the media menu for the state.
+ *
* @access private
+ * @since 3.5.0
+ *
+ * @param {media.view.Menu} view The menu view.
*/
_renderMenu: function( view ) {
var menuItem = this.get('menuItem'),
};
});
+ /**
+ * wp.media.selectionSync
+ *
+ * Sync an attachments selection in a state with another state.
+ *
+ * Allows for selecting multiple images in the Insert Media workflow, and then
+ * switching to the Insert Gallery workflow while preserving the attachments selection.
+ *
+ * @mixin
+ */
media.selectionSync = {
+ /**
+ * @since 3.5.0
+ */
syncSelection: function() {
var selection = this.get('selection'),
manager = this.frame._selection;
* of the selection's attachments and the set of selected
* attachments that this specific selection considered invalid.
* Reset the difference and record the single attachment.
+ *
+ * @since 3.5.0
*/
recordSelection: function() {
var selection = this.get('selection'),
};
/**
- * A state for choosing an attachment from the media library.
+ * wp.media.controller.Library
*
- * @constructor
+ * A state for choosing an attachment or group of attachments from the media library.
+ *
+ * @class
* @augments wp.media.controller.State
* @augments Backbone.Model
+ * @mixes media.selectionSync
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=library] Unique identifier.
+ * @param {string} [attributes.title=Media library] Title for the state. Displays in the media menu and the frame's title region.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
+ * If one is not supplied, a collection of all attachments will be created.
+ * @param {wp.media.model.Selection|object} [attributes.selection] A collection to contain attachment selections within the state.
+ * If the 'selection' attribute is a plain JS object,
+ * a Selection will be created using its values as the selection instance's `props` model.
+ * Otherwise, it will copy the library's `props` model.
+ * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
+ * @param {string} [attributes.content=upload] Initial mode for the content region.
+ * Overridden by persistent user setting if 'contentUserSetting' is true.
+ * @param {string} [attributes.menu=default] Initial mode for the menu region.
+ * @param {string} [attributes.router=browse] Initial mode for the router region.
+ * @param {string} [attributes.toolbar=select] Initial mode for the toolbar region.
+ * @param {boolean} [attributes.searchable=true] Whether the library is searchable.
+ * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown.
+ * Accepts 'all', 'uploaded', or 'unattached'.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
+ * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
+ * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
+ * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.
*/
media.controller.Library = media.controller.State.extend({
defaults: {
id: 'library',
title: l10n.mediaLibraryTitle,
- // Selection defaults. @see media.model.Selection
multiple: false,
- // Initial region modes.
content: 'upload',
menu: 'default',
router: 'browse',
toolbar: 'select',
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
searchable: true,
filterable: false,
sortable: true,
-
autoSelect: true,
describe: false,
- // Uses a user setting to override the content mode.
contentUserSetting: true,
- // Sync the selection from the last state when 'multiple' matches.
syncSelection: true
},
/**
* If a library isn't provided, query all media items.
* If a selection instance isn't provided, create one.
+ *
+ * @since 3.5.0
*/
initialize: function() {
var selection = this.get('selection'),
props = _.omit( props, 'orderby', 'query' );
}
- // If the `selection` attribute is set to an object,
- // it will use those values as the selection instance's
- // `props` model. Otherwise, it will copy the library's
- // `props` model.
this.set( 'selection', new media.model.Selection( null, {
multiple: this.get('multiple'),
props: props
this.resetDisplays();
},
+ /**
+ * @since 3.5.0
+ */
activate: function() {
this.syncSelection();
}
},
+ /**
+ * @since 3.5.0
+ */
deactivate: function() {
this.recordSelection();
wp.Uploader.queue.off( null, null, this );
},
+ /**
+ * Reset the library to its initial state.
+ *
+ * @since 3.5.0
+ */
reset: function() {
this.get('selection').reset();
this.resetDisplays();
this.refreshContent();
},
+ /**
+ * Reset the attachment display settings defaults to the site options.
+ *
+ * If site options don't define them, fall back to a persistent user setting.
+ *
+ * @since 3.5.0
+ */
resetDisplays: function() {
var defaultProps = media.view.settings.defaultProps;
this._displays = [];
},
/**
+ * Create a model to represent display settings (alignment, etc.) for an attachment.
+ *
+ * @since 3.5.0
+ *
* @param {wp.media.model.Attachment} attachment
* @returns {Backbone.Model}
*/
},
/**
+ * Given an attachment, create attachment display settings properties.
+ *
+ * @since 3.6.0
+ *
* @param {wp.media.model.Attachment} attachment
* @returns {Object}
*/
},
/**
+ * Whether an attachment can be embedded (audio or video).
+ *
+ * @since 3.6.0
+ *
* @param {wp.media.model.Attachment} attachment
* @returns {Boolean}
*/
* If the state is active, no items are selected, and the current
* content mode is not an option in the state's router (provided
* the state has a router), reset the content mode to the default.
+ *
+ * @since 3.5.0
*/
refreshContent: function() {
var selection = this.get('selection'),
},
/**
- * If the uploader was selected, navigate to the browser.
+ * Callback handler when an attachment is uploaded.
+ *
+ * Switch to the Media Library if uploaded from the 'Upload Files' tab.
+ *
+ * Adds any uploading attachments to the selection.
*
- * Automatically select any uploading attachments.
+ * If the state only supports one attachment to be selected and multiple
+ * attachments are uploaded, the last attachment in the upload queue will
+ * be selected.
*
- * Selections that don't support multiple attachments automatically
- * limit themselves to one attachment (in this case, the last
- * attachment in the upload queue).
+ * @since 3.5.0
*
* @param {wp.media.model.Attachment} attachment
*/
},
/**
- * Only track the browse router on library states.
+ * Persist the mode of the content region as a user setting.
+ *
+ * @since 3.5.0
*/
saveContentMode: function() {
if ( 'browse' !== this.get('router') ) {
}
});
+ // Make selectionSync available on any Media Library state.
_.extend( media.controller.Library.prototype, media.selectionSync );
/**
- * A state for editing the settings of an image within a content editor.
+ * wp.media.controller.ImageDetails
+ *
+ * A state for editing the attachment display settings of an image that's been
+ * inserted into the editor.
*
- * @constructor
+ * @class
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=image-details] Unique identifier.
+ * @param {string} [attributes.title=Image Details] Title for the state. Displays in the frame's title region.
+ * @param {wp.media.model.Attachment} attributes.image The image's model.
+ * @param {string|false} [attributes.content=image-details] Initial mode for the content region.
+ * @param {string|false} [attributes.menu=false] Initial mode for the menu region.
+ * @param {string|false} [attributes.router=false] Initial mode for the router region.
+ * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region.
+ * @param {boolean} [attributes.editing=false] Unused.
+ * @param {int} [attributes.priority=60] Unused.
+ *
+ * @todo This state inherits some defaults from media.controller.Library.prototype.defaults,
+ * however this may not do anything.
*/
media.controller.ImageDetails = media.controller.State.extend({
defaults: _.defaults({
id: 'image-details',
title: l10n.imageDetailsTitle,
- // Initial region modes.
content: 'image-details',
menu: false,
router: false,
toolbar: 'image-details',
-
editing: false,
priority: 60
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.9.0
+ *
+ * @param options Attributes
+ */
initialize: function( options ) {
this.image = options.image;
media.controller.State.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
this.frame.modal.$el.addClass('image-details');
}
});
/**
+ * wp.media.controller.GalleryEdit
+ *
* A state for editing a gallery's images and settings.
*
- * @constructor
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=gallery-edit] Unique identifier.
+ * @param {string} [attributes.title=Edit Gallery] Title for the state. Displays in the frame's title region.
+ * @param {wp.media.model.Attachments} [attributes.library] The collection of attachments in the gallery.
+ * If one is not supplied, an empty media.model.Selection collection is created.
+ * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
+ * @param {boolean} [attributes.searchable=false] Whether the library is searchable.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {string|false} [attributes.content=browse] Initial mode for the content region.
+ * @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region.
+ * @param {boolean} [attributes.describe=true] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
+ * @param {boolean} [attributes.displaySettings=true] Whether to show the attachment display settings interface.
+ * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable.
+ * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.
+ * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance.
+ * @param {int} [attributes.priority=60] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
+ * Defaults to false for this state, because the library passed in *is* the selection.
+ * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`.
+ * If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
*/
media.controller.GalleryEdit = media.controller.Library.extend({
defaults: {
- id: 'gallery-edit',
- title: l10n.editGalleryTitle,
- // Selection defaults. @see media.model.Selection
- multiple: false,
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
- searchable: false,
- sortable: true,
- display: false,
- // Initial region modes.
- content: 'browse',
- toolbar: 'gallery-edit',
-
+ id: 'gallery-edit',
+ title: l10n.editGalleryTitle,
+ multiple: false,
+ searchable: false,
+ sortable: true,
+ display: false,
+ content: 'browse',
+ toolbar: 'gallery-edit',
describe: true,
displaySettings: true,
dragInfo: true,
idealColumnWidth: 170,
editing: false,
priority: 60,
-
- // Don't sync the selection, as the Edit Gallery library
- // *is* the selection.
- syncSelection: false
+ syncSelection: false
},
+ /**
+ * @since 3.5.0
+ */
initialize: function() {
// If we haven't been provided a `library`, create a `Selection`.
if ( ! this.get('library') )
media.controller.Library.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ */
activate: function() {
var library = this.get('library');
media.controller.Library.prototype.activate.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ */
deactivate: function() {
// Stop watching for uploaded attachments.
this.get('library').unobserve( wp.Uploader.queue );
media.controller.Library.prototype.deactivate.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ *
+ * @param browser
+ */
gallerySettings: function( browser ) {
if ( ! this.get('displaySettings') ) {
return;
});
/**
- * A state for adding an image to a gallery.
+ * A state for selecting more images to add to a gallery.
*
- * @constructor
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=gallery-library] Unique identifier.
+ * @param {string} [attributes.title=Add to Gallery] Title for the state. Displays in the frame's title region.
+ * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
+ * If one is not supplied, a collection of all images will be created.
+ * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.
+ * Accepts 'all', 'uploaded', or 'unattached'.
+ * @param {string} [attributes.menu=gallery] Initial mode for the menu region.
+ * @param {string} [attributes.content=upload] Initial mode for the content region.
+ * Overridden by persistent user setting if 'contentUserSetting' is true.
+ * @param {string} [attributes.router=browse] Initial mode for the router region.
+ * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region.
+ * @param {boolean} [attributes.searchable=true] Whether the library is searchable.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
+ * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
+ * @param {int} [attributes.priority=100] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
+ * Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
*/
media.controller.GalleryAdd = media.controller.Library.extend({
defaults: _.defaults({
id: 'gallery-library',
title: l10n.addToGalleryTitle,
- // Selection defaults. @see media.model.Selection
multiple: 'add',
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
filterable: 'uploaded',
- // Initial region modes.
menu: 'gallery',
toolbar: 'gallery-add',
-
priority: 100,
- // Don't sync the selection, as the Edit Gallery library
- // *is* the selection.
syncSelection: false
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.5.0
+ */
initialize: function() {
- // If we haven't been provided a `library`, create a `Selection`.
+ // If a library wasn't supplied, create a library of images.
if ( ! this.get('library') )
this.set( 'library', media.query({ type: 'image' }) );
media.controller.Library.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ */
activate: function() {
var library = this.get('library'),
edit = this.frame.state('gallery-edit').get('library');
/**
* wp.media.controller.CollectionEdit
*
- * @constructor
+ * A state for editing a collection, which is used by audio and video playlists,
+ * and can be used for other collections.
+ *
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} attributes.title Title for the state. Displays in the media menu and the frame's title region.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to edit.
+ * If one is not supplied, an empty media.model.Selection collection is created.
+ * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
+ * @param {string} [attributes.content=browse] Initial mode for the content region.
+ * @param {string} attributes.menu Initial mode for the menu region. @todo this needs a better explanation.
+ * @param {boolean} [attributes.searchable=false] Whether the library is searchable.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.describe=true] Whether to offer UI to describe the attachments - e.g. captioning images in a gallery.
+ * @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable.
+ * @param {boolean} [attributes.dragInfoText] Instructional text about the attachments being sortable.
+ * @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.
+ * @param {boolean} [attributes.editing=false] Whether the gallery is being created, or editing an existing instance.
+ * @param {int} [attributes.priority=60] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
+ * Defaults to false for this state, because the library passed in *is* the selection.
+ * @param {view} [attributes.SettingsView] The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox).
+ * @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`.
+ * If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
+ * @param {string} attributes.type The collection's media type. (e.g. 'video').
+ * @param {string} attributes.collectionType The collection type. (e.g. 'playlist').
*/
media.controller.CollectionEdit = media.controller.Library.extend({
defaults: {
- // Selection defaults. @see media.model.Selection
- multiple: false,
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
- sortable: true,
- searchable: false,
- // Region mode defaults.
- content: 'browse',
-
+ multiple: false,
+ sortable: true,
+ searchable: false,
+ content: 'browse',
describe: true,
dragInfo: true,
idealColumnWidth: 170,
editing: false,
priority: 60,
SettingsView: false,
-
- // Don't sync the selection, as the Edit {Collection} library
- // *is* the selection.
- syncSelection: false
+ syncSelection: false
},
+ /**
+ * @since 3.9.0
+ */
initialize: function() {
var collectionType = this.get('collectionType');
media.controller.Library.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
var library = this.get('library');
media.controller.Library.prototype.activate.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
deactivate: function() {
// Stop watching for uploaded attachments.
this.get('library').unobserve( wp.Uploader.queue );
media.controller.Library.prototype.deactivate.apply( this, arguments );
},
- renderSettings: function( browser ) {
+ /**
+ * Render the collection embed settings view in the browser sidebar.
+ *
+ * @todo This is against the pattern elsewhere in media. Typically the frame
+ * is responsible for adding region mode callbacks. Explain.
+ *
+ * @since 3.9.0
+ *
+ * @param {wp.media.view.attachmentsBrowser} The attachments browser view.
+ */
+ renderSettings: function( attachmentsBrowserView ) {
var library = this.get('library'),
collectionType = this.get('collectionType'),
dragInfoText = this.get('dragInfoText'),
SettingsView = this.get('SettingsView'),
obj = {};
- if ( ! library || ! browser ) {
+ if ( ! library || ! attachmentsBrowserView ) {
return;
}
priority: 40
});
- browser.sidebar.set( obj );
+ attachmentsBrowserView.sidebar.set( obj );
if ( dragInfoText ) {
- browser.toolbar.set( 'dragInfo', new media.View({
+ attachmentsBrowserView.toolbar.set( 'dragInfo', new media.View({
el: $( '<div class="instructions">' + dragInfoText + '</div>' )[0],
priority: -40
}) );
}
- browser.toolbar.set( 'reverse', {
+ // Add the 'Reverse order' button to the toolbar.
+ attachmentsBrowserView.toolbar.set( 'reverse', {
text: l10n.reverseOrder,
priority: 80,
/**
* wp.media.controller.CollectionAdd
*
- * @constructor
+ * A state for adding attachments to a collection (e.g. video playlist).
+ *
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=library] Unique identifier.
+ * @param {string} attributes.title Title for the state. Displays in the frame's title region.
+ * @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
+ * If one is not supplied, a collection of attachments of the specified type will be created.
+ * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.
+ * Accepts 'all', 'uploaded', or 'unattached'.
+ * @param {string} [attributes.menu=gallery] Initial mode for the menu region.
+ * @param {string} [attributes.content=upload] Initial mode for the content region.
+ * Overridden by persistent user setting if 'contentUserSetting' is true.
+ * @param {string} [attributes.router=browse] Initial mode for the router region.
+ * @param {string} [attributes.toolbar=gallery-add] Initial mode for the toolbar region.
+ * @param {boolean} [attributes.searchable=true] Whether the library is searchable.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
+ * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
+ * @param {int} [attributes.priority=100] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
+ * Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
+ * @param {string} attributes.type The collection's media type. (e.g. 'video').
+ * @param {string} attributes.collectionType The collection type. (e.g. 'playlist').
*/
media.controller.CollectionAdd = media.controller.Library.extend({
defaults: _.defaults( {
syncSelection: false
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.9.0
+ */
initialize: function() {
var collectionType = this.get('collectionType');
media.controller.Library.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
var library = this.get('library'),
editLibrary = this.get('editLibrary'),
});
/**
+ * wp.media.controller.FeaturedImage
+ *
* A state for selecting a featured image for a post.
*
- * @constructor
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=featured-image] Unique identifier.
+ * @param {string} [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
+ * If one is not supplied, a collection of all images will be created.
+ * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
+ * @param {string} [attributes.content=upload] Initial mode for the content region.
+ * Overridden by persistent user setting if 'contentUserSetting' is true.
+ * @param {string} [attributes.menu=default] Initial mode for the menu region.
+ * @param {string} [attributes.router=browse] Initial mode for the router region.
+ * @param {string} [attributes.toolbar=featured-image] Initial mode for the toolbar region.
+ * @param {int} [attributes.priority=60] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.searchable=true] Whether the library is searchable.
+ * @param {boolean|string} [attributes.filterable=false] Whether the library is filterable, and if so what filters should be shown.
+ * Accepts 'all', 'uploaded', or 'unattached'.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
+ * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
+ * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
+ * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.
*/
media.controller.FeaturedImage = media.controller.Library.extend({
defaults: _.defaults({
id: 'featured-image',
title: l10n.setFeaturedImageTitle,
- // Selection defaults. @see media.model.Selection
multiple: false,
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
filterable: 'uploaded',
- // Region mode defaults.
toolbar: 'featured-image',
-
priority: 60,
syncSelection: true
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.5.0
+ */
initialize: function() {
var library, comparator;
library.observe( this.get('selection') );
},
+ /**
+ * @since 3.5.0
+ */
activate: function() {
this.updateSelection();
this.frame.on( 'open', this.updateSelection, this );
media.controller.Library.prototype.activate.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ */
deactivate: function() {
this.frame.off( 'open', this.updateSelection, this );
media.controller.Library.prototype.deactivate.apply( this, arguments );
},
+ /**
+ * @since 3.5.0
+ */
updateSelection: function() {
var selection = this.get('selection'),
id = media.view.settings.post.featuredImageId,
});
/**
+ * wp.media.controller.ReplaceImage
+ *
* A state for replacing an image.
*
- * @constructor
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} [attributes] The attributes hash passed to the state.
+ * @param {string} [attributes.id=replace-image] Unique identifier.
+ * @param {string} [attributes.title=Replace Image] Title for the state. Displays in the media menu and the frame's title region.
+ * @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
+ * If one is not supplied, a collection of all images will be created.
+ * @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
+ * @param {string} [attributes.content=upload] Initial mode for the content region.
+ * Overridden by persistent user setting if 'contentUserSetting' is true.
+ * @param {string} [attributes.menu=default] Initial mode for the menu region.
+ * @param {string} [attributes.router=browse] Initial mode for the router region.
+ * @param {string} [attributes.toolbar=replace] Initial mode for the toolbar region.
+ * @param {int} [attributes.priority=60] The priority for the state link in the media menu.
+ * @param {boolean} [attributes.searchable=true] Whether the library is searchable.
+ * @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.
+ * Accepts 'all', 'uploaded', or 'unattached'.
+ * @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
+ * @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
+ * @param {boolean} [attributes.describe=false] Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
+ * @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
+ * @param {boolean} [attributes.syncSelection=true] Whether the Attachments selection should be persisted from the last state.
*/
media.controller.ReplaceImage = media.controller.Library.extend({
defaults: _.defaults({
id: 'replace-image',
title: l10n.replaceImageTitle,
- // Selection defaults. @see media.model.Selection
multiple: false,
- // Attachments browser defaults. @see media.view.AttachmentsBrowser
filterable: 'uploaded',
- // Region mode defaults.
toolbar: 'replace',
menu: false,
-
priority: 60,
syncSelection: true
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.9.0
+ *
+ * @param options
+ */
initialize: function( options ) {
var library, comparator;
library.observe( this.get('selection') );
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
this.updateSelection();
media.controller.Library.prototype.activate.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
updateSelection: function() {
var selection = this.get('selection'),
attachment = this.image.attachment;
});
/**
+ * wp.media.controller.EditImage
+ *
* A state for editing (cropping, etc.) an image.
*
- * @constructor
+ * @class
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} attributes The attributes hash passed to the state.
+ * @param {wp.media.model.Attachment} attributes.model The attachment.
+ * @param {string} [attributes.id=edit-image] Unique identifier.
+ * @param {string} [attributes.title=Edit Image] Title for the state. Displays in the media menu and the frame's title region.
+ * @param {string} [attributes.content=edit-image] Initial mode for the content region.
+ * @param {string} [attributes.toolbar=edit-image] Initial mode for the toolbar region.
+ * @param {string} [attributes.menu=false] Initial mode for the menu region.
+ * @param {string} [attributes.url] Unused. @todo Consider removal.
*/
media.controller.EditImage = media.controller.State.extend({
defaults: {
id: 'edit-image',
title: l10n.editImage,
- // Region mode defaults.
menu: false,
toolbar: 'edit-image',
content: 'edit-image',
-
url: ''
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
this.listenTo( this.frame, 'toolbar:render:edit-image', this.toolbar );
},
+ /**
+ * @since 3.9.0
+ */
deactivate: function() {
this.stopListening( this.frame );
},
+ /**
+ * @since 3.9.0
+ */
toolbar: function() {
var frame = this.frame,
lastState = frame.lastState(),
/**
* wp.media.controller.MediaLibrary
*
- * @constructor
+ * @class
* @augments wp.media.controller.Library
* @augments wp.media.controller.State
* @augments Backbone.Model
syncSelection: false
}, media.controller.Library.prototype.defaults ),
+ /**
+ * @since 3.9.0
+ *
+ * @param options
+ */
initialize: function( options ) {
this.media = options.media;
this.type = options.type;
media.controller.Library.prototype.initialize.apply( this, arguments );
},
+ /**
+ * @since 3.9.0
+ */
activate: function() {
+ // @todo this should use this.frame.
if ( media.frame.lastMime ) {
this.set( 'library', media.query({ type: media.frame.lastMime }) );
delete media.frame.lastMime;
/**
* wp.media.controller.Embed
*
- * @constructor
+ * A state for embedding media from a URL.
+ *
+ * @class
* @augments wp.media.controller.State
* @augments Backbone.Model
+ *
+ * @param {object} attributes The attributes hash passed to the state.
+ * @param {string} [attributes.id=embed] Unique identifier.
+ * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region.
+ * @param {string} [attributes.content=embed] Initial mode for the content region.
+ * @param {string} [attributes.menu=default] Initial mode for the menu region.
+ * @param {string} [attributes.toolbar=main-embed] Initial mode for the toolbar region.
+ * @param {string} [attributes.menu=false] Initial mode for the menu region.
+ * @param {int} [attributes.priority=120] The priority for the state link in the media menu.
+ * @param {string} [attributes.type=link] The type of embed. Currently only link is supported.
+ * @param {string} [attributes.url] The embed URL.
+ * @param {object} [attributes.metadata={}] Properties of the embed, which will override attributes.url if set.
*/
media.controller.Embed = media.controller.State.extend({
defaults: {
id: 'embed',
title: l10n.insertFromUrlTitle,
- // Region mode defaults.
content: 'embed',
menu: 'default',
toolbar: 'main-embed',
-
priority: 120,
type: 'link',
url: '',
},
/**
+ * Trigger a scan of the embedded URL's content for metadata required to embed.
+ *
* @fires wp.media.controller.Embed#scan
*/
scan: function() {
this.set( attributes );
},
/**
+ * Try scanning the embed as an image to discover its dimensions.
+ *
* @param {Object} attributes
*/
scanImage: function( attributes ) {
/**
* wp.media.controller.Cropper
*
- * Allows for a cropping step.
+ * A state for cropping an image.
*
- * @constructor
+ * @class
* @augments wp.media.controller.State
* @augments Backbone.Model
*/
}
});
- /**
- * ========================================================================
- * VIEWS
- * ========================================================================
- */
-
/**
* wp.media.View
- * -------------
*
- * The base view class.
+ * The base view class for media.
*
* Undelegating events, removing events from the model, and
* removing events from the controller mirror the code for
* This behavior has since been removed, and should not be used
* outside of the media manager.
*
- * @constructor
+ * @class
* @augments wp.Backbone.View
* @augments Backbone.View
*/
wp.Backbone.View.apply( this, arguments );
},
/**
+ * @todo The internal comment mentions this might have been a stop-gap
+ * before Backbone 0.9.8 came out. Figure out if Backbone core takes
+ * care of this in Backbone.View now.
+ *
* @returns {wp.media.View} Returns itself to allow chaining
*/
dispose: function() {
* wp.media.view.Frame
*
* A frame is a composite view consisting of one or more regions and one or more
- * states. Only one state can be active at any given moment.
+ * states.
*
- * @constructor
+ * @see wp.media.controller.State
+ * @see wp.media.controller.Region
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
}, this );
},
/**
+ * Create the frame's states.
+ *
+ * @see wp.media.controller.State
+ * @see wp.media.controller.StateMachine
+ *
* @fires wp.media.controller.State#ready
*/
_createStates: function() {
this.states.add( this.options.states );
}
},
+
+ /**
+ * A frame can be in a mode or multiple modes at one time.
+ *
+ * For example, the manage media frame can be in the `Bulk Select` or `Edit` mode.
+ */
_createModes: function() {
// Store active "modes" that the frame is in. Unrelated to region modes.
this.activeModes = new Backbone.Collection();
}, this );
},
/**
+ * Reset all states on the frame to their defaults.
+ *
* @returns {wp.media.view.Frame} Returns itself to allow chaining
*/
reset: function() {
/**
* wp.media.view.MediaFrame
*
- * Type of frame used to create the media modal.
+ * The frame used to create the media modal.
*
- * @constructor
+ * @class
* @augments wp.media.view.Frame
* @augments wp.media.View
* @augments wp.Backbone.View
}, this );
this.on( 'content:create:iframe', this.iframeContent, this );
+ this.on( 'content:deactivate:iframe', this.iframeContentCleanup, this );
this.on( 'menu:render:default', this.iframeMenu, this );
this.on( 'open', this.hijackThickbox, this );
this.on( 'close', this.restoreThickbox, this );
});
},
+ iframeContentCleanup: function() {
+ this.$el.removeClass('hide-toolbar');
+ },
+
iframeMenu: function( view ) {
var views = {};
/**
* wp.media.view.MediaFrame.Select
*
- * Type of media frame that is used to select an item or items from the media library
+ * A frame for selecting an item or items from the media library.
*
- * @constructor
+ * @class
* @augments wp.media.view.MediaFrame
* @augments wp.media.view.Frame
* @augments wp.media.View
*/
media.view.MediaFrame.Select = media.view.MediaFrame.extend({
initialize: function() {
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.MediaFrame.prototype.initialize.apply( this, arguments );
_.defaults( this.options, {
sortable: state.get('sortable'),
search: state.get('searchable'),
filters: state.get('filterable'),
+ date: state.get('date'),
display: state.has('display') ? state.get('display') : state.get('displaySettings'),
dragInfo: state.get('dragInfo'),
/**
* wp.media.view.MediaFrame.Post
*
- * @constructor
+ * The frame for manipulating media on the Edit Post page.
+ *
+ * @class
* @augments wp.media.view.MediaFrame.Select
* @augments wp.media.view.MediaFrame
* @augments wp.media.view.Frame
state: 'insert',
metadata: {}
});
- /**
- * call 'initialize' directly on the parent class
- */
+
+ // Call 'initialize' directly on the parent class.
media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments );
this.createIframeStates();
},
+ /**
+ * Create the default states.
+ */
createStates: function() {
var options = this.options;
- // Add the default states.
this.states.add([
// Main states.
new media.controller.Library({
// Browse our library of attachments.
this.content.set( view );
+
+ // Trigger the controller to set focus
+ this.trigger( 'edit:selection', this );
},
editImageContent: function() {
/**
* wp.media.view.MediaFrame.ImageDetails
*
- * @constructor
+ * A media frame for manipulating an image that's already been inserted
+ * into a post.
+ *
+ * @class
* @augments wp.media.view.MediaFrame.Select
* @augments wp.media.view.MediaFrame
* @augments wp.media.view.Frame
/**
* wp.media.view.Modal
*
- * @constructor
+ * A modal view, which the media modal uses as its default container.
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.FocusManager
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.UploaderWindow
*
- * @constructor
+ * An uploader window that allows for dragging and dropping media.
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
+ *
+ * @param {object} [options] Options hash passed to the view.
+ * @param {object} [options.uploader] Uploader properties.
+ * @param {jQuery} [options.uploader.browser]
+ * @param {jQuery} [options.uploader.dropzone] jQuery collection of the dropzone.
+ * @param {object} [options.uploader.params]
*/
media.view.UploaderWindow = media.View.extend({
tagName: 'div',
});
/**
+ * Creates a dropzone on WP editor instances (elements with .wp-editor-wrap
+ * or #wp-fullscreen-body) and relays drag'n'dropped files to a media workflow.
+ *
* wp.media.view.EditorUploader
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
overDropzone: false,
draggingFile: null,
+ /**
+ * Bind drag'n'drop events to callbacks.
+ */
initialize: function() {
var self = this;
return this;
},
+ /**
+ * Check browser support for drag'n'drop.
+ *
+ * @return Boolean
+ */
browserSupport: function() {
var supports = false, div = document.createElement('div');
return this;
},
+ /**
+ * When a file is dropped on the editor uploader, open up an editor media workflow
+ * and upload the file immediately.
+ *
+ * @param {jQuery.Event} event The 'drop' event.
+ */
drop: function( event ) {
- var $wrap = null;
+ var $wrap = null, uploadView;
this.containerDragleave( event );
this.dropzoneDragleave( event );
title: wp.media.view.l10n.addMedia,
multiple: true
});
- this.workflow.on( 'uploader:ready', this.addFiles, this );
+ uploadView = this.workflow.uploader;
+ if ( uploadView.uploader && uploadView.uploader.ready ) {
+ this.addFiles.apply( this );
+ } else {
+ this.workflow.on( 'uploader:ready', this.addFiles, this );
+ }
} else {
this.workflow.state().reset();
this.addFiles.apply( this );
return false;
},
+ /**
+ * Add the files to the uploader.
+ */
addFiles: function() {
if ( this.files.length ) {
this.workflow.uploader.uploader.uploader.addFile( _.toArray( this.files ) );
/**
* wp.media.view.UploaderInline
*
- * @constructor
+ * The inline uploader that shows up in the 'Upload Files' tab.
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.UploaderStatus
*
- * @constructor
+ * An uploader status for on-going uploads.
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.UploaderStatusError
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Toolbar
*
- * @constructor
+ * A toolbar which consists of a primary and a secondary section. Each sections
+ * can be filled with views.
+ *
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Toolbar.Select
*
- * @constructor
+ * @class
* @augments wp.media.view.Toolbar
* @augments wp.media.View
* @augments wp.Backbone.View
requires: options.requires
}
});
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.Toolbar.prototype.initialize.apply( this, arguments );
},
/**
* wp.media.view.Toolbar.Embed
*
- * @constructor
+ * @class
* @augments wp.media.view.Toolbar.Select
* @augments wp.media.view.Toolbar
* @augments wp.media.View
text: l10n.insertIntoPost,
requires: false
});
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.Toolbar.Select.prototype.initialize.apply( this, arguments );
},
/**
* wp.media.view.Button
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.ButtonGroup
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.PriorityList
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.MenuItem
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Menu
*
- * @constructor
+ * @class
* @augments wp.media.view.PriorityList
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.RouterItem
*
- * @constructor
+ * @class
* @augments wp.media.view.MenuItem
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Router
*
- * @constructor
+ * @class
* @augments wp.media.view.Menu
* @augments wp.media.view.PriorityList
* @augments wp.media.View
initialize: function() {
this.controller.on( 'content:render', this.update, this );
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.Menu.prototype.initialize.apply( this, arguments );
},
/**
* wp.media.view.Sidebar
*
- * @constructor
+ * @class
* @augments wp.media.view.PriorityList
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Attachment
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
'click .close': 'removeFromLibrary',
'click .check': 'checkClickHandler',
'click a': 'preventDefault',
+ 'keydown .close': 'removeFromLibrary',
'keydown': 'toggleSelectionHandler'
},
this.model.on( 'selection:single selection:unsingle', this.details, this );
this.details( this.model, this.controller.state().get('selection') );
}
+
+ this.listenTo( this.controller, 'attachment:compat:waiting attachment:compat:ready', this.updateSave );
},
/**
* @returns {wp.media.view.Attachment} Returns itself to allow chaining
return;
}
+ event.preventDefault();
+
// In the grid view, bubble up an edit:attachment event to the controller.
if ( this.controller.isModeActive( 'grid' ) ) {
if ( this.controller.isModeActive( 'edit' ) ) {
// Pass the current target to restore focus when closing
this.controller.trigger( 'edit:attachment', this.model, event.currentTarget );
-
- // Don't scroll the view and don't attempt to submit anything.
- event.stopPropagation();
return;
}
});
this.controller.trigger( 'selection:toggle' );
-
- // Don't scroll the view and don't attempt to submit anything.
- event.stopPropagation();
},
/**
* @param {Object} options
* @param {Object} event
*/
removeFromLibrary: function( event ) {
+ // Catch enter and space events
+ if ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {
+ return;
+ }
+
// Stop propagation so the model isn't selected.
event.stopPropagation();
/**
* wp.media.view.Attachment.Library
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachment
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Attachment.EditLibrary
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachment
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Attachments
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
// If the `collection` has a `comparator`, disable sorting.
disabled: !! collection.comparator,
- // Prevent attachments from being dragged outside the bounding
- // box of the list.
- containment: this.$el,
-
// Change the position of the attachment as soon as the
// mouse pointer overlaps a thumbnail.
tolerance: 'pointer',
/**
* wp.media.view.Search
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.AttachmentFilters
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
},
/**
- * When the selection changes, set the Query properties
- * accordingly for the selected filter.
+ * When the selected filter changes, update the Attachment Query properties to match.
*/
change: function() {
var filter = this.filters[ this.el.value ];
}
});
+ /**
+ * A filter dropdown for month/dates.
+ *
+ * @class
+ * @augments wp.media.view.AttachmentFilters
+ * @augments wp.media.View
+ * @augments wp.Backbone.View
+ * @augments Backbone.View
+ */
+ media.view.DateFilter = media.view.AttachmentFilters.extend({
+ id: 'media-attachment-date-filters',
+
+ createFilters: function() {
+ var filters = {};
+ _.each( media.view.settings.months || {}, function( value, index ) {
+ filters[ index ] = {
+ text: value.text,
+ props: {
+ year: value.year,
+ monthnum: value.month
+ }
+ };
+ });
+ filters.all = {
+ text: l10n.allDates,
+ props: {
+ monthnum: false,
+ year: false
+ },
+ priority: 10
+ };
+ this.filters = filters;
+ }
+ });
+
/**
* wp.media.view.AttachmentFilters.Uploaded
*
- * @constructor
+ * @class
* @augments wp.media.view.AttachmentFilters
* @augments wp.media.View
* @augments wp.Backbone.View
order: 'ASC'
},
priority: 20
+ },
+
+ unattached: {
+ text: l10n.unattached,
+ props: {
+ uploadedTo: 0,
+ orderby: 'menuOrder',
+ order: 'ASC'
+ },
+ priority: 50
}
};
}
/**
* wp.media.view.AttachmentFilters.All
*
- * @constructor
+ * @class
* @augments wp.media.view.AttachmentFilters
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.AttachmentsBrowser
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
+ *
+ * @param {object} options
+ * @param {object} [options.filters=false] Which filters to show in the browser's toolbar.
+ * Accepts 'uploaded' and 'all'.
+ * @param {object} [options.search=true] Whether to show the search interface in the
+ * browser's toolbar.
+ * @param {object} [options.date=true] Whether to show the date filter in the
+ * browser's toolbar.
+ * @param {object} [options.display=false] Whether to show the attachments display settings
+ * view in the sidebar.
+ * @param {bool|string} [options.sidebar=true] Whether to create a sidebar for the browser.
+ * Accepts true, false, and 'errors'.
*/
media.view.AttachmentsBrowser = media.View.extend({
tagName: 'div',
_.defaults( this.options, {
filters: false,
search: true,
+ date: true,
display: false,
sidebar: true,
AttachmentView: media.view.Attachment.Library
});
this.listenTo( this.controller, 'toggle:upload:attachment', _.bind( this.toggleUploader, this ) );
-
+ this.controller.on( 'edit:selection', this.editSelection );
this.createToolbar();
if ( this.options.sidebar ) {
this.createSidebar();
this.collection.on( 'add remove reset', this.updateContent, this );
},
+
+ editSelection: function( modal ) {
+ modal.$( '.media-button-backToLibrary' ).focus();
+ },
+
/**
* @returns {wp.media.view.AttachmentsBrowser} Returns itself to allow chaining
*/
changed.push( model.save() );
removed.push( model );
} else {
- model.destroy();
+ model.destroy({wait: true});
}
} );
}
}
}).render() );
+
+ if ( media.view.settings.mediaTrash ) {
+ this.toolbar.set( 'deleteSelectedPermanentlyButton', new media.view.DeleteSelectedPermanentlyButton({
+ filters: Filters,
+ style: 'primary',
+ disabled: true,
+ text: l10n.deleteSelected,
+ controller: this.controller,
+ priority: -55,
+ click: function() {
+ var removed = [], selection = this.controller.state().get( 'selection' );
+
+ if ( ! selection.length || ! confirm( l10n.warnBulkDelete ) ) {
+ return;
+ }
+
+ selection.each( function( model ) {
+ if ( ! model.get( 'nonces' )['delete'] ) {
+ removed.push( model );
+ return;
+ }
+
+ model.destroy();
+ } );
+
+ selection.remove( removed );
+ this.controller.trigger( 'selection:action:done' );
+ }
+ }).render() );
+ }
+
+ } else if ( this.options.date ) {
+ // DateFilter is a <select>, screen reader text needs to be rendered before
+ this.toolbar.set( 'dateFilterLabel', new media.view.Label({
+ value: l10n.filterByDate,
+ attributes: {
+ 'for': 'media-attachment-date-filters'
+ },
+ priority: -75
+ }).render() );
+ this.toolbar.set( 'dateFilter', new media.view.DateFilter({
+ controller: this.controller,
+ model: this.collection.props,
+ priority: -75
+ }).render() );
}
if ( this.options.search ) {
/**
* wp.media.view.Selection
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Attachment.Selection
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachment
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Attachments.Selection
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachments
* @augments wp.media.View
* @augments wp.Backbone.View
events: {},
initialize: function() {
_.defaults( this.options, {
- sortable: true,
+ sortable: false,
resize: false,
// The single `Attachment` view to be used in the `Attachments` view.
AttachmentView: media.view.Attachment.Selection
});
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
return media.view.Attachments.prototype.initialize.apply( this, arguments );
}
});
/**
* wp.media.view.Attachments.EditSelection
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachment.Selection
* @augments wp.media.view.Attachment
* @augments wp.media.View
/**
* wp.media.view.Settings
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Settings.AttachmentDisplay
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings
* @augments wp.media.View
* @augments wp.Backbone.View
_.defaults( this.options, {
userSettings: false
});
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.Settings.prototype.initialize.apply( this, arguments );
this.model.on( 'change:link', this.updateLinkTo, this );
/**
* wp.media.view.Settings.Gallery
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Settings.Playlist
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.Attachment.Details
*
- * @constructor
+ * @class
* @augments wp.media.view.Attachment
* @augments wp.media.View
* @augments wp.Backbone.View
className: 'attachment-details',
template: media.template('attachment-details'),
+ attributes: function() {
+ return {
+ 'tabIndex': 0,
+ 'data-id': this.model.get( 'id' )
+ };
+ },
+
events: {
'change [data-setting]': 'updateSetting',
'change [data-setting] input': 'updateSetting',
});
this.on( 'ready', this.initialFocus );
- /**
- * call 'initialize' directly on the parent class
- */
+ // Call 'initialize' directly on the parent class.
media.view.Attachment.prototype.initialize.apply( this, arguments );
},
*
* A view to display fields added via the `attachment_fields_to_edit` filter.
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
data[ pair.name ] = pair.value;
});
- this.model.saveCompat( data );
+ this.controller.trigger( 'attachment:compat:waiting', ['waiting'] );
+ this.model.saveCompat( data ).always( _.bind( this.postSave, this ) );
+ },
+
+ postSave: function() {
+ this.controller.trigger( 'attachment:compat:ready', ['ready'] );
}
});
/**
* wp.media.view.Iframe
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Embed
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
});
/**
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.EmbedUrl
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.EmbedLink
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings
* @augments wp.media.View
* @augments wp.Backbone.View
/**
* wp.media.view.EmbedImage
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings.AttachmentDisplay
* @augments wp.media.view.Settings
* @augments wp.media.View
/**
* wp.media.view.ImageDetails
*
- * @constructor
+ * @class
* @augments wp.media.view.Settings.AttachmentDisplay
* @augments wp.media.view.Settings
* @augments wp.media.View
* wp.customize.HeaderControl.calculateImageSelectOptions via
* wp.customize.HeaderControl.openMM.
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
/**
* wp.media.view.Spinner
*
- * @constructor
+ * @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View