Make WordPress Core

Changeset 22648


Ignore:
Timestamp:
11/19/2012 12:36:47 AM (12 years ago)
Author:
koopersmith
Message:

Media: Add a base view class.

  • Centralizes view and subview management, unifying several disjointed constructs.
  • Utilizes the dispose functionality found in Backbone master, providing a standard method for memory management.

see #21390.

Location:
trunk/wp-includes
Files:
3 edited

Legend:

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

    r22612 r22648  
    109109}
    110110
    111 .media-frame > .media-toolbar {
     111.media-frame-toolbar > .media-toolbar {
    112112    top: auto;
    113113    left: 200px;
     
    117117}
    118118
    119 .media-frame.hide-toolbar > .media-toolbar {
     119.hide-toolbar .media-frame-toolbar > .media-toolbar {
    120120    bottom: -61px;
    121121}
  • trunk/wp-includes/js/media-views.js

    r22612 r22648  
    6161     */
    6262    media.controller.Region = function( options ) {
    63         _.extend( this, _.pick( options || {}, 'id', 'controller' ) );
     63        _.extend( this, _.pick( options || {}, 'id', 'controller', 'selector' ) );
    6464
    6565        this.on( 'activate:empty', this.empty, this );
     
    114114                view.$el.addClass( 'mode-' + mode );
    115115
    116             // Remove the hide class.
    117             // this.$el.removeClass( 'hide-' + subview );
    118 
    119             if ( previous ) {
    120                 // Replace the view in place.
    121                 previous.$el.replaceWith( view.$el );
    122 
    123                 // Fire the view's `destroy` event if it exists.
    124                 if ( previous.destroy )
    125                     previous.destroy();
    126                 // Undelegate events.
    127                 previous.undelegateEvents();
    128             }
    129 
     116            this.controller.views.set( this.selector, view );
    130117            this._view = view;
    131118        },
    132119
    133120        empty: function() {
    134             this.view( new Backbone.View() );
     121            this.view( new media.View() );
    135122        }
    136123    });
     
    575562     */
    576563
     564    // wp.media.Views
     565    // -------------
     566    //
     567    // A subview manager.
     568
     569    media.Views = function( view, views ) {
     570        this.view = view;
     571        this._views = _.isArray( views ) ? { '': views } : views || {};
     572    };
     573
     574    media.Views.extend = Backbone.Model.extend;
     575
     576    _.extend( media.Views.prototype, {
     577        get: function( selector ) {
     578            selector = selector || '';
     579            return this._views[ selector ];
     580        },
     581
     582        set: function( selector, views, options ) {
     583            var $selector, els, existing, add, method;
     584
     585            if ( ! _.isString( selector ) ) {
     586                options  = views;
     587                views    = selector;
     588                selector = '';
     589            }
     590
     591            views    = _.isArray( views ) ? views : [ views ];
     592            add      = options && options.add;
     593            existing = this.get( selector );
     594            method   = add ? 'attach' : 'replace';
     595
     596            if ( ! add && existing ) {
     597                this.unset( selector );
     598                _.invoke( existing, 'dispose' );
     599            }
     600
     601            this._views[ selector ] = add && existing ? existing.concat( views ) : views;
     602
     603            $selector = selector ? this.view.$( selector ) : this.view.$el;
     604            els = _.pluck( views, 'el' );
     605
     606            _.each( views, function( subview ) {
     607                var subviews = subview.views = subview.views || new this.constructor( subview );
     608                subviews.parent   = this.view;
     609                subviews.selector = selector;
     610            }, this );
     611
     612            this[ method ]( $selector, els );
     613            return this;
     614        },
     615
     616        add: function( selector, views ) {
     617            return this.set( selector, views, { add: true });
     618        },
     619
     620        unset: function( selector, views ) {
     621            var existing;
     622
     623            if ( ! _.isString( selector ) ) {
     624                views = selector;
     625                selector = '';
     626            }
     627
     628            views = _.isArray( views ) ? views : [ views ];
     629
     630            if ( existing = this.get( selector ) )
     631                this._views[ selector ] = _.difference( existing, views );
     632
     633            return this;
     634        },
     635
     636        render: function() {
     637            var root = this._views[''];
     638
     639            if ( root )
     640                this.replace( this.view.$el, _.pluck( root, 'el' ) );
     641
     642            _.each( this._views, function( views, selector ) {
     643                if ( selector )
     644                    this.replace( this.view.$( selector ), _.pluck( views, 'el' ) );
     645            }, this );
     646
     647            return this;
     648        },
     649
     650        dispose: function() {
     651            delete this.parent;
     652            delete this.selector;
     653
     654            _.chain( this._views ).flatten().invoke('dispose');
     655            this._views = [];
     656        },
     657
     658        replace: function( $target, els ) {
     659            if ( this.view.replace )
     660                return this.view.replace( $target, els );
     661
     662            $target.html( els );
     663        },
     664
     665        attach: function( $target, els ) {
     666            if ( this.view.attach )
     667                return this.view.attach( $target, els );
     668
     669            $target.append( els );
     670        }
     671    });
     672
     673    // wp.media.View
     674    // -------------
     675    //
     676    // The base view class.
     677    media.View = Backbone.View.extend({
     678        constructor: function() {
     679            this.views = new media.Views( this, this.views );
     680            Backbone.View.apply( this, arguments );
     681        },
     682
     683        dispose: function() {
     684            // Undelegating events, removing events from the model, and
     685            // removing events from the controller mirror the code for
     686            // `Backbone.View.dispose` in Backbone master.
     687            this.undelegateEvents();
     688
     689            if ( this.model && this.model.off )
     690                this.model.off( null, null, this );
     691
     692            if ( this.collection && this.collection.off )
     693                this.collection.off( null, null, this );
     694
     695            // Recursively dispose child views.
     696            if ( this.views )
     697                this.views.dispose();
     698
     699            return this;
     700        },
     701
     702        remove: function() {
     703            this.dispose();
     704            return Backbone.View.prototype.remove.apply( this, arguments );
     705        }
     706    });
     707
    577708    /**
    578709     * wp.media.view.Frame
    579710     */
    580     media.view.Frame = Backbone.View.extend({
    581 
     711    media.view.Frame = media.View.extend({
    582712        initialize: function() {
    583713            this._createRegions();
     
    593723                this[ region ] = new media.controller.Region({
    594724                    controller: this,
    595                     id:         region
     725                    id:         region,
     726                    selector:   '.media-frame-' + region
    596727                });
    597728            }, this );
     
    611742
    612743        render: function() {
    613             var els = _.map( this.regions, function( region ) {
    614                     return this[ region ].view().el;
    615                 }, this );
    616 
    617             // Detach the current views to maintain event bindings.
    618             $( els ).detach();
    619             this.$el.html( els );
    620 
     744            if ( ! this.template )
     745                return;
     746
     747            this.$el.html( this.template( this.options ) );
     748            this.views.render();
    621749            return this;
    622750        },
     
    636764    media.view.MediaFrame = media.view.Frame.extend({
    637765        className: 'media-frame',
     766        template:  media.template('media-frame'),
    638767        regions:   ['menu','content','sidebar','toolbar'],
    639768
     
    10851214
    10861215            this.menu.view().add({
    1087                 separateLibrary: new Backbone.View({
     1216                separateLibrary: new media.View({
    10881217                    className: 'separator',
    10891218                    priority: 60
     
    11131242                        }
    11141243                    },
    1115                     separateCancel: new Backbone.View({
     1244                    separateCancel: new media.View({
    11161245                        className: 'separator',
    11171246                        priority: 40
     
    11501279                        }
    11511280                    },
    1152                     separateCancel: new Backbone.View({
     1281                    separateCancel: new media.View({
    11531282                        className: 'separator',
    11541283                        priority: 40
     
    13701499     * wp.media.view.Modal
    13711500     */
    1372     media.view.Modal = Backbone.View.extend({
     1501    media.view.Modal = media.View.extend({
    13731502        tagName:  'div',
    13741503        template: media.template('media-modal'),
     
    14461575    // wp.media.view.UploaderWindow
    14471576    // ----------------------------
    1448     media.view.UploaderWindow = Backbone.View.extend({
     1577    media.view.UploaderWindow = media.View.extend({
    14491578        tagName:   'div',
    14501579        className: 'uploader-window',
     
    15251654    });
    15261655
    1527     media.view.UploaderInline = Backbone.View.extend({
     1656    media.view.UploaderInline = media.View.extend({
    15281657        tagName:   'div',
    15291658        className: 'uploader-inline',
     
    15811710     * wp.media.view.Toolbar
    15821711     */
    1583     media.view.Toolbar = Backbone.View.extend({
     1712    media.view.Toolbar = media.View.extend({
    15841713        tagName:   'div',
    15851714        className: 'media-toolbar',
     
    18171946     * wp.media.view.Button
    18181947     */
    1819     media.view.Button = Backbone.View.extend({
     1948    media.view.Button = media.View.extend({
    18201949        tagName:    'a',
    18211950        className:  'media-button',
     
    18932022     * wp.media.view.ButtonGroup
    18942023     */
    1895     media.view.ButtonGroup = Backbone.View.extend({
     2024    media.view.ButtonGroup = media.View.extend({
    18962025        tagName:   'div',
    18972026        className: 'button-group button-large media-button-group',
     
    19212050     */
    19222051
    1923     media.view.PriorityList = Backbone.View.extend({
     2052    media.view.PriorityList = media.View.extend({
    19242053        tagName:   'div',
    19252054
     
    19282057            this._views     = {};
    19292058
    1930             this.add( _.extend( {}, this.views, this.options.views ), { silent: true });
    1931             delete this.views;
     2059            this.add( _.extend( {}, this._views, this.options.views ), { silent: true });
    19322060            delete this.options.views;
    19332061
     
    19942122
    19952123        toView: function( options ) {
    1996             return new Backbone.View( options );
     2124            return new media.View( options );
    19972125        }
    19982126    });
     
    20272155    });
    20282156
    2029     media.view.MenuItem = Backbone.View.extend({
     2157    media.view.MenuItem = media.View.extend({
    20302158        tagName:   'li',
    20312159        className: 'media-menu-item',
     
    20662194     * wp.media.view.Attachment
    20672195     */
    2068     media.view.Attachment = Backbone.View.extend({
     2196    media.view.Attachment = media.View.extend({
    20692197        tagName:   'li',
    20702198        className: 'attachment',
     
    22642392     * wp.media.view.Attachments
    22652393     */
    2266     media.view.Attachments = Backbone.View.extend({
     2394    media.view.Attachments = media.View.extend({
    22672395        tagName:   'ul',
    22682396        className: 'attachments',
     
    24552583     * wp.media.view.Search
    24562584     */
    2457     media.view.Search = Backbone.View.extend({
     2585    media.view.Search = media.View.extend({
    24582586        tagName:   'input',
    24592587        className: 'search',
     
    24882616     * wp.media.view.AttachmentsBrowser
    24892617     */
    2490     media.view.AttachmentsBrowser = Backbone.View.extend({
     2618    media.view.AttachmentsBrowser = media.View.extend({
    24912619        tagName:   'div',
    24922620        className: 'attachments-browser',
     
    25162644
    25172645            if ( this.options.sortable ) {
    2518                 this.toolbar.set( 'dragInfo', new Backbone.View({
     2646                this.toolbar.set( 'dragInfo', new media.View({
    25192647                    el: $( '<div class="instructions">' + l10n.dragInfo + '</div>' )[0],
    25202648                    priority: -40
     
    25602688     * wp.media.view.SelectionPreview
    25612689     */
    2562     media.view.SelectionPreview = Backbone.View.extend({
     2690    media.view.SelectionPreview = media.View.extend({
    25632691        tagName:   'div',
    25642692        className: 'selection-preview',
     
    26112739     * wp.media.view.Selection
    26122740     */
    2613     media.view.Selection = Backbone.View.extend({
     2741    media.view.Selection = media.View.extend({
    26142742        tagName:   'div',
    26152743        className: 'media-selection',
     
    27082836     * wp.media.view.Settings
    27092837     */
    2710     media.view.Settings = Backbone.View.extend({
     2838    media.view.Settings = media.View.extend({
    27112839        events: {
    27122840            'click button':    'updateHandler',
     
    28542982     * wp.media.view.AttachmentCompat
    28552983     */
    2856     media.view.AttachmentCompat = Backbone.View.extend({
     2984    media.view.AttachmentCompat = media.View.extend({
    28572985        tagName:   'form',
    28582986        className: 'compat-item',
     
    29023030     * wp.media.view.Iframe
    29033031     */
    2904     media.view.Iframe = Backbone.View.extend({
     3032    media.view.Iframe = media.View.extend({
    29053033        className: 'media-iframe',
    29063034
     
    29183046     * wp.media.view.Embed
    29193047     */
    2920     media.view.Embed = Backbone.View.extend({
     3048    media.view.Embed = media.View.extend({
    29213049        className: 'media-embed',
    29223050
     
    29293057            }).render();
    29303058
    2931             this._settings = new Backbone.View();
     3059            this._settings = new media.View();
    29323060            this.refresh();
    29333061            this.model.on( 'change:type', this.refresh, this );
     
    29713099     * wp.media.view.EmbedUrl
    29723100     */
    2973     media.view.EmbedUrl = Backbone.View.extend({
     3101    media.view.EmbedUrl = media.View.extend({
    29743102        tagName:   'label',
    29753103        className: 'embed-url',
  • trunk/wp-includes/media.php

    r22608 r22648  
    13921392function wp_print_media_templates( $attachment ) {
    13931393    ?>
     1394    <script type="text/html" id="tmpl-media-frame">
     1395        <div class="media-frame-menu"></div>
     1396        <div class="media-frame-content"></div>
     1397        <div class="media-frame-sidebar"></div>
     1398        <div class="media-frame-toolbar"></div>
     1399    </script>
     1400
    13941401    <script type="text/html" id="tmpl-media-modal">
    13951402        <div class="media-modal">
Note: See TracChangeset for help on using the changeset viewer.