[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

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


Generated: Thu Jul 29 01:00:05 2021 Cross-referenced by PHPXref 0.7.1