PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
charitable / assets / js / campaign-builder / drag-fields.js

drag-fields.js in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.13, at assets/js/campaign-builder/drag-fields.js

934 lines 25.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global charitable_builder, wpchar, CharitableCampaignBuilder, CharitableUtils */
2
3 /**
4 * Campaign Builder Builder Fields Drag-n-Drop module.
5 *
6 * @since 1.8.0
7 */
8
9 'use strict';
10
11 var Charitable = window.Charitable || {};
12
13 Charitable.Admin = Charitable.Admin || {};
14 Charitable.Admin.Builder = Charitable.Admin.Builder || {};
15
16 Charitable.Admin.Builder.DragFields = Charitable.Admin.Builder.DragFields || ( function( document, window, $ ) {
17
18 /**
19 * Elements holder.
20 *
21 * @since 1.8.0
22 *
23 * @type {object}
24 */
25 let el = {};
26
27 /**
28 * Runtime variables.
29 *
30 * @since 1.8.0
31 *
32 * @type {object}
33 */
34 let vars = {};
35
36 /**
37 * Layout field functions wrapper.
38 *
39 * @since 1.8.0
40 *
41 * @type {object}
42 */
43 let fieldLayout;
44
45 /**
46 * Public functions and properties.
47 *
48 * @since 1.8.0
49 *
50 * @type {object}
51 */
52 const app = {
53
54 /**
55 * Start the engine.
56 *
57 * @since 1.8.0
58 */
59 init: function() {
60
61 $( app.ready );
62 },
63
64 /**
65 * DOM is fully loaded.
66 *
67 * @since 1.8.0
68 */
69 ready: function() {
70
71 app.setup();
72 app.initSortableFields();
73
74 app.events();
75 },
76
77 /**
78 * Setup. Prepare some variables.
79 *
80 * @since 1.8.0
81 */
82 setup: function() {
83
84 // Cache DOM elements.
85 el = {
86 $builder: $( '#charitable-builder' ),
87 $sortableFieldsWrap: $( '.charitable-panel-fields .charitable-field-wrap' ),
88 $sortableTabsWrap: $( '.charitable-panel-fields .charitable-tab-wrap' ),
89 $addFieldsButtons: $( '.charitable-add-fields-button' ).not( '.not-draggable' ).not( '.warning-modal' ).not( '.charitable-not-available' ).not( '.charitable-not-installed' ),
90 $preview: $( '.charitable-preview' )
91 };
92
93 wpchar.debug('setup drag-fields'), 'drag-fields';
94 wpchar.debug( el , 'drag-fields' );
95 },
96
97 /**
98 * Bind events.
99 *
100 * @since 1.8.0
101 */
102 events: function() {
103
104 el.$builder
105 .on( 'charitableFieldDragToggle', app.fieldDragToggleEvent );
106
107 el.$builder
108 .on( 'charitableAddNewTab', app.initAfterNewTab );
109
110 // el.$builder
111 // .on( 'charitableFieldPreviewSwitchTabs', app.charitableFieldPreviewSwitchTabs );
112 },
113
114 initAfterNewTab: function( $field, groupID = false ) {
115
116 wpchar.debug('groupID'), 'drag-fields';
117 wpchar.debug( $field , 'drag-fields' );
118 wpchar.debug( groupID , 'drag-fields' );
119 wpchar.debug( el.$sortableTabsWrap , 'drag-fields' );
120
121 el.$sortableTabsWrap = $( '.charitable-panel-fields .charitable-tab-wrap' );
122
123 wpchar.debug( el.$sortableTabsWrap , 'drag-fields' );
124
125 app.initSortableFields();
126
127 CharitableCampaignBuilder.setCampaignNotSaved();
128
129 },
130
131 /**
132 * Disable drag & drop.
133 *
134 * @since 1.7.1
135 * @since 1.8.0 Moved from admin-builder.js.
136 */
137 disableDragAndDrop: function() {
138 wpchar.debug('disableDragAndDrop'), 'drag-fields';
139 el.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'disable' );
140 el.$sortableFieldsWrap.sortable( 'disable' );
141 el.$sortableFieldsWrap.find( '.charitable-layout-section.ui-sortable' ).sortable( 'disable' ); // was layout-column
142 },
143
144 /**
145 * Enable drag & drop.
146 *
147 * @since 1.7.1
148 * @since 1.8.0 Moved from admin-builder.js.
149 */
150 enableDragAndDrop: function() {
151 wpchar.debug('enableDragAndDrop'), 'drag-fields';
152 el.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'enable' );
153 el.$sortableFieldsWrap.sortable( 'enable' );
154 el.$sortableFieldsWrap.find( '.charitable-layout-section.ui-sortable' ).sortable( 'enable' ); // was layout-column
155 },
156
157 /**
158 * Show popup in case if field is not draggable, and cancel moving.
159 *
160 * @since 1.7.5
161 * @since 1.8.0 Moved from admin-builder.js.
162 *
163 * @param {jQuery} $field A field or list of fields.
164 * @param {boolean} showPopUp Whether the pop-up should be displayed on dragging attempt.
165 */
166 fieldDragDisable: function( $field, showPopUp = true ) {
167
168 if ( $field.hasClass( 'ui-draggable-disabled' ) ) {
169 $field.draggable( 'enable' );
170
171 return;
172 }
173
174 let startTopPosition;
175
176 $field.draggable( {
177 revert: true,
178 axis: 'y',
179 delay: 100,
180 opacity: 0.75,
181 cursor: 'move',
182 start: function( event, ui ) {
183
184 startTopPosition = ui.position.top;
185 },
186 drag: function( event, ui ) {
187
188 if ( Math.abs( ui.position.top ) - Math.abs( startTopPosition ) > 15 ) {
189
190 if ( showPopUp ) {
191 app.youCantReorderFieldPopup();
192 }
193
194 return false;
195 }
196 }
197 } );
198 },
199
200 /**
201 * Allow field dragging.
202 *
203 * @since 1.7.5
204 * @since 1.8.0 Moved from admin-builder.js.
205 *
206 * @param {jQuery} $field A field or list of fields.
207 */
208 fieldDragEnable: function( $field ) {
209
210 if ( $field.hasClass( 'ui-draggable' ) ) {
211 return;
212 }
213
214 wpchar.debug('fieldDragEnable'), 'drag-fields';
215
216 $field.draggable( 'disable' );
217 },
218
219 /**
220 * Show the error message in the popup that you cannot reorder the field.
221 *
222 * @since 1.7.1
223 * @since 1.8.0 Moved from admin-builder.js.
224 */
225 youCantReorderFieldPopup: function() {
226
227 $.confirm( {
228 title: charitable_builder.heads_up,
229 content: charitable_builder.field_cannot_be_reordered,
230 icon: 'fa fa-exclamation-circle',
231 type: 'red',
232 buttons: {
233 confirm: {
234 text: charitable_builder.ok,
235 btnClass: 'btn-confirm',
236 keys: [ 'enter' ]
237 },
238 },
239 } );
240 },
241
242 /**
243 * Event handler for `charitableFieldDragToggle` event.
244 *
245 * @since 1.8.0
246 *
247 * @param {object} e Event object.
248 * @param {numeric} id Field ID.
249 */
250 fieldDragToggleEvent: function( e, id ) {
251
252 const $field = $( `#charitable-field-${id}` );
253
254 if (
255 $field.hasClass( 'charitable-field-not-draggable' ) ||
256 $field.hasClass( 'charitable-field-stick' )
257 ) {
258 app.fieldDragDisable( $field );
259 wpchar.debug('fieldDragToggleEvent fieldDragDisable'), 'drag-fields';
260 return;
261 }
262
263 app.fieldDragEnable( $field );
264
265 CharitableCampaignBuilder.setCampaignNotSaved();
266
267 },
268
269 /**
270 * Initialize sortable fields in the builder form preview area.
271 *
272 * @since 1.8.0
273 */
274 initSortableFields: function() {
275
276 wpchar.debug( 'initSortableFields' , 'drag-fields' );
277 wpchar.debug( el.$sortableFieldsWrap , 'drag-fields' );
278 wpchar.debug( el.$sortableTabsWrap , 'drag-fields' );
279
280 // app.initSortableContainer( el.$sortableFieldsWrap );
281
282 app.initSortableContainer( el.$sortableTabsWrap );
283
284 el.$builder.find( '.charitable-panel-fields .charitable-field-wrap' ).each( function() {
285 app.initSortableContainer( $( this ) );
286 } );
287
288 //app.fieldDragDisable( $( '.charitable-field-not-draggable, .charitable-field-stick' ) );
289 app.initDraggableFields();
290 },
291
292 /**
293 * Initialize sortable container with fields.
294 *
295 * @since 1.8.0
296 *
297 * @param {jQuery} $sortable Container to make sortable.
298 */
299 initSortableContainer: function( $sortable ) { // eslint-disable-line max-lines-per-function
300
301 wpchar.debug('initSortableContainer'), 'drag-fields';
302
303 let fieldId,
304 fieldType,
305 isNewField;
306
307 $sortable.sortable( {
308 items: '> .charitable-field:not(.charitable-field-stick):not(.no-fields-preview)',
309 connectWith: '.charitable-field-wrap, .charitable-tab-wrap', // , .charitable-layout-column was in here
310 delay: 100,
311 opacity: 0.75,
312 cursor: 'move',
313 cancel: '.charitable-field-not-draggable',
314 placeholder: 'charitable-field-drag-placeholder',
315 appendTo: '.charitable-design-wrap',
316 zindex: 10000,
317 tolerance: 'pointer',
318 distance: 1,
319 start: function( e, ui ) {
320
321 wpchar.debug( 'vars' , 'drag-fields' );
322 wpchar.debug( vars , 'drag-fields' );
323 wpchar.debug('start sortable via drag-fields.js'), 'drag-fields';
324 wpchar.debug( 'ui' , 'drag-fields' );
325 wpchar.debug( ui , 'drag-fields' );
326 wpchar.debug( 'ui.item' , 'drag-fields' );
327 wpchar.debug( ui.item , 'drag-fields' );
328
329 // Refuse to drag fields out of a locked row. Pairs with the over:/update: guards
330 // that refuse drops INTO locked rows -- contents of a locked row must stay put.
331 if ( ui.item.closest( '[data-row-locked="1"]' ).length ) {
332 $( this ).sortable( 'cancel' );
333 return false;
334 }
335
336 fieldId = ui.item.data( 'field-id' );
337 fieldType = ui.item.data( 'field-type' ) || vars.fieldType;
338 // fieldType = $field.data( 'field-type' )
339
340 if ( ! isNewField ) {
341 vars.section = ui.item.closest('.charitable-field-section');
342 } else {
343 vars.section = false;
344 }
345
346 isNewField = typeof fieldId === 'undefined';
347 wpchar.debug(' fieldId: ' + fieldId + ' - fieldType: ' + fieldType + ' - newField: ' + isNewField + ' - section: ' + vars.section), 'drag-fields';
348 // $fieldOption = $( '#charitable-field-option-' + fieldId );
349
350 vars.fieldReceived = false;
351 vars.fieldRejected = false;
352 vars.$sortableStart = $sortable;
353 vars.fieldType = fieldType;
354 vars.startPosition = ui.item.first().index();
355
356 $(this).attr('data-previndex', ui.item.index());
357
358
359 },
360 beforeStop: function( e, ui ) { // eslint-disable-line
361
362 wpchar.debug('beforeStop ==== sortable via drag-fields.js'), 'drag-fields';
363
364 },
365 stop: function( e, ui ) {
366
367 wpchar.debug('stop ==== sortable via drag-fields.js'), 'drag-fields';
368
369 wpchar.debug ( ui , 'drag-fields' );
370
371 const $field = ui.item.first();
372
373 ui.placeholder.removeClass( 'charitable-field-drag-not-allowed' );
374 $field.removeClass( 'charitable-field-drag-not-allowed' );
375
376 $field
377 .removeClass( 'charitable-field-dragging' )
378 .removeClass( 'charitable-field-drag-over' )
379 .attr( 'style', '' );
380
381 el.$builder.trigger( 'charitableFieldMove', ui );
382
383
384 },
385 over: function( e, ui ) { // eslint-disable-line complexity
386
387 wpchar.debug('over ==== sortable via drag-fields.js'), 'drag-fields';
388
389 const $field = ui.item.first(),
390 $target = $(e.target),
391 $placeholder = $target.find('.charitable-field-drag-placeholder'),
392 isColumn = $target.hasClass('charitable-layout-column'),
393 isRowLocked = $target.closest('[data-row-locked="1"]').length > 0,
394 targetClass = isColumn ? ' charitable-field-drag-to-column' : '',
395 helper = {
396 width: $target.outerWidth(),
397 height: $field.outerHeight()
398 };
399
400
401 fieldId = $field.data( 'field-id' );
402 fieldType = $field.data( 'field-type' ) || vars.fieldType;
403 isNewField = typeof fieldId === 'undefined';
404
405 // Adjust helper size according to the placeholder size.
406 $field
407 .addClass( 'charitable-field-dragging' + targetClass )
408 .css( {
409 'width': isColumn ? helper.width - 5 : helper.width,
410 'height': 'auto',
411 } );
412
413 // Adjust placeholder height according to the height of the helper.
414 $placeholder
415 .removeClass( 'charitable-field-drag-not-allowed charitable-field-drag-locked-row' )
416 .css( {
417 'height': isNewField ? helper.height + 18 : helper.height,
418 } );
419
420 // Drop to this place is not allowed.
421 if (
422 ( ! fieldLayout.isFieldAllowedInColum( fieldType ) && isColumn ) ||
423 isRowLocked
424 ) {
425 $placeholder.addClass( 'charitable-field-drag-not-allowed' );
426 $field.addClass( 'charitable-field-drag-not-allowed' );
427 }
428
429 if ( isRowLocked ) {
430 $placeholder.addClass( 'charitable-field-drag-locked-row' );
431 }
432
433 // Skip if it is the existing field.
434 if ( ! isNewField ) {
435 return;
436 }
437
438 $field
439 .addClass( 'charitable-field-drag-over' )
440 .removeClass( 'charitable-field-drag-out' );
441
442
443 },
444 out: function( e, ui ) { // eslint-disable-line
445
446 wpchar.debug('out ==== sortable via drag-fields.js'), 'drag-fields';
447
448
449 },
450 receive: function( e, ui ) { // eslint-disable-line complexity
451
452 wpchar.debug('receive ==== sortable via drag-fields.js'), 'drag-fields';
453
454 wpchar.debug ( ui , 'drag-fields' );
455 wpchar.debug ( ui.helper , 'drag-fields' );
456 wpchar.debug ( ui.item , 'drag-fields' );
457 wpchar.debug ( ui.position , 'drag-fields' );
458 wpchar.debug ( ui.originalPosition , 'drag-fields' );
459 wpchar.debug ( ui.sender , 'drag-fields' );
460 wpchar.debug ( ui.placeholder , 'drag-fields' );
461
462
463
464 },
465 update: function( e, ui ) { // eslint-disable-line
466
467 wpchar.debug('update ==== sortable via drag-fields.js'), 'drag-fields';
468
469 var newIndex = ui.item.index();
470 var oldIndex = $(this).attr('data-previndex');
471 var element_id = ui.item.attr('class');
472
473 $(this).attr('data-current-index', ui.item.index());
474 wpchar.debug ( $( this ) );
475
476
477 $(this).removeAttr('data-previndex');
478
479 // decalare a bunch of variables.
480
481 const $field = $( ui.helper || ui.item );
482
483 var area = $sortable.hasClass('charitable-field-wrap') ? 'fields' : 'tabs',
484 column_id = 'fields' === area ? parseInt($field.closest('.charitable-field-column').data('column-id')) : false,
485 section_id = 'fields' === area ? parseInt($field.closest('.charitable-field-section').data('section-id')) : false,
486 tab_id = 'tabs' === area ? parseInt($field.closest('.tab_content_item').data('tab-id')) : false,
487 fieldId = $field.data('field-id'),
488 fieldType = $field.data('field-type') || vars.fieldType;
489
490 const isNewField = typeof fieldId === 'undefined',
491 isColumn = $sortable.hasClass('charitable-layout-column'),
492 numfieldsDonateButton = el.$preview.find('.charitable-field.charitable-field-donate-button').length,
493 numfieldsDonationForm = el.$preview.find('.charitable-field.charitable-field-donation-form').length;
494
495 // Refuse drops into rows marked as locked (e.g. the Beacon hero row).
496 if ( $field.closest( '[data-row-locked="1"]' ).length ) {
497 $( this ).sortable( 'cancel' );
498 if ( isNewField ) {
499 $field.remove();
500 }
501 el.$builder.find( '.charitable-add-fields .charitable-add-fields-button' ).prop( 'disabled', false );
502 return;
503 }
504
505 wpchar.debug( $sortable );
506 wpchar.debug( $sortable.data( 'ui-sortable' ) );
507 wpchar.debug( $sortable.data( 'ui-sortable' ).currentItem );
508
509 var currentIndex = $(this).attr('data-current-index');
510
511 wpchar.debug ( currentIndex, 'currentIndex' );
512 wpchar.debug ( $( this ) );
513 let position = typeof currentIndex === 'undefined' ? -1 : currentIndex;
514 // let position = typeof $sortable.data( 'ui-sortable' ).currentItem === 'undefined' ? -1 : $sortable.data( 'ui-sortable' ).currentItem.index();
515
516 // disable any add field buttons until this is finished.
517 el.$builder.find( '.charitable-add-fields .charitable-add-fields-button' ).prop( 'disabled', true );
518
519 // you shouldn't try to add a donation form if a donation button is already added.
520 if ( fieldType === 'donation-form' ) {
521
522 if ( numfieldsDonateButton > 0 ) {
523
524 $('.ui-draggable-dragging').css('opacity', '0');
525
526 $.confirm( {
527 title: charitable_builder.heads_up,
528 content: charitable_builder.donation_form_donation_button,
529 icon: 'fa fa-exclamation-circle',
530 type: 'red',
531 buttons: {
532 confirm: {
533 text: charitable_builder.remove_donation_button,
534 btnClass: 'btn-confirm',
535 keys: [ 'enter' ],
536 action: function() {
537 el.$preview.find('.charitable-field.charitable-field-donate-button').each( function() {
538 var fieldDeleteId = $( this ).data('field-id');
539 if ( parseInt( fieldDeleteId ) > 0 ) {
540 CharitableCampaignBuilder.fieldDelete( fieldDeleteId, false );
541 }
542 } );
543 $('.ui-draggable-dragging').css('opacity', '1.0');
544 app.addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable )
545 },
546 },
547 cancel: {
548 text: charitable_builder.cancel,
549 keys: [ 'esc' ],
550 action: function() {
551 el.$builder.find( '.charitable-add-fields .charitable-add-fields-button' ).prop( 'disabled', false );
552 $field.remove();
553 return;
554 },
555 },
556 },
557 } );
558
559 } else if ( numfieldsDonationForm > 1 ) {
560
561 $('.ui-draggable-dragging').css('opacity', '0');
562
563 $.confirm( {
564 title: charitable_builder.heads_up,
565 content: charitable_builder.only_one_donation_form,
566 icon: 'fa fa-exclamation-circle',
567 type: 'red',
568 buttons: {
569 confirm: {
570 text: charitable_builder.remove_donation_form,
571 btnClass: 'btn-confirm',
572 keys: [ 'enter' ],
573 action: function() {
574 el.$preview.find('.charitable-field.charitable-field-donation-form').each( function() {
575 var fieldDeleteId = $( this ).data('field-id');
576 if ( parseInt( fieldDeleteId ) > 0 ) {
577 CharitableCampaignBuilder.fieldDelete( fieldDeleteId, false );
578 }
579 } );
580 $('.ui-draggable-dragging').css('opacity', '1.0');
581 app.addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable )
582 },
583 },
584 cancel: {
585 text: charitable_builder.cancel,
586 keys: [ 'esc' ],
587 action: function() {
588 el.$builder.find( '.charitable-add-fields .charitable-add-fields-button' ).prop( 'disabled', false );
589 $field.remove();
590 return;
591 },
592 },
593 },
594 } );
595
596 } else {
597
598 app.addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable, vars.section )
599
600 }
601
602 } else if ( fieldType === 'donate-button' && numfieldsDonationForm > 0 ) {
603
604 $('.ui-draggable-dragging').css('opacity', '0');
605
606 $.confirm( {
607 title: charitable_builder.heads_up,
608 content: charitable_builder.donation_button_donation_form,
609 icon: 'fa fa-exclamation-circle',
610 type: 'red',
611 buttons: {
612 confirm: {
613 text: charitable_builder.remove_donation_form,
614 btnClass: 'btn-confirm',
615 keys: [ 'enter' ],
616 action: function() {
617 el.$preview.find('.charitable-field.charitable-field-donation-form').each( function() {
618 var fieldDeleteId = $( this ).data('field-id');
619 if ( parseInt( fieldDeleteId ) > 0 ) {
620 CharitableCampaignBuilder.fieldDelete( fieldDeleteId, false );
621 }
622 } );
623 $('.ui-draggable-dragging').css('opacity', '1.0');
624 app.addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable, vars.section )
625 },
626 },
627 cancel: {
628 text: charitable_builder.cancel,
629 keys: [ 'esc' ],
630 action: function() {
631 el.$builder.find( '.charitable-add-fields .charitable-add-fields-button' ).prop( 'disabled', false );
632 $field.remove();
633 return;
634 },
635 },
636 },
637 } );
638
639 } else {
640
641 app.addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable, vars.section );
642
643 }
644
645
646 },
647 change: function( e, ui ) { // eslint-disable-line
648
649 wpchar.debug('change ==== sortable via drag-fields.js'), 'drag-fields';
650
651
652 },
653 sort: function( e, ui ) { // eslint-disable-line
654
655 wpchar.debug('sort ==== sortable via drag-fields.js'), 'drag-fields';
656 CharitableCampaignBuilder.setCampaignNotSaved();
657
658
659 },
660 } );
661 },
662
663 addFieldAfterDrag( $field, isNewField, isColumn, position, area, column_id, tab_id, section_id, fieldId, fieldType, $sortable, $section ) {
664
665 if ( isNewField ) {
666
667 // add the spinning loader icon to the field (because this requires an ajax call and there might be a delay)
668 $field
669 .addClass( 'charitable-field-drag-over charitable-field-drag-pending' )
670 .removeClass( 'charitable-field-drag-out' )
671 .append( CharitableCampaignBuilder.settings.spinnerInline )
672 .css( 'width', '100%' );
673
674 wpchar.debug( 'addFieldAfterDrag' );
675 wpchar.debug( isColumn );
676 wpchar.debug( position );
677
678 CharitableCampaignBuilder.fieldAdd(
679 vars.fieldType,
680 {
681 position: isColumn ? position - 1 : position,
682 placeholder: $field,
683 $sortable: $sortable,
684 column_id: column_id,
685 tab_id: tab_id,
686 section_id: section_id,
687 area: area,
688 section: false,
689 }
690 );
691
692 } else {
693
694 CharitableCampaignBuilder.fieldMove(
695 vars.fieldType,
696 {
697 // position: isColumn ? position - 1 : position,
698 field: $field,
699 fieldId: fieldId,
700 $sortable: $sortable,
701 column_id: column_id,
702 tab_id: tab_id,
703 section_id: section_id,
704 area: area,
705 section: $section,
706 }
707 );
708
709 }
710
711 CharitableCampaignBuilder.setCampaignNotSaved();
712
713 },
714
715 getChildIndex(childDiv) {
716 // Find the parent div of the given child div
717 var parentDiv = childDiv.parent();
718
719 // Find all the child divs within the parent div
720 var childDivs = parentDiv.children();
721
722 // Loop through the child divs to find the index of the given child div
723 for (var i = 0; i < childDivs.length; i++) {
724 if (childDivs[i] === childDiv[0]) {
725 // Return the index (1-based) if found
726 return i + 1;
727 }
728 }
729
730 // If the given child div is not found, return -1
731 return -1;
732 },
733
734 /**
735 * Initialize draggable fields buttons.
736 *
737 * @since 1.8.0
738 */
739 initDraggableFields: function() {
740
741 el.$addFieldsButtons.draggable( {
742 connectToSortable: '.charitable-field-wrap, .charitable-tab-wrap', // .charitable-layout-column was in there
743 delay: 200,
744 cancel: false,
745 scroll: false,
746 opacity: 0.75,
747 appendTo: '.charitable-design-wrap',
748 zindex: 10000,
749 helper: function() {
750
751 let $this = $( this ),
752 $el = $( '<div class="charitable-field-drag-out charitable-field-drag">' );
753
754 vars.fieldType = $this.data( 'field-type' );
755
756
757
758 wpchar.debug ('initDraggableFields start '), 'drag-fields';
759 wpchar.debug( vars , 'drag-fields' );
760 wpchar.debug( $el.html( $this.html(), 'drag-fields' ) );
761 wpchar.debug ('initDraggableFields end'), 'drag-fields';
762
763 return $el.html( $this.html() );
764 },
765
766 start: function( e, ui ) {
767
768 let event = CharitableUtils.triggerEvent(
769 el.$builder,
770 'charitableFieldAddDragStart',
771 [ vars.fieldType, ui ]
772 );
773
774 // wpchar.debug('event'), 'drag-fields';
775 // wpchar.debug(event), 'drag-fields';
776 // wpchar.debug(event.isDefaultPrevented), 'drag-fields';
777
778 // Allow callbacks on `charitableFieldAddDragStart` to cancel dragging the field
779 // by triggering `event.preventDefault()`.
780 if ( event.isDefaultPrevented() ) {
781 return false;
782 }
783 },
784 } );
785 },
786
787 /**
788 * Revert moving the field to the column.
789 *
790 * @since 1.8.0
791 *
792 * @param {jQuery} $field Field object.
793 */
794 revertMoveFieldToColumn: function( $field ) {
795
796 const isNewField = $field.data( 'field-id' ) === undefined;
797
798 if ( isNewField ) {
799
800 // Remove the field.
801 $field.remove();
802
803 return;
804 }
805
806 // Restore existing field on the previous position.
807 $field = $field.detach();
808
809 const $fieldInStartPosition = vars.$sortableStart
810 .find( '> .charitable-field' )
811 .eq( vars.startPosition );
812
813 $field
814 .removeClass( 'charitable-field-dragging' )
815 .removeClass( 'charitable-field-drag-over' )
816 .attr( 'style', '' );
817
818 if ( $fieldInStartPosition.length ) {
819 $fieldInStartPosition.before( $field );
820
821 return;
822 }
823
824 vars.$sortableStart.append( $field );
825 },
826 };
827
828 /**
829 * Layout field functions holder.
830 *
831 * @since 1.8.0
832 *
833 * @type {object}
834 */
835 fieldLayout = {
836
837 /**
838 * Position field in the column inside the Layout Field.
839 *
840 * @since 1.8.0
841 *
842 * @param {number} fieldId Field Id.
843 * @param {number} position The new position of the field inside the column.
844 * @param {jQuery} $sortable Sortable column container.
845 **/
846 positionFieldInColumn: function( fieldId, position, $sortable ) {
847
848 if ( ! Charitable.Admin.Builder.FieldLayout ) {
849 return;
850 }
851
852 Charitable.Admin.Builder.FieldLayout.positionFieldInColumn( fieldId, position, $sortable );
853 },
854
855 /**
856 * Receive field to column inside the Layout Field.
857 *
858 * @since 1.8.0
859 *
860 * @param {number} fieldId Field Id.
861 * @param {number} position Field position inside the column.
862 * @param {jQuery} $sortable Sortable column container.
863 **/
864 receiveFieldToColumn: function( fieldId, position, $sortable ) {
865
866 if ( ! Charitable.Admin.Builder.FieldLayout ) {
867 return;
868 }
869
870 Charitable.Admin.Builder.FieldLayout.receiveFieldToColumn( fieldId, position, $sortable );
871 },
872
873 /**
874 * Update field options according to the position of the field.
875 * Event `charitableFieldOptionTabToggle` handler.
876 *
877 * @since 1.8.0
878 *
879 * @param {Event} e Event.
880 * @param {int} fieldId Field id.
881 */
882 fieldOptionsUpdate: function( e, fieldId ) {
883
884 if ( ! Charitable.Admin.Builder.FieldLayout ) {
885 return;
886 }
887
888 Charitable.Admin.Builder.FieldLayout.fieldOptionsUpdate( e, fieldId );
889 },
890
891 /**
892 * Reorder fields options of the fields in columns.
893 * It is not critical, but it's better to keep some order in the `fields` data array.
894 *
895 * @since 1.8.0
896 *
897 * @param {jQuery} $layoutField Layout field object.
898 */
899 reorderLayoutFieldsOptions: function( $layoutField ) {
900
901 if ( ! Charitable.Admin.Builder.FieldLayout ) {
902 return;
903 }
904
905 Charitable.Admin.Builder.FieldLayout.reorderLayoutFieldsOptions( $layoutField );
906 },
907
908 /**
909 * Whether the field type is allowed to be in column.
910 *
911 * @since 1.8.0
912 *
913 * @param {string} fieldType Field ty to check.
914 *
915 * @returns {boolean} True if allowed.
916 */
917 isFieldAllowedInColum: function( fieldType ) {
918
919 if ( ! Charitable.Admin.Builder.FieldLayout ) {
920 return true;
921 }
922
923 return Charitable.Admin.Builder.FieldLayout.isFieldAllowedInColum( fieldType );
924 },
925 };
926
927 // Provide access to public functions/properties.
928 return app;
929
930 }( document, window, jQuery ) ); // eslint-disable-line
931
932 // Initialize.
933 Charitable.Admin.Builder.DragFields.init();
934