wp/wp-admin/js/widgets/media-gallery-widget.js
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 /* eslint consistent-this: [ "error", "control" ] */
       
     2 (function( component ) {
       
     3 	'use strict';
       
     4 
       
     5 	var GalleryWidgetModel, GalleryWidgetControl, GalleryDetailsMediaFrame;
       
     6 
       
     7 	/**
       
     8 	 * Custom gallery details frame.
       
     9 	 *
       
    10 	 * @since 4.9.0
       
    11 	 * @class GalleryDetailsMediaFrame
       
    12 	 * @constructor
       
    13 	 */
       
    14 	GalleryDetailsMediaFrame = wp.media.view.MediaFrame.Post.extend( {
       
    15 
       
    16 		/**
       
    17 		 * Create the default states.
       
    18 		 *
       
    19 		 * @since 4.9.0
       
    20 		 * @returns {void}
       
    21 		 */
       
    22 		createStates: function createStates() {
       
    23 			this.states.add([
       
    24 				new wp.media.controller.Library({
       
    25 					id:         'gallery',
       
    26 					title:      wp.media.view.l10n.createGalleryTitle,
       
    27 					priority:   40,
       
    28 					toolbar:    'main-gallery',
       
    29 					filterable: 'uploaded',
       
    30 					multiple:   'add',
       
    31 					editable:   true,
       
    32 
       
    33 					library:  wp.media.query( _.defaults({
       
    34 						type: 'image'
       
    35 					}, this.options.library ) )
       
    36 				}),
       
    37 
       
    38 				// Gallery states.
       
    39 				new wp.media.controller.GalleryEdit({
       
    40 					library: this.options.selection,
       
    41 					editing: this.options.editing,
       
    42 					menu:    'gallery'
       
    43 				}),
       
    44 
       
    45 				new wp.media.controller.GalleryAdd()
       
    46 			]);
       
    47 		}
       
    48 	} );
       
    49 
       
    50 	/**
       
    51 	 * Gallery widget model.
       
    52 	 *
       
    53 	 * See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports.
       
    54 	 *
       
    55 	 * @since 4.9.0
       
    56 	 * @class GalleryWidgetModel
       
    57 	 * @constructor
       
    58 	 */
       
    59 	GalleryWidgetModel = component.MediaWidgetModel.extend( {} );
       
    60 
       
    61 	/**
       
    62 	 * Gallery widget control.
       
    63 	 *
       
    64 	 * See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports.
       
    65 	 *
       
    66 	 * @since 4.9.0
       
    67 	 * @class GalleryWidgetControl
       
    68 	 * @constructor
       
    69 	 */
       
    70 	GalleryWidgetControl = component.MediaWidgetControl.extend( {
       
    71 
       
    72 		/**
       
    73 		 * View events.
       
    74 		 *
       
    75 		 * @since 4.9.0
       
    76 		 * @type {object}
       
    77 		 */
       
    78 		events: _.extend( {}, component.MediaWidgetControl.prototype.events, {
       
    79 			'click .media-widget-gallery-preview': 'editMedia'
       
    80 		} ),
       
    81 
       
    82 		/**
       
    83 		 * Initialize.
       
    84 		 *
       
    85 		 * @since 4.9.0
       
    86 		 * @param {Object}         options - Options.
       
    87 		 * @param {Backbone.Model} options.model - Model.
       
    88 		 * @param {jQuery}         options.el - Control field container element.
       
    89 		 * @param {jQuery}         options.syncContainer - Container element where fields are synced for the server.
       
    90 		 * @returns {void}
       
    91 		 */
       
    92 		initialize: function initialize( options ) {
       
    93 			var control = this;
       
    94 
       
    95 			component.MediaWidgetControl.prototype.initialize.call( control, options );
       
    96 
       
    97 			_.bindAll( control, 'updateSelectedAttachments', 'handleAttachmentDestroy' );
       
    98 			control.selectedAttachments = new wp.media.model.Attachments();
       
    99 			control.model.on( 'change:ids', control.updateSelectedAttachments );
       
   100 			control.selectedAttachments.on( 'change', control.renderPreview );
       
   101 			control.selectedAttachments.on( 'reset', control.renderPreview );
       
   102 			control.updateSelectedAttachments();
       
   103 
       
   104 			/*
       
   105 			 * Refresh a Gallery widget partial when the user modifies one of the selected attachments.
       
   106 			 * This ensures that when an attachment's caption is updated in the media modal the Gallery
       
   107 			 * widget in the preview will then be refreshed to show the change. Normally doing this
       
   108 			 * would not be necessary because all of the state should be contained inside the changeset,
       
   109 			 * as everything done in the Customizer should not make a change to the site unless the
       
   110 			 * changeset itself is published. Attachments are a current exception to this rule.
       
   111 			 * For a proposal to include attachments in the customized state, see #37887.
       
   112 			 */
       
   113 			if ( wp.customize && wp.customize.previewer ) {
       
   114 				control.selectedAttachments.on( 'change', function() {
       
   115 					wp.customize.previewer.send( 'refresh-widget-partial', control.model.get( 'widget_id' ) );
       
   116 				} );
       
   117 			}
       
   118 		},
       
   119 
       
   120 		/**
       
   121 		 * Update the selected attachments if necessary.
       
   122 		 *
       
   123 		 * @since 4.9.0
       
   124 		 * @returns {void}
       
   125 		 */
       
   126 		updateSelectedAttachments: function updateSelectedAttachments() {
       
   127 			var control = this, newIds, oldIds, removedIds, addedIds, addedQuery;
       
   128 
       
   129 			newIds = control.model.get( 'ids' );
       
   130 			oldIds = _.pluck( control.selectedAttachments.models, 'id' );
       
   131 
       
   132 			removedIds = _.difference( oldIds, newIds );
       
   133 			_.each( removedIds, function( removedId ) {
       
   134 				control.selectedAttachments.remove( control.selectedAttachments.get( removedId ) );
       
   135 			});
       
   136 
       
   137 			addedIds = _.difference( newIds, oldIds );
       
   138 			if ( addedIds.length ) {
       
   139 				addedQuery = wp.media.query({
       
   140 					order: 'ASC',
       
   141 					orderby: 'post__in',
       
   142 					perPage: -1,
       
   143 					post__in: newIds,
       
   144 					query: true,
       
   145 					type: 'image'
       
   146 				});
       
   147 				addedQuery.more().done( function() {
       
   148 					control.selectedAttachments.reset( addedQuery.models );
       
   149 				});
       
   150 			}
       
   151 		},
       
   152 
       
   153 		/**
       
   154 		 * Render preview.
       
   155 		 *
       
   156 		 * @since 4.9.0
       
   157 		 * @returns {void}
       
   158 		 */
       
   159 		renderPreview: function renderPreview() {
       
   160 			var control = this, previewContainer, previewTemplate, data;
       
   161 
       
   162 			previewContainer = control.$el.find( '.media-widget-preview' );
       
   163 			previewTemplate = wp.template( 'wp-media-widget-gallery-preview' );
       
   164 
       
   165 			data = control.previewTemplateProps.toJSON();
       
   166 			data.attachments = {};
       
   167 			control.selectedAttachments.each( function( attachment ) {
       
   168 				data.attachments[ attachment.id ] = attachment.toJSON();
       
   169 			} );
       
   170 
       
   171 			previewContainer.html( previewTemplate( data ) );
       
   172 		},
       
   173 
       
   174 		/**
       
   175 		 * Determine whether there are selected attachments.
       
   176 		 *
       
   177 		 * @since 4.9.0
       
   178 		 * @returns {boolean} Selected.
       
   179 		 */
       
   180 		isSelected: function isSelected() {
       
   181 			var control = this;
       
   182 
       
   183 			if ( control.model.get( 'error' ) ) {
       
   184 				return false;
       
   185 			}
       
   186 
       
   187 			return control.model.get( 'ids' ).length > 0;
       
   188 		},
       
   189 
       
   190 		/**
       
   191 		 * Open the media select frame to edit images.
       
   192 		 *
       
   193 		 * @since 4.9.0
       
   194 		 * @returns {void}
       
   195 		 */
       
   196 		editMedia: function editMedia() {
       
   197 			var control = this, selection, mediaFrame, mediaFrameProps;
       
   198 
       
   199 			selection = new wp.media.model.Selection( control.selectedAttachments.models, {
       
   200 				multiple: true
       
   201 			});
       
   202 
       
   203 			mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() );
       
   204 			selection.gallery = new Backbone.Model( mediaFrameProps );
       
   205 			if ( mediaFrameProps.size ) {
       
   206 				control.displaySettings.set( 'size', mediaFrameProps.size );
       
   207 			}
       
   208 			mediaFrame = new GalleryDetailsMediaFrame({
       
   209 				frame: 'manage',
       
   210 				text: control.l10n.add_to_widget,
       
   211 				selection: selection,
       
   212 				mimeType: control.mime_type,
       
   213 				selectedDisplaySettings: control.displaySettings,
       
   214 				showDisplaySettings: control.showDisplaySettings,
       
   215 				metadata: mediaFrameProps,
       
   216 				editing:   true,
       
   217 				multiple:  true,
       
   218 				state: 'gallery-edit'
       
   219 			});
       
   220 			wp.media.frame = mediaFrame; // See wp.media().
       
   221 
       
   222 			// Handle selection of a media item.
       
   223 			mediaFrame.on( 'update', function onUpdate( newSelection ) {
       
   224 				var state = mediaFrame.state(), resultSelection;
       
   225 
       
   226 				resultSelection = newSelection || state.get( 'selection' );
       
   227 				if ( ! resultSelection ) {
       
   228 					return;
       
   229 				}
       
   230 
       
   231 				// Copy orderby_random from gallery state.
       
   232 				if ( resultSelection.gallery ) {
       
   233 					control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) );
       
   234 				}
       
   235 
       
   236 				// Directly update selectedAttachments to prevent needing to do additional request.
       
   237 				control.selectedAttachments.reset( resultSelection.models );
       
   238 
       
   239 				// Update models in the widget instance.
       
   240 				control.model.set( {
       
   241 					ids: _.pluck( resultSelection.models, 'id' )
       
   242 				} );
       
   243 			} );
       
   244 
       
   245 			mediaFrame.$el.addClass( 'media-widget' );
       
   246 			mediaFrame.open();
       
   247 
       
   248 			if ( selection ) {
       
   249 				selection.on( 'destroy', control.handleAttachmentDestroy );
       
   250 			}
       
   251 		},
       
   252 
       
   253 		/**
       
   254 		 * Open the media select frame to chose an item.
       
   255 		 *
       
   256 		 * @since 4.9.0
       
   257 		 * @returns {void}
       
   258 		 */
       
   259 		selectMedia: function selectMedia() {
       
   260 			var control = this, selection, mediaFrame, mediaFrameProps;
       
   261 			selection = new wp.media.model.Selection( control.selectedAttachments.models, {
       
   262 				multiple: true
       
   263 			});
       
   264 
       
   265 			mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() );
       
   266 			if ( mediaFrameProps.size ) {
       
   267 				control.displaySettings.set( 'size', mediaFrameProps.size );
       
   268 			}
       
   269 			mediaFrame = new GalleryDetailsMediaFrame({
       
   270 				frame: 'select',
       
   271 				text: control.l10n.add_to_widget,
       
   272 				selection: selection,
       
   273 				mimeType: control.mime_type,
       
   274 				selectedDisplaySettings: control.displaySettings,
       
   275 				showDisplaySettings: control.showDisplaySettings,
       
   276 				metadata: mediaFrameProps,
       
   277 				state: 'gallery'
       
   278 			});
       
   279 			wp.media.frame = mediaFrame; // See wp.media().
       
   280 
       
   281 			// Handle selection of a media item.
       
   282 			mediaFrame.on( 'update', function onUpdate( newSelection ) {
       
   283 				var state = mediaFrame.state(), resultSelection;
       
   284 
       
   285 				resultSelection = newSelection || state.get( 'selection' );
       
   286 				if ( ! resultSelection ) {
       
   287 					return;
       
   288 				}
       
   289 
       
   290 				// Copy orderby_random from gallery state.
       
   291 				if ( resultSelection.gallery ) {
       
   292 					control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) );
       
   293 				}
       
   294 
       
   295 				// Directly update selectedAttachments to prevent needing to do additional request.
       
   296 				control.selectedAttachments.reset( resultSelection.models );
       
   297 
       
   298 				// Update widget instance.
       
   299 				control.model.set( {
       
   300 					ids: _.pluck( resultSelection.models, 'id' )
       
   301 				} );
       
   302 			} );
       
   303 
       
   304 			mediaFrame.$el.addClass( 'media-widget' );
       
   305 			mediaFrame.open();
       
   306 
       
   307 			if ( selection ) {
       
   308 				selection.on( 'destroy', control.handleAttachmentDestroy );
       
   309 			}
       
   310 
       
   311 			/*
       
   312 			 * Make sure focus is set inside of modal so that hitting Esc will close
       
   313 			 * the modal and not inadvertently cause the widget to collapse in the customizer.
       
   314 			 */
       
   315 			mediaFrame.$el.find( ':focusable:first' ).focus();
       
   316 		},
       
   317 
       
   318 		/**
       
   319 		 * Clear the selected attachment when it is deleted in the media select frame.
       
   320 		 *
       
   321 		 * @since 4.9.0
       
   322 		 * @param {wp.media.models.Attachment} attachment - Attachment.
       
   323 		 * @returns {void}
       
   324 		 */
       
   325 		handleAttachmentDestroy: function handleAttachmentDestroy( attachment ) {
       
   326 			var control = this;
       
   327 			control.model.set( {
       
   328 				ids: _.difference(
       
   329 					control.model.get( 'ids' ),
       
   330 					[ attachment.id ]
       
   331 				)
       
   332 			} );
       
   333 		}
       
   334 	} );
       
   335 
       
   336 	// Exports.
       
   337 	component.controlConstructors.media_gallery = GalleryWidgetControl;
       
   338 	component.modelConstructors.media_gallery = GalleryWidgetModel;
       
   339 
       
   340 })( wp.mediaWidgets );