PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.5.4
Secure Custom Fields v6.5.4
6.9.5 6.9.4 6.9.3 6.9.2 6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / assets / src / js / pro / _acf-field-gallery.js
secure-custom-fields / assets / src / js / pro Last commit date
_acf-blocks.js 1 year ago _acf-field-flexible-content.js 1 year ago _acf-field-gallery.js 1 year ago _acf-field-repeater.js 1 year ago _acf-jsx-names.js 1 year ago _acf-setting-clone.js 1 year ago _acf-setting-flexible-content.js 1 year ago _acf-setting-repeater.js 1 year ago _acf-ui-options-page.js 1 year ago acf-pro-blocks.js 1 year ago acf-pro-field-group.js 1 year ago acf-pro-input.js 1 year ago acf-pro-ui-options-page.js 1 year ago
_acf-field-gallery.js
616 lines
1 ( function ( $ ) {
2 var Field = acf.Field.extend( {
3 type: 'gallery',
4
5 events: {
6 'click .acf-gallery-add': 'onClickAdd',
7 'click .acf-gallery-edit': 'onClickEdit',
8 'click .acf-gallery-remove': 'onClickRemove',
9 'click .acf-gallery-attachment': 'onClickSelect',
10 'click .acf-gallery-close': 'onClickClose',
11 'change .acf-gallery-sort': 'onChangeSort',
12 'click .acf-gallery-update': 'onUpdate',
13 mouseover: 'onHover',
14 showField: 'render',
15 },
16
17 actions: {
18 validation_begin: 'onValidationBegin',
19 validation_failure: 'onValidationFailure',
20 resize: 'onResize',
21 },
22
23 onValidationBegin: function () {
24 acf.disable( this.$sideData(), this.cid );
25 },
26
27 onValidationFailure: function () {
28 acf.enable( this.$sideData(), this.cid );
29 },
30
31 $control: function () {
32 return this.$( '.acf-gallery' );
33 },
34
35 $collection: function () {
36 return this.$( '.acf-gallery-attachments' );
37 },
38
39 $attachments: function () {
40 return this.$( '.acf-gallery-attachment' );
41 },
42
43 $attachment: function ( id ) {
44 return this.$( '.acf-gallery-attachment[data-id="' + id + '"]' );
45 },
46
47 $active: function () {
48 return this.$( '.acf-gallery-attachment.active' );
49 },
50
51 $main: function () {
52 return this.$( '.acf-gallery-main' );
53 },
54
55 $side: function () {
56 return this.$( '.acf-gallery-side' );
57 },
58
59 $sideData: function () {
60 return this.$( '.acf-gallery-side-data' );
61 },
62
63 isFull: function () {
64 var max = parseInt( this.get( 'max' ) );
65 var count = this.$attachments().length;
66 return max && count >= max;
67 },
68
69 getValue: function () {
70 // vars
71 var val = [];
72
73 // loop
74 this.$attachments().each( function () {
75 val.push( $( this ).data( 'id' ) );
76 } );
77
78 // return
79 return val.length ? val : false;
80 },
81
82 addUnscopedEvents: function ( self ) {
83 // invalidField
84 this.on( 'change', '.acf-gallery-side', function ( e ) {
85 self.onUpdate( e, $( this ) );
86 } );
87 },
88
89 addSortable: function ( self ) {
90 // add sortable
91 this.$collection().sortable( {
92 items: '.acf-gallery-attachment',
93 forceHelperSize: true,
94 forcePlaceholderSize: true,
95 scroll: true,
96 start: function ( event, ui ) {
97 ui.placeholder.html( ui.item.html() );
98 ui.placeholder.removeAttr( 'style' );
99 },
100 update: function ( event, ui ) {
101 self.$input().trigger( 'change' );
102 },
103 } );
104
105 // resizable
106 this.$control().resizable( {
107 handles: 's',
108 minHeight: 200,
109 stop: function ( event, ui ) {
110 acf.update_user_setting( 'gallery_height', ui.size.height );
111 },
112 } );
113 },
114
115 initialize: function () {
116 // add unscoped events
117 this.addUnscopedEvents( this );
118
119 // render
120 this.render();
121 },
122
123 render: function () {
124 // vars
125 var $sort = this.$( '.acf-gallery-sort' );
126 var $add = this.$( '.acf-gallery-add' );
127 var count = this.$attachments().length;
128
129 // disable add
130 if ( this.isFull() ) {
131 $add.addClass( 'disabled' );
132 } else {
133 $add.removeClass( 'disabled' );
134 }
135
136 // disable select
137 if ( ! count ) {
138 $sort.addClass( 'disabled' );
139 } else {
140 $sort.removeClass( 'disabled' );
141 }
142
143 // resize
144 this.resize();
145 },
146
147 resize: function () {
148 // vars
149 var width = this.$control().width();
150 var target = 150;
151 var columns = Math.round( width / target );
152
153 // max columns = 8
154 columns = Math.min( columns, 8 );
155
156 // update data
157 this.$control().attr( 'data-columns', columns );
158 },
159
160 onResize: function () {
161 this.resize();
162 },
163
164 openSidebar: function () {
165 // add class
166 this.$control().addClass( '-open' );
167
168 // hide bulk actions
169 // should be done with CSS
170 //this.$main().find('.acf-gallery-sort').hide();
171
172 // vars
173 var width = this.$control().width() / 3;
174 width = parseInt( width );
175 width = Math.max( width, 350 );
176
177 // animate
178 this.$( '.acf-gallery-side-inner' ).css( { width: width - 1 } );
179 this.$side().animate( { width: width - 1 }, 250 );
180 this.$main().animate( { right: width }, 250 );
181 },
182
183 closeSidebar: function () {
184 // remove class
185 this.$control().removeClass( '-open' );
186
187 // clear selection
188 this.$active().removeClass( 'active' );
189
190 // disable sidebar
191 acf.disable( this.$side() );
192
193 // animate
194 var $sideData = this.$( '.acf-gallery-side-data' );
195 this.$main().animate( { right: 0 }, 250 );
196 this.$side().animate( { width: 0 }, 250, function () {
197 $sideData.html( '' );
198 } );
199 },
200
201 onClickAdd: function ( e, $el ) {
202 // validate
203 if ( this.isFull() ) {
204 this.showNotice( {
205 text: acf.__( 'Maximum selection reached' ),
206 type: 'warning',
207 } );
208 return;
209 }
210
211 // new frame
212 var frame = acf.newMediaPopup( {
213 mode: 'select',
214 title: acf.__( 'Add Image to Gallery' ),
215 field: this.get( 'key' ),
216 multiple: 'add',
217 library: this.get( 'library' ),
218 allowedTypes: this.get( 'mime_types' ),
219 selected: this.val(),
220 select: $.proxy( function ( attachment, i ) {
221 this.appendAttachment( attachment, i );
222 }, this ),
223 } );
224 },
225
226 appendAttachment: function ( attachment, i ) {
227 // vars
228 attachment = this.validateAttachment( attachment );
229
230 // bail early if is full
231 if ( this.isFull() ) {
232 return;
233 }
234
235 // bail early if already exists
236 if ( this.$attachment( attachment.id ).length ) {
237 return;
238 }
239
240 // html
241 var html = [
242 '<div class="acf-gallery-attachment" data-id="' +
243 attachment.id +
244 '">',
245 '<input type="hidden" value="' +
246 attachment.id +
247 '" name="' +
248 this.getInputName() +
249 '[]">',
250 '<div class="margin" title="">',
251 '<div class="thumbnail">',
252 '<img src="" alt="">',
253 '</div>',
254 '<div class="filename"></div>',
255 '</div>',
256 '<div class="actions">',
257 '<a href="#" class="acf-icon -cancel dark acf-gallery-remove" data-id="' +
258 attachment.id +
259 '"></a>',
260 '</div>',
261 '</div>',
262 ].join( '' );
263 var $html = $( html );
264
265 // append
266 this.$collection().append( $html );
267
268 // move to beginning
269 if ( this.get( 'insert' ) === 'prepend' ) {
270 var $before = this.$attachments().eq( i );
271 if ( $before.length ) {
272 $before.before( $html );
273 }
274 }
275
276 // render attachment
277 this.renderAttachment( attachment );
278
279 // render
280 this.render();
281
282 // trigger change
283 this.$input().trigger( 'change' );
284 },
285
286 validateAttachment: function ( attachment ) {
287 // defaults
288 attachment = acf.parseArgs( attachment, {
289 id: '',
290 url: '',
291 alt: '',
292 title: '',
293 filename: '',
294 type: 'image',
295 } );
296
297 // WP attachment
298 if ( attachment.attributes ) {
299 attachment = attachment.attributes;
300
301 // preview size
302 var url = acf.isget(
303 attachment,
304 'sizes',
305 this.get( 'preview_size' ),
306 'url'
307 );
308 if ( url !== null ) {
309 attachment.url = url;
310 }
311 }
312
313 // return
314 return attachment;
315 },
316
317 renderAttachment: function ( attachment ) {
318 // vars
319 attachment = this.validateAttachment( attachment );
320
321 // vars
322 var $el = this.$attachment( attachment.id );
323
324 // Image type.
325 if ( attachment.type == 'image' ) {
326 // Remove filename.
327 $el.find( '.filename' ).remove();
328
329 // Other file type.
330 } else {
331 // Check for attachment featured image.
332 var image = acf.isget( attachment, 'image', 'src' );
333 if ( image !== null ) {
334 attachment.url = image;
335 }
336
337 // Update filename text.
338 $el.find( '.filename' ).text( attachment.filename );
339 }
340
341 // Default to mimetype icon.
342 if ( ! attachment.url ) {
343 attachment.url = acf.get( 'mimeTypeIcon' );
344 $el.addClass( '-icon' );
345 }
346
347 // update els
348 $el.find( 'img' ).attr( {
349 src: attachment.url,
350 alt: attachment.alt,
351 title: attachment.title,
352 } );
353
354 // update val
355 acf.val( $el.find( 'input' ), attachment.id );
356 },
357
358 editAttachment: function ( id ) {
359 // new frame
360 var frame = acf.newMediaPopup( {
361 mode: 'edit',
362 title: acf.__( 'Edit Image' ),
363 button: acf.__( 'Update Image' ),
364 attachment: id,
365 field: this.get( 'key' ),
366 select: $.proxy( function ( attachment, i ) {
367 this.renderAttachment( attachment );
368 // todo - render sidebar
369 }, this ),
370 } );
371 },
372
373 onClickEdit: function ( e, $el ) {
374 var id = $el.data( 'id' );
375 if ( id ) {
376 this.editAttachment( id );
377 }
378 },
379
380 removeAttachment: function ( id ) {
381 // close sidebar (if open)
382 this.closeSidebar();
383
384 // remove attachment
385 this.$attachment( id ).remove();
386
387 // render
388 this.render();
389
390 // trigger change
391 this.$input().trigger( 'change' );
392 },
393
394 onClickRemove: function ( e, $el ) {
395 // prevent event from triggering click on attachment
396 e.preventDefault();
397 e.stopPropagation();
398
399 //remove
400 var id = $el.data( 'id' );
401 if ( id ) {
402 this.removeAttachment( id );
403 }
404 },
405
406 selectAttachment: function ( id ) {
407 // vars
408 var $el = this.$attachment( id );
409
410 // bail early if already active
411 if ( $el.hasClass( 'active' ) ) {
412 return;
413 }
414
415 // step 1
416 var step1 = this.proxy( function () {
417 // save any changes in sidebar
418 this.$side().find( ':focus' ).trigger( 'blur' );
419
420 // clear selection
421 this.$active().removeClass( 'active' );
422
423 // add selection
424 $el.addClass( 'active' );
425
426 // open sidebar
427 this.openSidebar();
428
429 // call step 2
430 step2();
431 } );
432
433 // step 2
434 var step2 = this.proxy( function () {
435 const ajaxData = {
436 action: 'acf/fields/gallery/get_attachment',
437 nonce: this.get( 'nonce' ),
438 field_key: this.get( 'key' ),
439 id: id,
440 };
441
442 // abort prev ajax call
443 if ( this.has( 'xhr' ) ) {
444 this.get( 'xhr' ).abort();
445 }
446
447 // loading
448 acf.showLoading( this.$sideData() );
449
450 // get HTML
451 var xhr = $.ajax( {
452 url: acf.get( 'ajaxurl' ),
453 data: acf.prepareForAjax( ajaxData ),
454 type: 'post',
455 dataType: 'html',
456 cache: false,
457 success: step3,
458 } );
459
460 // update
461 this.set( 'xhr', xhr );
462 } );
463
464 // step 3
465 var step3 = this.proxy( function ( html ) {
466 // bail early if no html
467 if ( ! html ) {
468 return;
469 }
470
471 // vars
472 var $side = this.$sideData();
473
474 // render
475 $side.html( html );
476
477 // remove acf form data
478 $side.find( '.compat-field-acf-form-data' ).remove();
479
480 // merge tables
481 $side
482 .find( '> table.form-table > tbody' )
483 .append(
484 $side.find( '> .compat-attachment-fields > tbody > tr' )
485 );
486
487 // setup fields
488 acf.doAction( 'append', $side );
489 } );
490
491 // run step 1
492 step1();
493 },
494
495 onClickSelect: function ( e, $el ) {
496 var id = $el.data( 'id' );
497 if ( id ) {
498 this.selectAttachment( id );
499 }
500 },
501
502 onClickClose: function ( e, $el ) {
503 this.closeSidebar();
504 },
505
506 onChangeSort: function ( e, $el ) {
507 // Bail early if is disabled.
508 if ( $el.hasClass( 'disabled' ) ) {
509 return;
510 }
511
512 // Get sort val.
513 var val = $el.val();
514 if ( ! val ) {
515 return;
516 }
517
518 // find ids
519 var ids = [];
520 this.$attachments().each( function () {
521 ids.push( $( this ).data( 'id' ) );
522 } );
523
524 // step 1
525 var step1 = this.proxy( function () {
526 const ajaxData = {
527 action: 'acf/fields/gallery/get_sort_order',
528 nonce: this.get( 'nonce' ),
529 field_key: this.get( 'key' ),
530 ids: ids,
531 sort: val,
532 };
533
534 // get results
535 var xhr = $.ajax( {
536 url: acf.get( 'ajaxurl' ),
537 dataType: 'json',
538 type: 'post',
539 cache: false,
540 data: acf.prepareForAjax( ajaxData ),
541 success: step2,
542 } );
543 } );
544
545 // step 2
546 var step2 = this.proxy( function ( json ) {
547 // validate
548 if ( ! acf.isAjaxSuccess( json ) ) {
549 return;
550 }
551
552 // reverse order
553 json.data.reverse();
554
555 // loop
556 json.data.map( function ( id ) {
557 this.$collection().prepend( this.$attachment( id ) );
558 }, this );
559 } );
560
561 // call step 1
562 step1();
563 },
564
565 onUpdate: function ( e, $el ) {
566 // vars
567 var $submit = this.$( '.acf-gallery-update' );
568
569 // validate
570 if ( $submit.hasClass( 'disabled' ) ) {
571 return;
572 }
573
574 // serialize data
575 const ajaxData = acf.serialize( this.$sideData() );
576
577 // loading
578 $submit.addClass( 'disabled' );
579 $submit.before( '<i class="acf-loading"></i> ' );
580
581 // Append AJAX action and nonce.
582 ajaxData.action = 'acf/fields/gallery/update_attachment';
583 ajaxData.nonce = this.get( 'nonce' );
584 ajaxData.field_key = this.get( 'key' );
585
586 // ajax
587 $.ajax( {
588 url: acf.get( 'ajaxurl' ),
589 data: acf.prepareForAjax( ajaxData ),
590 type: 'post',
591 dataType: 'json',
592 complete: function () {
593 $submit.removeClass( 'disabled' );
594 $submit.prev( '.acf-loading' ).remove();
595 },
596 } );
597 },
598
599 onHover: function () {
600 // add sortable
601 this.addSortable( this );
602
603 // remove event
604 this.off( 'mouseover' );
605 },
606 } );
607
608 acf.registerFieldType( Field );
609
610 // register existing conditions
611 acf.registerConditionForFieldType( 'hasValue', 'gallery' );
612 acf.registerConditionForFieldType( 'hasNoValue', 'gallery' );
613 acf.registerConditionForFieldType( 'selectionLessThan', 'gallery' );
614 acf.registerConditionForFieldType( 'selectionGreaterThan', 'gallery' );
615 } )( jQuery );
616