<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[22323] trunk/wp-includes: Add attachment details to the media sidebar.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/22323">22323</a></dd>
<dt>Author</dt> <dd>koopersmith</dd>
<dt>Date</dt> <dd>2012-10-29 15:13:02 +0000 (Mon, 29 Oct 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add attachment details to the media sidebar.

* Also moves most of the `Frame` view's `createSelection` method to a real `Selection` model (which inherits from the `Attachments` model).
* Properly assigns the library within the `Gallery` state, allowing for the `Gallery` state to inherit from the `Library` state.

see <a href="http://core.trac.wordpress.org/ticket/21390">#21390</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludescssmediaviewscss">trunk/wp-includes/css/media-views.css</a></li>
<li><a href="#trunkwpincludesjsmediamodelsjs">trunk/wp-includes/js/media-models.js</a></li>
<li><a href="#trunkwpincludesjsmediaviewsjs">trunk/wp-includes/js/media-views.js</a></li>
<li><a href="#trunkwpincludesmediaphp">trunk/wp-includes/media.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludescssmediaviewscss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/media-views.css (22322 => 22323)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/media-views.css        2012-10-29 07:38:13 UTC (rev 22322)
+++ trunk/wp-includes/css/media-views.css        2012-10-29 15:13:02 UTC (rev 22323)
</span><span class="lines">@@ -307,8 +307,8 @@
</span><span class="cx">         font-weight: bold;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.attachment .thumbnail,
-.attachment .thumbnail img {
</del><ins>+.attachment-preview .thumbnail,
+.attachment-preview .thumbnail img {
</ins><span class="cx">         -webkit-transition-property: width, height, top, left, right, bottom;
</span><span class="cx">         -moz-transition-property:    width, height, top, left, right, bottom;
</span><span class="cx">         -ms-transition-property:     width, height, top, left, right, bottom;
</span><span class="lines">@@ -326,12 +326,12 @@
</span><span class="cx">         transition-delay:            200ms;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.attachment .thumbnail {
</del><ins>+.attachment-preview .thumbnail {
</ins><span class="cx">         width: 199px;
</span><span class="cx">         height: 199px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.attachment .thumbnail:after {
</del><ins>+.attachment-preview .thumbnail:after {
</ins><span class="cx">         content: '';
</span><span class="cx">         display: block;
</span><span class="cx">         position: absolute;
</span><span class="lines">@@ -388,7 +388,7 @@
</span><span class="cx">         display: block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.attachment .describe {
</del><ins>+.media-frame .describe {
</ins><span class="cx">         position: relative;
</span><span class="cx">         display: block;
</span><span class="cx">         width: 100%;
</span><span class="lines">@@ -593,6 +593,38 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Attachment Details
+ */
+
+.attachment-details {
+        padding-top: 20px;
+}
+
+.attachment-details-preview {
+        cursor: default;
+}
+
+.attachment-details-preview,
+.attachment-details-preview .thumbnail {
+        width: auto;
+        height: auto;
+        float: left;
+        position: relative;
+}
+
+.attachment-details-preview .thumbnail img {
+        max-width: 120px;
+        max-height: 120px;
+        display: block;
+        margin: 0 auto;
+}
+
+.attachment-details .describe {
+        float: left;
+        margin: 10px 0 0;
+}
+
+/**
</ins><span class="cx">  * Attachment Display Settings
</span><span class="cx">  */
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkwpincludesjsmediamodelsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-models.js (22322 => 22323)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-models.js        2012-10-29 07:38:13 UTC (rev 22322)
+++ trunk/wp-includes/js/media-models.js        2012-10-29 15:13:02 UTC (rev 22323)
</span><span class="lines">@@ -613,4 +613,47 @@
</span><span class="cx">                 }())
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+        /**
+         * wp.media.model.Selection
+         *
+         * Used to manage a selection of attachments in the views.
+         */
+        media.model.Selection = Attachments.extend({
+                initialize: function( models, options ) {
+                        Attachments.prototype.initialize.apply( this, arguments );
+                        this.multiple = options &amp;&amp; options.multiple;
+                },
+
+                // Override the selection's add method.
+                // If the workflow does not support multiple
+                // selected attachments, reset the selection.
+                add: function( models, options ) {
+                        if ( ! this.multiple ) {
+                                models = _.isArray( models ) ? _.first( models ) : models;
+                                this.clear( options );
+                        }
+
+                        return Attachments.prototype.add.call( this, models, options );
+                },
+
+                // Removes all models from the selection.
+                clear: function( options ) {
+                        return this.remove( this.models, options );
+                },
+
+                // 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 );
+                },
+
+                // Create selection.has, which determines if a model
+                // exists in the collection based on cid and id,
+                // instead of direct comparison.
+                has: function( attachment ) {
+                        return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
+                }
+        });
+
</ins><span class="cx"> }(jQuery));
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesjsmediaviewsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-views.js (22322 => 22323)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-views.js        2012-10-29 07:38:13 UTC (rev 22322)
+++ trunk/wp-includes/js/media-views.js        2012-10-29 15:13:02 UTC (rev 22323)
</span><span class="lines">@@ -118,16 +118,43 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        if ( ! this.get('selection') )
-                                this.set( 'selection', new Attachments() );
</del><ins>+                        if ( ! this.get('selection') ) {
+                                this.set( 'selection', new media.model.Selection( null, {
+                                        multiple: this.get('multiple')
+                                }) );
+                        }
</ins><span class="cx"> 
</span><span class="cx">                         if ( ! this.get('library') )
</span><span class="cx">                                 this.set( 'library', media.query() );
</span><span class="cx"> 
</span><span class="cx">                         this.on( 'activate', this.activate, this );
</span><ins>+                        this.on( 'deactivate', this.deactivate, this );
+                        this.on( 'change:details', this.details, this );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 activate: function() {
</span><ins>+                        this.toolbar();
+                        this.sidebar();
+                        this.content();
+
+                        // If we're in a workflow that supports multiple attachments,
+                        // automatically select any uploading attachments.
+                        if ( this.get('multiple') )
+                                wp.Uploader.queue.on( 'add', this.selectUpload, this );
+
+                        this.get('selection').on( 'add remove', this.toggleDetails, this );
+                },
+
+                deactivate: function() {
+                        var toolbar = this._postLibraryToolbar;
+                        if ( toolbar )
+                                this.get('selection').off( 'add remove', toolbar.visibility, toolbar );
+
+                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
+                        this.get('selection').off( 'add remove', this.toggleDetails, this );
+                },
+
+                toolbar: function() {
</ins><span class="cx">                         var frame = this.frame,
</span><span class="cx">                                 toolbar;
</span><span class="cx"> 
</span><span class="lines">@@ -139,25 +166,35 @@
</span><span class="cx"> 
</span><span class="cx">                         frame.toolbar( toolbar );
</span><span class="cx">                         this.get('selection').on( 'add remove', toolbar.visibility, toolbar );
</span><ins>+                },
</ins><span class="cx"> 
</span><ins>+                sidebar: function() {
+                        var frame = this.frame;
+
</ins><span class="cx">                         // Sidebar.
</span><span class="cx">                         frame.sidebar( new media.view.Sidebar({
</span><del>-                                controller: frame,
-                                views: {
-                                        search: new media.view.Search({
-                                                controller: frame,
-                                                model:      this.get('library').props,
-                                                priority:   20
-                                        }),
-
-                                        selection: new media.view.SelectionPreview({
-                                                controller: frame,
-                                                collection: this.get('selection'),
-                                                priority:   40
-                                        })
-                                }
</del><ins>+                                controller: frame
</ins><span class="cx">                         }) );
</span><span class="cx"> 
</span><ins>+                        this.details({ silent: true });
+                        frame.sidebar().add({
+                                search: new media.view.Search({
+                                        controller: frame,
+                                        model:      this.get('library').props,
+                                        priority:   20
+                                }),
+
+                                selection: new media.view.SelectionPreview({
+                                        controller: frame,
+                                        collection: this.get('selection'),
+                                        priority:   40
+                                })
+                        });
+                },
+
+                content: function() {
+                        var frame = this.frame;
+
</ins><span class="cx">                         // Content.
</span><span class="cx">                         frame.content( new media.view.Attachments({
</span><span class="cx">                                 controller: frame,
</span><span class="lines">@@ -165,75 +202,81 @@
</span><span class="cx">                                 // The single `Attachment` view to be used in the `Attachments` view.
</span><span class="cx">                                 AttachmentView: media.view.Attachment.Library
</span><span class="cx">                         }).render() );
</span><ins>+                },
</ins><span class="cx"> 
</span><del>-                        // If we're in a workflow that supports multiple attachments,
-                        // automatically select any uploading attachments.
-                        if ( this.get('multiple') )
-                                wp.Uploader.queue.on( 'add', this.selectUpload, this );
</del><ins>+                selectUpload: function( attachment ) {
+                        this.get('selection').add( attachment );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                deactivate: function() {
-                        var toolbar = this._postLibraryToolbar;
</del><ins>+                details: function( options ) {
+                        var model = this.get('details'),
+                                view;
</ins><span class="cx"> 
</span><del>-                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
-                        this.get('selection').off( 'add remove', toolbar.visibility, toolbar );
</del><ins>+                        if ( model ) {
+                                view = new media.view.Attachment.Details({
+                                        controller: this.frame,
+                                        model:      model,
+                                        priority:   80
+                                });
+                        } else {
+                                view = new Backbone.View();
+                        }
+
+                        if ( ! options || ! options.silent )
+                                view.render();
+
+                        this.frame.sidebar().add( 'details', view, options );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                selectUpload: function( attachment ) {
-                        this.get('selection').add( attachment );
</del><ins>+                toggleDetails: function( model ) {
+                        var details = this.get('details'),
+                                selection = this.get('selection');
+
+                        if ( selection.has( model ) )
+                                this.set( 'details', model );
+                        else if ( selection.length )
+                                this.set( 'details', selection.last() );
+                        else
+                                this.unset('details');
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         // wp.media.controller.Gallery
</span><span class="cx">         // ---------------------------
</span><del>-        media.controller.Gallery = Backbone.Model.extend({
</del><ins>+        media.controller.Gallery = media.controller.Library.extend({
</ins><span class="cx">                 defaults: {
</span><span class="cx">                         id:         'gallery',
</span><del>-                        multiple:   true,
</del><ins>+                        multiple:   false,
</ins><span class="cx">                         describe:   true,
</span><span class="cx">                         title:      l10n.createGallery
</span><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                initialize: function() {
-                        if ( ! this.get('selection') )
-                                this.set( 'selection', new Attachments() );
-
-                        this.on( 'activate', this.activate, this );
</del><ins>+                toolbar: function() {
+                        this.frame.toolbar( new media.view.Toolbar.Gallery({
+                                controller: this.frame,
+                                state:      this
+                        }) );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                activate: function() {
</del><ins>+                sidebar: function() {
</ins><span class="cx">                         var frame = this.frame;
</span><span class="cx"> 
</span><del>-                        // Toolbar.
-                        frame.toolbar( new media.view.Toolbar.Gallery({
-                                controller: frame,
-                                state:      this
-                        }) );
-
</del><span class="cx">                         // Sidebar.
</span><span class="cx">                         frame.sidebar( new media.view.Sidebar({
</span><span class="cx">                                 controller: frame
</span><del>-                        }).render() );
</del><ins>+                        }) );
</ins><span class="cx"> 
</span><del>-                        // Content.
-                        frame.content( new media.view.Attachments({
-                                controller: frame,
-                                collection: this.get('selection'),
</del><ins>+                        this.details();
+                },
+
+                content: function() {
+                        this.frame.content( new media.view.Attachments({
+                                controller: this.frame,
+                                collection: this.get('library'),
</ins><span class="cx">                                 sortable:   true,
</span><span class="cx">                                 // The single `Attachment` view to be used in the `Attachments` view.
</span><span class="cx">                                 AttachmentView: media.view.Attachment.Gallery
</span><span class="cx">                         }).render() );
</span><del>-
-                        // Automatically select any uploading attachments.
-                        wp.Uploader.queue.on( 'add', this.selectUpload, this );
-                },
-
-                deactivate: function() {
-                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
-                },
-
-                selectUpload: function( attachment ) {
-                        this.get('selection').add( attachment );
</del><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -288,41 +331,11 @@
</span><span class="cx">                         var controller = this,
</span><span class="cx">                                 selection = this.options.selection;
</span><span class="cx"> 
</span><del>-                        if ( ! (selection instanceof Attachments) )
-                                selection = this.options.selection = new Attachments( selection );
-
-                        _.extend( selection, {
-                                // Override the selection's add method.
-                                // If the workflow does not support multiple
-                                // selected attachments, reset the selection.
-                                add: function( models, options ) {
-                                        if ( ! controller.state().get('multiple') ) {
-                                                models = _.isArray( models ) ? _.first( models ) : models;
-                                                this.clear( options );
-                                        }
-
-                                        return Attachments.prototype.add.call( this, models, options );
-                                },
-
-                                // Removes all models from the selection.
-                                clear: function( options ) {
-                                        return this.remove( this.models, options );
-                                },
-
-                                // 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 );
-                                },
-
-                                // Create selection.has, which determines if a model
-                                // exists in the collection based on cid and id,
-                                // instead of direct comparison.
-                                has: function( attachment ) {
-                                        return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
-                                }
-                        });
</del><ins>+                        if ( ! (selection instanceof media.model.Selection) ) {
+                                selection = this.options.selection = new media.model.Selection( selection, {
+                                        multiple: this.options.multiple
+                                });
+                        }
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 createStates: function() {
</span><span class="lines">@@ -339,12 +352,12 @@
</span><span class="cx">                         // Add the default states.
</span><span class="cx">                         this.states.add([
</span><span class="cx">                                 new media.controller.Library({
</span><del>-                                        selection:  options.selection,
-                                        collection: media.query( options.library ),
-                                        multiple:   this.options.multiple
</del><ins>+                                        selection: options.selection,
+                                        library:   media.query( options.library ),
+                                        multiple:  this.options.multiple
</ins><span class="cx">                                 }),
</span><span class="cx">                                 new media.controller.Gallery({
</span><del>-                                        selection:  options.selection
</del><ins>+                                        library: options.selection
</ins><span class="cx">                                 })
</span><span class="cx">                         ]);
</span><span class="cx"> 
</span><span class="lines">@@ -630,7 +643,10 @@
</span><span class="cx">                         this.$secondary = $('&lt;div class=&quot;media-toolbar-secondary&quot; /&gt;').prependTo( this.$el );
</span><span class="cx"> 
</span><span class="cx">                         if ( this.options.items )
</span><del>-                                this.add( this.options.items, { silent: true }).render();
</del><ins>+                                this.add( this.options.items, { silent: true });
+
+                        if ( ! this.options.silent )
+                                this.render();
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><span class="lines">@@ -650,11 +666,16 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 add: function( id, view, options ) {
</span><ins>+                        options = options || {};
+
</ins><span class="cx">                         // Accept an object with an `id` : `view` mapping.
</span><span class="cx">                         if ( _.isObject( id ) ) {
</span><span class="cx">                                 _.each( id, function( view, id ) {
</span><del>-                                        this.add( id, view, options );
</del><ins>+                                        this.add( id, view, { silent: true });
</ins><span class="cx">                                 }, this );
</span><ins>+
+                                if ( ! options.silent )
+                                        this.render();
</ins><span class="cx">                                 return this;
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="lines">@@ -666,7 +687,7 @@
</span><span class="cx">                         view.controller = view.controller || this.controller;
</span><span class="cx"> 
</span><span class="cx">                         this._views[ id ] = view;
</span><del>-                        if ( ! options || ! options.silent )
</del><ins>+                        if ( ! options.silent )
</ins><span class="cx">                                 this.render();
</span><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="lines">@@ -777,7 +798,7 @@
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         var state = this.options.state,
</span><span class="cx">                                 editing = state.get('editing'),
</span><del>-                                selection = state.get('selection'),
</del><ins>+                                library = state.get('library'),
</ins><span class="cx">                                 controller = this.options.controller;
</span><span class="cx"> 
</span><span class="cx">                         this.options.items = {
</span><span class="lines">@@ -787,8 +808,8 @@
</span><span class="cx">                                         priority: 40,
</span><span class="cx">                                         click:    function() {
</span><span class="cx">                                                 controller.close();
</span><del>-                                                state.trigger( 'update', selection );
-                                                selection.clear();
</del><ins>+                                                state.trigger( 'update', library );
+                                                library.clear();
</ins><span class="cx">                                                 controller.state('library');
</span><span class="cx">                                         }
</span><span class="cx">                                 },
</span><span class="lines">@@ -921,7 +942,10 @@
</span><span class="cx">                         this._views     = {};
</span><span class="cx"> 
</span><span class="cx">                         if ( this.options.views )
</span><del>-                                this.add( this.options.views, { silent: true }).render();
</del><ins>+                                this.add( this.options.views, { silent: true });
+
+                        if ( ! this.options.silent )
+                                this.render();
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><span class="lines">@@ -949,18 +973,23 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 add: function( id, view, options ) {
</span><ins>+                        options = options || {};
+
</ins><span class="cx">                         // Accept an object with an `id` : `view` mapping.
</span><span class="cx">                         if ( _.isObject( id ) ) {
</span><span class="cx">                                 _.each( id, function( view, id ) {
</span><del>-                                        this.add( id, view, options );
</del><ins>+                                        this.add( id, view, { silent: true });
</ins><span class="cx">                                 }, this );
</span><ins>+
+                                if ( ! options.silent )
+                                        this.render();
</ins><span class="cx">                                 return this;
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                         view.controller = view.controller || this.controller;
</span><span class="cx"> 
</span><span class="cx">                         this._views[ id ] = view;
</span><del>-                        if ( ! options || ! options.silent )
</del><ins>+                        if ( ! options.silent )
</ins><span class="cx">                                 this.render();
</span><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="lines">@@ -989,8 +1018,7 @@
</span><span class="cx">                         'click .attachment-preview':      'toggleSelection',
</span><span class="cx">                         'mouseenter .attachment-preview': 'shrink',
</span><span class="cx">                         'mouseleave .attachment-preview': 'expand',
</span><del>-                        'change .describe':               'describe',
-                        'click .close':                   'toggleSelection'
</del><ins>+                        'change .describe':               'describe'
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 buttons: {},
</span><span class="lines">@@ -1182,9 +1210,13 @@
</span><span class="cx"> 
</span><span class="cx">                 events: (function() {
</span><span class="cx">                         var events = _.clone( media.view.Attachment.prototype.events );
</span><del>-                        delete events['click .attachment-preview'];
</del><ins>+                        events['click .close'] = 'removeFromGallery';
</ins><span class="cx">                         return events;
</span><del>-                }())
</del><ins>+                }()),
+
+                removeFromGallery: function() {
+                        this.controller.state().get('library').remove( this.model );
+                }
</ins><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         /**
</span><span class="lines">@@ -1376,7 +1408,7 @@
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><span class="cx">                         var options = _.clone( this.options ),
</span><del>-                                first, sizes, amount;
</del><ins>+                                last, sizes, amount;
</ins><span class="cx"> 
</span><span class="cx">                         // If nothing is selected, display nothing.
</span><span class="cx">                         if ( ! this.collection.length ) {
</span><span class="lines">@@ -1385,13 +1417,13 @@
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                         options.count = this.collection.length;
</span><del>-                        first = this.collection.first();
-                        sizes = first.get('sizes');
</del><ins>+                        last  = this.collection.last();
+                        sizes = last.get('sizes');
</ins><span class="cx"> 
</span><del>-                        if ( 'image' === first.get('type') )
-                                options.thumbnail = ( sizes &amp;&amp; sizes.thumbnail ) ? sizes.thumbnail.url : first.get('url');
</del><ins>+                        if ( 'image' === last.get('type') )
+                                options.thumbnail = ( sizes &amp;&amp; sizes.thumbnail ) ? sizes.thumbnail.url : last.get('url');
</ins><span class="cx">                         else
</span><del>-                                options.thumbnail =  first.get('icon');
</del><ins>+                                options.thumbnail =  last.get('icon');
</ins><span class="cx"> 
</span><span class="cx">                         this.$el.html( this.template( options ) );
</span><span class="cx">                         return this;
</span><span class="lines">@@ -1490,4 +1522,17 @@
</span><span class="cx">                                 _( options.changes ).chain().keys().each( this.update, this );
</span><span class="cx">                 }
</span><span class="cx">         });
</span><ins>+
+        /**
+         * wp.media.view.Attachment.Details
+         */
+        media.view.Attachment.Details = media.view.Attachment.extend({
+                tagName:   'div',
+                className: 'attachment-details',
+                template:  media.template('attachment-details'),
+
+                events: {
+                        'change .describe': 'describe'
+                }
+        });
</ins><span class="cx"> }(jQuery));
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/media.php (22322 => 22323)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-10-29 07:38:13 UTC (rev 22322)
+++ trunk/wp-includes/media.php        2012-10-29 15:13:02 UTC (rev 22323)
</span><span class="lines">@@ -1305,7 +1305,7 @@
</span><span class="cx"> 
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-uploader-window&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;uploader-window-content&quot;&gt;
</span><del>-                        &lt;h3&gt;&lt;?php _e( 'Drop files here to upload' ); ?&gt;&lt;/h3&gt;
</del><ins>+                        &lt;h3&gt;&lt;?php _e( 'Drop files to upload' ); ?&gt;&lt;/h3&gt;
</ins><span class="cx">                 &lt;/div&gt;
</span><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -1358,6 +1358,39 @@
</span><span class="cx">                 &lt;% } %&gt;
</span><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><ins>+        &lt;script type=&quot;text/html&quot; id=&quot;tmpl-attachment-details&quot;&gt;
+                &lt;div class=&quot;attachment-preview attachment-details-preview type-&lt;%- type %&gt; subtype-&lt;%- subtype %&gt; &lt;%- orientation %&gt;&quot;&gt;
+                        &lt;% if ( uploading ) { %&gt;
+                                &lt;div class=&quot;media-progress-bar&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
+                        &lt;% } else if ( 'image' === type ) { %&gt;
+                                &lt;div class=&quot;thumbnail&quot;&gt;
+                                        &lt;img src=&quot;&lt;%- url %&gt;&quot; draggable=&quot;false&quot; /&gt;
+                                &lt;/div&gt;
+                        &lt;% } else { %&gt;
+                                &lt;div class=&quot;icon-thumbnail&quot;&gt;
+                                        &lt;img src=&quot;&lt;%- icon %&gt;&quot; class=&quot;icon&quot; draggable=&quot;false&quot; /&gt;
+                                        &lt;div class=&quot;filename&quot;&gt;&lt;%- filename %&gt;&lt;/div&gt;
+                                &lt;/div&gt;
+                        &lt;% } %&gt;
+                &lt;/div&gt;
+
+                &lt;% if ( 'image' === type ) { %&gt;
+                        &lt;textarea class=&quot;describe&quot;
+                                placeholder=&quot;&lt;?php esc_attr_e('Describe this image&amp;hellip;'); ?&gt;&quot;
+                                &gt;&lt;%- caption %&gt;&lt;/textarea&gt;
+                &lt;% } else { %&gt;
+                        &lt;textarea class=&quot;describe&quot;
+                                &lt;% if ( 'video' === type ) { %&gt;
+                                        placeholder=&quot;&lt;?php esc_attr_e('Describe this video&amp;hellip;'); ?&gt;&quot;
+                                &lt;% } else if ( 'audio' === type ) { %&gt;
+                                        placeholder=&quot;&lt;?php esc_attr_e('Describe this audio file&amp;hellip;'); ?&gt;&quot;
+                                &lt;% } else { %&gt;
+                                        placeholder=&quot;&lt;?php esc_attr_e('Describe this media file&amp;hellip;'); ?&gt;&quot;
+                                &lt;% } %&gt;
+                                &gt;&lt;%- title %&gt;&lt;/textarea&gt;
+                &lt;% } %&gt;
+        &lt;/script&gt;
+
</ins><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-selection-preview&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;selected-img selected-count-&lt;%- count %&gt;&quot;&gt;
</span><span class="cx">                         &lt;% if ( thumbnail ) { %&gt;
</span></span></pre>
</div>
</div>

</body>
</html>