summaryrefslogtreecommitdiff
blob: 6a926d698ae3caaaea7f12d883fcee2cf6e4351d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/* global _wpMediaViewsL10n, _wpGalleryWidgetAdminSettings */

( function( $ ) {
	var $ids;
	var $thumbs;

	$( function() {
		$( document.body ).on( 'click', '.gallery-widget-choose-images', function( event ) {
			event.preventDefault();

			var widget_form = $( this ).closest( 'form, .form' );

			$ids = widget_form.find( '.gallery-widget-ids' );
			$thumbs = widget_form.find( '.gallery-widget-thumbs' );

			var idsString = $ids.val();

			var attachments = getAttachments( idsString );

			var selection = null;
			var editing = false;

			if ( attachments ) {
				selection = getSelection( attachments );

				editing = true;
			}

			var options = {
				state: 'gallery-edit',
				title: wp.media.view.l10n.addMedia,
				multiple: true,
				editing: editing,
				selection: selection,
			};

			var workflow = getWorkflow( options );

			workflow.open();
		} );

		// Setup an onchange handler to toggle various options when changing style. The different style options
		// require different form inputs to be presented in the widget; this event will keep the UI in sync
		// with the selected style
		$( '.widget-inside' ).on( 'change', '.gallery-widget-style', setupStyleOptions );

		// Setup the Link To options for all forms currently on the page. Does the same as the onChange handler, but
		// is called once to display the correct form inputs for each widget on the page
		setupStyleOptions();
	} );

	var media = wp.media,
		l10n;

	// Link any localized strings.
	l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;

	/**
	 * wp.media.view.MediaFrame.GalleryWidget
	 *
	 * This behavior can be very nearly had by setting the workflow's state to 'gallery-edit', but
	 * we cannot use the custom WidgetGalleryEdit controller with it (must overide createStates(),
	 * which is necessary to disable the sidebar gallery settings in the media browser)
	 */
	media.view.MediaFrame.GalleryWidget = media.view.MediaFrame.Post.extend( {
		createStates: function() {
			var options = this.options;

			// `CollectionEdit` and `CollectionAdd` were only introduced in r27214-core,
			// so they may not be available yet.
			if ( 'CollectionEdit' in media.controller ) {
				this.states.add( [
					new media.controller.CollectionEdit( {
						type: 'image',
						collectionType: 'gallery',
						title: l10n.editGalleryTitle,
						SettingsView: media.view.Settings.Gallery,
						library: options.selection,
						editing: options.editing,
						menu: 'gallery',
					} ),
					new media.controller.CollectionAdd( {
						type: 'image',
						collectionType: 'gallery',
						title: l10n.addToGalleryTitle,
					} ),
				] );
			} else {
				// If `CollectionEdit` is not available, then use the old approach.

				if ( ! ( 'WidgetGalleryEdit' in media.controller ) ) {
					// Remove the gallery settings sidebar when editing widgets.
					media.controller.WidgetGalleryEdit = media.controller.GalleryEdit.extend( {
						gallerySettings: function(/*browser*/) {
							return;
						},
					} );
				}

				this.states.add( [
					new media.controller.WidgetGalleryEdit( {
						library: options.selection,
						editing: options.editing,
						menu: 'gallery',
					} ),
					new media.controller.GalleryAdd( {} ),
				] );
			}
		},
	} );

	function setupStyleOptions() {
		$( '.widget-inside .gallery-widget-style' ).each( function(/*i*/) {
			var style = $( this ).val();

			var form = $( this ).parents( 'form' );

			switch ( style ) {
				case 'slideshow':
					form.find( '.gallery-widget-link-wrapper' ).hide();
					form.find( '.gallery-widget-columns-wrapper' ).hide();

					break;

				default:
					form.find( '.gallery-widget-link-wrapper' ).show();
					form.find( '.gallery-widget-columns-wrapper' ).show();
			}
		} );
	}

	/**
	 * Take a given Selection of attachments and a thumbs wrapper div (jQuery object)
	 * and fill it with thumbnails
	 */
	function setupThumbs( selection, wrapper ) {
		wrapper.empty();

		var imageSize = _wpGalleryWidgetAdminSettings.thumbSize;

		selection.each( function( model ) {
			var sizedUrl = model.get( 'url' ) + '?w=' + imageSize + '&h=' + imageSize + '&crop=true';

			var thumb = jQuery( '<img>', {
				src: sizedUrl,
				alt: model.get( 'title' ),
				title: model.get( 'title' ),
				width: imageSize,
				height: imageSize,
				class: 'thumb',
			} );

			wrapper.append( thumb );
		} );
	}

	/**
	 * Take a csv string of ids (as stored in db) and fetch a full Attachments collection
	 */
	function getAttachments( idsString ) {
		if ( ! idsString ) {
			return null;
		}

		// Found in /wp-includes/js/media-editor.js
		var shortcode = wp.shortcode.next( 'gallery', '[gallery ids="' + idsString + '"]' );

		// Ignore the rest of the match object, to give attachments() below what it expects
		shortcode = shortcode.shortcode;

		var attachments = wp.media.gallery.attachments( shortcode );

		return attachments;
	}

	/**
	 * Take an Attachments collection and return a corresponding Selection model that can be
	 * passed to a MediaFrame to prepopulate the gallery picker
	 */
	function getSelection( attachments ) {
		var selection = new wp.media.model.Selection( attachments.models, {
			props: attachments.props.toJSON(),
			multiple: true,
		} );

		selection.gallery = attachments.gallery;

		// Fetch the query's attachments, and then break ties from the
		// query to allow for sorting.
		selection.more().done( function() {
			// Break ties with the query.
			selection.props.set( { query: false } );
			selection.unmirror();
			selection.props.unset( 'orderby' );
		} );

		return selection;
	}

	/**
	 * Create a media 'workflow' (MediaFrame). This is the main entry point for the media picker
	 */
	function getWorkflow( options ) {
		var workflow = new wp.media.view.MediaFrame.GalleryWidget( options );

		workflow.on(
			'update',
			function( selection ) {
				var state = workflow.state();

				selection = selection || state.get( 'selection' );

				if ( ! selection ) {
					return;
				}

				// Map the Models down into a simple array of ids that can be easily imploded to a csv string
				var ids = selection.map( function( model ) {
					return model.get( 'id' );
				} );

				var id_string = ids.join( ',' );

				$ids.val( id_string ).trigger( 'change' );

				setupThumbs( selection, $thumbs );
			},
			this
		);

		workflow.setState( workflow.options.state );

		return workflow;
	}
} )( jQuery );