Вход Регистрация
Файл: wordpress/wp-includes/js/media-models.js
Строк: 1595
<?php
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*globals wp, _, jQuery */

var $ = jQuery,
    
AttachmentAttachmentsl10nmedia;

window.wp window.wp || {};

/**
 * Create and return a media frame.
 *
 * Handles the default media experience.
 *
 * @param  {object} attributes The properties passed to the main media controller.
 * @return {wp.media.view.MediaFrame} A media workflow.
 */
media wp.media = function( attributes ) {
    var 
MediaFrame media.view.MediaFrame,
        
frame;

    if ( ! 
MediaFrame ) {
        return;
    }

    
attributes _.defaultsattributes || {}, {
        
frame'select'
    
});

    if ( 
'select' === attributes.frame && MediaFrame.Select ) {
        
frame = new MediaFrame.Selectattributes );
    } else if ( 
'post' === attributes.frame && MediaFrame.Post ) {
        
frame = new MediaFrame.Postattributes );
    } else if ( 
'manage' === attributes.frame && MediaFrame.Manage ) {
        
frame = new MediaFrame.Manageattributes );
    } else if ( 
'image' === attributes.frame && MediaFrame.ImageDetails ) {
        
frame = new MediaFrame.ImageDetailsattributes );
    } else if ( 
'audio' === attributes.frame && MediaFrame.AudioDetails ) {
        
frame = new MediaFrame.AudioDetailsattributes );
    } else if ( 
'video' === attributes.frame && MediaFrame.VideoDetails ) {
        
frame = new MediaFrame.VideoDetailsattributes );
    } else if ( 
'edit-attachments' === attributes.frame && MediaFrame.EditAttachments ) {
        
frame = new MediaFrame.EditAttachmentsattributes );
    }

    
delete attributes.frame;

    
media.frame frame;

    return 
frame;
};

_.extendmedia, { model: {}, view: {}, controller: {}, frames: {} });

// Link any localized strings.
l10n media.model.l10n window._wpMediaModelsL10n || {};

// Link any settings.
media.model.settings l10n.settings || {};
delete l10n.settings;

Attachment media.model.Attachment = require( './models/attachment.js' );
Attachments media.model.Attachments = require( './models/attachments.js' );

media.model.Query = require( './models/query.js' );
media.model.PostImage = require( './models/post-image.js' );
media.model.Selection = require( './models/selection.js' );

/**
 * ========================================================================
 * UTILITIES
 * ========================================================================
 */

/**
 * A basic equality comparator for Backbone models.
 *
 * Used to order models within a collection - @see wp.media.model.Attachments.comparator().
 *
 * @param  {mixed}  a  The primary parameter to compare.
 * @param  {mixed}  b  The primary parameter to compare.
 * @param  {string} ac The fallback parameter to compare, a's cid.
 * @param  {string} bc The fallback parameter to compare, b's cid.
 * @return {number}    -1: a should come before b.
 *                      0: a and b are of the same rank.
 *                      1: b should come before a.
 */
media.compare = function( abacbc ) {
    if ( 
_.isEquala) ) {
        return 
ac === bc : (ac bc ? -1);
    } else {
        return 
? -1;
    }
};

_.extendmedia, {
    
/**
     * media.template( id )
     *
     * Fetch a JavaScript template for an id, and return a templating function for it.
     *
     * See wp.template() in `wp-includes/js/wp-util.js`.
     *
     * @borrows wp.template as template
     */
    
templatewp.template,

    
/**
     * media.post( [action], [data] )
     *
     * Sends a POST request to WordPress.
     * See wp.ajax.post() in `wp-includes/js/wp-util.js`.
     *
     * @borrows wp.ajax.post as post
     */
    
postwp.ajax.post,

    
/**
     * media.ajax( [action], [options] )
     *
     * Sends an XHR request to WordPress.
     * See wp.ajax.send() in `wp-includes/js/wp-util.js`.
     *
     * @borrows wp.ajax.send as ajax
     */
    
ajaxwp.ajax.send,

    
/**
     * Scales a set of dimensions to fit within bounding dimensions.
     *
     * @param {Object} dimensions
     * @returns {Object}
     */
    
fit: function( dimensions ) {
        var 
width     dimensions.width,
            
height    dimensions.height,
            
maxWidth  dimensions.maxWidth,
            
maxHeight dimensions.maxHeight,
            
constraint;

        
// Compare ratios between the two values to determine which
        // max to constrain by. If a max value doesn't exist, then the
        // opposite side is the constraint.
        
if ( ! _.isUndefinedmaxWidth ) && ! _.isUndefinedmaxHeight ) ) {
            
constraint = ( width height maxWidth maxHeight ) ? 'width' 'height';
        } else if ( 
_.isUndefinedmaxHeight ) ) {
            
constraint 'width';
        } else if (  
_.isUndefinedmaxWidth ) && height maxHeight ) {
            
constraint 'height';
        }

        
// If the value of the constrained side is larger than the max,
        // then scale the values. Otherwise return the originals; they fit.
        
if ( 'width' === constraint && width maxWidth ) {
            return {
                
width maxWidth,
                
heightMath.roundmaxWidth height width )
            };
        } else if ( 
'height' === constraint && height maxHeight ) {
            return {
                
width Math.roundmaxHeight width height ),
                
heightmaxHeight
            
};
        } else {
            return {
                
width width,
                
heightheight
            
};
        }
    },
    
/**
     * Truncates a string by injecting an ellipsis into the middle.
     * Useful for filenames.
     *
     * @param {String} string
     * @param {Number} [length=30]
     * @param {String} [replacement=&hellip;]
     * @returns {String} The string, unless length is greater than string.length.
     */
    
truncate: function( stringlengthreplacement ) {
        
length length || 30;
        
replacement replacement || '&hellip;';

        if ( 
string.length <= length ) {
            return 
string;
        }

        return 
string.substr0length ) + replacement string.substr( -length );
    }
});

/**
 * ========================================================================
 * MODELS
 * ========================================================================
 */
/**
 * wp.media.attachment
 *
 * @static
 * @param {String} id A string used to identify a model.
 * @returns {wp.media.model.Attachment}
 */
media.attachment = function( id ) {
    return 
Attachment.getid );
};

/**
 * A collection of all attachments that have been fetched from the server.
 *
 * @static
 * @member {wp.media.model.Attachments}
 */
Attachments.all = new Attachments();

/**
 * wp.media.query
 *
 * Shorthand for creating a new Attachments Query.
 *
 * @param {object} [props]
 * @returns {wp.media.model.Attachments}
 */
media.query = function( props ) {
    return new 
Attachmentsnull, {
        
props_.extend_.defaultsprops || {}, { orderby'date' } ), { querytrue } )
    });
};

// Clean up. Prevents mobile browsers caching
$(window).on('unload', function(){
    
window.wp null;
});

},{
"./models/attachment.js":2,"./models/attachments.js":3,"./models/post-image.js":4,"./models/query.js":5,"./models/selection.js":6}],2:[function(require,module,exports){
/*globals wp, _, Backbone */

/**
 * wp.media.model.Attachment
 *
 * @class
 * @augments Backbone.Model
 */
var $ = Backbone.$,
    
Attachment;

Attachment Backbone.Model.extend({
    
/**
     * Triggered when attachment details change
     * Overrides Backbone.Model.sync
     *
     * @param {string} method
     * @param {wp.media.model.Attachment} model
     * @param {Object} [options={}]
     *
     * @returns {Promise}
     */
    
sync: function( methodmodeloptions ) {
        
// If the attachment does not yet have an `id`, return an instantly
        // rejected promise. Otherwise, all of our requests will fail.
        
if ( _.isUndefinedthis.id ) ) {
            return $.
Deferred().rejectWiththis ).promise();
        }

        
// Overload the `read` request so Attachment.fetch() functions correctly.
        
if ( 'read' === method ) {
            
options options || {};
            
options.context this;
            
options.data _.extendoptions.data || {}, {
                
action'get-attachment',
                
idthis.id
            
});
            return 
wp.media.ajaxoptions );

        
// Overload the `update` request so properties can be saved.
        
} else if ( 'update' === method ) {
            
// If we do not have the necessary nonce, fail immeditately.
            
if ( ! this.get('nonces') || ! this.get('nonces').update ) {
                return $.
Deferred().rejectWiththis ).promise();
            }

            
options options || {};
            
options.context this;

            
// Set the action and ID.
            
options.data _.extendoptions.data || {}, {
                
action:  'save-attachment',
                
id:      this.id,
                
nonce:   this.get('nonces').update,
                
post_idwp.media.model.settings.post.id
            
});

            
// Record the values of the changed attributes.
            
if ( model.hasChanged() ) {
                
options.data.changes = {};

                
_.eachmodel.changed, function( valuekey ) {
                    
options.data.changeskey ] = this.getkey );
                }, 
this );
            }

            return 
wp.media.ajaxoptions );

        
// Overload the `delete` request so attachments can be removed.
        // This will permanently delete an attachment.
        
} else if ( 'delete' === method ) {
            
options options || {};

            if ( ! 
options.wait ) {
                
this.destroyed true;
            }

            
options.context this;
            
options.data _.extendoptions.data || {}, {
                
action:   'delete-post',
                
id:       this.id,
                
_wpnoncethis.get('nonces')['delete']
            });

            return 
wp.media.ajaxoptions ).done( function() {
                
this.destroyed true;
            }).
fail( function() {
                
this.destroyed false;
            });

        
// Otherwise, fall back to `Backbone.sync()`.
        
} else {
            
/**
             * Call `sync` directly on Backbone.Model
             */
            
return Backbone.Model.prototype.sync.applythisarguments );
        }
    },
    
/**
     * Convert date strings into Date objects.
     *
     * @param {Object} resp The raw response object, typically returned by fetch()
     * @returns {Object} The modified response object, which is the attributes hash
     *    to be set on the model.
     */
    
parse: function( resp ) {
        if ( ! 
resp ) {
            return 
resp;
        }

        
resp.date = new Dateresp.date );
        
resp.modified = new Dateresp.modified );
        return 
resp;
    },
    
/**
     * @param {Object} data The properties to be saved.
     * @param {Object} options Sync options. e.g. patch, wait, success, error.
     *
     * @this Backbone.Model
     *
     * @returns {Promise}
     */
    
saveCompat: function( dataoptions ) {
        var 
model this;

        
// If we do not have the necessary nonce, fail immeditately.
        
if ( ! this.get('nonces') || ! this.get('nonces').update ) {
            return $.
Deferred().rejectWiththis ).promise();
        }

        return 
wp.media.post'save-attachment-compat'_.defaults({
            
id:      this.id,
            
nonce:   this.get('nonces').update,
            
post_idwp.media.model.settings.post.id
        
}, data ) ).done( function( respstatusxhr ) {
            
model.setmodel.parserespxhr ), options );
        });
    }
}, {
    
/**
     * Create a new model on the static 'all' attachments collection and return it.
     *
     * @static
     * @param {Object} attrs
     * @returns {wp.media.model.Attachment}
     */
    
create: function( attrs ) {
        var 
Attachments wp.media.model.Attachments;
        return 
Attachments.all.pushattrs );
    },
    
/**
     * Create a new model on the static 'all' attachments collection and return it.
     *
     * If this function has already been called for the id,
     * it returns the specified attachment.
     *
     * @static
     * @param {string} id A string used to identify a model.
     * @param {Backbone.Model|undefined} attachment
     * @returns {wp.media.model.Attachment}
     */
    
get_.memoize( function( idattachment ) {
        var 
Attachments wp.media.model.Attachments;
        return 
Attachments.all.pushattachment || { idid } );
    })
});

module.exports Attachment;

},{}],
3:[function(require,module,exports){
/*globals wp, _, Backbone */

/**
 * wp.media.model.Attachments
 *
 * A collection of attachments.
 *
 * This collection has no persistence with the server without supplying
 * 'options.props.query = true', which will mirror the collection
 * to an Attachments Query collection - @see wp.media.model.Attachments.mirror().
 *
 * @class
 * @augments Backbone.Collection
 *
 * @param {array}  [models]                Models to initialize with the collection.
 * @param {object} [options]               Options hash for the collection.
 * @param {string} [options.props]         Options hash for the initial query properties.
 * @param {string} [options.props.order]   Initial order (ASC or DESC) for the collection.
 * @param {string} [options.props.orderby] Initial attribute key to order the collection by.
 * @param {string} [options.props.query]   Whether the collection is linked to an attachments query.
 * @param {string} [options.observe]
 * @param {string} [options.filters]
 *
 */
var Attachments Backbone.Collection.extend({
    
/**
     * @type {wp.media.model.Attachment}
     */
    
modelwp.media.model.Attachment,
    
/**
     * @param {Array} [models=[]] Array of models used to populate the collection.
     * @param {Object} [options={}]
     */
    
initialize: function( modelsoptions ) {
        
options options || {};

        
this.props   = new Backbone.Model();
        
this.filters options.filters || {};

        
// Bind default `change` events to the `props` model.
        
this.props.on'change'this._changeFilteredPropsthis );

        
this.props.on'change:order',   this._changeOrder,   this );
        
this.props.on'change:orderby'this._changeOrderbythis );
        
this.props.on'change:query',   this._changeQuery,   this );

        
this.props.set_.defaultsoptions.props || {} ) );

        if ( 
options.observe ) {
            
this.observeoptions.observe );
        }
    },
    
/**
     * Sort the collection when the order attribute changes.
     *
     * @access private
     */
    
_changeOrder: function() {
        if ( 
this.comparator ) {
            
this.sort();
        }
    },
    
/**
     * Set the default comparator only when the `orderby` property is set.
     *
     * @access private
     *
     * @param {Backbone.Model} model
     * @param {string} orderby
     */
    
_changeOrderby: function( modelorderby ) {
        
// If a different comparator is defined, bail.
        
if ( this.comparator && this.comparator !== Attachments.comparator ) {
            return;
        }

        if ( 
orderby && 'post__in' !== orderby ) {
            
this.comparator Attachments.comparator;
        } else {
            
delete this.comparator;
        }
    },
    
/**
     * If the `query` property is set to true, query the server using
     * the `props` values, and sync the results to this collection.
     *
     * @access private
     *
     * @param {Backbone.Model} model
     * @param {Boolean} query
     */
    
_changeQuery: function( modelquery ) {
        if ( 
query ) {
            
this.props.on'change'this._requerythis );
            
this._requery();
        } else {
            
this.props.off'change'this._requerythis );
        }
    },
    
/**
     * @access private
     *
     * @param {Backbone.Model} model
     */
    
_changeFilteredProps: function( model ) {
        
// If this is a query, updating the collection will be handled by
        // `this._requery()`.
        
if ( this.props.get('query') ) {
            return;
        }

        var 
changed _.chainmodel.changed ).map( function( tprop ) {
            var 
filter Attachments.filtersprop ],
                
term model.getprop );

            if ( ! 
filter ) {
                return;
            }

            if ( 
term && ! this.filtersprop ] ) {
                
this.filtersprop ] = filter;
            } else if ( ! 
term && this.filtersprop ] === filter ) {
                
delete this.filtersprop ];
            } else {
                return;
            }

            
// Record the change.
            
return true;
        }, 
this ).any().value();

        if ( ! 
changed ) {
            return;
        }

        
// If no `Attachments` model is provided to source the searches
        // from, then automatically generate a source from the existing
        // models.
        
if ( ! this._source ) {
            
this._source = new Attachmentsthis.models );
        }

        
this.resetthis._source.filterthis.validatorthis ) );
    },

    
validateDestroyedfalse,
    
/**
     * Checks whether an attachment is valid.
     *
     * @param {wp.media.model.Attachment} attachment
     * @returns {Boolean}
     */
    
validator: function( attachment ) {
        if ( ! 
this.validateDestroyed && attachment.destroyed ) {
            return 
false;
        }
        return 
_.allthis.filters, function( filter ) {
            return !! 
filter.callthisattachment );
        }, 
this );
    },
    
/**
     * Add or remove an attachment to the collection depending on its validity.
     *
     * @param {wp.media.model.Attachment} attachment
     * @param {Object} options
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
validate: function( attachmentoptions ) {
        var 
valid this.validatorattachment ),
            
hasAttachment = !! this.getattachment.cid );

        if ( ! 
valid && hasAttachment ) {
            
this.removeattachmentoptions );
        } else if ( 
valid && ! hasAttachment ) {
            
this.addattachmentoptions );
        }

        return 
this;
    },

    
/**
     * Add or remove all attachments from another collection depending on each one's validity.
     *
     * @param {wp.media.model.Attachments} attachments
     * @param {object} [options={}]
     *
     * @fires wp.media.model.Attachments#reset
     *
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
validateAll: function( attachmentsoptions ) {
        
options options || {};

        
_.eachattachments.models, function( attachment ) {
            
this.validateattachment, { silenttrue });
        }, 
this );

        if ( ! 
options.silent ) {
            
this.trigger'reset'thisoptions );
        }
        return 
this;
    },
    
/**
     * Start observing another attachments collection change events
     * and replicate them on this collection.
     *
     * @param {wp.media.model.Attachments} The attachments collection to observe.
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining.
     */
    
observe: function( attachments ) {
        
this.observers this.observers || [];
        
this.observers.pushattachments );

        
attachments.on'add change remove'this._validateHandlerthis );
        
attachments.on'reset'this._validateAllHandlerthis );
        
this.validateAllattachments );
        return 
this;
    },
    
/**
     * Stop replicating collection change events from another attachments collection.
     *
     * @param {wp.media.model.Attachments} The attachments collection to stop observing.
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
unobserve: function( attachments ) {
        if ( 
attachments ) {
            
attachments.offnullnullthis );
            
this.observers _.withoutthis.observersattachments );

        } else {
            
_.eachthis.observers, function( attachments ) {
                
attachments.offnullnullthis );
            }, 
this );
            
delete this.observers;
        }

        return 
this;
    },
    
/**
     * @access private
     *
     * @param {wp.media.model.Attachments} attachment
     * @param {wp.media.model.Attachments} attachments
     * @param {Object} options
     *
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
_validateHandler: function( attachmentattachmentsoptions ) {
        
// If we're not mirroring this `attachments` collection,
        // only retain the `silent` option.
        
options attachments === this.mirroring options : {
            
silentoptions && options.silent
        
};

        return 
this.validateattachmentoptions );
    },
    
/**
     * @access private
     *
     * @param {wp.media.model.Attachments} attachments
     * @param {Object} options
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
_validateAllHandler: function( attachmentsoptions ) {
        return 
this.validateAllattachmentsoptions );
    },
    
/**
     * Start mirroring another attachments collection, clearing out any models already
     * in the collection.
     *
     * @param {wp.media.model.Attachments} The attachments collection to mirror.
     * @returns {wp.media.model.Attachments} Returns itself to allow chaining
     */
    
mirror: function( attachments ) {
        if ( 
this.mirroring && this.mirroring === attachments ) {
            return 
this;
        }

        
this.unmirror();
        
this.mirroring attachments;

        
// Clear the collection silently. A `reset` event will be fired
        // when `observe()` calls `validateAll()`.
        
this.reset( [], { silenttrue } );
        
this.observeattachments );

        return 
this;
    },
    
/**
     * Stop mirroring another attachments collection.
     */
    
unmirror: function() {
        if ( ! 
this.mirroring ) {
            return;
        }

        
this.unobservethis.mirroring );
        
delete this.mirroring;
    },
    
/**
     * Retrive more attachments from the server for the collection.
     *
     * Only works if the collection is mirroring a Query Attachments collection,
     * and forwards to its `more` method. This collection class doesn't have
     * server persistence by itself.
     *
     * @param {object} options
     * @returns {Promise}
     */
    
more: function( options ) {
        var 
deferred jQuery.Deferred(),
            
mirroring this.mirroring,
            
attachments this;

        if ( ! 
mirroring || ! mirroring.more ) {
            return 
deferred.resolveWiththis ).promise();
        }
        
// If we're mirroring another collection, forward `more` to
        // the mirrored collection. Account for a race condition by
        // checking if we're still mirroring that collection when
        // the request resolves.
        
mirroring.moreoptions ).done( function() {
            if ( 
this === attachments.mirroring ) {
                
deferred.resolveWiththis );
            }
        });

        return 
deferred.promise();
    },
    
/**
     * Whether there are more attachments that haven't been sync'd from the server
     * that match the collection's query.
     *
     * Only works if the collection is mirroring a Query Attachments collection,
     * and forwards to its `hasMore` method. This collection class doesn't have
     * server persistence by itself.
     *
     * @returns {boolean}
     */
    
hasMore: function() {
        return 
this.mirroring this.mirroring.hasMore() : false;
    },
    
/**
     * A custom AJAX-response parser.
     *
     * See trac ticket #24753
     *
     * @param {Object|Array} resp The raw response Object/Array.
     * @param {Object} xhr
     * @returns {Array} The array of model attributes to be added to the collection
     */
    
parse: function( respxhr ) {
        if ( ! 
_.isArrayresp ) ) {
            
resp = [resp];
        }

        return 
_.mapresp, function( attrs ) {
            var 
idattachmentnewAttributes;

            if ( 
attrs instanceof Backbone.Model ) {
                
id attrs.get'id' );
                
attrs attrs.attributes;
            } else {
                
id attrs.id;
            }

            
attachment wp.media.model.Attachment.getid );
            
newAttributes attachment.parseattrsxhr );

            if ( ! 
_.isEqualattachment.attributesnewAttributes ) ) {
                
attachment.setnewAttributes );
            }

            return 
attachment;
        });
    },
    
/**
     * If the collection is a query, create and mirror an Attachments Query collection.
     *
     * @access private
     */
    
_requery: function( refresh ) {
        var 
props;
        if ( 
this.props.get('query') ) {
            
props this.props.toJSON();
            
props.cache = ( true !== refresh );
            
this.mirrorwp.media.model.Query.getprops ) );
        }
    },
    
/**
     * If this collection is sorted by `menuOrder`, recalculates and saves
     * the menu order to the database.
     *
     * @returns {undefined|Promise}
     */
    
saveMenuOrder: function() {
        if ( 
'menuOrder' !== this.props.get('orderby') ) {
            return;
        }

        
// Removes any uploading attachments, updates each attachment's
        // menu order, and returns an object with an { id: menuOrder }
        // mapping to pass to the request.
        
var attachments this.chain().filter( function( attachment ) {
            return ! 
_.isUndefinedattachment.id );
        }).
map( function( attachmentindex ) {
            
// Indices start at 1.
            
index index 1;
            
attachment.set'menuOrder'index );
            return [ 
attachment.idindex ];
        }).
object().value();

        if ( 
_.isEmptyattachments ) ) {
            return;
        }

        return 
wp.media.post'save-attachment-order', {
            
nonce:       wp.media.model.settings.post.nonce,
            
post_id:     wp.media.model.settings.post.id,
            
attachmentsattachments
        
});
    }
}, {
    
/**
     * A function to compare two attachment models in an attachments collection.
     *
     * Used as the default comparator for instances of wp.media.model.Attachments
     * and its subclasses. @see wp.media.model.Attachments._changeOrderby().
     *
     * @static
     *
     * @param {Backbone.Model} a
     * @param {Backbone.Model} b
     * @param {Object} options
     * @returns {Number} -1 if the first model should come before the second,
     *    0 if they are of the same rank and
     *    1 if the first model should come after.
     */
    
comparator: function( aboptions ) {
        var 
key   this.props.get('orderby'),
            
order this.props.get('order') || 'DESC',
            
ac    a.cid,
            
bc    b.cid;

        
a.getkey );
        
b.getkey );

        if ( 
'date' === key || 'modified' === key ) {
            
|| new Date();
            
|| new Date();
        }

        
// If `options.ties` is set, don't enforce the `cid` tiebreaker.
        
if ( options && options.ties ) {
            
ac bc null;
        }

        return ( 
'DESC' === order ) ? wp.media.compareabacbc ) : wp.media.comparebabcac );
    },
    
/**
     * @namespace
     */
    
filters: {
        
/**
         * @static
         * Note that this client-side searching is *not* equivalent
         * to our server-side searching.
         *
         * @param {wp.media.model.Attachment} attachment
         *
         * @this wp.media.model.Attachments
         *
         * @returns {Boolean}
         */
        
search: function( attachment ) {
            if ( ! 
this.props.get('search') ) {
                return 
true;
            }

            return 
_.any(['title','filename','description','caption','name'], function( key ) {
                var 
value attachment.getkey );
                return 
value && -!== value.searchthis.props.get('search') );
            }, 
this );
        },
        
/**
         * @static
         * @param {wp.media.model.Attachment} attachment
         *
         * @this wp.media.model.Attachments
         *
         * @returns {Boolean}
         */
        
type: function( attachment ) {
            var 
type this.props.get('type');
            return ! 
type || -!== type.indexOfattachment.get('type') );
        },
        
/**
         * @static
         * @param {wp.media.model.Attachment} attachment
         *
         * @this wp.media.model.Attachments
         *
         * @returns {Boolean}
         */
        
uploadedTo: function( attachment ) {
            var 
uploadedTo this.props.get('uploadedTo');
            if ( 
_.isUndefineduploadedTo ) ) {
                return 
true;
            }

            return 
uploadedTo === attachment.get('uploadedTo');
        },
        
/**
         * @static
         * @param {wp.media.model.Attachment} attachment
         *
         * @this wp.media.model.Attachments
         *
         * @returns {Boolean}
         */
        
status: function( attachment ) {
            var 
status this.props.get('status');
            if ( 
_.isUndefinedstatus ) ) {
                return 
true;
            }

            return 
status === attachment.get('status');
        }
    }
});

module.exports Attachments;

},{}],
4:[function(require,module,exports){
/*globals Backbone */

/**
 * wp.media.model.PostImage
 *
 * An instance of an image that's been embedded into a post.
 *
 * Used in the embedded image attachment display settings modal - @see wp.media.view.MediaFrame.ImageDetails.
 *
 * @class
 * @augments Backbone.Model
 *
 * @param {int} [attributes]               Initial model attributes.
 * @param {int} [attributes.attachment_id] ID of the attachment.
 **/
var PostImage Backbone.Model.extend({

    
initialize: function( attributes ) {
        var 
Attachment wp.media.model.Attachment;
        
this.attachment false;

        if ( 
attributes.attachment_id ) {
            
this.attachment Attachment.getattributes.attachment_id );
            if ( 
this.attachment.get'url' ) ) {
                
this.dfd jQuery.Deferred();
                
this.dfd.resolve();
            } else {
                
this.dfd this.attachment.fetch();
            }
            
this.bindAttachmentListeners();
        }

        
// keep url in sync with changes to the type of link
        
this.on'change:link'this.updateLinkUrlthis );
        
this.on'change:size'this.updateSizethis );

        
this.setLinkTypeFromUrl();
        
this.setAspectRatio();

        
this.set'originalUrl'attributes.url );
    },

    
bindAttachmentListeners: function() {
        
this.listenTothis.attachment'sync'this.setLinkTypeFromUrl );
        
this.listenTothis.attachment'sync'this.setAspectRatio );
        
this.listenTothis.attachment'change'this.updateSize );
    },

    
changeAttachment: function( attachmentprops ) {
        
this.stopListeningthis.attachment );
        
this.attachment attachment;
        
this.bindAttachmentListeners();

        
this.set'attachment_id'this.attachment.get'id' ) );
        
this.set'caption'this.attachment.get'caption' ) );
        
this.set'alt'this.attachment.get'alt' ) );
        
this.set'size'props.get'size' ) );
        
this.set'align'props.get'align' ) );
        
this.set'link'props.get'link' ) );
        
this.updateLinkUrl();
        
this.updateSize();
    },

    
setLinkTypeFromUrl: function() {
        var 
linkUrl this.get'linkUrl' ),
            
type;

        if ( ! 
linkUrl ) {
            
this.set'link''none' );
            return;
        }

        
// default to custom if there is a linkUrl
        
type 'custom';

        if ( 
this.attachment ) {
            if ( 
this.attachment.get'url' ) === linkUrl ) {
                
type 'file';
            } else if ( 
this.attachment.get'link' ) === linkUrl ) {
                
type 'post';
            }
        } else {
            if ( 
this.get'url' ) === linkUrl ) {
                
type 'file';
            }
        }

        
this.set'link'type );
    },

    
updateLinkUrl: function() {
        var 
link this.get'link' ),
            
url;

        switch( 
link ) {
            case 
'file':
                if ( 
this.attachment ) {
                    
url this.attachment.get'url' );
                } else {
                    
url this.get'url' );
                }
                
this.set'linkUrl'url );
                break;
            case 
'post':
                
this.set'linkUrl'this.attachment.get'link' ) );
                break;
            case 
'none':
                
this.set'linkUrl''' );
                break;
        }
    },

    
updateSize: function() {
        var 
size;

        if ( ! 
this.attachment ) {
            return;
        }

        if ( 
this.get'size' ) === 'custom' ) {
            
this.set'width'this.get'customWidth' ) );
            
this.set'height'this.get'customHeight' ) );
            
this.set'url'this.get'originalUrl' ) );
            return;
        }

        
size this.attachment.get'sizes' )[ this.get'size' ) ];

        if ( ! 
size ) {
            return;
        }

        
this.set'url'size.url );
        
this.set'width'size.width );
        
this.set'height'size.height );
    },

    
setAspectRatio: function() {
        var 
full;

        if ( 
this.attachment && this.attachment.get'sizes' ) ) {
            
full this.attachment.get'sizes' ).full;

            if ( 
full ) {
                
this.set'aspectRatio'full.width full.height );
                return;
            }
        }

        
this.set'aspectRatio'this.get'customWidth' ) / this.get'customHeight' ) );
    }
});

module.exports PostImage;

},{}],
5:[function(require,module,exports){
/*globals wp, _ */

/**
 * wp.media.model.Query
 *
 * A collection of attachments that match the supplied query arguments.
 *
 * Note: Do NOT change this.args after the query has been initialized.
 *       Things will break.
 *
 * @class
 * @augments wp.media.model.Attachments
 * @augments Backbone.Collection
 *
 * @param {array}  [models]                      Models to initialize with the collection.
 * @param {object} [options]                     Options hash.
 * @param {object} [options.args]                Attachments query arguments.
 * @param {object} [options.args.posts_per_page]
 */
var Attachments wp.media.model.Attachments,
    
Query;

Query Attachments.extend({
    
/**
     * @global wp.Uploader
     *
     * @param {array}  [models=[]]  Array of initial models to populate the collection.
     * @param {object} [options={}]
     */
    
initialize: function( modelsoptions ) {
        var 
allowed;

        
options options || {};
        
Attachments.prototype.initialize.applythisarguments );

        
this.args     options.args;
        
this._hasMore true;
        
this.created  = new Date();

        
this.filters.order = function( attachment ) {
            var 
orderby this.props.get('orderby'),
                
order this.props.get('order');

            if ( ! 
this.comparator ) {
                return 
true;
            }

            
// We want any items that can be placed before the last
            // item in the set. If we add any items after the last
            // item, then we can't guarantee the set is complete.
            
if ( this.length ) {
                return 
!== this.comparatorattachmentthis.last(), { tiestrue });

            
// Handle the case where there are no items yet and
            // we're sorting for recent items. In that case, we want
            // changes that occurred after we created the query.
            
} else if ( 'DESC' === order && ( 'date' === orderby || 'modified' === orderby ) ) {
                return 
attachment.getorderby ) >= this.created;

            
// If we're sorting by menu order and we have no items,
            // accept any items that have the default menu order (0).
            
} else if ( 'ASC' === order && 'menuOrder' === orderby ) {
                return 
attachment.getorderby ) === 0;
            }

            
// Otherwise, we don't want any items yet.
            
return false;
        };

        
// Observe the central `wp.Uploader.queue` collection to watch for
        // new matches for the query.
        //
        // Only observe when a limited number of query args are set. There
        // are no filters for other properties, so observing will result in
        // false positives in those queries.
        
allowed = [ 's''order''orderby''posts_per_page''post_mime_type''post_parent' ];
        if ( 
wp.Uploader && _this.args ).chain().keys().differenceallowed ).isEmpty().value() ) {
            
this.observewp.Uploader.queue );
        }
    },
    
/**
     * Whether there are more attachments that haven't been sync'd from the server
     * that match the collection's query.
     *
     * @returns {boolean}
     */
    
hasMore: function() {
        return 
this._hasMore;
    },
    
/**
     * Fetch more attachments from the server for the collection.
     *
     * @param   {object}  [options={}]
     * @returns {Promise}
     */
    
more: function( options ) {
        var 
query this;

        
// If there is already a request pending, return early with the Deferred object.
        
if ( this._more && 'pending' === this._more.state() ) {
            return 
this._more;
        }

        if ( ! 
this.hasMore() ) {
            return 
jQuery.Deferred().resolveWiththis ).promise();
        }

        
options options || {};
        
options.remove false;

        return 
this._more this.fetchoptions ).done( function( resp ) {
            if ( 
_.isEmptyresp ) || -=== this.args.posts_per_page || resp.length this.args.posts_per_page ) {
                
query._hasMore false;
            }
        });
    },
    
/**
     * Overrides Backbone.Collection.sync
     * Overrides wp.media.model.Attachments.sync
     *
     * @param {String} method
     * @param {Backbone.Model} model
     * @param {Object} [options={}]
     * @returns {Promise}
     */
    
sync: function( methodmodeloptions ) {
        var 
argsfallback;

        
// Overload the read method so Attachment.fetch() functions correctly.
        
if ( 'read' === method ) {
            
options options || {};
            
options.context this;
            
options.data _.extendoptions.data || {}, {
                
action:  'query-attachments',
                
post_idwp.media.model.settings.post.id
            
});

            
// Clone the args so manipulation is non-destructive.
            
args _.clone( this.args );

            
// Determine which page to query.
            
if ( -!== args.posts_per_page ) {
                
args.paged Math.roundthis.length args.posts_per_page ) + 1;
            }

            
options.data.query args;
            return 
wp.media.ajaxoptions );

        
// Otherwise, fall back to Backbone.sync()
        
} else {
            
/**
             * Call wp.media.model.Attachments.sync or Backbone.sync
             */
            
fallback Attachments.prototype.sync Attachments.prototype Backbone;
            return 
fallback.sync.applythisarguments );
        }
    }
}, {
    
/**
     * @readonly
     */
    
defaultProps: {
        
orderby'date',
        
order:   'DESC'
    
},
    
/**
     * @readonly
     */
    
defaultArgs: {
        
posts_per_page40
    
},
    
/**
     * @readonly
     */
    
orderby: {
        
allowed:  [ 'name''author''date''title''modified''uploadedTo''id''post__in''menuOrder' ],
        
/**
         * A map of JavaScript orderby values to their WP_Query equivalents.
         * @type {Object}
         */
        
valuemap: {
            
'id':         'ID',
            
'uploadedTo''parent',
            
'menuOrder':  'menu_order ID'
        
}
    },
    
/**
     * A map of JavaScript query properties to their WP_Query equivalents.
     *
     * @readonly
     */
    
propmap: {
        
'search':    's',
        
'type':      'post_mime_type',
        
'perPage':   'posts_per_page',
        
'menuOrder''menu_order',
        
'uploadedTo''post_parent',
        
'status':     'post_status',
        
'include':    'post__in',
        
'exclude':    'post__not_in'
    
},
    
/**
     * Creates and returns an Attachments Query collection given the properties.
     *
     * Caches query objects and reuses where possible.
     *
     * @static
     * @method
     *
     * @param {object} [props]
     * @param {Object} [props.cache=true]   Whether to use the query cache or not.
     * @param {Object} [props.order]
     * @param {Object} [props.orderby]
     * @param {Object} [props.include]
     * @param {Object} [props.exclude]
     * @param {Object} [props.s]
     * @param {Object} [props.post_mime_type]
     * @param {Object} [props.posts_per_page]
     * @param {Object} [props.menu_order]
     * @param {Object} [props.post_parent]
     * @param {Object} [props.post_status]
     * @param {Object} [options]
     *
     * @returns {wp.media.model.Query} A new Attachments Query collection.
     */
    
get: (function(){
        
/**
         * @static
         * @type Array
         */
        
var queries = [];

        
/**
         * @returns {Query}
         */
        
return function( propsoptions ) {
            var 
args     = {},
                
orderby  Query.orderby,
                
defaults Query.defaultProps,
                
query,
                
cache    = !! props.cache || _.isUndefinedprops.cache );

            
// Remove the `query` property. This isn't linked to a query,
            // this *is* the query.
            
delete props.query;
            
delete props.cache;

            
// Fill default args.
            
_.defaultspropsdefaults );

            
// Normalize the order.
            
props.order props.order.toUpperCase();
            if ( 
'DESC' !== props.order && 'ASC' !== props.order ) {
                
props.order defaults.order.toUpperCase();
            }

            
// Ensure we have a valid orderby value.
            
if ( ! _.containsorderby.allowedprops.orderby ) ) {
                
props.orderby defaults.orderby;
            }

            
_.each( [ 'include''exclude' ], function( prop ) {
                if ( 
propsprop ] && ! _.isArraypropsprop ] ) ) {
                    
propsprop ] = [ propsprop ] ];
                }
            } );

            
// Generate the query `args` object.
            // Correct any differing property names.
            
_.eachprops, function( valueprop ) {
                if ( 
_.isNullvalue ) ) {
                    return;
                }

                
argsQuery.propmapprop ] || prop ] = value;
            });

            
// Fill any other default query args.
            
_.defaultsargsQuery.defaultArgs );

            
// `props.orderby` does not always map directly to `args.orderby`.
            // Substitute exceptions specified in orderby.keymap.
            
args.orderby orderby.valuemapprops.orderby ] || props.orderby;

            
// Search the query cache for a matching query.
            
if ( cache ) {
                
query _.findqueries, function( query ) {
                    return 
_.isEqualquery.argsargs );
                });
            } else {
                
queries = [];
            }

            
// Otherwise, create a new query and add it to the cache.
            
if ( ! query ) {
                
query = new Query( [], _.extendoptions || {}, {
                    
propsprops,
                    
args:  args
                
} ) );
                
queries.pushquery );
            }

            return 
query;
        };
    }())
});

module.exports Query;

},{}],
6:[function(require,module,exports){
/*globals wp, _ */

/**
 * wp.media.model.Selection
 *
 * A selection of attachments.
 *
 * @class
 * @augments wp.media.model.Attachments
 * @augments Backbone.Collection
 */
var Attachments wp.media.model.Attachments,
    
Selection;

Selection Attachments.extend({
    
/**
     * Refresh the `single` model whenever the selection changes.
     * Binds `single` instead of using the context argument to ensure
     * it receives no parameters.
     *
     * @param {Array} [models=[]] Array of models used to populate the collection.
     * @param {Object} [options={}]
     */
    
initialize: function( modelsoptions ) {
        
/**
         * call 'initialize' directly on the parent class
         */
        
Attachments.prototype.initialize.applythisarguments );
        
this.multiple options && options.multiple;

        
this.on'add remove reset'_.bindthis.singlethisfalse ) );
    },

    
/**
     * If the workflow does not support multi-select, clear out the selection
     * before adding a new attachment to it.
     *
     * @param {Array} models
     * @param {Object} options
     * @returns {wp.media.model.Attachment[]}
     */
    
add: function( modelsoptions ) {
        if ( ! 
this.multiple ) {
            
this.removethis.models );
        }
        
/**
         * call 'add' directly on the parent class
         */
        
return Attachments.prototype.add.callthismodelsoptions );
    },

    
/**
     * Fired when toggling (clicking on) an attachment in the modal.
     *
     * @param {undefined|boolean|wp.media.model.Attachment} model
     *
     * @fires wp.media.model.Selection#selection:single
     * @fires wp.media.model.Selection#selection:unsingle
     *
     * @returns {Backbone.Model}
     */
    
single: function( model ) {
        var 
previous this._single;

        
// If a `model` is provided, use it as the single model.
        
if ( model ) {
            
this._single model;
        }
        
// If the single model isn't in the selection, remove it.
        
if ( this._single && ! this.getthis._single.cid ) ) {
            
delete this._single;
        }

        
this._single this._single || this.last();

        
// If single has changed, fire an event.
        
if ( this._single !== previous ) {
            if ( 
previous ) {
                
previous.trigger'selection:unsingle'previousthis );

                
// If the model was already removed, trigger the collection
                // event manually.
                
if ( ! this.getprevious.cid ) ) {
                    
this.trigger'selection:unsingle'previousthis );
                }
            }
            if ( 
this._single ) {
                
this._single.trigger'selection:single'this._singlethis );
            }
        }

        
// Return the single model, or the last model as a fallback.
        
return this._single;
    }
});

module.exports Selection;

},{}]},{},[
1]);
?>
Онлайн: 0
Реклама