PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 1.2.6
JetFormBuilder — Dynamic Blocks Form Builder v1.2.6
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 4 years ago admin.js 4 years ago editor.js 4 years ago file-upload.js 4 years ago form-block.js 4 years ago frontend-forms.js 4 years ago package.js 4 years ago
frontend-forms.js
1437 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 .attr( 'required', 'required' );
355
356 } else {
357
358 $section.hide();
359
360 $section.find( '*[type="date"],*[type="time"],*[type="email"],*[type="url"]' ).each( function() {
361 var $this = $( this ),
362 type = $this.attr( 'type' );
363
364 $this.attr( 'data-initial-type', type );
365 $this.attr( 'type', 'text' );
366 } );
367
368 var $select = $section.find( 'select' );
369
370 if ( $select.length ) {
371 $select.append( '<option value="" data-is-hidden="1"></option>' );
372 }
373
374 $section.find( '*[required]' )
375 .removeAttr( 'required' )
376 .attr( 'data-required', 1 );
377
378 var $hiddenItems = $row.find( '>*' ).filter( function() {
379 return $( this ).css( 'display' ) === 'none';
380 } );
381
382 if ( $row.find( '>*' ).length === $hiddenItems.length ) {
383 $row.hide();
384 }
385 }
386
387 };
388
389 return this.each( function() {
390
391 var $section = $( this );
392 var conditions = $section.data( 'conditional' );
393
394 if ( ! conditions || ! conditions.length ) {
395 return;
396 }
397
398 for ( var i = 0; i < conditions.length; i++ ) {
399
400 let condition = conditions[ i ];
401
402 if ( ! condition.field ) {
403 continue;
404 }
405
406 let listenTo = '[data-field-name=' + condition.field + ']';
407 let listenFor = condition.value;
408 let operator = condition.operator;
409 let type = condition.type;
410 let valueToSet = condition.set_value;
411
412 //Set up event listener
413 $( document ).on( 'change.JetFormBuilderMain', listenTo, function() {
414
415 if ( 'show' === type || 'hide' === type ) {
416 checkVisibilityCond( listenTo, listenFor, $section, operator, type );
417 } else {
418 checkSetValueCond( listenTo, listenFor, $section, operator, valueToSet, type );
419 }
420
421 setValue( $section );
422 setVisibility( $section );
423
424 } );
425
426 //If setting was chosen, hide everything first...
427 if ( settings.hideJS && ( 'show' === type || 'hide' === type ) ) {
428 $section.hide();
429 }
430
431 //Show based on current value on page load
432 if ( 'show' === type || 'hide' === type ) {
433 checkVisibilityCond( listenTo, listenFor, $section, operator, type );
434 } else {
435 checkSetValueCond( listenTo, listenFor, $section, operator, valueToSet, type );
436 }
437
438 }
439
440 setValue( $section );
441 setVisibility( $section );
442 } );
443 };
444
445 var JetFormBuilder = {
446
447 initialized: false,
448 pages: {},
449 calcFields: {},
450 repeaterCalcFields: {},
451 childrenCalcFields: {},
452 currentFieldWithError: {
453 length: 0,
454 },
455
456 notSafeInit: function() {
457 const wrappers = $( '.jet-form-builder__form-wrapper' );
458
459 wrappers.each( function( index, value ) {
460 JetFormBuilder.widgetBookingForm( $( value ) );
461 } );
462 },
463 initCommon: function() {
464 if ( JetFormBuilder.initialized ) {
465 return;
466 }
467 const wrappers = $( '.jet-form-builder__form-wrapper' );
468
469 wrappers.each( function( index, value ) {
470 JetFormBuilder.widgetBookingForm( $( value ) );
471 JetFormBuilder.initialized = true;
472 } );
473 },
474
475 initElementor: function() {
476 if ( JetFormBuilder.initialized ) {
477 return;
478 }
479 const widgets = {
480 'jet-engine-booking-form.default': JetFormBuilder.widgetBookingForm,
481 'jet-form-builder-form.default': JetFormBuilder.widgetBookingForm,
482 };
483
484 $.each( widgets, function( widget, callback ) {
485 window.elementorFrontend.hooks.addAction( 'frontend/element_ready/' + widget, callback );
486 } );
487 JetFormBuilder.initialized = true;
488 },
489
490 addHandlersInit: function() {
491 var self = JetFormBuilder;
492
493 $( document )
494 .on( 'click.JetFormBuilderMain', '.jet-form-builder__submit.submit-type-ajax', self.ajaxSubmitForm )
495 .on( 'submit.JetFormBuilderMain', 'form.jet-form-builder.submit-type-reload', self.reloadSubmitForm )
496 .on( 'click.JetFormBuilderMain', '.jet-form-builder__next-page', self.nextFormPage )
497 .on( 'click.JetFormBuilderMain', '.jet-form-builder__prev-page', self.prevFormPage )
498 .on( 'focus.JetFormBuilderMain', '.jet-form-builder__field', self.clearFieldErrors )
499 .on( 'click.JetFormBuilderMain', '.jet-form-builder__field-template', self.simLabelClick )
500 .on( 'change.JetFormBuilderMain', '.jet-form-builder__field', self.recalcFields )
501 .on( 'jet-form-builder/repeater-changed', '.jet-form-builder-repeater', self.recalcFields )
502 .on( 'change.JetFormBuilderMain', '.jet-form-builder__field.checkboxes-group-required', self.requiredCheckboxGroup )
503 .on( 'change.JetFormBuilderMain', '.checkradio-field', self.changeActiveTemplateClass )
504 .on( 'input.JetFormBuilderMain/range', '.jet-form-builder__field.range-field', self.updateRangeField )
505 .on( 'click.JetFormBuilderMain', '.jet-form-builder-repeater__new', self.newRepeaterItem )
506 .on( 'click.JetFormBuilderMain', '.jet-form-builder-repeater__remove', self.removeRepeaterItem )
507 .on( 'jet-form-builder/page/field-changed', self.maybeSwitchPage )
508 .on( 'jet-form-builder/switch-page', self.updateProgress )
509 .on( 'input.JetFormBuilderMain', '.jet-form-builder__field.text-field, .jet-form-builder__field.textarea-field', self.inputTextFields )
510 },
511
512 inputTextFields: function() {
513 $( this ).trigger( 'change.JetFormBuilderMain' );
514 },
515
516 updateProgress: function( event, $fromPage, $toPage, $progress ) {
517 const [ from, to ] = [ $fromPage.data( 'page' ), $toPage.data( 'page' ) ];
518
519 const prevItem = $progress.find( `.jet-form-builder-progress-pages__item--wrapper[data-page="${ from }"]` );
520 const currentItem = $progress.find( `.jet-form-builder-progress-pages__item--wrapper[data-page="${ to }"]` );
521
522 prevItem.removeClass( 'active-page' );
523 currentItem.addClass( 'active-page' );
524 currentItem.removeClass( 'passed-page' );
525
526 if ( from < to ) {
527 prevItem.addClass( 'passed-page' );
528 } else {
529 prevItem.removeClass( 'passed-page' );
530 }
531 },
532
533 removeRepeaterItem: function() {
534
535 let $this = $( this ),
536 $repeater = $this.closest( '.jet-form-builder-repeater' ),
537 $repeaterItem = $this.closest( '.jet-form-builder-repeater__row' ),
538 $editor = $repeaterItem.find( '.wp-editor-area' );
539
540 $this.trigger( 'jet-form-builder/on-remove-repeater-item' );
541
542 if ( $editor.length && window.wp && window.wp.editor ) {
543 window.wp.editor.remove( $editor.attr( 'id' ) );
544 }
545
546 $repeaterItem.remove();
547 $repeater.trigger( 'jet-form-builder/repeater-changed' );
548
549 },
550
551 newRepeaterItem: function() {
552 var $this = $( this ),
553 $repeater = $this.closest( '.jet-form-builder-repeater' ),
554 $initial = $repeater.find( '.jet-form-builder-repeater__initial' ),
555 $items = $repeater.find( '.jet-form-builder-repeater__items' ),
556 $newVal = $initial.html(),
557 index = 0;
558
559 if ( $items.find( '.jet-form-builder-repeater__row' ).length ) {
560 $items.find( '.jet-form-builder-repeater__row' ).each( function() {
561 var $this = $( this ),
562 currentIndex = parseInt( $this.data( 'index' ), 10 );
563
564 if ( currentIndex > index ) {
565 index = currentIndex;
566 }
567 } );
568 index++;
569 }
570
571 $newVal = $newVal.replace( /__i__/g, index );
572 $newVal = $( $newVal );
573 $newVal.data( 'index', index );
574 $newVal.attr( 'data-index', index );
575
576 JetFormBuilder.initRangeFields( $newVal );
577
578 $items.append( $newVal );
579
580 var $editors = $newVal.find( '.wp-editor-area' );
581
582 if ( $editors.length && window.wp && window.wp.editor ) {
583 $editors.each( function() {
584 JetFormBuilder.wysiwygInitWithTriggers( this, true );
585 } );
586 }
587
588 $repeater.trigger( 'jet-form-builder/repeater-changed' );
589 $this.trigger( 'jet-form-builder/repeater-add-new', [ index ] );
590
591 JetFormBuilder.calculateRowValue( $newVal );
592
593 },
594
595 updateRepeaterItems: function( $repeater, $field ) {
596
597 var val = JetFormBuilder.getFieldValue( $field );
598
599 if ( ! val ) {
600 return;
601 }
602
603 for ( var i = 0; i < val; i++ ) {
604
605 var $item = $repeater.find( '.jet-form-builder-repeater__row[data-index="' + i + '"]' );
606
607 if ( ! $item.length ) {
608 JetFormBuilder.newRepeaterItem.call( $repeater );
609 }
610
611 }
612
613 var $rows = $repeater.find( '.jet-form-builder-repeater__row' );
614
615 if ( $rows.length ) {
616 $rows.each( function() {
617 var $row = $( this ),
618 index = parseInt( $row.data( 'index' ), 10 );
619
620 index++;
621
622 if ( index > val ) {
623 $row.remove();
624 $repeater.trigger( 'jet-form-builder/repeater-changed' );
625 }
626
627 } );
628 }
629
630 $repeater.trigger( 'change' );
631
632 },
633
634 calculateRowValue: function( $row ) {
635
636 var val = JetFormBuilder.calculateValue( $row );
637
638 $row.data( 'value', val );
639 JetFormBuilder.calculateFieldsInRow( $row );
640
641 },
642
643 calculateFieldsInRow: function( $row ) {
644
645 $row.find( '.jet-form-builder__calculated-field--child' ).each( function() {
646
647 var $childCalculatedField = $( this ),
648 val = JetFormBuilder.calculateValue( $childCalculatedField )
649
650 if ( ! val ) {
651 val = 0;
652 }
653
654 JetFormBuilder.setCalculatedValue( val, $childCalculatedField );
655 } );
656
657 },
658
659 initRepeaterListener: function( $scope ) {
660
661 var $repeater = $scope.find( '.jet-form-builder-repeater' );
662
663 if ( ! $repeater.length ) {
664 return;
665 }
666
667 $repeater.each( function() {
668
669 var $this = $( this ),
670 settings = $this.data( 'settings' );
671
672 if ( 'dynamically' === settings.manageItems && settings.itemsField ) {
673 var $itemsField = $scope.find( '[data-field-name="' + settings.itemsField + '"]' );
674
675 JetFormBuilder.updateRepeaterItems( $this, $itemsField );
676
677 $itemsField.on( 'change', function() {
678 JetFormBuilder.updateRepeaterItems( $this, $itemsField );
679 } );
680 }
681
682 if ( 'custom' === settings.calcType ) {
683
684 var calculated = null;
685
686 JetFormBuilder.repeaterCalcFields[ $this.data( 'field-name' ) ] = {
687 'el': $this,
688 'listenTo': $this.data( 'listen_fields' ),
689 };
690
691 calculated = JetFormBuilder.calculateValue( $this );
692
693 $this.data( 'value', calculated.toFixed( 0 ) );
694
695 }
696
697 var $initial = $this.find( '.jet-form-builder-repeater__initial' );
698 $initial = $( $initial.html() );
699
700 var $calcFields = $initial.find( '.jet-form-builder__calculated-field--child' );
701
702 if ( $calcFields.length ) {
703
704 $calcFields.each( function() {
705
706 var $childField = $( this );
707
708 JetFormBuilder.childrenCalcFields[ $childField.data( 'name' ) ] = {
709 'el': $childField,
710 'parentEl': $this,
711 'listenTo': $childField.data( 'listen_to' ),
712 };
713
714 $this.find( '.jet-form-builder-repeater__row' ).each( function() {
715 JetFormBuilder.calculateRowValue( $( this ), $childField.data( 'precision' ) );
716 } );
717
718 } );
719 }
720
721 } );
722
723 },
724
725 simLabelClick: function( event ) {
726 $( this ).next( '.jet-form-builder__field-label' ).trigger( 'click' );
727 },
728
729 maybeSwitchPage: function( event, $field, $page, disabled ) {
730
731 var $item = $field[ 0 ],
732 isSwitch = $field.data( 'switch' ),
733 value = null,
734 $toPage = null;
735
736 if ( ! isSwitch ) {
737 return;
738 }
739
740 if ( disabled ) {
741 return;
742 }
743
744 value = $item.value;
745
746 if ( ! value ) {
747 return;
748 }
749
750 $toPage = $page.next();
751
752 if ( ! $page || ! $page.length ) {
753 return;
754 }
755
756 if ( ! $toPage || ! $toPage.length ) {
757 return;
758 }
759
760 JetFormBuilder.switchFormPage( $page, $toPage );
761
762 },
763
764 changeActiveTemplateClass: function( event ) {
765
766 var $this = $( this ),
767 $template = $this.closest( '.jet-form-builder__field-wrap' ).find( '.jet-form-builder__field-template' );
768
769 if ( ! $template.length ) {
770 return;
771 }
772
773 if ( 'radio' === $this[ 0 ].type ) {
774 $template
775 .closest( '.jet-form-builder__fields-group' )
776 .find( '.jet-form-builder__field-template--checked' )
777 .removeClass( 'jet-form-builder__field-template--checked' );
778 }
779
780 $template.toggleClass( 'jet-form-builder__field-template--checked', $this[ 0 ].checked );
781
782 },
783
784 initConditions: function( $scope ) {
785 $scope.find( '.jet-form-builder__conditional' ).jetFormBuilderConditional();
786 },
787
788 widgetBookingForm: function( $scope ) {
789
790 var $calcFields = $.find( '.jet-form-builder__calculated-field' );
791 var $editors = $scope.find( '.jet-form-builder__field .wp-editor-area' );
792
793 if ( $editors.length && window.wp && window.wp.editor ) {
794 $editors.each( function() {
795 JetFormBuilder.wysiwygInitWithTriggers( this, true );
796 } );
797 }
798 JetFormBuilder.initRequiredCheckboxGroup( $scope );
799
800 $( document ).trigger( 'jet-form-builder/init', [ $scope ] );
801
802 JetFormBuilder.initFormPager( $scope );
803 JetFormBuilder.initRangeFields( $scope );
804 JetFormBuilder.initRepeaterListener( $scope );
805 JetFormBuilder.initConditions( $scope );
806
807 if ( $.fn.inputmask ) {
808 $scope.find( '.jet-form-builder__masked-field' ).inputmask();
809 }
810
811 if ( ! $calcFields.length ) {
812 return;
813 }
814
815 $( $calcFields ).each( function() {
816
817 var $this = $( this ),
818 calculated = null;
819
820 JetFormBuilder.calcFields[ $this.data( 'name' ) ] = {
821 'el': $this,
822 'listenTo': $this.data( 'listen_to' ),
823 };
824
825 calculated = JetFormBuilder.calculateValue( $this );
826
827 JetFormBuilder.setCalculatedValue( calculated, $this );
828 } );
829 },
830
831 initFormPager: function( $scope ) {
832 var $pages = $scope.find( '.jet-form-builder-page' ),
833 $form = $scope.find( '.jet-form-builder' );
834
835 if ( ! $pages.length ) {
836 return;
837 }
838
839 $pages.each( function() {
840
841 var $page = $( this );
842
843 if ( ! $page.hasClass( '.jet-form-builder-page--hidden' ) ) {
844 JetFormBuilder.initSingleFormPage( $page, $form, false );
845 }
846
847 } );
848
849 },
850
851 initSingleFormPage: function( $page, $form, $changedField ) {
852
853 var $button = $page.find( '.jet-form-builder__next-page' ),
854 $msg = $page.find( '.jet-form-builder__next-page-msg' ),
855 requiredFields = $page[ 0 ].querySelectorAll( '.jet-form-builder__field[required]' ),
856 pageNum = parseInt( $page.data( 'page' ), 10 ),
857 disabled = false,
858 radioFields = {};
859
860 $changedField = $changedField || false;
861
862 if ( requiredFields.length ) {
863 for ( var i = 0; i < requiredFields.length; i++ ) {
864
865 var $field = $( requiredFields[ i ] );
866 var val = null;
867 var isRadio = false;
868
869 if ( 'INPUT' === $field[ 0 ].nodeName ) {
870
871 if ( $field.length > 1 ) {
872 for ( var j = 0; j < $field.length; j++ ) {
873 if ( $field[ j ].checked ) {
874 val = $field[ j ].value;
875 }
876 }
877 } else if ( 'radio' === $field[ 0 ].type ) {
878
879 isRadio = true;
880
881 if ( $field[ 0 ].checked ) {
882 radioFields[ $field[ 0 ].name ] = $field[ 0 ].value;
883 }
884
885 } else {
886 val = $field.val();
887 }
888 }
889
890 if ( 'TEXTAREA' === $field[ 0 ].nodeName ) {
891 val = $field.val();
892 }
893
894 if ( 'SELECT' === $field[ 0 ].nodeName ) {
895 val = $field.find( 'option:selected' ).val();
896 }
897
898 if ( ! val ) {
899 disabled = true;
900 }
901
902 if ( isRadio && radioFields[ $field[ 0 ].name ] ) {
903 disabled = false;
904 }
905
906 }
907 }
908
909 if ( disabled ) {
910
911 if ( $msg.length ) {
912 $msg.addClass( 'jet-form-builder__next-page-msg--visible' );
913 }
914
915 $button.attr( 'disabled', true );
916 } else {
917
918 if ( $msg.length ) {
919 $msg.removeClass( 'jet-form-builder__next-page-msg--visible' );
920 }
921
922 $button.attr( 'disabled', false );
923 }
924
925 if ( ! JetFormBuilder.pages[ pageNum ] ) {
926 JetFormBuilder.pages[ pageNum ] = {
927 page: $page,
928 disabled: disabled,
929 };
930 } else {
931 JetFormBuilder.pages[ pageNum ].disabled = disabled;
932 }
933
934 if ( $changedField ) {
935 $( document ).trigger( 'jet-form-builder/page/field-changed', [ $changedField, $page, disabled ] );
936 }
937
938 if ( $page.hasClass( 'jet-form-builder-page--initialized' ) ) {
939 return;
940 }
941
942 $page.on( 'change.JetFormBuilderMain', '.jet-form-builder__field', function() {
943 JetFormBuilder.initSingleFormPage( $page, $form, $( this ) );
944 } );
945
946 $page.addClass( 'jet-form-builder-page--initialized' );
947
948 },
949
950 nextFormPage: function() {
951
952 var $button = $( this ),
953 $fromPage = $button.closest( '.jet-form-builder-page' ),
954 $pageFields = $fromPage.find( '.jet-form-builder__field' ).filter( ':input' ),
955 $toPage = $fromPage.next();
956
957 if ( ! JetFormBuilder.isFieldsValid( $pageFields ) ) {
958 return;
959 }
960
961 JetFormBuilder.switchFormPage( $fromPage, $toPage );
962
963 },
964
965 prevFormPage: function() {
966
967 var $button = $( this ),
968 $fromPage = $button.closest( '.jet-form-builder-page' ),
969 $toPage = $fromPage.prev();
970
971 JetFormBuilder.switchFormPage( $fromPage, $toPage );
972 },
973
974 isFieldsValid: function( $fields ) {
975 var isValid = true;
976
977 $fields.each( function( ind, field ) {
978 if ( ! field.checkValidity() ) {
979 field.reportValidity();
980 isValid = false;
981 return false;
982 }
983 } );
984
985 return isValid;
986 },
987
988 switchFormPage: function( $fromPage, $toPage ) {
989
990 var $form = $fromPage.closest( '.jet-form-builder' );
991
992 const $progress = $form.find( '.jet-form-builder-progress-pages' );
993
994 $fromPage.addClass( 'jet-form-builder-page--hidden' );
995 $toPage.removeClass( 'jet-form-builder-page--hidden' );
996
997 JetFormBuilder.initSingleFormPage( $toPage, $form, false );
998
999 $( '.jet-form-builder-messages-wrap[data-form-id="' + $form.data( 'form-id' ) + '"]' ).html( '' );
1000 $( document ).trigger( 'jet-form-builder/switch-page', [ $fromPage, $toPage, $progress ] );
1001 },
1002
1003 getFieldValue: function( $field ) {
1004
1005 var val = 0;
1006
1007 if ( $field.length ) {
1008
1009 if ( 'INPUT' === $field[ 0 ].nodeName ) {
1010 if ( $field.length > 1 ) {
1011
1012 for ( var i = 0; i < $field.length; i++ ) {
1013 if ( $field[ i ].checked ) {
1014
1015 var itemVal = 0;
1016
1017 if ( undefined !== $field[ i ].dataset.calculate ) {
1018 itemVal = $field[ i ].dataset.calculate;
1019 } else {
1020 itemVal = $field[ i ].value;
1021 }
1022
1023 if ( 'checkbox' === $field[ i ].type ) {
1024 val += parseFloat( itemVal );
1025 } else {
1026 val = itemVal;
1027 }
1028
1029 }
1030 }
1031
1032 } else {
1033 if ( 'checkbox' === $field[ 0 ].type ) {
1034 if ( $field[ 0 ].checked ) {
1035 if ( undefined !== $field[ 0 ].dataset.calculate ) {
1036 val = $field[ 0 ].dataset.calculate;
1037 } else {
1038 val = $field[ 0 ].value;
1039 }
1040 }
1041 } else {
1042 val = $field.val();
1043 }
1044 }
1045 }
1046
1047 if ( 'SELECT' === $field[ 0 ].nodeName ) {
1048
1049 var selectedOption = $field.find( 'option:selected' ),
1050 calcValue = selectedOption.data( 'calculate' );
1051
1052 if ( undefined !== calcValue ) {
1053 val = calcValue;
1054 } else {
1055 val = $field.find( 'option:selected' ).val();
1056 }
1057
1058 }
1059
1060 if ( 'DIV' === $field[ 0 ].nodeName ) {
1061
1062 if ( $field.hasClass( 'jet-form-builder-repeater' ) ) {
1063 var repeaterSettings = $field.data( 'settings' );
1064 if ( repeaterSettings && 'custom' === repeaterSettings.calcType ) {
1065 $field.find( '.jet-form-builder-repeater__row' ).each( function() {
1066 var $row = $( this ),
1067 rowVal = JetFormBuilder.calculateValue( $row );
1068
1069 $row.data( 'value', rowVal );
1070
1071 val += rowVal;
1072 } );
1073
1074 } else {
1075 val = $field.find( '.jet-form-builder-repeater__row' ).length;
1076 }
1077 }
1078
1079 }
1080
1081 }
1082
1083 if ( ! val ) {
1084 val = '0';
1085 }
1086
1087 val = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-field-value', val, $field );
1088
1089 return val;
1090
1091 },
1092
1093 calculateValue: function( $scope ) {
1094
1095 var formula = String( $scope.data( 'formula' ) ),
1096 listenTo = $( '[name^="' + $scope.data( 'listen_to' ) + '"]', $scope.closest( 'form' ) ),
1097 regexp = /%([a-zA-Z0-9-_]+)%/g,
1098 func = null;
1099
1100 if ( typeof formula === 'undefined' ) {
1101 return null;
1102 }
1103
1104 formula = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-formula-before-value', formula, $scope );
1105
1106 formula = formula.replace( regexp, function( match1, match2 ) {
1107
1108 var object = null;
1109
1110 if ( $scope.data( 'repeater' ) ) {
1111 object = $scope;
1112 } else if ( $scope.hasClass( 'jet-form-builder__calculated-field--child' ) ) {
1113 object = $scope.closest( '.jet-form-builder-repeater__row' ).find( '[data-field-name="' + match2 + '"]' );
1114 } else if ( $scope.data( 'repeater-row' ) ) {
1115 object = $scope.find( '[data-field-name="' + match2 + '"]' );
1116 } else {
1117 object = $scope.closest( 'form' ).find( '[name="' + match2 + '"], [name="' + match2 + '[]"]' );
1118 }
1119
1120 return JetFormBuilder.getFieldValue( object );
1121
1122 } );
1123
1124 formula = JetFormBuilderMain.filters.applyFilters( 'forms/calculated-formula-after-value', formula, $scope );
1125
1126 func = new Function( 'return ' + formula );
1127
1128 return func();
1129
1130 },
1131
1132 setCalculatedValue: function( calculatedValue, calcField ) {
1133 const fieldPrecision = calcField.data( 'precision' );
1134 const number = calculatedValue.toFixed( fieldPrecision );
1135
1136 calcField.find( '.jet-form-builder__calculated-field-val' ).text( number );
1137 calcField.find( '.jet-form-builder__calculated-field-input' ).val( number ).trigger( 'change.JetFormBuilderMain' );
1138 },
1139
1140 recalcFields: function( event ) {
1141
1142 var $this = $( this ),
1143 fieldName = $this.attr( 'name' ),
1144 calculated = null;
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 calculated = JetFormBuilder.calculateValue( field.el );
1160
1161 JetFormBuilder.setCalculatedValue( calculated, field.el )
1162 }
1163
1164 } );
1165
1166 if ( 'jet-form-builder/repeater-changed' !== event.type ) {
1167
1168 $.each( JetFormBuilder.repeaterCalcFields, function( calcFieldName, field ) {
1169
1170 fieldName = fieldName.replace( '[]', '' );
1171
1172 if ( 0 <= $.inArray( fieldName, field.listenTo ) ) {
1173
1174 field.el.trigger( 'jet-form-builder/repeater-changed' );
1175
1176 }
1177
1178 } );
1179
1180 }
1181
1182 $.each( JetFormBuilder.childrenCalcFields, function( calcFieldName, field ) {
1183
1184 fieldName = fieldName.replace( '[]', '' );
1185
1186 if ( 0 <= $.inArray( fieldName, field.listenTo ) ) {
1187 var $row = $this.closest( '.jet-form-builder-repeater__row' );
1188 JetFormBuilder.calculateFieldsInRow( $row );
1189 }
1190
1191 } );
1192
1193 },
1194
1195 initRequiredCheckboxGroup: function( $scope ) {
1196 var $group = $scope.find( '.jet-form-builder__fields-group' );
1197
1198 $group.each( function() {
1199 var $this = $( this ),
1200 $checkboxes = $( '.checkboxes-group-required', $this );
1201
1202 if ( $checkboxes.length ) {
1203 var isChecked = $checkboxes.is( ':checked' );
1204
1205 $checkboxes.prop( 'required', ! isChecked );
1206 }
1207 } );
1208 },
1209
1210 requiredCheckboxGroup: function( event ) {
1211 var $this = $( event.target ),
1212 $group = $this.closest( '.jet-form-builder__fields-group' ),
1213 $checkboxes = $( '.checkboxes-field', $group );
1214
1215 if ( $checkboxes.length < 2 ) {
1216 return;
1217 }
1218
1219 var isChecked = $checkboxes.is( ':checked' );
1220
1221 $checkboxes.prop( 'required', ! isChecked );
1222 },
1223
1224 initRangeFields: function( $scope ) {
1225 var $rangeFields = $scope.find( '.jet-form-builder__field.range-field' );
1226
1227 if ( ! $rangeFields.length ) {
1228 return;
1229 }
1230
1231 $rangeFields.each( function() {
1232 JetFormBuilder.updateRangeField( { target: $( this ), firstInit: true } );
1233 } );
1234 },
1235
1236 updateRangeField: function( event ) {
1237 var $target = $( event.target ),
1238 $wrap = $target.closest( '.jet-form-builder__field-wrap' ),
1239 $number = $wrap.find( '.jet-form-builder__field-value-number' ),
1240 max = $target.attr( 'max' ) || 100,
1241 val = $target.val();
1242
1243 if ( event.firstInit ) {
1244 $number.text( max );
1245 }
1246
1247 $number.text( val );
1248 },
1249
1250 reloadSubmitForm: function( event ) {
1251 const $target = $( event.target );
1252 const $maskedFields = $target.find( '.jet-form-builder__masked-field' );
1253
1254 if ( $maskedFields && $maskedFields.length ) {
1255 $maskedFields.each( function() {
1256 const $maskedField = $( this );
1257
1258 // Remove mask if empty value
1259 if ( ! $maskedField.val() && $maskedField.inputmask ) {
1260 $maskedField.inputmask( 'remove' );
1261 }
1262 } );
1263 }
1264 $target.find( '.jet-form-builder__submit' ).attr( 'disabled', true );
1265 },
1266
1267 ajaxSubmitForm: function() {
1268
1269 var $this = $( this ),
1270 $form = $this.closest( '.jet-form-builder' ),
1271 formID = $form.data( 'form-id' ),
1272 data = {
1273 action: JetFormBuilderSettings.form_action,
1274 };
1275
1276 if ( 'undefined' !== typeof $form[ 0 ].checkValidity && 'undefined' !== typeof $form[ 0 ].reportValidity && ! $form[ 0 ].checkValidity() ) {
1277 $form[ 0 ].reportValidity();
1278 return;
1279 }
1280
1281 if ( window.tinyMCE ) {
1282 window.tinyMCE.triggerSave();
1283 }
1284
1285 data.values = $form.serializeArray();
1286 data._jet_engine_booking_form_id = formID;
1287
1288 $form.addClass( 'is-loading' );
1289 $this.attr( 'disabled', true );
1290
1291 JetFormBuilder.clearFieldErrors( formID );
1292
1293 $.ajax( {
1294 url: JetFormBuilderSettings.ajaxurl,
1295 type: 'POST',
1296 dataType: 'json',
1297 data: data,
1298 } ).done( function( response ) {
1299
1300 $form.removeClass( 'is-loading' );
1301 $this.attr( 'disabled', false );
1302
1303 switch ( response.status ) {
1304
1305 case 'validation_failed':
1306
1307 Object.entries( response.fields ).forEach( function( [ fieldName, fieldData ] ) {
1308 var $field = JetFormBuilder.findFieldByName( $form, fieldName );
1309
1310 const afterMessage = `<div class="error-message">${ fieldData.message }</div>`;
1311
1312 $field.addClass( 'field-has-error' );
1313
1314 if ( $field.hasClass( 'checkradio-field' ) ) {
1315 $field.closest( '.jet-form-builder__field-wrap' ).after( afterMessage );
1316 } else {
1317 $field.after( afterMessage );
1318 }
1319
1320 JetFormBuilder.currentFieldWithError = {
1321 length: 0,
1322 };
1323 } );
1324
1325 break;
1326
1327 case 'success':
1328
1329 if ( response.redirect ) {
1330 window.location = response.redirect;
1331 } else if ( response.reload ) {
1332 window.location.reload();
1333 }
1334
1335 $( document ).trigger( 'jet-form-builder/ajax/on-success', [ response, $form, data ] );
1336
1337 break;
1338 }
1339
1340 $( '.jet-form-builder-messages-wrap[data-form-id="' + formID + '"]' ).html( response.message );
1341
1342 } );
1343
1344 },
1345
1346 clearFieldErrors: function( formID ) {
1347 var $this = $( this );
1348
1349 $this.closest( '.jet-form-builder-col' ).find( '.jet-form-builder__field-error' ).remove();
1350
1351 $( '.jet-form-builder__field.field-has-error' ).each( ( index, elem ) => {
1352 $( elem ).removeClass( 'field-has-error' );
1353 $( elem ).siblings( '.error-message' ).remove();
1354 } );
1355
1356 $( '.jet-form-builder-messages-wrap[data-form-id="' + formID + '"]' ).html( '' );
1357
1358 },
1359
1360 findFieldByName: function( form, fieldName ) {
1361 const callbackFinders = [
1362 'findInputDefault',
1363 'findWysiwyg',
1364 ];
1365
1366 callbackFinders.forEach( function( callback ) {
1367 if ( JetFormBuilder.currentFieldWithError && ! JetFormBuilder.currentFieldWithError.length ) {
1368 JetFormBuilder.currentFieldWithError = JetFormBuilder[ callback ]( form, fieldName );
1369 }
1370 } );
1371
1372 return JetFormBuilder.currentFieldWithError;
1373 },
1374
1375 findInputDefault: function( form, fieldName ) {
1376 return form.find( `.jet-form-builder__field[name="${ fieldName }"]:last` );
1377 },
1378
1379 findWysiwyg: function( form, fieldName ) {
1380 let field;
1381
1382 form.find( '.jet-form-builder__field[data-editor]' ).each( function( index, editor ) {
1383
1384 if ( fieldName === $( editor ).data( 'editor' ).textarea_name ) {
1385 field = $( editor );
1386 }
1387 } );
1388
1389 return field;
1390 },
1391
1392 addTriggersWysiwyg: function( field, editorId ) {
1393 const callable = function( e ) {
1394 field.trigger( 'change.JetFormBuilderMain', [ this ] );
1395 };
1396
1397 const editor = tinymce.get( editorId );
1398
1399 editor
1400 .on( 'input', callable )
1401 .on( 'change', callable );
1402 },
1403 wysiwygInit: function( closure, replace = false ) {
1404 const self = $( closure ),
1405 editorID = self.attr( 'id' ),
1406 field = self.closest( '.jet-form-builder__field' );
1407
1408 if ( replace && window.tinymce && window.tinymce.get( editorID ) ) {
1409 window.tinymce.get( editorID ).remove();
1410 }
1411
1412 window.wp.editor.initialize(
1413 editorID,
1414 field.data( 'editor' ),
1415 );
1416
1417 return { editorID, field };
1418 },
1419 wysiwygInitWithTriggers: function( closure, replace = false ) {
1420 const { editorID, field } = JetFormBuilder.wysiwygInit( closure, replace );
1421
1422 JetFormBuilder.addTriggersWysiwyg( field, editorID );
1423 },
1424
1425 };
1426
1427 window.JetFormBuilderDev = JetFormBuilderDev;
1428 window.JetFormBuilder = JetFormBuilder;
1429
1430 $( JetFormBuilder.initCommon );
1431 $( window ).on( 'elementor/frontend/init', JetFormBuilder.initElementor );
1432
1433 document.addEventListener( 'jet-fb.render.form-block', JetFormBuilder.notSafeInit )
1434
1435 JetFormBuilder.addHandlersInit();
1436 } )( jQuery );
1437