[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

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


Generated: Thu Nov 21 01:00:03 2024 Cross-referenced by PHPXref 0.7.1