Make WordPress Core

Changeset 29266


Ignore:
Timestamp:
07/22/2014 04:20:59 PM (12 years ago)
Author:
wonderboymusic
Message:

Media Grid: general JS cleanup.

Props ericlewis.
See #28965.

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

Legend:

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

    r29265 r29266  
    913913
    914914.attachment.details,
    915 .media-grid-view .selected.attachment {
     915.media-frame.mode-grid .selected.attachment {
    916916        -webkit-box-shadow: 0 0 0 1px #fff,
    917917                                0 0 0 5px #1e8cbe;
    … …  
    922922.attachment.details .check,
    923923.attachment.selected .check:focus,
    924 .media-grid-view .attachment.selected .check {
     924.media-frame.mode-grid .attachment.selected .check {
    925925        background-color: #1e8cbe;
    926926        -webkit-box-shadow: 0 0 0 1px #fff,
    … …  
    930930}
    931931
    932 .media-grid-view .attachment .check {
    933         display: block;
    934 }
    935 
    936 .media-grid-view .attachment .check div {
     932.media-frame.mode-grid .attachment .check {
     933        display: block;
     934}
     935
     936.media-frame.mode-grid .attachment .check div {
    937937        background-position: 21px 0;
    938938}
    939939
    940940.attachment.details .check div,
    941 .media-grid-view .attachment.selected .check div {
     941.media-frame.mode-grid .attachment.selected .check div {
    942942        background-position: -21px 0;
    943943}
    … …  
    945945.attachment.details .check:hover div,
    946946.attachment.selected .check:focus div,
    947 .media-grid-view .attachment.selected .check:hover div {
     947.media-frame.mode-grid .attachment.selected .check:hover div {
    948948        background-position: -60px 0;
    949949}
    … …  
    10691069}
    10701070
    1071 .attachment-preview:hover ~ .inline-toolbar {
     1071.attachment-preview:hover + .inline-toolbar,
     1072.inline-toolbar:hover {
    10721073        display: block;
    10731074}
    … …  
    25972598 * Media Grid
    25982599 */
    2599 .media-grid-view,
    2600 .media-grid-view .media-frame-content,
    2601 .media-grid-view .attachments-browser .attachments,
    2602 .media-grid-view .uploader-inline-content {
     2600.media-frame.mode-grid,
     2601.media-frame.mode-grid .media-frame-content,
     2602.media-frame.mode-grid .attachments-browser .attachments,
     2603.media-frame.mode-grid .uploader-inline-content {
    26032604        position: static;
    26042605}
    26052606
    26062607/* Regions we don't use at all */
    2607 .media-grid-view .media-frame-title,
    2608 .media-grid-view .media-frame-toolbar,
    2609 .media-grid-view .media-frame-menu {
    2610         display: none;
    2611 }
    2612 
    2613 .media-grid-view .media-frame-content {
     2608.media-frame.mode-grid .media-frame-title,
     2609.media-frame.mode-grid .media-frame-toolbar,
     2610.media-frame.mode-grid .media-frame-router,
     2611.media-frame.mode-grid .media-frame-menu {
     2612        display: none;
     2613}
     2614
     2615.media-frame.mode-grid .media-frame-content {
    26142616        background-color: transparent;
    26152617        border: none;
    26162618}
    26172619
    2618 .media-grid-view .uploader-inline {
     2620.media-frame.mode-grid .uploader-inline {
    26192621        position: relative;
    26202622        top: auto;
    … …  
    26262628}
    26272629
    2628 .media-grid-view .media-toolbar select {
     2630.media-frame.mode-grid .media-toolbar select {
    26292631        margin-top: 1px;
    26302632        font-size: inherit;
    26312633}
    26322634
    2633 .media-grid-view .attachments-browser .bulk-select {
     2635.media-frame.mode-grid .attachments-browser .bulk-select {
    26342636        display: inline-block;
    26352637}
    … …  
    26402642 * This should be OOCSS'd so both use a shared selector.
    26412643 */
    2642 .media-grid-view .attachments-browser .media-toolbar {
     2644.media-frame.mode-grid .attachments-browser .media-toolbar {
    26432645        background: #fff;
    26442646        -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
    … …  
    26582660}
    26592661
    2660 .media-grid-view input[type="search"] {
     2662.media-frame.mode-grid input[type="search"] {
    26612663        margin: 1px;
    26622664        padding: 3px 5px;
    … …  
    26702672}
    26712673
    2672 .media-grid-view .view-switch {
     2674.media-frame.mode-grid .view-switch {
    26732675        display: inline-block;
    26742676        float: none;
    … …  
    26782680}
    26792681
    2680 .media-grid-view select {
     2682.media-frame.mode-grid select {
    26812683        margin: 0 10px 0 0;
    26822684}
    26832685
    2684 .media-grid-view .spinner {
     2686.media-frame.mode-grid .spinner {
    26852687        margin-top: 15px;
    26862688}
    26872689
    2688 .media-grid-view .attachments-browser {
     2690.media-frame.mode-grid .attachments-browser {
    26892691        padding: 0;
    26902692}
    26912693
    2692 .media-grid-view .attachments-browser .no-media {
     2694.media-frame.mode-grid .attachments-browser .no-media {
    26932695        color: #999;
    26942696        font-size: 18px;
    … …  
    28062808        bottom: 0;
    28072809        top: 56px;
    2808 }
    2809 
    2810 /* Hiding this for the moment instead of removing it from the template. */
    2811 .edit-attachment-frame h3 {
    2812         display: none;
    28132810}
    28142811
    … …  
    29542951
    29552952@media only screen and (max-width: 1120px) {
    2956         .media-grid-view .attachments-browser .media-toolbar-primary,
    2957         .media-grid-view .attachments-browser .media-toolbar-secondary {
     2953        .media-frame.mode-grid .attachments-browser .media-toolbar-primary,
     2954        .media-frame.mode-grid .attachments-browser .media-toolbar-secondary {
    29582955                float: none;
    29592956        }
    29602957
    2961         .media-grid-view input[type="search"] {
     2958        .media-frame.mode-grid input[type="search"] {
    29622959                margin: 20px 0;
    29632960                position: static;
  • trunk/src/wp-includes/js/media-grid.js

    r29263 r29266  
    11/* global _wpMediaViewsL10n, MediaElementPlayer, _wpMediaGridSettings, confirm */
    22(function($, _, Backbone, wp) {
     3        // Local reference to the WordPress media namespace.
    34        var media = wp.media, l10n;
    45
    5         // Link any localized strings.
     6        // Link localized strings and settings.
    67        if ( media.view.l10n ) {
    78                l10n = media.view.l10n;
    … …  
    1213
    1314        /**
     15         * wp.media.controller.EditAttachmentMetadata
     16         *
    1417         * A state for editing an attachment's metadata.
    1518         *
    … …  
    2124                defaults: {
    2225                        id:      'edit-attachment',
     26                        // Title string passed to the frame's title region view.
    2327                        title:   l10n.attachmentDetails,
    2428                        // Region mode defaults.
     29                        content: 'edit-metadata',
    2530                        menu:    false,
    26                         content: 'edit-metadata',
    27 
    28                         url:     ''
    29                 },
    30 
    31                 _ready: function() {},
    32 
    33                 /**
    34                  * Override media.controller.State._postActivate, since this state doesn't
    35                  * include the regions expected there.
    36                  */
    37                 _postActivate: function() {
    38                         this.frame.on( 'title:render:default', this._renderTitle, this );
    39 
    40                         this._title();
    41                         this._content();
    42                 },
    43 
    44                 /**
    45                  * @access private
    46                  */
    47                 _title: function() {
    48                         this.frame.title.render( this.get('titleMode') || 'default' );
    49                 },
    50                 /**
    51                  * @access private
    52                  */
    53                 _renderTitle: function( view ) {
    54                         view.$el.text( this.get('title') || '' );
    55                 },
    56 
    57                 _content: function() {
    58                         var mode = this.get( 'content' );
    59                         if ( mode ) {
    60                                 this.frame.content.render( mode );
    61                         }
     31                        toolbar: false,
     32                        router:  false
    6233                }
    6334        });
    … …  
    8859                                modal:     false,
    8960                                selection: [],
    90                                 library:   {},
     61                                library:   {}, // Options hash for the query to the media library.
    9162                                multiple:  'add',
    9263                                state:     'library',
    9364                                uploader:  true,
    94                                 mode:      [ 'grid', 'edit' ]
     65                                mode:      [ 'grid' ]
    9566                        });
    9667
    9768                        $(document).on( 'click', '.add-new-h2', _.bind( this.addNewClickHandler, this ) );
    98                         $(document).on( 'screen:options:open', _.bind( this.screenOptionsOpen, this ) );
    99                         $(document).on( 'screen:options:close', _.bind( this.screenOptionsClose, this ) );
    10069
    10170                        // Ensure core and media grid view UI is enabled.
    102                         this.$el.addClass('wp-core-ui media-grid-view');
     71                        this.$el.addClass('wp-core-ui');
    10372
    10473                        // Force the uploader off if the upload limit has been exceeded or
    … …  
    12392                        }
    12493
    125                         /**
    126                          * call 'initialize' directly on the parent class
    127                          */
     94                        // Call 'initialize' directly on the parent class.
    12895                        media.view.MediaFrame.prototype.initialize.apply( this, arguments );
    12996
    130                         // Since we're not using the default modal built into
    131                         // a media frame, append our $element to the supplied container.
     97                        // Append the frame view directly the supplied container.
    13298                        this.$el.appendTo( this.options.container );
    13399
    134                         this.createSelection();
    135100                        this.createStates();
    136                         this.bindHandlers();
     101                        this.bindRegionModeHandlers();
    137102                        this.render();
    138103
    … …  
    146111                        }, 1000 ) );
    147112
     113                        // This is problematic.
    148114                        _.delay( _.bind( this.createRouter, this ), 1000 );
    149                 },
    150 
    151                 screenOptionsOpen: function() {
    152                         this.$el.addClass( 'media-grid-view-options' );
    153                 },
    154 
    155                 screenOptionsClose: function() {
    156                         this.$el.removeClass( 'media-grid-view-options' );
    157115                },
    158116
    … …  
    169127                },
    170128
    171                 createSelection: function() {
    172                         var selection = this.options.selection;
    173 
    174                         if ( ! (selection instanceof media.model.Selection) ) {
    175                                 this.options.selection = new media.model.Selection( selection, {
    176                                         multiple: this.options.multiple
    177                                 });
    178                         }
    179 
    180                         this._selection = {
    181                                 attachments: new media.model.Attachments(),
    182                                 difference: []
    183                         };
    184                 },
    185 
     129                /**
     130                 * Create the default states for the frame.
     131                 */
    186132                createStates: function() {
    187133                        var options = this.options;
    … …  
    197143                                        multiple:   options.multiple,
    198144                                        title:      options.title,
    199                                         priority:   20,
    200 
    201                                         router:     false,
    202145                                        content:    'browse',
    203146
    … …  
    207150                },
    208151
    209                 bindHandlers: function() {
     152                /**
     153                 * Bind region mode activation events to proper handlers.
     154                 */
     155                bindRegionModeHandlers: function() {
    210156                        this.on( 'content:create:browse', this.browseContent, this );
    211                         this.on( 'content:render:edit-image', this.editImageContent, this );
    212157
    213158                        // Handle a frame-level event for editing an attachment.
    214                         this.on( 'edit:attachment', this.editAttachment, this );
    215                 },
    216 
     159                        this.on( 'edit:attachment', this.openEditAttachmentModal, this );
     160                },
     161
     162                /**
     163                 * Click handler for the `Add New` button.
     164                 */
    217165                addNewClickHandler: function( event ) {
    218166                        event.preventDefault();
    … …  
    223171                 * Open the Edit Attachment modal.
    224172                 */
    225                 editAttachment: function( model ) {
     173                openEditAttachmentModal: function( model ) {
    226174                        // Create a new EditAttachment frame, passing along the library and the attachment model.
    227175                        wp.media( {
    … …  
    234182
    235183                /**
    236                  * Content
     184                 * Create an attachments browser view within the content region.
    237185                 *
    238                  * @param {Object} content
     186                 * @param {Object} contentRegion Basic object with a `view` property, which
     187                 *                               should be set with the proper region view.
    239188                 * @this wp.media.controller.Region
    240189                 */
    241                 browseContent: function( content ) {
     190                browseContent: function( contentRegion ) {
    242191                        var state = this.state();
    243192
    244193                        // Browse our library of attachments.
    245                         content.view = new media.view.AttachmentsBrowser({
     194                        contentRegion.view = new media.view.AttachmentsBrowser({
    246195                                controller: this,
    247196                                collection: state.get('library'),
    … …  
    260209                                AttachmentView: state.get('AttachmentView')
    261210                        });
    262                 },
    263 
    264                 editImageContent: function() {
    265                         var image = this.state().get('image'),
    266                                 view = new media.view.EditImage( { model: image, controller: this } ).render();
    267 
    268                         this.content.set( view );
    269 
    270                         // after creating the wrapper view, load the actual editor via an ajax call
    271                         view.loadEditor();
    272 
    273                 }
    274         });
    275 
     211                }
     212        });
     213
     214        /**
     215         * A similar view to media.view.Attachment.Details
     216         * for use in the Edit Attachment modal.
     217         *
     218         * @constructor
     219         * @augments wp.media.view.Attachment.Details
     220         * @augments wp.media.view.Attachment
     221         * @augments wp.media.View
     222         * @augments wp.Backbone.View
     223         * @augments Backbone.View
     224         */
    276225        media.view.Attachment.Details.TwoColumn = media.view.Attachment.Details.extend({
    277                 template: wp.template( 'attachment-details-two-column' ),
    278 
    279                 events: {
    280                         'change [data-setting]':          'updateSetting',
    281                         'change [data-setting] input':    'updateSetting',
    282                         'change [data-setting] select':   'updateSetting',
    283                         'change [data-setting] textarea': 'updateSetting',
    284                         'click .delete-attachment':       'deleteAttachment',
    285                         'click .trash-attachment':        'trashAttachment',
    286                         'click .edit-attachment':         'editAttachment',
    287                         'click .refresh-attachment':      'refreshAttachment',
    288                         'click .edit-image':              'handleEditImageClick'
    289                 },
    290 
    291                 initialize: function() {
    292                         if ( ! this.model ) {
    293                                 return;
    294                         }
    295 
    296                         this.$el.attr('aria-label', this.model.get( 'title' ) ).attr( 'aria-checked', false );
    297 
    298                         this.model.on( 'change:title',   this._syncTitle, this );
    299                         this.model.on( 'change:caption', this._syncCaption, this );
    300                         this.model.on( 'change:percent', this.progress, this );
    301                         this.model.on( 'change:album',   this._syncAlbum, this );
    302                         this.model.on( 'change:artist',  this._syncArtist, this );
    303 
    304                         // Update the selection.
    305                         this.model.on( 'add', this.select, this );
    306                         this.model.on( 'remove', this.deselect, this );
    307                         this.model.on( 'sync', this.afterDelete, this );
    308                 },
     226                template: media.template( 'attachment-details-two-column' ),
    309227
    310228                preDestroy: function( event ) {
    … …  
    325243                },
    326244
    327                 handleEditImageClick: function() {
     245                editAttachment: function( event ) {
     246                        event.preventDefault();
    328247                        this.controller.setState( 'edit-image' );
    329248                },
     249
     250                /**
     251                 * Noop this from parent class, doesn't apply here.
     252                 */
     253                toggleSelectionHandler: function() {},
    330254
    331255                afterDelete: function( model ) {
    … …  
    352276
    353277                        media.mixin.removeAllPlayers();
    354                         $( 'audio, video', this.$el ).each( function (i, elem) {
     278                        this.$( 'audio, video' ).each( function (i, elem) {
    355279                                var el = media.view.MediaDetails.prepareSrc( elem );
    356280                                new MediaElementPlayer( el, media.mixin.mejsSettings );
    … …  
    360284
    361285        /**
    362          * A router for handling the browser history and application state
     286         * A router for handling the browser history and application state.
     287         *
     288         * @constructor
     289         * @augments Backbone.Router
    363290         */
    364291        media.view.MediaFrame.Manage.Router = Backbone.Router.extend({
    365292                routes: {
    366                         'upload.php?item=:slug':    'showitem',
     293                        'upload.php?item=:slug':    'showItem',
    367294                        'upload.php?search=:query': 'search',
    368295                        ':default':                 'defaultRoute'
    … …  
    382309
    383310                // Show the modal with a specific item
    384                 showitem: function( query ) {
     311                showItem: function( query ) {
    385312                        var library = media.frame.state().get('library');
    386313
    … …  
    411338         *
    412339         * Requires an attachment model to be passed in the options hash under `model`.
     340         *
     341         * @constructor
     342         * @augments wp.media.view.Frame
     343         * @augments wp.media.View
     344         * @augments wp.Backbone.View
     345         * @augments Backbone.View
     346         * @mixes wp.media.controller.StateMachine
    413347         */
    414348        media.view.MediaFrame.EditAttachments = media.view.MediaFrame.extend({
    … …  
    444378                        this.createStates();
    445379
    446                         this.on( 'content:render:edit-metadata', this.editMetadataContent, this );
    447                         this.on( 'content:render:edit-image', this.editImageContentUgh, this );
     380                        this.on( 'content:create:edit-metadata', this.editMetadataMode, this );
     381                        this.on( 'content:create:edit-image', this.editImageMode, this );
    448382                        this.on( 'close', this.detach );
    449383
    … …  
    474408                                } );
    475409
     410                                // Set this frame as the modal's content.
    476411                                this.modal.content( this );
    477412                                this.modal.open();
    … …  
    497432                /**
    498433                 * Content region rendering callback for the `edit-metadata` mode.
    499                  */
    500                 editMetadataContent: function() {
    501                         var view = new media.view.Attachment.Details.TwoColumn({
     434                 *
     435                 * @param {Object} contentRegion Basic object with a `view` property, which
     436                 *                               should be set with the proper region view.
     437                 */
     438                editMetadataMode: function( contentRegion ) {
     439                        contentRegion.view = new media.view.Attachment.Details.TwoColumn({
    502440                                controller: this,
    503441                                model:      this.model
    504442                        });
    505                         this.content.set( view );
    506443                        // Update browser url when navigating media details
    507444                        if ( this.model ) {
    508445                                this.gridRouter.navigate( this.gridRouter.baseUrl( '?item=' + this.model.id ) );
    509                         } else {
    510                                 this.resetRoute();
    511                         }
    512                 },
    513 
    514                 /**
    515                  * For some reason the view doesn't exist in the DOM yet, don't have the
    516                  * patience to track this down right now.
    517                  */
    518                 editImageContentUgh: function() {
    519                         _.defer( _.bind( this.editImageContent, this ) );
     446                        }
    520447                },
    521448
    522449                /**
    523450                 * Render the EditImage view into the frame's content region.
    524                  */
    525                 editImageContent: function() {
    526                         var view = new media.view.EditImage( { model: this.model, controller: this } ).render();
    527 
    528                         this.content.set( view );
    529 
    530                         // after creating the wrapper view, load the actual editor via an ajax call
    531                         view.loadEditor();
    532                 },
    533 
     451                 *
     452                 * @param {Object} contentRegion Basic object with a `view` property, which
     453                 *                               should be set with the proper region view.
     454                 */
     455                editImageMode: function( contentRegion ) {
     456                        contentRegion.view = new media.view.EditImage( { model: this.model, controller: this } );
     457                        // Defer a call to load the editor, which
     458                        // requires DOM elements to exist.
     459                        _.defer( _.bind( contentRegion.view.loadEditor, contentRegion.view ) );
     460                },
     461
     462                /**
     463                 * Close this modal and immediately open another one.
     464                 *
     465                 * Allows for quickly swapping out the attachment being edited.
     466                 */
    534467                resetContent: function() {
    535468                        this.modal.close();
    … …  
    604537        });
    605538
     539        /**
     540         * Controller for bulk selection.
     541         */
    606542        media.view.BulkSelection = media.View.extend({
    607543                className: 'bulk-select',
    … …  
    629565        });
    630566
     567        /**
     568         * Bulk Selection dropdown view.
     569         *
     570         * @constructor
     571         * @augments wp.media.View
     572         * @augments wp.Backbone.View
     573         * @augments Backbone.View
     574         */
    631575        media.view.BulkSelectionActionDropdown = media.View.extend({
    632576                tagName:   'select',
    … …  
    638582                                .append( $('<option></option>').val( 'delete' ).html( l10n.deletePermanently ) );
    639583                        this.$el.prop( 'disabled', true );
    640                         this.$el.on( 'change', _.bind( this.toggleChange, this ) );
    641                 },
    642 
    643                 toggleChange: function() {
     584                        this.$el.on( 'change', _.bind( this.changeHandler, this ) );
     585                },
     586
     587                /**
     588                 * Change handler for the dropdown.
     589                 *
     590                 * Sets the bulk selection controller's currentAction.
     591                 */
     592                changeHandler: function() {
    644593                        this.controller.model.set( { 'currentAction': this.$el.val() } );
    645594                },
     595
     596                /**
     597                 * Enable or disable the dropdown if attachments have been selected.
     598                 */
    646599                enabled: function() {
    647600                        var disabled = ! this.controller.controller.state().get('selection').length;
    … …  
    650603        });
    651604
     605        /**
     606         * Bulk Selection dropdown view.
     607         *
     608         * @constructor
     609         *
     610         * @augments wp.media.view.Button
     611         * @augments wp.media.View
     612         * @augments wp.Backbone.View
     613         * @augments Backbone.View
     614         */
    652615        media.view.BulkSelectionActionButton = media.view.Button.extend({
    653616                tagName: 'button',
    … …  
    659622                        this.listenTo( this.controller.controller.state().get( 'selection' ), 'add remove reset', _.bind( this.enabled, this ) );
    660623                },
    661 
     624                /**
     625                 * Button click handler.
     626                 */
    662627                click: function() {
    663628                        var selection = this.controller.controller.state().get('selection');
    … …  
    673638                        this.enabled();
    674639                },
    675 
     640                /**
     641                 * Enable or disable the button depending if a bulk action is selected
     642                 * in the bulk select dropdown, and if attachments have been selected.
     643                 */
    676644                enabled: function() {
    677645                        var currentAction = this.controller.model.get( 'currentAction' ),
  • trunk/src/wp-includes/js/media-views.js

    r29220 r29266  
    16861686        media.view.Frame = media.View.extend({
    16871687                initialize: function() {
     1688                        _.defaults( this.options, {
     1689                                mode: [ 'select' ]
     1690                        });
    16881691                        this._createRegions();
    16891692                        this._createStates();
     1693                        this._createModes();
    16901694                },
    16911695
    … …  
    17221726                        }
    17231727                },
     1728                _createModes: function() {
     1729                        // Store active "modes" that the frame is in. Unrelated to region modes.
     1730                        this.activeModes = new Backbone.Collection();
     1731                        this.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );
     1732
     1733                        _.each( this.options.mode, function( mode ) {
     1734                                this.activateMode( mode );
     1735                        }, this );
     1736                },
    17241737                /**
    17251738                 * @returns {wp.media.view.Frame} Returns itself to allow chaining
    … …  
    17281741                        this.states.invoke( 'trigger', 'reset' );
    17291742                        return this;
    1730                 }
    1731         });
    1732 
    1733         // Make the `Frame` a `StateMachine`.
    1734         _.extend( media.view.Frame.prototype, media.controller.StateMachine.prototype );
    1735 
    1736         /**
    1737          * wp.media.view.MediaFrame
    1738          *
    1739          * Type of frame used to create the media modal.
    1740          *
    1741          * @constructor
    1742          * @augments wp.media.view.Frame
    1743          * @augments wp.media.View
    1744          * @augments wp.Backbone.View
    1745          * @augments Backbone.View
    1746          * @mixes wp.media.controller.StateMachine
    1747          */
    1748         media.view.MediaFrame = media.view.Frame.extend({
    1749                 className: 'media-frame',
    1750                 template:  media.template('media-frame'),
    1751                 regions:   ['menu','title','content','toolbar','router'],
    1752 
    1753                 /**
    1754                  * @global wp.Uploader
    1755                  */
    1756                 initialize: function() {
    1757                         media.view.Frame.prototype.initialize.apply( this, arguments );
    1758 
    1759                         _.defaults( this.options, {
    1760                                 title:    '',
    1761                                 modal:    true,
    1762                                 uploader: true,
    1763                                 mode:     [ 'select' ]
    1764                         });
    1765 
    1766                         // Ensure core UI is enabled.
    1767                         this.$el.addClass('wp-core-ui');
    1768 
    1769                         // Initialize modal container view.
    1770                         if ( this.options.modal ) {
    1771                                 this.modal = new media.view.Modal({
    1772                                         controller: this,
    1773                                         title:      this.options.title
    1774                                 });
    1775 
    1776                                 this.modal.content( this );
    1777                         }
    1778 
    1779                         // Store active "modes" that the frame is in. Unrelated to region modes.
    1780                         this.activeModes = new Backbone.Collection();
    1781                         this.activeModes.on( 'add remove reset', _.bind( this.triggerModeEvents, this ) );
    1782 
    1783                         _.each( this.options.mode, function( mode ) {
    1784                                 this.activateMode( mode );
    1785                         }, this );
    1786 
    1787                         // Force the uploader off if the upload limit has been exceeded or
    1788                         // if the browser isn't supported.
    1789                         if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {
    1790                                 this.options.uploader = false;
    1791                         }
    1792 
    1793                         // Initialize window-wide uploader.
    1794                         if ( this.options.uploader ) {
    1795                                 this.uploader = new media.view.UploaderWindow({
    1796                                         controller: this,
    1797                                         uploader: {
    1798                                                 dropzone:  this.modal ? this.modal.$el : this.$el,
    1799                                                 container: this.$el
    1800                                         }
    1801                                 });
    1802                                 this.views.set( '.media-frame-uploader', this.uploader );
    1803                         }
    1804 
    1805                         this.on( 'attach', _.bind( this.views.ready, this.views ), this );
    1806 
    1807                         // Bind default title creation.
    1808                         this.on( 'title:create:default', this.createTitle, this );
    1809                         this.title.mode('default');
    1810 
    1811                         // Bind default menu.
    1812                         this.on( 'menu:create:default', this.createMenu, this );
    1813                 },
    1814                 /**
    1815                  * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
    1816                  */
    1817                 render: function() {
    1818                         // Activate the default state if no active state exists.
    1819                         if ( ! this.state() && this.options.state ) {
    1820                                 this.setState( this.options.state );
    1821                         }
    1822                         /**
    1823                          * call 'render' directly on the parent class
    1824                          */
    1825                         return media.view.Frame.prototype.render.apply( this, arguments );
    1826                 },
    1827                 /**
    1828                  * @param {Object} title
    1829                  * @this wp.media.controller.Region
    1830                  */
    1831                 createTitle: function( title ) {
    1832                         title.view = new media.View({
    1833                                 controller: this,
    1834                                 tagName: 'h1'
    1835                         });
    1836                 },
    1837                 /**
    1838                  * @param {Object} menu
    1839                  * @this wp.media.controller.Region
    1840                  */
    1841                 createMenu: function( menu ) {
    1842                         menu.view = new media.view.Menu({
    1843                                 controller: this
    1844                         });
    1845                 },
    1846                 /**
    1847                  * @param {Object} toolbar
    1848                  * @this wp.media.controller.Region
    1849                  */
    1850                 createToolbar: function( toolbar ) {
    1851                         toolbar.view = new media.view.Toolbar({
    1852                                 controller: this
    1853                         });
    1854                 },
    1855                 /**
    1856                  * @param {Object} router
    1857                  * @this wp.media.controller.Region
    1858                  */
    1859                 createRouter: function( router ) {
    1860                         router.view = new media.view.Router({
    1861                                 controller: this
    1862                         });
    1863                 },
    1864                 /**
    1865                  * @param {Object} options
    1866                  */
    1867                 createIframeStates: function( options ) {
    1868                         var settings = media.view.settings,
    1869                                 tabs = settings.tabs,
    1870                                 tabUrl = settings.tabUrl,
    1871                                 $postId;
    1872 
    1873                         if ( ! tabs || ! tabUrl ) {
    1874                                 return;
    1875                         }
    1876 
    1877                         // Add the post ID to the tab URL if it exists.
    1878                         $postId = $('#post_ID');
    1879                         if ( $postId.length ) {
    1880                                 tabUrl += '&post_id=' + $postId.val();
    1881                         }
    1882 
    1883                         // Generate the tab states.
    1884                         _.each( tabs, function( title, id ) {
    1885                                 this.state( 'iframe:' + id ).set( _.defaults({
    1886                                         tab:     id,
    1887                                         src:     tabUrl + '&tab=' + id,
    1888                                         title:   title,
    1889                                         content: 'iframe',
    1890                                         menu:    'default'
    1891                                 }, options ) );
    1892                         }, this );
    1893 
    1894                         this.on( 'content:create:iframe', this.iframeContent, this );
    1895                         this.on( 'menu:render:default', this.iframeMenu, this );
    1896                         this.on( 'open', this.hijackThickbox, this );
    1897                         this.on( 'close', this.restoreThickbox, this );
    1898                 },
    1899 
    1900                 /**
    1901                  * @param {Object} content
    1902                  * @this wp.media.controller.Region
    1903                  */
    1904                 iframeContent: function( content ) {
    1905                         this.$el.addClass('hide-toolbar');
    1906                         content.view = new media.view.Iframe({
    1907                                 controller: this
    1908                         });
    1909                 },
    1910 
    1911                 iframeMenu: function( view ) {
    1912                         var views = {};
    1913 
    1914                         if ( ! view ) {
    1915                                 return;
    1916                         }
    1917 
    1918                         _.each( media.view.settings.tabs, function( title, id ) {
    1919                                 views[ 'iframe:' + id ] = {
    1920                                         text: this.state( 'iframe:' + id ).get('title'),
    1921                                         priority: 200
    1922                                 };
    1923                         }, this );
    1924 
    1925                         view.set( views );
    1926                 },
    1927 
    1928                 hijackThickbox: function() {
    1929                         var frame = this;
    1930 
    1931                         if ( ! window.tb_remove || this._tb_remove ) {
    1932                                 return;
    1933                         }
    1934 
    1935                         this._tb_remove = window.tb_remove;
    1936                         window.tb_remove = function() {
    1937                                 frame.close();
    1938                                 frame.reset();
    1939                                 frame.setState( frame.options.state );
    1940                                 frame._tb_remove.call( window );
    1941                         };
    1942                 },
    1943 
    1944                 restoreThickbox: function() {
    1945                         if ( ! this._tb_remove ) {
    1946                                 return;
    1947                         }
    1948 
    1949                         window.tb_remove = this._tb_remove;
    1950                         delete this._tb_remove;
    1951                 },
    1952 
     1743                },
    19531744                /**
    19541745                 * Map activeMode collection events to the frame.
    … …  
    19681759                        } );
    19691760
    1970                         if ( ! _.has( modeEventMap, collectionEvent ) )
     1761                        if ( ! _.has( modeEventMap, collectionEvent ) ) {
    19711762                                return;
     1763                        }
    19721764
    19731765                        eventToTrigger = model.get('id') + ':' + modeEventMap[collectionEvent];
    … …  
    19861778                        }
    19871779                        this.activeModes.add( [ { id: mode } ] );
    1988                         // Add a css class to the frame for anything that needs to be styled
    1989                         // for the mode.
     1780                        // Add a CSS class to the frame so elements can be styled for the mode.
    19901781                        this.$el.addClass( 'mode-' + mode );
    19911782                        /**
    … …  
    20281819                isModeActive: function( mode ) {
    20291820                        return Boolean( this.activeModes.where( { id: mode } ).length );
     1821                }
     1822        });
     1823
     1824        // Make the `Frame` a `StateMachine`.
     1825        _.extend( media.view.Frame.prototype, media.controller.StateMachine.prototype );
     1826
     1827        /**
     1828         * wp.media.view.MediaFrame
     1829         *
     1830         * Type of frame used to create the media modal.
     1831         *
     1832         * @constructor
     1833         * @augments wp.media.view.Frame
     1834         * @augments wp.media.View
     1835         * @augments wp.Backbone.View
     1836         * @augments Backbone.View
     1837         * @mixes wp.media.controller.StateMachine
     1838         */
     1839        media.view.MediaFrame = media.view.Frame.extend({
     1840                className: 'media-frame',
     1841                template:  media.template('media-frame'),
     1842                regions:   ['menu','title','content','toolbar','router'],
     1843
     1844                /**
     1845                 * @global wp.Uploader
     1846                 */
     1847                initialize: function() {
     1848                        media.view.Frame.prototype.initialize.apply( this, arguments );
     1849
     1850                        _.defaults( this.options, {
     1851                                title:    '',
     1852                                modal:    true,
     1853                                uploader: true
     1854                        });
     1855
     1856                        // Ensure core UI is enabled.
     1857                        this.$el.addClass('wp-core-ui');
     1858
     1859                        // Initialize modal container view.
     1860                        if ( this.options.modal ) {
     1861                                this.modal = new media.view.Modal({
     1862                                        controller: this,
     1863                                        title:      this.options.title
     1864                                });
     1865
     1866                                this.modal.content( this );
     1867                        }
     1868
     1869                        // Force the uploader off if the upload limit has been exceeded or
     1870                        // if the browser isn't supported.
     1871                        if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {
     1872                                this.options.uploader = false;
     1873                        }
     1874
     1875                        // Initialize window-wide uploader.
     1876                        if ( this.options.uploader ) {
     1877                                this.uploader = new media.view.UploaderWindow({
     1878                                        controller: this,
     1879                                        uploader: {
     1880                                                dropzone:  this.modal ? this.modal.$el : this.$el,
     1881                                                container: this.$el
     1882                                        }
     1883                                });
     1884                                this.views.set( '.media-frame-uploader', this.uploader );
     1885                        }
     1886
     1887                        this.on( 'attach', _.bind( this.views.ready, this.views ), this );
     1888
     1889                        // Bind default title creation.
     1890                        this.on( 'title:create:default', this.createTitle, this );
     1891                        this.title.mode('default');
     1892
     1893                        // Bind default menu.
     1894                        this.on( 'menu:create:default', this.createMenu, this );
     1895                },
     1896                /**
     1897                 * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
     1898                 */
     1899                render: function() {
     1900                        // Activate the default state if no active state exists.
     1901                        if ( ! this.state() && this.options.state ) {
     1902                                this.setState( this.options.state );
     1903                        }
     1904                        /**
     1905                         * call 'render' directly on the parent class
     1906                         */
     1907                        return media.view.Frame.prototype.render.apply( this, arguments );
     1908                },
     1909                /**
     1910                 * @param {Object} title
     1911                 * @this wp.media.controller.Region
     1912                 */
     1913                createTitle: function( title ) {
     1914                        title.view = new media.View({
     1915                                controller: this,
     1916                                tagName: 'h1'
     1917                        });
     1918                },
     1919                /**
     1920                 * @param {Object} menu
     1921                 * @this wp.media.controller.Region
     1922                 */
     1923                createMenu: function( menu ) {
     1924                        menu.view = new media.view.Menu({
     1925                                controller: this
     1926                        });
     1927                },
     1928                /**
     1929                 * @param {Object} toolbar
     1930                 * @this wp.media.controller.Region
     1931                 */
     1932                createToolbar: function( toolbar ) {
     1933                        toolbar.view = new media.view.Toolbar({
     1934                                controller: this
     1935                        });
     1936                },
     1937                /**
     1938                 * @param {Object} router
     1939                 * @this wp.media.controller.Region
     1940                 */
     1941                createRouter: function( router ) {
     1942                        router.view = new media.view.Router({
     1943                                controller: this
     1944                        });
     1945                },
     1946                /**
     1947                 * @param {Object} options
     1948                 */
     1949                createIframeStates: function( options ) {
     1950                        var settings = media.view.settings,
     1951                                tabs = settings.tabs,
     1952                                tabUrl = settings.tabUrl,
     1953                                $postId;
     1954
     1955                        if ( ! tabs || ! tabUrl ) {
     1956                                return;
     1957                        }
     1958
     1959                        // Add the post ID to the tab URL if it exists.
     1960                        $postId = $('#post_ID');
     1961                        if ( $postId.length ) {
     1962                                tabUrl += '&post_id=' + $postId.val();
     1963                        }
     1964
     1965                        // Generate the tab states.
     1966                        _.each( tabs, function( title, id ) {
     1967                                this.state( 'iframe:' + id ).set( _.defaults({
     1968                                        tab:     id,
     1969                                        src:     tabUrl + '&tab=' + id,
     1970                                        title:   title,
     1971                                        content: 'iframe',
     1972                                        menu:    'default'
     1973                                }, options ) );
     1974                        }, this );
     1975
     1976                        this.on( 'content:create:iframe', this.iframeContent, this );
     1977                        this.on( 'menu:render:default', this.iframeMenu, this );
     1978                        this.on( 'open', this.hijackThickbox, this );
     1979                        this.on( 'close', this.restoreThickbox, this );
     1980                },
     1981
     1982                /**
     1983                 * @param {Object} content
     1984                 * @this wp.media.controller.Region
     1985                 */
     1986                iframeContent: function( content ) {
     1987                        this.$el.addClass('hide-toolbar');
     1988                        content.view = new media.view.Iframe({
     1989                                controller: this
     1990                        });
     1991                },
     1992
     1993                iframeMenu: function( view ) {
     1994                        var views = {};
     1995
     1996                        if ( ! view ) {
     1997                                return;
     1998                        }
     1999
     2000                        _.each( media.view.settings.tabs, function( title, id ) {
     2001                                views[ 'iframe:' + id ] = {
     2002                                        text: this.state( 'iframe:' + id ).get('title'),
     2003                                        priority: 200
     2004                                };
     2005                        }, this );
     2006
     2007                        view.set( views );
     2008                },
     2009
     2010                hijackThickbox: function() {
     2011                        var frame = this;
     2012
     2013                        if ( ! window.tb_remove || this._tb_remove ) {
     2014                                return;
     2015                        }
     2016
     2017                        this._tb_remove = window.tb_remove;
     2018                        window.tb_remove = function() {
     2019                                frame.close();
     2020                                frame.reset();
     2021                                frame.setState( frame.options.state );
     2022                                frame._tb_remove.call( window );
     2023                        };
     2024                },
     2025
     2026                restoreThickbox: function() {
     2027                        if ( ! this._tb_remove ) {
     2028                                return;
     2029                        }
     2030
     2031                        window.tb_remove = this._tb_remove;
     2032                        delete this._tb_remove;
    20302033                }
    20312034        });
    … …  
    46324635
    46334636                initialize: function() {
    4634                         var selection = this.options.selection;
    4635 
    4636                         this.$el.attr('aria-label', this.model.attributes.title).attr('aria-checked', false);
    4637                         this.model.on( 'change', this.render, this );
     4637                        var selection = this.options.selection,
     4638                                options = _.defaults( this.options, {
     4639                                        rerenderOnModelChange: true
     4640                                } );
     4641                        this.$el.attr( 'aria-label', this.model.get( 'title' ) ).attr( 'aria-checked', false );
     4642
     4643                        if ( options.rerenderOnModelChange ) {
     4644                                this.model.on( 'change', this.render, this );
     4645                        }
    46384646                        this.model.on( 'change:title', this._syncTitle, this );
    46394647                        this.model.on( 'change:caption', this._syncCaption, this );
    … …  
    46474655                        if ( selection ) {
    46484656                                selection.on( 'reset', this.updateSelect, this );
    4649                         }
    4650 
    4651                         // Update the model's details view.
    4652                         this.model.on( 'selection:single selection:unsingle', this.details, this );
    4653                         this.details( this.model, this.controller.state().get('selection') );
     4657                                // Update the model's details view.
     4658                                this.model.on( 'selection:single selection:unsingle', this.details, this );
     4659                                this.details( this.model, this.controller.state().get('selection') );
     4660                        }
    46544661                },
    46554662                /**
    … …  
    47534760
    47544761                        // In the grid view, bubble up an edit:attachment event to the controller.
    4755                         if ( this.controller.activeModes.where( { id: 'edit' } ).length ) {
     4762                        if ( this.controller.isModeActive( 'grid' ) ) {
    47564763                                this.controller.trigger( 'edit:attachment', this.model );
    47574764                                return;
    … …  
    63196326
    63206327                initialize: function() {
     6328                        this.options = _.defaults( this.options, {
     6329                                rerenderOnModelChange: false
     6330                        });
    63216331                        /**
    63226332                         * call 'initialize' directly on the parent class
    63236333                         */
    63246334                        media.view.Attachment.prototype.initialize.apply( this, arguments );
    6325                 },
    6326                 /**
    6327                  * @returns {wp.media.view..Attachment.Details} Returns itself to allow chaining
    6328                  */
    6329                 render: function() {
    6330                         /**
    6331                          * call 'render' directly on the parent class
    6332                          */
    6333                         media.view.Attachment.prototype.render.apply( this, arguments );
    6334                         return this;
    63356335                },
    63366336                /**
    … …  
    63806380                },
    63816381                /**
     6382                 * When reverse tabbing(shift+tab) out of the right details panel, deliver
     6383                 * the focus to the item in the list that was being edited.
     6384                 *
    63826385                 * @param {Object} event
    63836386                 */
    63846387                toggleSelectionHandler: function( event ) {
    6385                         // Reverse tabbing out of the right details panel
    6386                         // should take me back to the item in the list that was being edited.
    63876388                        if ( 'keydown' === event.type && 9 === event.keyCode && event.shiftKey && event.target === $( ':tabbable', this.$el ).filter( ':first' )[0] ) {
    63886389                                $('.attachments-browser .details').focus();
  • trunk/src/wp-includes/media-template.php

    r29263 r29266  
    264264
    265265        <script type="text/html" id="tmpl-attachment-details-two-column">
    266                 <h3>
    267                         <?php _e('Attachment Details'); ?>
    268                 </h3>
    269266                <div class="attachment-media-view">
    270267                        <div class="thumbnail thumbnail-{{ data.type }}">
    … …  
    295292                                <div class="attachment-actions">
    296293                                        <# if ( 'image' === data.type && ! data.uploading ) { #>
    297                                                 <a class="button edit-image" href="#"><?php _e( 'Edit Image' ); ?></a>
     294                                                <a class="button edit-attachment" href="#"><?php _e( 'Edit Image' ); ?></a>
    298295                                        <# } #>
    299296
Note: See TracChangeset for help on using the changeset viewer.