PageRenderTime 81ms CodeModel.GetById 17ms app.highlight 43ms RepoModel.GetById 1ms app.codeStats 2ms

/HotelSpaWP/wp-includes/js/media-views.js

https://bitbucket.org/Trulsh/personal-bootstrap-projects
JavaScript | 8542 lines | 5137 code | 1223 blank | 2182 comment | 606 complexity | b44bc57736b0f9071a8d5b4e1a1c38c0 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1(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){
   2/**
   3 * wp.media.controller.CollectionAdd
   4 *
   5 * A state for adding attachments to a collection (e.g. video playlist).
   6 *
   7 * @class
   8 * @augments wp.media.controller.Library
   9 * @augments wp.media.controller.State
  10 * @augments Backbone.Model
  11 *
  12 * @param {object}                     [attributes]                         The attributes hash passed to the state.
  13 * @param {string}                     [attributes.id=library]      Unique identifier.
  14 * @param {string}                     attributes.title                    Title for the state. Displays in the frame's title region.
  15 * @param {boolean}                    [attributes.multiple=add]            Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
  16 * @param {wp.media.model.Attachments} [attributes.library]                 The attachments collection to browse.
  17 *                                                                          If one is not supplied, a collection of attachments of the specified type will be created.
  18 * @param {boolean|string}             [attributes.filterable=uploaded]     Whether the library is filterable, and if so what filters should be shown.
  19 *                                                                          Accepts 'all', 'uploaded', or 'unattached'.
  20 * @param {string}                     [attributes.menu=gallery]            Initial mode for the menu region.
  21 * @param {string}                     [attributes.content=upload]          Initial mode for the content region.
  22 *                                                                          Overridden by persistent user setting if 'contentUserSetting' is true.
  23 * @param {string}                     [attributes.router=browse]           Initial mode for the router region.
  24 * @param {string}                     [attributes.toolbar=gallery-add]     Initial mode for the toolbar region.
  25 * @param {boolean}                    [attributes.searchable=true]         Whether the library is searchable.
  26 * @param {boolean}                    [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
  27 * @param {boolean}                    [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
  28 * @param {boolean}                    [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
  29 * @param {int}                        [attributes.priority=100]            The priority for the state link in the media menu.
  30 * @param {boolean}                    [attributes.syncSelection=false]     Whether the Attachments selection should be persisted from the last state.
  31 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
  32 * @param {string}                     attributes.type                   The collection's media type. (e.g. 'video').
  33 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
  34 */
  35var Selection = wp.media.model.Selection,
  36	Library = wp.media.controller.Library,
  37	CollectionAdd;
  38
  39CollectionAdd = Library.extend({
  40	defaults: _.defaults( {
  41		// Selection defaults. @see media.model.Selection
  42		multiple:      'add',
  43		// Attachments browser defaults. @see media.view.AttachmentsBrowser
  44		filterable:    'uploaded',
  45
  46		priority:      100,
  47		syncSelection: false
  48	}, Library.prototype.defaults ),
  49
  50	/**
  51	 * @since 3.9.0
  52	 */
  53	initialize: function() {
  54		var collectionType = this.get('collectionType');
  55
  56		if ( 'video' === this.get( 'type' ) ) {
  57			collectionType = 'video-' + collectionType;
  58		}
  59
  60		this.set( 'id', collectionType + '-library' );
  61		this.set( 'toolbar', collectionType + '-add' );
  62		this.set( 'menu', collectionType );
  63
  64		// If we haven't been provided a `library`, create a `Selection`.
  65		if ( ! this.get('library') ) {
  66			this.set( 'library', wp.media.query({ type: this.get('type') }) );
  67		}
  68		Library.prototype.initialize.apply( this, arguments );
  69	},
  70
  71	/**
  72	 * @since 3.9.0
  73	 */
  74	activate: function() {
  75		var library = this.get('library'),
  76			editLibrary = this.get('editLibrary'),
  77			edit = this.frame.state( this.get('collectionType') + '-edit' ).get('library');
  78
  79		if ( editLibrary && editLibrary !== edit ) {
  80			library.unobserve( editLibrary );
  81		}
  82
  83		// Accepts attachments that exist in the original library and
  84		// that do not exist in gallery's library.
  85		library.validator = function( attachment ) {
  86			return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments );
  87		};
  88
  89		// Reset the library to ensure that all attachments are re-added
  90		// to the collection. Do so silently, as calling `observe` will
  91		// trigger the `reset` event.
  92		library.reset( library.mirroring.models, { silent: true });
  93		library.observe( edit );
  94		this.set('editLibrary', edit);
  95
  96		Library.prototype.activate.apply( this, arguments );
  97	}
  98});
  99
 100module.exports = CollectionAdd;
 101
 102},{}],2:[function(require,module,exports){
 103/**
 104 * wp.media.controller.CollectionEdit
 105 *
 106 * A state for editing a collection, which is used by audio and video playlists,
 107 * and can be used for other collections.
 108 *
 109 * @class
 110 * @augments wp.media.controller.Library
 111 * @augments wp.media.controller.State
 112 * @augments Backbone.Model
 113 *
 114 * @param {object}                     [attributes]                      The attributes hash passed to the state.
 115 * @param {string}                     attributes.title                  Title for the state. Displays in the media menu and the frame's title region.
 116 * @param {wp.media.model.Attachments} [attributes.library]              The attachments collection to edit.
 117 *                                                                       If one is not supplied, an empty media.model.Selection collection is created.
 118 * @param {boolean}                    [attributes.multiple=false]       Whether multi-select is enabled.
 119 * @param {string}                     [attributes.content=browse]       Initial mode for the content region.
 120 * @param {string}                     attributes.menu                   Initial mode for the menu region. @todo this needs a better explanation.
 121 * @param {boolean}                    [attributes.searchable=false]     Whether the library is searchable.
 122 * @param {boolean}                    [attributes.sortable=true]        Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 123 * @param {boolean}                    [attributes.date=true]            Whether to show the date filter in the browser's toolbar.
 124 * @param {boolean}                    [attributes.describe=true]        Whether to offer UI to describe the attachments - e.g. captioning images in a gallery.
 125 * @param {boolean}                    [attributes.dragInfo=true]        Whether to show instructional text about the attachments being sortable.
 126 * @param {boolean}                    [attributes.dragInfoText]         Instructional text about the attachments being sortable.
 127 * @param {int}                        [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.
 128 * @param {boolean}                    [attributes.editing=false]        Whether the gallery is being created, or editing an existing instance.
 129 * @param {int}                        [attributes.priority=60]          The priority for the state link in the media menu.
 130 * @param {boolean}                    [attributes.syncSelection=false]  Whether the Attachments selection should be persisted from the last state.
 131 *                                                                       Defaults to false for this state, because the library passed in  *is* the selection.
 132 * @param {view}                       [attributes.SettingsView]         The view to edit the collection instance settings (e.g. Playlist settings with "Show tracklist" checkbox).
 133 * @param {view}                       [attributes.AttachmentView]       The single `Attachment` view to be used in the `Attachments`.
 134 *                                                                       If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
 135 * @param {string}                     attributes.type                   The collection's media type. (e.g. 'video').
 136 * @param {string}                     attributes.collectionType         The collection type. (e.g. 'playlist').
 137 */
 138var Library = wp.media.controller.Library,
 139	l10n = wp.media.view.l10n,
 140	$ = jQuery,
 141	CollectionEdit;
 142
 143CollectionEdit = Library.extend({
 144	defaults: {
 145		multiple:         false,
 146		sortable:         true,
 147		date:             false,
 148		searchable:       false,
 149		content:          'browse',
 150		describe:         true,
 151		dragInfo:         true,
 152		idealColumnWidth: 170,
 153		editing:          false,
 154		priority:         60,
 155		SettingsView:     false,
 156		syncSelection:    false
 157	},
 158
 159	/**
 160	 * @since 3.9.0
 161	 */
 162	initialize: function() {
 163		var collectionType = this.get('collectionType');
 164
 165		if ( 'video' === this.get( 'type' ) ) {
 166			collectionType = 'video-' + collectionType;
 167		}
 168
 169		this.set( 'id', collectionType + '-edit' );
 170		this.set( 'toolbar', collectionType + '-edit' );
 171
 172		// If we haven't been provided a `library`, create a `Selection`.
 173		if ( ! this.get('library') ) {
 174			this.set( 'library', new wp.media.model.Selection() );
 175		}
 176		// The single `Attachment` view to be used in the `Attachments` view.
 177		if ( ! this.get('AttachmentView') ) {
 178			this.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary );
 179		}
 180		Library.prototype.initialize.apply( this, arguments );
 181	},
 182
 183	/**
 184	 * @since 3.9.0
 185	 */
 186	activate: function() {
 187		var library = this.get('library');
 188
 189		// Limit the library to images only.
 190		library.props.set( 'type', this.get( 'type' ) );
 191
 192		// Watch for uploaded attachments.
 193		this.get('library').observe( wp.Uploader.queue );
 194
 195		this.frame.on( 'content:render:browse', this.renderSettings, this );
 196
 197		Library.prototype.activate.apply( this, arguments );
 198	},
 199
 200	/**
 201	 * @since 3.9.0
 202	 */
 203	deactivate: function() {
 204		// Stop watching for uploaded attachments.
 205		this.get('library').unobserve( wp.Uploader.queue );
 206
 207		this.frame.off( 'content:render:browse', this.renderSettings, this );
 208
 209		Library.prototype.deactivate.apply( this, arguments );
 210	},
 211
 212	/**
 213	 * Render the collection embed settings view in the browser sidebar.
 214	 *
 215	 * @todo This is against the pattern elsewhere in media. Typically the frame
 216	 *       is responsible for adding region mode callbacks. Explain.
 217	 *
 218	 * @since 3.9.0
 219	 *
 220	 * @param {wp.media.view.attachmentsBrowser} The attachments browser view.
 221	 */
 222	renderSettings: function( attachmentsBrowserView ) {
 223		var library = this.get('library'),
 224			collectionType = this.get('collectionType'),
 225			dragInfoText = this.get('dragInfoText'),
 226			SettingsView = this.get('SettingsView'),
 227			obj = {};
 228
 229		if ( ! library || ! attachmentsBrowserView ) {
 230			return;
 231		}
 232
 233		library[ collectionType ] = library[ collectionType ] || new Backbone.Model();
 234
 235		obj[ collectionType ] = new SettingsView({
 236			controller: this,
 237			model:      library[ collectionType ],
 238			priority:   40
 239		});
 240
 241		attachmentsBrowserView.sidebar.set( obj );
 242
 243		if ( dragInfoText ) {
 244			attachmentsBrowserView.toolbar.set( 'dragInfo', new wp.media.View({
 245				el: $( '<div class="instructions">' + dragInfoText + '</div>' )[0],
 246				priority: -40
 247			}) );
 248		}
 249
 250		// Add the 'Reverse order' button to the toolbar.
 251		attachmentsBrowserView.toolbar.set( 'reverse', {
 252			text:     l10n.reverseOrder,
 253			priority: 80,
 254
 255			click: function() {
 256				library.reset( library.toArray().reverse() );
 257			}
 258		});
 259	}
 260});
 261
 262module.exports = CollectionEdit;
 263
 264},{}],3:[function(require,module,exports){
 265/**
 266 * wp.media.controller.Cropper
 267 *
 268 * A state for cropping an image.
 269 *
 270 * @class
 271 * @augments wp.media.controller.State
 272 * @augments Backbone.Model
 273 */
 274var l10n = wp.media.view.l10n,
 275	Cropper;
 276
 277Cropper = wp.media.controller.State.extend({
 278	defaults: {
 279		id:          'cropper',
 280		title:       l10n.cropImage,
 281		// Region mode defaults.
 282		toolbar:     'crop',
 283		content:     'crop',
 284		router:      false,
 285		canSkipCrop: false,
 286
 287		// Default doCrop Ajax arguments to allow the Customizer (for example) to inject state.
 288		doCropArgs: {}
 289	},
 290
 291	activate: function() {
 292		this.frame.on( 'content:create:crop', this.createCropContent, this );
 293		this.frame.on( 'close', this.removeCropper, this );
 294		this.set('selection', new Backbone.Collection(this.frame._selection.single));
 295	},
 296
 297	deactivate: function() {
 298		this.frame.toolbar.mode('browse');
 299	},
 300
 301	createCropContent: function() {
 302		this.cropperView = new wp.media.view.Cropper({
 303			controller: this,
 304			attachment: this.get('selection').first()
 305		});
 306		this.cropperView.on('image-loaded', this.createCropToolbar, this);
 307		this.frame.content.set(this.cropperView);
 308
 309	},
 310	removeCropper: function() {
 311		this.imgSelect.cancelSelection();
 312		this.imgSelect.setOptions({remove: true});
 313		this.imgSelect.update();
 314		this.cropperView.remove();
 315	},
 316	createCropToolbar: function() {
 317		var canSkipCrop, toolbarOptions;
 318
 319		canSkipCrop = this.get('canSkipCrop') || false;
 320
 321		toolbarOptions = {
 322			controller: this.frame,
 323			items: {
 324				insert: {
 325					style:    'primary',
 326					text:     l10n.cropImage,
 327					priority: 80,
 328					requires: { library: false, selection: false },
 329
 330					click: function() {
 331						var controller = this.controller,
 332							selection;
 333
 334						selection = controller.state().get('selection').first();
 335						selection.set({cropDetails: controller.state().imgSelect.getSelection()});
 336
 337						this.$el.text(l10n.cropping);
 338						this.$el.attr('disabled', true);
 339
 340						controller.state().doCrop( selection ).done( function( croppedImage ) {
 341							controller.trigger('cropped', croppedImage );
 342							controller.close();
 343						}).fail( function() {
 344							controller.trigger('content:error:crop');
 345						});
 346					}
 347				}
 348			}
 349		};
 350
 351		if ( canSkipCrop ) {
 352			_.extend( toolbarOptions.items, {
 353				skip: {
 354					style:      'secondary',
 355					text:       l10n.skipCropping,
 356					priority:   70,
 357					requires:   { library: false, selection: false },
 358					click:      function() {
 359						var selection = this.controller.state().get('selection').first();
 360						this.controller.state().cropperView.remove();
 361						this.controller.trigger('skippedcrop', selection);
 362						this.controller.close();
 363					}
 364				}
 365			});
 366		}
 367
 368		this.frame.toolbar.set( new wp.media.view.Toolbar(toolbarOptions) );
 369	},
 370
 371	doCrop: function( attachment ) {
 372		return wp.ajax.post( 'custom-header-crop', _.extend(
 373			{},
 374			this.defaults.doCropArgs,
 375			{
 376				nonce: attachment.get( 'nonces' ).edit,
 377				id: attachment.get( 'id' ),
 378				cropDetails: attachment.get( 'cropDetails' )
 379			}
 380		) );
 381	}
 382});
 383
 384module.exports = Cropper;
 385
 386},{}],4:[function(require,module,exports){
 387/**
 388 * wp.media.controller.CustomizeImageCropper
 389 *
 390 * A state for cropping an image.
 391 *
 392 * @class
 393 * @augments wp.media.controller.Cropper
 394 * @augments wp.media.controller.State
 395 * @augments Backbone.Model
 396 */
 397var Controller = wp.media.controller,
 398	CustomizeImageCropper;
 399
 400CustomizeImageCropper = Controller.Cropper.extend({
 401	doCrop: function( attachment ) {
 402		var cropDetails = attachment.get( 'cropDetails' ),
 403			control = this.get( 'control' ),
 404			ratio = cropDetails.width / cropDetails.height;
 405
 406		// Use crop measurements when flexible in both directions.
 407		if ( control.params.flex_width && control.params.flex_height ) {
 408			cropDetails.dst_width  = cropDetails.width;
 409			cropDetails.dst_height = cropDetails.height;
 410
 411		// Constrain flexible side based on image ratio and size of the fixed side.
 412		} else {
 413			cropDetails.dst_width  = control.params.flex_width  ? control.params.height * ratio : control.params.width;
 414			cropDetails.dst_height = control.params.flex_height ? control.params.width  / ratio : control.params.height;
 415		}
 416
 417		return wp.ajax.post( 'crop-image', {
 418			wp_customize: 'on',
 419			nonce: attachment.get( 'nonces' ).edit,
 420			id: attachment.get( 'id' ),
 421			context: control.id,
 422			cropDetails: cropDetails
 423		} );
 424	}
 425});
 426
 427module.exports = CustomizeImageCropper;
 428
 429},{}],5:[function(require,module,exports){
 430/**
 431 * wp.media.controller.EditImage
 432 *
 433 * A state for editing (cropping, etc.) an image.
 434 *
 435 * @class
 436 * @augments wp.media.controller.State
 437 * @augments Backbone.Model
 438 *
 439 * @param {object}                    attributes                      The attributes hash passed to the state.
 440 * @param {wp.media.model.Attachment} attributes.model                The attachment.
 441 * @param {string}                    [attributes.id=edit-image]      Unique identifier.
 442 * @param {string}                    [attributes.title=Edit Image]   Title for the state. Displays in the media menu and the frame's title region.
 443 * @param {string}                    [attributes.content=edit-image] Initial mode for the content region.
 444 * @param {string}                    [attributes.toolbar=edit-image] Initial mode for the toolbar region.
 445 * @param {string}                    [attributes.menu=false]         Initial mode for the menu region.
 446 * @param {string}                    [attributes.url]                Unused. @todo Consider removal.
 447 */
 448var l10n = wp.media.view.l10n,
 449	EditImage;
 450
 451EditImage = wp.media.controller.State.extend({
 452	defaults: {
 453		id:      'edit-image',
 454		title:   l10n.editImage,
 455		menu:    false,
 456		toolbar: 'edit-image',
 457		content: 'edit-image',
 458		url:     ''
 459	},
 460
 461	/**
 462	 * @since 3.9.0
 463	 */
 464	activate: function() {
 465		this.frame.on( 'toolbar:render:edit-image', _.bind( this.toolbar, this ) );
 466	},
 467
 468	/**
 469	 * @since 3.9.0
 470	 */
 471	deactivate: function() {
 472		this.frame.off( 'toolbar:render:edit-image' );
 473	},
 474
 475	/**
 476	 * @since 3.9.0
 477	 */
 478	toolbar: function() {
 479		var frame = this.frame,
 480			lastState = frame.lastState(),
 481			previous = lastState && lastState.id;
 482
 483		frame.toolbar.set( new wp.media.view.Toolbar({
 484			controller: frame,
 485			items: {
 486				back: {
 487					style: 'primary',
 488					text:     l10n.back,
 489					priority: 20,
 490					click:    function() {
 491						if ( previous ) {
 492							frame.setState( previous );
 493						} else {
 494							frame.close();
 495						}
 496					}
 497				}
 498			}
 499		}) );
 500	}
 501});
 502
 503module.exports = EditImage;
 504
 505},{}],6:[function(require,module,exports){
 506/**
 507 * wp.media.controller.Embed
 508 *
 509 * A state for embedding media from a URL.
 510 *
 511 * @class
 512 * @augments wp.media.controller.State
 513 * @augments Backbone.Model
 514 *
 515 * @param {object} attributes                         The attributes hash passed to the state.
 516 * @param {string} [attributes.id=embed]              Unique identifier.
 517 * @param {string} [attributes.title=Insert From URL] Title for the state. Displays in the media menu and the frame's title region.
 518 * @param {string} [attributes.content=embed]         Initial mode for the content region.
 519 * @param {string} [attributes.menu=default]          Initial mode for the menu region.
 520 * @param {string} [attributes.toolbar=main-embed]    Initial mode for the toolbar region.
 521 * @param {string} [attributes.menu=false]            Initial mode for the menu region.
 522 * @param {int}    [attributes.priority=120]          The priority for the state link in the media menu.
 523 * @param {string} [attributes.type=link]             The type of embed. Currently only link is supported.
 524 * @param {string} [attributes.url]                   The embed URL.
 525 * @param {object} [attributes.metadata={}]           Properties of the embed, which will override attributes.url if set.
 526 */
 527var l10n = wp.media.view.l10n,
 528	$ = Backbone.$,
 529	Embed;
 530
 531Embed = wp.media.controller.State.extend({
 532	defaults: {
 533		id:       'embed',
 534		title:    l10n.insertFromUrlTitle,
 535		content:  'embed',
 536		menu:     'default',
 537		toolbar:  'main-embed',
 538		priority: 120,
 539		type:     'link',
 540		url:      '',
 541		metadata: {}
 542	},
 543
 544	// The amount of time used when debouncing the scan.
 545	sensitivity: 400,
 546
 547	initialize: function(options) {
 548		this.metadata = options.metadata;
 549		this.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity );
 550		this.props = new Backbone.Model( this.metadata || { url: '' });
 551		this.props.on( 'change:url', this.debouncedScan, this );
 552		this.props.on( 'change:url', this.refresh, this );
 553		this.on( 'scan', this.scanImage, this );
 554	},
 555
 556	/**
 557	 * Trigger a scan of the embedded URL's content for metadata required to embed.
 558	 *
 559	 * @fires wp.media.controller.Embed#scan
 560	 */
 561	scan: function() {
 562		var scanners,
 563			embed = this,
 564			attributes = {
 565				type: 'link',
 566				scanners: []
 567			};
 568
 569		// Scan is triggered with the list of `attributes` to set on the
 570		// state, useful for the 'type' attribute and 'scanners' attribute,
 571		// an array of promise objects for asynchronous scan operations.
 572		if ( this.props.get('url') ) {
 573			this.trigger( 'scan', attributes );
 574		}
 575
 576		if ( attributes.scanners.length ) {
 577			scanners = attributes.scanners = $.when.apply( $, attributes.scanners );
 578			scanners.always( function() {
 579				if ( embed.get('scanners') === scanners ) {
 580					embed.set( 'loading', false );
 581				}
 582			});
 583		} else {
 584			attributes.scanners = null;
 585		}
 586
 587		attributes.loading = !! attributes.scanners;
 588		this.set( attributes );
 589	},
 590	/**
 591	 * Try scanning the embed as an image to discover its dimensions.
 592	 *
 593	 * @param {Object} attributes
 594	 */
 595	scanImage: function( attributes ) {
 596		var frame = this.frame,
 597			state = this,
 598			url = this.props.get('url'),
 599			image = new Image(),
 600			deferred = $.Deferred();
 601
 602		attributes.scanners.push( deferred.promise() );
 603
 604		// Try to load the image and find its width/height.
 605		image.onload = function() {
 606			deferred.resolve();
 607
 608			if ( state !== frame.state() || url !== state.props.get('url') ) {
 609				return;
 610			}
 611
 612			state.set({
 613				type: 'image'
 614			});
 615
 616			state.props.set({
 617				width:  image.width,
 618				height: image.height
 619			});
 620		};
 621
 622		image.onerror = deferred.reject;
 623		image.src = url;
 624	},
 625
 626	refresh: function() {
 627		this.frame.toolbar.get().refresh();
 628	},
 629
 630	reset: function() {
 631		this.props.clear().set({ url: '' });
 632
 633		if ( this.active ) {
 634			this.refresh();
 635		}
 636	}
 637});
 638
 639module.exports = Embed;
 640
 641},{}],7:[function(require,module,exports){
 642/**
 643 * wp.media.controller.FeaturedImage
 644 *
 645 * A state for selecting a featured image for a post.
 646 *
 647 * @class
 648 * @augments wp.media.controller.Library
 649 * @augments wp.media.controller.State
 650 * @augments Backbone.Model
 651 *
 652 * @param {object}                     [attributes]                          The attributes hash passed to the state.
 653 * @param {string}                     [attributes.id=featured-image]        Unique identifier.
 654 * @param {string}                     [attributes.title=Set Featured Image] Title for the state. Displays in the media menu and the frame's title region.
 655 * @param {wp.media.model.Attachments} [attributes.library]                  The attachments collection to browse.
 656 *                                                                           If one is not supplied, a collection of all images will be created.
 657 * @param {boolean}                    [attributes.multiple=false]           Whether multi-select is enabled.
 658 * @param {string}                     [attributes.content=upload]           Initial mode for the content region.
 659 *                                                                           Overridden by persistent user setting if 'contentUserSetting' is true.
 660 * @param {string}                     [attributes.menu=default]             Initial mode for the menu region.
 661 * @param {string}                     [attributes.router=browse]            Initial mode for the router region.
 662 * @param {string}                     [attributes.toolbar=featured-image]   Initial mode for the toolbar region.
 663 * @param {int}                        [attributes.priority=60]              The priority for the state link in the media menu.
 664 * @param {boolean}                    [attributes.searchable=true]          Whether the library is searchable.
 665 * @param {boolean|string}             [attributes.filterable=false]         Whether the library is filterable, and if so what filters should be shown.
 666 *                                                                           Accepts 'all', 'uploaded', or 'unattached'.
 667 * @param {boolean}                    [attributes.sortable=true]            Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 668 * @param {boolean}                    [attributes.autoSelect=true]          Whether an uploaded attachment should be automatically added to the selection.
 669 * @param {boolean}                    [attributes.describe=false]           Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 670 * @param {boolean}                    [attributes.contentUserSetting=true]  Whether the content region's mode should be set and persisted per user.
 671 * @param {boolean}                    [attributes.syncSelection=true]       Whether the Attachments selection should be persisted from the last state.
 672 */
 673var Attachment = wp.media.model.Attachment,
 674	Library = wp.media.controller.Library,
 675	l10n = wp.media.view.l10n,
 676	FeaturedImage;
 677
 678FeaturedImage = Library.extend({
 679	defaults: _.defaults({
 680		id:            'featured-image',
 681		title:         l10n.setFeaturedImageTitle,
 682		multiple:      false,
 683		filterable:    'uploaded',
 684		toolbar:       'featured-image',
 685		priority:      60,
 686		syncSelection: true
 687	}, Library.prototype.defaults ),
 688
 689	/**
 690	 * @since 3.5.0
 691	 */
 692	initialize: function() {
 693		var library, comparator;
 694
 695		// If we haven't been provided a `library`, create a `Selection`.
 696		if ( ! this.get('library') ) {
 697			this.set( 'library', wp.media.query({ type: 'image' }) );
 698		}
 699
 700		Library.prototype.initialize.apply( this, arguments );
 701
 702		library    = this.get('library');
 703		comparator = library.comparator;
 704
 705		// Overload the library's comparator to push items that are not in
 706		// the mirrored query to the front of the aggregate collection.
 707		library.comparator = function( a, b ) {
 708			var aInQuery = !! this.mirroring.get( a.cid ),
 709				bInQuery = !! this.mirroring.get( b.cid );
 710
 711			if ( ! aInQuery && bInQuery ) {
 712				return -1;
 713			} else if ( aInQuery && ! bInQuery ) {
 714				return 1;
 715			} else {
 716				return comparator.apply( this, arguments );
 717			}
 718		};
 719
 720		// Add all items in the selection to the library, so any featured
 721		// images that are not initially loaded still appear.
 722		library.observe( this.get('selection') );
 723	},
 724
 725	/**
 726	 * @since 3.5.0
 727	 */
 728	activate: function() {
 729		this.updateSelection();
 730		this.frame.on( 'open', this.updateSelection, this );
 731
 732		Library.prototype.activate.apply( this, arguments );
 733	},
 734
 735	/**
 736	 * @since 3.5.0
 737	 */
 738	deactivate: function() {
 739		this.frame.off( 'open', this.updateSelection, this );
 740
 741		Library.prototype.deactivate.apply( this, arguments );
 742	},
 743
 744	/**
 745	 * @since 3.5.0
 746	 */
 747	updateSelection: function() {
 748		var selection = this.get('selection'),
 749			id = wp.media.view.settings.post.featuredImageId,
 750			attachment;
 751
 752		if ( '' !== id && -1 !== id ) {
 753			attachment = Attachment.get( id );
 754			attachment.fetch();
 755		}
 756
 757		selection.reset( attachment ? [ attachment ] : [] );
 758	}
 759});
 760
 761module.exports = FeaturedImage;
 762
 763},{}],8:[function(require,module,exports){
 764/**
 765 * wp.media.controller.GalleryAdd
 766 *
 767 * A state for selecting more images to add to a gallery.
 768 *
 769 * @class
 770 * @augments wp.media.controller.Library
 771 * @augments wp.media.controller.State
 772 * @augments Backbone.Model
 773 *
 774 * @param {object}                     [attributes]                         The attributes hash passed to the state.
 775 * @param {string}                     [attributes.id=gallery-library]      Unique identifier.
 776 * @param {string}                     [attributes.title=Add to Gallery]    Title for the state. Displays in the frame's title region.
 777 * @param {boolean}                    [attributes.multiple=add]            Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
 778 * @param {wp.media.model.Attachments} [attributes.library]                 The attachments collection to browse.
 779 *                                                                          If one is not supplied, a collection of all images will be created.
 780 * @param {boolean|string}             [attributes.filterable=uploaded]     Whether the library is filterable, and if so what filters should be shown.
 781 *                                                                          Accepts 'all', 'uploaded', or 'unattached'.
 782 * @param {string}                     [attributes.menu=gallery]            Initial mode for the menu region.
 783 * @param {string}                     [attributes.content=upload]          Initial mode for the content region.
 784 *                                                                          Overridden by persistent user setting if 'contentUserSetting' is true.
 785 * @param {string}                     [attributes.router=browse]           Initial mode for the router region.
 786 * @param {string}                     [attributes.toolbar=gallery-add]     Initial mode for the toolbar region.
 787 * @param {boolean}                    [attributes.searchable=true]         Whether the library is searchable.
 788 * @param {boolean}                    [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 789 * @param {boolean}                    [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
 790 * @param {boolean}                    [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
 791 * @param {int}                        [attributes.priority=100]            The priority for the state link in the media menu.
 792 * @param {boolean}                    [attributes.syncSelection=false]     Whether the Attachments selection should be persisted from the last state.
 793 *                                                                          Defaults to false because for this state, because the library of the Edit Gallery state is the selection.
 794 */
 795var Selection = wp.media.model.Selection,
 796	Library = wp.media.controller.Library,
 797	l10n = wp.media.view.l10n,
 798	GalleryAdd;
 799
 800GalleryAdd = Library.extend({
 801	defaults: _.defaults({
 802		id:            'gallery-library',
 803		title:         l10n.addToGalleryTitle,
 804		multiple:      'add',
 805		filterable:    'uploaded',
 806		menu:          'gallery',
 807		toolbar:       'gallery-add',
 808		priority:      100,
 809		syncSelection: false
 810	}, Library.prototype.defaults ),
 811
 812	/**
 813	 * @since 3.5.0
 814	 */
 815	initialize: function() {
 816		// If a library wasn't supplied, create a library of images.
 817		if ( ! this.get('library') ) {
 818			this.set( 'library', wp.media.query({ type: 'image' }) );
 819		}
 820
 821		Library.prototype.initialize.apply( this, arguments );
 822	},
 823
 824	/**
 825	 * @since 3.5.0
 826	 */
 827	activate: function() {
 828		var library = this.get('library'),
 829			edit    = this.frame.state('gallery-edit').get('library');
 830
 831		if ( this.editLibrary && this.editLibrary !== edit ) {
 832			library.unobserve( this.editLibrary );
 833		}
 834
 835		// Accepts attachments that exist in the original library and
 836		// that do not exist in gallery's library.
 837		library.validator = function( attachment ) {
 838			return !! this.mirroring.get( attachment.cid ) && ! edit.get( attachment.cid ) && Selection.prototype.validator.apply( this, arguments );
 839		};
 840
 841		// Reset the library to ensure that all attachments are re-added
 842		// to the collection. Do so silently, as calling `observe` will
 843		// trigger the `reset` event.
 844		library.reset( library.mirroring.models, { silent: true });
 845		library.observe( edit );
 846		this.editLibrary = edit;
 847
 848		Library.prototype.activate.apply( this, arguments );
 849	}
 850});
 851
 852module.exports = GalleryAdd;
 853
 854},{}],9:[function(require,module,exports){
 855/**
 856 * wp.media.controller.GalleryEdit
 857 *
 858 * A state for editing a gallery's images and settings.
 859 *
 860 * @class
 861 * @augments wp.media.controller.Library
 862 * @augments wp.media.controller.State
 863 * @augments Backbone.Model
 864 *
 865 * @param {object}                     [attributes]                       The attributes hash passed to the state.
 866 * @param {string}                     [attributes.id=gallery-edit]       Unique identifier.
 867 * @param {string}                     [attributes.title=Edit Gallery]    Title for the state. Displays in the frame's title region.
 868 * @param {wp.media.model.Attachments} [attributes.library]               The collection of attachments in the gallery.
 869 *                                                                        If one is not supplied, an empty media.model.Selection collection is created.
 870 * @param {boolean}                    [attributes.multiple=false]        Whether multi-select is enabled.
 871 * @param {boolean}                    [attributes.searchable=false]      Whether the library is searchable.
 872 * @param {boolean}                    [attributes.sortable=true]         Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
 873 * @param {boolean}                    [attributes.date=true]             Whether to show the date filter in the browser's toolbar.
 874 * @param {string|false}               [attributes.content=browse]        Initial mode for the content region.
 875 * @param {string|false}               [attributes.toolbar=image-details] Initial mode for the toolbar region.
 876 * @param {boolean}                    [attributes.describe=true]         Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
 877 * @param {boolean}                    [attributes.displaySettings=true]  Whether to show the attachment display settings interface.
 878 * @param {boolean}                    [attributes.dragInfo=true]         Whether to show instructional text about the attachments being sortable.
 879 * @param {int}                        [attributes.idealColumnWidth=170]  The ideal column width in pixels for attachments.
 880 * @param {boolean}                    [attributes.editing=false]         Whether the gallery is being created, or editing an existing instance.
 881 * @param {int}                        [attributes.priority=60]           The priority for the state link in the media menu.
 882 * @param {boolean}                    [attributes.syncSelection=false]   Whether the Attachments selection should be persisted from the last state.
 883 *                                                                        Defaults to false for this state, because the library passed in  *is* the selection.
 884 * @param {view}                       [attributes.AttachmentView]        The single `Attachment` view to be used in the `Attachments`.
 885 *                                                                        If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
 886 */
 887var Library = wp.media.controller.Library,
 888	l10n = wp.media.view.l10n,
 889	GalleryEdit;
 890
 891GalleryEdit = Library.extend({
 892	defaults: {
 893		id:               'gallery-edit',
 894		title:            l10n.editGalleryTitle,
 895		multiple:         false,
 896		searchable:       false,
 897		sortable:         true,
 898		date:             false,
 899		display:          false,
 900		content:          'browse',
 901		toolbar:          'gallery-edit',
 902		describe:         true,
 903		displaySettings:  true,
 904		dragInfo:         true,
 905		idealColumnWidth: 170,
 906		editing:          false,
 907		priority:         60,
 908		syncSelection:    false
 909	},
 910
 911	/**
 912	 * @since 3.5.0
 913	 */
 914	initialize: function() {
 915		// If we haven't been provided a `library`, create a `Selection`.
 916		if ( ! this.get('library') ) {
 917			this.set( 'library', new wp.media.model.Selection() );
 918		}
 919
 920		// The single `Attachment` view to be used in the `Attachments` view.
 921		if ( ! this.get('AttachmentView') ) {
 922			this.set( 'AttachmentView', wp.media.view.Attachment.EditLibrary );
 923		}
 924
 925		Library.prototype.initialize.apply( this, arguments );
 926	},
 927
 928	/**
 929	 * @since 3.5.0
 930	 */
 931	activate: function() {
 932		var library = this.get('library');
 933
 934		// Limit the library to images only.
 935		library.props.set( 'type', 'image' );
 936
 937		// Watch for uploaded attachments.
 938		this.get('library').observe( wp.Uploader.queue );
 939
 940		this.frame.on( 'content:render:browse', this.gallerySettings, this );
 941
 942		Library.prototype.activate.apply( this, arguments );
 943	},
 944
 945	/**
 946	 * @since 3.5.0
 947	 */
 948	deactivate: function() {
 949		// Stop watching for uploaded attachments.
 950		this.get('library').unobserve( wp.Uploader.queue );
 951
 952		this.frame.off( 'content:render:browse', this.gallerySettings, this );
 953
 954		Library.prototype.deactivate.apply( this, arguments );
 955	},
 956
 957	/**
 958	 * @since 3.5.0
 959	 *
 960	 * @param browser
 961	 */
 962	gallerySettings: function( browser ) {
 963		if ( ! this.get('displaySettings') ) {
 964			return;
 965		}
 966
 967		var library = this.get('library');
 968
 969		if ( ! library || ! browser ) {
 970			return;
 971		}
 972
 973		library.gallery = library.gallery || new Backbone.Model();
 974
 975		browser.sidebar.set({
 976			gallery: new wp.media.view.Settings.Gallery({
 977				controller: this,
 978				model:      library.gallery,
 979				priority:   40
 980			})
 981		});
 982
 983		browser.toolbar.set( 'reverse', {
 984			text:     l10n.reverseOrder,
 985			priority: 80,
 986
 987			click: function() {
 988				library.reset( library.toArray().reverse() );
 989			}
 990		});
 991	}
 992});
 993
 994module.exports = GalleryEdit;
 995
 996},{}],10:[function(require,module,exports){
 997/**
 998 * wp.media.controller.ImageDetails
 999 *
1000 * A state for editing the attachment display settings of an image that's been
1001 * inserted into the editor.
1002 *
1003 * @class
1004 * @augments wp.media.controller.State
1005 * @augments Backbone.Model
1006 *
1007 * @param {object}                    [attributes]                       The attributes hash passed to the state.
1008 * @param {string}                    [attributes.id=image-details]      Unique identifier.
1009 * @param {string}                    [attributes.title=Image Details]   Title for the state. Displays in the frame's title region.
1010 * @param {wp.media.model.Attachment} attributes.image                   The image's model.
1011 * @param {string|false}              [attributes.content=image-details] Initial mode for the content region.
1012 * @param {string|false}              [attributes.menu=false]            Initial mode for the menu region.
1013 * @param {string|false}              [attributes.router=false]          Initial mode for the router region.
1014 * @param {string|false}              [attributes.toolbar=image-details] Initial mode for the toolbar region.
1015 * @param {boolean}                   [attributes.editing=false]         Unused.
1016 * @param {int}                       [attributes.priority=60]           Unused.
1017 *
1018 * @todo This state inherits some defaults from media.controller.Library.prototype.defaults,
1019 *       however this may not do anything.
1020 */
1021var State = wp.media.controller.State,
1022	Library = wp.media.controller.Library,
1023	l10n = wp.media.view.l10n,
1024	ImageDetails;
1025
1026ImageDetails = State.extend({
1027	defaults: _.defaults({
1028		id:       'image-details',
1029		title:    l10n.imageDetailsTitle,
1030		content:  'image-details',
1031		menu:     false,
1032		router:   false,
1033		toolbar:  'image-details',
1034		editing:  false,
1035		priority: 60
1036	}, Library.prototype.defaults ),
1037
1038	/**
1039	 * @since 3.9.0
1040	 *
1041	 * @param options Attributes
1042	 */
1043	initialize: function( options ) {
1044		this.image = options.image;
1045		State.prototype.initialize.apply( this, arguments );
1046	},
1047
1048	/**
1049	 * @since 3.9.0
1050	 */
1051	activate: function() {
1052		this.frame.modal.$el.addClass('image-details');
1053	}
1054});
1055
1056module.exports = ImageDetails;
1057
1058},{}],11:[function(require,module,exports){
1059/**
1060 * wp.media.controller.Library
1061 *
1062 * A state for choosing an attachment or group of attachments from the media library.
1063 *
1064 * @class
1065 * @augments wp.media.controller.State
1066 * @augments Backbone.Model
1067 * @mixes media.selectionSync
1068 *
1069 * @param {object}                          [attributes]                         The attributes hash passed to the state.
1070 * @param {string}                          [attributes.id=library]              Unique identifier.
1071 * @param {string}                          [attributes.title=Media library]     Title for the state. Displays in the media menu and the frame's title region.
1072 * @param {wp.media.model.Attachments}      [attributes.library]                 The attachments collection to browse.
1073 *                                                                               If one is not supplied, a collection of all attachments will be created.
1074 * @param {wp.media.model.Selection|object} [attributes.selection]               A collection to contain attachment selections within the state.
1075 *                                                                               If the 'selection' attribute is a plain JS object,
1076 *                                                                               a Selection will be created using its values as the selection instance's `props` model.
1077 *                                                                               Otherwise, it will copy the library's `props` model.
1078 * @param {boolean}                         [attributes.multiple=false]          Whether multi-select is enabled.
1079 * @param {string}                          [attributes.content=upload]          Initial mode for the content region.
1080 *                                                                               Overridden by persistent user setting if 'contentUserSetting' is true.
1081 * @param {string}                          [attributes.menu=default]            Initial mode for the menu region.
1082 * @param {string}                          [attributes.router=browse]           Initial mode for the router region.
1083 * @param {string}                          [attributes.toolbar=select]          Initial mode for the toolbar region.
1084 * @param {boolean}                         [attributes.searchable=true]         Whether the library is searchable.
1085 * @param {boolean|string}                  [attributes.filterable=false]        Whether the library is filterable, and if so what filters should be shown.
1086 *                                                                               Accepts 'all', 'uploaded', or 'unattached'.
1087 * @param {boolean}                         [attributes.sortable=true]           Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
1088 * @param {boolean}                         [attributes.autoSelect=true]         Whether an uploaded attachment should be automatically added to the selection.
1089 * @param {boolean}                         [attributes.describe=false]          Whether to offer UI to describe attachments - e.g. captioning images in a gallery.
1090 * @param {boolean}                         [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
1091 * @param {boolean}                         [attributes.syncSelection=true]      Whether the Attachments selection should be persisted from the last state.
1092 */
1093var l10n = wp.media.view.l10n,
1094	getUserSetting = window.getUserSetting,
1095	setUserSetting = window.setUserSetting,
1096	Library;
1097
1098Library = wp.media.controller.State.extend({
1099	defaults: {
1100		id:                 'library',
1101		title:              l10n.mediaLibraryTitle,
1102		multiple:           false,
1103		content:            'upload',
1104		menu:               'default',
1105		router:             'browse',
1106		toolbar:            'select',
1107		searchable:         true,
1108		filterable:         false,
1109		sortable:           true,
1110		autoSelect:         true,
1111		describe:           false,
1112		contentUserSetting: true,
1113		syncSelection:      true
1114	},
1115
1116	/**
1117	 * If a library isn't provided, query all media items.
1118	 * If a selection instance isn't provided, create one.
1119	 *
1120	 * @since 3.5.0
1121	 */
1122	initialize: function() {
1123		var selection = this.get('selection'),
1124			props;
1125
1126		if ( ! this.get('library') ) {
1127			this.set( 'library', wp.media.query() );
1128		}
1129
1130		if ( ! ( selection instanceof wp.media.model.Selection ) ) {
1131			props = selection;
1132
1133			if ( ! props ) {
1134				props = this.get('library').props.toJSON();
1135				props = _.omit( props, 'orderby', 'query' );
1136			}
1137
1138			this.set( 'selection', new wp.media.model.Selection( null, {
1139				multiple: this.get('multiple'),
1140				props: props
1141			}) );
1142		}
1143
1144		this.resetDisplays();
1145	},
1146
1147	/**
1148	 * @since 3.5.0
1149	 */
1150	activate: function() {
1151		this.syncSelection();
1152
1153		wp.Uploader.queue.on( 'add', this.uploading, this );
1154
1155		this.get('selection').on( 'add remove reset', this.refreshContent, this );
1156
1157		if ( this.get( 'router' ) && this.get('contentUserSetting') ) {
1158			this.frame.on( 'content:activate', this.saveContentMode, this );
1159			this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) );
1160		}
1161	},
1162
1163	/**
1164	 * @since 3.5.0
1165	 */
1166	deactivate: function() {
1167		this.recordSelection();
1168
1169		this.frame.off( 'content:activate', this.saveContentMode, this );
1170
1171		// Unbind all event handlers that use this state as the context
1172		// from the selection.
1173		this.get('selection').off( null, null, this );
1174
1175		wp.Uploader.queue.off( null, null, this );
1176	},
1177
1178	/**
1179	 * Reset the library to its initial state.
1180	 *
1181	 * @since 3.5.0
1182	 */
1183	reset: function() {
1184		this.get('selection').reset();
1185		this.resetDisplays();
1186		this.refreshContent();
1187	},
1188
1189	/**
1190	 * Reset the attachment display settings defaults to the site options.
1191	 *
1192	 * If site options don't define them, fall back to a persistent user setting.
1193	 *
1194	 * @since 3.5.0
1195	 */
1196	resetDisplays: function() {
1197		var defaultProps = wp.media.view.settings.defaultProps;
1198		this._displays = [];
1199		this._defaultDisplaySettings = {
1200			align: getUserSetting( 'align', defaultProps.align ) || 'none',
1201			size:  getUserSetting( 'imgsize', defaultProps.size ) || 'medium',
1202			link:  getUserSetting( 'urlbutton', defaultProps.link ) || 'none'
1203		};
1204	},
1205
1206	/**
1207	 * Create a model to represent display settings (alignment, etc.) for an attachment.
1208	 *
1209	 * @since 3.5.0
1210	 *
1211	 * @param {wp.media.model.Attachment} attachment
1212	 * @returns {Backbone.Model}
1213	 */
1214	display: function( attachment ) {
1215		var displays = this._displays;
1216
1217		if ( ! displays[ attachment.cid ] ) {
1218			displays[ attachment.cid ] = new Backbone.Model( this.defaultDisplaySettings( attachment ) );
1219		}
1220		return displays[ attachment.cid ];
1221	},
1222
1223	/**
1224	 * Given an attachment, create attachment display settings properties.
1225	 *
1226	 * @since 3.6.0
1227	 *
1228	 * @param {wp.media.model.Attachment} attachment
1229	 * @returns {Object}
1230	 */
1231	defaultDisplaySettings: function( attachment ) {
1232		var settings = _.clone( this._defaultDisplaySettings );
1233
1234		if ( settings.canEmbed = this.canEmbed( attachment ) ) {
1235			settings.link = 'embed';
1236		} else if ( ! this.isImageAttachment( attachment ) && settings.link === 'none' ) {
1237			settings.link = 'file';
1238		}
1239
1240		return settings;
1241	},
1242
1243	/**
1244	 * Whether an attachment is image.
1245	 *
1246	 * @since 4.4.1
1247	 *
1248	 * @param {wp.media.model.Attachment} attachment
1249	 * @returns {Boolean}
1250	 */
1251	isImageAttachment: function( attachment ) {
1252		// If uploading, we know the filename but not the mime type.
1253		if ( attachment.get('uploading') ) {
1254			return /\.(jpe?g|png|gif)$/i.test( attachment.get('filename') );
1255		}
1256
1257		return attachment.get('type') === 'image';
1258	},
1259
1260	/**
1261	 * Whether an attachment can be embedded (audio or video).
1262	 *
1263	 * @since 3.6.0
1264	 *
1265	 * @param {wp.media.model.Attachment} attachment
1266	 * @returns {Boolean}
1267	 */
1268	canEmbed: function( attachment ) {
1269		// If uploading, we know the filename but not the mime type.
1270		if ( ! attachment.get('uploading') ) {
1271			var type = attachment.get('type');
1272			if ( type !== 'audio' && type !== 'video' ) {
1273				return false;
1274			}
1275		}
1276
1277		return _.contains( wp.media.view.settings.embedExts, attachment.get('filename').split('.').pop() );
1278	},
1279
1280
1281	/**
1282	 * If the state is active, no items are selected, and the current
1283	 * content mode is not an option in the state's router (provided
1284	 * the state has a router), reset the content mode to the default.
1285	 *
1286	 * @since 3.5.0
1287	 */
1288	refreshContent: function() {
1289		var selection = this.get('selection'),
1290			frame = this.frame,
1291			router = frame.router.get(),
1292			mode = frame.content.mode();
1293
1294		if ( this.active && ! selection.length && router && ! router.get( mode ) ) {
1295			this.frame.content.render( this.get('content') );
1296		}
1297	},
1298
1299	/**
1300	 * Callback handler when an attachment is uploaded.
1301	 *
1302	 * Switch to the Media Library if uploaded from the 'Upload Files' tab.
1303	 *
1304	 * Adds any uploading attachments to the selection.
1305	 *
1306	 * If the state only supports one attachment to be selected and multiple
1307	 * attachments are uploaded, the last attachment in the upload queue will
1308	 * be selected.
1309	 *
1310	 * @since 3.5.0
1311	 *
1312	 * @param {wp.media.model.Attachment} attachment
1313	 */
1314	uploading: function( attachment ) {
1315		var content = this.frame.content;
1316
1317		if ( 'upload' === content.mode() ) {
1318			this.frame.content.mode('browse');
1319		}
1320
1321		if ( this.get( 'autoSelect' ) ) {
1322			this.get('selection').add( attachment );
1323			this.frame.trigger( 'library:selection:add' );
1324		}
1325	},
1326
1327	/**
1328	 * Persist the mode of the content region as a user setting.
1329	 *
1330	 * @since 3.5.0
1331	 */
1332	saveContentMode: function() {
1333		if ( 'browse' !== this.get('router') ) {
1334			return;
1335		}
1336
1337		var mode = this.frame.content.mode(),
1338			view = this.frame.router.get();
1339
1340		if ( view && view.get( mode ) ) {
1341			setUserSetting( 'libraryContent', mode );

Large files files are truncated, but you can click here to view the full file