Make WordPress Core

Changeset 22692


Ignore:
Timestamp:
11/20/2012 12:53:02 AM (14 years ago)
Author:
koopersmith
Message:

Media: Detect when views are added to the DOM and fire a ready event. see #21390.

File:
1 edited

Legend:

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

    r22690 r22692  
    633633                // `options.at`. By default, `views` are added to the end of the array.
    634634                set: function( selector, views, options ) {
    635                         var $selector, els, existing, method;
     635                        var existing, next;
    636636
    637637                        if ( ! _.isString( selector ) ) {
     
    645645                        existing = this.get( selector );
    646646                        next     = views;
    647                         method   = options.add ? 'insert' : 'replace';
    648647
    649648                        if ( existing ) {
     
    673672                        this._views[ selector ] = next;
    674673
    675                         $selector = selector ? this.view.$( selector ) : this.view.$el;
    676                         els = _.pluck( views, 'el' );
    677 
    678674                        _.each( views, function( subview ) {
    679675                                var constructor = subview.Views || media.Views,
     
    683679                        }, this );
    684680
    685                         if ( ! options.silent ) {
    686                                 _.each( views, this._maybeRender, this );
    687                                 this[ method ]( $selector, els, options );
    688                         }
     681                        if ( ! options.silent )
     682                                this._attach( selector, views, _.extend({ ready: this._isReady() }, options ) );
    689683
    690684                        return this;
     
    756750                // Renders all subviews. Used in conjunction with `Views.detach()`.
    757751                render: function() {
    758                         var root = this._views[''];
    759 
    760                         _.each( this.all(), this._maybeRender, this );
    761 
    762                         if ( root )
    763                                 this.replace( this.view.$el, _.pluck( root, 'el' ) );
     752                        var options = {
     753                                        ready: this._isReady()
     754                                };
    764755
    765756                        _.each( this._views, function( views, selector ) {
    766                                 if ( selector )
    767                                         this.replace( this.view.$( selector ), _.pluck( views, 'el' ) );
     757                                this._attach( selector, views, options );
    768758                        }, this );
    769759
     
    821811                },
    822812
    823 
    824                 // #### Internal. Maybe render a view.
    825                 _maybeRender: function( view ) {
    826                         if ( ! view.views || view.views.rendered )
    827                                 return;
    828 
    829                         view.render();
    830                         view.views.rendered = true;
     813                // ### Trigger the ready event
     814                //
     815                // **Only use this method if you know what you're doing.**
     816                // For performance reasons, this method does not check if the view is
     817                // actually attached to the DOM. It's taking your word for it.
     818                //
     819                // Fires the ready event on the current view and all attached subviews.
     820                ready: function() {
     821                        this.view.trigger('ready');
     822
     823                        // Find all attached subviews, and call ready on them.
     824                        _.chain( this.all() ).map( function( view ) {
     825                                return view.views;
     826                        }).flatten().where({ attached: true }).invoke('ready');
     827                },
     828
     829                // #### Internal. Attaches a series of views to a selector.
     830                //
     831                // Checks to see if a matching selector exists, renders the views,
     832                // performs the proper DOM operation, and then checks if the view is
     833                // attached to the document.
     834                _attach: function( selector, views, options ) {
     835                        var $selector = selector ? this.view.$( selector ) : this.view.$el,
     836                                managers;
     837
     838                        // Check if we found a location to attach the views.
     839                        if ( ! $selector.length )
     840                                return this;
     841
     842                        managers = _.chain( views ).pluck('views').flatten().value();
     843
     844                        // Render the views if necessary.
     845                        _.each( managers, function( manager ) {
     846                                if ( manager.rendered )
     847                                        return;
     848
     849                                manager.view.render();
     850                                manager.rendered = true;
     851                        }, this );
     852
     853                        // Insert or replace the views.
     854                        this[ options.add ? 'insert' : 'replace' ]( $selector, _.pluck( views, 'el' ), options );
     855
     856                        // Set attached and trigger ready if the current view is already
     857                        // attached to the DOM.
     858                        _.each( managers, function( manager ) {
     859                                manager.attached = true;
     860
     861                                if ( options.ready )
     862                                        manager.ready();
     863                        }, this );
     864
     865                        return this;
     866                },
     867
     868                // #### Internal. Checks if the current view is in the DOM.
     869                _isReady: function() {
     870                        var node = this.view.el;
     871                        while ( node ) {
     872                                if ( node === document.body )
     873                                        return true;
     874                                node = node.parentNode;
     875                        }
     876
     877                        return false;
    831878                }
    832879        });
     
    842889                constructor: function() {
    843890                        this.views = new this.Views( this, this.views );
     891                        this.on( 'ready', this.ready, this );
    844892                        Backbone.View.apply( this, arguments );
    845893                },
     
    886934                prepare: function() {
    887935                        return this.options;
    888                 }
     936                },
     937
     938                ready: function() {}
    889939        });
    890940
     
    9681018                                });
    9691019                        }
     1020
     1021                        this.on( 'attach', _.bind( this.views.ready, this.views ), this );
    9701022                },
    9711023
     
    10611113        _.each(['open','close','attach','detach'], function( method ) {
    10621114                media.view.MediaFrame.prototype[ method ] = function( view ) {
    1063                         this.trigger( method );
    10641115                        if ( this.modal )
    10651116                                this.modal[ method ].apply( this.modal, arguments );
     1117                        this.trigger( method );
    10661118                        return this;
    10671119                };
     
    15931645                attach: function() {
    15941646                        this.$el.appendTo( this.options.container );
    1595                         this.controller.trigger( 'attach', this.controller );
     1647                        this.trigger('attach');
    15961648                        return this;
    15971649                },
     
    15991651                detach: function() {
    16001652                        this.$el.detach();
    1601                         this.controller.trigger( 'detach', this.controller );
     1653                        this.trigger('detach');
    16021654                        return this;
    16031655                },
     
    16051657                open: function() {
    16061658                        this.$el.show();
    1607                         this.controller.trigger( 'open', this.controller );
     1659                        this.trigger('open');
    16081660                        return this;
    16091661                },
     
    16111663                close: function() {
    16121664                        this.$el.hide();
    1613                         this.controller.trigger( 'close', this.controller );
     1665                        this.trigger('close');
    16141666                        return this;
    16151667                },
Note: See TracChangeset for help on using the changeset viewer.