WordPress.org

Make WordPress Core

Changeset 22466


Ignore:
Timestamp:
11/08/12 14:15:09 (18 months ago)
Author:
koopersmith
Message:

Media: Improve sidebar handling and make attachment display properties attachment-specific.

wp.mce.media

  • Watch all workflows for the insert event and attempt to insert the current state's selection if it exists.
  • Fetch and pass attachment display properties through to wp.media.string.image().

wp.media.controller.Region

  • Separate the concept of events and modes.
  • All events triggered on a Region trigger both event and event:mode callbacks.
  • When a mode is deactivated, deactivate and deactivate:mode events are fired.
  • When a mode is activated, activate and activate:mode events are fired.

wp.media.controller.Library

  • Remove the details(), buildDetails(), and clearDetails() methods that juggled sidebar views. Instead, handle the sidebar views using modes.

wp.media.controller.Gallery

  • Shift the overloaded sidebar() method to use modes.

wp.media.view.MediaFrame.Post

  • Declare activate:mode event bindings using an nested object to reduce repetition.
  • Update sidebar activation callbacks.

wp.media.view.Settings

  • Refactor to leverage HTML data attributes and implicit values (instead of setting the fallback whenever an object was created). This has the additional benefit that gallery shortcode parameters are not output when the user has left them set to the default.

see #21390.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/js/media-upload.js

    r22437 r22466  
    108108            } ) ); 
    109109 
    110             workflow.get('library').on( 'insert', function( selection ) { 
     110            workflow.on( 'insert', function() { 
     111                var state = workflow.state(), 
     112                    selection = state.get('selection'), 
     113                    details = state.get('details'); 
     114 
     115                if ( ! selection || ! details ) 
     116                    return; 
     117 
    111118                this.insert( selection.map( function( attachment ) { 
     119                    var detail = details[ attachment.cid ]; 
     120 
     121                    if ( detail ) 
     122                        detail = detail.toJSON(); 
     123 
    112124                    if ( 'image' === attachment.get('type') ) 
    113                         return wp.media.string.image( attachment ) + ' '; 
     125                        return wp.media.string.image( attachment, detail ) + ' '; 
    114126                    else 
    115127                        return wp.media.string.link( attachment ) + ' '; 
  • trunk/wp-includes/css/media-views.css

    r22437 r22466  
    760760 */ 
    761761 
     762.attachment-details { 
     763    overflow: auto; 
     764} 
     765 
    762766.attachment-details-preview { 
    763767    cursor: default; 
  • trunk/wp-includes/js/media-views.js

    r22454 r22466  
    5959        _.extend( this, _.pick( options || {}, 'id', 'controller' ) ); 
    6060 
    61         this.on( 'empty', this.empty, this ); 
     61        this.on( 'activate:empty', this.empty, this ); 
    6262        this.mode('empty'); 
    6363    }; 
     
    6767 
    6868    _.extend( media.controller.Region.prototype, Backbone.Events, { 
    69         trigger: function( id ) { 
    70             this._mode = id; 
    71             return Backbone.Events.trigger.apply( this, arguments ); 
    72         }, 
     69        trigger: (function() { 
     70            var eventSplitter = /\s+/, 
     71                trigger = Backbone.Events.trigger; 
     72 
     73            return function( events ) { 
     74                var mode = ':' + this._mode, 
     75                    modeEvents = events.split( eventSplitter ).join( mode ) + mode; 
     76 
     77                trigger.apply( this, arguments ); 
     78                trigger.apply( this, [ modeEvents ].concat( _.rest( arguments ) ) ); 
     79                return this; 
     80            }; 
     81        }()), 
    7382 
    7483        mode: function( mode ) { 
    75             if ( mode ) 
    76                 return this.trigger( mode ); 
     84            if ( mode ) { 
     85                this.trigger('deactivate'); 
     86                this._mode = mode; 
     87                return this.trigger('activate'); 
     88            } 
    7789            return this._mode; 
    7890        }, 
     
    271283                this.set( 'gutter', 8 ); 
    272284 
     285            if ( ! this.get('details') ) 
     286                this.set( 'details', [] ); 
     287 
    273288            media.controller.State.prototype.initialize.apply( this, arguments ); 
    274289        }, 
     
    282297                wp.Uploader.queue.on( 'add', this.selectUpload, this ); 
    283298 
    284             selection.on( 'selection:single', this.buildDetails, this ); 
    285             selection.on( 'selection:unsingle', this.clearDetails, this ); 
     299            selection.on( 'selection:single selection:unsingle', this.sidebar, this ); 
    286300            selection.on( 'add remove reset', this.refreshToolbar, this ); 
    287301 
     
    307321 
    308322        sidebar: function() { 
    309             media.controller.State.prototype.sidebar.apply( this, arguments ); 
    310             this.details(); 
     323            var sidebar = this.frame.sidebar; 
     324 
     325            if ( this.get('selection').single() ) 
     326                sidebar.mode( this.get('sidebar') ); 
     327            else 
     328                sidebar.mode('clear'); 
    311329        }, 
    312330 
     
    343361        selectUpload: function( attachment ) { 
    344362            this.get('selection').add( attachment ); 
    345         }, 
    346  
    347         details: function() { 
    348             var single = this.get('selection').single(); 
    349             this[ single ? 'buildDetails' : 'clearDetails' ]( single ); 
    350         }, 
    351  
    352         buildDetails: function( model ) { 
    353             var frame = this.frame; 
    354             frame.sidebar.view().add( 'details', new media.view.Attachment.Details({ 
    355                 controller: frame, 
    356                 model:      model, 
    357                 priority:   80 
    358             }).render() ); 
    359             return this; 
    360         }, 
    361  
    362         clearDetails: function( model ) { 
    363             if ( this.get('selection').single() ) 
    364                 return this; 
    365  
    366             this.frame.sidebar.view().add( 'details', new Backbone.View({ 
    367                 priority: 80 
    368             }).render() ); 
    369             return this; 
    370363        }, 
    371364 
     
    437430 
    438431        sidebar: function() { 
    439             var frame = this.frame; 
    440  
    441             media.controller.State.prototype.sidebar.apply( this, arguments ); 
    442             this.details(); 
    443  
    444             frame.sidebar.view().add({ 
    445                 settings: new media.view.Settings.Gallery({ 
    446                     controller: frame, 
    447                     model:      this.get('library').props, 
    448                     priority:   40 
    449                 }).render() 
    450             }); 
     432            media.controller.Library.prototype.sidebar.apply( this, arguments ); 
     433            this.frame.sidebar.trigger('gallery-settings'); 
     434            return this; 
    451435        } 
    452436    }); 
     
    591575 
    592576        bindHandlers: function() { 
    593             this.menu.on( 'main', this.mainMenu, this ); 
    594             this.menu.on( 'batch', this.batchMenu, this ); 
    595             this.menu.on( 'gallery', this.galleryMenu, this ); 
    596  
    597             this.content.on( 'browse', this.browseContent, this ); 
    598             this.content.on( 'upload', this.uploadContent, this ); 
    599             this.content.on( 'embed', this.embedContent, this ); 
    600  
    601             this.sidebar.on( 'settings', this.settingsSidebar, this ); 
    602             this.sidebar.on( 'attachment-settings', this.attachmentSettingsSidebar, this ); 
    603  
    604             this.toolbar.on( 'main-attachments', this.mainAttachmentsToolbar, this ); 
    605             this.toolbar.on( 'main-embed', this.mainEmbedToolbar, this ); 
    606             this.toolbar.on( 'batch-edit', this.batchEditToolbar, this ); 
    607             this.toolbar.on( 'batch-add', this.batchAddToolbar, this ); 
    608             this.toolbar.on( 'gallery-edit', this.galleryEditToolbar, this ); 
    609             this.toolbar.on( 'gallery-add', this.galleryAddToolbar, this ); 
     577            var handlers = { 
     578                    menu: { 
     579                        main:    'mainMenu', 
     580                        batch:   'batchMenu', 
     581                        gallery: 'galleryMenu' 
     582                    }, 
     583 
     584                    content: { 
     585                        browse: 'browseContent', 
     586                        upload: 'uploadContent', 
     587                        embed:  'embedContent' 
     588                    }, 
     589 
     590                    sidebar: { 
     591                        'clear':               'clearSidebar', 
     592                        'settings':            'settingsSidebar', 
     593                        'attachment-settings': 'attachmentSettingsSidebar' 
     594                    }, 
     595 
     596                    toolbar: { 
     597                        'main-attachments': 'mainAttachmentsToolbar', 
     598                        'main-embed':       'mainEmbedToolbar', 
     599                        'batch-edit':       'batchEditToolbar', 
     600                        'batch-add':        'batchAddToolbar', 
     601                        'gallery-edit':     'galleryEditToolbar', 
     602                        'gallery-add':      'galleryAddToolbar' 
     603                    } 
     604                }; 
     605 
     606            _.each( handlers, function( regionHandlers, region ) { 
     607                _.each( regionHandlers, function( callback, handler ) { 
     608                    this[ region ].on( 'activate:' + handler, this[ callback ], this ); 
     609                }, this ); 
     610            }, this ); 
     611 
     612            this.sidebar.on( 'gallery-settings', this.onSidebarGallerySettings, this ); 
    610613        }, 
    611614 
     
    622625 
    623626        createStates: function() { 
    624             var options = this.options; 
     627            var options = this.options, 
     628                main, gallery; 
     629 
     630            main = { 
     631                multiple: this.options.multiple, 
     632                menu:      'main', 
     633                sidebar:   'attachment-settings', 
     634 
     635                // Update user settings when users adjust the 
     636                // attachment display settings. 
     637                displayUserSettings: true 
     638            }; 
     639 
     640            gallery = { 
     641                multiple: true, 
     642                menu:     'gallery', 
     643                toolbar:  'gallery-add' 
     644            }; 
    625645 
    626646            // Add the default states. 
    627647            this.states.add([ 
    628                 new media.controller.Library({ 
     648                new media.controller.Library( _.defaults({ 
    629649                    selection: options.selection, 
    630                     library:   media.query( options.library ), 
    631                     multiple:  this.options.multiple, 
    632                     menu:      'main', 
    633                     sidebar:   'attachment-settings' 
    634                 }), 
    635  
    636                 new media.controller.Upload({ 
    637                     multiple: this.options.multiple, 
    638                     menu:      'main', 
    639                     sidebar:   'attachment-settings' 
    640                 }), 
     650                    library:   media.query( options.library ) 
     651                }, main ) ), 
     652 
     653                new media.controller.Upload( main ), 
    641654 
    642655                new media.controller.Gallery({ 
     
    645658                }), 
    646659 
    647                 new media.controller.Library({ 
    648                     id:        'gallery-library', 
    649                     library:   media.query({ type: 'image' }), 
    650                     multiple:  true, 
    651                     menu:      'gallery', 
    652                     toolbar:   'gallery-add' 
    653                 }), 
    654  
    655                 new media.controller.Upload({ 
    656                     id:        'gallery-upload', 
    657                     multiple:  true, 
    658                     menu:      'gallery', 
    659                     toolbar:   'gallery-add' 
    660                 }) 
     660                new media.controller.Library( _.defaults({ 
     661                    id:      'gallery-library', 
     662                    library: media.query({ type: 'image' }) 
     663                }, gallery ) ), 
     664 
     665                new media.controller.Upload( _.defaults({ 
     666                    id: 'gallery-upload' 
     667                }, gallery ) ) 
    661668            ]); 
    662669 
     
    814821 
    815822        // Sidebars 
    816         settingsSidebar: function() { 
     823        clearSidebar: function() { 
    817824            this.sidebar.view( new media.view.Sidebar({ 
    818825                controller: this 
     
    820827        }, 
    821828 
    822         attachmentSettingsSidebar: function() { 
     829        settingsSidebar: function( options ) { 
    823830            this.sidebar.view( new media.view.Sidebar({ 
    824831                controller: this, 
     832                silent:     options && options.silent, 
     833 
    825834                views: { 
    826                     settings: new media.view.Settings.AttachmentDisplay({ 
     835                    details: new media.view.Attachment.Details({ 
    827836                        controller: this, 
    828                         priority:   20 
     837                        model:      this.state().get('selection').single(), 
     838                        priority:   80 
    829839                    }).render() 
    830840                } 
    831841            }) ); 
     842        }, 
     843 
     844        onSidebarGallerySettings: function( options ) { 
     845            this.sidebar.view().add({ 
     846                gallery: new media.view.Settings.Gallery({ 
     847                    controller: this, 
     848                    model:      this.state().get('library').props, 
     849                    priority:   40 
     850                }).render() 
     851            }, options ); 
     852        }, 
     853 
     854        attachmentSettingsSidebar: function( options ) { 
     855            var state = this.state(), 
     856                display = state.get('details'), 
     857                single = state.get('selection').single().cid; 
     858 
     859            this.settingsSidebar({ silent: true }); 
     860 
     861            display[ single ] = display[ single ] || new Backbone.Model({ 
     862                align: getUserSetting( 'align', 'none' ), 
     863                size:  getUserSetting( 'imgsize', 'medium' ), 
     864                link:  getUserSetting( 'urlbutton', 'post' ) 
     865            }); 
     866 
     867            this.sidebar.view().add({ 
     868                display: new media.view.Settings.AttachmentDisplay({ 
     869                    controller:   this, 
     870                    model:        display[ single ], 
     871                    priority:     100, 
     872                    userSettings: state.get('displayUserSettings') 
     873                }).render() 
     874            }, options ); 
    832875        }, 
    833876 
     
    21262169        }, 
    21272170 
    2128         settings: {}, 
    2129  
    21302171        initialize: function() { 
    2131             var settings = this.settings; 
    2132  
    21332172            this.model = this.model || new Backbone.Model(); 
    2134  
    2135             _.each( settings, function( setting, key ) { 
    2136                 if ( setting.name ) 
    2137                     this.model.set( key, getUserSetting( setting.name, setting.fallback ) ); 
    2138                 else 
    2139                     this.model.set( key, this.model.get( key ) || setting.fallback ); 
    2140             }, this ); 
    2141  
    2142             this.model.validate = function( attrs ) { 
    2143                 return _.any( attrs, function( value, key ) { 
    2144                     // If we don't have a `setting` for the `key`, assume the 
    2145                     // `value` is valid. Otherwise, check if the `value` exists 
    2146                     // in the `setting.accepts` array. 
    2147                     return settings[ key ] && ! _.contains( settings[ key ].accepts, value ); 
    2148                 }); 
    2149             }; 
    2150  
    2151             this.model.on( 'change', function( model, options ) { 
    2152                 if ( ! options.changes ) 
    2153                     return; 
    2154  
    2155                 _.each( _.keys( options.changes ), function( key ) { 
    2156                     if ( settings[ key ] && settings[ key ].name ) 
    2157                         setUserSetting( settings[ key ].name, model.get( key ) ); 
    2158                 }); 
    2159             }, this ); 
    2160  
    21612173            this.model.on( 'change', this.updateChanges, this ); 
    21622174        }, 
    21632175 
    21642176        render: function() { 
    2165             this.$el.html( this.template( this.model.toJSON() ) ); 
     2177            this.$el.html( this.template( _.defaults({ 
     2178                model: this.model.toJSON() 
     2179            }, this.options ) ) ); 
    21662180 
    21672181            // Select the correct values. 
     
    21712185 
    21722186        update: function( key ) { 
    2173             var setting = this.settings[ key ], 
     2187            var value = this.model.get( key ), 
    21742188                $setting = this.$('[data-setting="' + key + '"]'), 
    21752189                $buttons; 
    21762190 
    2177             if ( ! setting ) 
     2191            // Bail if we didn't find a matching setting. 
     2192            if ( ! $setting.length ) 
    21782193                return; 
    21792194 
    2180             if ( 'select' === setting.type ) { 
    2181                 $setting.find('[value="' + this.model.get( key ) + '"]').attr( 'selected', true ); 
    2182             } else { 
     2195            // Attempt to determine how the setting is rendered and update 
     2196            // the selected value. 
     2197 
     2198            // Handle dropdowns. 
     2199            if ( $setting.is('select') ) { 
     2200                $setting.find('[value="' + value + '"]').attr( 'selected', true ); 
     2201 
     2202            // Handle button groups. 
     2203            } else if ( $setting.hasClass('button-group') ) { 
    21832204                $buttons = $setting.find('button').removeClass('active'); 
    2184                 $buttons.filter( '[value="' + this.model.get( key ) + '"]' ).addClass('active'); 
     2205                $buttons.filter( '[value="' + value + '"]' ).addClass('active'); 
    21852206            } 
    21862207        }, 
    21872208 
    21882209        updateHandler: function( event ) { 
    2189             var $setting = $( event.target ).closest('[data-setting]'); 
     2210            var $setting = $( event.target ).closest('[data-setting]'), 
     2211                value = event.target.value, 
     2212                userSetting; 
    21902213 
    21912214            event.preventDefault(); 
    21922215 
    2193             if ( $setting.length ) 
    2194                 this.model.set( $setting.data('setting'), event.target.value ); 
     2216            if ( ! $setting.length ) 
     2217                return; 
     2218 
     2219            this.model.set( $setting.data('setting'), value ); 
     2220 
     2221            // If the setting has a corresponding user setting, 
     2222            // update that as well. 
     2223            if ( userSetting = $setting.data('userSetting') ) 
     2224                setUserSetting( userSetting, value ); 
    21952225        }, 
    21962226 
     
    22082238        template:  media.template('attachment-display-settings'), 
    22092239 
    2210         settings: { 
    2211             align: { 
    2212                 accepts:  ['left','center','right','none'], 
    2213                 name:     'align', 
    2214                 fallback: 'none' 
    2215             }, 
    2216             link: { 
    2217                 accepts:  ['post','file','none'], 
    2218                 name:     'urlbutton', 
    2219                 fallback: 'post' 
    2220             }, 
    2221             size: { 
    2222                 // @todo: Dynamically generate these. 
    2223                 accepts:  ['thumbnail','medium','large','full'], 
    2224                 name:     'imgsize', 
    2225                 fallback: 'medium' 
    2226             } 
     2240        initialize: function() { 
     2241            _.defaults( this.options, { 
     2242                userSettings: false 
     2243            }); 
     2244            media.view.Settings.prototype.initialize.apply( this, arguments ); 
    22272245        } 
    22282246    }); 
     
    22332251    media.view.Settings.Gallery = media.view.Settings.extend({ 
    22342252        className: 'gallery-settings', 
    2235         template:  media.template('gallery-settings'), 
    2236  
    2237         settings: { 
    2238             columns: { 
    2239                 accepts:  _.invoke( _.range( 1, 10 ), 'toString' ), 
    2240                 fallback: '3', 
    2241                 type:     'select' 
    2242             }, 
    2243             link: { 
    2244                 accepts:  ['post','file'], 
    2245                 fallback: 'post' 
    2246             } 
    2247         } 
     2253        template:  media.template('gallery-settings') 
    22482254    }); 
    22492255 
  • trunk/wp-includes/media.php

    r22437 r22466  
    14181418 
    14191419        <h4><?php _e('Alignment'); ?></h4> 
    1420         <div class="alignment button-group button-large" data-setting="align"> 
     1420        <div class="alignment button-group button-large" 
     1421            data-setting="align" 
     1422            <# if ( userSettings ) { #> 
     1423                data-user-setting="align" 
     1424            <# } #>> 
     1425 
    14211426            <button class="button" value="left"> 
    14221427                <?php esc_attr_e('Left'); ?> 
     
    14281433                <?php esc_attr_e('Right'); ?> 
    14291434            </button> 
    1430             <button class="button" value="none"> 
     1435            <button class="button active" value="none"> 
    14311436                <?php esc_attr_e('None'); ?> 
    14321437            </button> 
     
    14341439 
    14351440        <h4><?php _e('Link To'); ?></h4> 
    1436         <div class="link-to button-group button-large" data-setting="link"> 
    1437             <button class="button" value="post"> 
     1441        <div class="link-to button-group button-large" 
     1442            data-setting="link" 
     1443            <# if ( userSettings ) { #> 
     1444                data-user-setting="urlbutton" 
     1445            <# } #>> 
     1446 
     1447            <button class="button active" value="post"> 
    14381448                <?php esc_attr_e('Attachment Page'); ?> 
    14391449            </button> 
     
    14511461 
    14521462        <h4><?php _e('Link To'); ?></h4> 
    1453         <div class="link-to button-group" data-setting="link"> 
    1454             <button class="button" value="post"> 
     1463        <div class="link-to button-group" 
     1464            data-setting="link"> 
     1465 
     1466            <button class="button active" value="post"> 
    14551467                <?php esc_attr_e('Attachment Page'); ?> 
    14561468            </button> 
     
    14621474        <h4><?php _e('Gallery Columns'); ?></h4> 
    14631475 
    1464         <select class="columns" name="columns" data-setting="columns"> 
     1476        <select class="columns" name="columns" 
     1477            data-setting="columns"> 
    14651478            <?php for ( $i = 1; $i <= 9; $i++ ) : ?> 
    1466                 <option value="<?php echo esc_attr( $i ); ?>"> 
     1479                <option value="<?php echo esc_attr( $i ); ?>" <?php selected( $i, 3 ); ?>> 
    14671480                    <?php echo esc_html( $i ); ?> 
    14681481                </option> 
Note: See TracChangeset for help on using the changeset viewer.