Make WordPress Core

Ticket #26870: 26870-media-models.diff

File 26870-media-models.diff, 24.0 KB (added by wonderboymusic, 11 years ago)
  • src/wp-includes/js/media-models.js

     
    1212         * Does nothing if the controllers do not exist.
    1313         *
    1414         * @param  {object} attributes The properties passed to the main media controller.
    15          * @return {object}            A media workflow.
     15         * @return {wp.media.view.MediaFrame} A media workflow.
    1616         */
    1717        media = wp.media = function( attributes ) {
    1818                var MediaFrame = media.view.MediaFrame,
    1919                        frame;
    2020
    21                 if ( ! MediaFrame )
     21                if ( ! MediaFrame ) {
    2222                        return;
     23                }
    2324
    2425                attributes = _.defaults( attributes || {}, {
    2526                        frame: 'select'
    2627                });
    2728
    28                 if ( 'select' === attributes.frame && MediaFrame.Select )
     29                if ( 'select' === attributes.frame && MediaFrame.Select ) {
    2930                        frame = new MediaFrame.Select( attributes );
    30                 else if ( 'post' === attributes.frame && MediaFrame.Post )
     31                } else if ( 'post' === attributes.frame && MediaFrame.Post ) {
    3132                        frame = new MediaFrame.Post( attributes );
     33                }
    3234
    3335                delete attributes.frame;
    3436
     
    6264         *                      1: b should come before a.
    6365         */
    6466        compare = function( a, b, ac, bc ) {
    65                 if ( _.isEqual( a, b ) )
     67                if ( _.isEqual( a, b ) ) {
    6668                        return ac === bc ? 0 : (ac > bc ? -1 : 1);
    67                 else
     69                } else {
    6870                        return a > b ? -1 : 1;
     71                }
    6972        };
    7073
    7174        _.extend( media, {
     
    9396                 */
    9497                ajax: wp.ajax.send,
    9598
    96                 // Scales a set of dimensions to fit within bounding dimensions.
     99                /**
     100                 * Scales a set of dimensions to fit within bounding dimensions.
     101                 *
     102                 * @param {Object} dimensions
     103                 * @returns {Object}
     104                 */
    97105                fit: function( dimensions ) {
    98106                        var width     = dimensions.width,
    99107                                height    = dimensions.height,
     
    131139                                };
    132140                        }
    133141                },
    134 
    135                 // Truncates a string by injecting an ellipsis into the middle.
    136                 // Useful for filenames.
     142                /**
     143                 * Truncates a string by injecting an ellipsis into the middle.
     144                 * Useful for filenames.
     145                 *
     146                 * @param {String} string
     147                 * @param {Number} [length=30]
     148                 * @param {String} [replacement=…]
     149                 * @returns {String}
     150                 */
    137151                truncate: function( string, length, replacement ) {
    138152                        length = length || 30;
    139153                        replacement = replacement || '…';
    140154
    141                         if ( string.length <= length )
     155                        if ( string.length <= length ) {
    142156                                return string;
     157                        }
    143158
    144159                        return string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 );
    145160                }
    146161        });
    147162
    148 
    149163        /**
    150164         * ========================================================================
    151165         * MODELS
    152166         * ========================================================================
    153167         */
    154 
    155168        /**
    156169         * wp.media.attachment
     170         *
     171         * @static
     172         * @param {String} id
     173         * @returns {wp.media.model.Attachment}
    157174         */
    158175        media.attachment = function( id ) {
    159176                return Attachment.get( id );
     
    161178
    162179        /**
    163180         * wp.media.model.Attachment
     181         *
     182         * @constructor
     183         * @augments Backbone.Model
    164184         */
    165185        Attachment = media.model.Attachment = Backbone.Model.extend({
     186                /**
     187                 * @param {string} method
     188                 * @param {Backbone.Model} model
     189                 * @param {Object} [options={}]
     190                 * @returns {Promise}
     191                 */
    166192                sync: function( method, model, options ) {
    167193                        // If the attachment does not yet have an `id`, return an instantly
    168194                        // rejected promise. Otherwise, all of our requests will fail.
    169                         if ( _.isUndefined( this.id ) )
     195                        if ( _.isUndefined( this.id ) ) {
    170196                                return $.Deferred().rejectWith( this ).promise();
     197                        }
    171198
    172199                        // Overload the `read` request so Attachment.fetch() functions correctly.
    173200                        if ( 'read' === method ) {
     
    182209                        // Overload the `update` request so properties can be saved.
    183210                        } else if ( 'update' === method ) {
    184211                                // If we do not have the necessary nonce, fail immeditately.
    185                                 if ( ! this.get('nonces') || ! this.get('nonces').update )
     212                                if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    186213                                        return $.Deferred().rejectWith( this ).promise();
     214                                }
    187215
    188216                                options = options || {};
    189217                                options.context = this;
     
    212240                        } else if ( 'delete' === method ) {
    213241                                options = options || {};
    214242
    215                                 if ( ! options.wait )
     243                                if ( ! options.wait ) {
    216244                                        this.destroyed = true;
     245                                }
    217246
    218247                                options.context = this;
    219248                                options.data = _.extend( options.data || {}, {
     
    230259
    231260                        // Otherwise, fall back to `Backbone.sync()`.
    232261                        } else {
     262                                /**
     263                                 * Call `sync` directly on Backbone.Model
     264                                 */
    233265                                return Backbone.Model.prototype.sync.apply( this, arguments );
    234266                        }
    235267                },
    236 
     268                /**
     269                 * @param {Object} resp
     270                 * @returns {Object}
     271                 */
    237272                parse: function( resp ) {
    238                         if ( ! resp )
     273                        if ( ! resp ) {
    239274                                return resp;
     275                        }
    240276
    241277                        // Convert date strings into Date objects.
    242278                        resp.date = new Date( resp.date );
    243279                        resp.modified = new Date( resp.modified );
    244280                        return resp;
    245281                },
    246 
     282                /**
     283                 * @param {Object} data
     284                 * @param {Object} options
     285                 * @returns {Promise}
     286                 */
    247287                saveCompat: function( data, options ) {
    248288                        var model = this;
    249289
    250290                        // If we do not have the necessary nonce, fail immeditately.
    251                         if ( ! this.get('nonces') || ! this.get('nonces').update )
     291                        if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    252292                                return $.Deferred().rejectWith( this ).promise();
     293                        }
    253294
    254295                        return media.post( 'save-attachment-compat', _.defaults({
    255296                                id:      this.id,
     
    260301                        });
    261302                }
    262303        }, {
     304                /**
     305                 * @param {Object} attrs
     306                 * @returns {wp.media.model.Attachment}
     307                 */
    263308                create: function( attrs ) {
    264309                        return Attachments.all.push( attrs );
    265310                },
    266 
     311                /**
     312                 * @param {string} id
     313                 * @param {Backbone.Model} attachment
     314                 * @returns {wp.media.model.Attachment}
     315                 */
    267316                get: _.memoize( function( id, attachment ) {
    268317                        return Attachments.all.push( attachment || { id: id } );
    269318                })
     
    271320
    272321        /**
    273322         * wp.media.model.Attachments
     323         *
     324         * @constructor
     325         * @augments Backbone.Collection
    274326         */
    275327        Attachments = media.model.Attachments = Backbone.Collection.extend({
     328                /**
     329                 * @type {wp.media.model.Attachment}
     330                 */
    276331                model: Attachment,
    277 
     332                /**
     333                 * @param {Array|Object} models
     334                 * @param {Object} [options={}]
     335                 */
    278336                initialize: function( models, options ) {
    279337                        options = options || {};
    280338
     
    292350                        this.props.set( _.defaults( options.props || {} ) );
    293351
    294352                        // Observe another `Attachments` collection if one is provided.
    295                         if ( options.observe )
     353                        if ( options.observe ) {
    296354                                this.observe( options.observe );
     355                        }
    297356                },
    298 
    299                 // Automatically sort the collection when the order changes.
     357                /**
     358                 * Automatically sort the collection when the order changes.
     359                 *
     360                 * @access private
     361                 */
    300362                _changeOrder: function() {
    301                         if ( this.comparator )
     363                        if ( this.comparator ) {
    302364                                this.sort();
     365                        }
    303366                },
    304 
    305                 // Set the default comparator only when the `orderby` property is set.
     367                /**
     368                 * Set the default comparator only when the `orderby` property is set.
     369                 *
     370                 * @access private
     371                 *
     372                 * @param {Backbone.Model} model
     373                 * @param {string} orderby
     374                 */
    306375                _changeOrderby: function( model, orderby ) {
    307376                        // If a different comparator is defined, bail.
    308                         if ( this.comparator && this.comparator !== Attachments.comparator )
     377                        if ( this.comparator && this.comparator !== Attachments.comparator ) {
    309378                                return;
     379                        }
    310380
    311                         if ( orderby && 'post__in' !== orderby )
     381                        if ( orderby && 'post__in' !== orderby ) {
    312382                                this.comparator = Attachments.comparator;
    313                         else
     383                        } else {
    314384                                delete this.comparator;
     385                        }
    315386                },
    316 
    317                 // If the `query` property is set to true, query the server using
    318                 // the `props` values, and sync the results to this collection.
     387                /**
     388                 * If the `query` property is set to true, query the server using
     389                 * the `props` values, and sync the results to this collection.
     390                 *
     391                 * @access private
     392                 *
     393                 * @param {Backbone.Model} model
     394                 * @param {Boolean} query
     395                 */
    319396                _changeQuery: function( model, query ) {
    320397                        if ( query ) {
    321398                                this.props.on( 'change', this._requery, this );
     
    324401                                this.props.off( 'change', this._requery, this );
    325402                        }
    326403                },
    327 
     404                /**
     405                 * @access private
     406                 *
     407                 * @param {Backbone.Model} model
     408                 */
    328409                _changeFilteredProps: function( model ) {
    329410                        // If this is a query, updating the collection will be handled by
    330411                        // `this._requery()`.
    331                         if ( this.props.get('query') )
     412                        if ( this.props.get('query') ) {
    332413                                return;
     414                        }
    333415
    334416                        var changed = _.chain( model.changed ).map( function( t, prop ) {
    335417                                var filter = Attachments.filters[ prop ],
    336418                                        term = model.get( prop );
    337419
    338                                 if ( ! filter )
     420                                if ( ! filter ) {
    339421                                        return;
     422                                }
    340423
    341                                 if ( term && ! this.filters[ prop ] )
     424                                if ( term && ! this.filters[ prop ] ) {
    342425                                        this.filters[ prop ] = filter;
    343                                 else if ( ! term && this.filters[ prop ] === filter )
     426                                } else if ( ! term && this.filters[ prop ] === filter ) {
    344427                                        delete this.filters[ prop ];
    345                                 else
     428                                } else {
    346429                                        return;
     430                                }
    347431
    348432                                // Record the change.
    349433                                return true;
    350434                        }, this ).any().value();
    351435
    352                         if ( ! changed )
     436                        if ( ! changed ) {
    353437                                return;
     438                        }
    354439
    355440                        // If no `Attachments` model is provided to source the searches
    356441                        // from, then automatically generate a source from the existing
    357442                        // models.
    358                         if ( ! this._source )
     443                        if ( ! this._source ) {
    359444                                this._source = new Attachments( this.models );
     445                        }
    360446
    361447                        this.reset( this._source.filter( this.validator, this ) );
    362448                },
    363449
    364450                validateDestroyed: false,
    365 
     451                /**
     452                 * @param {wp.media.model.Attachment} attachment
     453                 * @returns {Boolean}
     454                 */
    366455                validator: function( attachment ) {
    367                         if ( ! this.validateDestroyed && attachment.destroyed )
     456                        if ( ! this.validateDestroyed && attachment.destroyed ) {
    368457                                return false;
     458                        }
    369459                        return _.all( this.filters, function( filter ) {
    370460                                return !! filter.call( this, attachment );
    371461                        }, this );
    372462                },
    373 
     463                /**
     464                 * @param {wp.media.model.Attachment} attachment
     465                 * @param {Object} options
     466                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     467                 */
    374468                validate: function( attachment, options ) {
    375469                        var valid = this.validator( attachment ),
    376470                                hasAttachment = !! this.get( attachment.cid );
    377471
    378                         if ( ! valid && hasAttachment )
     472                        if ( ! valid && hasAttachment ) {
    379473                                this.remove( attachment, options );
    380                         else if ( valid && ! hasAttachment )
     474                        } else if ( valid && ! hasAttachment ) {
    381475                                this.add( attachment, options );
     476                        }
    382477
    383478                        return this;
    384479                },
    385480
     481                /**
     482                 * @param {Backbone.Collection} attachments
     483                 * @param {object} [options={}]
     484                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     485                 */
    386486                validateAll: function( attachments, options ) {
    387487                        options = options || {};
    388488
     
    390490                                this.validate( attachment, { silent: true });
    391491                        }, this );
    392492
    393                         if ( ! options.silent )
     493                        if ( ! options.silent ) {
    394494                                this.trigger( 'reset', this, options );
    395 
     495                        }
    396496                        return this;
    397497                },
    398 
     498                /**
     499                 * @param {Backbone.Collection} attachments
     500                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     501                 */
    399502                observe: function( attachments ) {
    400503                        this.observers = this.observers || [];
    401504                        this.observers.push( attachments );
     
    405508                        this.validateAll( attachments );
    406509                        return this;
    407510                },
    408 
     511                /**
     512                 * @param {Backbone.Collection} attachments
     513                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     514                 */
    409515                unobserve: function( attachments ) {
    410516                        if ( attachments ) {
    411517                                attachments.off( null, null, this );
     
    420526
    421527                        return this;
    422528                },
    423 
     529                /**
     530                 * @access private
     531                 *
     532                 * @param {Backbone.Model} attachment
     533                 * @param {Backbone.Collction} attachments
     534                 * @param {Object} options
     535                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     536                 */
    424537                _validateHandler: function( attachment, attachments, options ) {
    425538                        // If we're not mirroring this `attachments` collection,
    426539                        // only retain the `silent` option.
     
    430543
    431544                        return this.validate( attachment, options );
    432545                },
    433 
     546                /**
     547                 * @access private
     548                 *
     549                 * @param {Backbone.Collction} attachments
     550                 * @param {Object} options
     551                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     552                 */
    434553                _validateAllHandler: function( attachments, options ) {
    435554                        return this.validateAll( attachments, options );
    436555                },
    437 
     556                /**
     557                 * @param {Backbone.Collction} attachments
     558                 * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     559                 */
    438560                mirror: function( attachments ) {
    439                         if ( this.mirroring && this.mirroring === attachments )
     561                        if ( this.mirroring && this.mirroring === attachments ) {
    440562                                return this;
     563                        }
    441564
    442565                        this.unmirror();
    443566                        this.mirroring = attachments;
     
    449572
    450573                        return this;
    451574                },
    452 
    453575                unmirror: function() {
    454                         if ( ! this.mirroring )
     576                        if ( ! this.mirroring ) {
    455577                                return;
     578                        }
    456579
    457580                        this.unobserve( this.mirroring );
    458581                        delete this.mirroring;
    459582                },
    460 
     583                /**
     584                 * @param {Object} options
     585                 * @returns {Promise}
     586                 */
    461587                more: function( options ) {
    462588                        var deferred = $.Deferred(),
    463589                                mirroring = this.mirroring,
    464590                                attachments = this;
    465591
    466                         if ( ! mirroring || ! mirroring.more )
     592                        if ( ! mirroring || ! mirroring.more ) {
    467593                                return deferred.resolveWith( this ).promise();
    468 
     594                        }
    469595                        // If we're mirroring another collection, forward `more` to
    470596                        // the mirrored collection. Account for a race condition by
    471597                        // checking if we're still mirroring that collection when
     
    477603
    478604                        return deferred.promise();
    479605                },
    480 
     606                /**
     607                 * @returns {Boolean}
     608                 */
    481609                hasMore: function() {
    482610                        return this.mirroring ? this.mirroring.hasMore() : false;
    483611                },
    484 
     612                /**
     613                 * @param {Object} resp
     614                 * @param {XMLHttpRequest} xhr
     615                 * @returns {Array}
     616                 */
    485617                parse: function( resp, xhr ) {
    486                         if ( ! _.isArray( resp ) )
     618                        if ( ! _.isArray( resp ) ) {
    487619                                resp = [resp];
     620                        }
    488621
    489622                        return _.map( resp, function( attrs ) {
    490623                                var id, attachment, newAttributes;
     
    499632                                attachment = Attachment.get( id );
    500633                                newAttributes = attachment.parse( attrs, xhr );
    501634
    502                                 if ( ! _.isEqual( attachment.attributes, newAttributes ) )
     635                                if ( ! _.isEqual( attachment.attributes, newAttributes ) ) {
    503636                                        attachment.set( newAttributes );
     637                                }
    504638
    505639                                return attachment;
    506640                        });
    507641                },
    508 
     642                /**
     643                 * @access private
     644                 */
    509645                _requery: function() {
    510                         if ( this.props.get('query') )
     646                        if ( this.props.get('query') ) {
    511647                                this.mirror( Query.get( this.props.toJSON() ) );
     648                        }
    512649                },
    513 
    514                 // If this collection is sorted by `menuOrder`, recalculates and saves
    515                 // the menu order to the database.
     650                /**
     651                 * If this collection is sorted by `menuOrder`, recalculates and saves
     652                 * the menu order to the database.
     653                 *
     654                 * @returns {undefined|Promise}
     655                 */
    516656                saveMenuOrder: function() {
    517                         if ( 'menuOrder' !== this.props.get('orderby') )
     657                        if ( 'menuOrder' !== this.props.get('orderby') ) {
    518658                                return;
     659                        }
    519660
    520661                        // Removes any uploading attachments, updates each attachment's
    521662                        // menu order, and returns an object with an { id: menuOrder }
     
    529670                                return [ attachment.id, index ];
    530671                        }).object().value();
    531672
    532                         if ( _.isEmpty( attachments ) )
     673                        if ( _.isEmpty( attachments ) ) {
    533674                                return;
     675                        }
    534676
    535677                        return media.post( 'save-attachment-order', {
    536678                                nonce:       media.model.settings.post.nonce,
     
    539681                        });
    540682                }
    541683        }, {
     684                /**
     685                 * @param {Backbone.Model} a
     686                 * @param {Backbone.Model} b
     687                 * @param {Object} options
     688                 * @returns {Number}
     689                 */
    542690                comparator: function( a, b, options ) {
    543691                        var key   = this.props.get('orderby'),
    544692                                order = this.props.get('order') || 'DESC',
     
    554702                        }
    555703
    556704                        // If `options.ties` is set, don't enforce the `cid` tiebreaker.
    557                         if ( options && options.ties )
     705                        if ( options && options.ties ) {
    558706                                ac = bc = null;
     707                        }
    559708
    560709                        return ( 'DESC' === order ) ? compare( a, b, ac, bc ) : compare( b, a, bc, ac );
    561710                },
    562711
    563712                filters: {
    564                         // Note that this client-side searching is *not* equivalent
    565                         // to our server-side searching.
     713                        /**
     714                         * Note that this client-side searching is *not* equivalent
     715                         * to our server-side searching.
     716                         *
     717                         * @param {wp.media.model.Attachment} attachment
     718                         * @returns {Boolean}
     719                         */
    566720                        search: function( attachment ) {
    567                                 if ( ! this.props.get('search') )
     721                                if ( ! this.props.get('search') ) {
    568722                                        return true;
     723                                }
    569724
    570725                                return _.any(['title','filename','description','caption','name'], function( key ) {
    571726                                        var value = attachment.get( key );
    572727                                        return value && -1 !== value.search( this.props.get('search') );
    573728                                }, this );
    574729                        },
    575 
     730                        /**
     731                         * @param {wp.media.model.Attachment} attachment
     732                         * @returns {Boolean}
     733                         */
    576734                        type: function( attachment ) {
    577735                                var type = this.props.get('type');
    578736                                return ! type || -1 !== type.indexOf( attachment.get('type') );
    579737                        },
    580 
     738                        /**
     739                         * @param {wp.media.model.Attachment} attachment
     740                         * @returns {Boolean}
     741                         */
    581742                        uploadedTo: function( attachment ) {
    582743                                var uploadedTo = this.props.get('uploadedTo');
    583                                 if ( _.isUndefined( uploadedTo ) )
     744                                if ( _.isUndefined( uploadedTo ) ) {
    584745                                        return true;
     746                                }
    585747
    586748                                return uploadedTo === attachment.get('uploadedTo');
    587749                        }
    588750                }
    589751        });
    590752
     753        /**
     754         * @member {wp.media.model.Attachments}
     755         */
    591756        Attachments.all = new Attachments();
    592757
    593758        /**
    594759         * wp.media.query
     760         *
     761         * @static
     762         * @returns {Attachments}
    595763         */
    596764        media.query = function( props ) {
    597765                return new Attachments( null, {
     
    607775         *
    608776         * Note: Do NOT change this.args after the query has been initialized.
    609777         *       Things will break.
     778         *
     779         * @constructor
     780         * @augments wp.media.model.Attachments
     781         * @augments Backbone.Collection
    610782         */
    611783        Query = media.model.Query = Attachments.extend({
     784                /**
     785                 * @global wp.Uploader
     786                 *
     787                 * @param {Array} models
     788                 * @param {Object} [options={}]
     789                 */
    612790                initialize: function( models, options ) {
    613791                        var allowed;
    614792
     
    623801                                var orderby = this.props.get('orderby'),
    624802                                        order = this.props.get('order');
    625803
    626                                 if ( ! this.comparator )
     804                                if ( ! this.comparator ) {
    627805                                        return true;
     806                                }
    628807
    629808                                // We want any items that can be placed before the last
    630809                                // item in the set. If we add any items after the last
     
    655834                        // are no filters for other properties, so observing will result in
    656835                        // false positives in those queries.
    657836                        allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent' ];
    658                         if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() )
     837                        if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {
    659838                                this.observe( wp.Uploader.queue );
     839                        }
    660840                },
    661 
     841                /**
     842                 * @returns {Boolean}
     843                 */
    662844                hasMore: function() {
    663845                        return this._hasMore;
    664846                },
    665 
     847                /**
     848                 * @param {Object} [options={}]
     849                 * @returns {Promise}
     850                 */
    666851                more: function( options ) {
    667852                        var query = this;
    668853
    669                         if ( this._more && 'pending' === this._more.state() )
     854                        if ( this._more && 'pending' === this._more.state() ) {
    670855                                return this._more;
     856                        }
    671857
    672                         if ( ! this.hasMore() )
     858                        if ( ! this.hasMore() ) {
    673859                                return $.Deferred().resolveWith( this ).promise();
     860                        }
    674861
    675862                        options = options || {};
    676863                        options.remove = false;
    677864
    678865                        return this._more = this.fetch( options ).done( function( resp ) {
    679                                 if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page )
     866                                if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {
    680867                                        query._hasMore = false;
     868                                }
    681869                        });
    682870                },
    683 
     871                /**
     872                 * @param {String} method
     873                 * @param {Backbone.Model} model
     874                 * @param {Object} [options={}]
     875                 * @returns {Promise}
     876                 */
    684877                sync: function( method, model, options ) {
    685878                        var args, fallback;
    686879
     
    697890                                args = _.clone( this.args );
    698891
    699892                                // Determine which page to query.
    700                                 if ( -1 !== args.posts_per_page )
     893                                if ( -1 !== args.posts_per_page ) {
    701894                                        args.paged = Math.floor( this.length / args.posts_per_page ) + 1;
     895                                }
    702896
    703897                                options.data.query = args;
    704898                                return media.ajax( options );
    705899
    706900                        // Otherwise, fall back to Backbone.sync()
    707901                        } else {
     902                                /**
     903                                 * Call wp.media.model.Attachments.sync or Backbone.sync
     904                                 */
    708905                                fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
    709906                                return fallback.sync.apply( this, arguments );
    710907                        }
     
    738935
    739936                // Caches query objects so queries can be easily reused.
    740937                get: (function(){
     938                        /**
     939                         * @static
     940                         * @type Array
     941                         */
    741942                        var queries = [];
    742943
     944                        /**
     945                         * @param {Object} props
     946                         * @param {Object} options
     947                         * @returns {Query}
     948                         */
    743949                        return function( props, options ) {
    744950                                var args     = {},
    745951                                        orderby  = Query.orderby,
     
    755961
    756962                                // Normalize the order.
    757963                                props.order = props.order.toUpperCase();
    758                                 if ( 'DESC' !== props.order && 'ASC' !== props.order )
     964                                if ( 'DESC' !== props.order && 'ASC' !== props.order ) {
    759965                                        props.order = defaults.order.toUpperCase();
     966                                }
    760967
    761968                                // Ensure we have a valid orderby value.
    762                                 if ( ! _.contains( orderby.allowed, props.orderby ) )
     969                                if ( ! _.contains( orderby.allowed, props.orderby ) ) {
    763970                                        props.orderby = defaults.orderby;
     971                                }
    764972
    765973                                // Generate the query `args` object.
    766974                                // Correct any differing property names.
    767975                                _.each( props, function( value, prop ) {
    768                                         if ( _.isNull( value ) )
     976                                        if ( _.isNull( value ) ) {
    769977                                                return;
     978                                        }
    770979
    771980                                        args[ Query.propmap[ prop ] || prop ] = value;
    772981                                });
     
    8011010         * wp.media.model.Selection
    8021011         *
    8031012         * Used to manage a selection of attachments in the views.
     1013         *
     1014         * @constructor
     1015         * @augments wp.media.model.Attachments
     1016         * @augments Backbone.Collection
    8041017         */
    8051018        media.model.Selection = Attachments.extend({
     1019                /**
     1020                 * Refresh the `single` model whenever the selection changes.
     1021                 * Binds `single` instead of using the context argument to ensure
     1022                 * it receives no parameters.
     1023                 *
     1024                 * @param {Array} models
     1025                 * @param {Object} options
     1026                 */
    8061027                initialize: function( models, options ) {
     1028                        /**
     1029                         * call 'initialize' directly on the parent class
     1030                         */
    8071031                        Attachments.prototype.initialize.apply( this, arguments );
    8081032                        this.multiple = options && options.multiple;
    8091033
    810                         // Refresh the `single` model whenever the selection changes.
    811                         // Binds `single` instead of using the context argument to ensure
    812                         // it receives no parameters.
    8131034                        this.on( 'add remove reset', _.bind( this.single, this, false ) );
    8141035                },
    8151036
    816                 // Override the selection's add method.
    817                 // If the workflow does not support multiple
    818                 // selected attachments, reset the selection.
     1037                /**
     1038                 * Override the selection's add method.
     1039                 * If the workflow does not support multiple
     1040                 * selected attachments, reset the selection.
     1041                 *
     1042                 * @param {Array} models
     1043                 * @param {Object} options
     1044                 * @returns {wp.media.model.Attachment[]}
     1045                 */
    8191046                add: function( models, options ) {
    820                         if ( ! this.multiple )
     1047                        if ( ! this.multiple ) {
    8211048                                this.remove( this.models );
    822 
     1049                        }
     1050                        /**
     1051                         * call 'add' directly on the parent class
     1052                         */
    8231053                        return Attachments.prototype.add.call( this, models, options );
    8241054                },
    8251055
     1056                /**
     1057                 *
     1058                 * @param {Backbone.Model} model
     1059                 *
     1060                 * @fires wp.media.model.Selection#selection:single
     1061                 * @fires wp.media.model.Selection#selection:unsingle
     1062                 *
     1063                 * @returns {Backbone.Model}
     1064                 */
    8261065                single: function( model ) {
    8271066                        var previous = this._single;
    8281067
    8291068                        // If a `model` is provided, use it as the single model.
    830                         if ( model )
     1069                        if ( model ) {
    8311070                                this._single = model;
    832 
     1071                        }
    8331072                        // If the single model isn't in the selection, remove it.
    834                         if ( this._single && ! this.get( this._single.cid ) )
     1073                        if ( this._single && ! this.get( this._single.cid ) ) {
    8351074                                delete this._single;
     1075                        }
    8361076
    8371077                        this._single = this._single || this.last();
    8381078
     
    8431083
    8441084                                        // If the model was already removed, trigger the collection
    8451085                                        // event manually.
    846                                         if ( ! this.get( previous.cid ) )
     1086                                        if ( ! this.get( previous.cid ) ) {
    8471087                                                this.trigger( 'selection:unsingle', previous, this );
     1088                                        }
    8481089                                }
    849                                 if ( this._single )
     1090                                if ( this._single ) {
    8501091                                        this._single.trigger( 'selection:single', this._single, this );
     1092                                }
    8511093                        }
    8521094
    8531095                        // Return the single model, or the last model as a fallback.