Вход Регистрация
Файл: wordpress/wp-includes/js/media-views.js
Строк: 8479
<?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, _ */

/**
 * wp.media.controller.CollectionAdd
 *
 * A state for adding attachments to a collection (e.g. video playlist).
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                         The attributes hash passed to the state.
 * @param {string}                     [attributes.id=library]      Unique identifier.
 * @param {string}                     attributes.title                    Title for the state. Displays in the frame's title region.
 * @param {boolean}                    [attributes.multiple=add]            Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
 * @param {wp.media.model.Attachments} [attributes.library]                 The attachments collection to browse.
 *                                                                          If one is not supplied, a collection of attachments of the specified type will be created.
 * @param {boolean|string}             [attributes.filterable=uploaded]     Whether the library is filterable, and if so what filters should be shown.
 *                                                                          Accepts 'all', 'uploaded', or 'unattached'.
 * @param {string}                     [attributes.menu=gallery]            Initial mode for the menu region.
 * @param {string}                     [attributes.content=upload]          Initial mode for the content region.
 *                                                                          Overridden by persistent user setting if 'contentUserSetting' is true.
 * @param {string}                     [attributes.router=browse]           Initial mode for the router region.
 * @param {string}                     [attributes.toolbar=gallery-add]     Initial mode for the toolbar region.
 * @param {boolean}                    [attributes.searchable=true]         Whether the library is searchable.
 * @param {boolean}                    [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
 * @param {boolean}                    [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
 * @param {int}                        [attributes.priority=100]            The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.syncSelection=false]     Whether the Attachments selection should be persisted from the last state.
 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
 * @param {string}                     attributes.type                   The collection's media type. (e.g. 'video').
 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
 */
var Selection wp.media.model.Selection,
    
Library wp.media.controller.Library,
    
CollectionAdd;

CollectionAdd Library.extend({
    
defaults_.defaults( {
        
// Selection defaults. @see media.model.Selection
        
multiple:      'add',
        
// Attachments browser defaults. @see media.view.AttachmentsBrowser
        
filterable:    'uploaded',

        
priority:      100,
        
syncSelectionfalse
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.9.0
     */
    
initialize: function() {
        var 
collectionType this.get('collectionType');

        if ( 
'video' === this.get'type' ) ) {
            
collectionType 'video-' collectionType;
        }

        
this.set'id'collectionType '-library' );
        
this.set'toolbar'collectionType '-add' );
        
this.set'menu'collectionType );

        
// If we haven't been provided a `library`, create a `Selection`.
        
if ( ! this.get('library') ) {
            
this.set'library'wp.media.query({ typethis.get('type') }) );
        }
        
Library.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        var 
library this.get('library'),
            
editLibrary this.get('editLibrary'),
            
edit this.frame.statethis.get('collectionType') + '-edit' ).get('library');

        if ( 
editLibrary && editLibrary !== edit ) {
            
library.unobserveeditLibrary );
        }

        
// Accepts attachments that exist in the original library and
        // that do not exist in gallery's library.
        
library.validator = function( attachment ) {
            return !! 
this.mirroring.getattachment.cid ) && ! edit.getattachment.cid ) && Selection.prototype.validator.applythisarguments );
        };

        
// Reset the library to ensure that all attachments are re-added
        // to the collection. Do so silently, as calling `observe` will
        // trigger the `reset` event.
        
library.resetlibrary.mirroring.models, { silenttrue });
        
library.observeedit );
        
this.set('editLibrary'edit);

        
Library.prototype.activate.applythisarguments );
    }
});

module.exports CollectionAdd;

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

/**
 * wp.media.controller.CollectionEdit
 *
 * A state for editing a collection, which is used by audio and video playlists,
 * and can be used for other collections.
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                      The attributes hash passed to the state.
 * @param {string}                     attributes.title                  Title for the state. Displays in the media menu and the frame's title region.
 * @param {wp.media.model.Attachments} [attributes.library]              The attachments collection to edit.
 *                                                                       If one is not supplied, an empty media.model.Selection collection is created.
 * @param {boolean}                    [attributes.multiple=false]       Whether multi-select is enabled.
 * @param {string}                     [attributes.content=browse]       Initial mode for the content region.
 * @param {string}                     attributes.menu                   Initial mode for the menu region. @todo this needs a better explanation.
 * @param {boolean}                    [attributes.searchable=false]     Whether the library is searchable.
 * @param {boolean}                    [attributes.sortable=true]        Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.date=true]            Whether to show the date filter in the browser's toolbar.
 * @param {boolean}                    [attributes.describe=true]        Whether to offer UI to describe the attachments - e.g. captioning images in a gallery.
 * @param {boolean}                    [attributes.dragInfo=true]        Whether to show instructional text about the attachments being sortable.
 * @param {boolean}                    [attributes.dragInfoText]         Instructional text about the attachments being sortable.
 * @param {int}                        [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.
 * @param {boolean}                    [attributes.editing=false]        Whether the gallery is being created, or editing an existing instance.
 * @param {int}                        [attributes.priority=60]          The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.syncSelection=false]  Whether the Attachments selection should be persisted from the last state.
 *                                                                       Defaults to false for this state, because the library passed in  *is* the selection.
 * @param {view}                       [attributes.SettingsView]         The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox).
 * @param {view}                       [attributes.AttachmentView]       The single `Attachment` view to be used in the `Attachments`.
 *                                                                       If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
 * @param {string}                     attributes.type                   The collection's media type. (e.g. 'video').
 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
 */
var Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    $ = 
jQuery,
    
CollectionEdit;

CollectionEdit Library.extend({
    
defaults: {
        
multiple:         false,
        
sortable:         true,
        
date:             false,
        
searchable:       false,
        
content:          'browse',
        
describe:         true,
        
dragInfo:         true,
        
idealColumnWidth170,
        
editing:          false,
        
priority:         60,
        
SettingsView:     false,
        
syncSelection:    false
    
},

    
/**
     * @since 3.9.0
     */
    
initialize: function() {
        var 
collectionType this.get('collectionType');

        if ( 
'video' === this.get'type' ) ) {
            
collectionType 'video-' collectionType;
        }

        
this.set'id'collectionType '-edit' );
        
this.set'toolbar'collectionType '-edit' );

        
// If we haven't been provided a `library`, create a `Selection`.
        
if ( ! this.get('library') ) {
            
this.set'library', new wp.media.model.Selection() );
        }
        
// The single `Attachment` view to be used in the `Attachments` view.
        
if ( ! this.get('AttachmentView') ) {
            
this.set'AttachmentView'wp.media.view.Attachment.EditLibrary );
        }
        
Library.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        var 
library this.get('library');

        
// Limit the library to images only.
        
library.props.set'type'this.get'type' ) );

        
// Watch for uploaded attachments.
        
this.get('library').observewp.Uploader.queue );

        
this.frame.on'content:render:browse'this.renderSettingsthis );

        
Library.prototype.activate.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
deactivate: function() {
        
// Stop watching for uploaded attachments.
        
this.get('library').unobservewp.Uploader.queue );

        
this.frame.off'content:render:browse'this.renderSettingsthis );

        
Library.prototype.deactivate.applythisarguments );
    },

    
/**
     * Render the collection embed settings view in the browser sidebar.
     *
     * @todo This is against the pattern elsewhere in media. Typically the frame
     *       is responsible for adding region mode callbacks. Explain.
     *
     * @since 3.9.0
     *
     * @param {wp.media.view.attachmentsBrowser} The attachments browser view.
     */
    
renderSettings: function( attachmentsBrowserView ) {
        var 
library this.get('library'),
            
collectionType this.get('collectionType'),
            
dragInfoText this.get('dragInfoText'),
            
SettingsView this.get('SettingsView'),
            
obj = {};

        if ( ! 
library || ! attachmentsBrowserView ) {
            return;
        }

        
librarycollectionType ] = librarycollectionType ] || new Backbone.Model();

        
objcollectionType ] = new SettingsView({
            
controllerthis,
            
model:      librarycollectionType ],
            
priority:   40
        
});

        
attachmentsBrowserView.sidebar.setobj );

        if ( 
dragInfoText ) {
            
attachmentsBrowserView.toolbar.set'dragInfo', new wp.media.View({
                
el: $( '<div class="instructions">' dragInfoText '</div>' )[0],
                
priority: -40
            
}) );
        }

        
// Add the 'Reverse order' button to the toolbar.
        
attachmentsBrowserView.toolbar.set'reverse', {
            
text:     l10n.reverseOrder,
            
priority80,

            
click: function() {
                
library.resetlibrary.toArray().reverse() );
            }
        });
    }
});

module.exports CollectionEdit;

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

/**
 * wp.media.controller.Cropper
 *
 * A state for cropping an image.
 *
 * @class
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 */
var l10n wp.media.view.l10n,
    
Cropper;

Cropper wp.media.controller.State.extend({
    
defaults: {
        
id:          'cropper',
        
title:       l10n.cropImage,
        
// Region mode defaults.
        
toolbar:     'crop',
        
content:     'crop',
        
router:      false,

        
canSkipCropfalse
    
},

    
activate: function() {
        
this.frame.on'content:create:crop'this.createCropContentthis );
        
this.frame.on'close'this.removeCropperthis );
        
this.set('selection', new Backbone.Collection(this.frame._selection.single));
    },

    
deactivate: function() {
        
this.frame.toolbar.mode('browse');
    },

    
createCropContent: function() {
        
this.cropperView = new wp.media.view.Cropper({
            
controllerthis,
            
attachmentthis.get('selection').first()
        });
        
this.cropperView.on('image-loaded'this.createCropToolbarthis);
        
this.frame.content.set(this.cropperView);

    },
    
removeCropper: function() {
        
this.imgSelect.cancelSelection();
        
this.imgSelect.setOptions({removetrue});
        
this.imgSelect.update();
        
this.cropperView.remove();
    },
    
createCropToolbar: function() {
        var 
canSkipCroptoolbarOptions;

        
canSkipCrop this.get('canSkipCrop') || false;

        
toolbarOptions = {
            
controllerthis.frame,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     l10n.cropImage,
                    
priority80,
                    
requires: { libraryfalseselectionfalse },

                    
click: function() {
                        var 
controller this.controller,
                            
selection;

                        
selection controller.state().get('selection').first();
                        
selection.set({cropDetailscontroller.state().imgSelect.getSelection()});

                        
this.$el.text(l10n.cropping);
                        
this.$el.attr('disabled'true);

                        
controller.state().doCropselection ).done( function( croppedImage ) {
                            
controller.trigger('cropped'croppedImage );
                            
controller.close();
                        }).
fail( function() {
                            
controller.trigger('content:error:crop');
                        });
                    }
                }
            }
        };

        if ( 
canSkipCrop ) {
            
_.extendtoolbarOptions.items, {
                
skip: {
                    
style:      'secondary',
                    
text:       l10n.skipCropping,
                    
priority:   70,
                    
requires:   { libraryfalseselectionfalse },
                    
click:      function() {
                        var 
selection this.controller.state().get('selection').first();
                        
this.controller.state().cropperView.remove();
                        
this.controller.trigger('skippedcrop'selection);
                        
this.controller.close();
                    }
                }
            });
        }

        
this.frame.toolbar.set( new wp.media.view.Toolbar(toolbarOptions) );
    },

    
doCrop: function( attachment ) {
        return 
wp.ajax.post'custom-header-crop', {
            
nonceattachment.get('nonces').edit,
            
idattachment.get('id'),
            
cropDetailsattachment.get('cropDetails')
        } );
    }
});

module.exports Cropper;

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

/**
 * wp.media.controller.EditImage
 *
 * A state for editing (cropping, etc.) an image.
 *
 * @class
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                    attributes                      The attributes hash passed to the state.
 * @param {wp.media.model.Attachment} attributes.model                The attachment.
 * @param {string}                    [attributes.id=edit-image]      Unique identifier.
 * @param {string}                    [attributes.title=Edit Image]   Title for the state. Displays in the media menu and the frame's title region.
 * @param {string}                    [attributes.content=edit-image] Initial mode for the content region.
 * @param {string}                    [attributes.toolbar=edit-image] Initial mode for the toolbar region.
 * @param {string}                    [attributes.menu=false]         Initial mode for the menu region.
 * @param {string}                    [attributes.url]                Unused. @todo Consider removal.
 */
var l10n wp.media.view.l10n,
    
EditImage;

EditImage wp.media.controller.State.extend({
    
defaults: {
        
id:      'edit-image',
        
title:   l10n.editImage,
        
menu:    false,
        
toolbar'edit-image',
        
content'edit-image',
        
url:     ''
    
},

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        
this.listenTothis.frame'toolbar:render:edit-image'this.toolbar );
    },

    
/**
     * @since 3.9.0
     */
    
deactivate: function() {
        
this.stopListeningthis.frame );
    },

    
/**
     * @since 3.9.0
     */
    
toolbar: function() {
        var 
frame this.frame,
            
lastState frame.lastState(),
            
previous lastState && lastState.id;

        
frame.toolbar.set( new wp.media.view.Toolbar({
            
controllerframe,
            
items: {
                
back: {
                    
style'primary',
                    
text:     l10n.back,
                    
priority20,
                    
click:    function() {
                        if ( 
previous ) {
                            
frame.setStateprevious );
                        } else {
                            
frame.close();
                        }
                    }
                }
            }
        }) );
    }
});

module.exports EditImage;

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

/**
 * wp.media.controller.Embed
 *
 * A state for embedding media from a URL.
 *
 * @class
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object} attributes                         The attributes hash passed to the state.
 * @param {string} [attributes.id=embed]              Unique identifier.
 * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region.
 * @param {string} [attributes.content=embed]         Initial mode for the content region.
 * @param {string} [attributes.menu=default]          Initial mode for the menu region.
 * @param {string} [attributes.toolbar=main-embed]    Initial mode for the toolbar region.
 * @param {string} [attributes.menu=false]            Initial mode for the menu region.
 * @param {int}    [attributes.priority=120]          The priority for the state link in the media menu.
 * @param {string} [attributes.type=link]             The type of embed. Currently only link is supported.
 * @param {string} [attributes.url]                   The embed URL.
 * @param {object} [attributes.metadata={}]           Properties of the embed, which will override attributes.url if set.
 */
var l10n wp.media.view.l10n,
    $ = 
Backbone.$,
    
Embed;

Embed wp.media.controller.State.extend({
    
defaults: {
        
id:       'embed',
        
title:    l10n.insertFromUrlTitle,
        
content:  'embed',
        
menu:     'default',
        
toolbar:  'main-embed',
        
priority120,
        
type:     'link',
        
url:      '',
        
metadata: {}
    },

    
// The amount of time used when debouncing the scan.
    
sensitivity200,

    
initialize: function(options) {
        
this.metadata options.metadata;
        
this.debouncedScan _.debounce_.bindthis.scanthis ), this.sensitivity );
        
this.props = new Backbone.Modelthis.metadata || { url'' });
        
this.props.on'change:url'this.debouncedScanthis );
        
this.props.on'change:url'this.refreshthis );
        
this.on'scan'this.scanImagethis );
    },

    
/**
     * Trigger a scan of the embedded URL's content for metadata required to embed.
     *
     * @fires wp.media.controller.Embed#scan
     */
    
scan: function() {
        var 
scanners,
            
embed this,
            
attributes = {
                
type'link',
                
scanners: []
            };

        
// Scan is triggered with the list of `attributes` to set on the
        // state, useful for the 'type' attribute and 'scanners' attribute,
        // an array of promise objects for asynchronous scan operations.
        
if ( this.props.get('url') ) {
            
this.trigger'scan'attributes );
        }

        if ( 
attributes.scanners.length ) {
            
scanners attributes.scanners = $.when.apply( $, attributes.scanners );
            
scanners.always( function() {
                if ( 
embed.get('scanners') === scanners ) {
                    
embed.set'loading'false );
                }
            });
        } else {
            
attributes.scanners null;
        }

        
attributes.loading = !! attributes.scanners;
        
this.setattributes );
    },
    
/**
     * Try scanning the embed as an image to discover its dimensions.
     *
     * @param {Object} attributes
     */
    
scanImage: function( attributes ) {
        var 
frame this.frame,
            
state this,
            
url this.props.get('url'),
            
image = new Image(),
            
deferred = $.Deferred();

        
attributes.scanners.pushdeferred.promise() );

        
// Try to load the image and find its width/height.
        
image.onload = function() {
            
deferred.resolve();

            if ( 
state !== frame.state() || url !== state.props.get('url') ) {
                return;
            }

            
state.set({
                
type'image'
            
});

            
state.props.set({
                
width:  image.width,
                
heightimage.height
            
});
        };

        
image.onerror deferred.reject;
        
image.src url;
    },

    
refresh: function() {
        
this.frame.toolbar.get().refresh();
    },

    
reset: function() {
        
this.props.clear().set({ url'' });

        if ( 
this.active ) {
            
this.refresh();
        }
    }
});

module.exports Embed;

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

/**
 * wp.media.controller.FeaturedImage
 *
 * A state for selecting a featured image for a post.
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                          The attributes hash passed to the state.
 * @param {string}                     [attributes.id=featured-image]        Unique identifier.
 * @param {string}                     [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region.
 * @param {wp.media.model.Attachments} [attributes.library]                  The attachments collection to browse.
 *                                                                           If one is not supplied, a collection of all images will be created.
 * @param {boolean}                    [attributes.multiple=false]           Whether multi-select is enabled.
 * @param {string}                     [attributes.content=upload]           Initial mode for the content region.
 *                                                                           Overridden by persistent user setting if 'contentUserSetting' is true.
 * @param {string}                     [attributes.menu=default]             Initial mode for the menu region.
 * @param {string}                     [attributes.router=browse]            Initial mode for the router region.
 * @param {string}                     [attributes.toolbar=featured-image]   Initial mode for the toolbar region.
 * @param {int}                        [attributes.priority=60]              The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.searchable=true]          Whether the library is searchable.
 * @param {boolean|string}             [attributes.filterable=false]         Whether the library is filterable, and if so what filters should be shown.
 *                                                                           Accepts 'all', 'uploaded', or 'unattached'.
 * @param {boolean}                    [attributes.sortable=true]            Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.autoSelect=true]          Whether an uploaded attachment should be automatically added to the selection.
 * @param {boolean}                    [attributes.describe=false]           Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 * @param {boolean}                    [attributes.contentUserSetting=true]  Whether the content region's mode should be set and persisted per user.
 * @param {boolean}                    [attributes.syncSelection=true]       Whether the Attachments selection should be persisted from the last state.
 */
var Attachment wp.media.model.Attachment,
    
Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
FeaturedImage;

FeaturedImage Library.extend({
    
defaults_.defaults({
        
id:            'featured-image',
        
title:         l10n.setFeaturedImageTitle,
        
multiple:      false,
        
filterable:    'uploaded',
        
toolbar:       'featured-image',
        
priority:      60,
        
syncSelectiontrue
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.5.0
     */
    
initialize: function() {
        var 
librarycomparator;

        
// If we haven't been provided a `library`, create a `Selection`.
        
if ( ! this.get('library') ) {
            
this.set'library'wp.media.query({ type'image' }) );
        }

        
Library.prototype.initialize.applythisarguments );

        
library    this.get('library');
        
comparator library.comparator;

        
// Overload the library's comparator to push items that are not in
        // the mirrored query to the front of the aggregate collection.
        
library.comparator = function( a) {
            var 
aInQuery = !! this.mirroring.geta.cid ),
                
bInQuery = !! this.mirroring.getb.cid );

            if ( ! 
aInQuery && bInQuery ) {
                return -
1;
            } else if ( 
aInQuery && ! bInQuery ) {
                return 
1;
            } else {
                return 
comparator.applythisarguments );
            }
        };

        
// Add all items in the selection to the library, so any featured
        // images that are not initially loaded still appear.
        
library.observethis.get('selection') );
    },

    
/**
     * @since 3.5.0
     */
    
activate: function() {
        
this.updateSelection();
        
this.frame.on'open'this.updateSelectionthis );

        
Library.prototype.activate.applythisarguments );
    },

    
/**
     * @since 3.5.0
     */
    
deactivate: function() {
        
this.frame.off'open'this.updateSelectionthis );

        
Library.prototype.deactivate.applythisarguments );
    },

    
/**
     * @since 3.5.0
     */
    
updateSelection: function() {
        var 
selection this.get('selection'),
            
id wp.media.view.settings.post.featuredImageId,
            
attachment;

        if ( 
'' !== id && -!== id ) {
            
attachment Attachment.getid );
            
attachment.fetch();
        }

        
selection.resetattachment ? [ attachment ] : [] );
    }
});

module.exports FeaturedImage;

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

/**
 * wp.media.controller.GalleryAdd
 *
 * A state for selecting more images to add to a gallery.
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                         The attributes hash passed to the state.
 * @param {string}                     [attributes.id=gallery-library]      Unique identifier.
 * @param {string}                     [attributes.title=Add to Gallery]    Title for the state. Displays in the frame's title region.
 * @param {boolean}                    [attributes.multiple=add]            Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
 * @param {wp.media.model.Attachments} [attributes.library]                 The attachments collection to browse.
 *                                                                          If one is not supplied, a collection of all images will be created.
 * @param {boolean|string}             [attributes.filterable=uploaded]     Whether the library is filterable, and if so what filters should be shown.
 *                                                                          Accepts 'all', 'uploaded', or 'unattached'.
 * @param {string}                     [attributes.menu=gallery]            Initial mode for the menu region.
 * @param {string}                     [attributes.content=upload]          Initial mode for the content region.
 *                                                                          Overridden by persistent user setting if 'contentUserSetting' is true.
 * @param {string}                     [attributes.router=browse]           Initial mode for the router region.
 * @param {string}                     [attributes.toolbar=gallery-add]     Initial mode for the toolbar region.
 * @param {boolean}                    [attributes.searchable=true]         Whether the library is searchable.
 * @param {boolean}                    [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
 * @param {boolean}                    [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
 * @param {int}                        [attributes.priority=100]            The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.syncSelection=false]     Whether the Attachments selection should be persisted from the last state.
 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
 */
var Selection wp.media.model.Selection,
    
Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
GalleryAdd;

GalleryAdd Library.extend({
    
defaults_.defaults({
        
id:            'gallery-library',
        
title:         l10n.addToGalleryTitle,
        
multiple:      'add',
        
filterable:    'uploaded',
        
menu:          'gallery',
        
toolbar:       'gallery-add',
        
priority:      100,
        
syncSelectionfalse
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.5.0
     */
    
initialize: function() {
        
// If a library wasn't supplied, create a library of images.
        
if ( ! this.get('library') ) {
            
this.set'library'wp.media.query({ type'image' }) );
        }

        
Library.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.5.0
     */
    
activate: function() {
        var 
library this.get('library'),
            
edit    this.frame.state('gallery-edit').get('library');

        if ( 
this.editLibrary && this.editLibrary !== edit ) {
            
library.unobservethis.editLibrary );
        }

        
// Accepts attachments that exist in the original library and
        // that do not exist in gallery's library.
        
library.validator = function( attachment ) {
            return !! 
this.mirroring.getattachment.cid ) && ! edit.getattachment.cid ) && Selection.prototype.validator.applythisarguments );
        };

        
// Reset the library to ensure that all attachments are re-added
        // to the collection. Do so silently, as calling `observe` will
        // trigger the `reset` event.
        
library.resetlibrary.mirroring.models, { silenttrue });
        
library.observeedit );
        
this.editLibrary edit;

        
Library.prototype.activate.applythisarguments );
    }
});

module.exports GalleryAdd;

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

/**
 * wp.media.controller.GalleryEdit
 *
 * A state for editing a gallery's images and settings.
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                       The attributes hash passed to the state.
 * @param {string}                     [attributes.id=gallery-edit]       Unique identifier.
 * @param {string}                     [attributes.title=Edit Gallery]    Title for the state. Displays in the frame's title region.
 * @param {wp.media.model.Attachments} [attributes.library]               The collection of attachments in the gallery.
 *                                                                        If one is not supplied, an empty media.model.Selection collection is created.
 * @param {boolean}                    [attributes.multiple=false]        Whether multi-select is enabled.
 * @param {boolean}                    [attributes.searchable=false]      Whether the library is searchable.
 * @param {boolean}                    [attributes.sortable=true]         Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.date=true]             Whether to show the date filter in the browser's toolbar.
 * @param {string|false}               [attributes.content=browse]        Initial mode for the content region.
 * @param {string|false}               [attributes.toolbar=image-details] Initial mode for the toolbar region.
 * @param {boolean}                    [attributes.describe=true]         Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 * @param {boolean}                    [attributes.displaySettings=true]  Whether to show the attachment display settings interface.
 * @param {boolean}                    [attributes.dragInfo=true]         Whether to show instructional text about the attachments being sortable.
 * @param {int}                        [attributes.idealColumnWidth=170]  The ideal column width in pixels for attachments.
 * @param {boolean}                    [attributes.editing=false]         Whether the gallery is being created, or editing an existing instance.
 * @param {int}                        [attributes.priority=60]           The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.syncSelection=false]   Whether the Attachments selection should be persisted from the last state.
 *                                                                        Defaults to false for this state, because the library passed in  *is* the selection.
 * @param {view}                       [attributes.AttachmentView]        The single `Attachment` view to be used in the `Attachments`.
 *                                                                        If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
 */
var Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
GalleryEdit;

GalleryEdit Library.extend({
    
defaults: {
        
id:               'gallery-edit',
        
title:            l10n.editGalleryTitle,
        
multiple:         false,
        
searchable:       false,
        
sortable:         true,
        
date:             false,
        
display:          false,
        
content:          'browse',
        
toolbar:          'gallery-edit',
        
describe:         true,
        
displaySettings:  true,
        
dragInfo:         true,
        
idealColumnWidth170,
        
editing:          false,
        
priority:         60,
        
syncSelection:    false
    
},

    
/**
     * @since 3.5.0
     */
    
initialize: function() {
        
// If we haven't been provided a `library`, create a `Selection`.
        
if ( ! this.get('library') ) {
            
this.set'library', new wp.media.model.Selection() );
        }

        
// The single `Attachment` view to be used in the `Attachments` view.
        
if ( ! this.get('AttachmentView') ) {
            
this.set'AttachmentView'wp.media.view.Attachment.EditLibrary );
        }

        
Library.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.5.0
     */
    
activate: function() {
        var 
library this.get('library');

        
// Limit the library to images only.
        
library.props.set'type''image' );

        
// Watch for uploaded attachments.
        
this.get('library').observewp.Uploader.queue );

        
this.frame.on'content:render:browse'this.gallerySettingsthis );

        
Library.prototype.activate.applythisarguments );
    },

    
/**
     * @since 3.5.0
     */
    
deactivate: function() {
        
// Stop watching for uploaded attachments.
        
this.get('library').unobservewp.Uploader.queue );

        
this.frame.off'content:render:browse'this.gallerySettingsthis );

        
Library.prototype.deactivate.applythisarguments );
    },

    
/**
     * @since 3.5.0
     *
     * @param browser
     */
    
gallerySettings: function( browser ) {
        if ( ! 
this.get('displaySettings') ) {
            return;
        }

        var 
library this.get('library');

        if ( ! 
library || ! browser ) {
            return;
        }

        
library.gallery library.gallery || new Backbone.Model();

        
browser.sidebar.set({
            
gallery: new wp.media.view.Settings.Gallery({
                
controllerthis,
                
model:      library.gallery,
                
priority:   40
            
})
        });

        
browser.toolbar.set'reverse', {
            
text:     l10n.reverseOrder,
            
priority80,

            
click: function() {
                
library.resetlibrary.toArray().reverse() );
            }
        });
    }
});

module.exports GalleryEdit;

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

/**
 * wp.media.controller.ImageDetails
 *
 * A state for editing the attachment display settings of an image that's been
 * inserted into the editor.
 *
 * @class
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                    [attributes]                       The attributes hash passed to the state.
 * @param {string}                    [attributes.id=image-details]      Unique identifier.
 * @param {string}                    [attributes.title=Image Details]   Title for the state. Displays in the frame's title region.
 * @param {wp.media.model.Attachment} attributes.image                   The image's model.
 * @param {string|false}              [attributes.content=image-details] Initial mode for the content region.
 * @param {string|false}              [attributes.menu=false]            Initial mode for the menu region.
 * @param {string|false}              [attributes.router=false]          Initial mode for the router region.
 * @param {string|false}              [attributes.toolbar=image-details] Initial mode for the toolbar region.
 * @param {boolean}                   [attributes.editing=false]         Unused.
 * @param {int}                       [attributes.priority=60]           Unused.
 *
 * @todo This state inherits some defaults from media.controller.Library.prototype.defaults,
 *       however this may not do anything.
 */
var State wp.media.controller.State,
    
Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
ImageDetails;

ImageDetails State.extend({
    
defaults_.defaults({
        
id:       'image-details',
        
title:    l10n.imageDetailsTitle,
        
content:  'image-details',
        
menu:     false,
        
router:   false,
        
toolbar:  'image-details',
        
editing:  false,
        
priority60
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.9.0
     *
     * @param options Attributes
     */
    
initialize: function( options ) {
        
this.image options.image;
        
State.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        
this.frame.modal.$el.addClass('image-details');
    }
});

module.exports ImageDetails;

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

/**
 * wp.media.controller.Library
 *
 * A state for choosing an attachment or group of attachments from the media library.
 *
 * @class
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 * @mixes media.selectionSync
 *
 * @param {object}                          [attributes]                         The attributes hash passed to the state.
 * @param {string}                          [attributes.id=library]              Unique identifier.
 * @param {string}                          [attributes.title=Media library]     Title for the state. Displays in the media menu and the frame's title region.
 * @param {wp.media.model.Attachments}      [attributes.library]                 The attachments collection to browse.
 *                                                                               If one is not supplied, a collection of all attachments will be created.
 * @param {wp.media.model.Selection|object} [attributes.selection]               A collection to contain attachment selections within the state.
 *                                                                               If the 'selection' attribute is a plain JS object,
 *                                                                               a Selection will be created using its values as the selection instance's `props` model.
 *                                                                               Otherwise, it will copy the library's `props` model.
 * @param {boolean}                         [attributes.multiple=false]          Whether multi-select is enabled.
 * @param {string}                          [attributes.content=upload]          Initial mode for the content region.
 *                                                                               Overridden by persistent user setting if 'contentUserSetting' is true.
 * @param {string}                          [attributes.menu=default]            Initial mode for the menu region.
 * @param {string}                          [attributes.router=browse]           Initial mode for the router region.
 * @param {string}                          [attributes.toolbar=select]          Initial mode for the toolbar region.
 * @param {boolean}                         [attributes.searchable=true]         Whether the library is searchable.
 * @param {boolean|string}                  [attributes.filterable=false]        Whether the library is filterable, and if so what filters should be shown.
 *                                                                               Accepts 'all', 'uploaded', or 'unattached'.
 * @param {boolean}                         [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                         [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
 * @param {boolean}                         [attributes.describe=false]          Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 * @param {boolean}                         [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
 * @param {boolean}                         [attributes.syncSelection=true]      Whether the Attachments selection should be persisted from the last state.
 */
var l10n wp.media.view.l10n,
    
getUserSetting window.getUserSetting,
    
setUserSetting window.setUserSetting,
    
Library;

Library wp.media.controller.State.extend({
    
defaults: {
        
id:                 'library',
        
title:              l10n.mediaLibraryTitle,
        
multiple:           false,
        
content:            'upload',
        
menu:               'default',
        
router:             'browse',
        
toolbar:            'select',
        
searchable:         true,
        
filterable:         false,
        
sortable:           true,
        
autoSelect:         true,
        
describe:           false,
        
contentUserSettingtrue,
        
syncSelection:      true
    
},

    
/**
     * If a library isn't provided, query all media items.
     * If a selection instance isn't provided, create one.
     *
     * @since 3.5.0
     */
    
initialize: function() {
        var 
selection this.get('selection'),
            
props;

        if ( ! 
this.get('library') ) {
            
this.set'library'wp.media.query() );
        }

        if ( ! ( 
selection instanceof wp.media.model.Selection ) ) {
            
props selection;

            if ( ! 
props ) {
                
props this.get('library').props.toJSON();
                
props _.omitprops'orderby''query' );
            }

            
this.set'selection', new wp.media.model.Selectionnull, {
                
multiplethis.get('multiple'),
                
propsprops
            
}) );
        }

        
this.resetDisplays();
    },

    
/**
     * @since 3.5.0
     */
    
activate: function() {
        
this.syncSelection();

        
wp.Uploader.queue.on'add'this.uploadingthis );

        
this.get('selection').on'add remove reset'this.refreshContentthis );

        if ( 
this.get'router' ) && this.get('contentUserSetting') ) {
            
this.frame.on'content:activate'this.saveContentModethis );
            
this.set'content'getUserSetting'libraryContent'this.get('content') ) );
        }
    },

    
/**
     * @since 3.5.0
     */
    
deactivate: function() {
        
this.recordSelection();

        
this.frame.off'content:activate'this.saveContentModethis );

        
// Unbind all event handlers that use this state as the context
        // from the selection.
        
this.get('selection').offnullnullthis );

        
wp.Uploader.queue.offnullnullthis );
    },

    
/**
     * Reset the library to its initial state.
     *
     * @since 3.5.0
     */
    
reset: function() {
        
this.get('selection').reset();
        
this.resetDisplays();
        
this.refreshContent();
    },

    
/**
     * Reset the attachment display settings defaults to the site options.
     *
     * If site options don't define them, fall back to a persistent user setting.
     *
     * @since 3.5.0
     */
    
resetDisplays: function() {
        var 
defaultProps wp.media.view.settings.defaultProps;
        
this._displays = [];
        
this._defaultDisplaySettings = {
            
aligndefaultProps.align || getUserSetting'align''none' ),
            
size:  defaultProps.size  || getUserSetting'imgsize''medium' ),
            
link:  defaultProps.link  || getUserSetting'urlbutton''file' )
        };
    },

    
/**
     * Create a model to represent display settings (alignment, etc.) for an attachment.
     *
     * @since 3.5.0
     *
     * @param {wp.media.model.Attachment} attachment
     * @returns {Backbone.Model}
     */
    
display: function( attachment ) {
        var 
displays this._displays;

        if ( ! 
displaysattachment.cid ] ) {
            
displaysattachment.cid ] = new Backbone.Modelthis.defaultDisplaySettingsattachment ) );
        }
        return 
displaysattachment.cid ];
    },

    
/**
     * Given an attachment, create attachment display settings properties.
     *
     * @since 3.6.0
     *
     * @param {wp.media.model.Attachment} attachment
     * @returns {Object}
     */
    
defaultDisplaySettings: function( attachment ) {
        var 
settings this._defaultDisplaySettings;
        if ( 
settings.canEmbed this.canEmbedattachment ) ) {
            
settings.link 'embed';
        }
        return 
settings;
    },

    
/**
     * Whether an attachment can be embedded (audio or video).
     *
     * @since 3.6.0
     *
     * @param {wp.media.model.Attachment} attachment
     * @returns {Boolean}
     */
    
canEmbed: function( attachment ) {
        
// If uploading, we know the filename but not the mime type.
        
if ( ! attachment.get('uploading') ) {
            var 
type attachment.get('type');
            if ( 
type !== 'audio' && type !== 'video' ) {
                return 
false;
            }
        }

        return 
_.containswp.media.view.settings.embedExtsattachment.get('filename').split('.').pop() );
    },


    
/**
     * If the state is active, no items are selected, and the current
     * content mode is not an option in the state's router (provided
     * the state has a router), reset the content mode to the default.
     *
     * @since 3.5.0
     */
    
refreshContent: function() {
        var 
selection this.get('selection'),
            
frame this.frame,
            
router frame.router.get(),
            
mode frame.content.mode();

        if ( 
this.active && ! selection.length && router && ! router.getmode ) ) {
            
this.frame.content.renderthis.get('content') );
        }
    },

    
/**
     * Callback handler when an attachment is uploaded.
     *
     * Switch to the Media Library if uploaded from the 'Upload Files' tab.
     *
     * Adds any uploading attachments to the selection.
     *
     * If the state only supports one attachment to be selected and multiple
     * attachments are uploaded, the last attachment in the upload queue will
     * be selected.
     *
     * @since 3.5.0
     *
     * @param {wp.media.model.Attachment} attachment
     */
    
uploading: function( attachment ) {
        var 
content this.frame.content;

        if ( 
'upload' === content.mode() ) {
            
this.frame.content.mode('browse');
        }

        if ( 
this.get'autoSelect' ) ) {
            
this.get('selection').addattachment );
            
this.frame.trigger'library:selection:add' );
        }
    },

    
/**
     * Persist the mode of the content region as a user setting.
     *
     * @since 3.5.0
     */
    
saveContentMode: function() {
        if ( 
'browse' !== this.get('router') ) {
            return;
        }

        var 
mode this.frame.content.mode(),
            
view this.frame.router.get();

        if ( 
view && view.getmode ) ) {
            
setUserSetting'libraryContent'mode );
        }
    }
});

// Make selectionSync available on any Media Library state.
_.extendLibrary.prototypewp.media.selectionSync );

module.exports Library;

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

/**
 * wp.media.controller.MediaLibrary
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 */
var Library wp.media.controller.Library,
    
MediaLibrary;

MediaLibrary Library.extend({
    
defaults_.defaults({
        
// Attachments browser defaults. @see media.view.AttachmentsBrowser
        
filterable:      'uploaded',

        
displaySettingsfalse,
        
priority:        80,
        
syncSelection:   false
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.9.0
     *
     * @param options
     */
    
initialize: function( options ) {
        
this.media options.media;
        
this.type options.type;
        
this.set'library'wp.media.query({ typethis.type }) );

        
Library.prototype.initialize.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        
// @todo this should use this.frame.
        
if ( wp.media.frame.lastMime ) {
            
this.set'library'wp.media.query({ typewp.media.frame.lastMime }) );
            
delete wp.media.frame.lastMime;
        }
        
Library.prototype.activate.applythisarguments );
    }
});

module.exports MediaLibrary;

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

/**
 * wp.media.controller.Region
 *
 * A region is a persistent application layout area.
 *
 * A region assumes one mode at any time, and can be switched to another.
 *
 * When mode changes, events are triggered on the region's parent view.
 * The parent view will listen to specific events and fill the region with an
 * appropriate view depending on mode. For example, a frame listens for the
 * 'browse' mode t be activated on the 'content' view and then fills the region
 * with an AttachmentsBrowser view.
 *
 * @class
 *
 * @param {object}        options          Options hash for the region.
 * @param {string}        options.id       Unique identifier for the region.
 * @param {Backbone.View} options.view     A parent view the region exists within.
 * @param {string}        options.selector jQuery selector for the region within the parent view.
 */
var Region = function( options ) {
    
_.extendthis_.pickoptions || {}, 'id''view''selector' ) );
};

// Use Backbone's self-propagating `extend` inheritance method.
Region.extend Backbone.Model.extend;

_.extendRegion.prototype, {
    
/**
     * Activate a mode.
     *
     * @since 3.5.0
     *
     * @param {string} mode
     *
     * @fires this.view#{this.id}:activate:{this._mode}
     * @fires this.view#{this.id}:activate
     * @fires this.view#{this.id}:deactivate:{this._mode}
     * @fires this.view#{this.id}:deactivate
     *
     * @returns {wp.media.controller.Region} Returns itself to allow chaining.
     */
    
mode: function( mode ) {
        if ( ! 
mode ) {
            return 
this._mode;
        }
        
// Bail if we're trying to change to the current mode.
        
if ( mode === this._mode ) {
            return 
this;
        }

        
/**
         * Region mode deactivation event.
         *
         * @event this.view#{this.id}:deactivate:{this._mode}
         * @event this.view#{this.id}:deactivate
         */
        
this.trigger('deactivate');

        
this._mode mode;
        
this.rendermode );

        
/**
         * Region mode activation event.
         *
         * @event this.view#{this.id}:activate:{this._mode}
         * @event this.view#{this.id}:activate
         */
        
this.trigger('activate');
        return 
this;
    },
    
/**
     * Render a mode.
     *
     * @since 3.5.0
     *
     * @param {string} mode
     *
     * @fires this.view#{this.id}:create:{this._mode}
     * @fires this.view#{this.id}:create
     * @fires this.view#{this.id}:render:{this._mode}
     * @fires this.view#{this.id}:render
     *
     * @returns {wp.media.controller.Region} Returns itself to allow chaining
     */
    
render: function( mode ) {
        
// If the mode isn't active, activate it.
        
if ( mode && mode !== this._mode ) {
            return 
this.modemode );
        }

        var 
set = { viewnull },
            
view;

        
/**
         * Create region view event.
         *
         * Region view creation takes place in an event callback on the frame.
         *
         * @event this.view#{this.id}:create:{this._mode}
         * @event this.view#{this.id}:create
         */
        
this.trigger'create'set );
        
view set.view;

        
/**
         * Render region view event.
         *
         * Region view creation takes place in an event callback on the frame.
         *
         * @event this.view#{this.id}:create:{this._mode}
         * @event this.view#{this.id}:create
         */
        
this.trigger'render'view );
        if ( 
view ) {
            
this.setview );
        }
        return 
this;
    },

    
/**
     * Get the region's view.
     *
     * @since 3.5.0
     *
     * @returns {wp.media.View}
     */
    
get: function() {
        return 
this.view.views.firstthis.selector );
    },

    
/**
     * Set the region's view as a subview of the frame.
     *
     * @since 3.5.0
     *
     * @param {Array|Object} views
     * @param {Object} [options={}]
     * @returns {wp.Backbone.Subviews} Subviews is returned to allow chaining
     */
    
set: function( viewsoptions ) {
        if ( 
options ) {
            
options.add false;
        }
        return 
this.view.views.setthis.selectorviewsoptions );
    },

    
/**
     * Trigger regional view events on the frame.
     *
     * @since 3.5.0
     *
     * @param {string} event
     * @returns {undefined|wp.media.controller.Region} Returns itself to allow chaining.
     */
    
trigger: function( event ) {
        var 
baseargs;

        if ( ! 
this._mode ) {
            return;
        }

        
args _.toArrayarguments );
        
base this.id ':' event;

        
// Trigger `{this.id}:{event}:{this._mode}` event on the frame.
        
args[0] = base ':' this._mode;
        
this.view.trigger.applythis.viewargs );

        
// Trigger `{this.id}:{event}` event on the frame.
        
args[0] = base;
        
this.view.trigger.applythis.viewargs );
        return 
this;
    }
});

module.exports Region;

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

/**
 * wp.media.controller.ReplaceImage
 *
 * A state for replacing an image.
 *
 * @class
 * @augments wp.media.controller.Library
 * @augments wp.media.controller.State
 * @augments Backbone.Model
 *
 * @param {object}                     [attributes]                         The attributes hash passed to the state.
 * @param {string}                     [attributes.id=replace-image]        Unique identifier.
 * @param {string}                     [attributes.title=Replace Image]     Title for the state. Displays in the media menu and the frame's title region.
 * @param {wp.media.model.Attachments} [attributes.library]                 The attachments collection to browse.
 *                                                                          If one is not supplied, a collection of all images will be created.
 * @param {boolean}                    [attributes.multiple=false]          Whether multi-select is enabled.
 * @param {string}                     [attributes.content=upload]          Initial mode for the content region.
 *                                                                          Overridden by persistent user setting if 'contentUserSetting' is true.
 * @param {string}                     [attributes.menu=default]            Initial mode for the menu region.
 * @param {string}                     [attributes.router=browse]           Initial mode for the router region.
 * @param {string}                     [attributes.toolbar=replace]         Initial mode for the toolbar region.
 * @param {int}                        [attributes.priority=60]             The priority for the state link in the media menu.
 * @param {boolean}                    [attributes.searchable=true]         Whether the library is searchable.
 * @param {boolean|string}             [attributes.filterable=uploaded]     Whether the library is filterable, and if so what filters should be shown.
 *                                                                          Accepts 'all', 'uploaded', or 'unattached'.
 * @param {boolean}                    [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 * @param {boolean}                    [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
 * @param {boolean}                    [attributes.describe=false]          Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 * @param {boolean}                    [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
 * @param {boolean}                    [attributes.syncSelection=true]      Whether the Attachments selection should be persisted from the last state.
 */
var Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
ReplaceImage;

ReplaceImage Library.extend({
    
defaults_.defaults({
        
id:            'replace-image',
        
title:         l10n.replaceImageTitle,
        
multiple:      false,
        
filterable:    'uploaded',
        
toolbar:       'replace',
        
menu:          false,
        
priority:      60,
        
syncSelectiontrue
    
}, Library.prototype.defaults ),

    
/**
     * @since 3.9.0
     *
     * @param options
     */
    
initialize: function( options ) {
        var 
librarycomparator;

        
this.image options.image;
        
// If we haven't been provided a `library`, create a `Selection`.
        
if ( ! this.get('library') ) {
            
this.set'library'wp.media.query({ type'image' }) );
        }

        
Library.prototype.initialize.applythisarguments );

        
library    this.get('library');
        
comparator library.comparator;

        
// Overload the library's comparator to push items that are not in
        // the mirrored query to the front of the aggregate collection.
        
library.comparator = function( a) {
            var 
aInQuery = !! this.mirroring.geta.cid ),
                
bInQuery = !! this.mirroring.getb.cid );

            if ( ! 
aInQuery && bInQuery ) {
                return -
1;
            } else if ( 
aInQuery && ! bInQuery ) {
                return 
1;
            } else {
                return 
comparator.applythisarguments );
            }
        };

        
// Add all items in the selection to the library, so any featured
        // images that are not initially loaded still appear.
        
library.observethis.get('selection') );
    },

    
/**
     * @since 3.9.0
     */
    
activate: function() {
        
this.updateSelection();
        
Library.prototype.activate.applythisarguments );
    },

    
/**
     * @since 3.9.0
     */
    
updateSelection: function() {
        var 
selection this.get('selection'),
            
attachment this.image.attachment;

        
selection.resetattachment ? [ attachment ] : [] );
    }
});

module.exports ReplaceImage;

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

/**
 * wp.media.controller.StateMachine
 *
 * A state machine keeps track of state. It is in one state at a time,
 * and can change from one state to another.
 *
 * States are stored as models in a Backbone collection.
 *
 * @since 3.5.0
 *
 * @class
 * @augments Backbone.Model
 * @mixin
 * @mixes Backbone.Events
 *
 * @param {Array} states
 */
var StateMachine = function( states ) {
    
// @todo This is dead code. The states collection gets created in media.view.Frame._createStates.
    
this.states = new Backbone.Collectionstates );
};

// Use Backbone's self-propagating `extend` inheritance method.
StateMachine.extend Backbone.Model.extend;

_.extendStateMachine.prototypeBackbone.Events, {
    
/**
     * Fetch a state.
     *
     * If no `id` is provided, returns the active state.
     *
     * Implicitly creates states.
     *
     * Ensure that the `states` collection exists so the `StateMachine`
     *   can be used as a mixin.
     *
     * @since 3.5.0
     *
     * @param {string} id
     * @returns {wp.media.controller.State} Returns a State model
     *   from the StateMachine collection
     */
    
state: function( id ) {
        
this.states this.states || new Backbone.Collection();

        
// Default to the active state.
        
id id || this._state;

        if ( 
id && ! this.states.getid ) ) {
            
this.states.add({ idid });
        }
        return 
this.states.getid );
    },

    
/**
     * Sets the active state.
     *
     * Bail if we're trying to select the current state, if we haven't
     * created the `states` collection, or are trying to select a state
     * that does not exist.
     *
     * @since 3.5.0
     *
     * @param {string} id
     *
     * @fires wp.media.controller.State#deactivate
     * @fires wp.media.controller.State#activate
     *
     * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining
     */
    
setState: function( id ) {
        var 
previous this.state();

        if ( ( 
previous && id === previous.id ) || ! this.states || ! this.states.getid ) ) {
            return 
this;
        }

        if ( 
previous ) {
            
previous.trigger('deactivate');
            
this._lastState previous.id;
        }

        
this._state id;
        
this.state().trigger('activate');

        return 
this;
    },

    
/**
     * Returns the previous active state.
     *
     * Call the `state()` method with no parameters to retrieve the current
     * active state.
     *
     * @since 3.5.0
     *
     * @returns {wp.media.controller.State} Returns a State model
     *    from the StateMachine collection
     */
    
lastState: function() {
        if ( 
this._lastState ) {
            return 
this.statethis._lastState );
        }
    }
});

// Map all event binding and triggering on a StateMachine to its `states` collection.
_.each([ 'on''off''trigger' ], function( method ) {
    
/**
     * @returns {wp.media.controller.StateMachine} Returns itself to allow chaining.
     */
    
StateMachine.prototypemethod ] = function() {
        
// Ensure that the `states` collection exists so the `StateMachine`
        // can be used as a mixin.
        
this.states this.states || new Backbone.Collection();
        
// Forward the method to the `states` collection.
        
this.statesmethod ].applythis.statesarguments );
        return 
this;
    };
});

module.exports StateMachine;

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

/**
 * wp.media.controller.State
 *
 * A state is a step in a workflow that when set will trigger the controllers
 * for the regions to be updated as specified in the frame.
 *
 * A state has an event-driven lifecycle:
 *
 *     'ready'      triggers when a state is added to a state machine's collection.
 *     'activate'   triggers when a state is activated by a state machine.
 *     'deactivate' triggers when a state is deactivated by a state machine.
 *     'reset'      is not triggered automatically. It should be invoked by the
 *                  proper controller to reset the state to its default.
 *
 * @class
 * @augments Backbone.Model
 */
var State Backbone.Model.extend({
    
/**
     * Constructor.
     *
     * @since 3.5.0
     */
    
constructor: function() {
        
this.on'activate'this._preActivatethis );
        
this.on'activate'this.activatethis );
        
this.on'activate'this._postActivatethis );
        
this.on'deactivate'this._deactivatethis );
        
this.on'deactivate'this.deactivatethis );
        
this.on'reset'this.resetthis );
        
this.on'ready'this._readythis );
        
this.on'ready'this.readythis );
        
/**
         * Call parent constructor with passed arguments
         */
        
Backbone.Model.applythisarguments );
        
this.on'change:menu'this._updateMenuthis );
    },
    
/**
     * Ready event callback.
     *
     * @abstract
     * @since 3.5.0
     */
    
ready: function() {},

    
/**
     * Activate event callback.
     *
     * @abstract
     * @since 3.5.0
     */
    
activate: function() {},

    
/**
     * Deactivate event callback.
     *
     * @abstract
     * @since 3.5.0
     */
    
deactivate: function() {},

    
/**
     * Reset event callback.
     *
     * @abstract
     * @since 3.5.0
     */
    
reset: function() {},

    
/**
     * @access private
     * @since 3.5.0
     */
    
_ready: function() {
        
this._updateMenu();
    },

    
/**
     * @access private
     * @since 3.5.0
    */
    
_preActivate: function() {
        
this.active true;
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_postActivate: function() {
        
this.on'change:menu'this._menuthis );
        
this.on'change:titleMode'this._titlethis );
        
this.on'change:content'this._contentthis );
        
this.on'change:toolbar'this._toolbarthis );

        
this.frame.on'title:render:default'this._renderTitlethis );

        
this._title();
        
this._menu();
        
this._toolbar();
        
this._content();
        
this._router();
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_deactivate: function() {
        
this.active false;

        
this.frame.off'title:render:default'this._renderTitlethis );

        
this.off'change:menu'this._menuthis );
        
this.off'change:titleMode'this._titlethis );
        
this.off'change:content'this._contentthis );
        
this.off'change:toolbar'this._toolbarthis );
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_title: function() {
        
this.frame.title.renderthis.get('titleMode') || 'default' );
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_renderTitle: function( view ) {
        
view.$el.textthis.get('title') || '' );
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_router: function() {
        var 
router this.frame.router,
            
mode this.get('router'),
            
view;

        
this.frame.$el.toggleClass'hide-router', ! mode );
        if ( ! 
mode ) {
            return;
        }

        
this.frame.router.rendermode );

        
view router.get();
        if ( 
view && view.select ) {
            
view.selectthis.frame.content.mode() );
        }
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_menu: function() {
        var 
menu this.frame.menu,
            
mode this.get('menu'),
            
view;

        
this.frame.$el.toggleClass'hide-menu', ! mode );
        if ( ! 
mode ) {
            return;
        }

        
menu.modemode );

        
view menu.get();
        if ( 
view && view.select ) {
            
view.selectthis.id );
        }
    },

    
/**
     * @access private
     * @since 3.5.0
     */
    
_updateMenu: function() {
        var 
previous this.previous('menu'),
            
menu this.get('menu');

        if ( 
previous ) {
            
this.frame.off'menu:render:' previousthis._renderMenuthis );
        }

        if ( 
menu ) {
            
this.frame.on'menu:render:' menuthis._renderMenuthis );
        }
    },

    
/**
     * Create a view in the media menu for the state.
     *
     * @access private
     * @since 3.5.0
     *
     * @param {media.view.Menu} view The menu view.
     */
    
_renderMenu: function( view ) {
        var 
menuItem this.get('menuItem'),
            
title this.get('title'),
            
priority this.get('priority');

        if ( ! 
menuItem && title ) {
            
menuItem = { texttitle };

            if ( 
priority ) {
                
menuItem.priority priority;
            }
        }

        if ( ! 
menuItem ) {
            return;
        }

        
view.setthis.idmenuItem );
    }
});

_.each(['toolbar','content'], function( region ) {
    
/**
     * @access private
     */
    
State.prototype'_' region ] = function() {
        var 
mode this.getregion );
        if ( 
mode ) {
            
this.frameregion ].rendermode );
        }
    };
});

module.exports State;

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

/**
 * wp.media.selectionSync
 *
 * Sync an attachments selection in a state with another state.
 *
 * Allows for selecting multiple images in the Insert Media workflow, and then
 * switching to the Insert Gallery workflow while preserving the attachments selection.
 *
 * @mixin
 */
var selectionSync = {
    
/**
     * @since 3.5.0
     */
    
syncSelection: function() {
        var 
selection this.get('selection'),
            
manager this.frame._selection;

        if ( ! 
this.get('syncSelection') || ! manager || ! selection ) {
            return;
        }

        
// If the selection supports multiple items, validate the stored
        // attachments based on the new selection's conditions. Record
        // the attachments that are not included; we'll maintain a
        // reference to those. Other attachments are considered in flux.
        
if ( selection.multiple ) {
            
selection.reset( [], { silenttrue });
            
selection.validateAllmanager.attachments );
            
manager.difference _.differencemanager.attachments.modelsselection.models );
        }

        
// Sync the selection's single item with the master.
        
selection.singlemanager.single );
    },

    
/**
     * Record the currently active attachments, which is a combination
     * of the selection's attachments and the set of selected
     * attachments that this specific selection considered invalid.
     * Reset the difference and record the single attachment.
     *
     * @since 3.5.0
     */
    
recordSelection: function() {
        var 
selection this.get('selection'),
            
manager this.frame._selection;

        if ( ! 
this.get('syncSelection') || ! manager || ! selection ) {
            return;
        }

        if ( 
selection.multiple ) {
            
manager.attachments.resetselection.toArray().concatmanager.difference ) );
            
manager.difference = [];
        } else {
            
manager.attachments.addselection.toArray() );
        }

        
manager.single selection._single;
    }
};

module.exports selectionSync;

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

var media wp.media,
    $ = 
jQuery,
    
l10n;

media.isTouchDevice = ( 'ontouchend' in document );

// Link any localized strings.
l10n media.view.l10n window._wpMediaViewsL10n || {};

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

// Copy the `post` setting over to the model settings.
media.model.settings.post media.view.settings.post;

// Check if the browser supports CSS 3.0 transitions
$.support.transition = (function(){
    var 
style document.documentElement.style,
        
transitions = {
            
WebkitTransition'webkitTransitionEnd',
            
MozTransition:    'transitionend',
            
OTransition:      'oTransitionEnd otransitionend',
            
transition:       'transitionend'
        
}, transition;

    
transition _.find_.keystransitions ), function( transition ) {
        return ! 
_.isUndefinedstyletransition ] );
    });

    return 
transition && {
        
endtransitionstransition ]
    };
}());

/**
 * A shared event bus used to provide events into
 * the media workflows that 3rd-party devs can use to hook
 * in.
 */
media.events _.extend( {}, Backbone.Events );

/**
 * Makes it easier to bind events using transitions.
 *
 * @param {string} selector
 * @param {Number} sensitivity
 * @returns {Promise}
 */
media.transition = function( selectorsensitivity ) {
    var 
deferred = $.Deferred();

    
sensitivity sensitivity || 2000;

    if ( $.
support.transition ) {
        if ( ! (
selector instanceof $) ) {
            
selector = $( selector );
        }

        
// Resolve the deferred when the first element finishes animating.
        
selector.first().one( $.support.transition.enddeferred.resolve );

        
// Just in case the event doesn't trigger, fire a callback.
        
_.delaydeferred.resolvesensitivity );

    
// Otherwise, execute on the spot.
    
} else {
        
deferred.resolve();
    }

    return 
deferred.promise();
};

media.controller.Region = require( './controllers/region.js' );
media.controller.StateMachine = require( './controllers/state-machine.js' );
media.controller.State = require( './controllers/state.js' );

media.selectionSync = require( './utils/selection-sync.js' );
media.controller.Library = require( './controllers/library.js' );
media.controller.ImageDetails = require( './controllers/image-details.js' );
media.controller.GalleryEdit = require( './controllers/gallery-edit.js' );
media.controller.GalleryAdd = require( './controllers/gallery-add.js' );
media.controller.CollectionEdit = require( './controllers/collection-edit.js' );
media.controller.CollectionAdd = require( './controllers/collection-add.js' );
media.controller.FeaturedImage = require( './controllers/featured-image.js' );
media.controller.ReplaceImage = require( './controllers/replace-image.js' );
media.controller.EditImage = require( './controllers/edit-image.js' );
media.controller.MediaLibrary = require( './controllers/media-library.js' );
media.controller.Embed = require( './controllers/embed.js' );
media.controller.Cropper = require( './controllers/cropper.js' );

media.View = require( './views/view.js' );
media.view.Frame = require( './views/frame.js' );
media.view.MediaFrame = require( './views/media-frame.js' );
media.view.MediaFrame.Select = require( './views/frame/select.js' );
media.view.MediaFrame.Post = require( './views/frame/post.js' );
media.view.MediaFrame.ImageDetails = require( './views/frame/image-details.js' );
media.view.Modal = require( './views/modal.js' );
media.view.FocusManager = require( './views/focus-manager.js' );
media.view.UploaderWindow = require( './views/uploader/window.js' );
media.view.EditorUploader = require( './views/uploader/editor.js' );
media.view.UploaderInline = require( './views/uploader/inline.js' );
media.view.UploaderStatus = require( './views/uploader/status.js' );
media.view.UploaderStatusError = require( './views/uploader/status-error.js' );
media.view.Toolbar = require( './views/toolbar.js' );
media.view.Toolbar.Select = require( './views/toolbar/select.js' );
media.view.Toolbar.Embed = require( './views/toolbar/embed.js' );
media.view.Button = require( './views/button.js' );
media.view.ButtonGroup = require( './views/button-group.js' );
media.view.PriorityList = require( './views/priority-list.js' );
media.view.MenuItem = require( './views/menu-item.js' );
media.view.Menu = require( './views/menu.js' );
media.view.RouterItem = require( './views/router-item.js' );
media.view.Router = require( './views/router.js' );
media.view.Sidebar = require( './views/sidebar.js' );
media.view.Attachment = require( './views/attachment.js' );
media.view.Attachment.Library = require( './views/attachment/library.js' );
media.view.Attachment.EditLibrary = require( './views/attachment/edit-library.js' );
media.view.Attachments = require( './views/attachments.js' );
media.view.Search = require( './views/search.js' );
media.view.AttachmentFilters = require( './views/attachment-filters.js' );
media.view.DateFilter = require( './views/attachment-filters/date.js' );
media.view.AttachmentFilters.Uploaded = require( './views/attachment-filters/uploaded.js' );
media.view.AttachmentFilters.All = require( './views/attachment-filters/all.js' );
media.view.AttachmentsBrowser = require( './views/attachments/browser.js' );
media.view.Selection = require( './views/selection.js' );
media.view.Attachment.Selection = require( './views/attachment/selection.js' );
media.view.Attachments.Selection = require( './views/attachments/selection.js' );
media.view.Attachment.EditSelection = require( './views/attachment/edit-selection.js' );
media.view.Settings = require( './views/settings.js' );
media.view.Settings.AttachmentDisplay = require( './views/settings/attachment-display.js' );
media.view.Settings.Gallery = require( './views/settings/gallery.js' );
media.view.Settings.Playlist = require( './views/settings/playlist.js' );
media.view.Attachment.Details = require( './views/attachment/details.js' );
media.view.AttachmentCompat = require( './views/attachment-compat.js' );
media.view.Iframe = require( './views/iframe.js' );
media.view.Embed = require( './views/embed.js' );
media.view.Label = require( './views/label.js' );
media.view.EmbedUrl = require( './views/embed/url.js' );
media.view.EmbedLink = require( './views/embed/link.js' );
media.view.EmbedImage = require( './views/embed/image.js' );
media.view.ImageDetails = require( './views/image-details.js' );
media.view.Cropper = require( './views/cropper.js' );
media.view.EditImage = require( './views/edit-image.js' );
media.view.Spinner = require( './views/spinner.js' );

},{
"./controllers/collection-add.js":1,"./controllers/collection-edit.js":2,"./controllers/cropper.js":3,"./controllers/edit-image.js":4,"./controllers/embed.js":5,"./controllers/featured-image.js":6,"./controllers/gallery-add.js":7,"./controllers/gallery-edit.js":8,"./controllers/image-details.js":9,"./controllers/library.js":10,"./controllers/media-library.js":11,"./controllers/region.js":12,"./controllers/replace-image.js":13,"./controllers/state-machine.js":14,"./controllers/state.js":15,"./utils/selection-sync.js":16,"./views/attachment-compat.js":18,"./views/attachment-filters.js":19,"./views/attachment-filters/all.js":20,"./views/attachment-filters/date.js":21,"./views/attachment-filters/uploaded.js":22,"./views/attachment.js":23,"./views/attachment/details.js":24,"./views/attachment/edit-library.js":25,"./views/attachment/edit-selection.js":26,"./views/attachment/library.js":27,"./views/attachment/selection.js":28,"./views/attachments.js":29,"./views/attachments/browser.js":30,"./views/attachments/selection.js":31,"./views/button-group.js":32,"./views/button.js":33,"./views/cropper.js":34,"./views/edit-image.js":35,"./views/embed.js":36,"./views/embed/image.js":37,"./views/embed/link.js":38,"./views/embed/url.js":39,"./views/focus-manager.js":40,"./views/frame.js":41,"./views/frame/image-details.js":42,"./views/frame/post.js":43,"./views/frame/select.js":44,"./views/iframe.js":45,"./views/image-details.js":46,"./views/label.js":47,"./views/media-frame.js":48,"./views/menu-item.js":49,"./views/menu.js":50,"./views/modal.js":51,"./views/priority-list.js":52,"./views/router-item.js":53,"./views/router.js":54,"./views/search.js":55,"./views/selection.js":56,"./views/settings.js":57,"./views/settings/attachment-display.js":58,"./views/settings/gallery.js":59,"./views/settings/playlist.js":60,"./views/sidebar.js":61,"./views/spinner.js":62,"./views/toolbar.js":63,"./views/toolbar/embed.js":64,"./views/toolbar/select.js":65,"./views/uploader/editor.js":66,"./views/uploader/inline.js":67,"./views/uploader/status-error.js":68,"./views/uploader/status.js":69,"./views/uploader/window.js":70,"./views/view.js":71}],18:[function(require,module,exports){
/*globals _ */

/**
 * wp.media.view.AttachmentCompat
 *
 * A view to display fields added via the `attachment_fields_to_edit` filter.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
AttachmentCompat;

AttachmentCompat View.extend({
    
tagName:   'form',
    
className'compat-item',

    
events: {
        
'submit':          'preventDefault',
        
'change input':    'save',
        
'change select':   'save',
        
'change textarea''save'
    
},

    
initialize: function() {
        
this.listenTothis.model'change:compat'this.render );
    },
    
/**
     * @returns {wp.media.view.AttachmentCompat} Returns itself to allow chaining
     */
    
dispose: function() {
        if ( 
this.$(':focus').length ) {
            
this.save();
        }
        
/**
         * call 'dispose' directly on the parent class
         */
        
return View.prototype.dispose.applythisarguments );
    },
    
/**
     * @returns {wp.media.view.AttachmentCompat} Returns itself to allow chaining
     */
    
render: function() {
        var 
compat this.model.get('compat');
        if ( ! 
compat || ! compat.item ) {
            return;
        }

        
this.views.detach();
        
this.$el.htmlcompat.item );
        
this.views.render();
        return 
this;
    },
    
/**
     * @param {Object} event
     */
    
preventDefault: function( event ) {
        
event.preventDefault();
    },
    
/**
     * @param {Object} event
     */
    
save: function( event ) {
        var 
data = {};

        if ( 
event ) {
            
event.preventDefault();
        }

        
_.eachthis.$el.serializeArray(), function( pair ) {
            
datapair.name ] = pair.value;
        });

        
this.controller.trigger'attachment:compat:waiting', ['waiting'] );
        
this.model.saveCompatdata ).always_.bindthis.postSavethis ) );
    },

    
postSave: function() {
        
this.controller.trigger'attachment:compat:ready', ['ready'] );
    }
});

module.exports AttachmentCompat;

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

/**
 * wp.media.view.AttachmentFilters
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var $ = jQuery,
    
AttachmentFilters;

AttachmentFilters wp.media.View.extend({
    
tagName:   'select',
    
className'attachment-filters',
    
id:        'media-attachment-filters',

    
events: {
        
change'change'
    
},

    
keys: [],

    
initialize: function() {
        
this.createFilters();
        
_.extendthis.filtersthis.options.filters );

        
// Build `<option>` elements.
        
this.$el.html_.chainthis.filters ).map( function( filtervalue ) {
            return {
                
el: $( '<option></option>' ).valvalue ).htmlfilter.text )[0],
                
priorityfilter.priority || 50
            
};
        }, 
this ).sortBy('priority').pluck('el').value() );

        
this.listenTothis.model'change'this.select );
        
this.select();
    },

    
/**
     * @abstract
     */
    
createFilters: function() {
        
this.filters = {};
    },

    
/**
     * When the selected filter changes, update the Attachment Query properties to match.
     */
    
change: function() {
        var 
filter this.filtersthis.el.value ];
        if ( 
filter ) {
            
this.model.setfilter.props );
        }
    },

    
select: function() {
        var 
model this.model,
            
value 'all',
            
props model.toJSON();

        
_.findthis.filters, function( filterid ) {
            var 
equal _.allfilter.props, function( propkey ) {
                return 
prop === ( _.isUndefinedpropskey ] ) ? null propskey ] );
            });

            if ( 
equal ) {
                return 
value id;
            }
        });

        
this.$el.valvalue );
    }
});

module.exports AttachmentFilters;

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

/**
 * wp.media.view.AttachmentFilters.All
 *
 * @class
 * @augments wp.media.view.AttachmentFilters
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var l10n wp.media.view.l10n,
    
All;

All wp.media.view.AttachmentFilters.extend({
    
createFilters: function() {
        var 
filters = {};

        
_.eachwp.media.view.settings.mimeTypes || {}, function( textkey ) {
            
filterskey ] = {
                
texttext,
                
props: {
                    
status:  null,
                    
type:    key,
                    
uploadedTonull,
                    
orderby'date',
                    
order:   'DESC'
                
}
            };
        });

        
filters.all = {
            
text:  l10n.allMediaItems,
            
props: {
                
status:  null,
                
type:    null,
                
uploadedTonull,
                
orderby'date',
                
order:   'DESC'
            
},
            
priority10
        
};

        if ( 
wp.media.view.settings.post.id ) {
            
filters.uploaded = {
                
text:  l10n.uploadedToThisPost,
                
props: {
                    
status:  null,
                    
type:    null,
                    
uploadedTowp.media.view.settings.post.id,
                    
orderby'menuOrder',
                    
order:   'ASC'
                
},
                
priority20
            
};
        }

        
filters.unattached = {
            
text:  l10n.unattached,
            
props: {
                
status:     null,
                
uploadedTo0,
                
type:       null,
                
orderby:    'menuOrder',
                
order:      'ASC'
            
},
            
priority50
        
};

        if ( 
wp.media.view.settings.mediaTrash &&
            
this.controller.isModeActive'grid' ) ) {

            
filters.trash = {
                
text:  l10n.trash,
                
props: {
                    
uploadedTonull,
                    
status:     'trash',
                    
type:       null,
                    
orderby:    'date',
                    
order:      'DESC'
                
},
                
priority50
            
};
        }

        
this.filters filters;
    }
});

module.exports All;

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

/**
 * A filter dropdown for month/dates.
 *
 * @class
 * @augments wp.media.view.AttachmentFilters
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var l10n wp.media.view.l10n,
    
DateFilter;

DateFilter wp.media.view.AttachmentFilters.extend({
    
id'media-attachment-date-filters',

    
createFilters: function() {
        var 
filters = {};
        
_.eachwp.media.view.settings.months || {}, function( valueindex ) {
            
filtersindex ] = {
                
textvalue.text,
                
props: {
                    
yearvalue.year,
                    
monthnumvalue.month
                
}
            };
        });
        
filters.all = {
            
text:  l10n.allDates,
            
props: {
                
monthnumfalse,
                
year:  false
            
},
            
priority10
        
};
        
this.filters filters;
    }
});

module.exports DateFilter;

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

/**
 * wp.media.view.AttachmentFilters.Uploaded
 *
 * @class
 * @augments wp.media.view.AttachmentFilters
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var l10n wp.media.view.l10n,
    
Uploaded;

Uploaded wp.media.view.AttachmentFilters.extend({
    
createFilters: function() {
        var 
type this.model.get('type'),
            
types wp.media.view.settings.mimeTypes,
            
text;

        if ( 
types && type ) {
            
text typestype ];
        }

        
this.filters = {
            
all: {
                
text:  text || l10n.allMediaItems,
                
props: {
                    
uploadedTonull,
                    
orderby'date',
                    
order:   'DESC'
                
},
                
priority10
            
},

            
uploaded: {
                
text:  l10n.uploadedToThisPost,
                
props: {
                    
uploadedTowp.media.view.settings.post.id,
                    
orderby'menuOrder',
                    
order:   'ASC'
                
},
                
priority20
            
},

            
unattached: {
                
text:  l10n.unattached,
                
props: {
                    
uploadedTo0,
                    
orderby'menuOrder',
                    
order:   'ASC'
                
},
                
priority50
            
}
        };
    }
});

module.exports Uploaded;

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

/**
 * wp.media.view.Attachment
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    $ = 
jQuery,
    
Attachment;

Attachment View.extend({
    
tagName:   'li',
    
className'attachment',
    
template:  wp.template('attachment'),

    
attributes: function() {
        return {
            
'tabIndex':     0,
            
'role':         'checkbox',
            
'aria-label':   this.model.get'title' ),
            
'aria-checked'false,
            
'data-id':      this.model.get'id' )
        };
    },

    
events: {
        
'click .js--select-attachment':   'toggleSelectionHandler',
        
'change [data-setting]':          'updateSetting',
        
'change [data-setting] input':    'updateSetting',
        
'change [data-setting] select':   'updateSetting',
        
'change [data-setting] textarea''updateSetting',
        
'click .close':                   'removeFromLibrary',
        
'click .check':                   'checkClickHandler',
        
'click a':                        'preventDefault',
        
'keydown .close':                 'removeFromLibrary',
        
'keydown':                        'toggleSelectionHandler'
    
},

    
buttons: {},

    
initialize: function() {
        var 
selection this.options.selection,
            
options _.defaultsthis.options, {
                
rerenderOnModelChangetrue
            
} );

        if ( 
options.rerenderOnModelChange ) {
            
this.listenTothis.model'change'this.render );
        } else {
            
this.listenTothis.model'change:percent'this.progress );
        }
        
this.listenTothis.model'change:title'this._syncTitle );
        
this.listenTothis.model'change:caption'this._syncCaption );
        
this.listenTothis.model'change:artist'this._syncArtist );
        
this.listenTothis.model'change:album'this._syncAlbum );

        
// Update the selection.
        
this.listenTothis.model'add'this.select );
        
this.listenTothis.model'remove'this.deselect );
        if ( 
selection ) {
            
selection.on'reset'this.updateSelectthis );
            
// Update the model's details view.
            
this.listenTothis.model'selection:single selection:unsingle'this.details );
            
this.detailsthis.modelthis.controller.state().get('selection') );
        }

        
this.listenTothis.controller'attachment:compat:waiting attachment:compat:ready'this.updateSave );
    },
    
/**
     * @returns {wp.media.view.Attachment} Returns itself to allow chaining
     */
    
dispose: function() {
        var 
selection this.options.selection;

        
// Make sure all settings are saved before removing the view.
        
this.updateAll();

        if ( 
selection ) {
            
selection.offnullnullthis );
        }
        
/**
         * call 'dispose' directly on the parent class
         */
        
View.prototype.dispose.applythisarguments );
        return 
this;
    },
    
/**
     * @returns {wp.media.view.Attachment} Returns itself to allow chaining
     */
    
render: function() {
        var 
options _.defaultsthis.model.toJSON(), {
                
orientation:   'landscape',
                
uploading:     false,
                
type:          '',
                
subtype:       '',
                
icon:          '',
                
filename:      '',
                
caption:       '',
                
title:         '',
                
dateFormatted'',
                
width:         '',
                
height:        '',
                
compat:        false,
                
alt:           '',
                
description:   ''
            
}, this.options );

        
options.buttons  this.buttons;
        
options.describe this.controller.state().get('describe');

        if ( 
'image' === options.type ) {
            
options.size this.imageSize();
        }

        
options.can = {};
        if ( 
options.nonces ) {
            
options.can.remove = !! options.nonces['delete'];
            
options.can.save = !! options.nonces.update;
        }

        if ( 
this.controller.state().get('allowLocalEdits') ) {
            
options.allowLocalEdits true;
        }

        if ( 
options.uploading && ! options.percent ) {
            
options.percent 0;
        }

        
this.views.detach();
        
this.$el.htmlthis.templateoptions ) );

        
this.$el.toggleClass'uploading'options.uploading );

        if ( 
options.uploading ) {
            
this.$bar this.$('.media-progress-bar div');
        } else {
            
delete this.$bar;
        }

        
// Check if the model is selected.
        
this.updateSelect();

        
// Update the save status.
        
this.updateSave();

        
this.views.render();

        return 
this;
    },

    
progress: function() {
        if ( 
this.$bar && this.$bar.length ) {
            
this.$bar.widththis.model.get('percent') + '%' );
        }
    },

    
/**
     * @param {Object} event
     */
    
toggleSelectionHandler: function( event ) {
        var 
method;

        
// Don't do anything inside inputs.
        
if ( 'INPUT' === event.target.nodeName ) {
            return;
        }

        
// Catch arrow events
        
if ( 37 === event.keyCode || 38 === event.keyCode || 39 === event.keyCode || 40 === event.keyCode ) {
            
this.controller.trigger'attachment:keydown:arrow'event );
            return;
        }

        
// Catch enter and space events
        
if ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {
            return;
        }

        
event.preventDefault();

        
// In the grid view, bubble up an edit:attachment event to the controller.
        
if ( this.controller.isModeActive'grid' ) ) {
            if ( 
this.controller.isModeActive'edit' ) ) {
                
// Pass the current target to restore focus when closing
                
this.controller.trigger'edit:attachment'this.modelevent.currentTarget );
                return;
            }

            if ( 
this.controller.isModeActive'select' ) ) {
                
method 'toggle';
            }
        }

        if ( 
event.shiftKey ) {
            
method 'between';
        } else if ( 
event.ctrlKey || event.metaKey ) {
            
method 'toggle';
        }

        
this.toggleSelection({
            
methodmethod
        
});

        
this.controller.trigger'selection:toggle' );
    },
    
/**
     * @param {Object} options
     */
    
toggleSelection: function( options ) {
        var 
collection this.collection,
            
selection this.options.selection,
            
model this.model,
            
method options && options.method,
            
singlemodelssingleIndexmodelIndex;

        if ( ! 
selection ) {
            return;
        }

        
single selection.single();
        
method _.isUndefinedmethod ) ? selection.multiple method;

        
// If the `method` is set to `between`, select all models that
        // exist between the current and the selected model.
        
if ( 'between' === method && single && selection.multiple ) {
            
// If the models are the same, short-circuit.
            
if ( single === model ) {
                return;
            }

            
singleIndex collection.indexOfsingle );
            
modelIndex  collection.indexOfthis.model );

            if ( 
singleIndex modelIndex ) {
                
models collection.models.slicesingleIndexmodelIndex );
            } else {
                
models collection.models.slicemodelIndexsingleIndex );
            }

            
selection.addmodels );
            
selection.singlemodel );
            return;

        
// If the `method` is set to `toggle`, just flip the selection
        // status, regardless of whether the model is the single model.
        
} else if ( 'toggle' === method ) {
            
selectionthis.selected() ? 'remove' 'add' ]( model );
            
selection.singlemodel );
            return;
        } else if ( 
'add' === method ) {
            
selection.addmodel );
            
selection.singlemodel );
            return;
        }

        
// Fixes bug that loses focus when selecting a featured image
        
if ( ! method ) {
            
method 'add';
        }

        if ( 
method !== 'add' ) {
            
method 'reset';
        }

        if ( 
this.selected() ) {
            
// If the model is the single model, remove it.
            // If it is not the same as the single model,
            // it now becomes the single model.
            
selectionsingle === model 'remove' 'single' ]( model );
        } else {
            
// If the model is not selected, run the `method` on the
            // selection. By default, we `reset` the selection, but the
            // `method` can be set to `add` the model to the selection.
            
selectionmethod ]( model );
            
selection.singlemodel );
        }
    },

    
updateSelect: function() {
        
thisthis.selected() ? 'select' 'deselect' ]();
    },
    
/**
     * @returns {unresolved|Boolean}
     */
    
selected: function() {
        var 
selection this.options.selection;
        if ( 
selection ) {
            return !! 
selection.getthis.model.cid );
        }
    },
    
/**
     * @param {Backbone.Model} model
     * @param {Backbone.Collection} collection
     */
    
select: function( modelcollection ) {
        var 
selection this.options.selection,
            
controller this.controller;

        
// Check if a selection exists and if it's the collection provided.
        // If they're not the same collection, bail; we're in another
        // selection's event loop.
        
if ( ! selection || ( collection && collection !== selection ) ) {
            return;
        }

        
// Bail if the model is already selected.
        
if ( this.$el.hasClass'selected' ) ) {
            return;
        }

        
// Add 'selected' class to model, set aria-checked to true.
        
this.$el.addClass'selected' ).attr'aria-checked'true );
        
//  Make the checkbox tabable, except in media grid (bulk select mode).
        
if ( ! ( controller.isModeActive'grid' ) && controller.isModeActive'select' ) ) ) {
            
this.$( '.check' ).attr'tabindex''0' );
        }
    },
    
/**
     * @param {Backbone.Model} model
     * @param {Backbone.Collection} collection
     */
    
deselect: function( modelcollection ) {
        var 
selection this.options.selection;

        
// Check if a selection exists and if it's the collection provided.
        // If they're not the same collection, bail; we're in another
        // selection's event loop.
        
if ( ! selection || ( collection && collection !== selection ) ) {
            return;
        }
        
this.$el.removeClass'selected' ).attr'aria-checked'false )
            .
find'.check' ).attr'tabindex''-1' );
    },
    
/**
     * @param {Backbone.Model} model
     * @param {Backbone.Collection} collection
     */
    
details: function( modelcollection ) {
        var 
selection this.options.selection,
            
details;

        if ( 
selection !== collection ) {
            return;
        }

        
details selection.single();
        
this.$el.toggleClass'details'details === this.model );
    },
    
/**
     * @param {Object} event
     */
    
preventDefault: function( event ) {
        
event.preventDefault();
    },
    
/**
     * @param {string} size
     * @returns {Object}
     */
    
imageSize: function( size ) {
        var 
sizes this.model.get('sizes'), matched false;

        
size size || 'medium';

        
// Use the provided image size if possible.
        
if ( sizes ) {
            if ( 
sizessize ] ) {
                
matched sizessize ];
            } else if ( 
sizes.large ) {
                
matched sizes.large;
            } else if ( 
sizes.thumbnail ) {
                
matched sizes.thumbnail;
            } else if ( 
sizes.full ) {
                
matched sizes.full;
            }

            if ( 
matched ) {
                return 
_.clone( matched );
            }
        }

        return {
            
url:         this.model.get('url'),
            
width:       this.model.get('width'),
            
height:      this.model.get('height'),
            
orientationthis.model.get('orientation')
        };
    },
    
/**
     * @param {Object} event
     */
    
updateSetting: function( event ) {
        var 
$setting = $( event.target ).closest('[data-setting]'),
            
settingvalue;

        if ( ! 
$setting.length ) {
            return;
        }

        
setting $setting.data('setting');
        
value   event.target.value;

        if ( 
this.model.getsetting ) !== value ) {
            
this.savesettingvalue );
        }
    },

    
/**
     * Pass all the arguments to the model's save method.
     *
     * Records the aggregate status of all save requests and updates the
     * view's classes accordingly.
     */
    
save: function() {
        var 
view this,
            
save this._save this._save || { status'ready' },
            
request this.model.save.applythis.modelarguments ),
            
requests save.requests ? $.whenrequestsave.requests ) : request;

        
// If we're waiting to remove 'Saved.', stop.
        
if ( save.savedTimer ) {
            
clearTimeoutsave.savedTimer );
        }

        
this.updateSave('waiting');
        
save.requests requests;
        
requests.always( function() {
            
// If we've performed another request since this one, bail.
            
if ( save.requests !== requests ) {
                return;
            }

            
view.updateSaverequests.state() === 'resolved' 'complete' 'error' );
            
save.savedTimer setTimeout( function() {
                
view.updateSave('ready');
                
delete save.savedTimer;
            }, 
2000 );
        });
    },
    
/**
     * @param {string} status
     * @returns {wp.media.view.Attachment} Returns itself to allow chaining
     */
    
updateSave: function( status ) {
        var 
save this._save this._save || { status'ready' };

        if ( 
status && status !== save.status ) {
            
this.$el.removeClass'save-' save.status );
            
save.status status;
        }

        
this.$el.addClass'save-' save.status );
        return 
this;
    },

    
updateAll: function() {
        var 
$settings this.$('[data-setting]'),
            
model this.model,
            
changed;

        
changed _.chain$settings ).map( function( el ) {
            var 
$input = $('input, textarea, select, [value]'el ),
                
settingvalue;

            if ( ! 
$input.length ) {
                return;
            }

            
setting = $(el).data('setting');
            
value $input.val();

            
// Record the value if it changed.
            
if ( model.getsetting ) !== value ) {
                return [ 
settingvalue ];
            }
        }).
compact().object().value();

        if ( ! 
_.isEmptychanged ) ) {
            
model.savechanged );
        }
    },
    
/**
     * @param {Object} event
     */
    
removeFromLibrary: function( event ) {
        
// Catch enter and space events
        
if ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {
            return;
        }

        
// Stop propagation so the model isn't selected.
        
event.stopPropagation();

        
this.collection.removethis.model );
    },

    
/**
     * Add the model if it isn't in the selection, if it is in the selection,
     * remove it.
     *
     * @param  {[type]} event [description]
     * @return {[type]}       [description]
     */
    
checkClickHandler: function ( event ) {
        var 
selection this.options.selection;
        if ( ! 
selection ) {
            return;
        }
        
event.stopPropagation();
        if ( 
selection.where( { idthis.model.get'id' ) } ).length ) {
            
selection.removethis.model );
            
// Move focus back to the attachment tile (from the check).
            
this.$el.focus();
        } else {
            
selection.addthis.model );
        }
    }
});

// Ensure settings remain in sync between attachment views.
_.each({
    
caption'_syncCaption',
    
title:   '_syncTitle',
    
artist:  '_syncArtist',
    
album:   '_syncAlbum'
}, function( methodsetting ) {
    
/**
     * @param {Backbone.Model} model
     * @param {string} value
     * @returns {wp.media.view.Attachment} Returns itself to allow chaining
     */
    
Attachment.prototypemethod ] = function( modelvalue ) {
        var 
$setting this.$('[data-setting="' setting '"]');

        if ( ! 
$setting.length ) {
            return 
this;
        }

        
// If the updated value is in sync with the value in the DOM, there
        // is no need to re-render. If we're currently editing the value,
        // it will automatically be in sync, suppressing the re-render for
        // the view we're editing, while updating any others.
        
if ( value === $setting.find('input, textarea, select, [value]').val() ) {
            return 
this;
        }

        return 
this.render();
    };
});

module.exports Attachment;

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

/**
 * wp.media.view.Attachment.Details
 *
 * @class
 * @augments wp.media.view.Attachment
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Attachment wp.media.view.Attachment,
    
l10n wp.media.view.l10n,
    
Details;

Details Attachment.extend({
    
tagName:   'div',
    
className'attachment-details',
    
template:  wp.template('attachment-details'),

    
attributes: function() {
        return {
            
'tabIndex':     0,
            
'data-id':      this.model.get'id' )
        };
    },

    
events: {
        
'change [data-setting]':          'updateSetting',
        
'change [data-setting] input':    'updateSetting',
        
'change [data-setting] select':   'updateSetting',
        
'change [data-setting] textarea''updateSetting',
        
'click .delete-attachment':       'deleteAttachment',
        
'click .trash-attachment':        'trashAttachment',
        
'click .untrash-attachment':      'untrashAttachment',
        
'click .edit-attachment':         'editAttachment',
        
'click .refresh-attachment':      'refreshAttachment',
        
'keydown':                        'toggleSelectionHandler'
    
},

    
initialize: function() {
        
this.options _.defaultsthis.options, {
            
rerenderOnModelChangefalse
        
});

        
this.on'ready'this.initialFocus );
        
// Call 'initialize' directly on the parent class.
        
Attachment.prototype.initialize.applythisarguments );
    },

    
initialFocus: function() {
        if ( ! 
wp.media.isTouchDevice ) {
            
this.$( ':input' ).eq).focus();
        }
    },
    
/**
     * @param {Object} event
     */
    
deleteAttachment: function( event ) {
        
event.preventDefault();

        if ( 
window.confirml10n.warnDelete ) ) {
            
this.model.destroy();
            
// Keep focus inside media modal
            // after image is deleted
            
this.controller.modal.focusManager.focus();
        }
    },
    
/**
     * @param {Object} event
     */
    
trashAttachment: function( event ) {
        var 
library this.controller.library;
        
event.preventDefault();

        if ( 
wp.media.view.settings.mediaTrash &&
            
'edit-metadata' === this.controller.content.mode() ) {

            
this.model.set'status''trash' );
            
this.model.save().done( function() {
                
library._requerytrue );
            } );
        }  else {
            
this.model.destroy();
        }
    },
    
/**
     * @param {Object} event
     */
    
untrashAttachment: function( event ) {
        var 
library this.controller.library;
        
event.preventDefault();

        
this.model.set'status''inherit' );
        
this.model.save().done( function() {
            
library._requerytrue );
        } );
    },
    
/**
     * @param {Object} event
     */
    
editAttachment: function( event ) {
        var 
editState this.controller.states.get'edit-image' );
        if ( 
window.imageEdit && editState ) {
            
event.preventDefault();

            
editState.set'image'this.model );
            
this.controller.setState'edit-image' );
        } else {
            
this.$el.addClass('needs-refresh');
        }
    },
    
/**
     * @param {Object} event
     */
    
refreshAttachment: function( event ) {
        
this.$el.removeClass('needs-refresh');
        
event.preventDefault();
        
this.model.fetch();
    },
    
/**
     * When reverse tabbing(shift+tab) out of the right details panel, deliver
     * the focus to the item in the list that was being edited.
     *
     * @param {Object} event
     */
    
toggleSelectionHandler: function( event ) {
        if ( 
'keydown' === event.type && === event.keyCode && event.shiftKey && event.target === this.$( ':tabbable' ).get) ) {
            
this.controller.trigger'attachment:details:shift-tab'event );
            return 
false;
        }

        if ( 
37 === event.keyCode || 38 === event.keyCode || 39 === event.keyCode || 40 === event.keyCode ) {
            
this.controller.trigger'attachment:keydown:arrow'event );
            return;
        }
    }
});

module.exports Details;

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

/**
 * wp.media.view.Attachment.EditLibrary
 *
 * @class
 * @augments wp.media.view.Attachment
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var EditLibrary wp.media.view.Attachment.extend({
    
buttons: {
        
closetrue
    
}
});

module.exports EditLibrary;

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

/**
 * wp.media.view.Attachments.EditSelection
 *
 * @class
 * @augments wp.media.view.Attachment.Selection
 * @augments wp.media.view.Attachment
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var EditSelection wp.media.view.Attachment.Selection.extend({
    
buttons: {
        
closetrue
    
}
});

module.exports EditSelection;

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

/**
 * wp.media.view.Attachment.Library
 *
 * @class
 * @augments wp.media.view.Attachment
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Library wp.media.view.Attachment.extend({
    
buttons: {
        
checktrue
    
}
});

module.exports Library;

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

/**
 * wp.media.view.Attachment.Selection
 *
 * @class
 * @augments wp.media.view.Attachment
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Selection wp.media.view.Attachment.extend({
    
className'attachment selection',

    
// On click, just select the model, instead of removing the model from
    // the selection.
    
toggleSelection: function() {
        
this.options.selection.singlethis.model );
    }
});

module.exports Selection;

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

/**
 * wp.media.view.Attachments
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    $ = 
jQuery,
    
Attachments;

Attachments View.extend({
    
tagName:   'ul',
    
className'attachments',

    
attributes: {
        
tabIndex: -1
    
},

    
initialize: function() {
        
this.el.id _.uniqueId('__attachments-view-');

        
_.defaultsthis.options, {
            
refreshSensitivitywp.media.isTouchDevice 300 200,
            
refreshThreshold:   3,
            
AttachmentView:     wp.media.view.Attachment,
            
sortable:           false,
            
resize:             true,
            
idealColumnWidth:   $( window ).width() < 640 135 150
        
});

        
this._viewsByCid = {};
        
this.$window = $( window );
        
this.resizeEvent 'resize.media-modal-columns';

        
this.collection.on'add', function( attachment ) {
            
this.views.addthis.createAttachmentViewattachment ), {
                
atthis.collection.indexOfattachment )
            });
        }, 
this );

        
this.collection.on'remove', function( attachment ) {
            var 
view this._viewsByCidattachment.cid ];
            
delete this._viewsByCidattachment.cid ];

            if ( 
view ) {
                
view.remove();
            }
        }, 
this );

        
this.collection.on'reset'this.renderthis );

        
this.listenTothis.controller'library:selection:add',    this.attachmentFocus );

        
// Throttle the scroll handler and bind this.
        
this.scroll _.chainthis.scroll ).bindthis ).throttlethis.options.refreshSensitivity ).value();

        
this.options.scrollElement this.options.scrollElement || this.el;
        $( 
this.options.scrollElement ).on'scroll'this.scroll );

        
this.initSortable();

        
_.bindAllthis'setColumns' );

        if ( 
this.options.resize ) {
            
this.on'ready'this.bindEvents );
            
this.controller.on'open'this.setColumns );

            
// Call this.setColumns() after this view has been rendered in the DOM so
            // attachments get proper width applied.
            
_.deferthis.setColumnsthis );
        }
    },

    
bindEvents: function() {
        
this.$window.offthis.resizeEvent ).onthis.resizeEvent_.debouncethis.setColumns50 ) );
    },

    
attachmentFocus: function() {
        
this.$( 'li:first' ).focus();
    },

    
restoreFocus: function() {
        
this.$( 'li.selected:first' ).focus();
    },

    
arrowEvent: function( event ) {
        var 
attachments this.$el.children'li' ),
            
perRow this.columns,
            
index attachments.filter':focus' ).index(),
            
row = ( index ) <= perRow Math.ceil( ( index ) / perRow );

        if ( 
index === -) {
            return;
        }

        
// Left arrow
        
if ( 37 === event.keyCode ) {
            if ( 
=== index ) {
                return;
            }
            
attachments.eqindex ).focus();
        }

        
// Up arrow
        
if ( 38 === event.keyCode ) {
            if ( 
=== row ) {
                return;
            }
            
attachments.eqindex perRow ).focus();
        }

        
// Right arrow
        
if ( 39 === event.keyCode ) {
            if ( 
attachments.length === index ) {
                return;
            }
            
attachments.eqindex ).focus();
        }

        
// Down arrow
        
if ( 40 === event.keyCode ) {
            if ( 
Math.ceilattachments.length perRow ) === row ) {
                return;
            }
            
attachments.eqindex perRow ).focus();
        }
    },

    
dispose: function() {
        
this.collection.props.offnullnullthis );
        if ( 
this.options.resize ) {
            
this.$window.offthis.resizeEvent );
        }

        
/**
         * call 'dispose' directly on the parent class
         */
        
View.prototype.dispose.applythisarguments );
    },

    
setColumns: function() {
        var 
prev this.columns,
            
width this.$el.width();

        if ( 
width ) {
            
this.columns Math.minMath.roundwidth this.options.idealColumnWidth ), 12 ) || 1;

            if ( ! 
prev || prev !== this.columns ) {
                
this.$el.closest'.media-frame-content' ).attr'data-columns'this.columns );
            }
        }
    },

    
initSortable: function() {
        var 
collection this.collection;

        if ( 
wp.media.isTouchDevice || ! this.options.sortable || ! $.fn.sortable ) {
            return;
        }

        
this.$el.sortable_.extend({
            
// If the `collection` has a `comparator`, disable sorting.
            
disabled: !! collection.comparator,

            
// Change the position of the attachment as soon as the
            // mouse pointer overlaps a thumbnail.
            
tolerance'pointer',

            
// Record the initial `index` of the dragged model.
            
start: function( eventui ) {
                
ui.item.data('sortableIndexStart'ui.item.index());
            },

            
// Update the model's index in the collection.
            // Do so silently, as the view is already accurate.
            
update: function( eventui ) {
                var 
model collection.atui.item.data('sortableIndexStart') ),
                    
comparator collection.comparator;

                
// Temporarily disable the comparator to prevent `add`
                // from re-sorting.
                
delete collection.comparator;

                
// Silently shift the model to its new index.
                
collection.removemodel, {
                    
silenttrue
                
});
                
collection.addmodel, {
                    
silenttrue,
                    
at:     ui.item.index()
                });

                
// Restore the comparator.
                
collection.comparator comparator;

                
// Fire the `reset` event to ensure other collections sync.
                
collection.trigger'reset'collection );

                
// If the collection is sorted by menu order,
                // update the menu order.
                
collection.saveMenuOrder();
            }
        }, 
this.options.sortable ) );

        
// If the `orderby` property is changed on the `collection`,
        // check to see if we have a `comparator`. If so, disable sorting.
        
collection.props.on'change:orderby', function() {
            
this.$el.sortable'option''disabled', !! collection.comparator );
        }, 
this );

        
this.collection.props.on'change:orderby'this.refreshSortablethis );
        
this.refreshSortable();
    },

    
refreshSortable: function() {
        if ( 
wp.media.isTouchDevice || ! this.options.sortable || ! $.fn.sortable ) {
            return;
        }

        
// If the `collection` has a `comparator`, disable sorting.
        
var collection this.collection,
            
orderby collection.props.get('orderby'),
            
enabled 'menuOrder' === orderby || ! collection.comparator;

        
this.$el.sortable'option''disabled', ! enabled );
    },

    
/**
     * @param {wp.media.model.Attachment} attachment
     * @returns {wp.media.View}
     */
    
createAttachmentView: function( attachment ) {
        var 
view = new this.options.AttachmentView({
            
controller:           this.controller,
            
model:                attachment,
            
collection:           this.collection,
            
selection:            this.options.selection
        
});

        return 
this._viewsByCidattachment.cid ] = view;
    },

    
prepare: function() {
        
// Create all of the Attachment views, and replace
        // the list in a single DOM operation.
        
if ( this.collection.length ) {
            
this.views.setthis.collection.mapthis.createAttachmentViewthis ) );

        
// If there are no elements, clear the views and load some.
        
} else {
            
this.views.unset();
            
this.collection.more().donethis.scroll );
        }
    },

    
ready: function() {
        
// Trigger the scroll event to check if we're within the
        // threshold to query for additional attachments.
        
this.scroll();
    },

    
scroll: function() {
        var 
view this,
            
el this.options.scrollElement,
            
scrollTop el.scrollTop,
            
toolbar;

        
// The scroll event occurs on the document, but the element
        // that should be checked is the document body.
        
if ( el === document ) {
            
el document.body;
            
scrollTop = $(document).scrollTop();
        }

        if ( ! $(
el).is(':visible') || ! this.collection.hasMore() ) {
            return;
        }

        
toolbar this.views.parent.toolbar;

        
// Show the spinner only if we are close to the bottom.
        
if ( el.scrollHeight - ( scrollTop el.clientHeight ) < el.clientHeight ) {
            
toolbar.get('spinner').show();
        }

        if ( 
el.scrollHeight scrollTop + ( el.clientHeight this.options.refreshThreshold ) ) {
            
this.collection.more().done(function() {
                
view.scroll();
                
toolbar.get('spinner').hide();
            });
        }
    }
});

module.exports Attachments;

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

/**
 * wp.media.view.AttachmentsBrowser
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 *
 * @param {object}         [options]               The options hash passed to the view.
 * @param {boolean|string} [options.filters=false] Which filters to show in the browser's toolbar.
 *                                                 Accepts 'uploaded' and 'all'.
 * @param {boolean}        [options.search=true]   Whether to show the search interface in the
 *                                                 browser's toolbar.
 * @param {boolean}        [options.date=true]     Whether to show the date filter in the
 *                                                 browser's toolbar.
 * @param {boolean}        [options.display=false] Whether to show the attachments display settings
 *                                                 view in the sidebar.
 * @param {boolean|string} [options.sidebar=true]  Whether to create a sidebar for the browser.
 *                                                 Accepts true, false, and 'errors'.
 */
var View wp.media.View,
    
mediaTrash wp.media.view.settings.mediaTrash,
    
l10n wp.media.view.l10n,
    $ = 
jQuery,
    
AttachmentsBrowser;

AttachmentsBrowser View.extend({
    
tagName:   'div',
    
className'attachments-browser',

    
initialize: function() {
        
_.defaultsthis.options, {
            
filtersfalse,
            
search:  true,
            
date:    true,
            
displayfalse,
            
sidebartrue,
            
AttachmentViewwp.media.view.Attachment.Library
        
});

        
this.listenTothis.controller'toggle:upload:attachment'_.bindthis.toggleUploaderthis ) );
        
this.controller.on'edit:selection'this.editSelection );
        
this.createToolbar();
        if ( 
this.options.sidebar ) {
            
this.createSidebar();
        }
        
this.createUploader();
        
this.createAttachments();
        
this.updateContent();

        if ( ! 
this.options.sidebar || 'errors' === this.options.sidebar ) {
            
this.$el.addClass'hide-sidebar' );

            if ( 
'errors' === this.options.sidebar ) {
                
this.$el.addClass'sidebar-for-errors' );
            }
        }

        
this.collection.on'add remove reset'this.updateContentthis );
    },

    
editSelection: function( modal ) {
        
modal.$( '.media-button-backToLibrary' ).focus();
    },

    
/**
     * @returns {wp.media.view.AttachmentsBrowser} Returns itself to allow chaining
     */
    
dispose: function() {
        
this.options.selection.offnullnullthis );
        
View.prototype.dispose.applythisarguments );
        return 
this;
    },

    
createToolbar: function() {
        var 
LibraryViewSwitcherFilterstoolbarOptions;

        
toolbarOptions = {
            
controllerthis.controller
        
};

        if ( 
this.controller.isModeActive'grid' ) ) {
            
toolbarOptions.className 'media-toolbar wp-filter';
        }

        
/**
        * @member {wp.media.view.Toolbar}
        */
        
this.toolbar = new wp.media.view.ToolbartoolbarOptions );

        
this.views.addthis.toolbar );

        
this.toolbar.set'spinner', new wp.media.view.Spinner({
            
priority: -60
        
}) );

        if ( -
!== $.inArraythis.options.filters, [ 'uploaded''all' ] ) ) {
            
// "Filters" will return a <select>, need to render
            // screen reader text before
            
this.toolbar.set'filtersLabel', new wp.media.view.Label({
                
valuel10n.filterByType,
                
attributes: {
                    
'for':  'media-attachment-filters'
                
},
                
priority:   -80
            
}).render() );

            if ( 
'uploaded' === this.options.filters ) {
                
this.toolbar.set'filters', new wp.media.view.AttachmentFilters.Uploaded({
                    
controllerthis.controller,
                    
model:      this.collection.props,
                    
priority:   -80
                
}).render() );
            } else {
                
Filters = new wp.media.view.AttachmentFilters.All({
                    
controllerthis.controller,
                    
model:      this.collection.props,
                    
priority:   -80
                
});

                
this.toolbar.set'filters'Filters.render() );
            }
        }

        
// Feels odd to bring the global media library switcher into the Attachment
        // browser view. Is this a use case for doAction( 'add:toolbar-items:attachments-browser', this.toolbar );
        // which the controller can tap into and add this view?
        
if ( this.controller.isModeActive'grid' ) ) {
            
LibraryViewSwitcher View.extend({
                
className'view-switch media-grid-view-switch',
                
templatewp.template'media-library-view-switcher')
            });

            
this.toolbar.set'libraryViewSwitcher', new LibraryViewSwitcher({
                
controllerthis.controller,
                
priority: -90
            
}).render() );

            
// DateFilter is a <select>, screen reader text needs to be rendered before
            
this.toolbar.set'dateFilterLabel', new wp.media.view.Label({
                
valuel10n.filterByDate,
                
attributes: {
                    
'for''media-attachment-date-filters'
                
},
                
priority: -75
            
}).render() );
            
this.toolbar.set'dateFilter', new wp.media.view.DateFilter({
                
controllerthis.controller,
                
model:      this.collection.props,
                
priority: -75
            
}).render() );

            
// BulkSelection is a <div> with subviews, including screen reader text
            
this.toolbar.set'selectModeToggleButton', new wp.media.view.SelectModeToggleButton({
                
textl10n.bulkSelect,
                
controllerthis.controller,
                
priority: -70
            
}).render() );

            
this.toolbar.set'deleteSelectedButton', new wp.media.view.DeleteSelectedButton({
                
filtersFilters,
                
style'primary',
                
disabledtrue,
                
textmediaTrash l10n.trashSelected l10n.deleteSelected,
                
controllerthis.controller,
                
priority: -60,
                
click: function() {
                    var 
changed = [], removed = [],
                        
selection this.controller.state().get'selection' ),
                        
library this.controller.state().get'library' );

                    if ( ! 
selection.length ) {
                        return;
                    }

                    if ( ! 
mediaTrash && ! window.confirml10n.warnBulkDelete ) ) {
                        return;
                    }

                    if ( 
mediaTrash &&
                        
'trash' !== selection.at).get'status' ) &&
                        ! 
window.confirml10n.warnBulkTrash ) ) {

                        return;
                    }

                    
selection.each( function( model ) {
                        if ( ! 
model.get'nonces' )['delete'] ) {
                            
removed.pushmodel );
                            return;
                        }

                        if ( 
mediaTrash && 'trash' === model.get'status' ) ) {
                            
model.set'status''inherit' );
                            
changed.pushmodel.save() );
                            
removed.pushmodel );
                        } else if ( 
mediaTrash ) {
                            
model.set'status''trash' );
                            
changed.pushmodel.save() );
                            
removed.pushmodel );
                        } else {
                            
model.destroy({waittrue});
                        }
                    } );

                    if ( 
changed.length ) {
                        
selection.removeremoved );

                        $.
when.applynullchanged ).then_.bind( function() {
                            
library._requerytrue );
                            
this.controller.trigger'selection:action:done' );
                        }, 
this ) );
                    } else {
                        
this.controller.trigger'selection:action:done' );
                    }
                }
            }).
render() );

            if ( 
mediaTrash ) {
                
this.toolbar.set'deleteSelectedPermanentlyButton', new wp.media.view.DeleteSelectedPermanentlyButton({
                    
filtersFilters,
                    
style'primary',
                    
disabledtrue,
                    
textl10n.deleteSelected,
                    
controllerthis.controller,
                    
priority: -55,
                    
click: function() {
                        var 
removed = [], selection this.controller.state().get'selection' );

                        if ( ! 
selection.length || ! window.confirml10n.warnBulkDelete ) ) {
                            return;
                        }

                        
selection.each( function( model ) {
                            if ( ! 
model.get'nonces' )['delete'] ) {
                                
removed.pushmodel );
                                return;
                            }

                            
model.destroy();
                        } );

                        
selection.removeremoved );
                        
this.controller.trigger'selection:action:done' );
                    }
                }).
render() );
            }

        } else if ( 
this.options.date ) {
            
// DateFilter is a <select>, screen reader text needs to be rendered before
            
this.toolbar.set'dateFilterLabel', new wp.media.view.Label({
                
valuel10n.filterByDate,
                
attributes: {
                    
'for''media-attachment-date-filters'
                
},
                
priority: -75
            
}).render() );
            
this.toolbar.set'dateFilter', new wp.media.view.DateFilter({
                
controllerthis.controller,
                
model:      this.collection.props,
                
priority: -75
            
}).render() );
        }

        if ( 
this.options.search ) {
            
// Search is an input, screen reader text needs to be rendered before
            
this.toolbar.set'searchLabel', new wp.media.view.Label({
                
valuel10n.searchMediaLabel,
                
attributes: {
                    
'for''media-search-input'
                
},
                
priority:   60
            
}).render() );
            
this.toolbar.set'search', new wp.media.view.Search({
                
controllerthis.controller,
                
model:      this.collection.props,
                
priority:   60
            
}).render() );
        }

        if ( 
this.options.dragInfo ) {
            
this.toolbar.set'dragInfo', new View({
                
el: $( '<div class="instructions">' l10n.dragInfo '</div>' )[0],
                
priority: -40
            
}) );
        }

        if ( 
this.options.suggestedWidth && this.options.suggestedHeight ) {
            
this.toolbar.set'suggestedDimensions', new View({
                
el: $( '<div class="instructions">' l10n.suggestedDimensions ' ' this.options.suggestedWidth ' &times; ' this.options.suggestedHeight '</div>' )[0],
                
priority: -40
            
}) );
        }
    },

    
updateContent: function() {
        var 
view this,
            
noItemsView;

        if ( 
this.controller.isModeActive'grid' ) ) {
            
noItemsView view.attachmentsNoResults;
        } else {
            
noItemsView view.uploader;
        }

        if ( ! 
this.collection.length ) {
            
this.toolbar.get'spinner' ).show();
            
this.dfd this.collection.more().done( function() {
                if ( ! 
view.collection.length ) {
                    
noItemsView.$el.removeClass'hidden' );
                } else {
                    
noItemsView.$el.addClass'hidden' );
                }
                
view.toolbar.get'spinner' ).hide();
            } );
        } else {
            
noItemsView.$el.addClass'hidden' );
            
view.toolbar.get'spinner' ).hide();
        }
    },

    
createUploader: function() {
        
this.uploader = new wp.media.view.UploaderInline({
            
controllerthis.controller,
            
status:     false,
            
message:    this.controller.isModeActive'grid' ) ? '' l10n.noItemsFound,
            
canClose:   this.controller.isModeActive'grid' )
        });

        
this.uploader.hide();
        
this.views.addthis.uploader );
    },

    
toggleUploader: function() {
        if ( 
this.uploader.$el.hasClass'hidden' ) ) {
            
this.uploader.show();
        } else {
            
this.uploader.hide();
        }
    },

    
createAttachments: function() {
        
this.attachments = new wp.media.view.Attachments({
            
controller:           this.controller,
            
collection:           this.collection,
            
selection:            this.options.selection,
            
model:                this.model,
            
sortable:             this.options.sortable,
            
scrollElement:        this.options.scrollElement,
            
idealColumnWidth:     this.options.idealColumnWidth,

            
// The single `Attachment` view to be used in the `Attachments` view.
            
AttachmentViewthis.options.AttachmentView
        
});

        
// Add keydown listener to the instance of the Attachments view
        
this.attachments.listenTothis.controller'attachment:keydown:arrow',     this.attachments.arrowEvent );
        
this.attachments.listenTothis.controller'attachment:details:shift-tab'this.attachments.restoreFocus );

        
this.views.addthis.attachments );


        if ( 
this.controller.isModeActive'grid' ) ) {
            
this.attachmentsNoResults = new View({
                
controllerthis.controller,
                
tagName'p'
            
});

            
this.attachmentsNoResults.$el.addClass'hidden no-media' );
            
this.attachmentsNoResults.$el.htmll10n.noMedia );

            
this.views.addthis.attachmentsNoResults );
        }
    },

    
createSidebar: function() {
        var 
options this.options,
            
selection options.selection,
            
sidebar this.sidebar = new wp.media.view.Sidebar({
                
controllerthis.controller
            
});

        
this.views.addsidebar );

        if ( 
this.controller.uploader ) {
            
sidebar.set'uploads', new wp.media.view.UploaderStatus({
                
controllerthis.controller,
                
priority:   40
            
}) );
        }

        
selection.on'selection:single'this.createSinglethis );
        
selection.on'selection:unsingle'this.disposeSinglethis );

        if ( 
selection.single() ) {
            
this.createSingle();
        }
    },

    
createSingle: function() {
        var 
sidebar this.sidebar,
            
single this.options.selection.single();

        
sidebar.set'details', new wp.media.view.Attachment.Details({
            
controllerthis.controller,
            
model:      single,
            
priority:   80
        
}) );

        
sidebar.set'compat', new wp.media.view.AttachmentCompat({
            
controllerthis.controller,
            
model:      single,
            
priority:   120
        
}) );

        if ( 
this.options.display ) {
            
sidebar.set'display', new wp.media.view.Settings.AttachmentDisplay({
                
controller:   this.controller,
                
model:        this.model.displaysingle ),
                
attachment:   single,
                
priority:     160,
                
userSettingsthis.model.get('displayUserSettings')
            }) );
        }

        
// Show the sidebar on mobile
        
if ( this.model.id === 'insert' ) {
            
sidebar.$el.addClass'visible' );
        }
    },

    
disposeSingle: function() {
        var 
sidebar this.sidebar;
        
sidebar.unset('details');
        
sidebar.unset('compat');
        
sidebar.unset('display');
        
// Hide the sidebar on mobile
        
sidebar.$el.removeClass'visible' );
    }
});

module.exports AttachmentsBrowser;

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

/**
 * wp.media.view.Attachments.Selection
 *
 * @class
 * @augments wp.media.view.Attachments
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Attachments wp.media.view.Attachments,
    
Selection;

Selection Attachments.extend({
    
events: {},
    
initialize: function() {
        
_.defaultsthis.options, {
            
sortable:   false,
            
resize:     false,

            
// The single `Attachment` view to be used in the `Attachments` view.
            
AttachmentViewwp.media.view.Attachment.Selection
        
});
        
// Call 'initialize' directly on the parent class.
        
return Attachments.prototype.initialize.applythisarguments );
    }
});

module.exports Selection;

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

/**
 * wp.media.view.ButtonGroup
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var $ = Backbone.$,
    
ButtonGroup;

ButtonGroup wp.media.View.extend({
    
tagName:   'div',
    
className'button-group button-large media-button-group',

    
initialize: function() {
        
/**
         * @member {wp.media.view.Button[]}
         */
        
this.buttons _.mapthis.options.buttons || [], function( button ) {
            if ( 
button instanceof Backbone.View ) {
                return 
button;
            } else {
                return new 
wp.media.view.Buttonbutton ).render();
            }
        });

        
delete this.options.buttons;

        if ( 
this.options.classes ) {
            
this.$el.addClassthis.options.classes );
        }
    },

    
/**
     * @returns {wp.media.view.ButtonGroup}
     */
    
render: function() {
        
this.$el.html( $( _.pluckthis.buttons'el' ) ).detach() );
        return 
this;
    }
});

module.exports ButtonGroup;

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

/**
 * wp.media.view.Button
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Button wp.media.View.extend({
    
tagName:    'a',
    
className:  'media-button',
    
attributes: { href'#' },

    
events: {
        
'click''click'
    
},

    
defaults: {
        
text:     '',
        
style:    '',
        
size:     'large',
        
disabledfalse
    
},

    
initialize: function() {
        
/**
         * Create a model with the provided `defaults`.
         *
         * @member {Backbone.Model}
         */
        
this.model = new Backbone.Modelthis.defaults );

        
// If any of the `options` have a key from `defaults`, apply its
        // value to the `model` and remove it from the `options object.
        
_.eachthis.defaults, function( defkey ) {
            var 
value this.optionskey ];
            if ( 
_.isUndefinedvalue ) ) {
                return;
            }

            
this.model.setkeyvalue );
            
delete this.optionskey ];
        }, 
this );

        
this.listenTothis.model'change'this.render );
    },
    
/**
     * @returns {wp.media.view.Button} Returns itself to allow chaining
     */
    
render: function() {
        var 
classes = [ 'button'this.className ],
            
model this.model.toJSON();

        if ( 
model.style ) {
            
classes.push'button-' model.style );
        }

        if ( 
model.size ) {
            
classes.push'button-' model.size );
        }

        
classes _.uniqclasses.concatthis.options.classes ) );
        
this.el.className classes.join(' ');

        
this.$el.attr'disabled'model.disabled );
        
this.$el.textthis.model.get('text') );

        return 
this;
    },
    
/**
     * @param {Object} event
     */
    
click: function( event ) {
        if ( 
'#' === this.attributes.href ) {
            
event.preventDefault();
        }

        if ( 
this.options.click && ! this.model.get('disabled') ) {
            
this.options.click.applythisarguments );
        }
    }
});

module.exports Button;

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

/**
 * wp.media.view.Cropper
 *
 * Uses the imgAreaSelect plugin to allow a user to crop an image.
 *
 * Takes imgAreaSelect options from
 * wp.customize.HeaderControl.calculateImageSelectOptions via
 * wp.customize.HeaderControl.openMM.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
UploaderStatus wp.media.view.UploaderStatus,
    
l10n wp.media.view.l10n,
    $ = 
jQuery,
    
Cropper;

Cropper View.extend({
    
className'crop-content',
    
templatewp.template('crop-content'),
    
initialize: function() {
        
_.bindAll(this'onImageLoad');
    },
    
ready: function() {
        
this.controller.frame.on('content:error:crop'this.onErrorthis);
        
this.$image this.$el.find('.crop-image');
        
this.$image.on('load'this.onImageLoad);
        $(
window).on('resize.cropper'_.debounce(this.onImageLoad250));
    },
    
remove: function() {
        $(
window).off('resize.cropper');
        
this.$el.remove();
        
this.$el.off();
        
View.prototype.remove.apply(thisarguments);
    },
    
prepare: function() {
        return {
            
titlel10n.cropYourImage,
            
urlthis.options.attachment.get('url')
        };
    },
    
onImageLoad: function() {
        var 
imgOptions this.controller.get('imgSelectOptions');
        if (
typeof imgOptions === 'function') {
            
imgOptions imgOptions(this.options.attachmentthis.controller);
        }

        
imgOptions _.extend(imgOptions, {parentthis.$el});
        
this.trigger('image-loaded');
        
this.controller.imgSelect this.$image.imgAreaSelect(imgOptions);
    },
    
onError: function() {
        var 
filename this.options.attachment.get('filename');

        
this.views.add'.upload-errors', new wp.media.view.UploaderStatusError({
            
filenameUploaderStatus.prototype.filename(filename),
            
messagewindow._wpMediaViewsL10n.cropError
        
}), { at});
    }
});

module.exports Cropper;

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

/**
 * wp.media.view.EditImage
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
EditImage;

EditImage View.extend({
    
className'image-editor',
    
templatewp.template('image-editor'),

    
initialize: function( options ) {
        
this.editor window.imageEdit;
        
this.controller options.controller;
        
View.prototype.initialize.applythisarguments );
    },

    
prepare: function() {
        return 
this.model.toJSON();
    },

    
loadEditor: function() {
        var 
dfd this.editor.openthis.model.get('id'), this.model.get('nonces').editthis );
        
dfd.done_.bindthis.focusthis ) );
    },

    
focus: function() {
        
this.$( '.imgedit-submit .button' ).eq).focus();
    },

    
back: function() {
        var 
lastState this.controller.lastState();
        
this.controller.setStatelastState );
    },

    
refresh: function() {
        
this.model.fetch();
    },

    
save: function() {
        var 
lastState this.controller.lastState();

        
this.model.fetch().done_.bind( function() {
            
this.controller.setStatelastState );
        }, 
this ) );
    }

});

module.exports EditImage;

},{}],
36:[function(require,module,exports){
/**
 * wp.media.view.Embed
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Embed wp.media.View.extend({
    
className'media-embed',

    
initialize: function() {
        
/**
         * @member {wp.media.view.EmbedUrl}
         */
        
this.url = new wp.media.view.EmbedUrl({
            
controllerthis.controller,
            
model:      this.model.props
        
}).render();

        
this.views.set([ this.url ]);
        
this.refresh();
        
this.listenTothis.model'change:type'this.refresh );
        
this.listenTothis.model'change:loading'this.loading );
    },

    
/**
     * @param {Object} view
     */
    
settings: function( view ) {
        if ( 
this._settings ) {
            
this._settings.remove();
        }
        
this._settings view;
        
this.views.addview );
    },

    
refresh: function() {
        var 
type this.model.get('type'),
            
constructor;

        if ( 
'image' === type ) {
            
constructor wp.media.view.EmbedImage;
        } else if ( 
'link' === type ) {
            
constructor wp.media.view.EmbedLink;
        } else {
            return;
        }

        
this.settings( new constructor({
            
controllerthis.controller,
            
model:      this.model.props,
            
priority:   40
        
}) );
    },

    
loading: function() {
        
this.$el.toggleClass'embed-loading'this.model.get('loading') );
    }
});

module.exports Embed;

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

/**
 * wp.media.view.EmbedImage
 *
 * @class
 * @augments wp.media.view.Settings.AttachmentDisplay
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var AttachmentDisplay wp.media.view.Settings.AttachmentDisplay,
    
EmbedImage;

EmbedImage AttachmentDisplay.extend({
    
className'embed-media-settings',
    
template:  wp.template('embed-image-settings'),

    
initialize: function() {
        
/**
         * Call `initialize` directly on parent class with passed arguments
         */
        
AttachmentDisplay.prototype.initialize.applythisarguments );
        
this.listenTothis.model'change:url'this.updateImage );
    },

    
updateImage: function() {
        
this.$('img').attr'src'this.model.get('url') );
    }
});

module.exports EmbedImage;

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

/**
 * wp.media.view.EmbedLink
 *
 * @class
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var $ = jQuery,
    
EmbedLink;

EmbedLink wp.media.view.Settings.extend({
    
className'embed-link-settings',
    
template:  wp.template('embed-link-settings'),

    
initialize: function() {
        
this.spinner = $('<span class="spinner" />');
        
this.$el.appendthis.spinner[0] );
        
this.listenTothis.model'change:url'this.updateoEmbed );
    },

    
updateoEmbed_.debounce( function() {
        var 
url this.model.get'url' );

        
// clear out previous results
        
this.$('.embed-container').hide().find('.embed-preview').empty();
        
this.$( '.setting' ).hide();

        
// only proceed with embed if the field contains more than 6 characters
        
if ( url && url.length ) {
            return;
        }

        
this.fetch();
    }, 
600 ),

    
fetch: function() {
        
// check if they haven't typed in 500 ms
        
if ( $('#embed-url-field').val() !== this.model.get('url') ) {
            return;
        }

        
wp.ajax.send'parse-embed', {
            
data : {
                
post_IDwp.media.view.settings.post.id,
                
shortcode'[embed]' this.model.get('url') + '[/embed]'
            
}
        } )
            .
done_.bindthis.renderoEmbedthis ) )
            .
fail_.bindthis.renderFailthis ) );
    },

    
renderFail: function () {
        
this.$( '.link-text' ).show();
    },

    
renderoEmbed: function( response ) {
        var 
html = ( response && response.body ) || '';

        if ( 
html ) {
            
this.$('.embed-container').show().find('.embed-preview').htmlhtml );
        } else {
            
this.renderFail();
        }
    }
});

module.exports EmbedLink;

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

/**
 * wp.media.view.EmbedUrl
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    $ = 
jQuery,
    
EmbedUrl;

EmbedUrl View.extend({
    
tagName:   'label',
    
className'embed-url',

    
events: {
        
'input':  'url',
        
'keyup':  'url',
        
'change''url'
    
},

    
initialize: function() {
        
this.$input = $('<input id="embed-url-field" type="url" />').valthis.model.get('url') );
        
this.input this.$input[0];

        
this.spinner = $('<span class="spinner" />')[0];
        
this.$el.append([ this.inputthis.spinner ]);

        
this.listenTothis.model'change:url'this.render );

        if ( 
this.model.get'url' ) ) {
            
_.delay_.bind( function () {
                
this.model.trigger'change:url' );
            }, 
this ), 500 );
        }
    },
    
/**
     * @returns {wp.media.view.EmbedUrl} Returns itself to allow chaining
     */
    
render: function() {
        var 
$input this.$input;

        if ( 
$input.is(':focus') ) {
            return;
        }

        
this.input.value this.model.get('url') || 'http://';
        
/**
         * Call `render` directly on parent class with passed arguments
         */
        
View.prototype.render.applythisarguments );
        return 
this;
    },

    
ready: function() {
        if ( ! 
wp.media.isTouchDevice ) {
            
this.focus();
        }
    },

    
url: function( event ) {
        
this.model.set'url'event.target.value );
    },

    
/**
     * If the input is visible, focus and select its contents.
     */
    
focus: function() {
        var 
$input this.$input;
        if ( 
$input.is(':visible') ) {
            
$input.focus()[0].select();
        }
    }
});

module.exports EmbedUrl;

},{}],
40:[function(require,module,exports){
/**
 * wp.media.view.FocusManager
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var FocusManager wp.media.View.extend({

    
events: {
        
'keydown''constrainTabbing'
    
},

    
focus: function() { // Reset focus on first left menu item
        
this.$('.media-menu-item').first().focus();
    },
    
/**
     * @param {Object} event
     */
    
constrainTabbing: function( event ) {
        var 
tabbables;

        
// Look for the tab key.
        
if ( !== event.keyCode ) {
            return;
        }

        
// Skip the file input added by Plupload.
        
tabbables this.$( ':tabbable' ).not'.moxie-shim input[type="file"]' );

        
// Keep tab focus within media modal while it's open
        
if ( tabbables.last()[0] === event.target && ! event.shiftKey ) {
            
tabbables.first().focus();
            return 
false;
        } else if ( 
tabbables.first()[0] === event.target && event.shiftKey ) {
            
tabbables.last().focus();
            return 
false;
        }
    }

});

module.exports FocusManager;

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

/**
 * wp.media.view.Frame
 *
 * A frame is a composite view consisting of one or more regions and one or more
 * states.
 *
 * @see wp.media.controller.State
 * @see wp.media.controller.Region
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 * @mixes wp.media.controller.StateMachine
 */
var Frame wp.media.View.extend({
    
initialize: function() {
        
_.defaultsthis.options, {
            
mode: [ 'select' ]
        });
        
this._createRegions();
        
this._createStates();
        
this._createModes();
    },

    
_createRegions: function() {
        
// Clone the regions array.
        
this.regions this.regions this.regions.slice() : [];

        
// Initialize regions.
        
_.eachthis.regions, function( region ) {
            
thisregion ] = new wp.media.controller.Region({
                
view:     this,
                
id:       region,
                
selector'.media-frame-' region
            
});
        }, 
this );
    },
    
/**
     * Create the frame's states.
     *
     * @see wp.media.controller.State
     * @see wp.media.controller.StateMachine
     *
     * @fires wp.media.controller.State#ready
     */
    
_createStates: function() {
        
// Create the default `states` collection.
        
this.states = new Backbone.Collectionnull, {
            
modelwp.media.controller.State
        
});

        
// Ensure states have a reference to the frame.
        
this.states.on'add', function( model ) {
            
model.frame this;
            
model.trigger('ready');
        }, 
this );

        if ( 
this.options.states ) {
            
this.states.addthis.options.states );
        }
    },

    
/**
     * A frame can be in a mode or multiple modes at one time.
     *
     * For example, the manage media frame can be in the `Bulk Select` or `Edit` mode.
     */
    
_createModes: function() {
        
// Store active "modes" that the frame is in. Unrelated to region modes.
        
this.activeModes = new Backbone.Collection();
        
this.activeModes.on'add remove reset'_.bindthis.triggerModeEventsthis ) );

        
_.eachthis.options.mode, function( mode ) {
            
this.activateModemode );
        }, 
this );
    },
    
/**
     * Reset all states on the frame to their defaults.
     *
     * @returns {wp.media.view.Frame} Returns itself to allow chaining
     */
    
reset: function() {
        
this.states.invoke'trigger''reset' );
        return 
this;
    },
    
/**
     * Map activeMode collection events to the frame.
     */
    
triggerModeEvents: function( modelcollectionoptions ) {
        var 
collectionEvent,
            
modeEventMap = {
                
add'activate',
                
remove'deactivate'
            
},
            
eventToTrigger;
        
// Probably a better way to do this.
        
_.eachoptions, function( valuekey ) {
            if ( 
value ) {
                
collectionEvent key;
            }
        } );

        if ( ! 
_.hasmodeEventMapcollectionEvent ) ) {
            return;
        }

        
eventToTrigger model.get('id') + ':' modeEventMap[collectionEvent];
        
this.triggereventToTrigger );
    },
    
/**
     * Activate a mode on the frame.
     *
     * @param string mode Mode ID.
     * @returns {this} Returns itself to allow chaining.
     */
    
activateMode: function( mode ) {
        
// Bail if the mode is already active.
        
if ( this.isModeActivemode ) ) {
            return;
        }
        
this.activeModes.add( [ { idmode } ] );
        
// Add a CSS class to the frame so elements can be styled for the mode.
        
this.$el.addClass'mode-' mode );

        return 
this;
    },
    
/**
     * Deactivate a mode on the frame.
     *
     * @param string mode Mode ID.
     * @returns {this} Returns itself to allow chaining.
     */
    
deactivateMode: function( mode ) {
        
// Bail if the mode isn't active.
        
if ( ! this.isModeActivemode ) ) {
            return 
this;
        }
        
this.activeModes.removethis.activeModes.where( { idmode } ) );
        
this.$el.removeClass'mode-' mode );
        
/**
         * Frame mode deactivation event.
         *
         * @event this#{mode}:deactivate
         */
        
this.triggermode ':deactivate' );

        return 
this;
    },
    
/**
     * Check if a mode is enabled on the frame.
     *
     * @param  string mode Mode ID.
     * @return bool
     */
    
isModeActive: function( mode ) {
        return 
Booleanthis.activeModes.where( { idmode } ).length );
    }
});

// Make the `Frame` a `StateMachine`.
_.extendFrame.prototypewp.media.controller.StateMachine.prototype );

module.exports Frame;

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

/**
 * wp.media.view.MediaFrame.ImageDetails
 *
 * A media frame for manipulating an image that's already been inserted
 * into a post.
 *
 * @class
 * @augments wp.media.view.MediaFrame.Select
 * @augments wp.media.view.MediaFrame
 * @augments wp.media.view.Frame
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 * @mixes wp.media.controller.StateMachine
 */
var Select wp.media.view.MediaFrame.Select,
    
l10n wp.media.view.l10n,
    
ImageDetails;

ImageDetails Select.extend({
    
defaults: {
        
id:      'image',
        
url:     '',
        
menu:    'image-details',
        
content'image-details',
        
toolbar'image-details',
        
type:    'link',
        
title:    l10n.imageDetailsTitle,
        
priority120
    
},

    
initialize: function( options ) {
        
this.image = new wp.media.model.PostImageoptions.metadata );
        
this.options.selection = new wp.media.model.Selectionthis.image.attachment, { multiplefalse } );
        
Select.prototype.initialize.applythisarguments );
    },

    
bindHandlers: function() {
        
Select.prototype.bindHandlers.applythisarguments );
        
this.on'menu:create:image-details'this.createMenuthis );
        
this.on'content:create:image-details'this.imageDetailsContentthis );
        
this.on'content:render:edit-image'this.editImageContentthis );
        
this.on'toolbar:render:image-details'this.renderImageDetailsToolbarthis );
        
// override the select toolbar
        
this.on'toolbar:render:replace'this.renderReplaceImageToolbarthis );
    },

    
createStates: function() {
        
this.states.add([
            new 
wp.media.controller.ImageDetails({
                
imagethis.image,
                
editablefalse
            
}),
            new 
wp.media.controller.ReplaceImage({
                
id'replace-image',
                
librarywp.media.query( { type'image' } ),
                
imagethis.image,
                
multiple:  false,
                
title:     l10n.imageReplaceTitle,
                
toolbar'replace',
                
priority:  80,
                
displaySettingstrue
            
}),
            new 
wp.media.controller.EditImage( {
                
imagethis.image,
                
selectionthis.options.selection
            
} )
        ]);
    },

    
imageDetailsContent: function( options ) {
        
options.view = new wp.media.view.ImageDetails({
            
controllerthis,
            
modelthis.state().image,
            
attachmentthis.state().image.attachment
        
});
    },

    
editImageContent: function() {
        var 
state this.state(),
            
model state.get('image'),
            
view;

        if ( ! 
model ) {
            return;
        }

        
view = new wp.media.view.EditImage( { modelmodelcontrollerthis } ).render();

        
this.content.setview );

        
// after bringing in the frame, load the actual editor via an ajax call
        
view.loadEditor();

    },

    
renderImageDetailsToolbar: function() {
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
select: {
                    
style:    'primary',
                    
text:     l10n.update,
                    
priority80,

                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state();

                        
controller.close();

                        
// not sure if we want to use wp.media.string.image which will create a shortcode or
                        // perhaps wp.html.string to at least to build the <img />
                        
state.trigger'update'controller.image.toJSON() );

                        
// Restore and reset the default state.
                        
controller.setStatecontroller.options.state );
                        
controller.reset();
                    }
                }
            }
        }) );
    },

    
renderReplaceImageToolbar: function() {
        var 
frame this,
            
lastState frame.lastState(),
            
previous lastState && lastState.id;

        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
back: {
                    
text:     l10n.back,
                    
priority20,
                    
click:    function() {
                        if ( 
previous ) {
                            
frame.setStateprevious );
                        } else {
                            
frame.close();
                        }
                    }
                },

                
replace: {
                    
style:    'primary',
                    
text:     l10n.replace,
                    
priority80,

                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state(),
                            
selection state.get'selection' ),
                            
attachment selection.single();

                        
controller.close();

                        
controller.image.changeAttachmentattachmentstate.displayattachment ) );

                        
// not sure if we want to use wp.media.string.image which will create a shortcode or
                        // perhaps wp.html.string to at least to build the <img />
                        
state.trigger'replace'controller.image.toJSON() );

                        
// Restore and reset the default state.
                        
controller.setStatecontroller.options.state );
                        
controller.reset();
                    }
                }
            }
        }) );
    }

});

module.exports ImageDetails;

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

/**
 * wp.media.view.MediaFrame.Post
 *
 * The frame for manipulating media on the Edit Post page.
 *
 * @class
 * @augments wp.media.view.MediaFrame.Select
 * @augments wp.media.view.MediaFrame
 * @augments wp.media.view.Frame
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 * @mixes wp.media.controller.StateMachine
 */
var Select wp.media.view.MediaFrame.Select,
    
Library wp.media.controller.Library,
    
l10n wp.media.view.l10n,
    
Post;

Post Select.extend({
    
initialize: function() {
        
this.counts = {
            
audio: {
                
countwp.media.view.settings.attachmentCounts.audio,
                
state'playlist'
            
},
            
video: {
                
countwp.media.view.settings.attachmentCounts.video,
                
state'video-playlist'
            
}
        };

        
_.defaultsthis.options, {
            
multiple:  true,
            
editing:   false,
            
state:    'insert',
            
metadata:  {}
        });

        
// Call 'initialize' directly on the parent class.
        
Select.prototype.initialize.applythisarguments );
        
this.createIframeStates();

    },

    
/**
     * Create the default states.
     */
    
createStates: function() {
        var 
options this.options;

        
this.states.add([
            
// Main states.
            
new Library({
                
id:         'insert',
                
title:      l10n.insertMediaTitle,
                
priority:   20,
                
toolbar:    'main-insert',
                
filterable'all',
                
library:    wp.media.queryoptions.library ),
                
multiple:   options.multiple 'reset' false,
                
editable:   true,

                
// If the user isn't allowed to edit fields,
                // can they still edit it locally?
                
allowLocalEditstrue,

                
// Show the attachment display settings.
                
displaySettingstrue,
                
// Update user settings when users adjust the
                // attachment display settings.
                
displayUserSettingstrue
            
}),

            new 
Library({
                
id:         'gallery',
                
title:      l10n.createGalleryTitle,
                
priority:   40,
                
toolbar:    'main-gallery',
                
filterable'uploaded',
                
multiple:   'add',
                
editable:   false,

                
library:  wp.media.query_.defaults({
                    
type'image'
                
}, options.library ) )
            }),

            
// Embed states.
            
new wp.media.controller.Embed( { metadataoptions.metadata } ),

            new 
wp.media.controller.EditImage( { modeloptions.editImage } ),

            
// Gallery states.
            
new wp.media.controller.GalleryEdit({
                
libraryoptions.selection,
                
editingoptions.editing,
                
menu:    'gallery'
            
}),

            new 
wp.media.controller.GalleryAdd(),

            new 
Library({
                
id:         'playlist',
                
title:      l10n.createPlaylistTitle,
                
priority:   60,
                
toolbar:    'main-playlist',
                
filterable'uploaded',
                
multiple:   'add',
                
editable:   false,

                
library:  wp.media.query_.defaults({
                    
type'audio'
                
}, options.library ) )
            }),

            
// Playlist states.
            
new wp.media.controller.CollectionEdit({
                
type'audio',
                
collectionType'playlist',
                
title:          l10n.editPlaylistTitle,
                
SettingsView:   wp.media.view.Settings.Playlist,
                
library:        options.selection,
                
editing:        options.editing,
                
menu:           'playlist',
                
dragInfoText:   l10n.playlistDragInfo,
                
dragInfo:       false
            
}),

            new 
wp.media.controller.CollectionAdd({
                
type'audio',
                
collectionType'playlist',
                
titlel10n.addToPlaylistTitle
            
}),

            new 
Library({
                
id:         'video-playlist',
                
title:      l10n.createVideoPlaylistTitle,
                
priority:   60,
                
toolbar:    'main-video-playlist',
                
filterable'uploaded',
                
multiple:   'add',
                
editable:   false,

                
library:  wp.media.query_.defaults({
                    
type'video'
                
}, options.library ) )
            }),

            new 
wp.media.controller.CollectionEdit({
                
type'video',
                
collectionType'playlist',
                
title:          l10n.editVideoPlaylistTitle,
                
SettingsView:   wp.media.view.Settings.Playlist,
                
library:        options.selection,
                
editing:        options.editing,
                
menu:           'video-playlist',
                
dragInfoText:   l10n.videoPlaylistDragInfo,
                
dragInfo:       false
            
}),

            new 
wp.media.controller.CollectionAdd({
                
type'video',
                
collectionType'playlist',
                
titlel10n.addToVideoPlaylistTitle
            
})
        ]);

        if ( 
wp.media.view.settings.post.featuredImageId ) {
            
this.states.add( new wp.media.controller.FeaturedImage() );
        }
    },

    
bindHandlers: function() {
        var 
handlerscheckCounts;

        
Select.prototype.bindHandlers.applythisarguments );

        
this.on'activate'this.activatethis );

        
// Only bother checking media type counts if one of the counts is zero
        
checkCounts _.findthis.counts, function( type ) {
            return 
type.count === 0;
        } );

        if ( 
typeof checkCounts !== 'undefined' ) {
            
this.listenTowp.media.model.Attachments.all'change:type'this.mediaTypeCounts );
        }

        
this.on'menu:create:gallery'this.createMenuthis );
        
this.on'menu:create:playlist'this.createMenuthis );
        
this.on'menu:create:video-playlist'this.createMenuthis );
        
this.on'toolbar:create:main-insert'this.createToolbarthis );
        
this.on'toolbar:create:main-gallery'this.createToolbarthis );
        
this.on'toolbar:create:main-playlist'this.createToolbarthis );
        
this.on'toolbar:create:main-video-playlist'this.createToolbarthis );
        
this.on'toolbar:create:featured-image'this.featuredImageToolbarthis );
        
this.on'toolbar:create:main-embed'this.mainEmbedToolbarthis );

        
handlers = {
            
menu: {
                
'default''mainMenu',
                
'gallery''galleryMenu',
                
'playlist''playlistMenu',
                
'video-playlist''videoPlaylistMenu'
            
},

            
content: {
                
'embed':          'embedContent',
                
'edit-image':     'editImageContent',
                
'edit-selection''editSelectionContent'
            
},

            
toolbar: {
                
'main-insert':      'mainInsertToolbar',
                
'main-gallery':     'mainGalleryToolbar',
                
'gallery-edit':     'galleryEditToolbar',
                
'gallery-add':      'galleryAddToolbar',
                
'main-playlist':    'mainPlaylistToolbar',
                
'playlist-edit':    'playlistEditToolbar',
                
'playlist-add':        'playlistAddToolbar',
                
'main-video-playlist''mainVideoPlaylistToolbar',
                
'video-playlist-edit''videoPlaylistEditToolbar',
                
'video-playlist-add''videoPlaylistAddToolbar'
            
}
        };

        
_.eachhandlers, function( regionHandlersregion ) {
            
_.eachregionHandlers, function( callbackhandler ) {
                
this.onregion ':render:' handlerthiscallback ], this );
            }, 
this );
        }, 
this );
    },

    
activate: function() {
        
// Hide menu items for states tied to particular media types if there are no items
        
_.eachthis.counts, function( type ) {
            if ( 
type.count ) {
                
this.menuItemVisibilitytype.state'hide' );
            }
        }, 
this );
    },

    
mediaTypeCounts: function( modelattr ) {
        if ( 
typeof this.countsattr ] !== 'undefined' && this.countsattr ].count ) {
            
this.countsattr ].count++;
            
this.menuItemVisibilitythis.countsattr ].state'show' );
        }
    },

    
// Menus
    /**
     * @param {wp.Backbone.View} view
     */
    
mainMenu: function( view ) {
        
view.set({
            
'library-separator': new wp.media.View({
                
className'separator',
                
priority100
            
})
        });
    },

    
menuItemVisibility: function( statevisibility ) {
        var 
menu this.menu.get();
        if ( 
visibility === 'hide' ) {
            
menu.hidestate );
        } else if ( 
visibility === 'show' ) {
            
menu.showstate );
        }
    },
    
/**
     * @param {wp.Backbone.View} view
     */
    
galleryMenu: function( view ) {
        var 
lastState this.lastState(),
            
previous lastState && lastState.id,
            
frame this;

        
view.set({
            
cancel: {
                
text:     l10n.cancelGalleryTitle,
                
priority20,
                
click:    function() {
                    if ( 
previous ) {
                        
frame.setStateprevious );
                    } else {
                        
frame.close();
                    }

                    
// Keep focus inside media modal
                    // after canceling a gallery
                    
this.controller.modal.focusManager.focus();
                }
            },
            
separateCancel: new wp.media.View({
                
className'separator',
                
priority40
            
})
        });
    },

    
playlistMenu: function( view ) {
        var 
lastState this.lastState(),
            
previous lastState && lastState.id,
            
frame this;

        
view.set({
            
cancel: {
                
text:     l10n.cancelPlaylistTitle,
                
priority20,
                
click:    function() {
                    if ( 
previous ) {
                        
frame.setStateprevious );
                    } else {
                        
frame.close();
                    }
                }
            },
            
separateCancel: new wp.media.View({
                
className'separator',
                
priority40
            
})
        });
    },

    
videoPlaylistMenu: function( view ) {
        var 
lastState this.lastState(),
            
previous lastState && lastState.id,
            
frame this;

        
view.set({
            
cancel: {
                
text:     l10n.cancelVideoPlaylistTitle,
                
priority20,
                
click:    function() {
                    if ( 
previous ) {
                        
frame.setStateprevious );
                    } else {
                        
frame.close();
                    }
                }
            },
            
separateCancel: new wp.media.View({
                
className'separator',
                
priority40
            
})
        });
    },

    
// Content
    
embedContent: function() {
        var 
view = new wp.media.view.Embed({
            
controllerthis,
            
model:      this.state()
        }).
render();

        
this.content.setview );

        if ( ! 
wp.media.isTouchDevice ) {
            
view.url.focus();
        }
    },

    
editSelectionContent: function() {
        var 
state this.state(),
            
selection state.get('selection'),
            
view;

        
view = new wp.media.view.AttachmentsBrowser({
            
controllerthis,
            
collectionselection,
            
selection:  selection,
            
model:      state,
            
sortable:   true,
            
search:     false,
            
date:       false,
            
dragInfo:   true,

            
AttachmentViewwp.media.view.Attachments.EditSelection
        
}).render();

        
view.toolbar.set'backToLibrary', {
            
text:     l10n.returnToLibrary,
            
priority: -100,

            
click: function() {
                
this.controller.content.mode('browse');
            }
        });

        
// Browse our library of attachments.
        
this.content.setview );

        
// Trigger the controller to set focus
        
this.trigger'edit:selection'this );
    },

    
editImageContent: function() {
        var 
image this.state().get('image'),
            
view = new wp.media.view.EditImage( { modelimagecontrollerthis } ).render();

        
this.content.setview );

        
// after creating the wrapper view, load the actual editor via an ajax call
        
view.loadEditor();

    },

    
// Toolbars

    /**
     * @param {wp.Backbone.View} view
     */
    
selectionStatusToolbar: function( view ) {
        var 
editable this.state().get('editable');

        
view.set'selection', new wp.media.view.Selection({
            
controllerthis,
            
collectionthis.state().get('selection'),
            
priority:   -40,

            
// If the selection is editable, pass the callback to
            // switch the content mode.
            
editableeditable && function() {
                
this.controller.content.mode('edit-selection');
            }
        }).
render() );
    },

    
/**
     * @param {wp.Backbone.View} view
     */
    
mainInsertToolbar: function( view ) {
        var 
controller this;

        
this.selectionStatusToolbarview );

        
view.set'insert', {
            
style:    'primary',
            
priority80,
            
text:     l10n.insertIntoPost,
            
requires: { selectiontrue },

            
/**
             * @fires wp.media.controller.State#insert
             */
            
click: function() {
                var 
state controller.state(),
                    
selection state.get('selection');

                
controller.close();
                
state.trigger'insert'selection ).reset();
            }
        });
    },

    
/**
     * @param {wp.Backbone.View} view
     */
    
mainGalleryToolbar: function( view ) {
        var 
controller this;

        
this.selectionStatusToolbarview );

        
view.set'gallery', {
            
style:    'primary',
            
text:     l10n.createNewGallery,
            
priority60,
            
requires: { selectiontrue },

            
click: function() {
                var 
selection controller.state().get('selection'),
                    
edit controller.state('gallery-edit'),
                    
models selection.where({ type'image' });

                
edit.set'library', new wp.media.model.Selectionmodels, {
                    
props:    selection.props.toJSON(),
                    
multipletrue
                
}) );

                
this.controller.setState('gallery-edit');

                
// Keep focus inside media modal
                // after jumping to gallery view
                
this.controller.modal.focusManager.focus();
            }
        });
    },

    
mainPlaylistToolbar: function( view ) {
        var 
controller this;

        
this.selectionStatusToolbarview );

        
view.set'playlist', {
            
style:    'primary',
            
text:     l10n.createNewPlaylist,
            
priority100,
            
requires: { selectiontrue },

            
click: function() {
                var 
selection controller.state().get('selection'),
                    
edit controller.state('playlist-edit'),
                    
models selection.where({ type'audio' });

                
edit.set'library', new wp.media.model.Selectionmodels, {
                    
props:    selection.props.toJSON(),
                    
multipletrue
                
}) );

                
this.controller.setState('playlist-edit');

                
// Keep focus inside media modal
                // after jumping to playlist view
                
this.controller.modal.focusManager.focus();
            }
        });
    },

    
mainVideoPlaylistToolbar: function( view ) {
        var 
controller this;

        
this.selectionStatusToolbarview );

        
view.set'video-playlist', {
            
style:    'primary',
            
text:     l10n.createNewVideoPlaylist,
            
priority100,
            
requires: { selectiontrue },

            
click: function() {
                var 
selection controller.state().get('selection'),
                    
edit controller.state('video-playlist-edit'),
                    
models selection.where({ type'video' });

                
edit.set'library', new wp.media.model.Selectionmodels, {
                    
props:    selection.props.toJSON(),
                    
multipletrue
                
}) );

                
this.controller.setState('video-playlist-edit');

                
// Keep focus inside media modal
                // after jumping to video playlist view
                
this.controller.modal.focusManager.focus();
            }
        });
    },

    
featuredImageToolbar: function( toolbar ) {
        
this.createSelectToolbartoolbar, {
            
text:  l10n.setFeaturedImage,
            
statethis.options.state
        
});
    },

    
mainEmbedToolbar: function( toolbar ) {
        
toolbar.view = new wp.media.view.Toolbar.Embed({
            
controllerthis
        
});
    },

    
galleryEditToolbar: function() {
        var 
editing this.state().get('editing');
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     editing l10n.updateGallery l10n.insertGallery,
                    
priority80,
                    
requires: { librarytrue },

                    
/**
                     * @fires wp.media.controller.State#update
                     */
                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state();

                        
controller.close();
                        
state.trigger'update'state.get('library') );

                        
// Restore and reset the default state.
                        
controller.setStatecontroller.options.state );
                        
controller.reset();
                    }
                }
            }
        }) );
    },

    
galleryAddToolbar: function() {
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     l10n.addToGallery,
                    
priority80,
                    
requires: { selectiontrue },

                    
/**
                     * @fires wp.media.controller.State#reset
                     */
                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state(),
                            
edit controller.state('gallery-edit');

                        
edit.get('library').addstate.get('selection').models );
                        
state.trigger('reset');
                        
controller.setState('gallery-edit');
                    }
                }
            }
        }) );
    },

    
playlistEditToolbar: function() {
        var 
editing this.state().get('editing');
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     editing l10n.updatePlaylist l10n.insertPlaylist,
                    
priority80,
                    
requires: { librarytrue },

                    
/**
                     * @fires wp.media.controller.State#update
                     */
                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state();

                        
controller.close();
                        
state.trigger'update'state.get('library') );

                        
// Restore and reset the default state.
                        
controller.setStatecontroller.options.state );
                        
controller.reset();
                    }
                }
            }
        }) );
    },

    
playlistAddToolbar: function() {
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     l10n.addToPlaylist,
                    
priority80,
                    
requires: { selectiontrue },

                    
/**
                     * @fires wp.media.controller.State#reset
                     */
                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state(),
                            
edit controller.state('playlist-edit');

                        
edit.get('library').addstate.get('selection').models );
                        
state.trigger('reset');
                        
controller.setState('playlist-edit');
                    }
                }
            }
        }) );
    },

    
videoPlaylistEditToolbar: function() {
        var 
editing this.state().get('editing');
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     editing l10n.updateVideoPlaylist l10n.insertVideoPlaylist,
                    
priority140,
                    
requires: { librarytrue },

                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state(),
                            
library state.get('library');

                        
library.type 'video';

                        
controller.close();
                        
state.trigger'update'library );

                        
// Restore and reset the default state.
                        
controller.setStatecontroller.options.state );
                        
controller.reset();
                    }
                }
            }
        }) );
    },

    
videoPlaylistAddToolbar: function() {
        
this.toolbar.set( new wp.media.view.Toolbar({
            
controllerthis,
            
items: {
                
insert: {
                    
style:    'primary',
                    
text:     l10n.addToVideoPlaylist,
                    
priority140,
                    
requires: { selectiontrue },

                    
click: function() {
                        var 
controller this.controller,
                            
state controller.state(),
                            
edit controller.state('video-playlist-edit');

                        
edit.get('library').addstate.get('selection').models );
                        
state.trigger('reset');
                        
controller.setState('video-playlist-edit');
                    }
                }
            }
        }) );
    }
});

module.exports Post;

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

/**
 * wp.media.view.MediaFrame.Select
 *
 * A frame for selecting an item or items from the media library.
 *
 * @class
 * @augments wp.media.view.MediaFrame
 * @augments wp.media.view.Frame
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 * @mixes wp.media.controller.StateMachine
 */

var MediaFrame wp.media.view.MediaFrame,
    
l10n wp.media.view.l10n,
    
Select;

Select MediaFrame.extend({
    
initialize: function() {
        
// Call 'initialize' directly on the parent class.
        
MediaFrame.prototype.initialize.applythisarguments );

        
_.defaultsthis.options, {
            
selection: [],
            
library:   {},
            
multiple:  false,
            
state:    'library'
        
});

        
this.createSelection();
        
this.createStates();
        
this.bindHandlers();
    },

    
/**
     * Attach a selection collection to the frame.
     *
     * A selection is a collection of attachments used for a specific purpose
     * by a media frame. e.g. Selecting an attachment (or many) to insert into
     * post content.
     *
     * @see media.model.Selection
     */
    
createSelection: function() {
        var 
selection this.options.selection;

        if ( ! (
selection instanceof wp.media.model.Selection) ) {
            
this.options.selection = new wp.media.model.Selectionselection, {
                
multiplethis.options.multiple
            
});
        }

        
this._selection = {
            
attachments: new wp.media.model.Attachments(),
            
difference: []
        };
    },

    
/**
     * Create the default states on the frame.
     */
    
createStates: function() {
        var 
options this.options;

        if ( 
this.options.states ) {
            return;
        }

        
// Add the default states.
        
this.states.add([
            
// Main states.
            
new wp.media.controller.Library({
                
library:   wp.media.queryoptions.library ),
                
multiple:  options.multiple,
                
title:     options.title,
                
priority:  20
            
})
        ]);
    },

    
/**
     * Bind region mode event callbacks.
     *
     * @see media.controller.Region.render
     */
    
bindHandlers: function() {
        
this.on'router:create:browse'this.createRouterthis );
        
this.on'router:render:browse'this.browseRouterthis );
        
this.on'content:create:browse'this.browseContentthis );
        
this.on'content:render:upload'this.uploadContentthis );
        
this.on'toolbar:create:select'this.createSelectToolbarthis );
    },

    
/**
     * Render callback for the router region in the `browse` mode.
     *
     * @param {wp.media.view.Router} routerView
     */
    
browseRouter: function( routerView ) {
        
routerView.set({
            
upload: {
                
text:     l10n.uploadFilesTitle,
                
priority20
            
},
            
browse: {
                
text:     l10n.mediaLibraryTitle,
                
priority40
            
}
        });
    },

    
/**
     * Render callback for the content region in the `browse` mode.
     *
     * @param {wp.media.controller.Region} contentRegion
     */
    
browseContent: function( contentRegion ) {
        var 
state this.state();

        
this.$el.removeClass('hide-toolbar');

        
// Browse our library of attachments.
        
contentRegion.view = new wp.media.view.AttachmentsBrowser({
            
controllerthis,
            
collectionstate.get('library'),
            
selection:  state.get('selection'),
            
model:      state,
            
sortable:   state.get('sortable'),
            
search:     state.get('searchable'),
            
filters:    state.get('filterable'),
            
date:       state.get('date'),
            
display:    state.has('display') ? state.get('display') : state.get('displaySettings'),
            
dragInfo:   state.get('dragInfo'),

            
idealColumnWidthstate.get('idealColumnWidth'),
            
suggestedWidth:   state.get('suggestedWidth'),
            
suggestedHeight:  state.get('suggestedHeight'),

            
AttachmentViewstate.get('AttachmentView')
        });
    },

    
/**
     * Render callback for the content region in the `upload` mode.
     */
    
uploadContent: function() {
        
this.$el.removeClass'hide-toolbar' );
        
this.content.set( new wp.media.view.UploaderInline({
            
controllerthis
        
}) );
    },

    
/**
     * Toolbars
     *
     * @param {Object} toolbar
     * @param {Object} [options={}]
     * @this wp.media.controller.Region
     */
    
createSelectToolbar: function( toolbaroptions ) {
        
options options || this.options.button || {};
        
options.controller this;

        
toolbar.view = new wp.media.view.Toolbar.Selectoptions );
    }
});

module.exports Select;

},{}],
45:[function(require,module,exports){
/**
 * wp.media.view.Iframe
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Iframe wp.media.View.extend({
    
className'media-iframe',
    
/**
     * @returns {wp.media.view.Iframe} Returns itself to allow chaining
     */
    
render: function() {
        
this.views.detach();
        
this.$el.html'<iframe src="' this.controller.state().get('src') + '" />' );
        
this.views.render();
        return 
this;
    }
});

module.exports Iframe;

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

/**
 * wp.media.view.ImageDetails
 *
 * @class
 * @augments wp.media.view.Settings.AttachmentDisplay
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var AttachmentDisplay wp.media.view.Settings.AttachmentDisplay,
    $ = 
jQuery,
    
ImageDetails;

ImageDetails AttachmentDisplay.extend({
    
className'image-details',
    
template:  wp.template('image-details'),
    
events_.defaultsAttachmentDisplay.prototype.events, {
        
'click .edit-attachment''editAttachment',
        
'click .replace-attachment''replaceAttachment',
        
'click .advanced-toggle''onToggleAdvanced',
        
'change [data-setting="customWidth"]''onCustomSize',
        
'change [data-setting="customHeight"]''onCustomSize',
        
'keyup [data-setting="customWidth"]''onCustomSize',
        
'keyup [data-setting="customHeight"]''onCustomSize'
    
} ),
    
initialize: function() {
        
// used in AttachmentDisplay.prototype.updateLinkTo
        
this.options.attachment this.model.attachment;
        
this.listenTothis.model'change:url'this.updateUrl );
        
this.listenTothis.model'change:link'this.toggleLinkSettings );
        
this.listenTothis.model'change:size'this.toggleCustomSize );

        
AttachmentDisplay.prototype.initialize.applythisarguments );
    },

    
prepare: function() {
        var 
attachment false;

        if ( 
this.model.attachment ) {
            
attachment this.model.attachment.toJSON();
        }
        return 
_.defaults({
            
modelthis.model.toJSON(),
            
attachmentattachment
        
}, this.options );
    },

    
render: function() {
        var 
args arguments;

        if ( 
this.model.attachment && 'pending' === this.model.dfd.state() ) {
            
this.model.dfd
                
.done_.bind( function() {
                    
AttachmentDisplay.prototype.render.applythisargs );
                    
this.postRender();
                }, 
this ) )
                .
fail_.bind( function() {
                    
this.model.attachment false;
                    
AttachmentDisplay.prototype.render.applythisargs );
                    
this.postRender();
                }, 
this ) );
        } else {
            
AttachmentDisplay.prototype.render.applythisarguments );
            
this.postRender();
        }

        return 
this;
    },

    
postRender: function() {
        
setTimeout_.bindthis.resetFocusthis ), 10 );
        
this.toggleLinkSettings();
        if ( 
window.getUserSetting'advImgDetails' ) === 'show' ) {
            
this.toggleAdvancedtrue );
        }
        
this.trigger'post-render' );
    },

    
resetFocus: function() {
        
this.$( '.link-to-custom' ).blur();
        
this.$( '.embed-media-settings' ).scrollTop);
    },

    
updateUrl: function() {
        
this.$( '.image img' ).attr'src'this.model.get'url' ) );
        
this.$( '.url' ).valthis.model.get'url' ) );
    },

    
toggleLinkSettings: function() {
        if ( 
this.model.get'link' ) === 'none' ) {
            
this.$( '.link-settings' ).addClass('hidden');
        } else {
            
this.$( '.link-settings' ).removeClass('hidden');
        }
    },

    
toggleCustomSize: function() {
        if ( 
this.model.get'size' ) !== 'custom' ) {
            
this.$( '.custom-size' ).addClass('hidden');
        } else {
            
this.$( '.custom-size' ).removeClass('hidden');
        }
    },

    
onCustomSize: function( event ) {
        var 
dimension = $( event.target ).data('setting'),
            
num = $( event.target ).val(),
            
value;

        
// Ignore bogus input
        
if ( ! /^d+/.testnum ) || parseIntnum10 ) < ) {
            
event.preventDefault();
            return;
        }

        if ( 
dimension === 'customWidth' ) {
            
value Math.roundthis.model.get'aspectRatio' ) * num );
            
this.model.set'customHeight'value, { silenttrue } );
            
this.$( '[data-setting="customHeight"]' ).valvalue );
        } else {
            
value Math.roundthis.model.get'aspectRatio' ) * num );
            
this.model.set'customWidth'value, { silenttrue  } );
            
this.$( '[data-setting="customWidth"]' ).valvalue );
        }
    },

    
onToggleAdvanced: function( event ) {
        
event.preventDefault();
        
this.toggleAdvanced();
    },

    
toggleAdvanced: function( show ) {
        var 
$advanced this.$el.find'.advanced-section' ),
            
mode;

        if ( 
$advanced.hasClass('advanced-visible') || show === false ) {
            
$advanced.removeClass('advanced-visible');
            
$advanced.find('.advanced-settings').addClass('hidden');
            
mode 'hide';
        } else {
            
$advanced.addClass('advanced-visible');
            
$advanced.find('.advanced-settings').removeClass('hidden');
            
mode 'show';
        }

        
window.setUserSetting'advImgDetails'mode );
    },

    
editAttachment: function( event ) {
        var 
editState this.controller.states.get'edit-image' );

        if ( 
window.imageEdit && editState ) {
            
event.preventDefault();
            
editState.set'image'this.model.attachment );
            
this.controller.setState'edit-image' );
        }
    },

    
replaceAttachment: function( event ) {
        
event.preventDefault();
        
this.controller.setState'replace-image' );
    }
});

module.exports ImageDetails;

},{}],
47:[function(require,module,exports){
/**
 * wp.media.view.Label
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Label wp.media.View.extend({
    
tagName'label',
    
className'screen-reader-text',

    
initialize: function() {
        
this.value this.options.value;
    },

    
render: function() {
        
this.$el.htmlthis.value );

        return 
this;
    }
});

module.exports Label;

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

/**
 * wp.media.view.MediaFrame
 *
 * The frame used to create the media modal.
 *
 * @class
 * @augments wp.media.view.Frame
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 * @mixes wp.media.controller.StateMachine
 */
var Frame wp.media.view.Frame,
    $ = 
jQuery,
    
MediaFrame;

MediaFrame Frame.extend({
    
className'media-frame',
    
template:  wp.template('media-frame'),
    
regions:   ['menu','title','content','toolbar','router'],

    
events: {
        
'click div.media-frame-title h1''toggleMenu'
    
},

    
/**
     * @global wp.Uploader
     */
    
initialize: function() {
        
Frame.prototype.initialize.applythisarguments );

        
_.defaultsthis.options, {
            
title:    '',
            
modal:    true,
            
uploadertrue
        
});

        
// Ensure core UI is enabled.
        
this.$el.addClass('wp-core-ui');

        
// Initialize modal container view.
        
if ( this.options.modal ) {
            
this.modal = new wp.media.view.Modal({
                
controllerthis,
                
title:      this.options.title
            
});

            
this.modal.contentthis );
        }

        
// Force the uploader off if the upload limit has been exceeded or
        // if the browser isn't supported.
        
if ( wp.Uploader.limitExceeded || ! wp.Uploader.browser.supported ) {
            
this.options.uploader false;
        }

        
// Initialize window-wide uploader.
        
if ( this.options.uploader ) {
            
this.uploader = new wp.media.view.UploaderWindow({
                
controllerthis,
                
uploader: {
                    
dropzone:  this.modal this.modal.$el this.$el,
                    
containerthis.$el
                
}
            });
            
this.views.set'.media-frame-uploader'this.uploader );
        }

        
this.on'attach'_.bindthis.views.readythis.views ), this );

        
// Bind default title creation.
        
this.on'title:create:default'this.createTitlethis );
        
this.title.mode('default');

        
this.on'title:render', function( view ) {
            
view.$el.append'<span class="dashicons dashicons-arrow-down"></span>' );
        });

        
// Bind default menu.
        
this.on'menu:create:default'this.createMenuthis );
    },
    
/**
     * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
     */
    
render: function() {
        
// Activate the default state if no active state exists.
        
if ( ! this.state() && this.options.state ) {
            
this.setStatethis.options.state );
        }
        
/**
         * call 'render' directly on the parent class
         */
        
return Frame.prototype.render.applythisarguments );
    },
    
/**
     * @param {Object} title
     * @this wp.media.controller.Region
     */
    
createTitle: function( title ) {
        
title.view = new wp.media.View({
            
controllerthis,
            
tagName'h1'
        
});
    },
    
/**
     * @param {Object} menu
     * @this wp.media.controller.Region
     */
    
createMenu: function( menu ) {
        
menu.view = new wp.media.view.Menu({
            
controllerthis
        
});
    },

    
toggleMenu: function() {
        
this.$el.find'.media-menu' ).toggleClass'visible' );
    },

    
/**
     * @param {Object} toolbar
     * @this wp.media.controller.Region
     */
    
createToolbar: function( toolbar ) {
        
toolbar.view = new wp.media.view.Toolbar({
            
controllerthis
        
});
    },
    
/**
     * @param {Object} router
     * @this wp.media.controller.Region
     */
    
createRouter: function( router ) {
        
router.view = new wp.media.view.Router({
            
controllerthis
        
});
    },
    
/**
     * @param {Object} options
     */
    
createIframeStates: function( options ) {
        var 
settings wp.media.view.settings,
            
tabs settings.tabs,
            
tabUrl settings.tabUrl,
            
$postId;

        if ( ! 
tabs || ! tabUrl ) {
            return;
        }

        
// Add the post ID to the tab URL if it exists.
        
$postId = $('#post_ID');
        if ( 
$postId.length ) {
            
tabUrl += '&post_id=' $postId.val();
        }

        
// Generate the tab states.
        
_.eachtabs, function( titleid ) {
            
this.state'iframe:' id ).set_.defaults({
                
tab:     id,
                
src:     tabUrl '&tab=' id,
                
title:   title,
                
content'iframe',
                
menu:    'default'
            
}, options ) );
        }, 
this );

        
this.on'content:create:iframe'this.iframeContentthis );
        
this.on'content:deactivate:iframe'this.iframeContentCleanupthis );
        
this.on'menu:render:default'this.iframeMenuthis );
        
this.on'open'this.hijackThickboxthis );
        
this.on'close'this.restoreThickboxthis );
    },

    
/**
     * @param {Object} content
     * @this wp.media.controller.Region
     */
    
iframeContent: function( content ) {
        
this.$el.addClass('hide-toolbar');
        
content.view = new wp.media.view.Iframe({
            
controllerthis
        
});
    },

    
iframeContentCleanup: function() {
        
this.$el.removeClass('hide-toolbar');
    },

    
iframeMenu: function( view ) {
        var 
views = {};

        if ( ! 
view ) {
            return;
        }

        
_.eachwp.media.view.settings.tabs, function( titleid ) {
            
views'iframe:' id ] = {
                
textthis.state'iframe:' id ).get('title'),
                
priority200
            
};
        }, 
this );

        
view.setviews );
    },

    
hijackThickbox: function() {
        var 
frame this;

        if ( ! 
window.tb_remove || this._tb_remove ) {
            return;
        }

        
this._tb_remove window.tb_remove;
        
window.tb_remove = function() {
            
frame.close();
            
frame.reset();
            
frame.setStateframe.options.state );
            
frame._tb_remove.callwindow );
        };
    },

    
restoreThickbox: function() {
        if ( ! 
this._tb_remove ) {
            return;
        }

        
window.tb_remove this._tb_remove;
        
delete this._tb_remove;
    }
});

// Map some of the modal's methods to the frame.
_.each(['open','close','attach','detach','escape'], function( method ) {
    
/**
     * @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
     */
    
MediaFrame.prototypemethod ] = function() {
        if ( 
this.modal ) {
            
this.modalmethod ].applythis.modalarguments );
        }
        return 
this;
    };
});

module.exports MediaFrame;

},{}],
49:[function(require,module,exports){
/*globals jQuery */

/**
 * wp.media.view.MenuItem
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var $ = jQuery,
    
MenuItem;

MenuItem wp.media.View.extend({
    
tagName:   'a',
    
className'media-menu-item',

    
attributes: {
        
href'#'
    
},

    
events: {
        
'click''_click'
    
},
    
/**
     * @param {Object} event
     */
    
_click: function( event ) {
        var 
clickOverride this.options.click;

        if ( 
event ) {
            
event.preventDefault();
        }

        if ( 
clickOverride ) {
            
clickOverride.callthis );
        } else {
            
this.click();
        }

        
// When selecting a tab along the left side,
        // focus should be transferred into the main panel
        
if ( ! wp.media.isTouchDevice ) {
            $(
'.media-frame-content input').first().focus();
        }
    },

    
click: function() {
        var 
state this.options.state;

        if ( 
state ) {
            
this.controller.setStatestate );
            
this.views.parent.$el.removeClass'visible' ); // TODO: or hide on any click, see below
        
}
    },
    
/**
     * @returns {wp.media.view.MenuItem} returns itself to allow chaining
     */
    
render: function() {
        var 
options this.options;

        if ( 
options.text ) {
            
this.$el.textoptions.text );
        } else if ( 
options.html ) {
            
this.$el.htmloptions.html );
        }

        return 
this;
    }
});

module.exports MenuItem;

},{}],
50:[function(require,module,exports){
/**
 * wp.media.view.Menu
 *
 * @class
 * @augments wp.media.view.PriorityList
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var MenuItem wp.media.view.MenuItem,
    
PriorityList wp.media.view.PriorityList,
    
Menu;

Menu PriorityList.extend({
    
tagName:   'div',
    
className'media-menu',
    
property:  'state',
    
ItemView:  MenuItem,
    
region:    'menu',

    
/* TODO: alternatively hide on any click anywhere
    events: {
        'click': 'click'
    },

    click: function() {
        this.$el.removeClass( 'visible' );
    },
    */

    /**
     * @param {Object} options
     * @param {string} id
     * @returns {wp.media.View}
     */
    
toView: function( optionsid ) {
        
options options || {};
        
optionsthis.property ] = optionsthis.property ] || id;
        return new 
this.ItemViewoptions ).render();
    },

    
ready: function() {
        
/**
         * call 'ready' directly on the parent class
         */
        
PriorityList.prototype.ready.applythisarguments );
        
this.visibility();
    },

    
set: function() {
        
/**
         * call 'set' directly on the parent class
         */
        
PriorityList.prototype.set.applythisarguments );
        
this.visibility();
    },

    unset: function() {
        
/**
         * call 'unset' directly on the parent class
         */
        
PriorityList.prototype.unset.applythisarguments );
        
this.visibility();
    },

    
visibility: function() {
        var 
region this.region,
            
view this.controllerregion ].get(),
            
views this.views.get(),
            
hide = ! views || views.length 2;

        if ( 
this === view ) {
            
this.controller.$el.toggleClass'hide-' regionhide );
        }
    },
    
/**
     * @param {string} id
     */
    
select: function( id ) {
        var 
view this.getid );

        if ( ! 
view ) {
            return;
        }

        
this.deselect();
        
view.$el.addClass('active');
    },

    
deselect: function() {
        
this.$el.children().removeClass('active');
    },

    
hide: function( id ) {
        var 
view this.getid );

        if ( ! 
view ) {
            return;
        }

        
view.$el.addClass('hidden');
    },

    
show: function( id ) {
        var 
view this.getid );

        if ( ! 
view ) {
            return;
        }

        
view.$el.removeClass('hidden');
    }
});

module.exports Menu;

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

/**
 * wp.media.view.Modal
 *
 * A modal view, which the media modal uses as its default container.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var $ = jQuery,
    
Modal;

Modal wp.media.View.extend({
    
tagName:  'div',
    
templatewp.template('media-modal'),

    
attributes: {
        
tabindex0
    
},

    
events: {
        
'click .media-modal-backdrop, .media-modal-close''escapeHandler',
        
'keydown''keydown'
    
},

    
initialize: function() {
        
_.defaultsthis.options, {
            
containerdocument.body,
            
title:     '',
            
propagatetrue,
            
freeze:    true
        
});

        
this.focusManager = new wp.media.view.FocusManager({
            
elthis.el
        
});
    },
    
/**
     * @returns {Object}
     */
    
prepare: function() {
        return {
            
titlethis.options.title
        
};
    },

    
/**
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
attach: function() {
        if ( 
this.views.attached ) {
            return 
this;
        }

        if ( ! 
this.views.rendered ) {
            
this.render();
        }

        
this.$el.appendTothis.options.container );

        
// Manually mark the view as attached and trigger ready.
        
this.views.attached true;
        
this.views.ready();

        return 
this.propagate('attach');
    },

    
/**
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
detach: function() {
        if ( 
this.$el.is(':visible') ) {
            
this.close();
        }

        
this.$el.detach();
        
this.views.attached false;
        return 
this.propagate('detach');
    },

    
/**
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
open: function() {
        var 
$el this.$el,
            
options this.options,
            
mceEditor;

        if ( 
$el.is(':visible') ) {
            return 
this;
        }

        if ( ! 
this.views.attached ) {
            
this.attach();
        }

        
// If the `freeze` option is set, record the window's scroll position.
        
if ( options.freeze ) {
            
this._freeze = {
                
scrollTop: $( window ).scrollTop()
            };
        }

        
// Disable page scrolling.
        
$( 'body' ).addClass'modal-open' );

        
$el.show();

        
// Try to close the onscreen keyboard
        
if ( 'ontouchend' in document ) {
            if ( ( 
mceEditor window.tinymce && window.tinymce.activeEditor )  && ! mceEditor.isHidden() && mceEditor.iframeElement ) {
                
mceEditor.iframeElement.focus();
                
mceEditor.iframeElement.blur();

                
setTimeout( function() {
                    
mceEditor.iframeElement.blur();
                }, 
100 );
            }
        }

        
this.$el.focus();

        return 
this.propagate('open');
    },

    
/**
     * @param {Object} options
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
close: function( options ) {
        var 
freeze this._freeze;

        if ( ! 
this.views.attached || ! this.$el.is(':visible') ) {
            return 
this;
        }

        
// Enable page scrolling.
        
$( 'body' ).removeClass'modal-open' );

        
// Hide modal and remove restricted media modal tab focus once it's closed
        
this.$el.hide().undelegate'keydown' );

        
// Put focus back in useful location once modal is closed
        
$('#wpbody-content').focus();

        
this.propagate('close');

        
// If the `freeze` option is set, restore the container's scroll position.
        
if ( freeze ) {
            $( 
window ).scrollTopfreeze.scrollTop );
        }

        if ( 
options && options.escape ) {
            
this.propagate('escape');
        }

        return 
this;
    },
    
/**
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
escape: function() {
        return 
this.close({ escapetrue });
    },
    
/**
     * @param {Object} event
     */
    
escapeHandler: function( event ) {
        
event.preventDefault();
        
this.escape();
    },

    
/**
     * @param {Array|Object} content Views to register to '.media-modal-content'
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
content: function( content ) {
        
this.views.set'.media-modal-content'content );
        return 
this;
    },

    
/**
     * Triggers a modal event and if the `propagate` option is set,
     * forwards events to the modal's controller.
     *
     * @param {string} id
     * @returns {wp.media.view.Modal} Returns itself to allow chaining
     */
    
propagate: function( id ) {
        
this.triggerid );

        if ( 
this.options.propagate ) {
            
this.controller.triggerid );
        }

        return 
this;
    },
    
/**
     * @param {Object} event
     */
    
keydown: function( event ) {
        
// Close the modal when escape is pressed.
        
if ( 27 === event.which && this.$el.is(':visible') ) {
            
this.escape();
            
event.stopImmediatePropagation();
        }
    }
});

module.exports Modal;

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

/**
 * wp.media.view.PriorityList
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var PriorityList wp.media.View.extend({
    
tagName:   'div',

    
initialize: function() {
        
this._views = {};

        
this.set_.extend( {}, this._viewsthis.options.views ), { silenttrue });
        
delete this.options.views;

        if ( ! 
this.options.silent ) {
            
this.render();
        }
    },
    
/**
     * @param {string} id
     * @param {wp.media.View|Object} view
     * @param {Object} options
     * @returns {wp.media.view.PriorityList} Returns itself to allow chaining
     */
    
set: function( idviewoptions ) {
        var 
priorityviewsindex;

        
options options || {};

        
// Accept an object with an `id` : `view` mapping.
        
if ( _.isObjectid ) ) {
            
_.eachid, function( viewid ) {
                
this.setidview );
            }, 
this );
            return 
this;
        }

        if ( ! (
view instanceof Backbone.View) ) {
            
view this.toViewviewidoptions );
        }
        
view.controller view.controller || this.controller;

        
this.unset( id );

        
priority view.options.priority || 10;
        
views this.views.get() || [];

        
_.findviews, function( existing) {
            if ( 
existing.options.priority priority ) {
                
index i;
                return 
true;
            }
        });

        
this._viewsid ] = view;
        
this.views.addview, {
            
at_.isNumberindex ) ? index views.length || 0
        
});

        return 
this;
    },
    
/**
     * @param {string} id
     * @returns {wp.media.View}
     */
    
get: function( id ) {
        return 
this._viewsid ];
    },
    
/**
     * @param {string} id
     * @returns {wp.media.view.PriorityList}
     */
    
unset: function( id ) {
        var 
view this.getid );

        if ( 
view ) {
            
view.remove();
        }

        
delete this._viewsid ];
        return 
this;
    },
    
/**
     * @param {Object} options
     * @returns {wp.media.View}
     */
    
toView: function( options ) {
        return new 
wp.media.Viewoptions );
    }
});

module.exports PriorityList;

},{}],
53:[function(require,module,exports){
/**
 * wp.media.view.RouterItem
 *
 * @class
 * @augments wp.media.view.MenuItem
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var RouterItem wp.media.view.MenuItem.extend({
    
/**
     * On click handler to activate the content region's corresponding mode.
     */
    
click: function() {
        var 
contentMode this.options.contentMode;
        if ( 
contentMode ) {
            
this.controller.content.modecontentMode );
        }
    }
});

module.exports RouterItem;

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

/**
 * wp.media.view.Router
 *
 * @class
 * @augments wp.media.view.Menu
 * @augments wp.media.view.PriorityList
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Menu wp.media.view.Menu,
    
Router;

Router Menu.extend({
    
tagName:   'div',
    
className'media-router',
    
property:  'contentMode',
    
ItemView:  wp.media.view.RouterItem,
    
region:    'router',

    
initialize: function() {
        
this.controller.on'content:render'this.updatethis );
        
// Call 'initialize' directly on the parent class.
        
Menu.prototype.initialize.applythisarguments );
    },

    
update: function() {
        var 
mode this.controller.content.mode();
        if ( 
mode ) {
            
this.selectmode );
        }
    }
});

module.exports Router;

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

/**
 * wp.media.view.Search
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var l10n wp.media.view.l10n,
    
Search;

Search wp.media.View.extend({
    
tagName:   'input',
    
className'search',
    
id:        'media-search-input',

    
attributes: {
        
type:        'search',
        
placeholderl10n.search
    
},

    
events: {
        
'input':  'search',
        
'keyup':  'search',
        
'change''search',
        
'search''search'
    
},

    
/**
     * @returns {wp.media.view.Search} Returns itself to allow chaining
     */
    
render: function() {
        
this.el.value this.model.escape('search');
        return 
this;
    },

    
search: function( event ) {
        if ( 
event.target.value ) {
            
this.model.set'search'event.target.value );
        } else {
            
this.model.unset('search');
        }
    }
});

module.exports Search;

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

/**
 * wp.media.view.Selection
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var l10n wp.media.view.l10n,
    
Selection;

Selection wp.media.View.extend({
    
tagName:   'div',
    
className'media-selection',
    
template:  wp.template('media-selection'),

    
events: {
        
'click .edit-selection':  'edit',
        
'click .clear-selection''clear'
    
},

    
initialize: function() {
        
_.defaultsthis.options, {
            
editable:  false,
            
clearabletrue
        
});

        
/**
         * @member {wp.media.view.Attachments.Selection}
         */
        
this.attachments = new wp.media.view.Attachments.Selection({
            
controllerthis.controller,
            
collectionthis.collection,
            
selection:  this.collection,
            
model:      new Backbone.Model()
        });

        
this.views.set'.selection-view'this.attachments );
        
this.collection.on'add remove reset'this.refreshthis );
        
this.controller.on'content:activate'this.refreshthis );
    },

    
ready: function() {
        
this.refresh();
    },

    
refresh: function() {
        
// If the selection hasn't been rendered, bail.
        
if ( ! this.$el.children().length ) {
            return;
        }

        var 
collection this.collection,
            
editing 'edit-selection' === this.controller.content.mode();

        
// If nothing is selected, display nothing.
        
this.$el.toggleClass'empty', ! collection.length );
        
this.$el.toggleClass'one'=== collection.length );
        
this.$el.toggleClass'editing'editing );

        
this.$('.count').textl10n.selected.replace('%d'collection.length) );
    },

    
edit: function( event ) {
        
event.preventDefault();
        if ( 
this.options.editable ) {
            
this.options.editable.callthisthis.collection );
        }
    },

    
clear: function( event ) {
        
event.preventDefault();
        
this.collection.reset();

        
// Keep focus inside media modal
        // after clear link is selected
        
this.controller.modal.focusManager.focus();
    }
});

module.exports Selection;

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

/**
 * wp.media.view.Settings
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    $ = 
Backbone.$,
    
Settings;

Settings View.extend({
    
events: {
        
'click button':    'updateHandler',
        
'change input':    'updateHandler',
        
'change select':   'updateHandler',
        
'change textarea''updateHandler'
    
},

    
initialize: function() {
        
this.model this.model || new Backbone.Model();
        
this.listenTothis.model'change'this.updateChanges );
    },

    
prepare: function() {
        return 
_.defaults({
            
modelthis.model.toJSON()
        }, 
this.options );
    },
    
/**
     * @returns {wp.media.view.Settings} Returns itself to allow chaining
     */
    
render: function() {
        
View.prototype.render.applythisarguments );
        
// Select the correct values.
        
_this.model.attributes ).chain().keys().eachthis.updatethis );
        return 
this;
    },
    
/**
     * @param {string} key
     */
    
update: function( key ) {
        var 
value this.model.getkey ),
            
$setting this.$('[data-setting="' key '"]'),
            
$buttons$value;

        
// Bail if we didn't find a matching setting.
        
if ( ! $setting.length ) {
            return;
        }

        
// Attempt to determine how the setting is rendered and update
        // the selected value.

        // Handle dropdowns.
        
if ( $setting.is('select') ) {
            
$value $setting.find('[value="' value '"]');

            if ( 
$value.length ) {
                
$setting.find('option').prop'selected'false );
                
$value.prop'selected'true );
            } else {
                
// If we can't find the desired value, record what *is* selected.
                
this.model.setkey$setting.find(':selected').val() );
            }

        
// Handle button groups.
        
} else if ( $setting.hasClass('button-group') ) {
            
$buttons $setting.find('button').removeClass('active');
            
$buttons.filter'[value="' value '"]' ).addClass('active');

        
// Handle text inputs and textareas.
        
} else if ( $setting.is('input[type="text"], textarea') ) {
            if ( ! 
$setting.is(':focus') ) {
                
$setting.valvalue );
            }
        
// Handle checkboxes.
        
} else if ( $setting.is('input[type="checkbox"]') ) {
            
$setting.prop'checked', !! value && 'false' !== value );
        }
    },
    
/**
     * @param {Object} event
     */
    
updateHandler: function( event ) {
        var 
$setting = $( event.target ).closest('[data-setting]'),
            
value event.target.value,
            
userSetting;

        
event.preventDefault();

        if ( ! 
$setting.length ) {
            return;
        }

        
// Use the correct value for checkboxes.
        
if ( $setting.is('input[type="checkbox"]') ) {
            
value $setting[0].checked;
        }

        
// Update the corresponding setting.
        
this.model.set$setting.data('setting'), value );

        
// If the setting has a corresponding user setting,
        // update that as well.
        
if ( userSetting $setting.data('userSetting') ) {
            
window.setUserSettinguserSettingvalue );
        }
    },

    
updateChanges: function( model ) {
        if ( 
model.hasChanged() ) {
            
_model.changed ).chain().keys().eachthis.updatethis );
        }
    }
});

module.exports Settings;

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

/**
 * wp.media.view.Settings.AttachmentDisplay
 *
 * @class
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Settings wp.media.view.Settings,
    
AttachmentDisplay;

AttachmentDisplay Settings.extend({
    
className'attachment-display-settings',
    
template:  wp.template('attachment-display-settings'),

    
initialize: function() {
        var 
attachment this.options.attachment;

        
_.defaultsthis.options, {
            
userSettingsfalse
        
});
        
// Call 'initialize' directly on the parent class.
        
Settings.prototype.initialize.applythisarguments );
        
this.listenTothis.model'change:link'this.updateLinkTo );

        if ( 
attachment ) {
            
attachment.on'change:uploading'this.renderthis );
        }
    },

    
dispose: function() {
        var 
attachment this.options.attachment;
        if ( 
attachment ) {
            
attachment.offnullnullthis );
        }
        
/**
         * call 'dispose' directly on the parent class
         */
        
Settings.prototype.dispose.applythisarguments );
    },
    
/**
     * @returns {wp.media.view.AttachmentDisplay} Returns itself to allow chaining
     */
    
render: function() {
        var 
attachment this.options.attachment;
        if ( 
attachment ) {
            
_.extendthis.options, {
                
sizesattachment.get('sizes'),
                
type:  attachment.get('type')
            });
        }
        
/**
         * call 'render' directly on the parent class
         */
        
Settings.prototype.render.callthis );
        
this.updateLinkTo();
        return 
this;
    },

    
updateLinkTo: function() {
        var 
linkTo this.model.get('link'),
            
$input this.$('.link-to-custom'),
            
attachment this.options.attachment;

        if ( 
'none' === linkTo || 'embed' === linkTo || ( ! attachment && 'custom' !== linkTo ) ) {
            
$input.addClass'hidden' );
            return;
        }

        if ( 
attachment ) {
            if ( 
'post' === linkTo ) {
                
$input.valattachment.get('link') );
            } else if ( 
'file' === linkTo ) {
                
$input.valattachment.get('url') );
            } else if ( ! 
this.model.get('linkUrl') ) {
                
$input.val('http://');
            }

            
$input.prop'readonly''custom' !== linkTo );
        }

        
$input.removeClass'hidden' );

        
// If the input is visible, focus and select its contents.
        
if ( ! wp.media.isTouchDevice && $input.is(':visible') ) {
            
$input.focus()[0].select();
        }
    }
});

module.exports AttachmentDisplay;

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

/**
 * wp.media.view.Settings.Gallery
 *
 * @class
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Gallery wp.media.view.Settings.extend({
    
className'collection-settings gallery-settings',
    
template:  wp.template('gallery-settings')
});

module.exports Gallery;

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

/**
 * wp.media.view.Settings.Playlist
 *
 * @class
 * @augments wp.media.view.Settings
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Playlist wp.media.view.Settings.extend({
    
className'collection-settings playlist-settings',
    
template:  wp.template('playlist-settings')
});

module.exports Playlist;

},{}],
61:[function(require,module,exports){
/**
 * wp.media.view.Sidebar
 *
 * @class
 * @augments wp.media.view.PriorityList
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Sidebar wp.media.view.PriorityList.extend({
    
className'media-sidebar'
});

module.exports Sidebar;

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

/**
 * wp.media.view.Spinner
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Spinner wp.media.View.extend({
    
tagName:   'span',
    
className'spinner',
    
spinnerTimeoutfalse,
    
delay400,

    
show: function() {
        if ( ! 
this.spinnerTimeout ) {
            
this.spinnerTimeout _.delay(function( $el ) {
                
$el.addClass'is-active' );
            }, 
this.delaythis.$el );
        }

        return 
this;
    },

    
hide: function() {
        
this.$el.removeClass'is-active' );
        
this.spinnerTimeout clearTimeoutthis.spinnerTimeout );

        return 
this;
    }
});

module.exports Spinner;

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

/**
 * wp.media.view.Toolbar
 *
 * A toolbar which consists of a primary and a secondary section. Each sections
 * can be filled with views.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
Toolbar;

Toolbar View.extend({
    
tagName:   'div',
    
className'media-toolbar',

    
initialize: function() {
        var 
state this.controller.state(),
            
selection this.selection state.get('selection'),
            
library this.library state.get('library');

        
this._views = {};

        
// The toolbar is composed of two `PriorityList` views.
        
this.primary   = new wp.media.view.PriorityList();
        
this.secondary = new wp.media.view.PriorityList();
        
this.primary.$el.addClass('media-toolbar-primary search-form');
        
this.secondary.$el.addClass('media-toolbar-secondary');

        
this.views.set([ this.secondarythis.primary ]);

        if ( 
this.options.items ) {
            
this.setthis.options.items, { silenttrue });
        }

        if ( ! 
this.options.silent ) {
            
this.render();
        }

        if ( 
selection ) {
            
selection.on'add remove reset'this.refreshthis );
        }

        if ( 
library ) {
            
library.on'add remove reset'this.refreshthis );
        }
    },
    
/**
     * @returns {wp.media.view.Toolbar} Returns itsef to allow chaining
     */
    
dispose: function() {
        if ( 
this.selection ) {
            
this.selection.offnullnullthis );
        }

        if ( 
this.library ) {
            
this.library.offnullnullthis );
        }
        
/**
         * call 'dispose' directly on the parent class
         */
        
return View.prototype.dispose.applythisarguments );
    },

    
ready: function() {
        
this.refresh();
    },

    
/**
     * @param {string} id
     * @param {Backbone.View|Object} view
     * @param {Object} [options={}]
     * @returns {wp.media.view.Toolbar} Returns itself to allow chaining
     */
    
set: function( idviewoptions ) {
        var list;
        
options options || {};

        
// Accept an object with an `id` : `view` mapping.
        
if ( _.isObjectid ) ) {
            
_.eachid, function( viewid ) {
                
this.setidview, { silenttrue });
            }, 
this );

        } else {
            if ( ! ( 
view instanceof Backbone.View ) ) {
                
view.classes = [ 'media-button-' id ].concatview.classes || [] );
                
view = new wp.media.view.Buttonview ).render();
            }

            
view.controller view.controller || this.controller;

            
this._viewsid ] = view;

            list = 
view.options.priority 'secondary' 'primary';
            
this[ list ].setidviewoptions );
        }

        if ( ! 
options.silent ) {
            
this.refresh();
        }

        return 
this;
    },
    
/**
     * @param {string} id
     * @returns {wp.media.view.Button}
     */
    
get: function( id ) {
        return 
this._viewsid ];
    },
    
/**
     * @param {string} id
     * @param {Object} options
     * @returns {wp.media.view.Toolbar} Returns itself to allow chaining
     */
    
unset: function( idoptions ) {
        
delete this._viewsid ];
        
this.primary.unset( idoptions );
        
this.secondary.unset( idoptions );

        if ( ! 
options || ! options.silent ) {
            
this.refresh();
        }
        return 
this;
    },

    
refresh: function() {
        var 
state this.controller.state(),
            
library state.get('library'),
            
selection state.get('selection');

        
_.eachthis._views, function( button ) {
            if ( ! 
button.model || ! button.options || ! button.options.requires ) {
                return;
            }

            var 
requires button.options.requires,
                
disabled false;

            
// Prevent insertion of attachments if any of them are still uploading
            
disabled _.someselection.models, function( attachment ) {
                return 
attachment.get('uploading') === true;
            });

            if ( 
requires.selection && selection && ! selection.length ) {
                
disabled true;
            } else if ( 
requires.library && library && ! library.length ) {
                
disabled true;
            }
            
button.model.set'disabled'disabled );
        });
    }
});

module.exports Toolbar;

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

/**
 * wp.media.view.Toolbar.Embed
 *
 * @class
 * @augments wp.media.view.Toolbar.Select
 * @augments wp.media.view.Toolbar
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Select wp.media.view.Toolbar.Select,
    
l10n wp.media.view.l10n,
    
Embed;

Embed Select.extend({
    
initialize: function() {
        
_.defaultsthis.options, {
            
textl10n.insertIntoPost,
            
requiresfalse
        
});
        
// Call 'initialize' directly on the parent class.
        
Select.prototype.initialize.applythisarguments );
    },

    
refresh: function() {
        var 
url this.controller.state().props.get('url');
        
this.get('select').model.set'disabled', ! url || url === 'http://' );
        
/**
         * call 'refresh' directly on the parent class
         */
        
Select.prototype.refresh.applythisarguments );
    }
});

module.exports Embed;

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

/**
 * wp.media.view.Toolbar.Select
 *
 * @class
 * @augments wp.media.view.Toolbar
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var Toolbar wp.media.view.Toolbar,
    
l10n wp.media.view.l10n,
    
Select;

Select Toolbar.extend({
    
initialize: function() {
        var 
options this.options;

        
_.bindAllthis'clickSelect' );

        
_.defaultsoptions, {
            
event'select',
            
statefalse,
            
resettrue,
            
closetrue,
            
text:  l10n.select,

            
// Does the button rely on the selection?
            
requires: {
                
selectiontrue
            
}
        });

        
options.items _.defaultsoptions.items || {}, {
            
select: {
                
style:    'primary',
                
text:     options.text,
                
priority80,
                
click:    this.clickSelect,
                
requiresoptions.requires
            
}
        });
        
// Call 'initialize' directly on the parent class.
        
Toolbar.prototype.initialize.applythisarguments );
    },

    
clickSelect: function() {
        var 
options this.options,
            
controller this.controller;

        if ( 
options.close ) {
            
controller.close();
        }

        if ( 
options.event ) {
            
controller.state().triggeroptions.event );
        }

        if ( 
options.state ) {
            
controller.setStateoptions.state );
        }

        if ( 
options.reset ) {
            
controller.reset();
        }
    }
});

module.exports Select;

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

/**
 * Creates a dropzone on WP editor instances (elements with .wp-editor-wrap
 * or #wp-fullscreen-body) and relays drag'n'dropped files to a media workflow.
 *
 * wp.media.view.EditorUploader
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
l10n wp.media.view.l10n,
    $ = 
jQuery,
    
EditorUploader;

EditorUploader View.extend({
    
tagName:   'div',
    
className'uploader-editor',
    
template:  wp.template'uploader-editor' ),

    
localDragfalse,
    
overContainerfalse,
    
overDropzonefalse,
    
draggingFilenull,

    
/**
     * Bind drag'n'drop events to callbacks.
     */
    
initialize: function() {
        
this.initialized false;

        
// Bail if not enabled or UA does not support drag'n'drop or File API.
        
if ( ! window.tinyMCEPreInit || ! window.tinyMCEPreInit.dragDropUpload || ! this.browserSupport() ) {
            return 
this;
        }

        
this.$document = $(document);
        
this.dropzones = [];
        
this.files = [];

        
this.$document.on'drop''.uploader-editor'_.bindthis.dropthis ) );
        
this.$document.on'dragover''.uploader-editor'_.bindthis.dropzoneDragoverthis ) );
        
this.$document.on'dragleave''.uploader-editor'_.bindthis.dropzoneDragleavethis ) );
        
this.$document.on'click''.uploader-editor'_.bindthis.clickthis ) );

        
this.$document.on'dragover'_.bindthis.containerDragoverthis ) );
        
this.$document.on'dragleave'_.bindthis.containerDragleavethis ) );

        
this.$document.on'dragstart dragend drop'_.bind( function( event ) {
            
this.localDrag event.type === 'dragstart';
        }, 
this ) );

        
this.initialized true;
        return 
this;
    },

    
/**
     * Check browser support for drag'n'drop.
     *
     * @return Boolean
     */
    
browserSupport: function() {
        var 
supports falsediv document.createElement('div');

        
supports = ( 'draggable' in div ) || ( 'ondragstart' in div && 'ondrop' in div );
        
supports supports && !! ( window.File && window.FileList && window.FileReader );
        return 
supports;
    },

    
isDraggingFile: function( event ) {
        if ( 
this.draggingFile !== null ) {
            return 
this.draggingFile;
        }

        if ( 
_.isUndefinedevent.originalEvent ) || _.isUndefinedevent.originalEvent.dataTransfer ) ) {
            return 
false;
        }

        
this.draggingFile _.indexOfevent.originalEvent.dataTransfer.types'Files' ) > -&&
            
_.indexOfevent.originalEvent.dataTransfer.types'text/plain' ) === -1;

        return 
this.draggingFile;
    },

    
refresh: function( ) {
        var 
dropzone_id;
        for ( 
dropzone_id in this.dropzones ) {
            
// Hide the dropzones only if dragging has left the screen.
            
this.dropzonesdropzone_id ].togglethis.overContainer || this.overDropzone );
        }

        if ( ! 
_.isUndefined) ) {
            $( 
e.target ).closest'.uploader-editor' ).toggleClass'droppable'this.overDropzone );
        }

        if ( ! 
this.overContainer && ! this.overDropzone ) {
            
this.draggingFile null;
        }

        return 
this;
    },

    
render: function() {
        if ( ! 
this.initialized ) {
            return 
this;
        }

        
View.prototype.render.applythisarguments );
        $( 
'.wp-editor-wrap, #wp-fullscreen-body' ).each_.bindthis.attachthis ) );
        return 
this;
    },

    
attach: function( indexeditor ) {
        
// Attach a dropzone to an editor.
        
var dropzone this.$el.clone();
        
this.dropzones.pushdropzone );
        $( 
editor ).appenddropzone );
        return 
this;
    },

    
/**
     * When a file is dropped on the editor uploader, open up an editor media workflow
     * and upload the file immediately.
     *
     * @param  {jQuery.Event} event The 'drop' event.
     */
    
drop: function( event ) {
        var 
$wrap nulluploadView;

        
this.containerDragleaveevent );
        
this.dropzoneDragleaveevent );

        
this.files event.originalEvent.dataTransfer.files;
        if ( 
this.files.length ) {
            return;
        }

        
// Set the active editor to the drop target.
        
$wrap = $( event.target ).parents'.wp-editor-wrap' );
        if ( 
$wrap.length && $wrap[0].id ) {
            
window.wpActiveEditor $wrap[0].id.slice3, -);
        }

        if ( ! 
this.workflow ) {
            
this.workflow wp.media.editor.open'content', {
                
frame:    'post',
                
state:    'insert',
                
title:    l10n.addMedia,
                
multipletrue
            
});
            
uploadView this.workflow.uploader;
            if ( 
uploadView.uploader && uploadView.uploader.ready ) {
                
this.addFiles.applythis );
            } else {
                
this.workflow.on'uploader:ready'this.addFilesthis );
            }
        } else {
            
this.workflow.state().reset();
            
this.addFiles.applythis );
            
this.workflow.open();
        }

        return 
false;
    },

    
/**
     * Add the files to the uploader.
     */
    
addFiles: function() {
        if ( 
this.files.length ) {
            
this.workflow.uploader.uploader.uploader.addFile_.toArraythis.files ) );
            
this.files = [];
        }
        return 
this;
    },

    
containerDragover: function( event ) {
        if ( 
this.localDrag || ! this.isDraggingFileevent ) ) {
            return;
        }

        
this.overContainer true;
        
this.refresh();
    },

    
containerDragleave: function() {
        
this.overContainer false;

        
// Throttle dragleave because it's called when bouncing from some elements to others.
        
_.delay_.bindthis.refreshthis ), 50 );
    },

    
dropzoneDragover: function( event ) {
        if ( 
this.localDrag || ! this.isDraggingFileevent ) ) {
            return;
        }

        
this.overDropzone true;
        
this.refreshevent );
        return 
false;
    },

    
dropzoneDragleave: function( ) {
        
this.overDropzone false;
        
_.delay_.bindthis.refreshthis), 50 );
    },

    
click: function( ) {
        
// In the rare case where the dropzone gets stuck, hide it on click.
        
this.containerDragleave);
        
this.dropzoneDragleave);
        
this.localDrag false;
    }
});

module.exports EditorUploader;

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

/**
 * wp.media.view.UploaderInline
 *
 * The inline uploader that shows up in the 'Upload Files' tab.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
UploaderInline;

UploaderInline View.extend({
    
tagName:   'div',
    
className'uploader-inline',
    
template:  wp.template('uploader-inline'),

    
events: {
        
'click .close''hide'
    
},

    
initialize: function() {
        
_.defaultsthis.options, {
            
message'',
            
status:  true,
            
canClosefalse
        
});

        if ( ! 
this.options.$browser && this.controller.uploader ) {
            
this.options.$browser this.controller.uploader.$browser;
        }

        if ( 
_.isUndefinedthis.options.postId ) ) {
            
this.options.postId wp.media.view.settings.post.id;
        }

        if ( 
this.options.status ) {
            
this.views.set'.upload-inline-status', new wp.media.view.UploaderStatus({
                
controllerthis.controller
            
}) );
        }
    },

    
prepare: function() {
        var 
suggestedWidth this.controller.state().get('suggestedWidth'),
            
suggestedHeight this.controller.state().get('suggestedHeight'),
            
data = {};

        
data.message this.options.message;
        
data.canClose this.options.canClose;

        if ( 
suggestedWidth && suggestedHeight ) {
            
data.suggestedWidth suggestedWidth;
            
data.suggestedHeight suggestedHeight;
        }

        return 
data;
    },
    
/**
     * @returns {wp.media.view.UploaderInline} Returns itself to allow chaining
     */
    
dispose: function() {
        if ( 
this.disposing ) {
            
/**
             * call 'dispose' directly on the parent class
             */
            
return View.prototype.dispose.applythisarguments );
        }

        
// Run remove on `dispose`, so we can be sure to refresh the
        // uploader with a view-less DOM. Track whether we're disposing
        // so we don't trigger an infinite loop.
        
this.disposing true;
        return 
this.remove();
    },
    
/**
     * @returns {wp.media.view.UploaderInline} Returns itself to allow chaining
     */
    
remove: function() {
        
/**
         * call 'remove' directly on the parent class
         */
        
var result View.prototype.remove.applythisarguments );

        
_.defer_.bindthis.refreshthis ) );
        return 
result;
    },

    
refresh: function() {
        var 
uploader this.controller.uploader;

        if ( 
uploader ) {
            
uploader.refresh();
        }
    },
    
/**
     * @returns {wp.media.view.UploaderInline}
     */
    
ready: function() {
        var 
$browser this.options.$browser,
            
$placeholder;

        if ( 
this.controller.uploader ) {
            
$placeholder this.$('.browser');

            
// Check if we've already replaced the placeholder.
            
if ( $placeholder[0] === $browser[0] ) {
                return;
            }

            
$browser.detach().text$placeholder.text() );
            
$browser[0].className $placeholder[0].className;
            
$placeholder.replaceWith$browser.show() );
        }

        
this.refresh();
        return 
this;
    },
    
show: function() {
        
this.$el.removeClass'hidden' );
    },
    
hide: function() {
        
this.$el.addClass'hidden' );
    }

});

module.exports UploaderInline;

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

/**
 * wp.media.view.UploaderStatusError
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var UploaderStatusError wp.media.View.extend({
    
className'upload-error',
    
template:  wp.template('uploader-status-error')
});

module.exports UploaderStatusError;

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

/**
 * wp.media.view.UploaderStatus
 *
 * An uploader status for on-going uploads.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.media.View,
    
UploaderStatus;

UploaderStatus View.extend({
    
className'media-uploader-status',
    
template:  wp.template('uploader-status'),

    
events: {
        
'click .upload-dismiss-errors''dismiss'
    
},

    
initialize: function() {
        
this.queue wp.Uploader.queue;
        
this.queue.on'add remove reset'this.visibilitythis );
        
this.queue.on'add remove reset change:percent'this.progressthis );
        
this.queue.on'add remove reset change:uploading'this.infothis );

        
this.errors wp.Uploader.errors;
        
this.errors.reset();
        
this.errors.on'add remove reset'this.visibilitythis );
        
this.errors.on'add'this.errorthis );
    },
    
/**
     * @global wp.Uploader
     * @returns {wp.media.view.UploaderStatus}
     */
    
dispose: function() {
        
wp.Uploader.queue.offnullnullthis );
        
/**
         * call 'dispose' directly on the parent class
         */
        
View.prototype.dispose.applythisarguments );
        return 
this;
    },

    
visibility: function() {
        
this.$el.toggleClass'uploading', !! this.queue.length );
        
this.$el.toggleClass'errors', !! this.errors.length );
        
this.$el.toggle( !! this.queue.length || !! this.errors.length );
    },

    
ready: function() {
        
_.each({
            
'$bar':      '.media-progress-bar div',
            
'$index':    '.upload-index',
            
'$total':    '.upload-total',
            
'$filename''.upload-filename'
        
}, function( selectorkey ) {
            
thiskey ] = this.$( selector );
        }, 
this );

        
this.visibility();
        
this.progress();
        
this.info();
    },

    
progress: function() {
        var 
queue this.queue,
            
$bar this.$bar;

        if ( ! 
$bar || ! queue.length ) {
            return;
        }

        
$bar.width( ( queue.reduce( function( memoattachment ) {
            if ( ! 
attachment.get('uploading') ) {
                return 
memo 100;
            }

            var 
percent attachment.get('percent');
            return 
memo + ( _.isNumberpercent ) ? percent 100 );
        }, 
) / queue.length ) + '%' );
    },

    
info: function() {
        var 
queue this.queue,
            
index 0active;

        if ( ! 
queue.length ) {
            return;
        }

        
active this.queue.find( function( attachment) {
            
index i;
            return 
attachment.get('uploading');
        });

        
this.$index.textindex );
        
this.$total.textqueue.length );
        
this.$filename.htmlactive this.filenameactive.get('filename') ) : '' );
    },
    
/**
     * @param {string} filename
     * @returns {string}
     */
    
filename: function( filename ) {
        return 
wp.media.truncate_.escapefilename ), 24 );
    },
    
/**
     * @param {Backbone.Model} error
     */
    
error: function( error ) {
        
this.views.add'.upload-errors', new wp.media.view.UploaderStatusError({
            
filenamethis.filenameerror.get('file').name ),
            
message:  error.get('message')
        }), { 
at});
    },

    
/**
     * @global wp.Uploader
     *
     * @param {Object} event
     */
    
dismiss: function( event ) {
        var 
errors this.views.get('.upload-errors');

        
event.preventDefault();

        if ( 
errors ) {
            
_.invokeerrors'remove' );
        }
        
wp.Uploader.errors.reset();
    }
});

module.exports UploaderStatus;

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

/**
 * wp.media.view.UploaderWindow
 *
 * An uploader window that allows for dragging and dropping media.
 *
 * @class
 * @augments wp.media.View
 * @augments wp.Backbone.View
 * @augments Backbone.View
 *
 * @param {object} [options]                   Options hash passed to the view.
 * @param {object} [options.uploader]          Uploader properties.
 * @param {jQuery} [options.uploader.browser]
 * @param {jQuery} [options.uploader.dropzone] jQuery collection of the dropzone.
 * @param {object} [options.uploader.params]
 */
var $ = jQuery,
    
UploaderWindow;

UploaderWindow wp.media.View.extend({
    
tagName:   'div',
    
className'uploader-window',
    
template:  wp.template('uploader-window'),

    
initialize: function() {
        var 
uploader;

        
this.$browser = $('<a href="#" class="browser" />').hide().appendTo('body');

        
uploader this.options.uploader _.defaultsthis.options.uploader || {}, {
            
dropzone:  this.$el,
            
browser:   this.$browser,
            
params:    {}
        });

        
// Ensure the dropzone is a jQuery collection.
        
if ( uploader.dropzone && ! (uploader.dropzone instanceof $) ) {
            
uploader.dropzone = $( uploader.dropzone );
        }

        
this.controller.on'activate'this.refreshthis );

        
this.controller.on'detach', function() {
            
this.$browser.remove();
        }, 
this );
    },

    
refresh: function() {
        if ( 
this.uploader ) {
            
this.uploader.refresh();
        }
    },

    
ready: function() {
        var 
postId wp.media.view.settings.post.id,
            
dropzone;

        
// If the uploader already exists, bail.
        
if ( this.uploader ) {
            return;
        }

        if ( 
postId ) {
            
this.options.uploader.params.post_id postId;
        }
        
this.uploader = new wp.Uploaderthis.options.uploader );

        
dropzone this.uploader.dropzone;
        
dropzone.on'dropzone:enter'_.bindthis.showthis ) );
        
dropzone.on'dropzone:leave'_.bindthis.hidethis ) );

        $( 
this.uploader ).on'uploader:ready'_.bindthis._readythis ) );
    },

    
_ready: function() {
        
this.controller.trigger'uploader:ready' );
    },

    
show: function() {
        var 
$el this.$el.show();

        
// Ensure that the animation is triggered by waiting until
        // the transparent element is painted into the DOM.
        
_.defer( function() {
            
$el.css({ opacity});
        });
    },

    
hide: function() {
        var 
$el this.$el.css({ opacity});

        
wp.media.transition$el ).done( function() {
            
// Transition end events are subject to race conditions.
            // Make sure that the value is set as intended.
            
if ( '0' === $el.css('opacity') ) {
                
$el.hide();
            }
        });

        
// https://core.trac.wordpress.org/ticket/27341
        
_.delay( function() {
            if ( 
'0' === $el.css('opacity') && $el.is(':visible') ) {
                
$el.hide();
            }
        }, 
500 );
    }
});

module.exports UploaderWindow;

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

/**
 * wp.media.View
 *
 * The base view class for media.
 *
 * Undelegating events, removing events from the model, and
 * removing events from the controller mirror the code for
 * `Backbone.View.dispose` in Backbone 0.9.8 development.
 *
 * This behavior has since been removed, and should not be used
 * outside of the media manager.
 *
 * @class
 * @augments wp.Backbone.View
 * @augments Backbone.View
 */
var View wp.Backbone.View.extend({
    
constructor: function( options ) {
        if ( 
options && options.controller ) {
            
this.controller options.controller;
        }
        
wp.Backbone.View.applythisarguments );
    },
    
/**
     * @todo The internal comment mentions this might have been a stop-gap
     *       before Backbone 0.9.8 came out. Figure out if Backbone core takes
     *       care of this in Backbone.View now.
     *
     * @returns {wp.media.View} Returns itself to allow chaining
     */
    
dispose: function() {
        
// Undelegating events, removing events from the model, and
        // removing events from the controller mirror the code for
        // `Backbone.View.dispose` in Backbone 0.9.8 development.
        
this.undelegateEvents();

        if ( 
this.model && this.model.off ) {
            
this.model.offnullnullthis );
        }

        if ( 
this.collection && this.collection.off ) {
            
this.collection.offnullnullthis );
        }

        
// Unbind controller events.
        
if ( this.controller && this.controller.off ) {
            
this.controller.offnullnullthis );
        }

        return 
this;
    },
    
/**
     * @returns {wp.media.View} Returns itself to allow chaining
     */
    
remove: function() {
        
this.dispose();
        
/**
         * call 'remove' directly on the parent class
         */
        
return wp.Backbone.View.prototype.remove.applythisarguments );
    }
});

module.exports View;

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