Make WordPress Core

Changeset 24368


Ignore:
Timestamp:
05/26/2013 06:43:13 AM (13 years ago)
Author:
koopersmith
Message:

Branch the generic JS utilities from the Backbone commands. See #24424.

Location:
trunk/wp-includes
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/wp-backbone.js

    r24367 r24368  
    22
    33(function ($) {
    4     /**
    5      * wp.template( id )
    6      *
    7      * Fetches a template by id.
    8      *
    9      * @param  {string} id   A string that corresponds to a DOM element with an id prefixed with "tmpl-".
    10      *                       For example, "attachment" maps to "tmpl-attachment".
    11      * @return {function}    A function that lazily-compiles the template requested.
    12      */
    13     wp.template = _.memoize(function ( id ) {
    14         var compiled,
    15             options = {
    16                 evaluate:    /<#([\s\S]+?)#>/g,
    17                 interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
    18                 escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
    19                 variable:    'data'
    20             };
    21 
    22         return function ( data ) {
    23             compiled = compiled || _.template( $( '#tmpl-' + id ).html(), null, options );
    24             return compiled( data );
    25         };
    26     });
    27 
    28 
    294    // Create the WordPress Backbone namespace.
    305    wp.Backbone = {};
  • trunk/wp-includes/js/wp-util.js

    r24367 r24368  
    2525        };
    2626    });
    27 
    28 
    29     // Create the WordPress Backbone namespace.
    30     wp.Backbone = {};
    31 
    32 
    33     // wp.Backbone.Subviews
    34     // --------------------
    35     //
    36     // A subview manager.
    37     wp.Backbone.Subviews = function( view, views ) {
    38         this.view = view;
    39         this._views = _.isArray( views ) ? { '': views } : views || {};
    40     };
    41 
    42     wp.Backbone.Subviews.extend = Backbone.Model.extend;
    43 
    44     _.extend( wp.Backbone.Subviews.prototype, {
    45         // ### Fetch all of the subviews
    46         //
    47         // Returns an array of all subviews.
    48         all: function() {
    49             return _.flatten( this._views );
    50         },
    51 
    52         // ### Get a selector's subviews
    53         //
    54         // Fetches all subviews that match a given `selector`.
    55         //
    56         // If no `selector` is provided, it will grab all subviews attached
    57         // to the view's root.
    58         get: function( selector ) {
    59             selector = selector || '';
    60             return this._views[ selector ];
    61         },
    62 
    63         // ### Get a selector's first subview
    64         //
    65         // Fetches the first subview that matches a given `selector`.
    66         //
    67         // If no `selector` is provided, it will grab the first subview
    68         // attached to the view's root.
    69         //
    70         // Useful when a selector only has one subview at a time.
    71         first: function( selector ) {
    72             var views = this.get( selector );
    73             return views && views.length ? views[0] : null;
    74         },
    75 
    76         // ### Register subview(s)
    77         //
    78         // Registers any number of `views` to a `selector`.
    79         //
    80         // When no `selector` is provided, the root selector (the empty string)
    81         // is used. `views` accepts a `Backbone.View` instance or an array of
    82         // `Backbone.View` instances.
    83         //
    84         // ---
    85         //
    86         // Accepts an `options` object, which has a significant effect on the
    87         // resulting behavior.
    88         //
    89         // `options.silent` &ndash; *boolean, `false`*
    90         // > If `options.silent` is true, no DOM modifications will be made.
    91         //
    92         // `options.add` &ndash; *boolean, `false`*
    93         // > Use `Views.add()` as a shortcut for setting `options.add` to true.
    94         //
    95         // > By default, the provided `views` will replace
    96         // any existing views associated with the selector. If `options.add`
    97         // is true, the provided `views` will be added to the existing views.
    98         //
    99         // `options.at` &ndash; *integer, `undefined`*
    100         // > When adding, to insert `views` at a specific index, use
    101         // `options.at`. By default, `views` are added to the end of the array.
    102         set: function( selector, views, options ) {
    103             var existing, next;
    104 
    105             if ( ! _.isString( selector ) ) {
    106                 options  = views;
    107                 views    = selector;
    108                 selector = '';
    109             }
    110 
    111             options  = options || {};
    112             views    = _.isArray( views ) ? views : [ views ];
    113             existing = this.get( selector );
    114             next     = views;
    115 
    116             if ( existing ) {
    117                 if ( options.add ) {
    118                     if ( _.isUndefined( options.at ) ) {
    119                         next = existing.concat( views );
    120                     } else {
    121                         next = existing;
    122                         next.splice.apply( next, [ options.at, 0 ].concat( views ) );
    123                     }
    124                 } else {
    125                     _.each( next, function( view ) {
    126                         view.__detach = true;
    127                     });
    128 
    129                     _.each( existing, function( view ) {
    130                         if ( view.__detach )
    131                             view.$el.detach();
    132                         else
    133                             view.remove();
    134                     });
    135 
    136                     _.each( next, function( view ) {
    137                         delete view.__detach;
    138                     });
    139                 }
    140             }
    141 
    142             this._views[ selector ] = next;
    143 
    144             _.each( views, function( subview ) {
    145                 var constructor = subview.Views || wp.Backbone.Subviews,
    146                     subviews = subview.views = subview.views || new constructor( subview );
    147                 subviews.parent   = this.view;
    148                 subviews.selector = selector;
    149             }, this );
    150 
    151             if ( ! options.silent )
    152                 this._attach( selector, views, _.extend({ ready: this._isReady() }, options ) );
    153 
    154             return this;
    155         },
    156 
    157         // ### Add subview(s) to existing subviews
    158         //
    159         // An alias to `Views.set()`, which defaults `options.add` to true.
    160         //
    161         // Adds any number of `views` to a `selector`.
    162         //
    163         // When no `selector` is provided, the root selector (the empty string)
    164         // is used. `views` accepts a `Backbone.View` instance or an array of
    165         // `Backbone.View` instances.
    166         //
    167         // Use `Views.set()` when setting `options.add` to `false`.
    168         //
    169         // Accepts an `options` object. By default, provided `views` will be
    170         // inserted at the end of the array of existing views. To insert
    171         // `views` at a specific index, use `options.at`. If `options.silent`
    172         // is true, no DOM modifications will be made.
    173         //
    174         // For more information on the `options` object, see `Views.set()`.
    175         add: function( selector, views, options ) {
    176             if ( ! _.isString( selector ) ) {
    177                 options  = views;
    178                 views    = selector;
    179                 selector = '';
    180             }
    181 
    182             return this.set( selector, views, _.extend({ add: true }, options ) );
    183         },
    184 
    185         // ### Stop tracking subviews
    186         //
    187         // Stops tracking `views` registered to a `selector`. If no `views` are
    188         // set, then all of the `selector`'s subviews will be unregistered and
    189         // removed.
    190         //
    191         // Accepts an `options` object. If `options.silent` is set, `remove`
    192         // will *not* be triggered on the unregistered views.
    193         unset: function( selector, views, options ) {
    194             var existing;
    195 
    196             if ( ! _.isString( selector ) ) {
    197                 options = views;
    198                 views = selector;
    199                 selector = '';
    200             }
    201 
    202             views = views || [];
    203 
    204             if ( existing = this.get( selector ) ) {
    205                 views = _.isArray( views ) ? views : [ views ];
    206                 this._views[ selector ] = views.length ? _.difference( existing, views ) : [];
    207             }
    208 
    209             if ( ! options || ! options.silent )
    210                 _.invoke( views, 'remove' );
    211 
    212             return this;
    213         },
    214 
    215         // ### Detach all subviews
    216         //
    217         // Detaches all subviews from the DOM.
    218         //
    219         // Helps to preserve all subview events when re-rendering the master
    220         // view. Used in conjunction with `Views.render()`.
    221         detach: function() {
    222             $( _.pluck( this.all(), 'el' ) ).detach();
    223             return this;
    224         },
    225 
    226         // ### Render all subviews
    227         //
    228         // Renders all subviews. Used in conjunction with `Views.detach()`.
    229         render: function() {
    230             var options = {
    231                     ready: this._isReady()
    232                 };
    233 
    234             _.each( this._views, function( views, selector ) {
    235                 this._attach( selector, views, options );
    236             }, this );
    237 
    238             this.rendered = true;
    239             return this;
    240         },
    241 
    242         // ### Remove all subviews
    243         //
    244         // Triggers the `remove()` method on all subviews. Detaches the master
    245         // view from its parent. Resets the internals of the views manager.
    246         //
    247         // Accepts an `options` object. If `options.silent` is set, `unset`
    248         // will *not* be triggered on the master view's parent.
    249         remove: function( options ) {
    250             if ( ! options || ! options.silent ) {
    251                 if ( this.parent && this.parent.views )
    252                     this.parent.views.unset( this.selector, this.view, { silent: true });
    253                 delete this.parent;
    254                 delete this.selector;
    255             }
    256 
    257             _.invoke( this.all(), 'remove' );
    258             this._views = [];
    259             return this;
    260         },
    261 
    262         // ### Replace a selector's subviews
    263         //
    264         // By default, sets the `$target` selector's html to the subview `els`.
    265         //
    266         // Can be overridden in subclasses.
    267         replace: function( $target, els ) {
    268             $target.html( els );
    269             return this;
    270         },
    271 
    272         // ### Insert subviews into a selector
    273         //
    274         // By default, appends the subview `els` to the end of the `$target`
    275         // selector. If `options.at` is set, inserts the subview `els` at the
    276         // provided index.
    277         //
    278         // Can be overridden in subclasses.
    279         insert: function( $target, els, options ) {
    280             var at = options && options.at,
    281                 $children;
    282 
    283             if ( _.isNumber( at ) && ($children = $target.children()).length > at )
    284                 $children.eq( at ).before( els );
    285             else
    286                 $target.append( els );
    287 
    288             return this;
    289         },
    290 
    291         // ### Trigger the ready event
    292         //
    293         // **Only use this method if you know what you're doing.**
    294         // For performance reasons, this method does not check if the view is
    295         // actually attached to the DOM. It's taking your word for it.
    296         //
    297         // Fires the ready event on the current view and all attached subviews.
    298         ready: function() {
    299             this.view.trigger('ready');
    300 
    301             // Find all attached subviews, and call ready on them.
    302             _.chain( this.all() ).map( function( view ) {
    303                 return view.views;
    304             }).flatten().where({ attached: true }).invoke('ready');
    305         },
    306 
    307         // #### Internal. Attaches a series of views to a selector.
    308         //
    309         // Checks to see if a matching selector exists, renders the views,
    310         // performs the proper DOM operation, and then checks if the view is
    311         // attached to the document.
    312         _attach: function( selector, views, options ) {
    313             var $selector = selector ? this.view.$( selector ) : this.view.$el,
    314                 managers;
    315 
    316             // Check if we found a location to attach the views.
    317             if ( ! $selector.length )
    318                 return this;
    319 
    320             managers = _.chain( views ).pluck('views').flatten().value();
    321 
    322             // Render the views if necessary.
    323             _.each( managers, function( manager ) {
    324                 if ( manager.rendered )
    325                     return;
    326 
    327                 manager.view.render();
    328                 manager.rendered = true;
    329             }, this );
    330 
    331             // Insert or replace the views.
    332             this[ options.add ? 'insert' : 'replace' ]( $selector, _.pluck( views, 'el' ), options );
    333 
    334             // Set attached and trigger ready if the current view is already
    335             // attached to the DOM.
    336             _.each( managers, function( manager ) {
    337                 manager.attached = true;
    338 
    339                 if ( options.ready )
    340                     manager.ready();
    341             }, this );
    342 
    343             return this;
    344         },
    345 
    346         // #### Internal. Checks if the current view is in the DOM.
    347         _isReady: function() {
    348             var node = this.view.el;
    349             while ( node ) {
    350                 if ( node === document.body )
    351                     return true;
    352                 node = node.parentNode;
    353             }
    354 
    355             return false;
    356         }
    357     });
    358 
    359 
    360     // wp.Backbone.View
    361     // ----------------
    362     //
    363     // The base view class.
    364     wp.Backbone.View = Backbone.View.extend({
    365         // The constructor for the `Views` manager.
    366         Subviews: wp.Backbone.Subviews,
    367 
    368         constructor: function() {
    369             this.views = new this.Subviews( this, this.views );
    370             this.on( 'ready', this.ready, this );
    371 
    372             Backbone.View.apply( this, arguments );
    373         },
    374 
    375         remove: function() {
    376             var result = Backbone.View.prototype.remove.apply( this, arguments );
    377 
    378             // Recursively remove child views.
    379             if ( this.views )
    380                 this.views.remove();
    381 
    382             return result;
    383         },
    384 
    385         render: function() {
    386             var options;
    387 
    388             if ( this.prepare )
    389                 options = this.prepare();
    390 
    391             this.views.detach();
    392 
    393             if ( this.template ) {
    394                 options = options || {};
    395                 this.trigger( 'prepare', options );
    396                 this.$el.html( this.template( options ) );
    397             }
    398 
    399             this.views.render();
    400             return this;
    401         },
    402 
    403         prepare: function() {
    404             return this.options;
    405         },
    406 
    407         ready: function() {}
    408     });
    40927}(jQuery));
  • trunk/wp-includes/script-loader.php

    r24364 r24368  
    274274    $scripts->add( 'underscore', '/wp-includes/js/underscore.min.js', array(), '1.4.4', 1 );
    275275    $scripts->add( 'backbone', '/wp-includes/js/backbone.min.js', array('underscore','jquery'), '1.0.0', 1 );
    276     $scripts->add( 'wp-backbone', "/wp-includes/js/wp-backbone$suffix.js", array('backbone'), false, 1 );
     276
     277    $scripts->add( 'wp-util', "/wp-includes/js/wp-util$suffix.js", array('underscore', 'jquery'), false, 1 );
     278    $scripts->add( 'wp-backbone', "/wp-includes/js/wp-backbone$suffix.js", array('backbone', 'wp-util'), false, 1 );
    277279
    278280    $scripts->add( 'revisions', "/wp-admin/js/revisions$suffix.js", array( 'wp-backbone', 'jquery-ui-slider', 'jquery-ui-tooltip' ), false, 1 );
Note: See TracChangeset for help on using the changeset viewer.