From 1daa774b271a518b6ff1d9d746d89948febcc993 Mon Sep 17 00:00:00 2001 From: Daryl Koopersmith Date: Wed, 10 Oct 2012 23:32:48 +0000 Subject: [PATCH] Caption editing in the media modal library. * Adds a `describe` option to the workflow controller to support inline caption editing. * For images, descriptions are mapped to the `caption` attribute. * For other media items, descriptions are mapped to the `title` attribute. * Descriptions are saved when the textarea's `change` event fires (i.e. when the textarea is blurred). fixes #21807, see #21390. git-svn-id: http://core.svn.wordpress.org/trunk@22173 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/admin-ajax.php | 3 ++- wp-admin/includes/ajax-actions.php | 30 ++++++++++++++++++++++++++++ wp-admin/js/media-upload.js | 3 ++- wp-includes/css/media-views.css | 32 +++++++++++++++++++----------- wp-includes/js/mce-view.js | 3 ++- wp-includes/js/media-models.js | 30 ++++++++++++++++++++++++---- wp-includes/js/media-views.js | 19 +++++++++++++----- wp-includes/media.php | 18 ++++++++++++++++- 8 files changed, 113 insertions(+), 25 deletions(-) diff --git a/wp-admin/admin-ajax.php b/wp-admin/admin-ajax.php index cc1128a6f9..9e67fa67c6 100644 --- a/wp-admin/admin-ajax.php +++ b/wp-admin/admin-ajax.php @@ -53,7 +53,8 @@ $core_actions_post = array( 'menu-locations-save', 'menu-quick-search', 'meta-box-order', 'get-permalink', 'sample-permalink', 'inline-save', 'inline-save-tax', 'find_posts', 'widgets-order', 'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post', - 'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment', 'query-attachments', + 'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment', + 'query-attachments', 'save-attachment', ); // Register core Ajax calls. diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index d4f13d1ecf..e03ffdc914 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -1820,3 +1820,33 @@ function wp_ajax_query_attachments() { wp_send_json_success( $posts ); } + +/** + * Save attachment attributes. + * + * @since 3.5.0 + */ +function wp_ajax_save_attachment() { + if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) ) + wp_send_json_error(); + + if ( ! $id = absint( $_REQUEST['id'] ) ) + wp_send_json_error(); + + if ( ! current_user_can( 'edit_post', $id ) ) + wp_send_json_error(); + + $changes = $_REQUEST['changes']; + $args = array(); + + if ( $changes['title'] ) + $args['post_title'] = $changes['title']; + + if ( $changes['caption'] ) + $args['post_excerpt'] = $changes['caption']; + + if ( $args ) + wp_update_post( array_merge( $args, array( 'ID' => $id ) ) ); + + wp_send_json_success(); +} diff --git a/wp-admin/js/media-upload.js b/wp-admin/js/media-upload.js index 4713d068a1..58fae2ebe7 100644 --- a/wp-admin/js/media-upload.js +++ b/wp-admin/js/media-upload.js @@ -104,7 +104,8 @@ var tb_position; workflow = workflows[ id ] = wp.media( _.defaults( options || {}, { title: wp.media.view.l10n.insertMedia, - multiple: true + multiple: true, + describe: true } ) ); workflow.on( 'update:insert', function( selection ) { diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css index be05e1a8c6..06b8535639 100644 --- a/wp-includes/css/media-views.css +++ b/wp-includes/css/media-views.css @@ -246,16 +246,9 @@ .attachment { position: relative; float: left; - width: 199px; - height: 199px; padding: 0; margin: 0 10px 20px; - box-shadow: - inset 0 0 15px rgba( 0, 0, 0, 0.1 ), - inset 0 0 0 1px rgba( 0, 0, 0, 0.05 ); - background: #eee; - cursor: pointer; color: #464646; -webkit-user-select: none; @@ -281,12 +274,15 @@ } .attachment-preview { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; + position: relative; + width: 199px; + height: 199px; overflow: hidden; + box-shadow: + inset 0 0 15px rgba( 0, 0, 0, 0.1 ), + inset 0 0 0 1px rgba( 0, 0, 0, 0.05 ); + background: #eee; + cursor: pointer; } .attachment .icon, @@ -390,6 +386,18 @@ display: block; } +.attachment .describe { + position: relative; + display: block; + width: 100%; + height: 66px; + margin: -1px 0 0; + padding: 8px; + font-size: 12px; + resize: none; + border-radius: 0; +} + /* Square crop with overflow visible on hover. */ /* diff --git a/wp-includes/js/mce-view.js b/wp-includes/js/mce-view.js index 88425e0a8c..546c714d85 100644 --- a/wp-includes/js/mce-view.js +++ b/wp-includes/js/mce-view.js @@ -639,7 +639,8 @@ window.wp = window.wp || {}; selection: this.attachments.models, title: mceview.l10n.editGallery, editing: true, - multiple: true + multiple: true, + describe: true }); // Create a single-use workflow. If the workflow is closed, diff --git a/wp-includes/js/media-models.js b/wp-includes/js/media-models.js index 59b34430d5..4e15f4f297 100644 --- a/wp-includes/js/media-models.js +++ b/wp-includes/js/media-models.js @@ -174,7 +174,7 @@ window.wp = window.wp || {}; */ Attachment = media.model.Attachment = Backbone.Model.extend({ sync: function( method, model, options ) { - // Overload the read method so Attachment.fetch() functions correctly. + // Overload the `read` request so Attachment.fetch() functions correctly. if ( 'read' === method ) { options = options || {}; options.context = this; @@ -184,13 +184,35 @@ window.wp = window.wp || {}; }); return media.ajax( options ); - // Otherwise, fall back to Backbone.sync() - } else { - return Backbone.sync.apply( this, arguments ); + // Overload the `update` request so properties can be saved. + } else if ( 'update' === method ) { + options = options || {}; + options.context = this; + + // Set the action and ID. + options.data = _.extend( options.data || {}, { + action: 'save-attachment', + id: this.id + }); + + // Record the values of the changed attributes. + if ( options.changes ) { + _.each( options.changes, function( value, key ) { + options.changes[ key ] = this.get( key ); + }, this ); + + options.data.changes = options.changes; + delete options.changes; + } + + return media.ajax( options ); } }, parse: function( resp, xhr ) { + if ( ! resp ) + return resp; + // Convert date strings into Date objects. resp.date = new Date( resp.date ); resp.modified = new Date( resp.modified ); diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js index 4d5412c0ef..3c5436db58 100644 --- a/wp-includes/js/media-views.js +++ b/wp-includes/js/media-views.js @@ -385,9 +385,10 @@ template: media.template('attachment'), events: { - 'click': 'toggleSelection', - 'mouseenter': 'shrink', - 'mouseleave': 'expand' + 'click .attachment-preview': 'toggleSelection', + 'mouseenter .attachment-preview': 'shrink', + 'mouseleave .attachment-preview': 'expand', + 'change .describe': 'describe' }, buttons: {}, @@ -415,7 +416,8 @@ filename: '' }); - options.buttons = this.buttons; + options.buttons = this.buttons; + options.describe = this.controller.get('describe'); if ( 'image' === options.type ) _.extend( options, this.crop() ); @@ -533,6 +535,13 @@ width: 199, height: 199 }); + }, + + describe: function( event ) { + if ( 'image' === this.model.get('type') ) + this.model.save( 'caption', event.target.value ); + else + this.model.save( 'title', event.target.value ); } }); @@ -817,7 +826,7 @@ template: media.template('attachments'), events: { - 'keyup input': 'search' + 'keyup .search': 'search' }, initialize: function() { diff --git a/wp-includes/media.php b/wp-includes/media.php index 87762f7de2..491ab76bb6 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -1345,7 +1345,23 @@ function wp_print_media_templates( $attachment ) { × <% } %> -
+ <% if ( describe ) { %> + <% if ( 'image' === type ) { %> + + <% } else { %> + + <% } %> + <% } %>