Make WordPress Core

Changeset 22648


Ignore:
Timestamp:
11/19/2012 12:36:47 AM (14 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.