Make WordPress Core

Changeset 31379


Ignore:
Timestamp:
02/09/2015 04:13:38 AM (8 years ago)
Author:
wonderboymusic
Message:

Make sure that media/views.js doesn't load Models that already exist in media/models.js.

See #28510.

Location:
trunk/src/wp-includes/js/media
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/media/audio-video.js

    r31373 r31379  
    224224
    225225}(_));
    226 },{"./controllers/audio-details.js":2,"./controllers/video-details.js":8,"./models/post-media.js":11,"./views/audio-details.js":25,"./views/frame/audio-details.js":29,"./views/frame/media-details.js":30,"./views/frame/video-details.js":32,"./views/media-details.js":35,"./views/video-details.js":54}],2:[function(require,module,exports){
     226},{"./controllers/audio-details.js":2,"./controllers/video-details.js":8,"./models/post-media.js":9,"./views/audio-details.js":21,"./views/frame/audio-details.js":25,"./views/frame/media-details.js":26,"./views/frame/video-details.js":28,"./views/media-details.js":31,"./views/video-details.js":50}],2:[function(require,module,exports){
    227227/*globals wp */
    228228
     
    294294 */
    295295var selectionSync = require( '../utils/selection-sync.js' ),
    296     Selection = require( '../models/selection.js' ),
    297296    State = require( './state.js' ),
    298297    l10n = wp.media.view.l10n,
     
    339338            }
    340339
    341             this.set( 'selection', new Selection( null, {
     340            this.set( 'selection', new wp.media.model.Selection( null, {
    342341                multiple: this.get('multiple'),
    343342                props: props
     
    530529
    531530module.exports = Library;
    532 },{"../models/selection.js":13,"../utils/selection-sync.js":14,"./state.js":7}],4:[function(require,module,exports){
     531},{"../utils/selection-sync.js":10,"./state.js":7}],4:[function(require,module,exports){
    533532/*globals _, wp */
    534533
     
    11611160module.exports = VideoDetails;
    11621161},{"./state.js":7}],9:[function(require,module,exports){
    1163 /*globals jQuery, Backbone, _, wp */
    1164 
    1165 /**
    1166  * wp.media.model.Attachment
    1167  *
    1168  * @class
    1169  * @augments Backbone.Model
    1170  */
    1171 var $ = jQuery,
    1172     Attachment;
    1173 
    1174 Attachment = Backbone.Model.extend({
    1175     /**
    1176      * Triggered when attachment details change
    1177      * Overrides Backbone.Model.sync
    1178      *
    1179      * @param {string} method
    1180      * @param {wp.media.model.Attachment} model
    1181      * @param {Object} [options={}]
    1182      *
    1183      * @returns {Promise}
    1184      */
    1185     sync: function( method, model, options ) {
    1186         // If the attachment does not yet have an `id`, return an instantly
    1187         // rejected promise. Otherwise, all of our requests will fail.
    1188         if ( _.isUndefined( this.id ) ) {
    1189             return $.Deferred().rejectWith( this ).promise();
    1190         }
    1191 
    1192         // Overload the `read` request so Attachment.fetch() functions correctly.
    1193         if ( 'read' === method ) {
    1194             options = options || {};
    1195             options.context = this;
    1196             options.data = _.extend( options.data || {}, {
    1197                 action: 'get-attachment',
    1198                 id: this.id
    1199             });
    1200             return wp.media.ajax( options );
    1201 
    1202         // Overload the `update` request so properties can be saved.
    1203         } else if ( 'update' === method ) {
    1204             // If we do not have the necessary nonce, fail immeditately.
    1205             if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    1206                 return $.Deferred().rejectWith( this ).promise();
    1207             }
    1208 
    1209             options = options || {};
    1210             options.context = this;
    1211 
    1212             // Set the action and ID.
    1213             options.data = _.extend( options.data || {}, {
    1214                 action:  'save-attachment',
    1215                 id:      this.id,
    1216                 nonce:   this.get('nonces').update,
    1217                 post_id: wp.media.model.settings.post.id
    1218             });
    1219 
    1220             // Record the values of the changed attributes.
    1221             if ( model.hasChanged() ) {
    1222                 options.data.changes = {};
    1223 
    1224                 _.each( model.changed, function( value, key ) {
    1225                     options.data.changes[ key ] = this.get( key );
    1226                 }, this );
    1227             }
    1228 
    1229             return wp.media.ajax( options );
    1230 
    1231         // Overload the `delete` request so attachments can be removed.
    1232         // This will permanently delete an attachment.
    1233         } else if ( 'delete' === method ) {
    1234             options = options || {};
    1235 
    1236             if ( ! options.wait ) {
    1237                 this.destroyed = true;
    1238             }
    1239 
    1240             options.context = this;
    1241             options.data = _.extend( options.data || {}, {
    1242                 action:   'delete-post',
    1243                 id:       this.id,
    1244                 _wpnonce: this.get('nonces')['delete']
    1245             });
    1246 
    1247             return wp.media.ajax( options ).done( function() {
    1248                 this.destroyed = true;
    1249             }).fail( function() {
    1250                 this.destroyed = false;
    1251             });
    1252 
    1253         // Otherwise, fall back to `Backbone.sync()`.
    1254         } else {
    1255             /**
    1256              * Call `sync` directly on Backbone.Model
    1257              */
    1258             return Backbone.Model.prototype.sync.apply( this, arguments );
    1259         }
    1260     },
    1261     /**
    1262      * Convert date strings into Date objects.
    1263      *
    1264      * @param {Object} resp The raw response object, typically returned by fetch()
    1265      * @returns {Object} The modified response object, which is the attributes hash
    1266      *    to be set on the model.
    1267      */
    1268     parse: function( resp ) {
    1269         if ( ! resp ) {
    1270             return resp;
    1271         }
    1272 
    1273         resp.date = new Date( resp.date );
    1274         resp.modified = new Date( resp.modified );
    1275         return resp;
    1276     },
    1277     /**
    1278      * @param {Object} data The properties to be saved.
    1279      * @param {Object} options Sync options. e.g. patch, wait, success, error.
    1280      *
    1281      * @this Backbone.Model
    1282      *
    1283      * @returns {Promise}
    1284      */
    1285     saveCompat: function( data, options ) {
    1286         var model = this;
    1287 
    1288         // If we do not have the necessary nonce, fail immeditately.
    1289         if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    1290             return $.Deferred().rejectWith( this ).promise();
    1291         }
    1292 
    1293         return media.post( 'save-attachment-compat', _.defaults({
    1294             id:      this.id,
    1295             nonce:   this.get('nonces').update,
    1296             post_id: wp.media.model.settings.post.id
    1297         }, data ) ).done( function( resp, status, xhr ) {
    1298             model.set( model.parse( resp, xhr ), options );
    1299         });
    1300     }
    1301 }, {
    1302     /**
    1303      * Create a new model on the static 'all' attachments collection and return it.
    1304      *
    1305      * @static
    1306      * @param {Object} attrs
    1307      * @returns {wp.media.model.Attachment}
    1308      */
    1309     create: function( attrs ) {
    1310         var Attachments = require( './attachments.js' );
    1311         return Attachments.all.push( attrs );
    1312     },
    1313     /**
    1314      * Create a new model on the static 'all' attachments collection and return it.
    1315      *
    1316      * If this function has already been called for the id,
    1317      * it returns the specified attachment.
    1318      *
    1319      * @static
    1320      * @param {string} id A string used to identify a model.
    1321      * @param {Backbone.Model|undefined} attachment
    1322      * @returns {wp.media.model.Attachment}
    1323      */
    1324     get: _.memoize( function( id, attachment ) {
    1325         var Attachments = require( './attachments.js' );
    1326         return Attachments.all.push( attachment || { id: id } );
    1327     })
    1328 });
    1329 
    1330 module.exports = Attachment;
    1331 },{"./attachments.js":10}],10:[function(require,module,exports){
    1332 /*globals jQuery, Backbone, _, wp */
    1333 
    1334 /**
    1335  * wp.media.model.Attachments
    1336  *
    1337  * A collection of attachments.
    1338  *
    1339  * This collection has no persistence with the server without supplying
    1340  * 'options.props.query = true', which will mirror the collection
    1341  * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().
    1342  *
    1343  * @class
    1344  * @augments Backbone.Collection
    1345  *
    1346  * @param {array}  [models]                Models to initialize with the collection.
    1347  * @param {object} [options]               Options hash for the collection.
    1348  * @param {string} [options.props]         Options hash for the initial query properties.
    1349  * @param {string} [options.props.order]   Initial order (ASC or DESC) for the collection.
    1350  * @param {string} [options.props.orderby] Initial attribute key to order the collection by.
    1351  * @param {string} [options.props.query]   Whether the collection is linked to an attachments query.
    1352  * @param {string} [options.observe]
    1353  * @param {string} [options.filters]
    1354  *
    1355  */
    1356 var Attachment = require( './attachment.js' ),
    1357     Attachments;
    1358 
    1359 Attachments = Backbone.Collection.extend({
    1360     /**
    1361      * @type {wp.media.model.Attachment}
    1362      */
    1363     model: Attachment,
    1364     /**
    1365      * @param {Array} [models=[]] Array of models used to populate the collection.
    1366      * @param {Object} [options={}]
    1367      */
    1368     initialize: function( models, options ) {
    1369         options = options || {};
    1370 
    1371         this.props   = new Backbone.Model();
    1372         this.filters = options.filters || {};
    1373 
    1374         // Bind default `change` events to the `props` model.
    1375         this.props.on( 'change', this._changeFilteredProps, this );
    1376 
    1377         this.props.on( 'change:order',   this._changeOrder,   this );
    1378         this.props.on( 'change:orderby', this._changeOrderby, this );
    1379         this.props.on( 'change:query',   this._changeQuery,   this );
    1380 
    1381         this.props.set( _.defaults( options.props || {} ) );
    1382 
    1383         if ( options.observe ) {
    1384             this.observe( options.observe );
    1385         }
    1386     },
    1387     /**
    1388      * Sort the collection when the order attribute changes.
    1389      *
    1390      * @access private
    1391      */
    1392     _changeOrder: function() {
    1393         if ( this.comparator ) {
    1394             this.sort();
    1395         }
    1396     },
    1397     /**
    1398      * Set the default comparator only when the `orderby` property is set.
    1399      *
    1400      * @access private
    1401      *
    1402      * @param {Backbone.Model} model
    1403      * @param {string} orderby
    1404      */
    1405     _changeOrderby: function( model, orderby ) {
    1406         // If a different comparator is defined, bail.
    1407         if ( this.comparator && this.comparator !== Attachments.comparator ) {
    1408             return;
    1409         }
    1410 
    1411         if ( orderby && 'post__in' !== orderby ) {
    1412             this.comparator = Attachments.comparator;
    1413         } else {
    1414             delete this.comparator;
    1415         }
    1416     },
    1417     /**
    1418      * If the `query` property is set to true, query the server using
    1419      * the `props` values, and sync the results to this collection.
    1420      *
    1421      * @access private
    1422      *
    1423      * @param {Backbone.Model} model
    1424      * @param {Boolean} query
    1425      */
    1426     _changeQuery: function( model, query ) {
    1427         if ( query ) {
    1428             this.props.on( 'change', this._requery, this );
    1429             this._requery();
    1430         } else {
    1431             this.props.off( 'change', this._requery, this );
    1432         }
    1433     },
    1434     /**
    1435      * @access private
    1436      *
    1437      * @param {Backbone.Model} model
    1438      */
    1439     _changeFilteredProps: function( model ) {
    1440         // If this is a query, updating the collection will be handled by
    1441         // `this._requery()`.
    1442         if ( this.props.get('query') ) {
    1443             return;
    1444         }
    1445 
    1446         var changed = _.chain( model.changed ).map( function( t, prop ) {
    1447             var filter = Attachments.filters[ prop ],
    1448                 term = model.get( prop );
    1449 
    1450             if ( ! filter ) {
    1451                 return;
    1452             }
    1453 
    1454             if ( term && ! this.filters[ prop ] ) {
    1455                 this.filters[ prop ] = filter;
    1456             } else if ( ! term && this.filters[ prop ] === filter ) {
    1457                 delete this.filters[ prop ];
    1458             } else {
    1459                 return;
    1460             }
    1461 
    1462             // Record the change.
    1463             return true;
    1464         }, this ).any().value();
    1465 
    1466         if ( ! changed ) {
    1467             return;
    1468         }
    1469 
    1470         // If no `Attachments` model is provided to source the searches
    1471         // from, then automatically generate a source from the existing
    1472         // models.
    1473         if ( ! this._source ) {
    1474             this._source = new Attachments( this.models );
    1475         }
    1476 
    1477         this.reset( this._source.filter( this.validator, this ) );
    1478     },
    1479 
    1480     validateDestroyed: false,
    1481     /**
    1482      * Checks whether an attachment is valid.
    1483      *
    1484      * @param {wp.media.model.Attachment} attachment
    1485      * @returns {Boolean}
    1486      */
    1487     validator: function( attachment ) {
    1488         if ( ! this.validateDestroyed && attachment.destroyed ) {
    1489             return false;
    1490         }
    1491         return _.all( this.filters, function( filter ) {
    1492             return !! filter.call( this, attachment );
    1493         }, this );
    1494     },
    1495     /**
    1496      * Add or remove an attachment to the collection depending on its validity.
    1497      *
    1498      * @param {wp.media.model.Attachment} attachment
    1499      * @param {Object} options
    1500      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1501      */
    1502     validate: function( attachment, options ) {
    1503         var valid = this.validator( attachment ),
    1504             hasAttachment = !! this.get( attachment.cid );
    1505 
    1506         if ( ! valid && hasAttachment ) {
    1507             this.remove( attachment, options );
    1508         } else if ( valid && ! hasAttachment ) {
    1509             this.add( attachment, options );
    1510         }
    1511 
    1512         return this;
    1513     },
    1514 
    1515     /**
    1516      * Add or remove all attachments from another collection depending on each one's validity.
    1517      *
    1518      * @param {wp.media.model.Attachments} attachments
    1519      * @param {object} [options={}]
    1520      *
    1521      * @fires wp.media.model.Attachments#reset
    1522      *
    1523      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1524      */
    1525     validateAll: function( attachments, options ) {
    1526         options = options || {};
    1527 
    1528         _.each( attachments.models, function( attachment ) {
    1529             this.validate( attachment, { silent: true });
    1530         }, this );
    1531 
    1532         if ( ! options.silent ) {
    1533             this.trigger( 'reset', this, options );
    1534         }
    1535         return this;
    1536     },
    1537     /**
    1538      * Start observing another attachments collection change events
    1539      * and replicate them on this collection.
    1540      *
    1541      * @param {wp.media.model.Attachments} The attachments collection to observe.
    1542      * @returns {wp.media.model.Attachments} Returns itself to allow chaining.
    1543      */
    1544     observe: function( attachments ) {
    1545         this.observers = this.observers || [];
    1546         this.observers.push( attachments );
    1547 
    1548         attachments.on( 'add change remove', this._validateHandler, this );
    1549         attachments.on( 'reset', this._validateAllHandler, this );
    1550         this.validateAll( attachments );
    1551         return this;
    1552     },
    1553     /**
    1554      * Stop replicating collection change events from another attachments collection.
    1555      *
    1556      * @param {wp.media.model.Attachments} The attachments collection to stop observing.
    1557      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1558      */
    1559     unobserve: function( attachments ) {
    1560         if ( attachments ) {
    1561             attachments.off( null, null, this );
    1562             this.observers = _.without( this.observers, attachments );
    1563 
    1564         } else {
    1565             _.each( this.observers, function( attachments ) {
    1566                 attachments.off( null, null, this );
    1567             }, this );
    1568             delete this.observers;
    1569         }
    1570 
    1571         return this;
    1572     },
    1573     /**
    1574      * @access private
    1575      *
    1576      * @param {wp.media.model.Attachments} attachment
    1577      * @param {wp.media.model.Attachments} attachments
    1578      * @param {Object} options
    1579      *
    1580      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1581      */
    1582     _validateHandler: function( attachment, attachments, options ) {
    1583         // If we're not mirroring this `attachments` collection,
    1584         // only retain the `silent` option.
    1585         options = attachments === this.mirroring ? options : {
    1586             silent: options && options.silent
    1587         };
    1588 
    1589         return this.validate( attachment, options );
    1590     },
    1591     /**
    1592      * @access private
    1593      *
    1594      * @param {wp.media.model.Attachments} attachments
    1595      * @param {Object} options
    1596      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1597      */
    1598     _validateAllHandler: function( attachments, options ) {
    1599         return this.validateAll( attachments, options );
    1600     },
    1601     /**
    1602      * Start mirroring another attachments collection, clearing out any models already
    1603      * in the collection.
    1604      *
    1605      * @param {wp.media.model.Attachments} The attachments collection to mirror.
    1606      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1607      */
    1608     mirror: function( attachments ) {
    1609         if ( this.mirroring && this.mirroring === attachments ) {
    1610             return this;
    1611         }
    1612 
    1613         this.unmirror();
    1614         this.mirroring = attachments;
    1615 
    1616         // Clear the collection silently. A `reset` event will be fired
    1617         // when `observe()` calls `validateAll()`.
    1618         this.reset( [], { silent: true } );
    1619         this.observe( attachments );
    1620 
    1621         return this;
    1622     },
    1623     /**
    1624      * Stop mirroring another attachments collection.
    1625      */
    1626     unmirror: function() {
    1627         if ( ! this.mirroring ) {
    1628             return;
    1629         }
    1630 
    1631         this.unobserve( this.mirroring );
    1632         delete this.mirroring;
    1633     },
    1634     /**
    1635      * Retrive more attachments from the server for the collection.
    1636      *
    1637      * Only works if the collection is mirroring a Query Attachments collection,
    1638      * and forwards to its `more` method. This collection class doesn't have
    1639      * server persistence by itself.
    1640      *
    1641      * @param {object} options
    1642      * @returns {Promise}
    1643      */
    1644     more: function( options ) {
    1645         var deferred = jQuery.Deferred(),
    1646             mirroring = this.mirroring,
    1647             attachments = this;
    1648 
    1649         if ( ! mirroring || ! mirroring.more ) {
    1650             return deferred.resolveWith( this ).promise();
    1651         }
    1652         // If we're mirroring another collection, forward `more` to
    1653         // the mirrored collection. Account for a race condition by
    1654         // checking if we're still mirroring that collection when
    1655         // the request resolves.
    1656         mirroring.more( options ).done( function() {
    1657             if ( this === attachments.mirroring )
    1658                 deferred.resolveWith( this );
    1659         });
    1660 
    1661         return deferred.promise();
    1662     },
    1663     /**
    1664      * Whether there are more attachments that haven't been sync'd from the server
    1665      * that match the collection's query.
    1666      *
    1667      * Only works if the collection is mirroring a Query Attachments collection,
    1668      * and forwards to its `hasMore` method. This collection class doesn't have
    1669      * server persistence by itself.
    1670      *
    1671      * @returns {boolean}
    1672      */
    1673     hasMore: function() {
    1674         return this.mirroring ? this.mirroring.hasMore() : false;
    1675     },
    1676     /**
    1677      * A custom AJAX-response parser.
    1678      *
    1679      * See trac ticket #24753
    1680      *
    1681      * @param {Object|Array} resp The raw response Object/Array.
    1682      * @param {Object} xhr
    1683      * @returns {Array} The array of model attributes to be added to the collection
    1684      */
    1685     parse: function( resp, xhr ) {
    1686         if ( ! _.isArray( resp ) ) {
    1687             resp = [resp];
    1688         }
    1689 
    1690         return _.map( resp, function( attrs ) {
    1691             var id, attachment, newAttributes;
    1692 
    1693             if ( attrs instanceof Backbone.Model ) {
    1694                 id = attrs.get( 'id' );
    1695                 attrs = attrs.attributes;
    1696             } else {
    1697                 id = attrs.id;
    1698             }
    1699 
    1700             attachment = Attachment.get( id );
    1701             newAttributes = attachment.parse( attrs, xhr );
    1702 
    1703             if ( ! _.isEqual( attachment.attributes, newAttributes ) ) {
    1704                 attachment.set( newAttributes );
    1705             }
    1706 
    1707             return attachment;
    1708         });
    1709     },
    1710     /**
    1711      * If the collection is a query, create and mirror an Attachments Query collection.
    1712      *
    1713      * @access private
    1714      */
    1715     _requery: function( refresh ) {
    1716         var props, Query;
    1717         if ( this.props.get('query') ) {
    1718             Query = require( './query.js' );
    1719             props = this.props.toJSON();
    1720             props.cache = ( true !== refresh );
    1721             this.mirror( Query.get( props ) );
    1722         }
    1723     },
    1724     /**
    1725      * If this collection is sorted by `menuOrder`, recalculates and saves
    1726      * the menu order to the database.
    1727      *
    1728      * @returns {undefined|Promise}
    1729      */
    1730     saveMenuOrder: function() {
    1731         if ( 'menuOrder' !== this.props.get('orderby') ) {
    1732             return;
    1733         }
    1734 
    1735         // Removes any uploading attachments, updates each attachment's
    1736         // menu order, and returns an object with an { id: menuOrder }
    1737         // mapping to pass to the request.
    1738         var attachments = this.chain().filter( function( attachment ) {
    1739             return ! _.isUndefined( attachment.id );
    1740         }).map( function( attachment, index ) {
    1741             // Indices start at 1.
    1742             index = index + 1;
    1743             attachment.set( 'menuOrder', index );
    1744             return [ attachment.id, index ];
    1745         }).object().value();
    1746 
    1747         if ( _.isEmpty( attachments ) ) {
    1748             return;
    1749         }
    1750 
    1751         return wp.media.post( 'save-attachment-order', {
    1752             nonce:       wp.media.model.settings.post.nonce,
    1753             post_id:     wp.media.model.settings.post.id,
    1754             attachments: attachments
    1755         });
    1756     }
    1757 }, {
    1758     /**
    1759      * A function to compare two attachment models in an attachments collection.
    1760      *
    1761      * Used as the default comparator for instances of wp.media.model.Attachments
    1762      * and its subclasses. @see wp.media.model.Attachments._changeOrderby().
    1763      *
    1764      * @static
    1765      *
    1766      * @param {Backbone.Model} a
    1767      * @param {Backbone.Model} b
    1768      * @param {Object} options
    1769      * @returns {Number} -1 if the first model should come before the second,
    1770      *    0 if they are of the same rank and
    1771      *    1 if the first model should come after.
    1772      */
    1773     comparator: function( a, b, options ) {
    1774         var key   = this.props.get('orderby'),
    1775             order = this.props.get('order') || 'DESC',
    1776             ac    = a.cid,
    1777             bc    = b.cid;
    1778 
    1779         a = a.get( key );
    1780         b = b.get( key );
    1781 
    1782         if ( 'date' === key || 'modified' === key ) {
    1783             a = a || new Date();
    1784             b = b || new Date();
    1785         }
    1786 
    1787         // If `options.ties` is set, don't enforce the `cid` tiebreaker.
    1788         if ( options && options.ties ) {
    1789             ac = bc = null;
    1790         }
    1791 
    1792         return ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );
    1793     },
    1794     /**
    1795      * @namespace
    1796      */
    1797     filters: {
    1798         /**
    1799          * @static
    1800          * Note that this client-side searching is *not* equivalent
    1801          * to our server-side searching.
    1802          *
    1803          * @param {wp.media.model.Attachment} attachment
    1804          *
    1805          * @this wp.media.model.Attachments
    1806          *
    1807          * @returns {Boolean}
    1808          */
    1809         search: function( attachment ) {
    1810             if ( ! this.props.get('search') ) {
    1811                 return true;
    1812             }
    1813 
    1814             return _.any(['title','filename','description','caption','name'], function( key ) {
    1815                 var value = attachment.get( key );
    1816                 return value && -1 !== value.search( this.props.get('search') );
    1817             }, this );
    1818         },
    1819         /**
    1820          * @static
    1821          * @param {wp.media.model.Attachment} attachment
    1822          *
    1823          * @this wp.media.model.Attachments
    1824          *
    1825          * @returns {Boolean}
    1826          */
    1827         type: function( attachment ) {
    1828             var type = this.props.get('type');
    1829             return ! type || -1 !== type.indexOf( attachment.get('type') );
    1830         },
    1831         /**
    1832          * @static
    1833          * @param {wp.media.model.Attachment} attachment
    1834          *
    1835          * @this wp.media.model.Attachments
    1836          *
    1837          * @returns {Boolean}
    1838          */
    1839         uploadedTo: function( attachment ) {
    1840             var uploadedTo = this.props.get('uploadedTo');
    1841             if ( _.isUndefined( uploadedTo ) ) {
    1842                 return true;
    1843             }
    1844 
    1845             return uploadedTo === attachment.get('uploadedTo');
    1846         },
    1847         /**
    1848          * @static
    1849          * @param {wp.media.model.Attachment} attachment
    1850          *
    1851          * @this wp.media.model.Attachments
    1852          *
    1853          * @returns {Boolean}
    1854          */
    1855         status: function( attachment ) {
    1856             var status = this.props.get('status');
    1857             if ( _.isUndefined( status ) ) {
    1858                 return true;
    1859             }
    1860 
    1861             return status === attachment.get('status');
    1862         }
    1863     }
    1864 });
    1865 
    1866 module.exports = Attachments;
    1867 },{"./attachment.js":9,"./query.js":12}],11:[function(require,module,exports){
    18681162/*globals Backbone, _, wp */
    18691163
     
    19081202
    19091203module.exports = PostMedia;
    1910 },{}],12:[function(require,module,exports){
    1911 /*globals jQuery, _, wp */
    1912 
    1913 /**
    1914  * wp.media.model.Query
    1915  *
    1916  * A collection of attachments that match the supplied query arguments.
    1917  *
    1918  * Note: Do NOT change this.args after the query has been initialized.
    1919  *       Things will break.
    1920  *
    1921  * @class
    1922  * @augments wp.media.model.Attachments
    1923  * @augments Backbone.Collection
    1924  *
    1925  * @param {array}  [models]                      Models to initialize with the collection.
    1926  * @param {object} [options]                     Options hash.
    1927  * @param {object} [options.args]                Attachments query arguments.
    1928  * @param {object} [options.args.posts_per_page]
    1929  */
    1930 var Attachments = require( './attachments.js' ),
    1931     Query;
    1932 
    1933 Query = Attachments.extend({
    1934     /**
    1935      * @global wp.Uploader
    1936      *
    1937      * @param {array}  [models=[]]  Array of initial models to populate the collection.
    1938      * @param {object} [options={}]
    1939      */
    1940     initialize: function( models, options ) {
    1941         var allowed;
    1942 
    1943         options = options || {};
    1944         Attachments.prototype.initialize.apply( this, arguments );
    1945 
    1946         this.args     = options.args;
    1947         this._hasMore = true;
    1948         this.created  = new Date();
    1949 
    1950         this.filters.order = function( attachment ) {
    1951             var orderby = this.props.get('orderby'),
    1952                 order = this.props.get('order');
    1953 
    1954             if ( ! this.comparator ) {
    1955                 return true;
    1956             }
    1957 
    1958             // We want any items that can be placed before the last
    1959             // item in the set. If we add any items after the last
    1960             // item, then we can't guarantee the set is complete.
    1961             if ( this.length ) {
    1962                 return 1 !== this.comparator( attachment, this.last(), { ties: true });
    1963 
    1964             // Handle the case where there are no items yet and
    1965             // we're sorting for recent items. In that case, we want
    1966             // changes that occurred after we created the query.
    1967             } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {
    1968                 return attachment.get( orderby ) >= this.created;
    1969 
    1970             // If we're sorting by menu order and we have no items,
    1971             // accept any items that have the default menu order (0).
    1972             } else if ( 'ASC' === order && 'menuOrder' === orderby ) {
    1973                 return attachment.get( orderby ) === 0;
    1974             }
    1975 
    1976             // Otherwise, we don't want any items yet.
    1977             return false;
    1978         };
    1979 
    1980         // Observe the central `wp.Uploader.queue` collection to watch for
    1981         // new matches for the query.
    1982         //
    1983         // Only observe when a limited number of query args are set. There
    1984         // are no filters for other properties, so observing will result in
    1985         // false positives in those queries.
    1986         allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent' ];
    1987         if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {
    1988             this.observe( wp.Uploader.queue );
    1989         }
    1990     },
    1991     /**
    1992      * Whether there are more attachments that haven't been sync'd from the server
    1993      * that match the collection's query.
    1994      *
    1995      * @returns {boolean}
    1996      */
    1997     hasMore: function() {
    1998         return this._hasMore;
    1999     },
    2000     /**
    2001      * Fetch more attachments from the server for the collection.
    2002      *
    2003      * @param   {object}  [options={}]
    2004      * @returns {Promise}
    2005      */
    2006     more: function( options ) {
    2007         var query = this;
    2008 
    2009         // If there is already a request pending, return early with the Deferred object.
    2010         if ( this._more && 'pending' === this._more.state() ) {
    2011             return this._more;
    2012         }
    2013 
    2014         if ( ! this.hasMore() ) {
    2015             return jQuery.Deferred().resolveWith( this ).promise();
    2016         }
    2017 
    2018         options = options || {};
    2019         options.remove = false;
    2020 
    2021         return this._more = this.fetch( options ).done( function( resp ) {
    2022             if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {
    2023                 query._hasMore = false;
    2024             }
    2025         });
    2026     },
    2027     /**
    2028      * Overrides Backbone.Collection.sync
    2029      * Overrides wp.media.model.Attachments.sync
    2030      *
    2031      * @param {String} method
    2032      * @param {Backbone.Model} model
    2033      * @param {Object} [options={}]
    2034      * @returns {Promise}
    2035      */
    2036     sync: function( method, model, options ) {
    2037         var args, fallback;
    2038 
    2039         // Overload the read method so Attachment.fetch() functions correctly.
    2040         if ( 'read' === method ) {
    2041             options = options || {};
    2042             options.context = this;
    2043             options.data = _.extend( options.data || {}, {
    2044                 action:  'query-attachments',
    2045                 post_id: wp.media.model.settings.post.id
    2046             });
    2047 
    2048             // Clone the args so manipulation is non-destructive.
    2049             args = _.clone( this.args );
    2050 
    2051             // Determine which page to query.
    2052             if ( -1 !== args.posts_per_page ) {
    2053                 args.paged = Math.floor( this.length / args.posts_per_page ) + 1;
    2054             }
    2055 
    2056             options.data.query = args;
    2057             return wp.media.ajax( options );
    2058 
    2059         // Otherwise, fall back to Backbone.sync()
    2060         } else {
    2061             /**
    2062              * Call wp.media.model.Attachments.sync or Backbone.sync
    2063              */
    2064             fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
    2065             return fallback.sync.apply( this, arguments );
    2066         }
    2067     }
    2068 }, {
    2069     /**
    2070      * @readonly
    2071      */
    2072     defaultProps: {
    2073         orderby: 'date',
    2074         order:   'DESC'
    2075     },
    2076     /**
    2077      * @readonly
    2078      */
    2079     defaultArgs: {
    2080         posts_per_page: 40
    2081     },
    2082     /**
    2083      * @readonly
    2084      */
    2085     orderby: {
    2086         allowed:  [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],
    2087         /**
    2088          * A map of JavaScript orderby values to their WP_Query equivalents.
    2089          * @type {Object}
    2090          */
    2091         valuemap: {
    2092             'id':         'ID',
    2093             'uploadedTo': 'parent',
    2094             'menuOrder':  'menu_order ID'
    2095         }
    2096     },
    2097     /**
    2098      * A map of JavaScript query properties to their WP_Query equivalents.
    2099      *
    2100      * @readonly
    2101      */
    2102     propmap: {
    2103         'search':    's',
    2104         'type':      'post_mime_type',
    2105         'perPage':   'posts_per_page',
    2106         'menuOrder': 'menu_order',
    2107         'uploadedTo': 'post_parent',
    2108         'status':     'post_status',
    2109         'include':    'post__in',
    2110         'exclude':    'post__not_in'
    2111     },
    2112     /**
    2113      * Creates and returns an Attachments Query collection given the properties.
    2114      *
    2115      * Caches query objects and reuses where possible.
    2116      *
    2117      * @static
    2118      * @method
    2119      *
    2120      * @param {object} [props]
    2121      * @param {Object} [props.cache=true]   Whether to use the query cache or not.
    2122      * @param {Object} [props.order]
    2123      * @param {Object} [props.orderby]
    2124      * @param {Object} [props.include]
    2125      * @param {Object} [props.exclude]
    2126      * @param {Object} [props.s]
    2127      * @param {Object} [props.post_mime_type]
    2128      * @param {Object} [props.posts_per_page]
    2129      * @param {Object} [props.menu_order]
    2130      * @param {Object} [props.post_parent]
    2131      * @param {Object} [props.post_status]
    2132      * @param {Object} [options]
    2133      *
    2134      * @returns {wp.media.model.Query} A new Attachments Query collection.
    2135      */
    2136     get: (function(){
    2137         /**
    2138          * @static
    2139          * @type Array
    2140          */
    2141         var queries = [];
    2142 
    2143         /**
    2144          * @returns {Query}
    2145          */
    2146         return function( props, options ) {
    2147             var args     = {},
    2148                 orderby  = Query.orderby,
    2149                 defaults = Query.defaultProps,
    2150                 query,
    2151                 cache    = !! props.cache || _.isUndefined( props.cache );
    2152 
    2153             // Remove the `query` property. This isn't linked to a query,
    2154             // this *is* the query.
    2155             delete props.query;
    2156             delete props.cache;
    2157 
    2158             // Fill default args.
    2159             _.defaults( props, defaults );
    2160 
    2161             // Normalize the order.
    2162             props.order = props.order.toUpperCase();
    2163             if ( 'DESC' !== props.order && 'ASC' !== props.order ) {
    2164                 props.order = defaults.order.toUpperCase();
    2165             }
    2166 
    2167             // Ensure we have a valid orderby value.
    2168             if ( ! _.contains( orderby.allowed, props.orderby ) ) {
    2169                 props.orderby = defaults.orderby;
    2170             }
    2171 
    2172             _.each( [ 'include', 'exclude' ], function( prop ) {
    2173                 if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {
    2174                     props[ prop ] = [ props[ prop ] ];
    2175                 }
    2176             } );
    2177 
    2178             // Generate the query `args` object.
    2179             // Correct any differing property names.
    2180             _.each( props, function( value, prop ) {
    2181                 if ( _.isNull( value ) ) {
    2182                     return;
    2183                 }
    2184 
    2185                 args[ Query.propmap[ prop ] || prop ] = value;
    2186             });
    2187 
    2188             // Fill any other default query args.
    2189             _.defaults( args, Query.defaultArgs );
    2190 
    2191             // `props.orderby` does not always map directly to `args.orderby`.
    2192             // Substitute exceptions specified in orderby.keymap.
    2193             args.orderby = orderby.valuemap[ props.orderby ] || props.orderby;
    2194 
    2195             // Search the query cache for a matching query.
    2196             if ( cache ) {
    2197                 query = _.find( queries, function( query ) {
    2198                     return _.isEqual( query.args, args );
    2199                 });
    2200             } else {
    2201                 queries = [];
    2202             }
    2203 
    2204             // Otherwise, create a new query and add it to the cache.
    2205             if ( ! query ) {
    2206                 query = new Query( [], _.extend( options || {}, {
    2207                     props: props,
    2208                     args:  args
    2209                 } ) );
    2210                 queries.push( query );
    2211             }
    2212 
    2213             return query;
    2214         };
    2215     }())
    2216 });
    2217 
    2218 module.exports = Query;
    2219 },{"./attachments.js":10}],13:[function(require,module,exports){
    2220 /*globals _ */
    2221 
    2222 /**
    2223  * wp.media.model.Selection
    2224  *
    2225  * A selection of attachments.
    2226  *
    2227  * @class
    2228  * @augments wp.media.model.Attachments
    2229  * @augments Backbone.Collection
    2230  */
    2231 var Attachments = require( './attachments.js' ),
    2232     Selection;
    2233 
    2234 Selection = Attachments.extend({
    2235     /**
    2236      * Refresh the `single` model whenever the selection changes.
    2237      * Binds `single` instead of using the context argument to ensure
    2238      * it receives no parameters.
    2239      *
    2240      * @param {Array} [models=[]] Array of models used to populate the collection.
    2241      * @param {Object} [options={}]
    2242      */
    2243     initialize: function( models, options ) {
    2244         /**
    2245          * call 'initialize' directly on the parent class
    2246          */
    2247         Attachments.prototype.initialize.apply( this, arguments );
    2248         this.multiple = options && options.multiple;
    2249 
    2250         this.on( 'add remove reset', _.bind( this.single, this, false ) );
    2251     },
    2252 
    2253     /**
    2254      * If the workflow does not support multi-select, clear out the selection
    2255      * before adding a new attachment to it.
    2256      *
    2257      * @param {Array} models
    2258      * @param {Object} options
    2259      * @returns {wp.media.model.Attachment[]}
    2260      */
    2261     add: function( models, options ) {
    2262         if ( ! this.multiple ) {
    2263             this.remove( this.models );
    2264         }
    2265         /**
    2266          * call 'add' directly on the parent class
    2267          */
    2268         return Attachments.prototype.add.call( this, models, options );
    2269     },
    2270 
    2271     /**
    2272      * Fired when toggling (clicking on) an attachment in the modal.
    2273      *
    2274      * @param {undefined|boolean|wp.media.model.Attachment} model
    2275      *
    2276      * @fires wp.media.model.Selection#selection:single
    2277      * @fires wp.media.model.Selection#selection:unsingle
    2278      *
    2279      * @returns {Backbone.Model}
    2280      */
    2281     single: function( model ) {
    2282         var previous = this._single;
    2283 
    2284         // If a `model` is provided, use it as the single model.
    2285         if ( model ) {
    2286             this._single = model;
    2287         }
    2288         // If the single model isn't in the selection, remove it.
    2289         if ( this._single && ! this.get( this._single.cid ) ) {
    2290             delete this._single;
    2291         }
    2292 
    2293         this._single = this._single || this.last();
    2294 
    2295         // If single has changed, fire an event.
    2296         if ( this._single !== previous ) {
    2297             if ( previous ) {
    2298                 previous.trigger( 'selection:unsingle', previous, this );
    2299 
    2300                 // If the model was already removed, trigger the collection
    2301                 // event manually.
    2302                 if ( ! this.get( previous.cid ) ) {
    2303                     this.trigger( 'selection:unsingle', previous, this );
    2304                 }
    2305             }
    2306             if ( this._single ) {
    2307                 this._single.trigger( 'selection:single', this._single, this );
    2308             }
    2309         }
    2310 
    2311         // Return the single model, or the last model as a fallback.
    2312         return this._single;
    2313     }
    2314 });
    2315 
    2316 module.exports = Selection;
    2317 },{"./attachments.js":10}],14:[function(require,module,exports){
     1204},{}],10:[function(require,module,exports){
    23181205/*globals _ */
    23191206
     
    23821269
    23831270module.exports = selectionSync;
    2384 },{}],15:[function(require,module,exports){
     1271},{}],11:[function(require,module,exports){
    23851272/*globals _ */
    23861273
     
    24681355
    24691356module.exports = AttachmentCompat;
    2470 },{"./view.js":55}],16:[function(require,module,exports){
     1357},{"./view.js":51}],12:[function(require,module,exports){
    24711358/*globals _, jQuery */
    24721359
     
    25471434
    25481435module.exports = AttachmentFilters;
    2549 },{"./view.js":55}],17:[function(require,module,exports){
     1436},{"./view.js":51}],13:[function(require,module,exports){
    25501437/*globals _, wp */
    25511438
     
    26391526
    26401527module.exports = All;
    2641 },{"../attachment-filters.js":16}],18:[function(require,module,exports){
     1528},{"../attachment-filters.js":12}],14:[function(require,module,exports){
    26421529/*globals _, wp */
    26431530
     
    26821569
    26831570module.exports = DateFilter;
    2684 },{"../attachment-filters.js":16}],19:[function(require,module,exports){
     1571},{"../attachment-filters.js":12}],15:[function(require,module,exports){
    26851572/*globals wp */
    26861573
     
    27431630
    27441631module.exports = Uploaded;
    2745 },{"../attachment-filters.js":16}],20:[function(require,module,exports){
     1632},{"../attachment-filters.js":12}],16:[function(require,module,exports){
    27461633/*globals _, wp, jQuery */
    27471634
     
    32982185
    32992186module.exports = Attachment;
    3300 },{"./view.js":55}],21:[function(require,module,exports){
     2187},{"./view.js":51}],17:[function(require,module,exports){
    33012188/*globals _, wp */
    33022189
     
    34392326
    34402327module.exports = Details;
    3441 },{"../attachment.js":20}],22:[function(require,module,exports){
     2328},{"../attachment.js":16}],18:[function(require,module,exports){
    34422329/**
    34432330 * wp.media.view.Attachment.Library
     
    34592346
    34602347module.exports = Library;
    3461 },{"../attachment.js":20}],23:[function(require,module,exports){
     2348},{"../attachment.js":16}],19:[function(require,module,exports){
    34622349/*globals _, wp, jQuery */
    34632350
     
    37602647
    37612648module.exports = Attachments;
    3762 },{"./attachment.js":20,"./view.js":55}],24:[function(require,module,exports){
     2649},{"./attachment.js":16,"./view.js":51}],20:[function(require,module,exports){
    37632650/*globals _, wp, jQuery */
    37642651
     
    42203107
    42213108module.exports = AttachmentsBrowser;
    4222 },{"../attachment-compat.js":15,"../attachment-filters/all.js":17,"../attachment-filters/date.js":18,"../attachment-filters/uploaded.js":19,"../attachment/details.js":21,"../attachment/library.js":22,"../attachments.js":23,"../label.js":34,"../search.js":43,"../settings/attachment-display.js":45,"../sidebar.js":46,"../spinner.js":47,"../toolbar.js":48,"../uploader/inline.js":50,"../uploader/status.js":52,"../view.js":55}],25:[function(require,module,exports){
     3109},{"../attachment-compat.js":11,"../attachment-filters/all.js":13,"../attachment-filters/date.js":14,"../attachment-filters/uploaded.js":15,"../attachment/details.js":17,"../attachment/library.js":18,"../attachments.js":19,"../label.js":30,"../search.js":39,"../settings/attachment-display.js":41,"../sidebar.js":42,"../spinner.js":43,"../toolbar.js":44,"../uploader/inline.js":46,"../uploader/status.js":48,"../view.js":51}],21:[function(require,module,exports){
    42233110/*globals wp */
    42243111
     
    42593146
    42603147module.exports = AudioDetails;
    4261 },{"./media-details":35}],26:[function(require,module,exports){
     3148},{"./media-details":31}],22:[function(require,module,exports){
    42623149/*globals _, Backbone */
    42633150
     
    43493236
    43503237module.exports = Button;
    4351 },{"./view.js":55}],27:[function(require,module,exports){
     3238},{"./view.js":51}],23:[function(require,module,exports){
    43523239/**
    43533240 * wp.media.view.FocusManager
     
    43973284
    43983285module.exports = FocusManager;
    4399 },{"./view.js":55}],28:[function(require,module,exports){
     3286},{"./view.js":51}],24:[function(require,module,exports){
    44003287/*globals _, Backbone */
    44013288
     
    45703457
    45713458module.exports = Frame;
    4572 },{"../controllers/region.js":5,"../controllers/state-machine.js":6,"../controllers/state.js":7,"./view.js":55}],29:[function(require,module,exports){
     3459},{"../controllers/region.js":5,"../controllers/state-machine.js":6,"../controllers/state.js":7,"./view.js":51}],25:[function(require,module,exports){
    45733460/*globals wp */
    45743461
     
    46483535
    46493536module.exports = AudioDetails;
    4650 },{"../../controllers/audio-details.js":2,"../../controllers/media-library.js":4,"../audio-details.js":25,"./media-details":30}],30:[function(require,module,exports){
     3537},{"../../controllers/audio-details.js":2,"../../controllers/media-library.js":4,"../audio-details.js":21,"./media-details":26}],26:[function(require,module,exports){
    46513538/*globals wp */
    46523539
     
    46663553    Toolbar = require( '../toolbar.js' ),
    46673554    Select = require( './select.js' ),
    4668     Selection = require( '../../models/selection.js' ),
    4669     PostMedia = require( '../../models/post-media.js' ),
    46703555    l10n = wp.media.view.l10n,
    46713556    MediaDetails;
     
    46873572        this.addText = options.addText;
    46883573
    4689         this.media = new PostMedia( options.metadata );
    4690         this.options.selection = new Selection( this.media.attachment, { multiple: false } );
     3574        this.media = new wp.media.model.PostMedia( options.metadata );
     3575        this.options.selection = new wp.media.model.Selection( this.media.attachment, { multiple: false } );
    46913576        Select.prototype.initialize.apply( this, arguments );
    46923577    },
     
    47833668
    47843669module.exports = MediaDetails;
    4785 },{"../../models/post-media.js":11,"../../models/selection.js":13,"../toolbar.js":48,"../view.js":55,"./select.js":31}],31:[function(require,module,exports){
     3670},{"../toolbar.js":44,"../view.js":51,"./select.js":27}],27:[function(require,module,exports){
    47863671/*globals _, wp */
    47873672
     
    48023687var MediaFrame = require( '../media-frame.js' ),
    48033688    Library = require( '../../controllers/library.js' ),
    4804     AttachmentsModel = require( '../../models/attachments.js' ),
    4805     SelectionModel = require( '../../models/selection.js' ),
    48063689    AttachmentsBrowser = require( '../attachments/browser.js' ),
    48073690    UploaderInline = require( '../uploader/inline.js' ),
     
    48393722        var selection = this.options.selection;
    48403723
    4841         if ( ! (selection instanceof SelectionModel) ) {
    4842             this.options.selection = new SelectionModel( selection, {
     3724        if ( ! (selection instanceof wp.media.model.Selection) ) {
     3725            this.options.selection = new wp.media.model.Selection( selection, {
    48433726                multiple: this.options.multiple
    48443727            });
     
    48463729
    48473730        this._selection = {
    4848             attachments: new AttachmentsModel(),
     3731            attachments: new wp.media.model.Attachments(),
    48493732            difference: []
    48503733        };
     
    49603843
    49613844module.exports = Select;
    4962 },{"../../controllers/library.js":3,"../../models/attachments.js":10,"../../models/selection.js":13,"../attachments/browser.js":24,"../media-frame.js":36,"../toolbar/select.js":49,"../uploader/inline.js":50}],32:[function(require,module,exports){
     3845},{"../../controllers/library.js":3,"../attachments/browser.js":20,"../media-frame.js":32,"../toolbar/select.js":45,"../uploader/inline.js":46}],28:[function(require,module,exports){
    49633846/*globals _, wp */
    49643847
     
    50983981
    50993982module.exports = VideoDetails;
    5100 },{"../../controllers/media-library.js":4,"../../controllers/video-details.js":8,"../video-details.js":54,"./media-details":30}],33:[function(require,module,exports){
     3983},{"../../controllers/media-library.js":4,"../../controllers/video-details.js":8,"../video-details.js":50,"./media-details":26}],29:[function(require,module,exports){
    51013984/**
    51023985 * wp.media.view.Iframe
     
    51244007
    51254008module.exports = Iframe;
    5126 },{"./view.js":55}],34:[function(require,module,exports){
     4009},{"./view.js":51}],30:[function(require,module,exports){
    51274010/**
    51284011 * @class
     
    51504033
    51514034module.exports = Label;
    5152 },{"./view.js":55}],35:[function(require,module,exports){
     4035},{"./view.js":51}],31:[function(require,module,exports){
    51534036/*globals _, wp, jQuery */
    51544037
     
    53024185
    53034186module.exports = MediaDetails;
    5304 },{"./settings/attachment-display.js":45}],36:[function(require,module,exports){
     4187},{"./settings/attachment-display.js":41}],32:[function(require,module,exports){
    53054188/*globals _, wp, jQuery */
    53064189
     
    55574440
    55584441module.exports = MediaFrame;
    5559 },{"./frame.js":28,"./iframe.js":33,"./menu.js":38,"./modal.js":39,"./router.js":42,"./toolbar.js":48,"./uploader/window.js":53,"./view.js":55}],37:[function(require,module,exports){
     4442},{"./frame.js":24,"./iframe.js":29,"./menu.js":34,"./modal.js":35,"./router.js":38,"./toolbar.js":44,"./uploader/window.js":49,"./view.js":51}],33:[function(require,module,exports){
    55604443/*globals wp, jQuery */
    55614444
     
    56314514
    56324515module.exports = MenuItem;
    5633 },{"./view.js":55}],38:[function(require,module,exports){
     4516},{"./view.js":51}],34:[function(require,module,exports){
    56344517/**
    56354518 * wp.media.view.Menu
     
    57474630
    57484631module.exports = Menu;
    5749 },{"./menu-item.js":37,"./priority-list.js":40}],39:[function(require,module,exports){
     4632},{"./menu-item.js":33,"./priority-list.js":36}],35:[function(require,module,exports){
    57504633/*globals _, wp, jQuery */
    57514634
     
    59634846
    59644847module.exports = Modal;
    5965 },{"./focus-manager.js":27,"./view.js":55}],40:[function(require,module,exports){
     4848},{"./focus-manager.js":23,"./view.js":51}],36:[function(require,module,exports){
    59664849/*globals _, Backbone */
    59674850
     
    60644947
    60654948module.exports = PriorityList;
    6066 },{"./view.js":55}],41:[function(require,module,exports){
     4949},{"./view.js":51}],37:[function(require,module,exports){
    60674950/**
    60684951 * wp.media.view.RouterItem
     
    60904973
    60914974module.exports = RouterItem;
    6092 },{"./menu-item.js":37}],42:[function(require,module,exports){
     4975},{"./menu-item.js":33}],38:[function(require,module,exports){
    60934976/**
    60944977 * wp.media.view.Router
     
    61275010
    61285011module.exports = Router;
    6129 },{"./menu.js":38,"./router-item.js":41}],43:[function(require,module,exports){
     5012},{"./menu.js":34,"./router-item.js":37}],39:[function(require,module,exports){
    61305013/*globals wp */
    61315014
     
    61775060
    61785061module.exports = Search;
    6179 },{"./view.js":55}],44:[function(require,module,exports){
     5062},{"./view.js":51}],40:[function(require,module,exports){
    61805063/*globals _, Backbone, jQuery */
    61815064
     
    62995182
    63005183module.exports = Settings;
    6301 },{"./view.js":55}],45:[function(require,module,exports){
     5184},{"./view.js":51}],41:[function(require,module,exports){
    63025185/*globals _, wp */
    63035186
     
    63945277
    63955278module.exports = AttachmentDisplay;
    6396 },{"../settings.js":44}],46:[function(require,module,exports){
     5279},{"../settings.js":40}],42:[function(require,module,exports){
    63975280/**
    63985281 * wp.media.view.Sidebar
     
    64125295
    64135296module.exports = Sidebar;
    6414 },{"./priority-list.js":40}],47:[function(require,module,exports){
     5297},{"./priority-list.js":36}],43:[function(require,module,exports){
    64155298/*globals _, wp */
    64165299
     
    64515334
    64525335module.exports = Spinner;
    6453 },{"./view.js":55}],48:[function(require,module,exports){
     5336},{"./view.js":51}],44:[function(require,module,exports){
    64545337/*globals Backbone, _ */
    64555338
     
    66145497
    66155498module.exports = Toolbar;
    6616 },{"./button.js":26,"./priority-list.js":40,"./view.js":55}],49:[function(require,module,exports){
     5499},{"./button.js":22,"./priority-list.js":36,"./view.js":51}],45:[function(require,module,exports){
    66175500/*globals _, wp */
    66185501
     
    66855568
    66865569module.exports = Select;
    6687 },{"../toolbar.js":48}],50:[function(require,module,exports){
     5570},{"../toolbar.js":44}],46:[function(require,module,exports){
    66885571/*globals _, wp */
    66895572
     
    68185701
    68195702module.exports = UploaderInline;
    6820 },{"../view.js":55,"./status.js":52}],51:[function(require,module,exports){
     5703},{"../view.js":51,"./status.js":48}],47:[function(require,module,exports){
    68215704/*globals wp */
    68225705
     
    68385721
    68395722module.exports = UploaderStatusError;
    6840 },{"../view.js":55}],52:[function(require,module,exports){
     5723},{"../view.js":51}],48:[function(require,module,exports){
    68415724/*globals _, wp */
    68425725
     
    69785861
    69795862module.exports = UploaderStatus;
    6980 },{"../view.js":55,"./status-error.js":51}],53:[function(require,module,exports){
     5863},{"../view.js":51,"./status-error.js":47}],49:[function(require,module,exports){
    69815864/*globals _, wp, jQuery */
    69825865
     
    70915974
    70925975module.exports = UploaderWindow;
    7093 },{"../view.js":55}],54:[function(require,module,exports){
     5976},{"../view.js":51}],50:[function(require,module,exports){
    70945977/*globals wp */
    70955978
     
    71356018
    71366019module.exports = VideoDetails;
    7137 },{"./media-details":35}],55:[function(require,module,exports){
     6020},{"./media-details":31}],51:[function(require,module,exports){
    71386021/*globals wp */
    71396022
  • trunk/src/wp-includes/js/media/controllers/collection-add.js

    r31373 r31379  
    3434 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
    3535 */
    36 var Selection = require( '../models/selection.js' ),
     36var Selection = wp.media.model.Selection,
    3737    Library = require( './library.js' ),
    3838    CollectionAdd;
  • trunk/src/wp-includes/js/media/controllers/collection-edit.js

    r31373 r31379  
    3535 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
    3636 */
    37 var Selection = require( '../models/selection.js' ),
    38     Library = require( './library.js' ),
     37var Library = require( './library.js' ),
    3938    View = require( '../views/view.js' ),
    4039    EditLibraryView = require( '../views/attachment/edit-library.js' ),
     
    7372        // If we haven't been provided a `library`, create a `Selection`.
    7473        if ( ! this.get('library') ) {
    75             this.set( 'library', new Selection() );
     74            this.set( 'library', new wp.media.model.Selection() );
    7675        }
    7776        // The single `Attachment` view to be used in the `Attachments` view.
  • trunk/src/wp-includes/js/media/controllers/featured-image.js

    r31373 r31379  
    3232 * @param {boolean}                    [attributes.syncSelection=true]       Whether the Attachments selection should be persisted from the last state.
    3333 */
    34 var Attachment = require( '../models/attachment.js' ),
     34var Attachment = wp.media.model.Attachment,
    3535    Library = require( './library.js' ),
    3636    l10n = wp.media.view.l10n,
  • trunk/src/wp-includes/js/media/controllers/gallery-add.js

    r31373 r31379  
    3030 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
    3131 */
    32 var Selection = require( '../models/selection.js' ),
     32var Selection = wp.media.model.Selection,
    3333    Library = require( './library.js' ),
    3434    l10n = wp.media.view.l10n,
  • trunk/src/wp-includes/js/media/controllers/gallery-edit.js

    r31373 r31379  
    3232 *                                                                        If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
    3333 */
    34 var Selection = require( '../models/selection.js' ),
    35     Library = require( './library.js' ),
     34var Library = require( './library.js' ),
    3635    EditLibraryView = require( '../views/attachment/edit-library.js' ),
    3736    GallerySettingsView = require( '../views/settings/gallery.js' ),
     
    6463        // If we haven't been provided a `library`, create a `Selection`.
    6564        if ( ! this.get('library') )
    66             this.set( 'library', new Selection() );
     65            this.set( 'library', new wp.media.model.Selection() );
    6766
    6867        // The single `Attachment` view to be used in the `Attachments` view.
  • trunk/src/wp-includes/js/media/controllers/library.js

    r31373 r31379  
    3636 */
    3737var selectionSync = require( '../utils/selection-sync.js' ),
    38     Selection = require( '../models/selection.js' ),
    3938    State = require( './state.js' ),
    4039    l10n = wp.media.view.l10n,
     
    8180            }
    8281
    83             this.set( 'selection', new Selection( null, {
     82            this.set( 'selection', new wp.media.model.Selection( null, {
    8483                multiple: this.get('multiple'),
    8584                props: props
  • trunk/src/wp-includes/js/media/grid.js

    r31373 r31379  
    108108
    109109module.exports = EditImage;
    110 },{"../views/toolbar.js":50,"./state.js":6}],3:[function(require,module,exports){
     110},{"../views/toolbar.js":46,"./state.js":6}],3:[function(require,module,exports){
    111111/*globals _, wp, Backbone, getUserSetting, setUserSetting */
    112112
     
    146146 */
    147147var selectionSync = require( '../utils/selection-sync.js' ),
    148     Selection = require( '../models/selection.js' ),
    149148    State = require( './state.js' ),
    150149    l10n = wp.media.view.l10n,
     
    191190            }
    192191
    193             this.set( 'selection', new Selection( null, {
     192            this.set( 'selection', new wp.media.model.Selection( null, {
    194193                multiple: this.get('multiple'),
    195194                props: props
     
    382381
    383382module.exports = Library;
    384 },{"../models/selection.js":11,"../utils/selection-sync.js":13,"./state.js":6}],4:[function(require,module,exports){
     383},{"../utils/selection-sync.js":9,"./state.js":6}],4:[function(require,module,exports){
    385384/*globals _, Backbone */
    386385
     
    945944
    946945}(wp));
    947 },{"./controllers/edit-attachment-metadata.js":1,"./routers/manage.js":12,"./views/attachment/details-two-column.js":20,"./views/button/delete-selected-permanently.js":26,"./views/button/delete-selected.js":27,"./views/button/select-mode-toggle.js":28,"./views/edit-image-details.js":29,"./views/frame/edit-attachments.js":33,"./views/frame/manage.js":34}],8:[function(require,module,exports){
    948 /*globals jQuery, Backbone, _, wp */
    949 
    950 /**
    951  * wp.media.model.Attachment
    952  *
    953  * @class
    954  * @augments Backbone.Model
    955  */
    956 var $ = jQuery,
    957     Attachment;
    958 
    959 Attachment = Backbone.Model.extend({
    960     /**
    961      * Triggered when attachment details change
    962      * Overrides Backbone.Model.sync
    963      *
    964      * @param {string} method
    965      * @param {wp.media.model.Attachment} model
    966      * @param {Object} [options={}]
    967      *
    968      * @returns {Promise}
    969      */
    970     sync: function( method, model, options ) {
    971         // If the attachment does not yet have an `id`, return an instantly
    972         // rejected promise. Otherwise, all of our requests will fail.
    973         if ( _.isUndefined( this.id ) ) {
    974             return $.Deferred().rejectWith( this ).promise();
    975         }
    976 
    977         // Overload the `read` request so Attachment.fetch() functions correctly.
    978         if ( 'read' === method ) {
    979             options = options || {};
    980             options.context = this;
    981             options.data = _.extend( options.data || {}, {
    982                 action: 'get-attachment',
    983                 id: this.id
    984             });
    985             return wp.media.ajax( options );
    986 
    987         // Overload the `update` request so properties can be saved.
    988         } else if ( 'update' === method ) {
    989             // If we do not have the necessary nonce, fail immeditately.
    990             if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    991                 return $.Deferred().rejectWith( this ).promise();
    992             }
    993 
    994             options = options || {};
    995             options.context = this;
    996 
    997             // Set the action and ID.
    998             options.data = _.extend( options.data || {}, {
    999                 action:  'save-attachment',
    1000                 id:      this.id,
    1001                 nonce:   this.get('nonces').update,
    1002                 post_id: wp.media.model.settings.post.id
    1003             });
    1004 
    1005             // Record the values of the changed attributes.
    1006             if ( model.hasChanged() ) {
    1007                 options.data.changes = {};
    1008 
    1009                 _.each( model.changed, function( value, key ) {
    1010                     options.data.changes[ key ] = this.get( key );
    1011                 }, this );
    1012             }
    1013 
    1014             return wp.media.ajax( options );
    1015 
    1016         // Overload the `delete` request so attachments can be removed.
    1017         // This will permanently delete an attachment.
    1018         } else if ( 'delete' === method ) {
    1019             options = options || {};
    1020 
    1021             if ( ! options.wait ) {
    1022                 this.destroyed = true;
    1023             }
    1024 
    1025             options.context = this;
    1026             options.data = _.extend( options.data || {}, {
    1027                 action:   'delete-post',
    1028                 id:       this.id,
    1029                 _wpnonce: this.get('nonces')['delete']
    1030             });
    1031 
    1032             return wp.media.ajax( options ).done( function() {
    1033                 this.destroyed = true;
    1034             }).fail( function() {
    1035                 this.destroyed = false;
    1036             });
    1037 
    1038         // Otherwise, fall back to `Backbone.sync()`.
    1039         } else {
    1040             /**
    1041              * Call `sync` directly on Backbone.Model
    1042              */
    1043             return Backbone.Model.prototype.sync.apply( this, arguments );
    1044         }
    1045     },
    1046     /**
    1047      * Convert date strings into Date objects.
    1048      *
    1049      * @param {Object} resp The raw response object, typically returned by fetch()
    1050      * @returns {Object} The modified response object, which is the attributes hash
    1051      *    to be set on the model.
    1052      */
    1053     parse: function( resp ) {
    1054         if ( ! resp ) {
    1055             return resp;
    1056         }
    1057 
    1058         resp.date = new Date( resp.date );
    1059         resp.modified = new Date( resp.modified );
    1060         return resp;
    1061     },
    1062     /**
    1063      * @param {Object} data The properties to be saved.
    1064      * @param {Object} options Sync options. e.g. patch, wait, success, error.
    1065      *
    1066      * @this Backbone.Model
    1067      *
    1068      * @returns {Promise}
    1069      */
    1070     saveCompat: function( data, options ) {
    1071         var model = this;
    1072 
    1073         // If we do not have the necessary nonce, fail immeditately.
    1074         if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    1075             return $.Deferred().rejectWith( this ).promise();
    1076         }
    1077 
    1078         return media.post( 'save-attachment-compat', _.defaults({
    1079             id:      this.id,
    1080             nonce:   this.get('nonces').update,
    1081             post_id: wp.media.model.settings.post.id
    1082         }, data ) ).done( function( resp, status, xhr ) {
    1083             model.set( model.parse( resp, xhr ), options );
    1084         });
    1085     }
    1086 }, {
    1087     /**
    1088      * Create a new model on the static 'all' attachments collection and return it.
    1089      *
    1090      * @static
    1091      * @param {Object} attrs
    1092      * @returns {wp.media.model.Attachment}
    1093      */
    1094     create: function( attrs ) {
    1095         var Attachments = require( './attachments.js' );
    1096         return Attachments.all.push( attrs );
    1097     },
    1098     /**
    1099      * Create a new model on the static 'all' attachments collection and return it.
    1100      *
    1101      * If this function has already been called for the id,
    1102      * it returns the specified attachment.
    1103      *
    1104      * @static
    1105      * @param {string} id A string used to identify a model.
    1106      * @param {Backbone.Model|undefined} attachment
    1107      * @returns {wp.media.model.Attachment}
    1108      */
    1109     get: _.memoize( function( id, attachment ) {
    1110         var Attachments = require( './attachments.js' );
    1111         return Attachments.all.push( attachment || { id: id } );
    1112     })
    1113 });
    1114 
    1115 module.exports = Attachment;
    1116 },{"./attachments.js":9}],9:[function(require,module,exports){
    1117 /*globals jQuery, Backbone, _, wp */
    1118 
    1119 /**
    1120  * wp.media.model.Attachments
    1121  *
    1122  * A collection of attachments.
    1123  *
    1124  * This collection has no persistence with the server without supplying
    1125  * 'options.props.query = true', which will mirror the collection
    1126  * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().
    1127  *
    1128  * @class
    1129  * @augments Backbone.Collection
    1130  *
    1131  * @param {array}  [models]                Models to initialize with the collection.
    1132  * @param {object} [options]               Options hash for the collection.
    1133  * @param {string} [options.props]         Options hash for the initial query properties.
    1134  * @param {string} [options.props.order]   Initial order (ASC or DESC) for the collection.
    1135  * @param {string} [options.props.orderby] Initial attribute key to order the collection by.
    1136  * @param {string} [options.props.query]   Whether the collection is linked to an attachments query.
    1137  * @param {string} [options.observe]
    1138  * @param {string} [options.filters]
    1139  *
    1140  */
    1141 var Attachment = require( './attachment.js' ),
    1142     Attachments;
    1143 
    1144 Attachments = Backbone.Collection.extend({
    1145     /**
    1146      * @type {wp.media.model.Attachment}
    1147      */
    1148     model: Attachment,
    1149     /**
    1150      * @param {Array} [models=[]] Array of models used to populate the collection.
    1151      * @param {Object} [options={}]
    1152      */
    1153     initialize: function( models, options ) {
    1154         options = options || {};
    1155 
    1156         this.props   = new Backbone.Model();
    1157         this.filters = options.filters || {};
    1158 
    1159         // Bind default `change` events to the `props` model.
    1160         this.props.on( 'change', this._changeFilteredProps, this );
    1161 
    1162         this.props.on( 'change:order',   this._changeOrder,   this );
    1163         this.props.on( 'change:orderby', this._changeOrderby, this );
    1164         this.props.on( 'change:query',   this._changeQuery,   this );
    1165 
    1166         this.props.set( _.defaults( options.props || {} ) );
    1167 
    1168         if ( options.observe ) {
    1169             this.observe( options.observe );
    1170         }
    1171     },
    1172     /**
    1173      * Sort the collection when the order attribute changes.
    1174      *
    1175      * @access private
    1176      */
    1177     _changeOrder: function() {
    1178         if ( this.comparator ) {
    1179             this.sort();
    1180         }
    1181     },
    1182     /**
    1183      * Set the default comparator only when the `orderby` property is set.
    1184      *
    1185      * @access private
    1186      *
    1187      * @param {Backbone.Model} model
    1188      * @param {string} orderby
    1189      */
    1190     _changeOrderby: function( model, orderby ) {
    1191         // If a different comparator is defined, bail.
    1192         if ( this.comparator && this.comparator !== Attachments.comparator ) {
    1193             return;
    1194         }
    1195 
    1196         if ( orderby && 'post__in' !== orderby ) {
    1197             this.comparator = Attachments.comparator;
    1198         } else {
    1199             delete this.comparator;
    1200         }
    1201     },
    1202     /**
    1203      * If the `query` property is set to true, query the server using
    1204      * the `props` values, and sync the results to this collection.
    1205      *
    1206      * @access private
    1207      *
    1208      * @param {Backbone.Model} model
    1209      * @param {Boolean} query
    1210      */
    1211     _changeQuery: function( model, query ) {
    1212         if ( query ) {
    1213             this.props.on( 'change', this._requery, this );
    1214             this._requery();
    1215         } else {
    1216             this.props.off( 'change', this._requery, this );
    1217         }
    1218     },
    1219     /**
    1220      * @access private
    1221      *
    1222      * @param {Backbone.Model} model
    1223      */
    1224     _changeFilteredProps: function( model ) {
    1225         // If this is a query, updating the collection will be handled by
    1226         // `this._requery()`.
    1227         if ( this.props.get('query') ) {
    1228             return;
    1229         }
    1230 
    1231         var changed = _.chain( model.changed ).map( function( t, prop ) {
    1232             var filter = Attachments.filters[ prop ],
    1233                 term = model.get( prop );
    1234 
    1235             if ( ! filter ) {
    1236                 return;
    1237             }
    1238 
    1239             if ( term && ! this.filters[ prop ] ) {
    1240                 this.filters[ prop ] = filter;
    1241             } else if ( ! term && this.filters[ prop ] === filter ) {
    1242                 delete this.filters[ prop ];
    1243             } else {
    1244                 return;
    1245             }
    1246 
    1247             // Record the change.
    1248             return true;
    1249         }, this ).any().value();
    1250 
    1251         if ( ! changed ) {
    1252             return;
    1253         }
    1254 
    1255         // If no `Attachments` model is provided to source the searches
    1256         // from, then automatically generate a source from the existing
    1257         // models.
    1258         if ( ! this._source ) {
    1259             this._source = new Attachments( this.models );
    1260         }
    1261 
    1262         this.reset( this._source.filter( this.validator, this ) );
    1263     },
    1264 
    1265     validateDestroyed: false,
    1266     /**
    1267      * Checks whether an attachment is valid.
    1268      *
    1269      * @param {wp.media.model.Attachment} attachment
    1270      * @returns {Boolean}
    1271      */
    1272     validator: function( attachment ) {
    1273         if ( ! this.validateDestroyed && attachment.destroyed ) {
    1274             return false;
    1275         }
    1276         return _.all( this.filters, function( filter ) {
    1277             return !! filter.call( this, attachment );
    1278         }, this );
    1279     },
    1280     /**
    1281      * Add or remove an attachment to the collection depending on its validity.
    1282      *
    1283      * @param {wp.media.model.Attachment} attachment
    1284      * @param {Object} options
    1285      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1286      */
    1287     validate: function( attachment, options ) {
    1288         var valid = this.validator( attachment ),
    1289             hasAttachment = !! this.get( attachment.cid );
    1290 
    1291         if ( ! valid && hasAttachment ) {
    1292             this.remove( attachment, options );
    1293         } else if ( valid && ! hasAttachment ) {
    1294             this.add( attachment, options );
    1295         }
    1296 
    1297         return this;
    1298     },
    1299 
    1300     /**
    1301      * Add or remove all attachments from another collection depending on each one's validity.
    1302      *
    1303      * @param {wp.media.model.Attachments} attachments
    1304      * @param {object} [options={}]
    1305      *
    1306      * @fires wp.media.model.Attachments#reset
    1307      *
    1308      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1309      */
    1310     validateAll: function( attachments, options ) {
    1311         options = options || {};
    1312 
    1313         _.each( attachments.models, function( attachment ) {
    1314             this.validate( attachment, { silent: true });
    1315         }, this );
    1316 
    1317         if ( ! options.silent ) {
    1318             this.trigger( 'reset', this, options );
    1319         }
    1320         return this;
    1321     },
    1322     /**
    1323      * Start observing another attachments collection change events
    1324      * and replicate them on this collection.
    1325      *
    1326      * @param {wp.media.model.Attachments} The attachments collection to observe.
    1327      * @returns {wp.media.model.Attachments} Returns itself to allow chaining.
    1328      */
    1329     observe: function( attachments ) {
    1330         this.observers = this.observers || [];
    1331         this.observers.push( attachments );
    1332 
    1333         attachments.on( 'add change remove', this._validateHandler, this );
    1334         attachments.on( 'reset', this._validateAllHandler, this );
    1335         this.validateAll( attachments );
    1336         return this;
    1337     },
    1338     /**
    1339      * Stop replicating collection change events from another attachments collection.
    1340      *
    1341      * @param {wp.media.model.Attachments} The attachments collection to stop observing.
    1342      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1343      */
    1344     unobserve: function( attachments ) {
    1345         if ( attachments ) {
    1346             attachments.off( null, null, this );
    1347             this.observers = _.without( this.observers, attachments );
    1348 
    1349         } else {
    1350             _.each( this.observers, function( attachments ) {
    1351                 attachments.off( null, null, this );
    1352             }, this );
    1353             delete this.observers;
    1354         }
    1355 
    1356         return this;
    1357     },
    1358     /**
    1359      * @access private
    1360      *
    1361      * @param {wp.media.model.Attachments} attachment
    1362      * @param {wp.media.model.Attachments} attachments
    1363      * @param {Object} options
    1364      *
    1365      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1366      */
    1367     _validateHandler: function( attachment, attachments, options ) {
    1368         // If we're not mirroring this `attachments` collection,
    1369         // only retain the `silent` option.
    1370         options = attachments === this.mirroring ? options : {
    1371             silent: options && options.silent
    1372         };
    1373 
    1374         return this.validate( attachment, options );
    1375     },
    1376     /**
    1377      * @access private
    1378      *
    1379      * @param {wp.media.model.Attachments} attachments
    1380      * @param {Object} options
    1381      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1382      */
    1383     _validateAllHandler: function( attachments, options ) {
    1384         return this.validateAll( attachments, options );
    1385     },
    1386     /**
    1387      * Start mirroring another attachments collection, clearing out any models already
    1388      * in the collection.
    1389      *
    1390      * @param {wp.media.model.Attachments} The attachments collection to mirror.
    1391      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    1392      */
    1393     mirror: function( attachments ) {
    1394         if ( this.mirroring && this.mirroring === attachments ) {
    1395             return this;
    1396         }
    1397 
    1398         this.unmirror();
    1399         this.mirroring = attachments;
    1400 
    1401         // Clear the collection silently. A `reset` event will be fired
    1402         // when `observe()` calls `validateAll()`.
    1403         this.reset( [], { silent: true } );
    1404         this.observe( attachments );
    1405 
    1406         return this;
    1407     },
    1408     /**
    1409      * Stop mirroring another attachments collection.
    1410      */
    1411     unmirror: function() {
    1412         if ( ! this.mirroring ) {
    1413             return;
    1414         }
    1415 
    1416         this.unobserve( this.mirroring );
    1417         delete this.mirroring;
    1418     },
    1419     /**
    1420      * Retrive more attachments from the server for the collection.
    1421      *
    1422      * Only works if the collection is mirroring a Query Attachments collection,
    1423      * and forwards to its `more` method. This collection class doesn't have
    1424      * server persistence by itself.
    1425      *
    1426      * @param {object} options
    1427      * @returns {Promise}
    1428      */
    1429     more: function( options ) {
    1430         var deferred = jQuery.Deferred(),
    1431             mirroring = this.mirroring,
    1432             attachments = this;
    1433 
    1434         if ( ! mirroring || ! mirroring.more ) {
    1435             return deferred.resolveWith( this ).promise();
    1436         }
    1437         // If we're mirroring another collection, forward `more` to
    1438         // the mirrored collection. Account for a race condition by
    1439         // checking if we're still mirroring that collection when
    1440         // the request resolves.
    1441         mirroring.more( options ).done( function() {
    1442             if ( this === attachments.mirroring )
    1443                 deferred.resolveWith( this );
    1444         });
    1445 
    1446         return deferred.promise();
    1447     },
    1448     /**
    1449      * Whether there are more attachments that haven't been sync'd from the server
    1450      * that match the collection's query.
    1451      *
    1452      * Only works if the collection is mirroring a Query Attachments collection,
    1453      * and forwards to its `hasMore` method. This collection class doesn't have
    1454      * server persistence by itself.
    1455      *
    1456      * @returns {boolean}
    1457      */
    1458     hasMore: function() {
    1459         return this.mirroring ? this.mirroring.hasMore() : false;
    1460     },
    1461     /**
    1462      * A custom AJAX-response parser.
    1463      *
    1464      * See trac ticket #24753
    1465      *
    1466      * @param {Object|Array} resp The raw response Object/Array.
    1467      * @param {Object} xhr
    1468      * @returns {Array} The array of model attributes to be added to the collection
    1469      */
    1470     parse: function( resp, xhr ) {
    1471         if ( ! _.isArray( resp ) ) {
    1472             resp = [resp];
    1473         }
    1474 
    1475         return _.map( resp, function( attrs ) {
    1476             var id, attachment, newAttributes;
    1477 
    1478             if ( attrs instanceof Backbone.Model ) {
    1479                 id = attrs.get( 'id' );
    1480                 attrs = attrs.attributes;
    1481             } else {
    1482                 id = attrs.id;
    1483             }
    1484 
    1485             attachment = Attachment.get( id );
    1486             newAttributes = attachment.parse( attrs, xhr );
    1487 
    1488             if ( ! _.isEqual( attachment.attributes, newAttributes ) ) {
    1489                 attachment.set( newAttributes );
    1490             }
    1491 
    1492             return attachment;
    1493         });
    1494     },
    1495     /**
    1496      * If the collection is a query, create and mirror an Attachments Query collection.
    1497      *
    1498      * @access private
    1499      */
    1500     _requery: function( refresh ) {
    1501         var props, Query;
    1502         if ( this.props.get('query') ) {
    1503             Query = require( './query.js' );
    1504             props = this.props.toJSON();
    1505             props.cache = ( true !== refresh );
    1506             this.mirror( Query.get( props ) );
    1507         }
    1508     },
    1509     /**
    1510      * If this collection is sorted by `menuOrder`, recalculates and saves
    1511      * the menu order to the database.
    1512      *
    1513      * @returns {undefined|Promise}
    1514      */
    1515     saveMenuOrder: function() {
    1516         if ( 'menuOrder' !== this.props.get('orderby') ) {
    1517             return;
    1518         }
    1519 
    1520         // Removes any uploading attachments, updates each attachment's
    1521         // menu order, and returns an object with an { id: menuOrder }
    1522         // mapping to pass to the request.
    1523         var attachments = this.chain().filter( function( attachment ) {
    1524             return ! _.isUndefined( attachment.id );
    1525         }).map( function( attachment, index ) {
    1526             // Indices start at 1.
    1527             index = index + 1;
    1528             attachment.set( 'menuOrder', index );
    1529             return [ attachment.id, index ];
    1530         }).object().value();
    1531 
    1532         if ( _.isEmpty( attachments ) ) {
    1533             return;
    1534         }
    1535 
    1536         return wp.media.post( 'save-attachment-order', {
    1537             nonce:       wp.media.model.settings.post.nonce,
    1538             post_id:     wp.media.model.settings.post.id,
    1539             attachments: attachments
    1540         });
    1541     }
    1542 }, {
    1543     /**
    1544      * A function to compare two attachment models in an attachments collection.
    1545      *
    1546      * Used as the default comparator for instances of wp.media.model.Attachments
    1547      * and its subclasses. @see wp.media.model.Attachments._changeOrderby().
    1548      *
    1549      * @static
    1550      *
    1551      * @param {Backbone.Model} a
    1552      * @param {Backbone.Model} b
    1553      * @param {Object} options
    1554      * @returns {Number} -1 if the first model should come before the second,
    1555      *    0 if they are of the same rank and
    1556      *    1 if the first model should come after.
    1557      */
    1558     comparator: function( a, b, options ) {
    1559         var key   = this.props.get('orderby'),
    1560             order = this.props.get('order') || 'DESC',
    1561             ac    = a.cid,
    1562             bc    = b.cid;
    1563 
    1564         a = a.get( key );
    1565         b = b.get( key );
    1566 
    1567         if ( 'date' === key || 'modified' === key ) {
    1568             a = a || new Date();
    1569             b = b || new Date();
    1570         }
    1571 
    1572         // If `options.ties` is set, don't enforce the `cid` tiebreaker.
    1573         if ( options && options.ties ) {
    1574             ac = bc = null;
    1575         }
    1576 
    1577         return ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );
    1578     },
    1579     /**
    1580      * @namespace
    1581      */
    1582     filters: {
    1583         /**
    1584          * @static
    1585          * Note that this client-side searching is *not* equivalent
    1586          * to our server-side searching.
    1587          *
    1588          * @param {wp.media.model.Attachment} attachment
    1589          *
    1590          * @this wp.media.model.Attachments
    1591          *
    1592          * @returns {Boolean}
    1593          */
    1594         search: function( attachment ) {
    1595             if ( ! this.props.get('search') ) {
    1596                 return true;
    1597             }
    1598 
    1599             return _.any(['title','filename','description','caption','name'], function( key ) {
    1600                 var value = attachment.get( key );
    1601                 return value && -1 !== value.search( this.props.get('search') );
    1602             }, this );
    1603         },
    1604         /**
    1605          * @static
    1606          * @param {wp.media.model.Attachment} attachment
    1607          *
    1608          * @this wp.media.model.Attachments
    1609          *
    1610          * @returns {Boolean}
    1611          */
    1612         type: function( attachment ) {
    1613             var type = this.props.get('type');
    1614             return ! type || -1 !== type.indexOf( attachment.get('type') );
    1615         },
    1616         /**
    1617          * @static
    1618          * @param {wp.media.model.Attachment} attachment
    1619          *
    1620          * @this wp.media.model.Attachments
    1621          *
    1622          * @returns {Boolean}
    1623          */
    1624         uploadedTo: function( attachment ) {
    1625             var uploadedTo = this.props.get('uploadedTo');
    1626             if ( _.isUndefined( uploadedTo ) ) {
    1627                 return true;
    1628             }
    1629 
    1630             return uploadedTo === attachment.get('uploadedTo');
    1631         },
    1632         /**
    1633          * @static
    1634          * @param {wp.media.model.Attachment} attachment
    1635          *
    1636          * @this wp.media.model.Attachments
    1637          *
    1638          * @returns {Boolean}
    1639          */
    1640         status: function( attachment ) {
    1641             var status = this.props.get('status');
    1642             if ( _.isUndefined( status ) ) {
    1643                 return true;
    1644             }
    1645 
    1646             return status === attachment.get('status');
    1647         }
    1648     }
    1649 });
    1650 
    1651 module.exports = Attachments;
    1652 },{"./attachment.js":8,"./query.js":10}],10:[function(require,module,exports){
    1653 /*globals jQuery, _, wp */
    1654 
    1655 /**
    1656  * wp.media.model.Query
    1657  *
    1658  * A collection of attachments that match the supplied query arguments.
    1659  *
    1660  * Note: Do NOT change this.args after the query has been initialized.
    1661  *       Things will break.
    1662  *
    1663  * @class
    1664  * @augments wp.media.model.Attachments
    1665  * @augments Backbone.Collection
    1666  *
    1667  * @param {array}  [models]                      Models to initialize with the collection.
    1668  * @param {object} [options]                     Options hash.
    1669  * @param {object} [options.args]                Attachments query arguments.
    1670  * @param {object} [options.args.posts_per_page]
    1671  */
    1672 var Attachments = require( './attachments.js' ),
    1673     Query;
    1674 
    1675 Query = Attachments.extend({
    1676     /**
    1677      * @global wp.Uploader
    1678      *
    1679      * @param {array}  [models=[]]  Array of initial models to populate the collection.
    1680      * @param {object} [options={}]
    1681      */
    1682     initialize: function( models, options ) {
    1683         var allowed;
    1684 
    1685         options = options || {};
    1686         Attachments.prototype.initialize.apply( this, arguments );
    1687 
    1688         this.args     = options.args;
    1689         this._hasMore = true;
    1690         this.created  = new Date();
    1691 
    1692         this.filters.order = function( attachment ) {
    1693             var orderby = this.props.get('orderby'),
    1694                 order = this.props.get('order');
    1695 
    1696             if ( ! this.comparator ) {
    1697                 return true;
    1698             }
    1699 
    1700             // We want any items that can be placed before the last
    1701             // item in the set. If we add any items after the last
    1702             // item, then we can't guarantee the set is complete.
    1703             if ( this.length ) {
    1704                 return 1 !== this.comparator( attachment, this.last(), { ties: true });
    1705 
    1706             // Handle the case where there are no items yet and
    1707             // we're sorting for recent items. In that case, we want
    1708             // changes that occurred after we created the query.
    1709             } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {
    1710                 return attachment.get( orderby ) >= this.created;
    1711 
    1712             // If we're sorting by menu order and we have no items,
    1713             // accept any items that have the default menu order (0).
    1714             } else if ( 'ASC' === order && 'menuOrder' === orderby ) {
    1715                 return attachment.get( orderby ) === 0;
    1716             }
    1717 
    1718             // Otherwise, we don't want any items yet.
    1719             return false;
    1720         };
    1721 
    1722         // Observe the central `wp.Uploader.queue` collection to watch for
    1723         // new matches for the query.
    1724         //
    1725         // Only observe when a limited number of query args are set. There
    1726         // are no filters for other properties, so observing will result in
    1727         // false positives in those queries.
    1728         allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent' ];
    1729         if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {
    1730             this.observe( wp.Uploader.queue );
    1731         }
    1732     },
    1733     /**
    1734      * Whether there are more attachments that haven't been sync'd from the server
    1735      * that match the collection's query.
    1736      *
    1737      * @returns {boolean}
    1738      */
    1739     hasMore: function() {
    1740         return this._hasMore;
    1741     },
    1742     /**
    1743      * Fetch more attachments from the server for the collection.
    1744      *
    1745      * @param   {object}  [options={}]
    1746      * @returns {Promise}
    1747      */
    1748     more: function( options ) {
    1749         var query = this;
    1750 
    1751         // If there is already a request pending, return early with the Deferred object.
    1752         if ( this._more && 'pending' === this._more.state() ) {
    1753             return this._more;
    1754         }
    1755 
    1756         if ( ! this.hasMore() ) {
    1757             return jQuery.Deferred().resolveWith( this ).promise();
    1758         }
    1759 
    1760         options = options || {};
    1761         options.remove = false;
    1762 
    1763         return this._more = this.fetch( options ).done( function( resp ) {
    1764             if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {
    1765                 query._hasMore = false;
    1766             }
    1767         });
    1768     },
    1769     /**
    1770      * Overrides Backbone.Collection.sync
    1771      * Overrides wp.media.model.Attachments.sync
    1772      *
    1773      * @param {String} method
    1774      * @param {Backbone.Model} model
    1775      * @param {Object} [options={}]
    1776      * @returns {Promise}
    1777      */
    1778     sync: function( method, model, options ) {
    1779         var args, fallback;
    1780 
    1781         // Overload the read method so Attachment.fetch() functions correctly.
    1782         if ( 'read' === method ) {
    1783             options = options || {};
    1784             options.context = this;
    1785             options.data = _.extend( options.data || {}, {
    1786                 action:  'query-attachments',
    1787                 post_id: wp.media.model.settings.post.id
    1788             });
    1789 
    1790             // Clone the args so manipulation is non-destructive.
    1791             args = _.clone( this.args );
    1792 
    1793             // Determine which page to query.
    1794             if ( -1 !== args.posts_per_page ) {
    1795                 args.paged = Math.floor( this.length / args.posts_per_page ) + 1;
    1796             }
    1797 
    1798             options.data.query = args;
    1799             return wp.media.ajax( options );
    1800 
    1801         // Otherwise, fall back to Backbone.sync()
    1802         } else {
    1803             /**
    1804              * Call wp.media.model.Attachments.sync or Backbone.sync
    1805              */
    1806             fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
    1807             return fallback.sync.apply( this, arguments );
    1808         }
    1809     }
    1810 }, {
    1811     /**
    1812      * @readonly
    1813      */
    1814     defaultProps: {
    1815         orderby: 'date',
    1816         order:   'DESC'
    1817     },
    1818     /**
    1819      * @readonly
    1820      */
    1821     defaultArgs: {
    1822         posts_per_page: 40
    1823     },
    1824     /**
    1825      * @readonly
    1826      */
    1827     orderby: {
    1828         allowed:  [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],
    1829         /**
    1830          * A map of JavaScript orderby values to their WP_Query equivalents.
    1831          * @type {Object}
    1832          */
    1833         valuemap: {
    1834             'id':         'ID',
    1835             'uploadedTo': 'parent',
    1836             'menuOrder':  'menu_order ID'
    1837         }
    1838     },
    1839     /**
    1840      * A map of JavaScript query properties to their WP_Query equivalents.
    1841      *
    1842      * @readonly
    1843      */
    1844     propmap: {
    1845         'search':    's',
    1846         'type':      'post_mime_type',
    1847         'perPage':   'posts_per_page',
    1848         'menuOrder': 'menu_order',
    1849         'uploadedTo': 'post_parent',
    1850         'status':     'post_status',
    1851         'include':    'post__in',
    1852         'exclude':    'post__not_in'
    1853     },
    1854     /**
    1855      * Creates and returns an Attachments Query collection given the properties.
    1856      *
    1857      * Caches query objects and reuses where possible.
    1858      *
    1859      * @static
    1860      * @method
    1861      *
    1862      * @param {object} [props]
    1863      * @param {Object} [props.cache=true]   Whether to use the query cache or not.
    1864      * @param {Object} [props.order]
    1865      * @param {Object} [props.orderby]
    1866      * @param {Object} [props.include]
    1867      * @param {Object} [props.exclude]
    1868      * @param {Object} [props.s]
    1869      * @param {Object} [props.post_mime_type]
    1870      * @param {Object} [props.posts_per_page]
    1871      * @param {Object} [props.menu_order]
    1872      * @param {Object} [props.post_parent]
    1873      * @param {Object} [props.post_status]
    1874      * @param {Object} [options]
    1875      *
    1876      * @returns {wp.media.model.Query} A new Attachments Query collection.
    1877      */
    1878     get: (function(){
    1879         /**
    1880          * @static
    1881          * @type Array
    1882          */
    1883         var queries = [];
    1884 
    1885         /**
    1886          * @returns {Query}
    1887          */
    1888         return function( props, options ) {
    1889             var args     = {},
    1890                 orderby  = Query.orderby,
    1891                 defaults = Query.defaultProps,
    1892                 query,
    1893                 cache    = !! props.cache || _.isUndefined( props.cache );
    1894 
    1895             // Remove the `query` property. This isn't linked to a query,
    1896             // this *is* the query.
    1897             delete props.query;
    1898             delete props.cache;
    1899 
    1900             // Fill default args.
    1901             _.defaults( props, defaults );
    1902 
    1903             // Normalize the order.
    1904             props.order = props.order.toUpperCase();
    1905             if ( 'DESC' !== props.order && 'ASC' !== props.order ) {
    1906                 props.order = defaults.order.toUpperCase();
    1907             }
    1908 
    1909             // Ensure we have a valid orderby value.
    1910             if ( ! _.contains( orderby.allowed, props.orderby ) ) {
    1911                 props.orderby = defaults.orderby;
    1912             }
    1913 
    1914             _.each( [ 'include', 'exclude' ], function( prop ) {
    1915                 if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {
    1916                     props[ prop ] = [ props[ prop ] ];
    1917                 }
    1918             } );
    1919 
    1920             // Generate the query `args` object.
    1921             // Correct any differing property names.
    1922             _.each( props, function( value, prop ) {
    1923                 if ( _.isNull( value ) ) {
    1924                     return;
    1925                 }
    1926 
    1927                 args[ Query.propmap[ prop ] || prop ] = value;
    1928             });
    1929 
    1930             // Fill any other default query args.
    1931             _.defaults( args, Query.defaultArgs );
    1932 
    1933             // `props.orderby` does not always map directly to `args.orderby`.
    1934             // Substitute exceptions specified in orderby.keymap.
    1935             args.orderby = orderby.valuemap[ props.orderby ] || props.orderby;
    1936 
    1937             // Search the query cache for a matching query.
    1938             if ( cache ) {
    1939                 query = _.find( queries, function( query ) {
    1940                     return _.isEqual( query.args, args );
    1941                 });
    1942             } else {
    1943                 queries = [];
    1944             }
    1945 
    1946             // Otherwise, create a new query and add it to the cache.
    1947             if ( ! query ) {
    1948                 query = new Query( [], _.extend( options || {}, {
    1949                     props: props,
    1950                     args:  args
    1951                 } ) );
    1952                 queries.push( query );
    1953             }
    1954 
    1955             return query;
    1956         };
    1957     }())
    1958 });
    1959 
    1960 module.exports = Query;
    1961 },{"./attachments.js":9}],11:[function(require,module,exports){
    1962 /*globals _ */
    1963 
    1964 /**
    1965  * wp.media.model.Selection
    1966  *
    1967  * A selection of attachments.
    1968  *
    1969  * @class
    1970  * @augments wp.media.model.Attachments
    1971  * @augments Backbone.Collection
    1972  */
    1973 var Attachments = require( './attachments.js' ),
    1974     Selection;
    1975 
    1976 Selection = Attachments.extend({
    1977     /**
    1978      * Refresh the `single` model whenever the selection changes.
    1979      * Binds `single` instead of using the context argument to ensure
    1980      * it receives no parameters.
    1981      *
    1982      * @param {Array} [models=[]] Array of models used to populate the collection.
    1983      * @param {Object} [options={}]
    1984      */
    1985     initialize: function( models, options ) {
    1986         /**
    1987          * call 'initialize' directly on the parent class
    1988          */
    1989         Attachments.prototype.initialize.apply( this, arguments );
    1990         this.multiple = options && options.multiple;
    1991 
    1992         this.on( 'add remove reset', _.bind( this.single, this, false ) );
    1993     },
    1994 
    1995     /**
    1996      * If the workflow does not support multi-select, clear out the selection
    1997      * before adding a new attachment to it.
    1998      *
    1999      * @param {Array} models
    2000      * @param {Object} options
    2001      * @returns {wp.media.model.Attachment[]}
    2002      */
    2003     add: function( models, options ) {
    2004         if ( ! this.multiple ) {
    2005             this.remove( this.models );
    2006         }
    2007         /**
    2008          * call 'add' directly on the parent class
    2009          */
    2010         return Attachments.prototype.add.call( this, models, options );
    2011     },
    2012 
    2013     /**
    2014      * Fired when toggling (clicking on) an attachment in the modal.
    2015      *
    2016      * @param {undefined|boolean|wp.media.model.Attachment} model
    2017      *
    2018      * @fires wp.media.model.Selection#selection:single
    2019      * @fires wp.media.model.Selection#selection:unsingle
    2020      *
    2021      * @returns {Backbone.Model}
    2022      */
    2023     single: function( model ) {
    2024         var previous = this._single;
    2025 
    2026         // If a `model` is provided, use it as the single model.
    2027         if ( model ) {
    2028             this._single = model;
    2029         }
    2030         // If the single model isn't in the selection, remove it.
    2031         if ( this._single && ! this.get( this._single.cid ) ) {
    2032             delete this._single;
    2033         }
    2034 
    2035         this._single = this._single || this.last();
    2036 
    2037         // If single has changed, fire an event.
    2038         if ( this._single !== previous ) {
    2039             if ( previous ) {
    2040                 previous.trigger( 'selection:unsingle', previous, this );
    2041 
    2042                 // If the model was already removed, trigger the collection
    2043                 // event manually.
    2044                 if ( ! this.get( previous.cid ) ) {
    2045                     this.trigger( 'selection:unsingle', previous, this );
    2046                 }
    2047             }
    2048             if ( this._single ) {
    2049                 this._single.trigger( 'selection:single', this._single, this );
    2050             }
    2051         }
    2052 
    2053         // Return the single model, or the last model as a fallback.
    2054         return this._single;
    2055     }
    2056 });
    2057 
    2058 module.exports = Selection;
    2059 },{"./attachments.js":9}],12:[function(require,module,exports){
     946},{"./controllers/edit-attachment-metadata.js":1,"./routers/manage.js":8,"./views/attachment/details-two-column.js":16,"./views/button/delete-selected-permanently.js":22,"./views/button/delete-selected.js":23,"./views/button/select-mode-toggle.js":24,"./views/edit-image-details.js":25,"./views/frame/edit-attachments.js":29,"./views/frame/manage.js":30}],8:[function(require,module,exports){
    2060947/*globals jQuery, Backbone */
    2061948
     
    2104991
    2105992module.exports = Router;
    2106 },{}],13:[function(require,module,exports){
     993},{}],9:[function(require,module,exports){
    2107994/*globals _ */
    2108995
     
    21711058
    21721059module.exports = selectionSync;
    2173 },{}],14:[function(require,module,exports){
     1060},{}],10:[function(require,module,exports){
    21741061/*globals _ */
    21751062
     
    22571144
    22581145module.exports = AttachmentCompat;
    2259 },{"./view.js":55}],15:[function(require,module,exports){
     1146},{"./view.js":51}],11:[function(require,module,exports){
    22601147/*globals _, jQuery */
    22611148
     
    23361223
    23371224module.exports = AttachmentFilters;
    2338 },{"./view.js":55}],16:[function(require,module,exports){
     1225},{"./view.js":51}],12:[function(require,module,exports){
    23391226/*globals _, wp */
    23401227
     
    24281315
    24291316module.exports = All;
    2430 },{"../attachment-filters.js":15}],17:[function(require,module,exports){
     1317},{"../attachment-filters.js":11}],13:[function(require,module,exports){
    24311318/*globals _, wp */
    24321319
     
    24711358
    24721359module.exports = DateFilter;
    2473 },{"../attachment-filters.js":15}],18:[function(require,module,exports){
     1360},{"../attachment-filters.js":11}],14:[function(require,module,exports){
    24741361/*globals wp */
    24751362
     
    25321419
    25331420module.exports = Uploaded;
    2534 },{"../attachment-filters.js":15}],19:[function(require,module,exports){
     1421},{"../attachment-filters.js":11}],15:[function(require,module,exports){
    25351422/*globals _, wp, jQuery */
    25361423
     
    30871974
    30881975module.exports = Attachment;
    3089 },{"./view.js":55}],20:[function(require,module,exports){
     1976},{"./view.js":51}],16:[function(require,module,exports){
    30901977/*globals wp */
    30911978
     
    31302017
    31312018module.exports = TwoColumn;
    3132 },{"../media-details.js":37,"./details.js":21}],21:[function(require,module,exports){
     2019},{"../media-details.js":33,"./details.js":17}],17:[function(require,module,exports){
    31332020/*globals _, wp */
    31342021
     
    32712158
    32722159module.exports = Details;
    3273 },{"../attachment.js":19}],22:[function(require,module,exports){
     2160},{"../attachment.js":15}],18:[function(require,module,exports){
    32742161/**
    32752162 * wp.media.view.Attachment.Library
     
    32912178
    32922179module.exports = Library;
    3293 },{"../attachment.js":19}],23:[function(require,module,exports){
     2180},{"../attachment.js":15}],19:[function(require,module,exports){
    32942181/*globals _, wp, jQuery */
    32952182
     
    35922479
    35932480module.exports = Attachments;
    3594 },{"./attachment.js":19,"./view.js":55}],24:[function(require,module,exports){
     2481},{"./attachment.js":15,"./view.js":51}],20:[function(require,module,exports){
    35952482/*globals _, wp, jQuery */
    35962483
     
    40522939
    40532940module.exports = AttachmentsBrowser;
    4054 },{"../attachment-compat.js":14,"../attachment-filters/all.js":16,"../attachment-filters/date.js":17,"../attachment-filters/uploaded.js":18,"../attachment/details.js":21,"../attachment/library.js":22,"../attachments.js":23,"../label.js":36,"../search.js":45,"../settings/attachment-display.js":47,"../sidebar.js":48,"../spinner.js":49,"../toolbar.js":50,"../uploader/inline.js":51,"../uploader/status.js":53,"../view.js":55}],25:[function(require,module,exports){
     2941},{"../attachment-compat.js":10,"../attachment-filters/all.js":12,"../attachment-filters/date.js":13,"../attachment-filters/uploaded.js":14,"../attachment/details.js":17,"../attachment/library.js":18,"../attachments.js":19,"../label.js":32,"../search.js":41,"../settings/attachment-display.js":43,"../sidebar.js":44,"../spinner.js":45,"../toolbar.js":46,"../uploader/inline.js":47,"../uploader/status.js":49,"../view.js":51}],21:[function(require,module,exports){
    40552942/*globals _, Backbone */
    40562943
     
    41423029
    41433030module.exports = Button;
    4144 },{"./view.js":55}],26:[function(require,module,exports){
     3031},{"./view.js":51}],22:[function(require,module,exports){
    41453032/**
    41463033 * When MEDIA_TRASH is true, a button that handles bulk Delete Permanently logic
     
    41863073
    41873074module.exports = DeleteSelectedPermanently;
    4188 },{"../button.js":25,"./delete-selected.js":27}],27:[function(require,module,exports){
     3075},{"../button.js":21,"./delete-selected.js":23}],23:[function(require,module,exports){
    41893076/*globals wp */
    41903077
     
    42383125
    42393126module.exports = DeleteSelected;
    4240 },{"../button.js":25}],28:[function(require,module,exports){
     3127},{"../button.js":21}],24:[function(require,module,exports){
    42413128/*globals wp */
    42423129
     
    42943181
    42953182module.exports = SelectModeToggle;
    4296 },{"../button.js":25}],29:[function(require,module,exports){
     3183},{"../button.js":21}],25:[function(require,module,exports){
    42973184var View = require( './view.js' ),
    42983185    EditImage = require( './edit-image.js' ),
     
    43213208
    43223209module.exports = Details;
    4323 },{"./edit-image.js":30,"./view.js":55}],30:[function(require,module,exports){
     3210},{"./edit-image.js":26,"./view.js":51}],26:[function(require,module,exports){
    43243211/*globals _, wp */
    43253212
     
    43763263
    43773264module.exports = EditImage;
    4378 },{"./view.js":55}],31:[function(require,module,exports){
     3265},{"./view.js":51}],27:[function(require,module,exports){
    43793266/**
    43803267 * wp.media.view.FocusManager
     
    44243311
    44253312module.exports = FocusManager;
    4426 },{"./view.js":55}],32:[function(require,module,exports){
     3313},{"./view.js":51}],28:[function(require,module,exports){
    44273314/*globals _, Backbone */
    44283315
     
    45973484
    45983485module.exports = Frame;
    4599 },{"../controllers/region.js":4,"../controllers/state-machine.js":5,"../controllers/state.js":6,"./view.js":55}],33:[function(require,module,exports){
     3486},{"../controllers/region.js":4,"../controllers/state-machine.js":5,"../controllers/state.js":6,"./view.js":51}],29:[function(require,module,exports){
    46003487/*globals _, wp, jQuery */
    46013488
     
    48463733
    48473734module.exports = EditAttachments;
    4848 },{"../../controllers/edit-attachment-metadata.js":1,"../../controllers/edit-image.js":2,"../attachment-compat.js":14,"../attachment/details-two-column.js":20,"../edit-image-details.js":29,"../frame.js":32,"../media-frame.js":38,"../modal.js":41}],34:[function(require,module,exports){
     3735},{"../../controllers/edit-attachment-metadata.js":1,"../../controllers/edit-image.js":2,"../attachment-compat.js":10,"../attachment/details-two-column.js":16,"../edit-image-details.js":25,"../frame.js":28,"../media-frame.js":34,"../modal.js":37}],30:[function(require,module,exports){
    48493736/*globals _, Backbone, wp, jQuery */
    48503737
     
    50943981
    50953982module.exports = Manage;
    5096 },{"../../controllers/library.js":3,"../../routers/manage.js":12,"../attachments/browser.js":24,"../media-frame.js":38,"../uploader/window.js":54}],35:[function(require,module,exports){
     3983},{"../../controllers/library.js":3,"../../routers/manage.js":8,"../attachments/browser.js":20,"../media-frame.js":34,"../uploader/window.js":50}],31:[function(require,module,exports){
    50973984/**
    50983985 * wp.media.view.Iframe
     
    51204007
    51214008module.exports = Iframe;
    5122 },{"./view.js":55}],36:[function(require,module,exports){
     4009},{"./view.js":51}],32:[function(require,module,exports){
    51234010/**
    51244011 * @class
     
    51464033
    51474034module.exports = Label;
    5148 },{"./view.js":55}],37:[function(require,module,exports){
     4035},{"./view.js":51}],33:[function(require,module,exports){
    51494036/*globals _, wp, jQuery */
    51504037
     
    52984185
    52994186module.exports = MediaDetails;
    5300 },{"./settings/attachment-display.js":47}],38:[function(require,module,exports){
     4187},{"./settings/attachment-display.js":43}],34:[function(require,module,exports){
    53014188/*globals _, wp, jQuery */
    53024189
     
    55534440
    55544441module.exports = MediaFrame;
    5555 },{"./frame.js":32,"./iframe.js":35,"./menu.js":40,"./modal.js":41,"./router.js":44,"./toolbar.js":50,"./uploader/window.js":54,"./view.js":55}],39:[function(require,module,exports){
     4442},{"./frame.js":28,"./iframe.js":31,"./menu.js":36,"./modal.js":37,"./router.js":40,"./toolbar.js":46,"./uploader/window.js":50,"./view.js":51}],35:[function(require,module,exports){
    55564443/*globals wp, jQuery */
    55574444
     
    56274514
    56284515module.exports = MenuItem;
    5629 },{"./view.js":55}],40:[function(require,module,exports){
     4516},{"./view.js":51}],36:[function(require,module,exports){
    56304517/**
    56314518 * wp.media.view.Menu
     
    57434630
    57444631module.exports = Menu;
    5745 },{"./menu-item.js":39,"./priority-list.js":42}],41:[function(require,module,exports){
     4632},{"./menu-item.js":35,"./priority-list.js":38}],37:[function(require,module,exports){
    57464633/*globals _, wp, jQuery */
    57474634
     
    59594846
    59604847module.exports = Modal;
    5961 },{"./focus-manager.js":31,"./view.js":55}],42:[function(require,module,exports){
     4848},{"./focus-manager.js":27,"./view.js":51}],38:[function(require,module,exports){
    59624849/*globals _, Backbone */
    59634850
     
    60604947
    60614948module.exports = PriorityList;
    6062 },{"./view.js":55}],43:[function(require,module,exports){
     4949},{"./view.js":51}],39:[function(require,module,exports){
    60634950/**
    60644951 * wp.media.view.RouterItem
     
    60864973
    60874974module.exports = RouterItem;
    6088 },{"./menu-item.js":39}],44:[function(require,module,exports){
     4975},{"./menu-item.js":35}],40:[function(require,module,exports){
    60894976/**
    60904977 * wp.media.view.Router
     
    61235010
    61245011module.exports = Router;
    6125 },{"./menu.js":40,"./router-item.js":43}],45:[function(require,module,exports){
     5012},{"./menu.js":36,"./router-item.js":39}],41:[function(require,module,exports){
    61265013/*globals wp */
    61275014
     
    61735060
    61745061module.exports = Search;
    6175 },{"./view.js":55}],46:[function(require,module,exports){
     5062},{"./view.js":51}],42:[function(require,module,exports){
    61765063/*globals _, Backbone, jQuery */
    61775064
     
    62955182
    62965183module.exports = Settings;
    6297 },{"./view.js":55}],47:[function(require,module,exports){
     5184},{"./view.js":51}],43:[function(require,module,exports){
    62985185/*globals _, wp */
    62995186
     
    63905277
    63915278module.exports = AttachmentDisplay;
    6392 },{"../settings.js":46}],48:[function(require,module,exports){
     5279},{"../settings.js":42}],44:[function(require,module,exports){
    63935280/**
    63945281 * wp.media.view.Sidebar
     
    64085295
    64095296module.exports = Sidebar;
    6410 },{"./priority-list.js":42}],49:[function(require,module,exports){
     5297},{"./priority-list.js":38}],45:[function(require,module,exports){
    64115298/*globals _, wp */
    64125299
     
    64475334
    64485335module.exports = Spinner;
    6449 },{"./view.js":55}],50:[function(require,module,exports){
     5336},{"./view.js":51}],46:[function(require,module,exports){
    64505337/*globals Backbone, _ */
    64515338
     
    66105497
    66115498module.exports = Toolbar;
    6612 },{"./button.js":25,"./priority-list.js":42,"./view.js":55}],51:[function(require,module,exports){
     5499},{"./button.js":21,"./priority-list.js":38,"./view.js":51}],47:[function(require,module,exports){
    66135500/*globals _, wp */
    66145501
     
    67435630
    67445631module.exports = UploaderInline;
    6745 },{"../view.js":55,"./status.js":53}],52:[function(require,module,exports){
     5632},{"../view.js":51,"./status.js":49}],48:[function(require,module,exports){
    67465633/*globals wp */
    67475634
     
    67635650
    67645651module.exports = UploaderStatusError;
    6765 },{"../view.js":55}],53:[function(require,module,exports){
     5652},{"../view.js":51}],49:[function(require,module,exports){
    67665653/*globals _, wp */
    67675654
     
    69035790
    69045791module.exports = UploaderStatus;
    6905 },{"../view.js":55,"./status-error.js":52}],54:[function(require,module,exports){
     5792},{"../view.js":51,"./status-error.js":48}],50:[function(require,module,exports){
    69065793/*globals _, wp, jQuery */
    69075794
     
    70165903
    70175904module.exports = UploaderWindow;
    7018 },{"../view.js":55}],55:[function(require,module,exports){
     5905},{"../view.js":51}],51:[function(require,module,exports){
    70195906/*globals wp */
    70205907
  • trunk/src/wp-includes/js/media/views.js

    r31373 r31379  
    3535 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
    3636 */
    37 var Selection = require( '../models/selection.js' ),
     37var Selection = wp.media.model.Selection,
    3838    Library = require( './library.js' ),
    3939    CollectionAdd;
     
    101101
    102102module.exports = CollectionAdd;
    103 },{"../models/selection.js":20,"./library.js":10}],2:[function(require,module,exports){
     103},{"./library.js":10}],2:[function(require,module,exports){
    104104/*globals wp, jQuery, Backbone */
    105105
     
    138138 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
    139139 */
    140 var Selection = require( '../models/selection.js' ),
    141     Library = require( './library.js' ),
     140var Library = require( './library.js' ),
    142141    View = require( '../views/view.js' ),
    143142    EditLibraryView = require( '../views/attachment/edit-library.js' ),
     
    176175        // If we haven't been provided a `library`, create a `Selection`.
    177176        if ( ! this.get('library') ) {
    178             this.set( 'library', new Selection() );
     177            this.set( 'library', new wp.media.model.Selection() );
    179178        }
    180179        // The single `Attachment` view to be used in the `Attachments` view.
     
    265264
    266265module.exports = CollectionEdit;
    267 },{"../models/selection.js":20,"../views/attachment/edit-library.js":30,"../views/view.js":76,"./library.js":10}],3:[function(require,module,exports){
     266},{"../views/attachment/edit-library.js":25,"../views/view.js":71,"./library.js":10}],3:[function(require,module,exports){
    268267/*globals _, wp, Backbone */
    269268
     
    383382
    384383module.exports = Cropper;
    385 },{"../views/cropper.js":39,"../views/toolbar.js":68,"./state.js":15}],4:[function(require,module,exports){
     384},{"../views/cropper.js":34,"../views/toolbar.js":63,"./state.js":15}],4:[function(require,module,exports){
    386385/*globals _, wp */
    387386
     
    462461
    463462module.exports = EditImage;
    464 },{"../views/toolbar.js":68,"./state.js":15}],5:[function(require,module,exports){
     463},{"../views/toolbar.js":63,"./state.js":15}],5:[function(require,module,exports){
    465464/*globals _, wp, jQuery, Backbone */
    466465
     
    634633 * @param {boolean}                    [attributes.syncSelection=true]       Whether the Attachments selection should be persisted from the last state.
    635634 */
    636 var Attachment = require( '../models/attachment.js' ),
     635var Attachment = wp.media.model.Attachment,
    637636    Library = require( './library.js' ),
    638637    l10n = wp.media.view.l10n,
     
    723722
    724723module.exports = FeaturedImage;
    725 },{"../models/attachment.js":16,"./library.js":10}],7:[function(require,module,exports){
     724},{"./library.js":10}],7:[function(require,module,exports){
    726725/*globals _, wp */
    727726
     
    755754 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
    756755 */
    757 var Selection = require( '../models/selection.js' ),
     756var Selection = wp.media.model.Selection,
    758757    Library = require( './library.js' ),
    759758    l10n = wp.media.view.l10n,
     
    811810
    812811module.exports = GalleryAdd;
    813 },{"../models/selection.js":20,"./library.js":10}],8:[function(require,module,exports){
     812},{"./library.js":10}],8:[function(require,module,exports){
    814813/*globals wp, Backbone */
    815814
     
    845844 *                                                                        If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
    846845 */
    847 var Selection = require( '../models/selection.js' ),
    848     Library = require( './library.js' ),
     846var Library = require( './library.js' ),
    849847    EditLibraryView = require( '../views/attachment/edit-library.js' ),
    850848    GallerySettingsView = require( '../views/settings/gallery.js' ),
     
    877875        // If we haven't been provided a `library`, create a `Selection`.
    878876        if ( ! this.get('library') )
    879             this.set( 'library', new Selection() );
     877            this.set( 'library', new wp.media.model.Selection() );
    880878
    881879        // The single `Attachment` view to be used in the `Attachments` view.
     
    952950
    953951module.exports = GalleryEdit;
    954 },{"../models/selection.js":20,"../views/attachment/edit-library.js":30,"../views/settings/gallery.js":64,"./library.js":10}],9:[function(require,module,exports){
     952},{"../views/attachment/edit-library.js":25,"../views/settings/gallery.js":59,"./library.js":10}],9:[function(require,module,exports){
    955953/*globals _, wp */
    956954
     
    10531051 */
    10541052var selectionSync = require( '../utils/selection-sync.js' ),
    1055     Selection = require( '../models/selection.js' ),
    10561053    State = require( './state.js' ),
    10571054    l10n = wp.media.view.l10n,
     
    10981095            }
    10991096
    1100             this.set( 'selection', new Selection( null, {
     1097            this.set( 'selection', new wp.media.model.Selection( null, {
    11011098                multiple: this.get('multiple'),
    11021099                props: props
     
    12891286
    12901287module.exports = Library;
    1291 },{"../models/selection.js":20,"../utils/selection-sync.js":21,"./state.js":15}],11:[function(require,module,exports){
     1288},{"../utils/selection-sync.js":16,"./state.js":15}],11:[function(require,module,exports){
    12921289/*globals _, wp */
    12931290
     
    19971994module.exports = State;
    19981995},{}],16:[function(require,module,exports){
    1999 /*globals jQuery, Backbone, _, wp */
    2000 
    2001 /**
    2002  * wp.media.model.Attachment
    2003  *
    2004  * @class
    2005  * @augments Backbone.Model
    2006  */
    2007 var $ = jQuery,
    2008     Attachment;
    2009 
    2010 Attachment = Backbone.Model.extend({
    2011     /**
    2012      * Triggered when attachment details change
    2013      * Overrides Backbone.Model.sync
    2014      *
    2015      * @param {string} method
    2016      * @param {wp.media.model.Attachment} model
    2017      * @param {Object} [options={}]
    2018      *
    2019      * @returns {Promise}
    2020      */
    2021     sync: function( method, model, options ) {
    2022         // If the attachment does not yet have an `id`, return an instantly
    2023         // rejected promise. Otherwise, all of our requests will fail.
    2024         if ( _.isUndefined( this.id ) ) {
    2025             return $.Deferred().rejectWith( this ).promise();
    2026         }
    2027 
    2028         // Overload the `read` request so Attachment.fetch() functions correctly.
    2029         if ( 'read' === method ) {
    2030             options = options || {};
    2031             options.context = this;
    2032             options.data = _.extend( options.data || {}, {
    2033                 action: 'get-attachment',
    2034                 id: this.id
    2035             });
    2036             return wp.media.ajax( options );
    2037 
    2038         // Overload the `update` request so properties can be saved.
    2039         } else if ( 'update' === method ) {
    2040             // If we do not have the necessary nonce, fail immeditately.
    2041             if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    2042                 return $.Deferred().rejectWith( this ).promise();
    2043             }
    2044 
    2045             options = options || {};
    2046             options.context = this;
    2047 
    2048             // Set the action and ID.
    2049             options.data = _.extend( options.data || {}, {
    2050                 action:  'save-attachment',
    2051                 id:      this.id,
    2052                 nonce:   this.get('nonces').update,
    2053                 post_id: wp.media.model.settings.post.id
    2054             });
    2055 
    2056             // Record the values of the changed attributes.
    2057             if ( model.hasChanged() ) {
    2058                 options.data.changes = {};
    2059 
    2060                 _.each( model.changed, function( value, key ) {
    2061                     options.data.changes[ key ] = this.get( key );
    2062                 }, this );
    2063             }
    2064 
    2065             return wp.media.ajax( options );
    2066 
    2067         // Overload the `delete` request so attachments can be removed.
    2068         // This will permanently delete an attachment.
    2069         } else if ( 'delete' === method ) {
    2070             options = options || {};
    2071 
    2072             if ( ! options.wait ) {
    2073                 this.destroyed = true;
    2074             }
    2075 
    2076             options.context = this;
    2077             options.data = _.extend( options.data || {}, {
    2078                 action:   'delete-post',
    2079                 id:       this.id,
    2080                 _wpnonce: this.get('nonces')['delete']
    2081             });
    2082 
    2083             return wp.media.ajax( options ).done( function() {
    2084                 this.destroyed = true;
    2085             }).fail( function() {
    2086                 this.destroyed = false;
    2087             });
    2088 
    2089         // Otherwise, fall back to `Backbone.sync()`.
    2090         } else {
    2091             /**
    2092              * Call `sync` directly on Backbone.Model
    2093              */
    2094             return Backbone.Model.prototype.sync.apply( this, arguments );
    2095         }
    2096     },
    2097     /**
    2098      * Convert date strings into Date objects.
    2099      *
    2100      * @param {Object} resp The raw response object, typically returned by fetch()
    2101      * @returns {Object} The modified response object, which is the attributes hash
    2102      *    to be set on the model.
    2103      */
    2104     parse: function( resp ) {
    2105         if ( ! resp ) {
    2106             return resp;
    2107         }
    2108 
    2109         resp.date = new Date( resp.date );
    2110         resp.modified = new Date( resp.modified );
    2111         return resp;
    2112     },
    2113     /**
    2114      * @param {Object} data The properties to be saved.
    2115      * @param {Object} options Sync options. e.g. patch, wait, success, error.
    2116      *
    2117      * @this Backbone.Model
    2118      *
    2119      * @returns {Promise}
    2120      */
    2121     saveCompat: function( data, options ) {
    2122         var model = this;
    2123 
    2124         // If we do not have the necessary nonce, fail immeditately.
    2125         if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    2126             return $.Deferred().rejectWith( this ).promise();
    2127         }
    2128 
    2129         return media.post( 'save-attachment-compat', _.defaults({
    2130             id:      this.id,
    2131             nonce:   this.get('nonces').update,
    2132             post_id: wp.media.model.settings.post.id
    2133         }, data ) ).done( function( resp, status, xhr ) {
    2134             model.set( model.parse( resp, xhr ), options );
    2135         });
    2136     }
    2137 }, {
    2138     /**
    2139      * Create a new model on the static 'all' attachments collection and return it.
    2140      *
    2141      * @static
    2142      * @param {Object} attrs
    2143      * @returns {wp.media.model.Attachment}
    2144      */
    2145     create: function( attrs ) {
    2146         var Attachments = require( './attachments.js' );
    2147         return Attachments.all.push( attrs );
    2148     },
    2149     /**
    2150      * Create a new model on the static 'all' attachments collection and return it.
    2151      *
    2152      * If this function has already been called for the id,
    2153      * it returns the specified attachment.
    2154      *
    2155      * @static
    2156      * @param {string} id A string used to identify a model.
    2157      * @param {Backbone.Model|undefined} attachment
    2158      * @returns {wp.media.model.Attachment}
    2159      */
    2160     get: _.memoize( function( id, attachment ) {
    2161         var Attachments = require( './attachments.js' );
    2162         return Attachments.all.push( attachment || { id: id } );
    2163     })
    2164 });
    2165 
    2166 module.exports = Attachment;
    2167 },{"./attachments.js":17}],17:[function(require,module,exports){
    2168 /*globals jQuery, Backbone, _, wp */
    2169 
    2170 /**
    2171  * wp.media.model.Attachments
    2172  *
    2173  * A collection of attachments.
    2174  *
    2175  * This collection has no persistence with the server without supplying
    2176  * 'options.props.query = true', which will mirror the collection
    2177  * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().
    2178  *
    2179  * @class
    2180  * @augments Backbone.Collection
    2181  *
    2182  * @param {array}  [models]                Models to initialize with the collection.
    2183  * @param {object} [options]               Options hash for the collection.
    2184  * @param {string} [options.props]         Options hash for the initial query properties.
    2185  * @param {string} [options.props.order]   Initial order (ASC or DESC) for the collection.
    2186  * @param {string} [options.props.orderby] Initial attribute key to order the collection by.
    2187  * @param {string} [options.props.query]   Whether the collection is linked to an attachments query.
    2188  * @param {string} [options.observe]
    2189  * @param {string} [options.filters]
    2190  *
    2191  */
    2192 var Attachment = require( './attachment.js' ),
    2193     Attachments;
    2194 
    2195 Attachments = Backbone.Collection.extend({
    2196     /**
    2197      * @type {wp.media.model.Attachment}
    2198      */
    2199     model: Attachment,
    2200     /**
    2201      * @param {Array} [models=[]] Array of models used to populate the collection.
    2202      * @param {Object} [options={}]
    2203      */
    2204     initialize: function( models, options ) {
    2205         options = options || {};
    2206 
    2207         this.props   = new Backbone.Model();
    2208         this.filters = options.filters || {};
    2209 
    2210         // Bind default `change` events to the `props` model.
    2211         this.props.on( 'change', this._changeFilteredProps, this );
    2212 
    2213         this.props.on( 'change:order',   this._changeOrder,   this );
    2214         this.props.on( 'change:orderby', this._changeOrderby, this );
    2215         this.props.on( 'change:query',   this._changeQuery,   this );
    2216 
    2217         this.props.set( _.defaults( options.props || {} ) );
    2218 
    2219         if ( options.observe ) {
    2220             this.observe( options.observe );
    2221         }
    2222     },
    2223     /**
    2224      * Sort the collection when the order attribute changes.
    2225      *
    2226      * @access private
    2227      */
    2228     _changeOrder: function() {
    2229         if ( this.comparator ) {
    2230             this.sort();
    2231         }
    2232     },
    2233     /**
    2234      * Set the default comparator only when the `orderby` property is set.
    2235      *
    2236      * @access private
    2237      *
    2238      * @param {Backbone.Model} model
    2239      * @param {string} orderby
    2240      */
    2241     _changeOrderby: function( model, orderby ) {
    2242         // If a different comparator is defined, bail.
    2243         if ( this.comparator && this.comparator !== Attachments.comparator ) {
    2244             return;
    2245         }
    2246 
    2247         if ( orderby && 'post__in' !== orderby ) {
    2248             this.comparator = Attachments.comparator;
    2249         } else {
    2250             delete this.comparator;
    2251         }
    2252     },
    2253     /**
    2254      * If the `query` property is set to true, query the server using
    2255      * the `props` values, and sync the results to this collection.
    2256      *
    2257      * @access private
    2258      *
    2259      * @param {Backbone.Model} model
    2260      * @param {Boolean} query
    2261      */
    2262     _changeQuery: function( model, query ) {
    2263         if ( query ) {
    2264             this.props.on( 'change', this._requery, this );
    2265             this._requery();
    2266         } else {
    2267             this.props.off( 'change', this._requery, this );
    2268         }
    2269     },
    2270     /**
    2271      * @access private
    2272      *
    2273      * @param {Backbone.Model} model
    2274      */
    2275     _changeFilteredProps: function( model ) {
    2276         // If this is a query, updating the collection will be handled by
    2277         // `this._requery()`.
    2278         if ( this.props.get('query') ) {
    2279             return;
    2280         }
    2281 
    2282         var changed = _.chain( model.changed ).map( function( t, prop ) {
    2283             var filter = Attachments.filters[ prop ],
    2284                 term = model.get( prop );
    2285 
    2286             if ( ! filter ) {
    2287                 return;
    2288             }
    2289 
    2290             if ( term && ! this.filters[ prop ] ) {
    2291                 this.filters[ prop ] = filter;
    2292             } else if ( ! term && this.filters[ prop ] === filter ) {
    2293                 delete this.filters[ prop ];
    2294             } else {
    2295                 return;
    2296             }
    2297 
    2298             // Record the change.
    2299             return true;
    2300         }, this ).any().value();
    2301 
    2302         if ( ! changed ) {
    2303             return;
    2304         }
    2305 
    2306         // If no `Attachments` model is provided to source the searches
    2307         // from, then automatically generate a source from the existing
    2308         // models.
    2309         if ( ! this._source ) {
    2310             this._source = new Attachments( this.models );
    2311         }
    2312 
    2313         this.reset( this._source.filter( this.validator, this ) );
    2314     },
    2315 
    2316     validateDestroyed: false,
    2317     /**
    2318      * Checks whether an attachment is valid.
    2319      *
    2320      * @param {wp.media.model.Attachment} attachment
    2321      * @returns {Boolean}
    2322      */
    2323     validator: function( attachment ) {
    2324         if ( ! this.validateDestroyed && attachment.destroyed ) {
    2325             return false;
    2326         }
    2327         return _.all( this.filters, function( filter ) {
    2328             return !! filter.call( this, attachment );
    2329         }, this );
    2330     },
    2331     /**
    2332      * Add or remove an attachment to the collection depending on its validity.
    2333      *
    2334      * @param {wp.media.model.Attachment} attachment
    2335      * @param {Object} options
    2336      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2337      */
    2338     validate: function( attachment, options ) {
    2339         var valid = this.validator( attachment ),
    2340             hasAttachment = !! this.get( attachment.cid );
    2341 
    2342         if ( ! valid && hasAttachment ) {
    2343             this.remove( attachment, options );
    2344         } else if ( valid && ! hasAttachment ) {
    2345             this.add( attachment, options );
    2346         }
    2347 
    2348         return this;
    2349     },
    2350 
    2351     /**
    2352      * Add or remove all attachments from another collection depending on each one's validity.
    2353      *
    2354      * @param {wp.media.model.Attachments} attachments
    2355      * @param {object} [options={}]
    2356      *
    2357      * @fires wp.media.model.Attachments#reset
    2358      *
    2359      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2360      */
    2361     validateAll: function( attachments, options ) {
    2362         options = options || {};
    2363 
    2364         _.each( attachments.models, function( attachment ) {
    2365             this.validate( attachment, { silent: true });
    2366         }, this );
    2367 
    2368         if ( ! options.silent ) {
    2369             this.trigger( 'reset', this, options );
    2370         }
    2371         return this;
    2372     },
    2373     /**
    2374      * Start observing another attachments collection change events
    2375      * and replicate them on this collection.
    2376      *
    2377      * @param {wp.media.model.Attachments} The attachments collection to observe.
    2378      * @returns {wp.media.model.Attachments} Returns itself to allow chaining.
    2379      */
    2380     observe: function( attachments ) {
    2381         this.observers = this.observers || [];
    2382         this.observers.push( attachments );
    2383 
    2384         attachments.on( 'add change remove', this._validateHandler, this );
    2385         attachments.on( 'reset', this._validateAllHandler, this );
    2386         this.validateAll( attachments );
    2387         return this;
    2388     },
    2389     /**
    2390      * Stop replicating collection change events from another attachments collection.
    2391      *
    2392      * @param {wp.media.model.Attachments} The attachments collection to stop observing.
    2393      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2394      */
    2395     unobserve: function( attachments ) {
    2396         if ( attachments ) {
    2397             attachments.off( null, null, this );
    2398             this.observers = _.without( this.observers, attachments );
    2399 
    2400         } else {
    2401             _.each( this.observers, function( attachments ) {
    2402                 attachments.off( null, null, this );
    2403             }, this );
    2404             delete this.observers;
    2405         }
    2406 
    2407         return this;
    2408     },
    2409     /**
    2410      * @access private
    2411      *
    2412      * @param {wp.media.model.Attachments} attachment
    2413      * @param {wp.media.model.Attachments} attachments
    2414      * @param {Object} options
    2415      *
    2416      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2417      */
    2418     _validateHandler: function( attachment, attachments, options ) {
    2419         // If we're not mirroring this `attachments` collection,
    2420         // only retain the `silent` option.
    2421         options = attachments === this.mirroring ? options : {
    2422             silent: options && options.silent
    2423         };
    2424 
    2425         return this.validate( attachment, options );
    2426     },
    2427     /**
    2428      * @access private
    2429      *
    2430      * @param {wp.media.model.Attachments} attachments
    2431      * @param {Object} options
    2432      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2433      */
    2434     _validateAllHandler: function( attachments, options ) {
    2435         return this.validateAll( attachments, options );
    2436     },
    2437     /**
    2438      * Start mirroring another attachments collection, clearing out any models already
    2439      * in the collection.
    2440      *
    2441      * @param {wp.media.model.Attachments} The attachments collection to mirror.
    2442      * @returns {wp.media.model.Attachments} Returns itself to allow chaining
    2443      */
    2444     mirror: function( attachments ) {
    2445         if ( this.mirroring && this.mirroring === attachments ) {
    2446             return this;
    2447         }
    2448 
    2449         this.unmirror();
    2450         this.mirroring = attachments;
    2451 
    2452         // Clear the collection silently. A `reset` event will be fired
    2453         // when `observe()` calls `validateAll()`.
    2454         this.reset( [], { silent: true } );
    2455         this.observe( attachments );
    2456 
    2457         return this;
    2458     },
    2459     /**
    2460      * Stop mirroring another attachments collection.
    2461      */
    2462     unmirror: function() {
    2463         if ( ! this.mirroring ) {
    2464             return;
    2465         }
    2466 
    2467         this.unobserve( this.mirroring );
    2468         delete this.mirroring;
    2469     },
    2470     /**
    2471      * Retrive more attachments from the server for the collection.
    2472      *
    2473      * Only works if the collection is mirroring a Query Attachments collection,
    2474      * and forwards to its `more` method. This collection class doesn't have
    2475      * server persistence by itself.
    2476      *
    2477      * @param {object} options
    2478      * @returns {Promise}
    2479      */
    2480     more: function( options ) {
    2481         var deferred = jQuery.Deferred(),
    2482             mirroring = this.mirroring,
    2483             attachments = this;
    2484 
    2485         if ( ! mirroring || ! mirroring.more ) {
    2486             return deferred.resolveWith( this ).promise();
    2487         }
    2488         // If we're mirroring another collection, forward `more` to
    2489         // the mirrored collection. Account for a race condition by
    2490         // checking if we're still mirroring that collection when
    2491         // the request resolves.
    2492         mirroring.more( options ).done( function() {
    2493             if ( this === attachments.mirroring )
    2494                 deferred.resolveWith( this );
    2495         });
    2496 
    2497         return deferred.promise();
    2498     },
    2499     /**
    2500      * Whether there are more attachments that haven't been sync'd from the server
    2501      * that match the collection's query.
    2502      *
    2503      * Only works if the collection is mirroring a Query Attachments collection,
    2504      * and forwards to its `hasMore` method. This collection class doesn't have
    2505      * server persistence by itself.
    2506      *
    2507      * @returns {boolean}
    2508      */
    2509     hasMore: function() {
    2510         return this.mirroring ? this.mirroring.hasMore() : false;
    2511     },
    2512     /**
    2513      * A custom AJAX-response parser.
    2514      *
    2515      * See trac ticket #24753
    2516      *
    2517      * @param {Object|Array} resp The raw response Object/Array.
    2518      * @param {Object} xhr
    2519      * @returns {Array} The array of model attributes to be added to the collection
    2520      */
    2521     parse: function( resp, xhr ) {
    2522         if ( ! _.isArray( resp ) ) {
    2523             resp = [resp];
    2524         }
    2525 
    2526         return _.map( resp, function( attrs ) {
    2527             var id, attachment, newAttributes;
    2528 
    2529             if ( attrs instanceof Backbone.Model ) {
    2530                 id = attrs.get( 'id' );
    2531                 attrs = attrs.attributes;
    2532             } else {
    2533                 id = attrs.id;
    2534             }
    2535 
    2536             attachment = Attachment.get( id );
    2537             newAttributes = attachment.parse( attrs, xhr );
    2538 
    2539             if ( ! _.isEqual( attachment.attributes, newAttributes ) ) {
    2540                 attachment.set( newAttributes );
    2541             }
    2542 
    2543             return attachment;
    2544         });
    2545     },
    2546     /**
    2547      * If the collection is a query, create and mirror an Attachments Query collection.
    2548      *
    2549      * @access private
    2550      */
    2551     _requery: function( refresh ) {
    2552         var props, Query;
    2553         if ( this.props.get('query') ) {
    2554             Query = require( './query.js' );
    2555             props = this.props.toJSON();
    2556             props.cache = ( true !== refresh );
    2557             this.mirror( Query.get( props ) );
    2558         }
    2559     },
    2560     /**
    2561      * If this collection is sorted by `menuOrder`, recalculates and saves
    2562      * the menu order to the database.
    2563      *
    2564      * @returns {undefined|Promise}
    2565      */
    2566     saveMenuOrder: function() {
    2567         if ( 'menuOrder' !== this.props.get('orderby') ) {
    2568             return;
    2569         }
    2570 
    2571         // Removes any uploading attachments, updates each attachment's
    2572         // menu order, and returns an object with an { id: menuOrder }
    2573         // mapping to pass to the request.
    2574         var attachments = this.chain().filter( function( attachment ) {
    2575             return ! _.isUndefined( attachment.id );
    2576         }).map( function( attachment, index ) {
    2577             // Indices start at 1.
    2578             index = index + 1;
    2579             attachment.set( 'menuOrder', index );
    2580             return [ attachment.id, index ];
    2581         }).object().value();
    2582 
    2583         if ( _.isEmpty( attachments ) ) {
    2584             return;
    2585         }
    2586 
    2587         return wp.media.post( 'save-attachment-order', {
    2588             nonce:       wp.media.model.settings.post.nonce,
    2589             post_id:     wp.media.model.settings.post.id,
    2590             attachments: attachments
    2591         });
    2592     }
    2593 }, {
    2594     /**
    2595      * A function to compare two attachment models in an attachments collection.
    2596      *
    2597      * Used as the default comparator for instances of wp.media.model.Attachments
    2598      * and its subclasses. @see wp.media.model.Attachments._changeOrderby().
    2599      *
    2600      * @static
    2601      *
    2602      * @param {Backbone.Model} a
    2603      * @param {Backbone.Model} b
    2604      * @param {Object} options
    2605      * @returns {Number} -1 if the first model should come before the second,
    2606      *    0 if they are of the same rank and
    2607      *    1 if the first model should come after.
    2608      */
    2609     comparator: function( a, b, options ) {
    2610         var key   = this.props.get('orderby'),
    2611             order = this.props.get('order') || 'DESC',
    2612             ac    = a.cid,
    2613             bc    = b.cid;
    2614 
    2615         a = a.get( key );
    2616         b = b.get( key );
    2617 
    2618         if ( 'date' === key || 'modified' === key ) {
    2619             a = a || new Date();
    2620             b = b || new Date();
    2621         }
    2622 
    2623         // If `options.ties` is set, don't enforce the `cid` tiebreaker.
    2624         if ( options && options.ties ) {
    2625             ac = bc = null;
    2626         }
    2627 
    2628         return ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );
    2629     },
    2630     /**
    2631      * @namespace
    2632      */
    2633     filters: {
    2634         /**
    2635          * @static
    2636          * Note that this client-side searching is *not* equivalent
    2637          * to our server-side searching.
    2638          *
    2639          * @param {wp.media.model.Attachment} attachment
    2640          *
    2641          * @this wp.media.model.Attachments
    2642          *
    2643          * @returns {Boolean}
    2644          */
    2645         search: function( attachment ) {
    2646             if ( ! this.props.get('search') ) {
    2647                 return true;
    2648             }
    2649 
    2650             return _.any(['title','filename','description','caption','name'], function( key ) {
    2651                 var value = attachment.get( key );
    2652                 return value && -1 !== value.search( this.props.get('search') );
    2653             }, this );
    2654         },
    2655         /**
    2656          * @static
    2657          * @param {wp.media.model.Attachment} attachment
    2658          *
    2659          * @this wp.media.model.Attachments
    2660          *
    2661          * @returns {Boolean}
    2662          */
    2663         type: function( attachment ) {
    2664             var type = this.props.get('type');
    2665             return ! type || -1 !== type.indexOf( attachment.get('type') );
    2666         },
    2667         /**
    2668          * @static
    2669          * @param {wp.media.model.Attachment} attachment
    2670          *
    2671          * @this wp.media.model.Attachments
    2672          *
    2673          * @returns {Boolean}
    2674          */
    2675         uploadedTo: function( attachment ) {
    2676             var uploadedTo = this.props.get('uploadedTo');
    2677             if ( _.isUndefined( uploadedTo ) ) {
    2678                 return true;
    2679             }
    2680 
    2681             return uploadedTo === attachment.get('uploadedTo');
    2682         },
    2683         /**
    2684          * @static
    2685          * @param {wp.media.model.Attachment} attachment
    2686          *
    2687          * @this wp.media.model.Attachments
    2688          *
    2689          * @returns {Boolean}
    2690          */
    2691         status: function( attachment ) {
    2692             var status = this.props.get('status');
    2693             if ( _.isUndefined( status ) ) {
    2694                 return true;
    2695             }
    2696 
    2697             return status === attachment.get('status');
    2698         }
    2699     }
    2700 });
    2701 
    2702 module.exports = Attachments;
    2703 },{"./attachment.js":16,"./query.js":19}],18:[function(require,module,exports){
    2704 /*globals jQuery, Backbone */
    2705 
    2706 /**
    2707  * wp.media.model.PostImage
    2708  *
    2709  * An instance of an image that's been embedded into a post.
    2710  *
    2711  * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.
    2712  *
    2713  * @class
    2714  * @augments Backbone.Model
    2715  *
    2716  * @param {int} [attributes]               Initial model attributes.
    2717  * @param {int} [attributes.attachment_id] ID of the attachment.
    2718  **/
    2719 var Attachment = require( './attachment' ),
    2720     PostImage;
    2721 
    2722 PostImage = Backbone.Model.extend({
    2723 
    2724     initialize: function( attributes ) {
    2725         this.attachment = false;
    2726 
    2727         if ( attributes.attachment_id ) {
    2728             this.attachment = Attachment.get( attributes.attachment_id );
    2729             if ( this.attachment.get( 'url' ) ) {
    2730                 this.dfd = jQuery.Deferred();
    2731                 this.dfd.resolve();
    2732             } else {
    2733                 this.dfd = this.attachment.fetch();
    2734             }
    2735             this.bindAttachmentListeners();
    2736         }
    2737 
    2738         // keep url in sync with changes to the type of link
    2739         this.on( 'change:link', this.updateLinkUrl, this );
    2740         this.on( 'change:size', this.updateSize, this );
    2741 
    2742         this.setLinkTypeFromUrl();
    2743         this.setAspectRatio();
    2744 
    2745         this.set( 'originalUrl', attributes.url );
    2746     },
    2747 
    2748     bindAttachmentListeners: function() {
    2749         this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );
    2750         this.listenTo( this.attachment, 'sync', this.setAspectRatio );
    2751         this.listenTo( this.attachment, 'change', this.updateSize );
    2752     },
    2753 
    2754     changeAttachment: function( attachment, props ) {
    2755         this.stopListening( this.attachment );
    2756         this.attachment = attachment;
    2757         this.bindAttachmentListeners();
    2758 
    2759         this.set( 'attachment_id', this.attachment.get( 'id' ) );
    2760         this.set( 'caption', this.attachment.get( 'caption' ) );
    2761         this.set( 'alt', this.attachment.get( 'alt' ) );
    2762         this.set( 'size', props.get( 'size' ) );
    2763         this.set( 'align', props.get( 'align' ) );
    2764         this.set( 'link', props.get( 'link' ) );
    2765         this.updateLinkUrl();
    2766         this.updateSize();
    2767     },
    2768 
    2769     setLinkTypeFromUrl: function() {
    2770         var linkUrl = this.get( 'linkUrl' ),
    2771             type;
    2772 
    2773         if ( ! linkUrl ) {
    2774             this.set( 'link', 'none' );
    2775             return;
    2776         }
    2777 
    2778         // default to custom if there is a linkUrl
    2779         type = 'custom';
    2780 
    2781         if ( this.attachment ) {
    2782             if ( this.attachment.get( 'url' ) === linkUrl ) {
    2783                 type = 'file';
    2784             } else if ( this.attachment.get( 'link' ) === linkUrl ) {
    2785                 type = 'post';
    2786             }
    2787         } else {
    2788             if ( this.get( 'url' ) === linkUrl ) {
    2789                 type = 'file';
    2790             }
    2791         }
    2792 
    2793         this.set( 'link', type );
    2794     },
    2795 
    2796     updateLinkUrl: function() {
    2797         var link = this.get( 'link' ),
    2798             url;
    2799 
    2800         switch( link ) {
    2801             case 'file':
    2802                 if ( this.attachment ) {
    2803                     url = this.attachment.get( 'url' );
    2804                 } else {
    2805                     url = this.get( 'url' );
    2806                 }
    2807                 this.set( 'linkUrl', url );
    2808                 break;
    2809             case 'post':
    2810                 this.set( 'linkUrl', this.attachment.get( 'link' ) );
    2811                 break;
    2812             case 'none':
    2813                 this.set( 'linkUrl', '' );
    2814                 break;
    2815         }
    2816     },
    2817 
    2818     updateSize: function() {
    2819         var size;
    2820 
    2821         if ( ! this.attachment ) {
    2822             return;
    2823         }
    2824 
    2825         if ( this.get( 'size' ) === 'custom' ) {
    2826             this.set( 'width', this.get( 'customWidth' ) );
    2827             this.set( 'height', this.get( 'customHeight' ) );
    2828             this.set( 'url', this.get( 'originalUrl' ) );
    2829             return;
    2830         }
    2831 
    2832         size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];
    2833 
    2834         if ( ! size ) {
    2835             return;
    2836         }
    2837 
    2838         this.set( 'url', size.url );
    2839         this.set( 'width', size.width );
    2840         this.set( 'height', size.height );
    2841     },
    2842 
    2843     setAspectRatio: function() {
    2844         var full;
    2845 
    2846         if ( this.attachment && this.attachment.get( 'sizes' ) ) {
    2847             full = this.attachment.get( 'sizes' ).full;
    2848 
    2849             if ( full ) {
    2850                 this.set( 'aspectRatio', full.width / full.height );
    2851                 return;
    2852             }
    2853         }
    2854 
    2855         this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );
    2856     }
    2857 });
    2858 
    2859 module.exports = PostImage;
    2860 },{"./attachment":16}],19:[function(require,module,exports){
    2861 /*globals jQuery, _, wp */
    2862 
    2863 /**
    2864  * wp.media.model.Query
    2865  *
    2866  * A collection of attachments that match the supplied query arguments.
    2867  *
    2868  * Note: Do NOT change this.args after the query has been initialized.
    2869  *       Things will break.
    2870  *
    2871  * @class
    2872  * @augments wp.media.model.Attachments
    2873  * @augments Backbone.Collection
    2874  *
    2875  * @param {array}  [models]                      Models to initialize with the collection.
    2876  * @param {object} [options]                     Options hash.
    2877  * @param {object} [options.args]                Attachments query arguments.
    2878  * @param {object} [options.args.posts_per_page]
    2879  */
    2880 var Attachments = require( './attachments.js' ),
    2881     Query;
    2882 
    2883 Query = Attachments.extend({
    2884     /**
    2885      * @global wp.Uploader
    2886      *
    2887      * @param {array}  [models=[]]  Array of initial models to populate the collection.
    2888      * @param {object} [options={}]
    2889      */
    2890     initialize: function( models, options ) {
    2891         var allowed;
    2892 
    2893         options = options || {};
    2894         Attachments.prototype.initialize.apply( this, arguments );
    2895 
    2896         this.args     = options.args;
    2897         this._hasMore = true;
    2898         this.created  = new Date();
    2899 
    2900         this.filters.order = function( attachment ) {
    2901             var orderby = this.props.get('orderby'),
    2902                 order = this.props.get('order');
    2903 
    2904             if ( ! this.comparator ) {
    2905                 return true;
    2906             }
    2907 
    2908             // We want any items that can be placed before the last
    2909             // item in the set. If we add any items after the last
    2910             // item, then we can't guarantee the set is complete.
    2911             if ( this.length ) {
    2912                 return 1 !== this.comparator( attachment, this.last(), { ties: true });
    2913 
    2914             // Handle the case where there are no items yet and
    2915             // we're sorting for recent items. In that case, we want
    2916             // changes that occurred after we created the query.
    2917             } else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {
    2918                 return attachment.get( orderby ) >= this.created;
    2919 
    2920             // If we're sorting by menu order and we have no items,
    2921             // accept any items that have the default menu order (0).
    2922             } else if ( 'ASC' === order && 'menuOrder' === orderby ) {
    2923                 return attachment.get( orderby ) === 0;
    2924             }
    2925 
    2926             // Otherwise, we don't want any items yet.
    2927             return false;
    2928         };
    2929 
    2930         // Observe the central `wp.Uploader.queue` collection to watch for
    2931         // new matches for the query.
    2932         //
    2933         // Only observe when a limited number of query args are set. There
    2934         // are no filters for other properties, so observing will result in
    2935         // false positives in those queries.
    2936         allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent' ];
    2937         if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {
    2938             this.observe( wp.Uploader.queue );
    2939         }
    2940     },
    2941     /**
    2942      * Whether there are more attachments that haven't been sync'd from the server
    2943      * that match the collection's query.
    2944      *
    2945      * @returns {boolean}
    2946      */
    2947     hasMore: function() {
    2948         return this._hasMore;
    2949     },
    2950     /**
    2951      * Fetch more attachments from the server for the collection.
    2952      *
    2953      * @param   {object}  [options={}]
    2954      * @returns {Promise}
    2955      */
    2956     more: function( options ) {
    2957         var query = this;
    2958 
    2959         // If there is already a request pending, return early with the Deferred object.
    2960         if ( this._more && 'pending' === this._more.state() ) {
    2961             return this._more;
    2962         }
    2963 
    2964         if ( ! this.hasMore() ) {
    2965             return jQuery.Deferred().resolveWith( this ).promise();
    2966         }
    2967 
    2968         options = options || {};
    2969         options.remove = false;
    2970 
    2971         return this._more = this.fetch( options ).done( function( resp ) {
    2972             if ( _.isEmpty( resp ) || -1 === this.args.posts_per_page || resp.length < this.args.posts_per_page ) {
    2973                 query._hasMore = false;
    2974             }
    2975         });
    2976     },
    2977     /**
    2978      * Overrides Backbone.Collection.sync
    2979      * Overrides wp.media.model.Attachments.sync
    2980      *
    2981      * @param {String} method
    2982      * @param {Backbone.Model} model
    2983      * @param {Object} [options={}]
    2984      * @returns {Promise}
    2985      */
    2986     sync: function( method, model, options ) {
    2987         var args, fallback;
    2988 
    2989         // Overload the read method so Attachment.fetch() functions correctly.
    2990         if ( 'read' === method ) {
    2991             options = options || {};
    2992             options.context = this;
    2993             options.data = _.extend( options.data || {}, {
    2994                 action:  'query-attachments',
    2995                 post_id: wp.media.model.settings.post.id
    2996             });
    2997 
    2998             // Clone the args so manipulation is non-destructive.
    2999             args = _.clone( this.args );
    3000 
    3001             // Determine which page to query.
    3002             if ( -1 !== args.posts_per_page ) {
    3003                 args.paged = Math.floor( this.length / args.posts_per_page ) + 1;
    3004             }
    3005 
    3006             options.data.query = args;
    3007             return wp.media.ajax( options );
    3008 
    3009         // Otherwise, fall back to Backbone.sync()
    3010         } else {
    3011             /**
    3012              * Call wp.media.model.Attachments.sync or Backbone.sync
    3013              */
    3014             fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
    3015             return fallback.sync.apply( this, arguments );
    3016         }
    3017     }
    3018 }, {
    3019     /**
    3020      * @readonly
    3021      */
    3022     defaultProps: {
    3023         orderby: 'date',
    3024         order:   'DESC'
    3025     },
    3026     /**
    3027      * @readonly
    3028      */
    3029     defaultArgs: {
    3030         posts_per_page: 40
    3031     },
    3032     /**
    3033      * @readonly
    3034      */
    3035     orderby: {
    3036         allowed:  [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],
    3037         /**
    3038          * A map of JavaScript orderby values to their WP_Query equivalents.
    3039          * @type {Object}
    3040          */
    3041         valuemap: {
    3042             'id':         'ID',
    3043             'uploadedTo': 'parent',
    3044             'menuOrder':  'menu_order ID'
    3045         }
    3046     },
    3047     /**
    3048      * A map of JavaScript query properties to their WP_Query equivalents.
    3049      *
    3050      * @readonly
    3051      */
    3052     propmap: {
    3053         'search':    's',
    3054         'type':      'post_mime_type',
    3055         'perPage':   'posts_per_page',
    3056         'menuOrder': 'menu_order',
    3057         'uploadedTo': 'post_parent',
    3058         'status':     'post_status',
    3059         'include':    'post__in',
    3060         'exclude':    'post__not_in'
    3061     },
    3062     /**
    3063      * Creates and returns an Attachments Query collection given the properties.
    3064      *
    3065      * Caches query objects and reuses where possible.
    3066      *
    3067      * @static
    3068      * @method
    3069      *
    3070      * @param {object} [props]
    3071      * @param {Object} [props.cache=true]   Whether to use the query cache or not.
    3072      * @param {Object} [props.order]
    3073      * @param {Object} [props.orderby]
    3074      * @param {Object} [props.include]
    3075      * @param {Object} [props.exclude]
    3076      * @param {Object} [props.s]
    3077      * @param {Object} [props.post_mime_type]
    3078      * @param {Object} [props.posts_per_page]
    3079      * @param {Object} [props.menu_order]
    3080      * @param {Object} [props.post_parent]
    3081      * @param {Object} [props.post_status]
    3082      * @param {Object} [options]
    3083      *
    3084      * @returns {wp.media.model.Query} A new Attachments Query collection.
    3085      */
    3086     get: (function(){
    3087         /**
    3088          * @static
    3089          * @type Array
    3090          */
    3091         var queries = [];
    3092 
    3093         /**
    3094          * @returns {Query}
    3095          */
    3096         return function( props, options ) {
    3097             var args     = {},
    3098                 orderby  = Query.orderby,
    3099                 defaults = Query.defaultProps,
    3100                 query,
    3101                 cache    = !! props.cache || _.isUndefined( props.cache );
    3102 
    3103             // Remove the `query` property. This isn't linked to a query,
    3104             // this *is* the query.
    3105             delete props.query;
    3106             delete props.cache;
    3107 
    3108             // Fill default args.
    3109             _.defaults( props, defaults );
    3110 
    3111             // Normalize the order.
    3112             props.order = props.order.toUpperCase();
    3113             if ( 'DESC' !== props.order && 'ASC' !== props.order ) {
    3114                 props.order = defaults.order.toUpperCase();
    3115             }
    3116 
    3117             // Ensure we have a valid orderby value.
    3118             if ( ! _.contains( orderby.allowed, props.orderby ) ) {
    3119                 props.orderby = defaults.orderby;
    3120             }
    3121 
    3122             _.each( [ 'include', 'exclude' ], function( prop ) {
    3123                 if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {
    3124                     props[ prop ] = [ props[ prop ] ];
    3125                 }
    3126             } );
    3127 
    3128             // Generate the query `args` object.
    3129             // Correct any differing property names.
    3130             _.each( props, function( value, prop ) {
    3131                 if ( _.isNull( value ) ) {
    3132                     return;
    3133                 }
    3134 
    3135                 args[ Query.propmap[ prop ] || prop ] = value;
    3136             });
    3137 
    3138             // Fill any other default query args.
    3139             _.defaults( args, Query.defaultArgs );
    3140 
    3141             // `props.orderby` does not always map directly to `args.orderby`.
    3142             // Substitute exceptions specified in orderby.keymap.
    3143             args.orderby = orderby.valuemap[ props.orderby ] || props.orderby;
    3144 
    3145             // Search the query cache for a matching query.
    3146             if ( cache ) {
    3147                 query = _.find( queries, function( query ) {
    3148                     return _.isEqual( query.args, args );
    3149                 });
    3150             } else {
    3151                 queries = [];
    3152             }
    3153 
    3154             // Otherwise, create a new query and add it to the cache.
    3155             if ( ! query ) {
    3156                 query = new Query( [], _.extend( options || {}, {
    3157                     props: props,
    3158                     args:  args
    3159                 } ) );
    3160                 queries.push( query );
    3161             }
    3162 
    3163             return query;
    3164         };
    3165     }())
    3166 });
    3167 
    3168 module.exports = Query;
    3169 },{"./attachments.js":17}],20:[function(require,module,exports){
    3170 /*globals _ */
    3171 
    3172 /**
    3173  * wp.media.model.Selection
    3174  *
    3175  * A selection of attachments.
    3176  *
    3177  * @class
    3178  * @augments wp.media.model.Attachments
    3179  * @augments Backbone.Collection
    3180  */
    3181 var Attachments = require( './attachments.js' ),
    3182     Selection;
    3183 
    3184 Selection = Attachments.extend({
    3185     /**
    3186      * Refresh the `single` model whenever the selection changes.
    3187      * Binds `single` instead of using the context argument to ensure
    3188      * it receives no parameters.
    3189      *
    3190      * @param {Array} [models=[]] Array of models used to populate the collection.
    3191      * @param {Object} [options={}]
    3192      */
    3193     initialize: function( models, options ) {
    3194         /**
    3195          * call 'initialize' directly on the parent class
    3196          */
    3197         Attachments.prototype.initialize.apply( this, arguments );
    3198         this.multiple = options && options.multiple;
    3199 
    3200         this.on( 'add remove reset', _.bind( this.single, this, false ) );
    3201     },
    3202 
    3203     /**
    3204      * If the workflow does not support multi-select, clear out the selection
    3205      * before adding a new attachment to it.
    3206      *
    3207      * @param {Array} models
    3208      * @param {Object} options
    3209      * @returns {wp.media.model.Attachment[]}
    3210      */
    3211     add: function( models, options ) {
    3212         if ( ! this.multiple ) {
    3213             this.remove( this.models );
    3214         }
    3215         /**
    3216          * call 'add' directly on the parent class
    3217          */
    3218         return Attachments.prototype.add.call( this, models, options );
    3219     },
    3220 
    3221     /**
    3222      * Fired when toggling (clicking on) an attachment in the modal.
    3223      *
    3224      * @param {undefined|boolean|wp.media.model.Attachment} model
    3225      *
    3226      * @fires wp.media.model.Selection#selection:single
    3227      * @fires wp.media.model.Selection#selection:unsingle
    3228      *
    3229      * @returns {Backbone.Model}
    3230      */
    3231     single: function( model ) {
    3232         var previous = this._single;
    3233 
    3234         // If a `model` is provided, use it as the single model.
    3235         if ( model ) {
    3236             this._single = model;
    3237         }
    3238         // If the single model isn't in the selection, remove it.
    3239         if ( this._single && ! this.get( this._single.cid ) ) {
    3240             delete this._single;
    3241         }
    3242 
    3243         this._single = this._single || this.last();
    3244 
    3245         // If single has changed, fire an event.
    3246         if ( this._single !== previous ) {
    3247             if ( previous ) {
    3248                 previous.trigger( 'selection:unsingle', previous, this );
    3249 
    3250                 // If the model was already removed, trigger the collection
    3251                 // event manually.
    3252                 if ( ! this.get( previous.cid ) ) {
    3253                     this.trigger( 'selection:unsingle', previous, this );
    3254                 }
    3255             }
    3256             if ( this._single ) {
    3257                 this._single.trigger( 'selection:single', this._single, this );
    3258             }
    3259         }
    3260 
    3261         // Return the single model, or the last model as a fallback.
    3262         return this._single;
    3263     }
    3264 });
    3265 
    3266 module.exports = Selection;
    3267 },{"./attachments.js":17}],21:[function(require,module,exports){
    32681996/*globals _ */
    32691997
     
    33322060
    33332061module.exports = selectionSync;
    3334 },{}],22:[function(require,module,exports){
     2062},{}],17:[function(require,module,exports){
    33352063/* global _wpMediaViewsL10n, confirm, getUserSetting, setUserSetting */
    33362064( function( $, _ ) {
     
    34812209
    34822210}(jQuery, _));
    3483 },{"./controllers/collection-add.js":1,"./controllers/collection-edit.js":2,"./controllers/cropper.js":3,"./controllers/edit-image.js":4,"./controllers/embed.js":5,"./controllers/featured-image.js":6,"./controllers/gallery-add.js":7,"./controllers/gallery-edit.js":8,"./controllers/image-details.js":9,"./controllers/library.js":10,"./controllers/media-library.js":11,"./controllers/region.js":12,"./controllers/replace-image.js":13,"./controllers/state-machine.js":14,"./controllers/state.js":15,"./utils/selection-sync.js":21,"./views/attachment-compat.js":23,"./views/attachment-filters.js":24,"./views/attachment-filters/all.js":25,"./views/attachment-filters/date.js":26,"./views/attachment-filters/uploaded.js":27,"./views/attachment.js":28,"./views/attachment/details.js":29,"./views/attachment/edit-library.js":30,"./views/attachment/edit-selection.js":31,"./views/attachment/library.js":32,"./views/attachment/selection.js":33,"./views/attachments.js":34,"./views/attachments/browser.js":35,"./views/attachments/selection.js":36,"./views/button-group.js":37,"./views/button.js":38,"./views/cropper.js":39,"./views/edit-image.js":40,"./views/embed.js":41,"./views/embed/image.js":42,"./views/embed/link.js":43,"./views/embed/url.js":44,"./views/focus-manager.js":45,"./views/frame/image-details.js":47,"./views/frame/post.js":48,"./views/frame/select.js":49,"./views/iframe.js":50,"./views/image-details.js":51,"./views/label.js":52,"./views/media-frame.js":53,"./views/menu-item.js":54,"./views/menu.js":55,"./views/modal.js":56,"./views/priority-list.js":57,"./views/router-item.js":58,"./views/router.js":59,"./views/search.js":60,"./views/selection.js":61,"./views/settings.js":62,"./views/settings/attachment-display.js":63,"./views/settings/gallery.js":64,"./views/settings/playlist.js":65,"./views/sidebar.js":66,"./views/spinner.js":67,"./views/toolbar.js":68,"./views/toolbar/embed.js":69,"./views/toolbar/select.js":70,"./views/uploader/editor.js":71,"./views/uploader/inline.js":72,"./views/uploader/status-error.js":73,"./views/uploader/status.js":74,"./views/uploader/window.js":75,"./views/view.js":76}],23:[function(require,module,exports){
     2211},{"./controllers/collection-add.js":1,"./controllers/collection-edit.js":2,"./controllers/cropper.js":3,"./controllers/edit-image.js":4,"./controllers/embed.js":5,"./controllers/featured-image.js":6,"./controllers/gallery-add.js":7,"./controllers/gallery-edit.js":8,"./controllers/image-details.js":9,"./controllers/library.js":10,"./controllers/media-library.js":11,"./controllers/region.js":12,"./controllers/replace-image.js":13,"./controllers/state-machine.js":14,"./controllers/state.js":15,"./utils/selection-sync.js":16,"./views/attachment-compat.js":18,"./views/attachment-filters.js":19,"./views/attachment-filters/all.js":20,"./views/attachment-filters/date.js":21,"./views/attachment-filters/uploaded.js":22,"./views/attachment.js":23,"./views/attachment/details.js":24,"./views/attachment/edit-library.js":25,"./views/attachment/edit-selection.js":26,"./views/attachment/library.js":27,"./views/attachment/selection.js":28,"./views/attachments.js":29,"./views/attachments/browser.js":30,"./views/attachments/selection.js":31,"./views/button-group.js":32,"./views/button.js":33,"./views/cropper.js":34,"./views/edit-image.js":35,"./views/embed.js":36,"./views/embed/image.js":37,"./views/embed/link.js":38,"./views/embed/url.js":39,"./views/focus-manager.js":40,"./views/frame/image-details.js":42,"./views/frame/post.js":43,"./views/frame/select.js":44,"./views/iframe.js":45,"./views/image-details.js":46,"./views/label.js":47,"./views/media-frame.js":48,"./views/menu-item.js":49,"./views/menu.js":50,"./views/modal.js":51,"./views/priority-list.js":52,"./views/router-item.js":53,"./views/router.js":54,"./views/search.js":55,"./views/selection.js":56,"./views/settings.js":57,"./views/settings/attachment-display.js":58,"./views/settings/gallery.js":59,"./views/settings/playlist.js":60,"./views/sidebar.js":61,"./views/spinner.js":62,"./views/toolbar.js":63,"./views/toolbar/embed.js":64,"./views/toolbar/select.js":65,"./views/uploader/editor.js":66,"./views/uploader/inline.js":67,"./views/uploader/status-error.js":68,"./views/uploader/status.js":69,"./views/uploader/window.js":70,"./views/view.js":71}],18:[function(require,module,exports){
    34842212/*globals _ */
    34852213
     
    35672295
    35682296module.exports = AttachmentCompat;
    3569 },{"./view.js":76}],24:[function(require,module,exports){
     2297},{"./view.js":71}],19:[function(require,module,exports){
    35702298/*globals _, jQuery */
    35712299
     
    36462374
    36472375module.exports = AttachmentFilters;
    3648 },{"./view.js":76}],25:[function(require,module,exports){
     2376},{"./view.js":71}],20:[function(require,module,exports){
    36492377/*globals _, wp */
    36502378
     
    37382466
    37392467module.exports = All;
    3740 },{"../attachment-filters.js":24}],26:[function(require,module,exports){
     2468},{"../attachment-filters.js":19}],21:[function(require,module,exports){
    37412469/*globals _, wp */
    37422470
     
    37812509
    37822510module.exports = DateFilter;
    3783 },{"../attachment-filters.js":24}],27:[function(require,module,exports){
     2511},{"../attachment-filters.js":19}],22:[function(require,module,exports){
    37842512/*globals wp */
    37852513
     
    38422570
    38432571module.exports = Uploaded;
    3844 },{"../attachment-filters.js":24}],28:[function(require,module,exports){
     2572},{"../attachment-filters.js":19}],23:[function(require,module,exports){
    38452573/*globals _, wp, jQuery */
    38462574
     
    43973125
    43983126module.exports = Attachment;
    4399 },{"./view.js":76}],29:[function(require,module,exports){
     3127},{"./view.js":71}],24:[function(require,module,exports){
    44003128/*globals _, wp */
    44013129
     
    45383266
    45393267module.exports = Details;
    4540 },{"../attachment.js":28}],30:[function(require,module,exports){
     3268},{"../attachment.js":23}],25:[function(require,module,exports){
    45413269/**
    45423270 * wp.media.view.Attachment.EditLibrary
     
    45583286
    45593287module.exports = EditLibrary;
    4560 },{"../attachment.js":28}],31:[function(require,module,exports){
     3288},{"../attachment.js":23}],26:[function(require,module,exports){
    45613289/**
    45623290 * wp.media.view.Attachments.EditSelection
     
    45793307
    45803308module.exports = EditSelection;
    4581 },{"./selection.js":33}],32:[function(require,module,exports){
     3309},{"./selection.js":28}],27:[function(require,module,exports){
    45823310/**
    45833311 * wp.media.view.Attachment.Library
     
    45993327
    46003328module.exports = Library;
    4601 },{"../attachment.js":28}],33:[function(require,module,exports){
     3329},{"../attachment.js":23}],28:[function(require,module,exports){
    46023330/**
    46033331 * wp.media.view.Attachment.Selection
     
    46233351
    46243352module.exports = Selection;
    4625 },{"../attachment.js":28}],34:[function(require,module,exports){
     3353},{"../attachment.js":23}],29:[function(require,module,exports){
    46263354/*globals _, wp, jQuery */
    46273355
     
    49243652
    49253653module.exports = Attachments;
    4926 },{"./attachment.js":28,"./view.js":76}],35:[function(require,module,exports){
     3654},{"./attachment.js":23,"./view.js":71}],30:[function(require,module,exports){
    49273655/*globals _, wp, jQuery */
    49283656
     
    53844112
    53854113module.exports = AttachmentsBrowser;
    5386 },{"../attachment-compat.js":23,"../attachment-filters/all.js":25,"../attachment-filters/date.js":26,"../attachment-filters/uploaded.js":27,"../attachment/details.js":29,"../attachment/library.js":32,"../attachments.js":34,"../label.js":52,"../search.js":60,"../settings/attachment-display.js":63,"../sidebar.js":66,"../spinner.js":67,"../toolbar.js":68,"../uploader/inline.js":72,"../uploader/status.js":74,"../view.js":76}],36:[function(require,module,exports){
     4114},{"../attachment-compat.js":18,"../attachment-filters/all.js":20,"../attachment-filters/date.js":21,"../attachment-filters/uploaded.js":22,"../attachment/details.js":24,"../attachment/library.js":27,"../attachments.js":29,"../label.js":47,"../search.js":55,"../settings/attachment-display.js":58,"../sidebar.js":61,"../spinner.js":62,"../toolbar.js":63,"../uploader/inline.js":67,"../uploader/status.js":69,"../view.js":71}],31:[function(require,module,exports){
    53874115/*globals _ */
    53884116
     
    54164144
    54174145module.exports = Selection;
    5418 },{"../attachment/selection.js":33,"../attachments.js":34}],37:[function(require,module,exports){
     4146},{"../attachment/selection.js":28,"../attachments.js":29}],32:[function(require,module,exports){
    54194147/*globals _, Backbone, jQuery */
    54204148
     
    54654193
    54664194module.exports = ButtonGroup;
    5467 },{"./button.js":38,"./view.js":76}],38:[function(require,module,exports){
     4195},{"./button.js":33,"./view.js":71}],33:[function(require,module,exports){
    54684196/*globals _, Backbone */
    54694197
     
    55554283
    55564284module.exports = Button;
    5557 },{"./view.js":76}],39:[function(require,module,exports){
     4285},{"./view.js":71}],34:[function(require,module,exports){
    55584286/*globals _, wp, jQuery */
    55594287
     
    56244352
    56254353module.exports = Cropper;
    5626 },{"./uploader/status-error.js":73,"./uploader/status.js":74,"./view.js":76}],40:[function(require,module,exports){
     4354},{"./uploader/status-error.js":68,"./uploader/status.js":69,"./view.js":71}],35:[function(require,module,exports){
    56274355/*globals _, wp */
    56284356
     
    56794407
    56804408module.exports = EditImage;
    5681 },{"./view.js":76}],41:[function(require,module,exports){
     4409},{"./view.js":71}],36:[function(require,module,exports){
    56824410/**
    56834411 * wp.media.view.Embed
     
    57484476
    57494477module.exports = Embed;
    5750 },{"./embed/image.js":42,"./embed/link.js":43,"./embed/url.js":44,"./view.js":76}],42:[function(require,module,exports){
     4478},{"./embed/image.js":37,"./embed/link.js":38,"./embed/url.js":39,"./view.js":71}],37:[function(require,module,exports){
    57514479/*globals wp */
    57524480
     
    57824510
    57834511module.exports = EmbedImage;
    5784 },{"../settings/attachment-display.js":63}],43:[function(require,module,exports){
     4512},{"../settings/attachment-display.js":58}],38:[function(require,module,exports){
    57854513/*globals _, wp, jQuery */
    57864514
     
    58504578
    58514579module.exports = EmbedLink;
    5852 },{"../settings.js":62}],44:[function(require,module,exports){
     4580},{"../settings.js":57}],39:[function(require,module,exports){
    58534581/*globals _, wp, jQuery */
    58544582
     
    59324660
    59334661module.exports = EmbedUrl;
    5934 },{"../view.js":76}],45:[function(require,module,exports){
     4662},{"../view.js":71}],40:[function(require,module,exports){
    59354663/**
    59364664 * wp.media.view.FocusManager
     
    59804708
    59814709module.exports = FocusManager;
    5982 },{"./view.js":76}],46:[function(require,module,exports){
     4710},{"./view.js":71}],41:[function(require,module,exports){
    59834711/*globals _, Backbone */
    59844712
     
    61534881
    61544882module.exports = Frame;
    6155 },{"../controllers/region.js":12,"../controllers/state-machine.js":14,"../controllers/state.js":15,"./view.js":76}],47:[function(require,module,exports){
     4883},{"../controllers/region.js":12,"../controllers/state-machine.js":14,"../controllers/state.js":15,"./view.js":71}],42:[function(require,module,exports){
    61564884/*globals wp */
    61574885
     
    61734901var Select = require( './select.js' ),
    61744902    Toolbar = require( '../toolbar.js' ),
    6175     PostImage = require( '../../models/post-image.js' ),
    6176     Selection = require( '../../models/selection.js' ),
    61774903    ImageDetailsController = require( '../../controllers/image-details.js' ),
    61784904    ReplaceImageController = require( '../../controllers/replace-image.js' ),
     
    61964922
    61974923    initialize: function( options ) {
    6198         this.image = new PostImage( options.metadata );
    6199         this.options.selection = new Selection( this.image.attachment, { multiple: false } );
     4924        this.image = new wp.media.model.PostImage( options.metadata );
     4925        this.options.selection = new wp.media.model.Selection( this.image.attachment, { multiple: false } );
    62004926        Select.prototype.initialize.apply( this, arguments );
    62014927    },
     
    63395065
    63405066module.exports = ImageDetails;
    6341 },{"../../controllers/edit-image.js":4,"../../controllers/image-details.js":9,"../../controllers/replace-image.js":13,"../../models/post-image.js":18,"../../models/selection.js":20,"../edit-image.js":40,"../image-details.js":51,"../toolbar.js":68,"./select.js":49}],48:[function(require,module,exports){
     5067},{"../../controllers/edit-image.js":4,"../../controllers/image-details.js":9,"../../controllers/replace-image.js":13,"../edit-image.js":35,"../image-details.js":46,"../toolbar.js":63,"./select.js":44}],43:[function(require,module,exports){
    63425068/*globals _, wp */
    63435069
     
    63665092    PlaylistSettings = require( '../settings/playlist.js' ),
    63675093    AttachmentsBrowser = require( '../attachments/browser.js' ),
    6368     SelectionModel = require( '../../models/selection.js' ),
    63695094    SelectionView = require( '../selection.js' ),
    63705095    EmbedController = require( '../../controllers/embed.js' ),
     
    68355560                    models = selection.where({ type: 'image' });
    68365561
    6837                 edit.set( 'library', new SelectionModel( models, {
     5562                edit.set( 'library', new wp.media.model.Selection( models, {
    68385563                    props:    selection.props.toJSON(),
    68395564                    multiple: true
     
    68655590                    models = selection.where({ type: 'audio' });
    68665591
    6867                 edit.set( 'library', new SelectionModel( models, {
     5592                edit.set( 'library', new wp.media.model.Selection( models, {
    68685593                    props:    selection.props.toJSON(),
    68695594                    multiple: true
     
    68955620                    models = selection.where({ type: 'video' });
    68965621
    6897                 edit.set( 'library', new SelectionModel( models, {
     5622                edit.set( 'library', new wp.media.model.Selection( models, {
    68985623                    props:    selection.props.toJSON(),
    68995624                    multiple: true
     
    70925817
    70935818module.exports = Post;
    7094 },{"../../controllers/collection-add.js":1,"../../controllers/collection-edit.js":2,"../../controllers/edit-image.js":4,"../../controllers/embed.js":5,"../../controllers/featured-image.js":6,"../../controllers/gallery-add.js":7,"../../controllers/gallery-edit.js":8,"../../controllers/library.js":10,"../../models/selection.js":20,"../attachment/edit-selection.js":31,"../attachments/browser.js":35,"../edit-image.js":40,"../embed.js":41,"../selection.js":61,"../settings/playlist.js":65,"../toolbar.js":68,"../toolbar/embed.js":69,"../view.js":76,"./select.js":49}],49:[function(require,module,exports){
     5819},{"../../controllers/collection-add.js":1,"../../controllers/collection-edit.js":2,"../../controllers/edit-image.js":4,"../../controllers/embed.js":5,"../../controllers/featured-image.js":6,"../../controllers/gallery-add.js":7,"../../controllers/gallery-edit.js":8,"../../controllers/library.js":10,"../attachment/edit-selection.js":26,"../attachments/browser.js":30,"../edit-image.js":35,"../embed.js":36,"../selection.js":56,"../settings/playlist.js":60,"../toolbar.js":63,"../toolbar/embed.js":64,"../view.js":71,"./select.js":44}],44:[function(require,module,exports){
    70955820/*globals _, wp */
    70965821
     
    71115836var MediaFrame = require( '../media-frame.js' ),
    71125837    Library = require( '../../controllers/library.js' ),
    7113     AttachmentsModel = require( '../../models/attachments.js' ),
    7114     SelectionModel = require( '../../models/selection.js' ),
    71155838    AttachmentsBrowser = require( '../attachments/browser.js' ),
    71165839    UploaderInline = require( '../uploader/inline.js' ),
     
    71485871        var selection = this.options.selection;
    71495872
    7150         if ( ! (selection instanceof SelectionModel) ) {
    7151             this.options.selection = new SelectionModel( selection, {
     5873        if ( ! (selection instanceof wp.media.model.Selection) ) {
     5874            this.options.selection = new wp.media.model.Selection( selection, {
    71525875                multiple: this.options.multiple
    71535876            });
     
    71555878
    71565879        this._selection = {
    7157             attachments: new AttachmentsModel(),
     5880            attachments: new wp.media.model.Attachments(),
    71585881            difference: []
    71595882        };
     
    72695992
    72705993module.exports = Select;
    7271 },{"../../controllers/library.js":10,"../../models/attachments.js":17,"../../models/selection.js":20,"../attachments/browser.js":35,"../media-frame.js":53,"../toolbar/select.js":70,"../uploader/inline.js":72}],50:[function(require,module,exports){
     5994},{"../../controllers/library.js":10,"../attachments/browser.js":30,"../media-frame.js":48,"../toolbar/select.js":65,"../uploader/inline.js":67}],45:[function(require,module,exports){
    72725995/**
    72735996 * wp.media.view.Iframe
     
    72956018
    72966019module.exports = Iframe;
    7297 },{"./view.js":76}],51:[function(require,module,exports){
     6020},{"./view.js":71}],46:[function(require,module,exports){
    72986021/*globals _, wp, jQuery */
    72996022
     
    74636186
    74646187module.exports = AttachmentDisplay;
    7465 },{"./settings/attachment-display.js":63}],52:[function(require,module,exports){
     6188},{"./settings/attachment-display.js":58}],47:[function(require,module,exports){
    74666189/**
    74676190 * @class
     
    74896212
    74906213module.exports = Label;
    7491 },{"./view.js":76}],53:[function(require,module,exports){
     6214},{"./view.js":71}],48:[function(require,module,exports){
    74926215/*globals _, wp, jQuery */
    74936216
     
    77446467
    77456468module.exports = MediaFrame;
    7746 },{"./frame.js":46,"./iframe.js":50,"./menu.js":55,"./modal.js":56,"./router.js":59,"./toolbar.js":68,"./uploader/window.js":75,"./view.js":76}],54:[function(require,module,exports){
     6469},{"./frame.js":41,"./iframe.js":45,"./menu.js":50,"./modal.js":51,"./router.js":54,"./toolbar.js":63,"./uploader/window.js":70,"./view.js":71}],49:[function(require,module,exports){
    77476470/*globals wp, jQuery */
    77486471
     
    78186541
    78196542module.exports = MenuItem;
    7820 },{"./view.js":76}],55:[function(require,module,exports){
     6543},{"./view.js":71}],50:[function(require,module,exports){
    78216544/**
    78226545 * wp.media.view.Menu
     
    79346657
    79356658module.exports = Menu;
    7936 },{"./menu-item.js":54,"./priority-list.js":57}],56:[function(require,module,exports){
     6659},{"./menu-item.js":49,"./priority-list.js":52}],51:[function(require,module,exports){
    79376660/*globals _, wp, jQuery */
    79386661
     
    81506873
    81516874module.exports = Modal;
    8152 },{"./focus-manager.js":45,"./view.js":76}],57:[function(require,module,exports){
     6875},{"./focus-manager.js":40,"./view.js":71}],52:[function(require,module,exports){
    81536876/*globals _, Backbone */
    81546877
     
    82516974
    82526975module.exports = PriorityList;
    8253 },{"./view.js":76}],58:[function(require,module,exports){
     6976},{"./view.js":71}],53:[function(require,module,exports){
    82546977/**
    82556978 * wp.media.view.RouterItem
     
    82777000
    82787001module.exports = RouterItem;
    8279 },{"./menu-item.js":54}],59:[function(require,module,exports){
     7002},{"./menu-item.js":49}],54:[function(require,module,exports){
    82807003/**
    82817004 * wp.media.view.Router
     
    83147037
    83157038module.exports = Router;
    8316 },{"./menu.js":55,"./router-item.js":58}],60:[function(require,module,exports){
     7039},{"./menu.js":50,"./router-item.js":53}],55:[function(require,module,exports){
    83177040/*globals wp */
    83187041
     
    83647087
    83657088module.exports = Search;
    8366 },{"./view.js":76}],61:[function(require,module,exports){
     7089},{"./view.js":71}],56:[function(require,module,exports){
    83677090/*globals _, Backbone, wp */
    83687091
     
    84507173
    84517174module.exports = Selection;
    8452 },{"./attachments/selection.js":36,"./view.js":76}],62:[function(require,module,exports){
     7175},{"./attachments/selection.js":31,"./view.js":71}],57:[function(require,module,exports){
    84537176/*globals _, Backbone, jQuery */
    84547177
     
    85727295
    85737296module.exports = Settings;
    8574 },{"./view.js":76}],63:[function(require,module,exports){
     7297},{"./view.js":71}],58:[function(require,module,exports){
    85757298/*globals _, wp */
    85767299
     
    86677390
    86687391module.exports = AttachmentDisplay;
    8669 },{"../settings.js":62}],64:[function(require,module,exports){
     7392},{"../settings.js":57}],59:[function(require,module,exports){
    86707393/*globals wp */
    86717394
     
    86887411
    86897412module.exports = Gallery;
    8690 },{"../settings.js":62}],65:[function(require,module,exports){
     7413},{"../settings.js":57}],60:[function(require,module,exports){
    86917414/*globals wp */
    86927415
     
    87097432
    87107433module.exports = Playlist;
    8711 },{"../settings.js":62}],66:[function(require,module,exports){
     7434},{"../settings.js":57}],61:[function(require,module,exports){
    87127435/**
    87137436 * wp.media.view.Sidebar
     
    87277450
    87287451module.exports = Sidebar;
    8729 },{"./priority-list.js":57}],67:[function(require,module,exports){
     7452},{"./priority-list.js":52}],62:[function(require,module,exports){
    87307453/*globals _, wp */
    87317454
     
    87667489
    87677490module.exports = Spinner;
    8768 },{"./view.js":76}],68:[function(require,module,exports){
     7491},{"./view.js":71}],63:[function(require,module,exports){
    87697492/*globals Backbone, _ */
    87707493
     
    89297652
    89307653module.exports = Toolbar;
    8931 },{"./button.js":38,"./priority-list.js":57,"./view.js":76}],69:[function(require,module,exports){
     7654},{"./button.js":33,"./priority-list.js":52,"./view.js":71}],64:[function(require,module,exports){
    89327655/*globals _, wp */
    89337656
     
    89677690
    89687691module.exports = Embed;
    8969 },{"./select.js":70}],70:[function(require,module,exports){
     7692},{"./select.js":65}],65:[function(require,module,exports){
    89707693/*globals _, wp */
    89717694
     
    90387761
    90397762module.exports = Select;
    9040 },{"../toolbar.js":68}],71:[function(require,module,exports){
     7763},{"../toolbar.js":63}],66:[function(require,module,exports){
    90417764/*globals _, wp, jQuery */
    90427765
     
    92607983
    92617984module.exports = EditorUploader;
    9262 },{"../view.js":76}],72:[function(require,module,exports){
     7985},{"../view.js":71}],67:[function(require,module,exports){
    92637986/*globals _, wp */
    92647987
     
    93938116
    93948117module.exports = UploaderInline;
    9395 },{"../view.js":76,"./status.js":74}],73:[function(require,module,exports){
     8118},{"../view.js":71,"./status.js":69}],68:[function(require,module,exports){
    93968119/*globals wp */
    93978120
     
    94138136
    94148137module.exports = UploaderStatusError;
    9415 },{"../view.js":76}],74:[function(require,module,exports){
     8138},{"../view.js":71}],69:[function(require,module,exports){
    94168139/*globals _, wp */
    94178140
     
    95538276
    95548277module.exports = UploaderStatus;
    9555 },{"../view.js":76,"./status-error.js":73}],75:[function(require,module,exports){
     8278},{"../view.js":71,"./status-error.js":68}],70:[function(require,module,exports){
    95568279/*globals _, wp, jQuery */
    95578280
     
    96668389
    96678390module.exports = UploaderWindow;
    9668 },{"../view.js":76}],76:[function(require,module,exports){
     8391},{"../view.js":71}],71:[function(require,module,exports){
    96698392/*globals wp */
    96708393
     
    97338456
    97348457module.exports = View;
    9735 },{}]},{},[22]);
     8458},{}]},{},[17]);
  • trunk/src/wp-includes/js/media/views/frame/image-details.js

    r31373 r31379  
    1818var Select = require( './select.js' ),
    1919    Toolbar = require( '../toolbar.js' ),
    20     PostImage = require( '../../models/post-image.js' ),
    21     Selection = require( '../../models/selection.js' ),
    2220    ImageDetailsController = require( '../../controllers/image-details.js' ),
    2321    ReplaceImageController = require( '../../controllers/replace-image.js' ),
     
    4139
    4240    initialize: function( options ) {
    43         this.image = new PostImage( options.metadata );
    44         this.options.selection = new Selection( this.image.attachment, { multiple: false } );
     41        this.image = new wp.media.model.PostImage( options.metadata );
     42        this.options.selection = new wp.media.model.Selection( this.image.attachment, { multiple: false } );
    4543        Select.prototype.initialize.apply( this, arguments );
    4644    },
  • trunk/src/wp-includes/js/media/views/frame/media-details.js

    r31373 r31379  
    1616    Toolbar = require( '../toolbar.js' ),
    1717    Select = require( './select.js' ),
    18     Selection = require( '../../models/selection.js' ),
    19     PostMedia = require( '../../models/post-media.js' ),
    2018    l10n = wp.media.view.l10n,
    2119    MediaDetails;
     
    3735        this.addText = options.addText;
    3836
    39         this.media = new PostMedia( options.metadata );
    40         this.options.selection = new Selection( this.media.attachment, { multiple: false } );
     37        this.media = new wp.media.model.PostMedia( options.metadata );
     38        this.options.selection = new wp.media.model.Selection( this.media.attachment, { multiple: false } );
    4139        Select.prototype.initialize.apply( this, arguments );
    4240    },
  • trunk/src/wp-includes/js/media/views/frame/post.js

    r31373 r31379  
    2525    PlaylistSettings = require( '../settings/playlist.js' ),
    2626    AttachmentsBrowser = require( '../attachments/browser.js' ),
    27     SelectionModel = require( '../../models/selection.js' ),
    2827    SelectionView = require( '../selection.js' ),
    2928    EmbedController = require( '../../controllers/embed.js' ),
     
    494493                    models = selection.where({ type: 'image' });
    495494
    496                 edit.set( 'library', new SelectionModel( models, {
     495                edit.set( 'library', new wp.media.model.Selection( models, {
    497496                    props:    selection.props.toJSON(),
    498497                    multiple: true
     
    524523                    models = selection.where({ type: 'audio' });
    525524
    526                 edit.set( 'library', new SelectionModel( models, {
     525                edit.set( 'library', new wp.media.model.Selection( models, {
    527526                    props:    selection.props.toJSON(),
    528527                    multiple: true
     
    554553                    models = selection.where({ type: 'video' });
    555554
    556                 edit.set( 'library', new SelectionModel( models, {
     555                edit.set( 'library', new wp.media.model.Selection( models, {
    557556                    props:    selection.props.toJSON(),
    558557                    multiple: true
  • trunk/src/wp-includes/js/media/views/frame/select.js

    r31373 r31379  
    1717var MediaFrame = require( '../media-frame.js' ),
    1818    Library = require( '../../controllers/library.js' ),
    19     AttachmentsModel = require( '../../models/attachments.js' ),
    20     SelectionModel = require( '../../models/selection.js' ),
    2119    AttachmentsBrowser = require( '../attachments/browser.js' ),
    2220    UploaderInline = require( '../uploader/inline.js' ),
     
    5452        var selection = this.options.selection;
    5553
    56         if ( ! (selection instanceof SelectionModel) ) {
    57             this.options.selection = new SelectionModel( selection, {
     54        if ( ! (selection instanceof wp.media.model.Selection) ) {
     55            this.options.selection = new wp.media.model.Selection( selection, {
    5856                multiple: this.options.multiple
    5957            });
     
    6159
    6260        this._selection = {
    63             attachments: new AttachmentsModel(),
     61            attachments: new wp.media.model.Attachments(),
    6462            difference: []
    6563        };
Note: See TracChangeset for help on using the changeset viewer.