Make WordPress Core

Changeset 22323


Ignore:
Timestamp:
10/29/2012 03:13:02 PM (14 years ago)
Author:
koopersmith
Message:

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 #21390.

Location:
trunk/wp-includes
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/css/media-views.css

    r22322 r22323  
    308308}
    309309
    310 .attachment .thumbnail,
    311 .attachment .thumbnail img {
     310.attachment-preview .thumbnail,
     311.attachment-preview .thumbnail img {
    312312        -webkit-transition-property: width, height, top, left, right, bottom;
    313313        -moz-transition-property:    width, height, top, left, right, bottom;
     
    327327}
    328328
    329 .attachment .thumbnail {
     329.attachment-preview .thumbnail {
    330330        width: 199px;
    331331        height: 199px;
    332332}
    333333
    334 .attachment .thumbnail:after {
     334.attachment-preview .thumbnail:after {
    335335        content: '';
    336336        display: block;
     
    389389}
    390390
    391 .attachment .describe {
     391.media-frame .describe {
    392392        position: relative;
    393393        display: block;
     
    594594
    595595/**
     596 * Attachment Details
     597 */
     598
     599.attachment-details {
     600        padding-top: 20px;
     601}
     602
     603.attachment-details-preview {
     604        cursor: default;
     605}
     606
     607.attachment-details-preview,
     608.attachment-details-preview .thumbnail {
     609        width: auto;
     610        height: auto;
     611        float: left;
     612        position: relative;
     613}
     614
     615.attachment-details-preview .thumbnail img {
     616        max-width: 120px;
     617        max-height: 120px;
     618        display: block;
     619        margin: 0 auto;
     620}
     621
     622.attachment-details .describe {
     623        float: left;
     624        margin: 10px 0 0;
     625}
     626
     627/**
    596628 * Attachment Display Settings
    597629 */
  • trunk/wp-includes/js/media-models.js

    r22320 r22323  
    614614        });
    615615
     616        /**
     617         * wp.media.model.Selection
     618         *
     619         * Used to manage a selection of attachments in the views.
     620         */
     621        media.model.Selection = Attachments.extend({
     622                initialize: function( models, options ) {
     623                        Attachments.prototype.initialize.apply( this, arguments );
     624                        this.multiple = options && options.multiple;
     625                },
     626
     627                // Override the selection's add method.
     628                // If the workflow does not support multiple
     629                // selected attachments, reset the selection.
     630                add: function( models, options ) {
     631                        if ( ! this.multiple ) {
     632                                models = _.isArray( models ) ? _.first( models ) : models;
     633                                this.clear( options );
     634                        }
     635
     636                        return Attachments.prototype.add.call( this, models, options );
     637                },
     638
     639                // Removes all models from the selection.
     640                clear: function( options ) {
     641                        return this.remove( this.models, options );
     642                },
     643
     644                // Override the selection's reset method.
     645                // Always direct items through add and remove,
     646                // as we need them to fire.
     647                reset: function( models, options ) {
     648                        return this.clear( options ).add( models, options );
     649                },
     650
     651                // Create selection.has, which determines if a model
     652                // exists in the collection based on cid and id,
     653                // instead of direct comparison.
     654                has: function( attachment ) {
     655                        return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
     656                }
     657        });
     658
    616659}(jQuery));
  • trunk/wp-includes/js/media-views.js

    r22322 r22323  
    119119
    120120                initialize: function() {
    121                         if ( ! this.get('selection') )
    122                                 this.set( 'selection', new Attachments() );
     121                        if ( ! this.get('selection') ) {
     122                                this.set( 'selection', new media.model.Selection( null, {
     123                                        multiple: this.get('multiple')
     124                                }) );
     125                        }
    123126
    124127                        if ( ! this.get('library') )
     
    126129
    127130                        this.on( 'activate', this.activate, this );
     131                        this.on( 'deactivate', this.deactivate, this );
     132                        this.on( 'change:details', this.details, this );
    128133                },
    129134
    130135                activate: function() {
     136                        this.toolbar();
     137                        this.sidebar();
     138                        this.content();
     139
     140                        // If we're in a workflow that supports multiple attachments,
     141                        // automatically select any uploading attachments.
     142                        if ( this.get('multiple') )
     143                                wp.Uploader.queue.on( 'add', this.selectUpload, this );
     144
     145                        this.get('selection').on( 'add remove', this.toggleDetails, this );
     146                },
     147
     148                deactivate: function() {
     149                        var toolbar = this._postLibraryToolbar;
     150                        if ( toolbar )
     151                                this.get('selection').off( 'add remove', toolbar.visibility, toolbar );
     152
     153                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
     154                        this.get('selection').off( 'add remove', this.toggleDetails, this );
     155                },
     156
     157                toolbar: function() {
    131158                        var frame = this.frame,
    132159                                toolbar;
     
    140167                        frame.toolbar( toolbar );
    141168                        this.get('selection').on( 'add remove', toolbar.visibility, toolbar );
     169                },
     170
     171                sidebar: function() {
     172                        var frame = this.frame;
    142173
    143174                        // Sidebar.
    144175                        frame.sidebar( new media.view.Sidebar({
    145                                 controller: frame,
    146                                 views: {
    147                                         search: new media.view.Search({
    148                                                 controller: frame,
    149                                                 model:      this.get('library').props,
    150                                                 priority:   20
    151                                         }),
    152 
    153                                         selection: new media.view.SelectionPreview({
    154                                                 controller: frame,
    155                                                 collection: this.get('selection'),
    156                                                 priority:   40
    157                                         })
    158                                 }
     176                                controller: frame
    159177                        }) );
     178
     179                        this.details({ silent: true });
     180                        frame.sidebar().add({
     181                                search: new media.view.Search({
     182                                        controller: frame,
     183                                        model:      this.get('library').props,
     184                                        priority:   20
     185                                }),
     186
     187                                selection: new media.view.SelectionPreview({
     188                                        controller: frame,
     189                                        collection: this.get('selection'),
     190                                        priority:   40
     191                                })
     192                        });
     193                },
     194
     195                content: function() {
     196                        var frame = this.frame;
    160197
    161198                        // Content.
     
    166203                                AttachmentView: media.view.Attachment.Library
    167204                        }).render() );
    168 
    169                         // If we're in a workflow that supports multiple attachments,
    170                         // automatically select any uploading attachments.
    171                         if ( this.get('multiple') )
    172                                 wp.Uploader.queue.on( 'add', this.selectUpload, this );
    173                 },
    174 
    175                 deactivate: function() {
    176                         var toolbar = this._postLibraryToolbar;
    177 
    178                         wp.Uploader.queue.off( 'add', this.selectUpload, this );
    179                         this.get('selection').off( 'add remove', toolbar.visibility, toolbar );
    180205                },
    181206
    182207                selectUpload: function( attachment ) {
    183208                        this.get('selection').add( attachment );
     209                },
     210
     211                details: function( options ) {
     212                        var model = this.get('details'),
     213                                view;
     214
     215                        if ( model ) {
     216                                view = new media.view.Attachment.Details({
     217                                        controller: this.frame,
     218                                        model:      model,
     219                                        priority:   80
     220                                });
     221                        } else {
     222                                view = new Backbone.View();
     223                        }
     224
     225                        if ( ! options || ! options.silent )
     226                                view.render();
     227
     228                        this.frame.sidebar().add( 'details', view, options );
     229                },
     230
     231                toggleDetails: function( model ) {
     232                        var details = this.get('details'),
     233                                selection = this.get('selection');
     234
     235                        if ( selection.has( model ) )
     236                                this.set( 'details', model );
     237                        else if ( selection.length )
     238                                this.set( 'details', selection.last() );
     239                        else
     240                                this.unset('details');
    184241                }
    185242        });
     
    187244        // wp.media.controller.Gallery
    188245        // ---------------------------
    189         media.controller.Gallery = Backbone.Model.extend({
     246        media.controller.Gallery = media.controller.Library.extend({
    190247                defaults: {
    191248                        id:         'gallery',
    192                         multiple:   true,
     249                        multiple:   false,
    193250                        describe:   true,
    194251                        title:      l10n.createGallery
    195252                },
    196253
    197                 initialize: function() {
    198                         if ( ! this.get('selection') )
    199                                 this.set( 'selection', new Attachments() );
    200 
    201                         this.on( 'activate', this.activate, this );
    202                 },
    203 
    204                 activate: function() {
    205                         var frame = this.frame;
    206 
    207                         // Toolbar.
    208                         frame.toolbar( new media.view.Toolbar.Gallery({
    209                                 controller: frame,
     254                toolbar: function() {
     255                        this.frame.toolbar( new media.view.Toolbar.Gallery({
     256                                controller: this.frame,
    210257                                state:      this
    211258                        }) );
     259                },
     260
     261                sidebar: function() {
     262                        var frame = this.frame;
    212263
    213264                        // Sidebar.
    214265                        frame.sidebar( new media.view.Sidebar({
    215266                                controller: frame
    216                         }).render() );
    217 
    218                         // Content.
    219                         frame.content( new media.view.Attachments({
    220                                 controller: frame,
    221                                 collection: this.get('selection'),
     267                        }) );
     268
     269                        this.details();
     270                },
     271
     272                content: function() {
     273                        this.frame.content( new media.view.Attachments({
     274                                controller: this.frame,
     275                                collection: this.get('library'),
    222276                                sortable:   true,
    223277                                // The single `Attachment` view to be used in the `Attachments` view.
    224278                                AttachmentView: media.view.Attachment.Gallery
    225279                        }).render() );
    226 
    227                         // Automatically select any uploading attachments.
    228                         wp.Uploader.queue.on( 'add', this.selectUpload, this );
    229                 },
    230 
    231                 deactivate: function() {
    232                         wp.Uploader.queue.off( 'add', this.selectUpload, this );
    233                 },
    234 
    235                 selectUpload: function( attachment ) {
    236                         this.get('selection').add( attachment );
    237280                }
    238281        });
     
    289332                                selection = this.options.selection;
    290333
    291                         if ( ! (selection instanceof Attachments) )
    292                                 selection = this.options.selection = new Attachments( selection );
    293 
    294                         _.extend( selection, {
    295                                 // Override the selection's add method.
    296                                 // If the workflow does not support multiple
    297                                 // selected attachments, reset the selection.
    298                                 add: function( models, options ) {
    299                                         if ( ! controller.state().get('multiple') ) {
    300                                                 models = _.isArray( models ) ? _.first( models ) : models;
    301                                                 this.clear( options );
    302                                         }
    303 
    304                                         return Attachments.prototype.add.call( this, models, options );
    305                                 },
    306 
    307                                 // Removes all models from the selection.
    308                                 clear: function( options ) {
    309                                         return this.remove( this.models, options );
    310                                 },
    311 
    312                                 // Override the selection's reset method.
    313                                 // Always direct items through add and remove,
    314                                 // as we need them to fire.
    315                                 reset: function( models, options ) {
    316                                         return this.clear( options ).add( models, options );
    317                                 },
    318 
    319                                 // Create selection.has, which determines if a model
    320                                 // exists in the collection based on cid and id,
    321                                 // instead of direct comparison.
    322                                 has: function( attachment ) {
    323                                         return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
    324                                 }
    325                         });
     334                        if ( ! (selection instanceof media.model.Selection) ) {
     335                                selection = this.options.selection = new media.model.Selection( selection, {
     336                                        multiple: this.options.multiple
     337                                });
     338                        }
    326339                },
    327340
     
    340353                        this.states.add([
    341354                                new media.controller.Library({
    342                                         selection:  options.selection,
    343                                         collection: media.query( options.library ),
    344                                         multiple:   this.options.multiple
     355                                        selection: options.selection,
     356                                        library:  media.query( options.library ),
     357                                        multiple:  this.options.multiple
    345358                                }),
    346359                                new media.controller.Gallery({
    347                                         selection: options.selection
     360                                        library: options.selection
    348361                                })
    349362                        ]);
     
    631644
    632645                        if ( this.options.items )
    633                                 this.add( this.options.items, { silent: true }).render();
     646                                this.add( this.options.items, { silent: true });
     647
     648                        if ( ! this.options.silent )
     649                                this.render();
    634650                },
    635651
     
    651667
    652668                add: function( id, view, options ) {
     669                        options = options || {};
     670
    653671                        // Accept an object with an `id` : `view` mapping.
    654672                        if ( _.isObject( id ) ) {
    655673                                _.each( id, function( view, id ) {
    656                                         this.add( id, view, options );
     674                                        this.add( id, view, { silent: true });
    657675                                }, this );
     676
     677                                if ( ! options.silent )
     678                                        this.render();
    658679                                return this;
    659680                        }
     
    667688
    668689                        this._views[ id ] = view;
    669                         if ( ! options || ! options.silent )
     690                        if ( ! options.silent )
    670691                                this.render();
    671692                        return this;
     
    778799                        var state = this.options.state,
    779800                                editing = state.get('editing'),
    780                                 selection = state.get('selection'),
     801                                library = state.get('library'),
    781802                                controller = this.options.controller;
    782803
     
    788809                                        click:    function() {
    789810                                                controller.close();
    790                                                 state.trigger( 'update', selection );
    791                                                 selection.clear();
     811                                                state.trigger( 'update', library );
     812                                                library.clear();
    792813                                                controller.state('library');
    793814                                        }
     
    922943
    923944                        if ( this.options.views )
    924                                 this.add( this.options.views, { silent: true }).render();
     945                                this.add( this.options.views, { silent: true });
     946
     947                        if ( ! this.options.silent )
     948                                this.render();
    925949                },
    926950
     
    950974
    951975                add: function( id, view, options ) {
     976                        options = options || {};
     977
    952978                        // Accept an object with an `id` : `view` mapping.
    953979                        if ( _.isObject( id ) ) {
    954980                                _.each( id, function( view, id ) {
    955                                         this.add( id, view, options );
     981                                        this.add( id, view, { silent: true });
    956982                                }, this );
     983
     984                                if ( ! options.silent )
     985                                        this.render();
    957986                                return this;
    958987                        }
     
    961990
    962991                        this._views[ id ] = view;
    963                         if ( ! options || ! options.silent )
     992                        if ( ! options.silent )
    964993                                this.render();
    965994                        return this;
     
    9901019                        'mouseenter .attachment-preview': 'shrink',
    9911020                        'mouseleave .attachment-preview': 'expand',
    992                         'change .describe':               'describe',
    993                         'click .close':                   'toggleSelection'
     1021                        'change .describe':               'describe'
    9941022                },
    9951023
     
    11831211                events: (function() {
    11841212                        var events = _.clone( media.view.Attachment.prototype.events );
    1185                         delete events['click .attachment-preview'];
     1213                        events['click .close'] = 'removeFromGallery';
    11861214                        return events;
    1187                 }())
     1215                }()),
     1216
     1217                removeFromGallery: function() {
     1218                        this.controller.state().get('library').remove( this.model );
     1219                }
    11881220        });
    11891221
     
    13771409                render: function() {
    13781410                        var options = _.clone( this.options ),
    1379                                 first, sizes, amount;
     1411                                last, sizes, amount;
    13801412
    13811413                        // If nothing is selected, display nothing.
     
    13861418
    13871419                        options.count = this.collection.length;
    1388                         first = this.collection.first();
    1389                         sizes = first.get('sizes');
    1390 
    1391                         if ( 'image' === first.get('type') )
    1392                                 options.thumbnail = ( sizes && sizes.thumbnail ) ? sizes.thumbnail.url : first.get('url');
     1420                        last  = this.collection.last();
     1421                        sizes = last.get('sizes');
     1422
     1423                        if ( 'image' === last.get('type') )
     1424                                options.thumbnail = ( sizes && sizes.thumbnail ) ? sizes.thumbnail.url : last.get('url');
    13931425                        else
    1394                                 options.thumbnail =  first.get('icon');
     1426                                options.thumbnail =  last.get('icon');
    13951427
    13961428                        this.$el.html( this.template( options ) );
     
    14911523                }
    14921524        });
     1525
     1526        /**
     1527         * wp.media.view.Attachment.Details
     1528         */
     1529        media.view.Attachment.Details = media.view.Attachment.extend({
     1530                tagName:   'div',
     1531                className: 'attachment-details',
     1532                template:  media.template('attachment-details'),
     1533
     1534                events: {
     1535                        'change .describe': 'describe'
     1536                }
     1537        });
    14931538}(jQuery));
  • trunk/wp-includes/media.php

    r22322 r22323  
    13061306        <script type="text/html" id="tmpl-uploader-window">
    13071307                <div class="uploader-window-content">
    1308                         <h3><?php _e( 'Drop files here to upload' ); ?></h3>
     1308                        <h3><?php _e( 'Drop files to upload' ); ?></h3>
    13091309                </div>
    13101310        </script>
     
    13591359        </script>
    13601360
     1361        <script type="text/html" id="tmpl-attachment-details">
     1362                <div class="attachment-preview attachment-details-preview type-<%- type %> subtype-<%- subtype %> <%- orientation %>">
     1363                        <% if ( uploading ) { %>
     1364                                <div class="media-progress-bar"><div></div></div>
     1365                        <% } else if ( 'image' === type ) { %>
     1366                                <div class="thumbnail">
     1367                                        <img src="<%- url %>" draggable="false" />
     1368                                </div>
     1369                        <% } else { %>
     1370                                <div class="icon-thumbnail">
     1371                                        <img src="<%- icon %>" class="icon" draggable="false" />
     1372                                        <div class="filename"><%- filename %></div>
     1373                                </div>
     1374                        <% } %>
     1375                </div>
     1376
     1377                <% if ( 'image' === type ) { %>
     1378                        <textarea class="describe"
     1379                                placeholder="<?php esc_attr_e('Describe this image&hellip;'); ?>"
     1380                                ><%- caption %></textarea>
     1381                <% } else { %>
     1382                        <textarea class="describe"
     1383                                <% if ( 'video' === type ) { %>
     1384                                        placeholder="<?php esc_attr_e('Describe this video&hellip;'); ?>"
     1385                                <% } else if ( 'audio' === type ) { %>
     1386                                        placeholder="<?php esc_attr_e('Describe this audio file&hellip;'); ?>"
     1387                                <% } else { %>
     1388                                        placeholder="<?php esc_attr_e('Describe this media file&hellip;'); ?>"
     1389                                <% } %>
     1390                                ><%- title %></textarea>
     1391                <% } %>
     1392        </script>
     1393
    13611394        <script type="text/html" id="tmpl-media-selection-preview">
    13621395                <div class="selected-img selected-count-<%- count %>">
Note: See TracChangeset for help on using the changeset viewer.