WordPress.org

Make WordPress Core

Changeset 29266


Ignore:
Timestamp:
07/22/2014 04:20:59 PM (5 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.