WordPress.org

Make WordPress Core

Changeset 29056


Ignore:
Timestamp:
07/10/2014 03:49:28 AM (6 years ago)
Author:
helen
Message:

Media grid:

  • Introduce the concept of bulk editing via a separate mode. Like the list view, only bulk deleting is available. The UI is a little funky, especially with the field display toggles there, but refinements will come.
  • Up the max thumbnail size from 120px to 150px.
  • Slide-down panel for the add new uploader. Known issue: it doesn't close again.
  • Remove the toolbar region in the EditAttachment frame.
  • Defer a function call so the grid fills available space.
  • Give feedback when no results are found. Also needs styling.

props ericlewis. see #24716.

Location:
trunk/src/wp-includes
Files:
4 edited

Legend:

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

    r29055 r29056  
    229229.media-toolbar-secondary > .media-button-group {
    230230    margin-right: 10px;
    231     float: left;
    232231    margin-top: 15px;
    233232}
     
    997996    overflow: auto;
    998997    outline: none;
     998    -webkit-transition: 1s ease-in-out;
     999    transition: 1s ease-in-out;
     1000}
     1001
     1002.attachments-browser .uploader-inline:not(.hidden) + .attachments {
     1003    -webkit-transform: translateY( 300px );
     1004    -ms-transform: translateY( 300px );
     1005    transform: translateY( 300px );
     1006}
     1007
     1008.attachments-browser .uploader-inline.hidden {
     1009    display: block;
     1010    -webkit-transform: translateY( -100% );
     1011    -ms-transform: translateY( -100% );
     1012    transform: translateY( -100% );
     1013}
     1014
     1015.attachments-browser .uploader-inline-content {
     1016    top: 0;
    9991017}
    10001018
     
    10821100}
    10831101
    1084 .attachments-browser.hide-sidebar .attachments {
     1102.attachments-browser.hide-sidebar .attachments,
     1103.attachments-browser.hide-sidebar .uploader-inline {
    10851104    right: 0;
    10861105    margin-right: 0;
     
    26582677}
    26592678
     2679.edit-attachment-frame .media-frame-content {
     2680    border-bottom: none;
     2681    bottom: 0;
     2682}
     2683
    26602684/* Hiding this for the moment instead of removing it from the template. */
    26612685.edit-attachment-frame h3 {
  • trunk/src/wp-includes/js/media-grid.js

    r28998 r29056  
    2626            router:  'edit-metadata',
    2727            content: 'edit-metadata',
    28             toolbar: 'toolbar',
    2928
    3029            url:     ''
     
    3332        initialize: function() {
    3433            media.controller._State.prototype.initialize.apply( this, arguments );
    35         },
    36 
    37         activate: function() {
    38             this.listenTo( this.frame, 'toolbar:render:edit-image', this.toolbar );
    3934        },
    4035
     
    4641        deactivate: function() {
    4742            this.stopListening( this.frame );
    48         },
    49 
    50         toolbar: function() {
    51             var frame = this.frame,
    52                 lastState = frame.lastState(),
    53                 previous = lastState && lastState.id;
    54 
    55             frame.toolbar.set( new media.view.Toolbar({
    56                 controller: frame,
    57                 items: {
    58                     back: {
    59                         style: 'primary',
    60                         text:     l10n.back,
    61                         priority: 20,
    62                         click:    function() {
    63                             if ( previous ) {
    64                                 frame.setState( previous );
    65                             } else {
    66                                 frame.close();
    67                             }
    68                         }
    69                     }
    70                 }
    71             }) );
    7243        },
    7344
     
    12697                selection: [],
    12798                library:   {},
    128                 multiple:  false,
     99                multiple:  'add',
    129100                state:     'library',
    130101                uploader:  true,
     
    132103            });
    133104
     105            $(document).on( 'click', '.add-new-h2', _.bind( this.addNewClickHandler, this ) );
    134106            // Ensure core and media grid view UI is enabled.
    135107            this.$el.addClass('wp-core-ui media-grid-view');
     
    187159
    188160        createStates: function() {
    189             var options = this.options;
     161            var options = this.options,
     162                libraryState;
    190163
    191164            if ( this.options.states ) {
     
    193166            }
    194167
     168            libraryState = new media.controller.Library({
     169                library:    media.query( options.library ),
     170                multiple:   options.multiple,
     171                title:      options.title,
     172                priority:   20,
     173                toolbar:    false,
     174                router:     false,
     175                content:    'browse',
     176                filterable: 'mime-types'
     177            });
     178
     179            libraryState._renderTitle = function( view ) {
     180                var text = this.get('title') || '';
     181                view.$el.addClass( 'wrap' );
     182                text += '<a class="add-new-h2">Add New</a>';
     183                view.$el.html( text );
     184            };
    195185            // Add the default states.
    196186            this.states.add([
    197                 new media.controller.Library({
    198                     library:    media.query( options.library ),
    199                     multiple:   options.multiple,
    200                     title:      options.title,
    201                     priority:   20,
    202                     toolbar:    false,
    203                     router:     false,
    204                     content:    'browse',
    205                     filterable: 'mime-types'
    206                 })
     187                libraryState
    207188            ]);
    208189        },
     
    218199        },
    219200
     201        addNewClickHandler: function() {
     202            this.trigger( 'show:upload:attachment' );
     203        },
     204
    220205        editPreviousAttachment: function( currentModel ) {
    221206            var library = this.state().get('library'),
     
    234219         */
    235220        editAttachment: function( model ) {
    236             var library = this.state().get('library'), hasPrevious, hasNext;
    237             if ( library.indexOf( model ) > 0 ) {
    238                 hasPrevious = true;
    239             }
    240             else {
    241                 hasPrevious = false;
    242             }
    243             if ( library.indexOf( model ) < library.length - 1 ) {
    244                 hasNext = true;
    245             }
    246             else {
    247                 hasNext = false;
    248             }
    249 
    250             new media.view.Frame.EditAttachment({
    251                 hasPrevious:    hasPrevious,
    252                 hasNext:        hasNext,
    253                 model:          model,
    254                 gridController: this
    255             });
     221            var library = this.state().get('library');
     222
     223            // Create a new EditAttachment frame, passing along the library and the attachment model.
     224            this.editAttachmentFrame = new media.view.Frame.EditAttachment({
     225                library:        library,
     226                model:          model
     227            });
     228
     229            // Listen to events on the edit attachment frame for triggering pagination callback handlers.
     230            this.listenTo( this.editAttachmentFrame, 'edit:attachment:next', this.editNextAttachment );
     231            this.listenTo( this.editAttachmentFrame, 'edit:attachment:previous', this.editPreviousAttachment );
    256232        },
    257233
     
    364340            }
    365341
     342            this.options.hasPrevious = ( this.options.library.indexOf( this.options.model ) > 0 ) ? true : false;
     343            this.options.hasNext = ( this.options.library.indexOf( this.options.model ) < this.options.library.length - 1 ) ? true : false;
     344
    366345            // Initialize modal container view.
    367346            if ( this.options.modal ) {
     
    472451                return;
    473452            this.modal.close();
    474             this.options.gridController.trigger( 'edit:attachment:previous', this.model );
     453            this.trigger( 'edit:attachment:previous', this.model );
    475454        },
    476455
     
    482461                return;
    483462            this.modal.close();
    484             this.options.gridController.trigger( 'edit:attachment:next', this.model );
    485         }
    486 
     463            this.trigger( 'edit:attachment:next', this.model );
     464        }
    487465    });
    488466
     
    515493    });
    516494
     495    media.view.BulkSelectionToggleButton = media.view.Button.extend({
     496        initialize: function() {
     497            media.view.Button.prototype.initialize.apply( this, arguments );
     498            this.listenTo( this.controller, 'bulk-edit:activate bulk-edit:deactivate', _.bind( this.toggleBulkEditHandler, this ) );
     499        },
     500
     501        click: function() {
     502            var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
     503            media.view.Button.prototype.click.apply( this, arguments );
     504
     505            if ( bulkEditActive ) {
     506                this.controller.deactivateMode( 'bulk-edit' );
     507                this.controller.activateMode( 'edit' );
     508            } else {
     509                this.controller.deactivateMode( 'edit' );
     510                this.controller.activateMode( 'bulk-edit' );
     511            }
     512        },
     513
     514        toggleBulkEditHandler: function() {
     515            var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
     516            if ( bulkEditActive ) {
     517                this.$el.addClass( 'button-primary' );
     518            } else {
     519                this.$el.removeClass( 'button-primary' );
     520                this.controller.state().get('selection').reset();
     521            }
     522        }
     523    });
     524
     525    media.view.BulkDeleteButton = media.view.Button.extend({
     526        initialize: function() {
     527            media.view.Button.prototype.initialize.apply( this, arguments );
     528            this.$el.hide();
     529            this.listenTo( this.controller, 'bulk-edit:activate bulk-edit:deactivate', _.bind( this.visibility, this ) );
     530        },
     531
     532        click: function() {
     533            media.view.Button.prototype.click.apply( this, arguments );
     534            while (this.controller.state().get('selection').length > 0) {
     535                this.controller.state().get('selection').at(0).destroy();
     536            }
     537        },
     538
     539        visibility: function() {
     540            var bulkEditActive = this.controller.activeModes.where( { id: 'bulk-edit' } ).length;
     541            if ( bulkEditActive ) {
     542                this.$el.show();
     543            } else {
     544                this.$el.hide();
     545            }
     546        }
     547    });
     548
    517549}(jQuery, _, Backbone, wp));
  • trunk/src/wp-includes/js/media-views.js

    r28995 r29056  
    666666
    667667            if ( ! this.get('edge') ) {
    668                 this.set( 'edge', 120 );
     668                this.set( 'edge', 150 );
    669669            }
    670670
     
    17861786         */
    17871787        initialize: function() {
    1788 
    17891788            media.view.Frame.prototype.initialize.apply( this, arguments );
    17901789
     
    17931792                modal:    true,
    17941793                uploader: true,
    1795                 mode:     ['select']
     1794                mode:     [ 'select' ]
    17961795            });
    17971796
     
    18081807                this.modal.content( this );
    18091808            }
     1809
     1810            // Store active "modes" that the frame is in. Unrelated to region modes.
     1811            this.activeModes = new Backbone.Collection();
     1812            this.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );
     1813
     1814            _.each( this.options.mode, function( mode ) {
     1815                this.activeModes.add( new Backbone.Model( { id: mode } ) );
     1816            }, this );
    18101817
    18111818            // Force the uploader off if the upload limit has been exceeded or
     
    19731980            window.tb_remove = this._tb_remove;
    19741981            delete this._tb_remove;
     1982        },
     1983
     1984        /**
     1985         * Map activeMode collection events to the frame.
     1986         */
     1987        triggerModeEvents: function( model, collection, options ) {
     1988            var collectionEvent,
     1989                modeEventMap = {
     1990                    add: 'activate',
     1991                    remove: 'deactivate'
     1992                },
     1993                eventToTrigger;
     1994            // Probably a better way to do this.
     1995            _.each( options, function( value, key ) {
     1996                if ( value ) {
     1997                    collectionEvent = key;
     1998                }
     1999            } );
     2000
     2001            if ( ! _.has( modeEventMap, collectionEvent ) )
     2002                return;
     2003
     2004            eventToTrigger = model.get('id') + ':' + modeEventMap[collectionEvent];
     2005            this.trigger( eventToTrigger );
     2006        },
     2007        activateMode: function( mode ) {
     2008            this.activeModes.add( [ { id: mode } ] );
     2009            this.trigger( mode + ':activate' );
     2010        },
     2011        deactivateMode: function( mode ) {
     2012            // Bail if the mode isn't active.
     2013            if ( ! this.activeModes.where( { id: mode } ).length ) {
     2014                return;
     2015            }
     2016            this.activeModes.remove( this.activeModes.where( { id: mode } ) );
     2017            this.trigger( mode + ':deactivate' );
    19752018        }
    19762019    });
     
    46744717
    46754718            // In the grid view, bubble up an edit:attachment event to the controller.
    4676             if ( _.contains( this.controller.options.mode, 'grid' ) ) {
     4719            if ( this.controller.activeModes.where( { id: 'edit' } ).length ) {
    46774720                this.controller.trigger( 'edit:attachment', this.model );
    46784721                return;
     
    50825125                $(window).on( 'resize.attachments', this._resizeCss );
    50835126            }
    5084             this.css();
     5127
     5128            // Call this.css() after this view has been rendered in the DOM so
     5129            // attachments get proper width applied.
     5130            _.defer( this.css, this );
    50855131        },
    50865132
     
    55325578            });
    55335579
     5580            this.listenTo( this.controller, 'show:upload:attachment', _.bind( this.showUploader, this ) );
    55345581            this.createToolbar();
     5582            this.createUploader();
     5583            this.createAttachments();
    55355584            this.updateContent();
    55365585            if ( this.options.sidebar ) {
     
    55695618            // browser view. Is this a use case for doAction( 'add:toolbar-items:attachments-browser', this.toolbar );
    55705619            // which the controller can tap into and add this view?
    5571             if ( _.contains( this.controller.options.mode, 'grid' ) ) {
     5620            if ( this.controller.activeModes.where( { id: 'grid' } ).length ) {
    55725621                LibraryViewSwitcher = media.View.extend({
    55735622                    className: 'view-switch media-grid-view-switch',
     
    55795628                }).render() );
    55805629
     5630                this.toolbar.set( 'bulkSelectionToggleButton', new media.view.BulkSelectionToggleButton({
     5631                    text: 'Bulk Edit',
     5632                    controller: this.controller,
     5633                    priority: -70
     5634                }).render() );
     5635
     5636                this.toolbar.set( 'BulkDeleteButton', new media.view.BulkDeleteButton({
     5637                    text: 'Bulk Delete',
     5638                    controller: this.controller,
     5639                    priority: -69
     5640                }).render() );
     5641
    55815642                this.toolbar.set( 'gridFieldOptions', new media.view.GridFieldOptions({
    55825643                    controller: this.controller,
     
    56365697        updateContent: function() {
    56375698            var view = this;
    5638 
    5639             if( ! this.attachments ) {
    5640                 this.createAttachments();
    5641             }
    5642 
    56435699            if ( ! this.collection.length ) {
    56445700                this.toolbar.get( 'spinner' ).show();
    56455701                this.collection.more().done(function() {
    56465702                    if ( ! view.collection.length ) {
    5647                         view.createUploader();
     5703                        view.attachmentsNoResults.$el.removeClass( 'hidden' );
     5704                    } else {
     5705                        view.attachmentsNoResults.$el.addClass( 'hidden' );
    56485706                    }
    56495707                    view.toolbar.get( 'spinner' ).hide();
    56505708                });
    56515709            } else {
     5710                this.attachmentsNoResults.$el.addClass( 'hidden' );
    56525711                view.toolbar.get( 'spinner' ).hide();
    56535712            }
    56545713        },
    56555714
    5656         removeContent: function() {
    5657             _.each(['attachments','uploader'], function( key ) {
    5658                 if ( this[ key ] ) {
    5659                     this[ key ].remove();
    5660                     delete this[ key ];
    5661                 }
    5662             }, this );
    5663         },
    5664 
    56655715        createUploader: function() {
    5666             this.removeContent();
    5667 
    56685716            this.uploader = new media.view.UploaderInline({
    56695717                controller: this.controller,
     
    56725720            });
    56735721
     5722            this.uploader.$el.addClass( 'hidden' );
    56745723            this.views.add( this.uploader );
    56755724        },
    56765725
     5726        showUploader: function() {
     5727            this.uploader.$el.removeClass( 'hidden' );
     5728        },
     5729
    56775730        createAttachments: function() {
    5678             this.removeContent();
    5679 
    56805731            this.attachments = new media.view.Attachments({
    56815732                controller:           this.controller,
     
    56915742
    56925743            this.views.add( this.attachments );
     5744
     5745            this.attachmentsNoResults = new media.View({
     5746                controller: this.controller
     5747            });
     5748
     5749            this.attachmentsNoResults.$el.addClass( 'hidden' );
     5750            this.attachmentsNoResults.$el.html( 'No media found.' );
     5751
     5752            this.views.add( this.attachmentsNoResults );
     5753
     5754
    56935755        },
    56945756
  • trunk/src/wp-includes/media-template.php

    r28998 r29056  
    277277        <div class="media-frame-router"></div>
    278278        <div class="media-frame-content"></div>
    279         <div class="media-frame-toolbar"></div>
    280279    </script>
    281280
     
    448447                if ( 'uploadedTo' === field ) {
    449448                    if ( data[ field ] ) {
    450                     #><?php _e( 'Uploaded To: ' ) ?>{{ data.uploadedToTitle }}<#
     449                    #><?php _e( 'Uploaded To: ' ) ?><a href="{{ data.uploadedToLink }}">{{ data.uploadedToTitle }}</a><#
    451450                    } else {
    452451                    #><?php _e( 'Unattached' ) ?><#
Note: See TracChangeset for help on using the changeset viewer.