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