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