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