[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/ -> media-models.js (source)

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


Generated : Sun Mar 9 08:20:01 2025 Cross-referenced by PHPXref