PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 1.2.3
JetFormBuilder — Dynamic Blocks Form Builder v1.2.3
3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / assets / js / frontend-forms.js
jetformbuilder / assets / js Last commit date
action-localize-helper.js 5 years ago admin.js 5 years ago editor.js 5 years ago file-upload.js 5 years ago form-block.js 5 years ago frontend-forms.js 5 years ago package.js 5 years ago
frontend-forms.js
1439 lines
1 ( function( $ ) {
2
3 'use strict';
4
5 const JetFormBuilderDev = {
6 isActive: function() {
7 return Boolean( window.JetFormBuilderSettings.devmode );
8 },
9 log: function( label = '', params = {} ) {
10 if ( ! this.isActive() || ! params ) {
11 return;
12 }
13 console.group( label );
14 for ( const key in params ) {
15 console.log( `${ key }: ${ params[ key ] }` );
16 }
17 console.groupEnd();
18 },
19 hardLog: function( label = '', params = {} ) {
20 this.log( label, params );
21 if ( this.isActive() ) {
22 debugger;
23 }
24 },
25 }
26
27 window.JetFormBuilderMain = {
28
29 filters: ( function() {
30
31 var callbacks = {};
32
33 return {
34
35 addFilter: function( name, callback ) {
36
37 if ( ! callbacks.hasOwnProperty( name ) ) {
38 callbacks[ name ] = [];
39 }
40
41 callbacks[ name ].push( callback );
42
43 },
44
45 applyFilters: function( name, value, args ) {
46
47 if ( ! callbacks.hasOwnProperty( name ) ) {
48 return value;
49 }
50
51 if ( args === undefined ) {
52 args = [];
53 }
54
55 var container = callbacks[ name ];
56 var cbLen = container.length;
57
58 for ( var i = 0; i < cbLen; i++ ) {
59 if ( typeof container[ i ] === 'function' ) {
60 value = container[ i ]( value, args );
61 }
62 }
63
64 return value;
65 },
66
67 };
68
69 } )(),
70
71 };
72
73 $.fn.jetFormBuilderConditional = function( options ) {
74
75 var settings = $.extend( {
76 hideJS: true,
77 }, options );
78
79 var checkValue = function( $listenTo, listenFor, operator ) {
80
81 var val = '';
82 var checkResult = false;
83 var controlType = 'plain';
84
85 operator = operator || 'equal';
86
87 if ( $listenTo.is( 'input[type=checkbox]' ) ) {
88 controlType = 'checkbox';
89 } else if ( $listenTo.is( 'input[type=radio]' ) ) {
90 controlType = 'radio';
91 }
92
93 if ( 'checkbox' === controlType ) {
94 val = [];
95 }
96
97 if ( 'plain' === controlType ) {
98 val = $listenTo.val();
99 } else {
100
101 $listenTo.each( function() {
102
103 var $control = $( this );
104
105 if ( $control.is( ':checked' ) ) {
106 if ( 'checkbox' === controlType ) {
107 val.push( $control.val() );
108 } else {
109 val = $control.val();
110 }
111 }
112
113 } );
114 }
115
116 JetFormBuilderDev.log( 'Conditional', {
117 val,
118 listenFor,
119 operator,
120 } );
121
122 switch ( operator ) {
123 case 'equal':
124 if ( val && val.constructor === Array ) {
125 checkResult = false;
126 } else {
127 checkResult = ( val == listenFor );
128 }
129 break;
130
131 case 'greater':
132 if ( val && val.constructor === Array ) {
133 checkResult = false;
134 } else {
135 checkResult = ( parseFloat( val ) > parseFloat( listenFor ) );
136 }
137 break;
138
139 case 'less':
140 if ( val && val.constructor === Array ) {
141 checkResult = false;
142 } else {
143 checkResult = ( parseFloat( val ) < parseFloat( listenFor ) );
144 }
145 break;
146
147 case 'between':
148
149 if ( val && val.constructor === Array ) {
150 checkResult = false;
151 } else {
152 if ( 2 <= listenFor.length ) {
153 let from = parseFloat( listenFor[ 0 ] );
154 let to = parseFloat( listenFor[ 1 ] );
155 val = parseFloat( val );
156 checkResult = ( from <= val && val <= to );
157 } else {
158 checkResult = false;
159 }
160 }
161
162 break;
163
164 case 'one_of':
165 if ( val && val.constructor === Array ) {
166 checkResult = val.includes( listenFor );
167
168 } else if ( ! val ) {
169 checkResult = false;
170 } else {
171 if ( listenFor.length ) {
172 checkResult = 0 <= listenFor.indexOf( val );
173 } else {
174 checkResult = false;
175 }
176 }
177
178 break;
179
180 case 'contain':
181 if ( val && val.constructor === Array ) {
182
183 var intersect = val.filter( function( n ) {
184 return n.indexOf( listenFor ) !== -1;
185 } );
186
187 checkResult = 0 < intersect.length;
188
189 } else if ( ! val ) {
190 checkResult = false;
191 } else {
192 checkResult = 0 <= val.indexOf( listenFor );
193 }
194
195 break;
196 }
197
198 return checkResult;
199 };
200
201 var checkVisibilityCond = function( listenTo, listenFor, $section, operator, type ) {
202
203 var checked = $section.data( 'checked' );
204 var $listenTo = $( listenTo );
205 var checkResult = checkValue( $listenTo, listenFor, operator );
206
207 type = type || 'show';
208
209 if ( ! checked ) {
210 checked = {};
211 }
212
213 if ( 'show' === type ) {
214 checked[ listenTo ] = checkResult;
215 } else {
216 checked[ listenTo ] = ! checkResult;
217 }
218
219 $section.data( 'checked', checked );
220
221 };
222
223 var checkSetValueCond = function( listenTo, listenFor, $section, operator, value, type ) {
224
225 var currentVal = $section.data( 'result_' + type );
226 var $listenTo = $( listenTo );
227 var checkResult = checkValue( $listenTo, listenFor, operator );
228
229 if ( checkResult ) {
230 currentVal = value;
231 }
232
233 $section.data( 'result_' + type, currentVal );
234
235 };
236
237 var setValue = function( $section ) {
238
239 var setVal = false;
240 var setCalcVal = false;
241 var $field;
242 var triggered = false;
243
244 if ( $section.data( 'result_set_value' ) ) {
245 setVal = $section.data( 'result_set_value' );
246 }
247
248 if ( $section.data( 'result_set_calculated_value' ) ) {
249 setCalcVal = $section.data( 'result_set_calculated_value' );
250 }
251
252 if ( ! setVal && ! setCalcVal ) {
253 return;
254 }
255
256 $field = $section.find( '.jet-form-builder__field' );
257
258 if ( ! $field.length ) {
259 return;
260 }
261
262 if ( $field.is( 'select' ) ) {
263
264 $field.find( ':selected' ).removeAttr( 'selected' );
265
266 if ( setVal ) {
267 $field.find( 'option[value="' + setVal + '"]' ).attr( 'selected', 'selected' ).trigger( 'change.JetFormBuilderMain' );
268 triggered = true;
269 }
270
271 if ( setCalcVal ) {
272 $field.find( 'option[data-calculate="' + setCalcVal + '"]' ).attr( 'selected', 'selected' );
273 if ( ! triggered ) {
274 $field.trigger( 'change.JetFormBuilderMain' );
275 triggered = true;
276 }
277 }
278
279 } else if ( $field.is( ':not( input[type=checkbox], input[type=radio] )' ) ) {
280
281 if ( setVal ) {
282 $field.val( setVal ).trigger( 'change.JetFormBuilderMain' );
283 triggered = true;
284 }
285
286 if ( setCalcVal ) {
287 $field.data( 'calculate', setCalcVal );
288 if ( ! triggered ) {
289 $field.trigger( 'change.JetFormBuilderMain' );
290 triggered = true;
291 }
292 }
293
294 } else {
295
296 $field.each( function() {
297
298 var $this = $( this );
299
300 if ( $this.is( ':checked' ) ) {
301 $this.removeAttr( 'checked' );
302 }
303
304 if ( setVal && setVal == $this.val() ) {
305 $this.attr( 'checked', 'checked' ).trigger( 'change.JetFormBuilderMain' );
306 triggered = true;
307 }
308
309 if ( setCalcVal && setCalcVal == $this.data( 'calculate' ) ) {
310 $this.attr( 'checked', 'checked' );
311 if ( ! triggered ) {
312 $this.trigger( 'change.JetFormBuilderMain' );
313 triggered = true;
314 }
315 }
316
317 } );
318
319 }
320
321 };
322
323 var setVisibility = function( $section ) {
324
325 var checked = $section.data( 'checked' );
326 var $row = $section.closest( '.jet-form-builder-row' );
327 var res = true;
328
329 if ( ! checked ) {
330 return;
331 }
332
333 for ( var check in checked ) {
334 if ( ! checked[ check ] ) {
335 res = false;
336 }
337 }
338
339 if ( res ) {
340
341 $section.show();
342 $row.show();
343
344 $section.find( '*[data-initial-type]' ).each( function() {
345 var $this = $( this );
346
347 $this.attr( 'type', $this.data( 'initial-type' ) );
348 } );
349
350 $section.find( 'select option[data-is-hidden="1"]' ).remove();
351
352 $section
353 .find( '*[data-required="1"]' )
354 .val( '' )
355 .attr( 'required', true );
356
357 } else {
358
359 $section.hide();
360
361 $section.find( '*[type="date"],*[type="time"],*[type="email"],*[type="url"]' ).each( function() {
362 var $this = $( this ),
363 type = $this.attr( 'type' );
364
365 $this.attr( 'data-initial-type', type );
366 $this.attr( 'type', 'text' );
367 } );
368
369 var $select = $section.find( 'select' );
370 var val = 'is-hidden';
371
372 if ( $select.length ) {
373
374 var defaultVal = $select.data( 'default-val' );
375
376 if ( defaultVal || 0 === defaultVal ) {
377 val = defaultVal;
378 }
379
380 $select.append( '<option value="' + val + '" data-is-hidden="1"></option>' );
381
382 }
383
384 $section.find( '*[required="required"]' )
385 .val( val )
386 .removeAttr( 'required' )
387 .attr( 'data-required', 1 );
388
389 var $hiddenItems = $row.find( '>*' ).filter( function() {
390 return $( this ).css( 'display' ) === 'none';
391 } );
392
393 if ( $row.find( '>*' ).length === $hiddenItems.length ) {
394 $row.hide();
395 }
396 }
397
398 };
399
400 return this.each( function() {
401
402 var $section = $( this );
403 var conditions = $section.data( 'conditional' );
404
405 if ( ! conditions || ! conditions.length ) {
406 return;
407 }
408
409 for ( var i = 0; i < conditions.length; i++ ) {
410
411 let condition = conditions[ i ];
412
413 if ( ! condition.field ) {
414 continue;
415 }
416
417 let listenTo = '[data-field-name=' + condition.field + ']';
418 let listenFor = condition.value;
419 let operator = condition.operator;
420 let type = condition.type;
421 let valueToSet = condition.set_value;
422
423 //Set up event listener
424 $( document ).on( 'change.JetFormBuilderMain', listenTo, function() {
425
426 if ( 'show' === type || 'hide' === type ) {
427 checkVisibilityCond( listenTo, listenFor, $section, operator, type );
428 } else {
429 checkSetValueCond( listenTo, listenFor, $section, operator, valueToSet, type );
430 }
431
432 setValue( $section );
433 setVisibility( $section );
434
435 } );
436
437 //If setting was chosen, hide everything first...
438 if ( settings.hideJS && ( 'show' === type || 'hide' === type ) ) {
439 $section.hide();
440 }
441
442 //Show based on current value on page load
443 if ( 'show' === type || 'hide' === type ) {
444 checkVisibilityCond( listenTo, listenFor, $section, operator, type );
445 } else {
446 checkSetValueCond( listenTo, listenFor, $section, operator, valueToSet, type );
447 }
448
449 }
450
451 setValue( $section );
452 setVisibility( $section );
453 } );
454 };
455
456 var JetFormBuilder = {
457
458 initialized: false,
459 pages: {},
460 calcFields: {},
461 repeaterCalcFields: {},
462 childrenCalcFields: {},
463 currentFieldWithError: {
464 length: 0,
465 },
466
467 initCommon: function() {
468 if ( JetFormBuilder.initialized ) {
469 return;
470 }
471 $( '.jet-form-builder__form-wrapper' ).each( function( index, value ) {
472 JetFormBuilder.widgetBookingForm( $( value ) );
473 } );
474 JetFormBuilder.initialized = true;
475 },
476
477 initElementor: function() {
478 if ( JetFormBuilder.initialized ) {
479 return;
480 }
481 const widgets = {
482 'jet-engine-booking-form.default': JetFormBuilder.widgetBookingForm,
483 'jet-form-builder-form.default': JetFormBuilder.widgetBookingForm,
484 };
485
486 $.each( widgets, function( widget, callback ) {
487 window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback );
488 } );
489 JetFormBuilder.initialized = true;
490 },
491
492 addHandlersInit: function() {
493 var self = JetFormBuilder;
494
495 $( document )
496 .on( 'click.JetFormBuilderMain', '.jet-form-builder__submit.submit-type-ajax', self.ajaxSubmitForm )
497 .on( 'submit.JetFormBuilderMain', 'form.jet-form-builder.submit-type-reload', self.reloadSubmitForm )
498 .on( 'click.JetFormBuilderMain', '.jet-form-builder__next-page', self.nextFormPage )
499 .on( 'click.JetFormBuilderMain', '.jet-form-builder__prev-page', self.prevFormPage )
500 .on( 'focus.JetFormBuilderMain', '.jet-form-builder__field', self.clearFieldErrors )
501 .on( 'click.JetFormBuilderMain', '.jet-form-builder__field-template', self.simLabelClick )
502 .on( 'change.JetFormBuilderMain', '.jet-form-builder__field', self.recalcFields )
503 .on( 'jet-form-builder/repeater-changed', '.jet-form-builder-repeater', self.recalcFields )
504 .on( 'change.JetFormBuilderMain', '.jet-form-builder__field.checkboxes-group-required', self.requiredCheckboxGroup )
505 .on( 'change.JetFormBuilderMain', '.checkradio-field', self.changeActiveTemplateClass )
506 .on( 'input.JetFormBuilderMain/range', '.jet-form-builder__field.range-field', self.updateRangeField )
507 .on( 'click.JetFormBuilderMain', '.jet-form-builder-repeater__new', self.newRepeaterItem )
508 .on( 'click.JetFormBuilderMain', '.jet-form-builder-repeater__remove', self.removeRepeaterItem )
509 .on( 'jet-form-builder/page/field-changed', self.maybeSwitchPage )
510 .on( 'jet-form-builder/switch-page', self.updateProgress )
511 .on( 'input.JetFormBuilderMain', '.jet-form-builder__field.text-field, .jet-form-builder__field.textarea-field', self.inputTextFields )
512 },
513
514 inputTextFields: function() {
515 $( this ).trigger( 'change.JetFormBuilderMain' );
516 },
517
518 updateProgress: function( event, $fromPage, $toPage, $progress ) {
519 const [ from, to ] = [ $fromPage.data( 'page' ), $toPage.data( 'page' ) ];
520
521 const prevItem = $progress.find( `.jet-form-builder-progress-pages__item--wrapper[data-page="${ from }"]` );
522 const currentItem = $progress.find( `.jet-form-builder-progress-pages__item--wrapper[data-page="${ to }"]` );
523
524 prevItem.removeClass( 'active-page' );
525 currentItem.addClass( 'active-page' );
526 currentItem.removeClass( 'passed-page' );
527
528 if ( $fromPage < $toPage ) {
529 prevItem.addClass( 'passed-page' );
530 } else {
531 prevItem.removeClass( 'passed-page' );
532 }
533 },
534
535 removeRepeaterItem: function() {
536
537 let $this = $( this ),
538 $repeater = $this.closest( '.jet-form-builder-repeater' ),
539 $repeaterItem = $this.closest( '.jet-form-builder-repeater__row' ),
540 $editor = $repeaterItem.find( '.wp-editor-area' );
541
542 $this.trigger( 'jet-form-builder/on-remove-repeater-item' );
543
544 if ( $editor.length && window.wp && window.wp.editor ) {
545 window.wp.editor.remove( $editor.attr( 'id' ) );
546 }
547
548 $repeaterItem.remove();
549 $repeater.trigger( 'jet-form-builder/repeater-changed' );
550
551 },
552
553 newRepeaterItem: function() {
554 var $this = $( this ),
555 $repeater = $this.closest( '.jet-form-builder-repeater' ),
556 $initial = $repeater.find( '.jet-form-builder-repeater__initial' ),
557 $items = $repeater.find( '.jet-form-builder-repeater__items' ),
558 $newVal = $initial.html(),
559 index = 0;
560
561 if ( $items.find( '.jet-form-builder-repeater__row' ).length ) {
562 $items.find( '.jet-form-builder-repeater__row' ).each( function() {
563 var $this = $( this ),
564 currentIndex = parseInt( $this.data( 'index' ), 10 );
565
566 if ( currentIndex > index ) {
567 index = currentIndex;
568 }
569 } );
570 index++;
571 }
572
573 $newVal = $newVal.replace( /__i__/g, index );
574 $newVal = $( $newVal );
575 $newVal.data( 'index', index );
576 $newVal.attr( 'data-index', index );
577
578 JetFormBuilder.initRangeFields( $newVal );
579
580 $items.append( $newVal );
581
582 var $editors = $newVal.find( '.wp-editor-area' );
583
584 if ( $editors.length && window.wp && window.wp.editor ) {
585 $editors.each( function() {
586 JetFormBuilder.wysiwygInitWithTriggers( this, true );
587 } );
588 }
589
590 $repeater.trigger( 'jet-form-builder/repeater-changed' );
591 $this.trigger( 'jet-form-builder/repeater-add-new', [ index ] );
592
593 JetFormBuilder.calculateRowValue( $newVal );
594
595 },
596
597 updateRepeaterItems: function( $repeater, $field ) {
598
599 var val = JetFormBuilder.getFieldValue( $field );
600
601 if ( ! val ) {
602 return;
603 }
604
605 for ( var i = 0; i < val; i++ ) {
606
607 var $item = $repeater.find( '.jet-form-builder-repeater__row[data-index="' + i + '"]' );
608
609 if ( ! $item.length ) {
610 JetFormBuilder.newRepeaterItem.call( $repeater );
611 }
612
613 }
614
615 var $rows = $repeater.find( '.jet-form-builder-repeater__row' );
616
617 if ( $rows.length ) {
618 $rows.each( function() {
619 var $row = $( this ),
620 index = parseInt( $row.data( 'index' ), 10 );
621
622 index++;
623
624 if ( index > val ) {
625 $row.remove();
626 $repeater.trigger( 'jet-form-builder/repeater-changed' );
627 }
628
629 } );
630 }
631
632 $repeater.trigger( 'change' );
633
634 },
635
636 calculateRowValue: function( $row ) {
637
638 var val = JetFormBuilder.calculateValue( $row );
639
640 $row.data( 'value', val );
641 JetFormBuilder.calculateFieldsInRow( $row );
642
643 },
644
645 calculateFieldsInRow: function( $row ) {
646
647 $row.find( '.jet-form-builder__calculated-field--child' ).each( function() {
648
649 var $childCalculatedField = $( this ),
650 val = JetFormBuilder.calculateValue( $childCalculatedField )
651
652 if ( ! val ) {
653 val = 0;
654 }
655
656 $childCalculatedField.find( '.jet-form-builder__calculated-field-val' ).text( val.toFixed( $childCalculatedField.data( 'precision' ) ) );
657 $childCalculatedField.find( '.jet-form-builder__calculated-field-input' ).val( val.toFixed( $childCalculatedField.data( 'precision' ) ) ).trigger( 'change.JetFormBuilderMain' );
658
659 } );
660
661 },
662
663 initRepeaterListener: function( $scope ) {
664
665 var $repeater = $scope.find( '.jet-form-builder-repeater' );
666
667 if ( ! $repeater.length ) {
668 return;
669 }
670
671 $repeater.each( function() {
672
673 var $this = $( this ),
674 settings = $this.data( 'settings' );
675
676 if ( 'dynamically' === settings.manageItems && settings.itemsField ) {
677 var $itemsField = $scope.find( '[data-field-name="' + settings.itemsField + '"]' );
678
679 JetFormBuilder.updateRepeaterItems( $this, $itemsField );
680
681 $itemsField.on( 'change', function() {
682 JetFormBuilder.updateRepeaterItems( $this, $itemsField );
683 } );
684 }
685
686 if ( 'custom' === settings.calcType ) {
687
688 var calculated = null;
689
690 JetFormBuilder.repeaterCalcFields[ $this.data( 'field-name' ) ] = {
691 'el': $this,
692 'listenTo': $this.data( 'listen_fields' ),
693 };
694
695 calculated = JetFormBuilder.calculateValue( $this );
696
697 $this.data( 'value', calculated.toFixed( 0 ) );
698
699 }
700
701 var $initial = $this.find( '.jet-form-builder-repeater__initial' );
702 $initial = $( $initial.html() );
703
704 var $calcFields = $initial.find( '.jet-form-builder__calculated-field--child' );
705
706 if ( $calcFields.length ) {
707
708 $calcFields.each( function() {
709
710 var $childField = $( this );
711
712 JetFormBuilder.childrenCalcFields[ $childField.data( 'name' ) ] = {
713 'el': $childField,
714 'parentEl': $this,
715 'listenTo': $childField.data( 'listen_to' ),
716 };
717
718 $this.find( '.jet-form-builder-repeater__row' ).each( function() {
719 JetFormBuilder.calculateRowValue( $( this ), $childField.data( 'precision' ) );
720 } );
721
722 } );
723 }
724
725 } );
726
727 },
728
729 simLabelClick: function( event ) {
730 $( this ).next( '.jet-form-builder__field-label' ).trigger( 'click' );
731 },
732
733 maybeSwitchPage: function( event, $field, $page, disabled ) {
734
735 var $item = $field[ 0 ],
736 isSwitch = $field.data( 'switch' ),
737 value = null,
738 $toPage = null;
739
740 if ( ! isSwitch ) {
741 return;
742 }
743
744 if ( disabled ) {
745 return;
746 }
747
748 value = $item.value;
749
750 if ( ! value ) {
751 return;
752 }
753
754 $toPage = $page.next();
755
756 if ( ! $page || ! $page.length ) {
757 return;
758 }
759
760 if ( ! $toPage || ! $toPage.length ) {
761 return;
762 }
763
764 JetFormBuilder.switchFormPage( $page, $toPage );
765
766 },
767
768 changeActiveTemplateClass: function( event ) {
769
770 var $this = $( this ),
771 $template = $this.closest( '.jet-form-builder__field-wrap' ).find( '.jet-form-builder__field-template' );
772
773 if ( ! $template.length ) {
774 return;
775 }
776
777 if ( 'radio' === $this[ 0 ].type ) {
778 $template
779 .closest( '.jet-form-builder__fields-group' )
780 .find( '.jet-form-builder__field-template--checked' )
781 .removeClass( 'jet-form-builder__field-template--checked' );
782 }
783
784 $template.toggleClass( 'jet-form-builder__field-template--checked', $this[ 0 ].checked );
785
786 },
787
788 initConditions: function( $scope ) {
789 $scope.find( '.jet-form-builder__conditional' ).jetFormBuilderConditional();
790 },
791
792 widgetBookingForm: function( $scope ) {
793
794 var $calcFields = $.find( '.jet-form-builder__calculated-field' );
795 var $editors = $scope.find( '.jet-form-builder__field .wp-editor-area' );
796
797 if ( $editors.length && window.wp && window.wp.editor ) {
798 $editors.each( function() {
799 JetFormBuilder.wysiwygInitWithTriggers( this, true );
800 } );
801 }
802 JetFormBuilder.initRequiredCheckboxGroup( $scope );
803
804 $( document ).trigger( 'jet-form-builder/init', [ $scope ] );
805
806 JetFormBuilder.initFormPager( $scope );
807 JetFormBuilder.initRangeFields( $scope );
808 JetFormBuilder.initRepeaterListener( $scope );
809 JetFormBuilder.initConditions( $scope );
810
811 if ( $.fn.inputmask ) {
812 $scope.find( '.jet-form-builder__masked-field' ).inputmask();
813 }
814
815 if ( ! $calcFields.length ) {
816 return;
817 }
818
819 $( $calcFields ).each( function() {
820
821 var $this = $( this ),
822 calculated = null;
823
824 JetFormBuilder.calcFields[ $this.data( 'name' ) ] = {
825 'el': $this,
826 'listenTo': $this.data( 'listen_to' ),
827 };
828
829 calculated = JetFormBuilder.calculateValue( $this );
830
831 $this.find( '.jet-form-builder__calculated-field-val' ).text( calculated.toFixed( $this.data( 'precision' ) ) );
832 $this.find( '.jet-form-builder__calculated-field-input' ).val( calculated.toFixed( $this.data( 'precision' ) ) ).trigger( 'change.JetFormBuilderMain' );
833
834 } );
835 },
836
837 initFormPager: function( $scope ) {
838 var $pages = $scope.find( '.jet-form-builder-page' ),
839 $form = $scope.find( '.jet-form-builder' );
840
841 if ( ! $pages.length ) {
842 return;
843 }
844
845 $pages.each( function() {
846
847 var $page = $( this );
848
849 if ( ! $page.hasClass( '.jet-form-builder-page--hidden' ) ) {
850 JetFormBuilder.initSingleFormPage( $page, $form, false );
851 }
852
853 } );
854
855 },
856
857 initSingleFormPage: function( $page, $form, $changedField ) {
858
859 var $button = $page.find( '.jet-form-builder__next-page' ),
860 $msg = $page.find( '.jet-form-builder__next-page-msg' ),
861 requiredFields = $page[ 0 ].querySelectorAll( '.jet-form-builder__field[required]' ),
862 pageNum = parseInt( $page.data( 'page' ), 10 ),
863 disabled = false,
864 radioFields = {};
865
866 $changedField = $changedField || false;
867
868 if ( requiredFields.length ) {
869 for ( var i = 0; i < requiredFields.length; i++ ) {
870
871 var $field = $( requiredFields[ i ] );
872 var val = null;
873 var isRadio = false;
874
875 if ( 'INPUT' === $field[ 0 ].nodeName ) {
876
877 if ( $field.length > 1 ) {
878 for ( var j = 0; j < $field.length; j++ ) {
879 if ( $field[ j ].checked ) {
880 val = $field[ j ].value;
881 }
882 }
883 } else if ( 'radio' === $field[ 0 ].type ) {
884
885 isRadio = true;
886
887 if ( $field[ 0 ].checked ) {
888 radioFields[ $field[ 0 ].name ] = $field[ 0 ].value;
889 }
890
891 } else {
892 val = $field.val();
893 }
894 }
895
896 if ( 'TEXTAREA' === $field[ 0 ].nodeName ) {
897 val = $field.val();
898 }
899
900 if ( 'SELECT' === $field[ 0 ].nodeName ) {
901 val = $field.find( 'option:selected' ).val();
902 }
903
904 if ( ! val ) {
905 disabled = true;
906 }
907
908 if ( isRadio && radioFields[ $field[ 0 ].name ] ) {
909 disabled = false;
910 }
911
912 }
913 }
914
915 if ( disabled ) {
916
917 if ( $msg.length ) {
918 $msg.addClass( 'jet-form-builder__next-page-msg--visible' );
919 }
920
921 $button.attr( 'disabled', true );
922 } else {
923
924 if ( $msg.length ) {
925 $msg.removeClass( 'jet-form-builder__next-page-msg--visible' );
926 }
927
928 $button.attr( 'disabled', false );
929 }
930
931 if ( ! JetFormBuilder.pages[ pageNum ] ) {
932 JetFormBuilder.pages[ pageNum ] = {
933 page: $page,
934 disabled: disabled,
935 };
936 } else {
937 JetFormBuilder.pages[ pageNum ].disabled = disabled;
938 }
939
940 if ( $changedField ) {
941 $( document ).trigger( 'jet-form-builder/page/field-changed', [ $changedField, $page, disabled ] );
942 }
943
944 if ( $page.hasClass( 'jet-form-builder-page--initialized' ) ) {
945 return;
946 }
947
948 $page.on( 'change.JetFormBuilderMain', '.jet-form-builder__field', function() {
949 JetFormBuilder.initSingleFormPage( $page, $form, $( this ) );
950 } );
951
952 $page.addClass( 'jet-form-builder-page--initialized' );
953
954 },
955
956 nextFormPage: function() {
957
958 var $button = $( this ),
959 $fromPage = $button.closest( '.jet-form-builder-page' ),
960 $pageFields = $fromPage.find( '.jet-form-builder__field' ).filter( ':input' ),
961 $toPage = $fromPage.next();
962
963 if ( ! JetFormBuilder.isFieldsValid( $pageFields ) ) {
964 return;
965 }
966
967 JetFormBuilder.switchFormPage( $fromPage, $toPage );
968
969 },
970
971 prevFormPage: function() {
972
973 var $button = $( this ),
974 $fromPage = $button.closest( '.jet-form-builder-page' ),
975 $toPage = $fromPage.prev();
976
977 JetFormBuilder.switchFormPage( $fromPage, $toPage );
978 },
979
980 isFieldsValid: function( $fields ) {
981 var isValid = true;
982
983 $fields.each( function( ind, field ) {
984 if ( ! field.checkValidity() ) {
985 field.reportValidity();
986 isValid = false;
987 return false;
988 }
989 } );
990
991 return isValid;
992 },
993
994 switchFormPage: function( $fromPage, $toPage ) {
995
996 var $form = $fromPage.closest( '.jet-form-builder' );
997
998 const $progress = $form.find( '.jet-form-builder-progress-pages' );
999
1000 $fromPage.addClass( 'jet-form-builder-page--hidden' );
1001 $toPage.removeClass( 'jet-form-builder-page--hidden' );
1002
1003 JetFormBuilder.initSingleFormPage( $toPage, $form, false );
1004
1005 $( '.jet-form-builder-messages-wrap[data-form-id="' + $form.data( 'form-id' ) + '"]' ).html( '' );
1006 $( document ).trigger( 'jet-form-builder/switch-page', [ $fromPage, $toPage, $progress ] );
1007 },
1008
1009 getFieldValue: function( $field ) {
1010
1011 var val = 0;
1012
1013 if ( $field.length ) {
1014
1015 if ( 'INPUT' === $field[ 0 ].nodeName ) {
1016 if ( $field.length > 1 ) {
1017
1018 for ( var i = 0; i < $field.length; i++ ) {
1019 if ( $field[ i ].checked ) {
1020
1021 var itemVal = 0;
1022
1023 if ( undefined !== $field[ i ].dataset.calculate ) {
1024 itemVal = $field[ i ].dataset.calculate;
1025 } else {
1026 itemVal = $field[ i ].value;
1027 }
1028
1029 if ( 'checkbox' === $field[ i ].type ) {
1030 val += parseInt( itemVal, 10 );
1031 } else {
1032 val = itemVal;
1033 }
1034
1035 }
1036 }
1037
1038 } else {
1039 if ( 'checkbox' === $field[ 0 ].type ) {
1040 if ( $field[ 0 ].checked ) {
1041 if ( undefined !== $field[ 0 ].dataset.calculate ) {
1042 val = $field[ 0 ].dataset.calculate;
1043 } else {
1044 val = $field[ 0 ].value;
1045 }
1046 }
1047 } else {
1048 val = $field.val();
1049 }
1050 }
1051 }
1052
1053 if ( 'SELECT' === $field[ 0 ].nodeName ) {
1054
1055 var selectedOption = $field.find( 'option:selected' ),
1056 calcValue = selectedOption.data( 'calculate' );
1057
1058 if ( undefined !== calcValue ) {
1059 val = calcValue;
1060 } else {
1061 val = $field.find( 'option:selected' ).val();
1062 }
1063
1064 }
1065
1066 if ( 'DIV' === $field[ 0 ].nodeName ) {
1067
1068 if ( $field.hasClass( 'jet-form-builder-repeater' ) ) {
1069 var repeaterSettings = $field.data( 'settings' );
1070 if ( repeaterSettings && 'custom' === repeaterSettings.calcType ) {
1071 $field.find( '.jet-form-builder-repeater__row' ).each( function() {
1072 var $row = $( this ),
1073 rowVal = JetFormBuilder.calculateValue( $row );
1074
1075 $row.data( 'value', rowVal );
1076
1077 val += rowVal;
1078 } );
1079
1080 } else {
1081 val = $field.find( '.jet-form-builder-repeater__row' ).length;
1082 }
1083 }
1084
1085 }
1086
1087 }
1088
1089 if ( ! val ) {
1090 val = '0';
1091 }
1092
1093 val = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-field-value', val, $field );
1094
1095 return val;
1096
1097 },
1098
1099 calculateValue: function( $scope ) {
1100
1101 var formula = String( $scope.data( 'formula' ) ),
1102 listenTo = $( '[name^="' + $scope.data( 'listen_to' ) + '"]', $scope.closest( 'form' ) ),
1103 regexp = /%([a-zA-Z0-9-_]+)%/g,
1104 func = null;
1105
1106 if ( typeof formula === 'undefined' ) {
1107 return null;
1108 }
1109
1110 formula = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-formula-before-value', formula, $scope );
1111
1112 formula = formula.replace( regexp, function( match1, match2 ) {
1113
1114 var object = null;
1115
1116 if ( $scope.data( 'repeater' ) ) {
1117 object = $scope;
1118 } else if ( $scope.hasClass( 'jet-form-builder__calculated-field--child' ) ) {
1119 object = $scope.closest( '.jet-form-builder-repeater__row' ).find( '[data-field-name="' + match2 + '"]' );
1120 } else if ( $scope.data( 'repeater-row' ) ) {
1121 object = $scope.find( '[data-field-name="' + match2 + '"]' );
1122 } else {
1123 object = $scope.closest( 'form' ).find( '[name="' + match2 + '"], [name="' + match2 + '[]"]' );
1124 }
1125
1126 return JetFormBuilder.getFieldValue( object );
1127
1128 } );
1129
1130 formula = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-formula-after-value', formula, $scope );
1131
1132 func = new Function( 'return ' + formula );
1133
1134 return func();
1135
1136 },
1137
1138 recalcFields: function( event ) {
1139
1140 var $this = $( this ),
1141 fieldName = $this.attr( 'name' ),
1142 fieldPrecision = 2,
1143 calculated = null,
1144 done = false;
1145
1146 if ( $this.data( 'field-name' ) ) {
1147 fieldName = $this.data( 'field-name' );
1148 }
1149
1150 if ( ! fieldName ) {
1151 return;
1152 }
1153
1154 $.each( JetFormBuilder.calcFields, function( calcFieldName, field ) {
1155
1156 fieldName = fieldName.replace( '[]', '' );
1157
1158 if ( 0 <= $.inArray( fieldName, field.listenTo ) ) {
1159
1160 calculated = JetFormBuilder.calculateValue( field.el );
1161 fieldPrecision = field.el.data( 'precision' );
1162
1163 field.el.find( '.jet-form-builder__calculated-field-val' ).text( calculated.toFixed( fieldPrecision ) );
1164 field.el.find( '.jet-form-builder__calculated-field-input' ).val( calculated.toFixed( fieldPrecision ) ).trigger( 'change.JetFormBuilderMain' );
1165
1166 }
1167
1168 } );
1169
1170 if ( 'jet-form-builder/repeater-changed' !== event.type ) {
1171
1172 $.each( JetFormBuilder.repeaterCalcFields, function( calcFieldName, field ) {
1173
1174 fieldName = fieldName.replace( '[]', '' );
1175
1176 if ( 0 <= $.inArray( fieldName, field.listenTo ) ) {
1177
1178 field.el.trigger( 'jet-form-builder/repeater-changed' );
1179
1180 }
1181
1182 } );
1183
1184 }
1185
1186 $.each( JetFormBuilder.childrenCalcFields, function( calcFieldName, field ) {
1187
1188 fieldName = fieldName.replace( '[]', '' );
1189
1190 if ( 0 <= $.inArray( fieldName, field.listenTo ) ) {
1191 var $row = $this.closest( '.jet-form-builder-repeater__row' );
1192 JetFormBuilder.calculateFieldsInRow( $row );
1193 }
1194
1195 } );
1196
1197 },
1198
1199 initRequiredCheckboxGroup: function( $scope ) {
1200 var $group = $scope.find( '.jet-form-builder__fields-group' );
1201
1202 $group.each( function() {
1203 var $this = $( this ),
1204 $checkboxes = $( '.checkboxes-group-required', $this );
1205
1206 if ( $checkboxes.length ) {
1207 var isChecked = $checkboxes.is( ':checked' );
1208
1209 $checkboxes.prop( 'required', ! isChecked );
1210 }
1211 } );
1212 },
1213
1214 requiredCheckboxGroup: function( event ) {
1215 var $this = $( event.target ),
1216 $group = $this.closest( '.jet-form-builder__fields-group' ),
1217 $checkboxes = $( '.checkboxes-field', $group );
1218
1219 if ( $checkboxes.length < 2 ) {
1220 return;
1221 }
1222
1223 var isChecked = $checkboxes.is( ':checked' );
1224
1225 $checkboxes.prop( 'required', ! isChecked );
1226 },
1227
1228 initRangeFields: function( $scope ) {
1229 var $rangeFields = $scope.find( '.jet-form-builder__field.range-field' );
1230
1231 if ( ! $rangeFields.length ) {
1232 return;
1233 }
1234
1235 $rangeFields.each( function() {
1236 JetFormBuilder.updateRangeField( { target: $( this ), firstInit: true } );
1237 } );
1238 },
1239
1240 updateRangeField: function( event ) {
1241 var $target = $( event.target ),
1242 $wrap = $target.closest( '.jet-form-builder__field-wrap' ),
1243 $number = $wrap.find( '.jet-form-builder__field-value-number' ),
1244 max = $target.attr( 'max' ) || 100,
1245 val = $target.val();
1246
1247 if ( event.firstInit ) {
1248 $number.text( max );
1249 }
1250
1251 $number.text( val );
1252 },
1253
1254 reloadSubmitForm: function( event ) {
1255 const $target = $( event.target );
1256 const $maskedFields = $target.find( '.jet-form-builder__masked-field' );
1257
1258 if ( $maskedFields && $maskedFields.length ) {
1259 $maskedFields.each( function() {
1260 const $maskedField = $( this );
1261
1262 // Remove mask if empty value
1263 if ( !$maskedField.val() && $maskedField.inputmask ) {
1264 $maskedField.inputmask( 'remove' );
1265 }
1266 } );
1267 }
1268 $target.find( '.jet-form-builder__submit' ).attr( 'disabled', true );
1269 },
1270
1271 ajaxSubmitForm: function() {
1272
1273 var $this = $( this ),
1274 $form = $this.closest( '.jet-form-builder' ),
1275 formID = $form.data( 'form-id' ),
1276 data = {
1277 action: JetFormBuilderSettings.form_action,
1278 };
1279
1280 if ( 'undefined' !== typeof $form[ 0 ].checkValidity && 'undefined' !== typeof $form[ 0 ].reportValidity && ! $form[ 0 ].checkValidity() ) {
1281 $form[ 0 ].reportValidity();
1282 return;
1283 }
1284
1285 if ( window.tinyMCE ) {
1286 window.tinyMCE.triggerSave();
1287 }
1288
1289 data.values = $form.serializeArray();
1290 data._jet_engine_booking_form_id = formID;
1291
1292 $form.addClass( 'is-loading' );
1293 $this.attr( 'disabled', true );
1294
1295 JetFormBuilder.clearFieldErrors( formID );
1296
1297 $.ajax( {
1298 url: JetFormBuilderSettings.ajaxurl,
1299 type: 'POST',
1300 dataType: 'json',
1301 data: data,
1302 } ).done( function( response ) {
1303
1304 $form.removeClass( 'is-loading' );
1305 $this.attr( 'disabled', false );
1306
1307 switch ( response.status ) {
1308
1309 case 'validation_failed':
1310
1311 Object.entries( response.fields ).forEach( function( [ fieldName, fieldData ] ) {
1312 var $field = JetFormBuilder.findFieldByName( $form, fieldName );
1313
1314 const afterMessage = `<div class="error-message">${ fieldData.message }</div>`;
1315
1316 $field.addClass( 'field-has-error' );
1317
1318 if ( $field.hasClass( 'checkradio-field' ) ) {
1319 $field.closest( '.jet-form-builder__field-wrap' ).after( afterMessage );
1320 } else {
1321 $field.after( afterMessage );
1322 }
1323
1324 JetFormBuilder.currentFieldWithError = {
1325 length: 0,
1326 };
1327 } );
1328
1329 break;
1330
1331 case 'success':
1332
1333 if ( response.redirect ) {
1334 window.location = response.redirect;
1335 } else if ( response.reload ) {
1336 window.location.reload();
1337 }
1338
1339 $( document ).trigger( 'jet-form-builder/ajax/on-success', [ response, $form, data ] );
1340
1341 break;
1342 }
1343
1344 $( '.jet-form-builder-messages-wrap[data-form-id="' + formID + '"]' ).html( response.message );
1345
1346 } );
1347
1348 },
1349
1350 clearFieldErrors: function( formID ) {
1351 var $this = $( this );
1352
1353 $this.closest( '.jet-form-builder-col' ).find( '.jet-form-builder__field-error' ).remove();
1354
1355 $( '.jet-form-builder__field.field-has-error' ).each( ( index, elem ) => {
1356 $( elem ).removeClass( 'field-has-error' );
1357 $( elem ).siblings( '.error-message' ).remove();
1358 } );
1359
1360 $( '.jet-form-builder-messages-wrap[data-form-id="' + formID + '"]' ).html( '' );
1361
1362 },
1363
1364 findFieldByName: function( form, fieldName ) {
1365 const callbackFinders = [
1366 'findInputDefault',
1367 'findWysiwyg',
1368 ];
1369
1370 callbackFinders.forEach( function( callback ) {
1371 if ( JetFormBuilder.currentFieldWithError && ! JetFormBuilder.currentFieldWithError.length ) {
1372 JetFormBuilder.currentFieldWithError = JetFormBuilder[ callback ]( form, fieldName );
1373 }
1374 } );
1375
1376 return JetFormBuilder.currentFieldWithError;
1377 },
1378
1379 findInputDefault: function( form, fieldName ) {
1380 return form.find( `.jet-form-builder__field[name="${ fieldName }"]:last` );
1381 },
1382
1383 findWysiwyg: function( form, fieldName ) {
1384 let field;
1385
1386 form.find( '.jet-form-builder__field[data-editor]' ).each( function( index, editor ) {
1387
1388 if ( fieldName === $( editor ).data( 'editor' ).textarea_name ) {
1389 field = $( editor );
1390 }
1391 } );
1392
1393 return field;
1394 },
1395
1396 addTriggersWysiwyg: function( field, editorId ) {
1397 const callable = function( e ) {
1398 field.trigger( 'change.JetFormBuilderMain', [ this ] );
1399 };
1400
1401 const editor = tinymce.get( editorId );
1402
1403 editor
1404 .on( 'input', callable )
1405 .on( 'change', callable );
1406 },
1407 wysiwygInit: function( closure, replace = false ) {
1408 const self = $( closure ),
1409 editorID = self.attr( 'id' ),
1410 field = self.closest( '.jet-form-builder__field' );
1411
1412 if ( replace && window.tinymce && window.tinymce.get( editorID ) ) {
1413 window.tinymce.get( editorID ).remove();
1414 }
1415
1416 window.wp.editor.initialize(
1417 editorID,
1418 field.data( 'editor' ),
1419 );
1420
1421 return { editorID, field };
1422 },
1423 wysiwygInitWithTriggers: function( closure, replace = false ) {
1424 const { editorID, field } = JetFormBuilder.wysiwygInit( closure, replace );
1425
1426 JetFormBuilder.addTriggersWysiwyg( field, editorID );
1427 },
1428
1429 };
1430
1431 window.JetFormBuilderDev = JetFormBuilderDev;
1432 window.JetFormBuilder = JetFormBuilder;
1433
1434 $( document ).ready( JetFormBuilder.initCommon );
1435 $( window ).on( 'elementor/frontend/init', JetFormBuilder.initElementor );
1436
1437 JetFormBuilder.addHandlersInit();
1438 } )( jQuery );
1439