balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

media-models.js (46500B)


      1 /******/ (function(modules) { // webpackBootstrap
      2 /******/ 	// The module cache
      3 /******/ 	var installedModules = {};
      4 /******/
      5 /******/ 	// The require function
      6 /******/ 	function __webpack_require__(moduleId) {
      7 /******/
      8 /******/ 		// Check if module is in cache
      9 /******/ 		if(installedModules[moduleId]) {
     10 /******/ 			return installedModules[moduleId].exports;
     11 /******/ 		}
     12 /******/ 		// Create a new module (and put it into the cache)
     13 /******/ 		var module = installedModules[moduleId] = {
     14 /******/ 			i: moduleId,
     15 /******/ 			l: false,
     16 /******/ 			exports: {}
     17 /******/ 		};
     18 /******/
     19 /******/ 		// Execute the module function
     20 /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
     21 /******/
     22 /******/ 		// Flag the module as loaded
     23 /******/ 		module.l = true;
     24 /******/
     25 /******/ 		// Return the exports of the module
     26 /******/ 		return module.exports;
     27 /******/ 	}
     28 /******/
     29 /******/
     30 /******/ 	// expose the modules object (__webpack_modules__)
     31 /******/ 	__webpack_require__.m = modules;
     32 /******/
     33 /******/ 	// expose the module cache
     34 /******/ 	__webpack_require__.c = installedModules;
     35 /******/
     36 /******/ 	// define getter function for harmony exports
     37 /******/ 	__webpack_require__.d = function(exports, name, getter) {
     38 /******/ 		if(!__webpack_require__.o(exports, name)) {
     39 /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
     40 /******/ 		}
     41 /******/ 	};
     42 /******/
     43 /******/ 	// define __esModule on exports
     44 /******/ 	__webpack_require__.r = function(exports) {
     45 /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
     46 /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
     47 /******/ 		}
     48 /******/ 		Object.defineProperty(exports, '__esModule', { value: true });
     49 /******/ 	};
     50 /******/
     51 /******/ 	// create a fake namespace object
     52 /******/ 	// mode & 1: value is a module id, require it
     53 /******/ 	// mode & 2: merge all properties of value into the ns
     54 /******/ 	// mode & 4: return value when already ns object
     55 /******/ 	// mode & 8|1: behave like require
     56 /******/ 	__webpack_require__.t = function(value, mode) {
     57 /******/ 		if(mode & 1) value = __webpack_require__(value);
     58 /******/ 		if(mode & 8) return value;
     59 /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
     60 /******/ 		var ns = Object.create(null);
     61 /******/ 		__webpack_require__.r(ns);
     62 /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
     63 /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
     64 /******/ 		return ns;
     65 /******/ 	};
     66 /******/
     67 /******/ 	// getDefaultExport function for compatibility with non-harmony modules
     68 /******/ 	__webpack_require__.n = function(module) {
     69 /******/ 		var getter = module && module.__esModule ?
     70 /******/ 			function getDefault() { return module['default']; } :
     71 /******/ 			function getModuleExports() { return module; };
     72 /******/ 		__webpack_require__.d(getter, 'a', getter);
     73 /******/ 		return getter;
     74 /******/ 	};
     75 /******/
     76 /******/ 	// Object.prototype.hasOwnProperty.call
     77 /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
     78 /******/
     79 /******/ 	// __webpack_public_path__
     80 /******/ 	__webpack_require__.p = "";
     81 /******/
     82 /******/
     83 /******/ 	// Load entry module and return exports
     84 /******/ 	return __webpack_require__(__webpack_require__.s = 2);
     85 /******/ })
     86 /************************************************************************/
     87 /******/ ({
     88 
     89 /***/ "0Ym0":
     90 /***/ (function(module, exports) {
     91 
     92 var $ = Backbone.$,
     93 	Attachment;
     94 
     95 /**
     96  * wp.media.model.Attachment
     97  *
     98  * @memberOf wp.media.model
     99  *
    100  * @class
    101  * @augments Backbone.Model
    102  */
    103 Attachment = Backbone.Model.extend(/** @lends wp.media.model.Attachment.prototype */{
    104 	/**
    105 	 * Triggered when attachment details change
    106 	 * Overrides Backbone.Model.sync
    107 	 *
    108 	 * @param {string} method
    109 	 * @param {wp.media.model.Attachment} model
    110 	 * @param {Object} [options={}]
    111 	 *
    112 	 * @return {Promise}
    113 	 */
    114 	sync: function( method, model, options ) {
    115 		// If the attachment does not yet have an `id`, return an instantly
    116 		// rejected promise. Otherwise, all of our requests will fail.
    117 		if ( _.isUndefined( this.id ) ) {
    118 			return $.Deferred().rejectWith( this ).promise();
    119 		}
    120 
    121 		// Overload the `read` request so Attachment.fetch() functions correctly.
    122 		if ( 'read' === method ) {
    123 			options = options || {};
    124 			options.context = this;
    125 			options.data = _.extend( options.data || {}, {
    126 				action: 'get-attachment',
    127 				id: this.id
    128 			});
    129 			return wp.media.ajax( options );
    130 
    131 		// Overload the `update` request so properties can be saved.
    132 		} else if ( 'update' === method ) {
    133 			// If we do not have the necessary nonce, fail immediately.
    134 			if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    135 				return $.Deferred().rejectWith( this ).promise();
    136 			}
    137 
    138 			options = options || {};
    139 			options.context = this;
    140 
    141 			// Set the action and ID.
    142 			options.data = _.extend( options.data || {}, {
    143 				action:  'save-attachment',
    144 				id:      this.id,
    145 				nonce:   this.get('nonces').update,
    146 				post_id: wp.media.model.settings.post.id
    147 			});
    148 
    149 			// Record the values of the changed attributes.
    150 			if ( model.hasChanged() ) {
    151 				options.data.changes = {};
    152 
    153 				_.each( model.changed, function( value, key ) {
    154 					options.data.changes[ key ] = this.get( key );
    155 				}, this );
    156 			}
    157 
    158 			return wp.media.ajax( options );
    159 
    160 		// Overload the `delete` request so attachments can be removed.
    161 		// This will permanently delete an attachment.
    162 		} else if ( 'delete' === method ) {
    163 			options = options || {};
    164 
    165 			if ( ! options.wait ) {
    166 				this.destroyed = true;
    167 			}
    168 
    169 			options.context = this;
    170 			options.data = _.extend( options.data || {}, {
    171 				action:   'delete-post',
    172 				id:       this.id,
    173 				_wpnonce: this.get('nonces')['delete']
    174 			});
    175 
    176 			return wp.media.ajax( options ).done( function() {
    177 				this.destroyed = true;
    178 			}).fail( function() {
    179 				this.destroyed = false;
    180 			});
    181 
    182 		// Otherwise, fall back to `Backbone.sync()`.
    183 		} else {
    184 			/**
    185 			 * Call `sync` directly on Backbone.Model
    186 			 */
    187 			return Backbone.Model.prototype.sync.apply( this, arguments );
    188 		}
    189 	},
    190 	/**
    191 	 * Convert date strings into Date objects.
    192 	 *
    193 	 * @param {Object} resp The raw response object, typically returned by fetch()
    194 	 * @return {Object} The modified response object, which is the attributes hash
    195 	 *                  to be set on the model.
    196 	 */
    197 	parse: function( resp ) {
    198 		if ( ! resp ) {
    199 			return resp;
    200 		}
    201 
    202 		resp.date = new Date( resp.date );
    203 		resp.modified = new Date( resp.modified );
    204 		return resp;
    205 	},
    206 	/**
    207 	 * @param {Object} data The properties to be saved.
    208 	 * @param {Object} options Sync options. e.g. patch, wait, success, error.
    209 	 *
    210 	 * @this Backbone.Model
    211 	 *
    212 	 * @return {Promise}
    213 	 */
    214 	saveCompat: function( data, options ) {
    215 		var model = this;
    216 
    217 		// If we do not have the necessary nonce, fail immediately.
    218 		if ( ! this.get('nonces') || ! this.get('nonces').update ) {
    219 			return $.Deferred().rejectWith( this ).promise();
    220 		}
    221 
    222 		return wp.media.post( 'save-attachment-compat', _.defaults({
    223 			id:      this.id,
    224 			nonce:   this.get('nonces').update,
    225 			post_id: wp.media.model.settings.post.id
    226 		}, data ) ).done( function( resp, status, xhr ) {
    227 			model.set( model.parse( resp, xhr ), options );
    228 		});
    229 	}
    230 },/** @lends wp.media.model.Attachment */{
    231 	/**
    232 	 * Create a new model on the static 'all' attachments collection and return it.
    233 	 *
    234 	 * @static
    235 	 *
    236 	 * @param {Object} attrs
    237 	 * @return {wp.media.model.Attachment}
    238 	 */
    239 	create: function( attrs ) {
    240 		var Attachments = wp.media.model.Attachments;
    241 		return Attachments.all.push( attrs );
    242 	},
    243 	/**
    244 	 * Create a new model on the static 'all' attachments collection and return it.
    245 	 *
    246 	 * If this function has already been called for the id,
    247 	 * it returns the specified attachment.
    248 	 *
    249 	 * @static
    250 	 * @param {string} id A string used to identify a model.
    251 	 * @param {Backbone.Model|undefined} attachment
    252 	 * @return {wp.media.model.Attachment}
    253 	 */
    254 	get: _.memoize( function( id, attachment ) {
    255 		var Attachments = wp.media.model.Attachments;
    256 		return Attachments.all.push( attachment || { id: id } );
    257 	})
    258 });
    259 
    260 module.exports = Attachment;
    261 
    262 
    263 /***/ }),
    264 
    265 /***/ 2:
    266 /***/ (function(module, exports, __webpack_require__) {
    267 
    268 module.exports = __webpack_require__("dx5j");
    269 
    270 
    271 /***/ }),
    272 
    273 /***/ "Io+g":
    274 /***/ (function(module, exports) {
    275 
    276 var Attachments = wp.media.model.Attachments,
    277 	Selection;
    278 
    279 /**
    280  * wp.media.model.Selection
    281  *
    282  * A selection of attachments.
    283  *
    284  * @memberOf wp.media.model
    285  *
    286  * @class
    287  * @augments wp.media.model.Attachments
    288  * @augments Backbone.Collection
    289  */
    290 Selection = Attachments.extend(/** @lends wp.media.model.Selection.prototype */{
    291 	/**
    292 	 * Refresh the `single` model whenever the selection changes.
    293 	 * Binds `single` instead of using the context argument to ensure
    294 	 * it receives no parameters.
    295 	 *
    296 	 * @param {Array} [models=[]] Array of models used to populate the collection.
    297 	 * @param {Object} [options={}]
    298 	 */
    299 	initialize: function( models, options ) {
    300 		/**
    301 		 * call 'initialize' directly on the parent class
    302 		 */
    303 		Attachments.prototype.initialize.apply( this, arguments );
    304 		this.multiple = options && options.multiple;
    305 
    306 		this.on( 'add remove reset', _.bind( this.single, this, false ) );
    307 	},
    308 
    309 	/**
    310 	 * If the workflow does not support multi-select, clear out the selection
    311 	 * before adding a new attachment to it.
    312 	 *
    313 	 * @param {Array} models
    314 	 * @param {Object} options
    315 	 * @return {wp.media.model.Attachment[]}
    316 	 */
    317 	add: function( models, options ) {
    318 		if ( ! this.multiple ) {
    319 			this.remove( this.models );
    320 		}
    321 		/**
    322 		 * call 'add' directly on the parent class
    323 		 */
    324 		return Attachments.prototype.add.call( this, models, options );
    325 	},
    326 
    327 	/**
    328 	 * Fired when toggling (clicking on) an attachment in the modal.
    329 	 *
    330 	 * @param {undefined|boolean|wp.media.model.Attachment} model
    331 	 *
    332 	 * @fires wp.media.model.Selection#selection:single
    333 	 * @fires wp.media.model.Selection#selection:unsingle
    334 	 *
    335 	 * @return {Backbone.Model}
    336 	 */
    337 	single: function( model ) {
    338 		var previous = this._single;
    339 
    340 		// If a `model` is provided, use it as the single model.
    341 		if ( model ) {
    342 			this._single = model;
    343 		}
    344 		// If the single model isn't in the selection, remove it.
    345 		if ( this._single && ! this.get( this._single.cid ) ) {
    346 			delete this._single;
    347 		}
    348 
    349 		this._single = this._single || this.last();
    350 
    351 		// If single has changed, fire an event.
    352 		if ( this._single !== previous ) {
    353 			if ( previous ) {
    354 				previous.trigger( 'selection:unsingle', previous, this );
    355 
    356 				// If the model was already removed, trigger the collection
    357 				// event manually.
    358 				if ( ! this.get( previous.cid ) ) {
    359 					this.trigger( 'selection:unsingle', previous, this );
    360 				}
    361 			}
    362 			if ( this._single ) {
    363 				this._single.trigger( 'selection:single', this._single, this );
    364 			}
    365 		}
    366 
    367 		// Return the single model, or the last model as a fallback.
    368 		return this._single;
    369 	}
    370 });
    371 
    372 module.exports = Selection;
    373 
    374 
    375 /***/ }),
    376 
    377 /***/ "K0z/":
    378 /***/ (function(module, exports) {
    379 
    380 /**
    381  * wp.media.model.Attachments
    382  *
    383  * A collection of attachments.
    384  *
    385  * This collection has no persistence with the server without supplying
    386  * 'options.props.query = true', which will mirror the collection
    387  * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().
    388  *
    389  * @memberOf wp.media.model
    390  *
    391  * @class
    392  * @augments Backbone.Collection
    393  *
    394  * @param {array}  [models]                Models to initialize with the collection.
    395  * @param {object} [options]               Options hash for the collection.
    396  * @param {string} [options.props]         Options hash for the initial query properties.
    397  * @param {string} [options.props.order]   Initial order (ASC or DESC) for the collection.
    398  * @param {string} [options.props.orderby] Initial attribute key to order the collection by.
    399  * @param {string} [options.props.query]   Whether the collection is linked to an attachments query.
    400  * @param {string} [options.observe]
    401  * @param {string} [options.filters]
    402  *
    403  */
    404 var Attachments = Backbone.Collection.extend(/** @lends wp.media.model.Attachments.prototype */{
    405 	/**
    406 	 * @type {wp.media.model.Attachment}
    407 	 */
    408 	model: wp.media.model.Attachment,
    409 	/**
    410 	 * @param {Array} [models=[]] Array of models used to populate the collection.
    411 	 * @param {Object} [options={}]
    412 	 */
    413 	initialize: function( models, options ) {
    414 		options = options || {};
    415 
    416 		this.props   = new Backbone.Model();
    417 		this.filters = options.filters || {};
    418 
    419 		// Bind default `change` events to the `props` model.
    420 		this.props.on( 'change', this._changeFilteredProps, this );
    421 
    422 		this.props.on( 'change:order',   this._changeOrder,   this );
    423 		this.props.on( 'change:orderby', this._changeOrderby, this );
    424 		this.props.on( 'change:query',   this._changeQuery,   this );
    425 
    426 		this.props.set( _.defaults( options.props || {} ) );
    427 
    428 		if ( options.observe ) {
    429 			this.observe( options.observe );
    430 		}
    431 	},
    432 	/**
    433 	 * Sort the collection when the order attribute changes.
    434 	 *
    435 	 * @access private
    436 	 */
    437 	_changeOrder: function() {
    438 		if ( this.comparator ) {
    439 			this.sort();
    440 		}
    441 	},
    442 	/**
    443 	 * Set the default comparator only when the `orderby` property is set.
    444 	 *
    445 	 * @access private
    446 	 *
    447 	 * @param {Backbone.Model} model
    448 	 * @param {string} orderby
    449 	 */
    450 	_changeOrderby: function( model, orderby ) {
    451 		// If a different comparator is defined, bail.
    452 		if ( this.comparator && this.comparator !== Attachments.comparator ) {
    453 			return;
    454 		}
    455 
    456 		if ( orderby && 'post__in' !== orderby ) {
    457 			this.comparator = Attachments.comparator;
    458 		} else {
    459 			delete this.comparator;
    460 		}
    461 	},
    462 	/**
    463 	 * If the `query` property is set to true, query the server using
    464 	 * the `props` values, and sync the results to this collection.
    465 	 *
    466 	 * @access private
    467 	 *
    468 	 * @param {Backbone.Model} model
    469 	 * @param {boolean} query
    470 	 */
    471 	_changeQuery: function( model, query ) {
    472 		if ( query ) {
    473 			this.props.on( 'change', this._requery, this );
    474 			this._requery();
    475 		} else {
    476 			this.props.off( 'change', this._requery, this );
    477 		}
    478 	},
    479 	/**
    480 	 * @access private
    481 	 *
    482 	 * @param {Backbone.Model} model
    483 	 */
    484 	_changeFilteredProps: function( model ) {
    485 		// If this is a query, updating the collection will be handled by
    486 		// `this._requery()`.
    487 		if ( this.props.get('query') ) {
    488 			return;
    489 		}
    490 
    491 		var changed = _.chain( model.changed ).map( function( t, prop ) {
    492 			var filter = Attachments.filters[ prop ],
    493 				term = model.get( prop );
    494 
    495 			if ( ! filter ) {
    496 				return;
    497 			}
    498 
    499 			if ( term && ! this.filters[ prop ] ) {
    500 				this.filters[ prop ] = filter;
    501 			} else if ( ! term && this.filters[ prop ] === filter ) {
    502 				delete this.filters[ prop ];
    503 			} else {
    504 				return;
    505 			}
    506 
    507 			// Record the change.
    508 			return true;
    509 		}, this ).any().value();
    510 
    511 		if ( ! changed ) {
    512 			return;
    513 		}
    514 
    515 		// If no `Attachments` model is provided to source the searches from,
    516 		// then automatically generate a source from the existing models.
    517 		if ( ! this._source ) {
    518 			this._source = new Attachments( this.models );
    519 		}
    520 
    521 		this.reset( this._source.filter( this.validator, this ) );
    522 	},
    523 
    524 	validateDestroyed: false,
    525 	/**
    526 	 * Checks whether an attachment is valid.
    527 	 *
    528 	 * @param {wp.media.model.Attachment} attachment
    529 	 * @return {boolean}
    530 	 */
    531 	validator: function( attachment ) {
    532 
    533 		if ( ! this.validateDestroyed && attachment.destroyed ) {
    534 			return false;
    535 		}
    536 		return _.all( this.filters, function( filter ) {
    537 			return !! filter.call( this, attachment );
    538 		}, this );
    539 	},
    540 	/**
    541 	 * Add or remove an attachment to the collection depending on its validity.
    542 	 *
    543 	 * @param {wp.media.model.Attachment} attachment
    544 	 * @param {Object} options
    545 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    546 	 */
    547 	validate: function( attachment, options ) {
    548 		var valid = this.validator( attachment ),
    549 			hasAttachment = !! this.get( attachment.cid );
    550 
    551 		if ( ! valid && hasAttachment ) {
    552 			this.remove( attachment, options );
    553 		} else if ( valid && ! hasAttachment ) {
    554 			this.add( attachment, options );
    555 		}
    556 
    557 		return this;
    558 	},
    559 
    560 	/**
    561 	 * Add or remove all attachments from another collection depending on each one's validity.
    562 	 *
    563 	 * @param {wp.media.model.Attachments} attachments
    564 	 * @param {Object} [options={}]
    565 	 *
    566 	 * @fires wp.media.model.Attachments#reset
    567 	 *
    568 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    569 	 */
    570 	validateAll: function( attachments, options ) {
    571 		options = options || {};
    572 
    573 		_.each( attachments.models, function( attachment ) {
    574 			this.validate( attachment, { silent: true });
    575 		}, this );
    576 
    577 		if ( ! options.silent ) {
    578 			this.trigger( 'reset', this, options );
    579 		}
    580 		return this;
    581 	},
    582 	/**
    583 	 * Start observing another attachments collection change events
    584 	 * and replicate them on this collection.
    585 	 *
    586 	 * @param {wp.media.model.Attachments} The attachments collection to observe.
    587 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    588 	 */
    589 	observe: function( attachments ) {
    590 		this.observers = this.observers || [];
    591 		this.observers.push( attachments );
    592 
    593 		attachments.on( 'add change remove', this._validateHandler, this );
    594 		attachments.on( 'add', this._addToTotalAttachments, this );
    595 		attachments.on( 'remove', this._removeFromTotalAttachments, this );
    596 		attachments.on( 'reset', this._validateAllHandler, this );
    597 		this.validateAll( attachments );
    598 		return this;
    599 	},
    600 	/**
    601 	 * Stop replicating collection change events from another attachments collection.
    602 	 *
    603 	 * @param {wp.media.model.Attachments} The attachments collection to stop observing.
    604 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    605 	 */
    606 	unobserve: function( attachments ) {
    607 		if ( attachments ) {
    608 			attachments.off( null, null, this );
    609 			this.observers = _.without( this.observers, attachments );
    610 
    611 		} else {
    612 			_.each( this.observers, function( attachments ) {
    613 				attachments.off( null, null, this );
    614 			}, this );
    615 			delete this.observers;
    616 		}
    617 
    618 		return this;
    619 	},
    620 	/**
    621 	 * Update total attachment count when items are added to a collection.
    622 	 *
    623 	 * @access private
    624 	 *
    625 	 * @since 5.8.0
    626 	 */
    627 	_removeFromTotalAttachments: function() {
    628 		if ( this.mirroring ) {
    629 			this.mirroring.totalAttachments = this.mirroring.totalAttachments - 1;
    630 		}
    631 	},
    632 	/**
    633 	 * Update total attachment count when items are added to a collection.
    634 	 *
    635 	 * @access private
    636 	 *
    637 	 * @since 5.8.0
    638 	 */
    639 	_addToTotalAttachments: function() {
    640 		if ( this.mirroring ) {
    641 			this.mirroring.totalAttachments = this.mirroring.totalAttachments + 1;
    642 		}
    643 	},
    644 	/**
    645 	 * @access private
    646 	 *
    647 	 * @param {wp.media.model.Attachments} attachment
    648 	 * @param {wp.media.model.Attachments} attachments
    649 	 * @param {Object} options
    650 	 *
    651 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    652 	 */
    653 	_validateHandler: function( attachment, attachments, options ) {
    654 		// If we're not mirroring this `attachments` collection,
    655 		// only retain the `silent` option.
    656 		options = attachments === this.mirroring ? options : {
    657 			silent: options && options.silent
    658 		};
    659 
    660 		return this.validate( attachment, options );
    661 	},
    662 	/**
    663 	 * @access private
    664 	 *
    665 	 * @param {wp.media.model.Attachments} attachments
    666 	 * @param {Object} options
    667 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    668 	 */
    669 	_validateAllHandler: function( attachments, options ) {
    670 		return this.validateAll( attachments, options );
    671 	},
    672 	/**
    673 	 * Start mirroring another attachments collection, clearing out any models already
    674 	 * in the collection.
    675 	 *
    676 	 * @param {wp.media.model.Attachments} The attachments collection to mirror.
    677 	 * @return {wp.media.model.Attachments} Returns itself to allow chaining.
    678 	 */
    679 	mirror: function( attachments ) {
    680 		if ( this.mirroring && this.mirroring === attachments ) {
    681 			return this;
    682 		}
    683 
    684 		this.unmirror();
    685 		this.mirroring = attachments;
    686 
    687 		// Clear the collection silently. A `reset` event will be fired
    688 		// when `observe()` calls `validateAll()`.
    689 		this.reset( [], { silent: true } );
    690 		this.observe( attachments );
    691 
    692 		// Used for the search results.
    693 		this.trigger( 'attachments:received', this );
    694 		return this;
    695 	},
    696 	/**
    697 	 * Stop mirroring another attachments collection.
    698 	 */
    699 	unmirror: function() {
    700 		if ( ! this.mirroring ) {
    701 			return;
    702 		}
    703 
    704 		this.unobserve( this.mirroring );
    705 		delete this.mirroring;
    706 	},
    707 	/**
    708 	 * Retrieve more attachments from the server for the collection.
    709 	 *
    710 	 * Only works if the collection is mirroring a Query Attachments collection,
    711 	 * and forwards to its `more` method. This collection class doesn't have
    712 	 * server persistence by itself.
    713 	 *
    714 	 * @param {Object} options
    715 	 * @return {Promise}
    716 	 */
    717 	more: function( options ) {
    718 		var deferred = jQuery.Deferred(),
    719 			mirroring = this.mirroring,
    720 			attachments = this;
    721 
    722 		if ( ! mirroring || ! mirroring.more ) {
    723 			return deferred.resolveWith( this ).promise();
    724 		}
    725 		/*
    726 		 * If we're mirroring another collection, forward `more` to
    727 		 * the mirrored collection. Account for a race condition by
    728 		 * checking if we're still mirroring that collection when
    729 		 * the request resolves.
    730 		 */
    731 		mirroring.more( options ).done( function() {
    732 			if ( this === attachments.mirroring ) {
    733 				deferred.resolveWith( this );
    734 			}
    735 
    736 			// Used for the search results.
    737 			attachments.trigger( 'attachments:received', this );
    738 		});
    739 
    740 		return deferred.promise();
    741 	},
    742 	/**
    743 	 * Whether there are more attachments that haven't been sync'd from the server
    744 	 * that match the collection's query.
    745 	 *
    746 	 * Only works if the collection is mirroring a Query Attachments collection,
    747 	 * and forwards to its `hasMore` method. This collection class doesn't have
    748 	 * server persistence by itself.
    749 	 *
    750 	 * @return {boolean}
    751 	 */
    752 	hasMore: function() {
    753 		return this.mirroring ? this.mirroring.hasMore() : false;
    754 	},
    755 	/**
    756 	 * Holds the total number of attachments.
    757 	 *
    758 	 * @since 5.8.0
    759 	 */
    760 	totalAttachments: 0,
    761 
    762 	/**
    763 	 * Gets the total number of attachments.
    764 	 *
    765 	 * @since 5.8.0
    766 	 *
    767 	 * @return {number} The total number of attachments.
    768 	 */
    769 	getTotalAttachments: function() {
    770 		return this.mirroring ? this.mirroring.totalAttachments : 0;
    771 	},
    772 
    773 	/**
    774 	 * A custom Ajax-response parser.
    775 	 *
    776 	 * See trac ticket #24753.
    777 	 *
    778 	 * Called automatically by Backbone whenever a collection's models are returned
    779 	 * by the server, in fetch. The default implementation is a no-op, simply
    780 	 * passing through the JSON response. We override this to add attributes to
    781 	 * the collection items.
    782 	 *
    783 	 * @param {Object|Array} response The raw response Object/Array.
    784 	 * @param {Object} xhr
    785 	 * @return {Array} The array of model attributes to be added to the collection
    786 	 */
    787 	parse: function( response, xhr ) {
    788 		if ( ! _.isArray( response ) ) {
    789 			  response = [response];
    790 		}
    791 		return _.map( response, function( attrs ) {
    792 			var id, attachment, newAttributes;
    793 
    794 			if ( attrs instanceof Backbone.Model ) {
    795 				id = attrs.get( 'id' );
    796 				attrs = attrs.attributes;
    797 			} else {
    798 				id = attrs.id;
    799 			}
    800 
    801 			attachment = wp.media.model.Attachment.get( id );
    802 			newAttributes = attachment.parse( attrs, xhr );
    803 
    804 			if ( ! _.isEqual( attachment.attributes, newAttributes ) ) {
    805 				attachment.set( newAttributes );
    806 			}
    807 
    808 			return attachment;
    809 		});
    810 	},
    811 
    812 	/**
    813 	 * If the collection is a query, create and mirror an Attachments Query collection.
    814 	 *
    815 	 * @access private
    816 	 * @param {Boolean} refresh Deprecated, refresh parameter no longer used.
    817 	 */
    818 	_requery: function() {
    819 		var props;
    820 		if ( this.props.get('query') ) {
    821 			props = this.props.toJSON();
    822 			this.mirror( wp.media.model.Query.get( props ) );
    823 		}
    824 	},
    825 	/**
    826 	 * If this collection is sorted by `menuOrder`, recalculates and saves
    827 	 * the menu order to the database.
    828 	 *
    829 	 * @return {undefined|Promise}
    830 	 */
    831 	saveMenuOrder: function() {
    832 		if ( 'menuOrder' !== this.props.get('orderby') ) {
    833 			return;
    834 		}
    835 
    836 		/*
    837 		 * Removes any uploading attachments, updates each attachment's
    838 		 * menu order, and returns an object with an { id: menuOrder }
    839 		 * mapping to pass to the request.
    840 		 */
    841 		var attachments = this.chain().filter( function( attachment ) {
    842 			return ! _.isUndefined( attachment.id );
    843 		}).map( function( attachment, index ) {
    844 			// Indices start at 1.
    845 			index = index + 1;
    846 			attachment.set( 'menuOrder', index );
    847 			return [ attachment.id, index ];
    848 		}).object().value();
    849 
    850 		if ( _.isEmpty( attachments ) ) {
    851 			return;
    852 		}
    853 
    854 		return wp.media.post( 'save-attachment-order', {
    855 			nonce:       wp.media.model.settings.post.nonce,
    856 			post_id:     wp.media.model.settings.post.id,
    857 			attachments: attachments
    858 		});
    859 	}
    860 },/** @lends wp.media.model.Attachments */{
    861 	/**
    862 	 * A function to compare two attachment models in an attachments collection.
    863 	 *
    864 	 * Used as the default comparator for instances of wp.media.model.Attachments
    865 	 * and its subclasses. @see wp.media.model.Attachments._changeOrderby().
    866 	 *
    867 	 * @param {Backbone.Model} a
    868 	 * @param {Backbone.Model} b
    869 	 * @param {Object} options
    870 	 * @return {number} -1 if the first model should come before the second,
    871 	 *                   0 if they are of the same rank and
    872 	 *                   1 if the first model should come after.
    873 	 */
    874 	comparator: function( a, b, options ) {
    875 		var key   = this.props.get('orderby'),
    876 			order = this.props.get('order') || 'DESC',
    877 			ac    = a.cid,
    878 			bc    = b.cid;
    879 
    880 		a = a.get( key );
    881 		b = b.get( key );
    882 
    883 		if ( 'date' === key || 'modified' === key ) {
    884 			a = a || new Date();
    885 			b = b || new Date();
    886 		}
    887 
    888 		// If `options.ties` is set, don't enforce the `cid` tiebreaker.
    889 		if ( options && options.ties ) {
    890 			ac = bc = null;
    891 		}
    892 
    893 		return ( 'DESC' === order ) ? wp.media.compare( a, b, ac, bc ) : wp.media.compare( b, a, bc, ac );
    894 	},
    895 	/** @namespace wp.media.model.Attachments.filters */
    896 	filters: {
    897 		/**
    898 		 * @static
    899 		 * Note that this client-side searching is *not* equivalent
    900 		 * to our server-side searching.
    901 		 *
    902 		 * @param {wp.media.model.Attachment} attachment
    903 		 *
    904 		 * @this wp.media.model.Attachments
    905 		 *
    906 		 * @return {Boolean}
    907 		 */
    908 		search: function( attachment ) {
    909 			if ( ! this.props.get('search') ) {
    910 				return true;
    911 			}
    912 
    913 			return _.any(['title','filename','description','caption','name'], function( key ) {
    914 				var value = attachment.get( key );
    915 				return value && -1 !== value.search( this.props.get('search') );
    916 			}, this );
    917 		},
    918 		/**
    919 		 * @static
    920 		 * @param {wp.media.model.Attachment} attachment
    921 		 *
    922 		 * @this wp.media.model.Attachments
    923 		 *
    924 		 * @return {boolean}
    925 		 */
    926 		type: function( attachment ) {
    927 			var type = this.props.get('type'), atts = attachment.toJSON(), mime, found;
    928 
    929 			if ( ! type || ( _.isArray( type ) && ! type.length ) ) {
    930 				return true;
    931 			}
    932 
    933 			mime = atts.mime || ( atts.file && atts.file.type ) || '';
    934 
    935 			if ( _.isArray( type ) ) {
    936 				found = _.find( type, function (t) {
    937 					return -1 !== mime.indexOf( t );
    938 				} );
    939 			} else {
    940 				found = -1 !== mime.indexOf( type );
    941 			}
    942 
    943 			return found;
    944 		},
    945 		/**
    946 		 * @static
    947 		 * @param {wp.media.model.Attachment} attachment
    948 		 *
    949 		 * @this wp.media.model.Attachments
    950 		 *
    951 		 * @return {boolean}
    952 		 */
    953 		uploadedTo: function( attachment ) {
    954 			var uploadedTo = this.props.get('uploadedTo');
    955 			if ( _.isUndefined( uploadedTo ) ) {
    956 				return true;
    957 			}
    958 
    959 			return uploadedTo === attachment.get('uploadedTo');
    960 		},
    961 		/**
    962 		 * @static
    963 		 * @param {wp.media.model.Attachment} attachment
    964 		 *
    965 		 * @this wp.media.model.Attachments
    966 		 *
    967 		 * @return {boolean}
    968 		 */
    969 		status: function( attachment ) {
    970 			var status = this.props.get('status');
    971 			if ( _.isUndefined( status ) ) {
    972 				return true;
    973 			}
    974 
    975 			return status === attachment.get('status');
    976 		}
    977 	}
    978 });
    979 
    980 module.exports = Attachments;
    981 
    982 
    983 /***/ }),
    984 
    985 /***/ "dx5j":
    986 /***/ (function(module, exports, __webpack_require__) {
    987 
    988 /**
    989  * @output wp-includes/js/media-models.js
    990  */
    991 
    992 var $ = jQuery,
    993 	Attachment, Attachments, l10n, media;
    994 
    995 /** @namespace wp */
    996 window.wp = window.wp || {};
    997 
    998 /**
    999  * Create and return a media frame.
   1000  *
   1001  * Handles the default media experience.
   1002  *
   1003  * @alias wp.media
   1004  * @memberOf wp
   1005  * @namespace
   1006  *
   1007  * @param {Object} attributes The properties passed to the main media controller.
   1008  * @return {wp.media.view.MediaFrame} A media workflow.
   1009  */
   1010 media = wp.media = function( attributes ) {
   1011 	var MediaFrame = media.view.MediaFrame,
   1012 		frame;
   1013 
   1014 	if ( ! MediaFrame ) {
   1015 		return;
   1016 	}
   1017 
   1018 	attributes = _.defaults( attributes || {}, {
   1019 		frame: 'select'
   1020 	});
   1021 
   1022 	if ( 'select' === attributes.frame && MediaFrame.Select ) {
   1023 		frame = new MediaFrame.Select( attributes );
   1024 	} else if ( 'post' === attributes.frame && MediaFrame.Post ) {
   1025 		frame = new MediaFrame.Post( attributes );
   1026 	} else if ( 'manage' === attributes.frame && MediaFrame.Manage ) {
   1027 		frame = new MediaFrame.Manage( attributes );
   1028 	} else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) {
   1029 		frame = new MediaFrame.ImageDetails( attributes );
   1030 	} else if ( 'audio' === attributes.frame && MediaFrame.AudioDetails ) {
   1031 		frame = new MediaFrame.AudioDetails( attributes );
   1032 	} else if ( 'video' === attributes.frame && MediaFrame.VideoDetails ) {
   1033 		frame = new MediaFrame.VideoDetails( attributes );
   1034 	} else if ( 'edit-attachments' === attributes.frame && MediaFrame.EditAttachments ) {
   1035 		frame = new MediaFrame.EditAttachments( attributes );
   1036 	}
   1037 
   1038 	delete attributes.frame;
   1039 
   1040 	media.frame = frame;
   1041 
   1042 	return frame;
   1043 };
   1044 
   1045 /** @namespace wp.media.model */
   1046 /** @namespace wp.media.view */
   1047 /** @namespace wp.media.controller */
   1048 /** @namespace wp.media.frames */
   1049 _.extend( media, { model: {}, view: {}, controller: {}, frames: {} });
   1050 
   1051 // Link any localized strings.
   1052 l10n = media.model.l10n = window._wpMediaModelsL10n || {};
   1053 
   1054 // Link any settings.
   1055 media.model.settings = l10n.settings || {};
   1056 delete l10n.settings;
   1057 
   1058 Attachment = media.model.Attachment = __webpack_require__( "0Ym0" );
   1059 Attachments = media.model.Attachments = __webpack_require__( "K0z/" );
   1060 
   1061 media.model.Query = __webpack_require__( "efdO" );
   1062 media.model.PostImage = __webpack_require__( "r1z7" );
   1063 media.model.Selection = __webpack_require__( "Io+g" );
   1064 
   1065 /**
   1066  * ========================================================================
   1067  * UTILITIES
   1068  * ========================================================================
   1069  */
   1070 
   1071 /**
   1072  * A basic equality comparator for Backbone models.
   1073  *
   1074  * Used to order models within a collection - @see wp.media.model.Attachments.comparator().
   1075  *
   1076  * @param {mixed}  a  The primary parameter to compare.
   1077  * @param {mixed}  b  The primary parameter to compare.
   1078  * @param {string} ac The fallback parameter to compare, a's cid.
   1079  * @param {string} bc The fallback parameter to compare, b's cid.
   1080  * @return {number} -1: a should come before b.
   1081  *                   0: a and b are of the same rank.
   1082  *                   1: b should come before a.
   1083  */
   1084 media.compare = function( a, b, ac, bc ) {
   1085 	if ( _.isEqual( a, b ) ) {
   1086 		return ac === bc ? 0 : (ac > bc ? -1 : 1);
   1087 	} else {
   1088 		return a > b ? -1 : 1;
   1089 	}
   1090 };
   1091 
   1092 _.extend( media, /** @lends wp.media */{
   1093 	/**
   1094 	 * media.template( id )
   1095 	 *
   1096 	 * Fetch a JavaScript template for an id, and return a templating function for it.
   1097 	 *
   1098 	 * See wp.template() in `wp-includes/js/wp-util.js`.
   1099 	 *
   1100 	 * @borrows wp.template as template
   1101 	 */
   1102 	template: wp.template,
   1103 
   1104 	/**
   1105 	 * media.post( [action], [data] )
   1106 	 *
   1107 	 * Sends a POST request to WordPress.
   1108 	 * See wp.ajax.post() in `wp-includes/js/wp-util.js`.
   1109 	 *
   1110 	 * @borrows wp.ajax.post as post
   1111 	 */
   1112 	post: wp.ajax.post,
   1113 
   1114 	/**
   1115 	 * media.ajax( [action], [options] )
   1116 	 *
   1117 	 * Sends an XHR request to WordPress.
   1118 	 * See wp.ajax.send() in `wp-includes/js/wp-util.js`.
   1119 	 *
   1120 	 * @borrows wp.ajax.send as ajax
   1121 	 */
   1122 	ajax: wp.ajax.send,
   1123 
   1124 	/**
   1125 	 * Scales a set of dimensions to fit within bounding dimensions.
   1126 	 *
   1127 	 * @param {Object} dimensions
   1128 	 * @return {Object}
   1129 	 */
   1130 	fit: function( dimensions ) {
   1131 		var width     = dimensions.width,
   1132 			height    = dimensions.height,
   1133 			maxWidth  = dimensions.maxWidth,
   1134 			maxHeight = dimensions.maxHeight,
   1135 			constraint;
   1136 
   1137 		/*
   1138 		 * Compare ratios between the two values to determine
   1139 		 * which max to constrain by. If a max value doesn't exist,
   1140 		 * then the opposite side is the constraint.
   1141 		 */
   1142 		if ( ! _.isUndefined( maxWidth ) && ! _.isUndefined( maxHeight ) ) {
   1143 			constraint = ( width / height > maxWidth / maxHeight ) ? 'width' : 'height';
   1144 		} else if ( _.isUndefined( maxHeight ) ) {
   1145 			constraint = 'width';
   1146 		} else if (  _.isUndefined( maxWidth ) && height > maxHeight ) {
   1147 			constraint = 'height';
   1148 		}
   1149 
   1150 		// If the value of the constrained side is larger than the max,
   1151 		// then scale the values. Otherwise return the originals; they fit.
   1152 		if ( 'width' === constraint && width > maxWidth ) {
   1153 			return {
   1154 				width : maxWidth,
   1155 				height: Math.round( maxWidth * height / width )
   1156 			};
   1157 		} else if ( 'height' === constraint && height > maxHeight ) {
   1158 			return {
   1159 				width : Math.round( maxHeight * width / height ),
   1160 				height: maxHeight
   1161 			};
   1162 		} else {
   1163 			return {
   1164 				width : width,
   1165 				height: height
   1166 			};
   1167 		}
   1168 	},
   1169 	/**
   1170 	 * Truncates a string by injecting an ellipsis into the middle.
   1171 	 * Useful for filenames.
   1172 	 *
   1173 	 * @param {string} string
   1174 	 * @param {number} [length=30]
   1175 	 * @param {string} [replacement=…]
   1176 	 * @return {string} The string, unless length is greater than string.length.
   1177 	 */
   1178 	truncate: function( string, length, replacement ) {
   1179 		length = length || 30;
   1180 		replacement = replacement || '…';
   1181 
   1182 		if ( string.length <= length ) {
   1183 			return string;
   1184 		}
   1185 
   1186 		return string.substr( 0, length / 2 ) + replacement + string.substr( -1 * length / 2 );
   1187 	}
   1188 });
   1189 
   1190 /**
   1191  * ========================================================================
   1192  * MODELS
   1193  * ========================================================================
   1194  */
   1195 /**
   1196  * wp.media.attachment
   1197  *
   1198  * @static
   1199  * @param {string} id A string used to identify a model.
   1200  * @return {wp.media.model.Attachment}
   1201  */
   1202 media.attachment = function( id ) {
   1203 	return Attachment.get( id );
   1204 };
   1205 
   1206 /**
   1207  * A collection of all attachments that have been fetched from the server.
   1208  *
   1209  * @static
   1210  * @member {wp.media.model.Attachments}
   1211  */
   1212 Attachments.all = new Attachments();
   1213 
   1214 /**
   1215  * wp.media.query
   1216  *
   1217  * Shorthand for creating a new Attachments Query.
   1218  *
   1219  * @param {Object} [props]
   1220  * @return {wp.media.model.Attachments}
   1221  */
   1222 media.query = function( props ) {
   1223 	return new Attachments( null, {
   1224 		props: _.extend( _.defaults( props || {}, { orderby: 'date' } ), { query: true } )
   1225 	});
   1226 };
   1227 
   1228 // Clean up. Prevents mobile browsers caching.
   1229 $(window).on('unload', function(){
   1230 	window.wp = null;
   1231 });
   1232 
   1233 
   1234 /***/ }),
   1235 
   1236 /***/ "efdO":
   1237 /***/ (function(module, exports) {
   1238 
   1239 var Attachments = wp.media.model.Attachments,
   1240 	Query;
   1241 
   1242 /**
   1243  * wp.media.model.Query
   1244  *
   1245  * A collection of attachments that match the supplied query arguments.
   1246  *
   1247  * Note: Do NOT change this.args after the query has been initialized.
   1248  *       Things will break.
   1249  *
   1250  * @memberOf wp.media.model
   1251  *
   1252  * @class
   1253  * @augments wp.media.model.Attachments
   1254  * @augments Backbone.Collection
   1255  *
   1256  * @param {array}  [models]                      Models to initialize with the collection.
   1257  * @param {object} [options]                     Options hash.
   1258  * @param {object} [options.args]                Attachments query arguments.
   1259  * @param {object} [options.args.posts_per_page]
   1260  */
   1261 Query = Attachments.extend(/** @lends wp.media.model.Query.prototype */{
   1262 	/**
   1263 	 * @param {Array}  [models=[]]  Array of initial models to populate the collection.
   1264 	 * @param {Object} [options={}]
   1265 	 */
   1266 	initialize: function( models, options ) {
   1267 		var allowed;
   1268 
   1269 		options = options || {};
   1270 		Attachments.prototype.initialize.apply( this, arguments );
   1271 
   1272 		this.args     = options.args;
   1273 		this._hasMore = true;
   1274 		this.created  = new Date();
   1275 
   1276 		this.filters.order = function( attachment ) {
   1277 			var orderby = this.props.get('orderby'),
   1278 				order = this.props.get('order');
   1279 
   1280 			if ( ! this.comparator ) {
   1281 				return true;
   1282 			}
   1283 
   1284 			/*
   1285 			 * We want any items that can be placed before the last
   1286 			 * item in the set. If we add any items after the last
   1287 			 * item, then we can't guarantee the set is complete.
   1288 			 */
   1289 			if ( this.length ) {
   1290 				return 1 !== this.comparator( attachment, this.last(), { ties: true });
   1291 
   1292 			/*
   1293 			 * Handle the case where there are no items yet and
   1294 			 * we're sorting for recent items. In that case, we want
   1295 			 * changes that occurred after we created the query.
   1296 			 */
   1297 			} else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {
   1298 				return attachment.get( orderby ) >= this.created;
   1299 
   1300 			// If we're sorting by menu order and we have no items,
   1301 			// accept any items that have the default menu order (0).
   1302 			} else if ( 'ASC' === order && 'menuOrder' === orderby ) {
   1303 				return attachment.get( orderby ) === 0;
   1304 			}
   1305 
   1306 			// Otherwise, we don't want any items yet.
   1307 			return false;
   1308 		};
   1309 
   1310 		/*
   1311 		 * Observe the central `wp.Uploader.queue` collection to watch for
   1312 		 * new matches for the query.
   1313 		 *
   1314 		 * Only observe when a limited number of query args are set. There
   1315 		 * are no filters for other properties, so observing will result in
   1316 		 * false positives in those queries.
   1317 		 */
   1318 		allowed = [ 's', 'order', 'orderby', 'posts_per_page', 'post_mime_type', 'post_parent', 'author' ];
   1319 		if ( wp.Uploader && _( this.args ).chain().keys().difference( allowed ).isEmpty().value() ) {
   1320 			this.observe( wp.Uploader.queue );
   1321 		}
   1322 	},
   1323 	/**
   1324 	 * Whether there are more attachments that haven't been sync'd from the server
   1325 	 * that match the collection's query.
   1326 	 *
   1327 	 * @return {boolean}
   1328 	 */
   1329 	hasMore: function() {
   1330 		return this._hasMore;
   1331 	},
   1332 	/**
   1333 	 * Fetch more attachments from the server for the collection.
   1334 	 *
   1335 	 * @param {Object} [options={}]
   1336 	 * @return {Promise}
   1337 	 */
   1338 	more: function( options ) {
   1339 		var query = this;
   1340 
   1341 		// If there is already a request pending, return early with the Deferred object.
   1342 		if ( this._more && 'pending' === this._more.state() ) {
   1343 			return this._more;
   1344 		}
   1345 
   1346 		if ( ! this.hasMore() ) {
   1347 			return jQuery.Deferred().resolveWith( this ).promise();
   1348 		}
   1349 
   1350 		options = options || {};
   1351 		options.remove = false;
   1352 
   1353 		return this._more = this.fetch( options ).done( function( response ) {
   1354 			if ( _.isEmpty( response ) || -1 === query.args.posts_per_page || response.length < query.args.posts_per_page ) {
   1355 				query._hasMore = false;
   1356 			}
   1357 		});
   1358 	},
   1359 	/**
   1360 	 * Overrides Backbone.Collection.sync
   1361 	 * Overrides wp.media.model.Attachments.sync
   1362 	 *
   1363 	 * @param {string} method
   1364 	 * @param {Backbone.Model} model
   1365 	 * @param {Object} [options={}]
   1366 	 * @return {Promise}
   1367 	 */
   1368 	sync: function( method, model, options ) {
   1369 		var args, fallback;
   1370 
   1371 		// Overload the read method so Attachment.fetch() functions correctly.
   1372 		if ( 'read' === method ) {
   1373 			options = options || {};
   1374 			options.context = this;
   1375 			options.data = _.extend( options.data || {}, {
   1376 				action:  'query-attachments',
   1377 				post_id: wp.media.model.settings.post.id
   1378 			});
   1379 
   1380 			// Clone the args so manipulation is non-destructive.
   1381 			args = _.clone( this.args );
   1382 
   1383 			// Determine which page to query.
   1384 			if ( -1 !== args.posts_per_page ) {
   1385 				args.paged = Math.round( this.length / args.posts_per_page ) + 1;
   1386 			}
   1387 
   1388 			options.data.query = args;
   1389 			return wp.media.ajax( options );
   1390 
   1391 		// Otherwise, fall back to `Backbone.sync()`.
   1392 		} else {
   1393 			/**
   1394 			 * Call wp.media.model.Attachments.sync or Backbone.sync
   1395 			 */
   1396 			fallback = Attachments.prototype.sync ? Attachments.prototype : Backbone;
   1397 			return fallback.sync.apply( this, arguments );
   1398 		}
   1399 	}
   1400 }, /** @lends wp.media.model.Query */{
   1401 	/**
   1402 	 * @readonly
   1403 	 */
   1404 	defaultProps: {
   1405 		orderby: 'date',
   1406 		order:   'DESC'
   1407 	},
   1408 	/**
   1409 	 * @readonly
   1410 	 */
   1411 	defaultArgs: {
   1412 		posts_per_page: 80
   1413 	},
   1414 	/**
   1415 	 * @readonly
   1416 	 */
   1417 	orderby: {
   1418 		allowed:  [ 'name', 'author', 'date', 'title', 'modified', 'uploadedTo', 'id', 'post__in', 'menuOrder' ],
   1419 		/**
   1420 		 * A map of JavaScript orderby values to their WP_Query equivalents.
   1421 		 * @type {Object}
   1422 		 */
   1423 		valuemap: {
   1424 			'id':         'ID',
   1425 			'uploadedTo': 'parent',
   1426 			'menuOrder':  'menu_order ID'
   1427 		}
   1428 	},
   1429 	/**
   1430 	 * A map of JavaScript query properties to their WP_Query equivalents.
   1431 	 *
   1432 	 * @readonly
   1433 	 */
   1434 	propmap: {
   1435 		'search':		's',
   1436 		'type':			'post_mime_type',
   1437 		'perPage':		'posts_per_page',
   1438 		'menuOrder':	'menu_order',
   1439 		'uploadedTo':	'post_parent',
   1440 		'status':		'post_status',
   1441 		'include':		'post__in',
   1442 		'exclude':		'post__not_in',
   1443 		'author':		'author'
   1444 	},
   1445 	/**
   1446 	 * Creates and returns an Attachments Query collection given the properties.
   1447 	 *
   1448 	 * Caches query objects and reuses where possible.
   1449 	 *
   1450 	 * @static
   1451 	 * @method
   1452 	 *
   1453 	 * @param {object} [props]
   1454 	 * @param {Object} [props.order]
   1455 	 * @param {Object} [props.orderby]
   1456 	 * @param {Object} [props.include]
   1457 	 * @param {Object} [props.exclude]
   1458 	 * @param {Object} [props.s]
   1459 	 * @param {Object} [props.post_mime_type]
   1460 	 * @param {Object} [props.posts_per_page]
   1461 	 * @param {Object} [props.menu_order]
   1462 	 * @param {Object} [props.post_parent]
   1463 	 * @param {Object} [props.post_status]
   1464 	 * @param {Object} [props.author]
   1465 	 * @param {Object} [options]
   1466 	 *
   1467 	 * @return {wp.media.model.Query} A new Attachments Query collection.
   1468 	 */
   1469 	get: (function(){
   1470 		/**
   1471 		 * @static
   1472 		 * @type Array
   1473 		 */
   1474 		var queries = [];
   1475 
   1476 		/**
   1477 		 * @return {Query}
   1478 		 */
   1479 		return function( props, options ) {
   1480 			var args     = {},
   1481 				orderby  = Query.orderby,
   1482 				defaults = Query.defaultProps,
   1483 				query;
   1484 
   1485 			// Remove the `query` property. This isn't linked to a query,
   1486 			// this *is* the query.
   1487 			delete props.query;
   1488 
   1489 			// Fill default args.
   1490 			_.defaults( props, defaults );
   1491 
   1492 			// Normalize the order.
   1493 			props.order = props.order.toUpperCase();
   1494 			if ( 'DESC' !== props.order && 'ASC' !== props.order ) {
   1495 				props.order = defaults.order.toUpperCase();
   1496 			}
   1497 
   1498 			// Ensure we have a valid orderby value.
   1499 			if ( ! _.contains( orderby.allowed, props.orderby ) ) {
   1500 				props.orderby = defaults.orderby;
   1501 			}
   1502 
   1503 			_.each( [ 'include', 'exclude' ], function( prop ) {
   1504 				if ( props[ prop ] && ! _.isArray( props[ prop ] ) ) {
   1505 					props[ prop ] = [ props[ prop ] ];
   1506 				}
   1507 			} );
   1508 
   1509 			// Generate the query `args` object.
   1510 			// Correct any differing property names.
   1511 			_.each( props, function( value, prop ) {
   1512 				if ( _.isNull( value ) ) {
   1513 					return;
   1514 				}
   1515 
   1516 				args[ Query.propmap[ prop ] || prop ] = value;
   1517 			});
   1518 
   1519 			// Fill any other default query args.
   1520 			_.defaults( args, Query.defaultArgs );
   1521 
   1522 			// `props.orderby` does not always map directly to `args.orderby`.
   1523 			// Substitute exceptions specified in orderby.keymap.
   1524 			args.orderby = orderby.valuemap[ props.orderby ] || props.orderby;
   1525 
   1526 			queries = [];
   1527 
   1528 			// Otherwise, create a new query and add it to the cache.
   1529 			if ( ! query ) {
   1530 				query = new Query( [], _.extend( options || {}, {
   1531 					props: props,
   1532 					args:  args
   1533 				} ) );
   1534 				queries.push( query );
   1535 			}
   1536 
   1537 			return query;
   1538 		};
   1539 	}())
   1540 });
   1541 
   1542 module.exports = Query;
   1543 
   1544 
   1545 /***/ }),
   1546 
   1547 /***/ "r1z7":
   1548 /***/ (function(module, exports) {
   1549 
   1550 /**
   1551  * wp.media.model.PostImage
   1552  *
   1553  * An instance of an image that's been embedded into a post.
   1554  *
   1555  * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.
   1556  *
   1557  * @memberOf wp.media.model
   1558  *
   1559  * @class
   1560  * @augments Backbone.Model
   1561  *
   1562  * @param {int} [attributes]               Initial model attributes.
   1563  * @param {int} [attributes.attachment_id] ID of the attachment.
   1564  **/
   1565 var PostImage = Backbone.Model.extend(/** @lends wp.media.model.PostImage.prototype */{
   1566 
   1567 	initialize: function( attributes ) {
   1568 		var Attachment = wp.media.model.Attachment;
   1569 		this.attachment = false;
   1570 
   1571 		if ( attributes.attachment_id ) {
   1572 			this.attachment = Attachment.get( attributes.attachment_id );
   1573 			if ( this.attachment.get( 'url' ) ) {
   1574 				this.dfd = jQuery.Deferred();
   1575 				this.dfd.resolve();
   1576 			} else {
   1577 				this.dfd = this.attachment.fetch();
   1578 			}
   1579 			this.bindAttachmentListeners();
   1580 		}
   1581 
   1582 		// Keep URL in sync with changes to the type of link.
   1583 		this.on( 'change:link', this.updateLinkUrl, this );
   1584 		this.on( 'change:size', this.updateSize, this );
   1585 
   1586 		this.setLinkTypeFromUrl();
   1587 		this.setAspectRatio();
   1588 
   1589 		this.set( 'originalUrl', attributes.url );
   1590 	},
   1591 
   1592 	bindAttachmentListeners: function() {
   1593 		this.listenTo( this.attachment, 'sync', this.setLinkTypeFromUrl );
   1594 		this.listenTo( this.attachment, 'sync', this.setAspectRatio );
   1595 		this.listenTo( this.attachment, 'change', this.updateSize );
   1596 	},
   1597 
   1598 	changeAttachment: function( attachment, props ) {
   1599 		this.stopListening( this.attachment );
   1600 		this.attachment = attachment;
   1601 		this.bindAttachmentListeners();
   1602 
   1603 		this.set( 'attachment_id', this.attachment.get( 'id' ) );
   1604 		this.set( 'caption', this.attachment.get( 'caption' ) );
   1605 		this.set( 'alt', this.attachment.get( 'alt' ) );
   1606 		this.set( 'size', props.get( 'size' ) );
   1607 		this.set( 'align', props.get( 'align' ) );
   1608 		this.set( 'link', props.get( 'link' ) );
   1609 		this.updateLinkUrl();
   1610 		this.updateSize();
   1611 	},
   1612 
   1613 	setLinkTypeFromUrl: function() {
   1614 		var linkUrl = this.get( 'linkUrl' ),
   1615 			type;
   1616 
   1617 		if ( ! linkUrl ) {
   1618 			this.set( 'link', 'none' );
   1619 			return;
   1620 		}
   1621 
   1622 		// Default to custom if there is a linkUrl.
   1623 		type = 'custom';
   1624 
   1625 		if ( this.attachment ) {
   1626 			if ( this.attachment.get( 'url' ) === linkUrl ) {
   1627 				type = 'file';
   1628 			} else if ( this.attachment.get( 'link' ) === linkUrl ) {
   1629 				type = 'post';
   1630 			}
   1631 		} else {
   1632 			if ( this.get( 'url' ) === linkUrl ) {
   1633 				type = 'file';
   1634 			}
   1635 		}
   1636 
   1637 		this.set( 'link', type );
   1638 	},
   1639 
   1640 	updateLinkUrl: function() {
   1641 		var link = this.get( 'link' ),
   1642 			url;
   1643 
   1644 		switch( link ) {
   1645 			case 'file':
   1646 				if ( this.attachment ) {
   1647 					url = this.attachment.get( 'url' );
   1648 				} else {
   1649 					url = this.get( 'url' );
   1650 				}
   1651 				this.set( 'linkUrl', url );
   1652 				break;
   1653 			case 'post':
   1654 				this.set( 'linkUrl', this.attachment.get( 'link' ) );
   1655 				break;
   1656 			case 'none':
   1657 				this.set( 'linkUrl', '' );
   1658 				break;
   1659 		}
   1660 	},
   1661 
   1662 	updateSize: function() {
   1663 		var size;
   1664 
   1665 		if ( ! this.attachment ) {
   1666 			return;
   1667 		}
   1668 
   1669 		if ( this.get( 'size' ) === 'custom' ) {
   1670 			this.set( 'width', this.get( 'customWidth' ) );
   1671 			this.set( 'height', this.get( 'customHeight' ) );
   1672 			this.set( 'url', this.get( 'originalUrl' ) );
   1673 			return;
   1674 		}
   1675 
   1676 		size = this.attachment.get( 'sizes' )[ this.get( 'size' ) ];
   1677 
   1678 		if ( ! size ) {
   1679 			return;
   1680 		}
   1681 
   1682 		this.set( 'url', size.url );
   1683 		this.set( 'width', size.width );
   1684 		this.set( 'height', size.height );
   1685 	},
   1686 
   1687 	setAspectRatio: function() {
   1688 		var full;
   1689 
   1690 		if ( this.attachment && this.attachment.get( 'sizes' ) ) {
   1691 			full = this.attachment.get( 'sizes' ).full;
   1692 
   1693 			if ( full ) {
   1694 				this.set( 'aspectRatio', full.width / full.height );
   1695 				return;
   1696 			}
   1697 		}
   1698 
   1699 		this.set( 'aspectRatio', this.get( 'customWidth' ) / this.get( 'customHeight' ) );
   1700 	}
   1701 });
   1702 
   1703 module.exports = PostImage;
   1704 
   1705 
   1706 /***/ })
   1707 
   1708 /******/ });