PluginProbe ʕ •ᴥ•ʔ
Conditional Fields for Contact Form 7 / 1.8.5
Conditional Fields for Contact Form 7 v1.8.5
2.7.13 2.7.11 2.7.12 2.7.10 2.7.9 2.7.8 2.7.7 2.7.6 2.7.5 2.7.4 2.7.3 2.7.2 0.2.4 0.2.5 0.2.6 0.2.7 0.2.8 0.2.9 1.0 1.1 1.2 1.2.1 1.2.2 1.2.3 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.4 1.4.1 1.4.2 1.4.3 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6.1 1.6.2 1.6.3 1.6.5 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.8 1.7.9 1.8 1.8.1 1.8.2 1.8.3 1.8.5 1.8.6 1.8.7 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2 2.2.1 2.2.10 2.2.11 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3 2.3.1 2.3.10 2.3.11 2.3.12 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.14 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.7 2.7.1 trunk 0.1 0.1.1 0.1.2 0.1.3 0.1.4 0.1.5 0.1.6 0.1.7 0.2 0.2.1 0.2.2 0.2.3
cf7-conditional-fields / js / scripts_es6.js
cf7-conditional-fields / js Last commit date
scripts.js 6 years ago scripts.js.map 6 years ago scripts_admin.js 6 years ago scripts_es6.js 6 years ago
scripts_es6.js
1045 lines
1 "use strict";
2
3 import jQuery from 'jquery';
4
5
6 var cf7signature_resized = 0; // for compatibility with contact-form-7-signature-addon
7
8 var wpcf7cf_timeout;
9 var wpcf7cf_change_time_ms = window.wpcf7cf_running_tests ? 0 : 100;
10
11 console.log(wpcf7cf_change_time_ms);
12
13 var wpcf7cf_show_animation = { "height": "show", "marginTop": "show", "marginBottom": "show", "paddingTop": "show", "paddingBottom": "show" };
14 var wpcf7cf_hide_animation = { "height": "hide", "marginTop": "hide", "marginBottom": "hide", "paddingTop": "hide", "paddingBottom": "hide" };
15
16 var wpcf7cf_show_step_animation = { "opacity": "show" };
17 var wpcf7cf_hide_step_animation = { "opacity": "hide" };
18
19 var wpcf7cf_change_events = 'input.wpcf7cf paste.wpcf7cf change.wpcf7cf click.wpcf7cf propertychange.wpcf7cf';
20
21 var wpcf7cf_forms = [];
22
23 // endswith polyfill
24 if (!String.prototype.endsWith) {
25 String.prototype.endsWith = function(search, this_len) {
26 if (this_len === undefined || this_len > this.length) {
27 this_len = this.length;
28 }
29 return this.substring(this_len - search.length, this_len) === search;
30 };
31 }
32
33 var Wpcf7cfForm = function($form) {
34
35 var options_element = $form.find('input[name="_wpcf7cf_options"]').eq(0);
36 if (!options_element.length || !options_element.val()) {
37 // doesn't look like a CF7 form created with conditional fields plugin enabled.
38 return false;
39 }
40
41 var form = this;
42
43 var form_options = JSON.parse(options_element.val());
44
45 form.$form = $form;
46 form.$input_hidden_group_fields = $form.find('[name="_wpcf7cf_hidden_group_fields"]');
47 form.$input_hidden_groups = $form.find('[name="_wpcf7cf_hidden_groups"]');
48 form.$input_visible_groups = $form.find('[name="_wpcf7cf_visible_groups"]');
49 form.$input_repeaters = $form.find('[name="_wpcf7cf_repeaters"]');
50 form.$input_steps = $form.find('[name="_wpcf7cf_steps"]');
51
52 form.unit_tag = $form.closest('.wpcf7').attr('id');
53 form.conditions = form_options['conditions'];
54
55 // compatibility with conditional forms created with older versions of the plugin ( < 1.4 )
56 for (var i=0; i < form.conditions.length; i++) {
57 var condition = form.conditions[i];
58 if (!('and_rules' in condition)) {
59 condition.and_rules = [{'if_field':condition.if_field,'if_value':condition.if_value,'operator':condition.operator}];
60 }
61 }
62
63 form.initial_conditions = form.conditions;
64 form.settings = form_options['settings'];
65
66 form.$groups = jQuery(); // empty jQuery set
67 form.repeaters = [];
68 form.multistep = null;
69 form.fields = [];
70
71 form.settings.animation_intime = parseInt(form.settings.animation_intime);
72 form.settings.animation_outtime = parseInt(form.settings.animation_outtime);
73
74 if (form.settings.animation === 'no') {
75 form.settings.animation_intime = 0;
76 form.settings.animation_outtime = 0;
77 }
78
79 form.updateGroups();
80 form.updateEventListeners();
81 form.displayFields();
82
83 // bring form in initial state if the reset event is fired on it.
84 form.$form.on('reset.wpcf7cf', form, function(e) {
85 var form = e.data;
86 setTimeout(function(){
87 form.displayFields();
88 form.resetRepeaters();
89 if (form.multistep != null) {
90 form.multistep.moveToStep(1);
91 }
92 },200);
93 });
94
95 // PRO ONLY
96
97 jQuery('.wpcf7cf_repeater:not(.wpcf7cf_repeater .wpcf7cf_repeater)', $form).each(function(){
98 form.repeaters.push(new Wpcf7cfRepeater(jQuery(this),form));
99 });
100
101 form.$input_repeaters.val(JSON.stringify(form.repeaters.map((item)=>item.params.$repeater.id)));
102
103 var $multistep = jQuery('.wpcf7cf_multistep', $form);
104
105 if ($multistep.length) {
106 form.multistep = new Wpcf7cfMultistep($multistep, form);
107 // window.wpcf7cf.updateMultistepState(form.multistep);
108 }
109
110 // END PRO ONLY
111
112 }
113
114 /**
115 * reset initial number of subs for each repeater.
116 * (does not clear values)
117 */
118 Wpcf7cfForm.prototype.resetRepeaters = function() {
119 var form = this;
120 form.repeaters.forEach(repeater => {
121 repeater.updateSubs( repeater.params.$repeater.initial_subs );
122 });
123 }
124
125 Wpcf7cfForm.prototype.displayFields = function() {
126
127 var form = this;
128
129 window.wpcf7cf.get_simplified_dom_model(form.$form);
130
131 var unit_tag = this.unit_tag;
132 var wpcf7cf_conditions = this.conditions;
133 var wpcf7cf_settings = this.settings;
134
135 //for compatibility with contact-form-7-signature-addon
136 if (cf7signature_resized === 0 && typeof signatures !== 'undefined' && signatures.constructor === Array && signatures.length > 0 ) {
137 for (var i = 0; i < signatures.length; i++) {
138 if (signatures[i].canvas.width === 0) {
139
140 var $sig_canvas = jQuery(".wpcf7-form-control-signature-body>canvas");
141 var $sig_wrap = jQuery(".wpcf7-form-control-signature-wrap");
142 $sig_canvas.eq(i).attr('width', $sig_wrap.width());
143 $sig_canvas.eq(i).attr('height', $sig_wrap.height());
144
145 cf7signature_resized = 1;
146 }
147 }
148 }
149
150 form.$groups.addClass('wpcf7cf-hidden');
151
152 for (var i=0; i < wpcf7cf_conditions.length; i++) {
153
154 var condition = wpcf7cf_conditions[i];
155
156 var show_group = window.wpcf7cf.should_group_be_shown(condition, form.$form);
157
158 if (show_group) {
159 jQuery('[data-id="'+condition.then_field+'"]',form.$form).eq(0).removeClass('wpcf7cf-hidden');
160 }
161 }
162
163 var animation_intime = wpcf7cf_settings.animation_intime;
164 var animation_outtime = wpcf7cf_settings.animation_outtime;
165
166 form.$groups.each(function (index) {
167 var $group = jQuery(this);
168 if ($group.is(':animated')) $group.finish(); // stop any current animations on the group
169 if ($group.css('display') === 'none' && !$group.hasClass('wpcf7cf-hidden')) {
170 if ($group.prop('tagName') === 'SPAN') {
171 $group.show().trigger('wpcf7cf_show_group');
172 } else {
173 $group.animate(wpcf7cf_show_animation, animation_intime).trigger('wpcf7cf_show_group'); // show
174 }
175 } else if ($group.css('display') !== 'none' && $group.hasClass('wpcf7cf-hidden')) {
176
177 if ($group.attr('data-clear_on_hide') !== undefined) {
178 var $inputs = jQuery(':input', $group).not(':button, :submit, :reset, :hidden');
179
180 $inputs.each(function(){
181 var $this = jQuery(this);
182 $this.val(this.defaultValue);
183 $this.prop('checked', this.defaultChecked);
184 });
185
186 jQuery('option', $group).each(function() {
187 this.selected = this.defaultSelected;
188 });
189
190 jQuery('select', $group).each(function() {
191 const $select = jQuery(this);
192 if ($select.val() === null) {
193 $select.val(jQuery("option:first",$select).val());
194 }
195 });
196
197 $inputs.change();
198 //display_fields();
199 }
200
201 if ($group.prop('tagName') === 'SPAN') {
202 $group.hide().trigger('wpcf7cf_hide_group');
203 } else {
204 $group.animate(wpcf7cf_hide_animation, animation_outtime).trigger('wpcf7cf_hide_group'); // hide
205 }
206
207 }
208 });
209
210 form.updateHiddenFields();
211 form.updateSummaryFields();
212 };
213
214 Wpcf7cfForm.prototype.updateSummaryFields = function() {
215 var $summary = jQuery('.wpcf7cf-summary', this.$form);
216
217 if ($summary.length == 0 || !$summary.is(':visible')) return;
218
219 var fd = new FormData();
220
221 var formdata = this.$form.serializeArray();
222 jQuery.each(formdata,function(key, input){
223 fd.append(input.name, input.value);
224 });
225
226 jQuery.ajax({
227 url: wpcf7cf_global_settings.ajaxurl + '?action=wpcf7cf_get_summary',
228 type: 'POST',
229 data: fd,
230 processData: false,
231 contentType: false,
232 dataType: 'json',
233 success: function(json) {
234 $summary.html(json.summaryHtml);
235 }
236 });
237 };
238
239 Wpcf7cfForm.prototype.updateHiddenFields = function() {
240
241 var form = this;
242
243 var hidden_fields = [];
244 var hidden_groups = [];
245 var visible_groups = [];
246
247 form.$groups.each(function () {
248 var $this = jQuery(this);
249 if ($this.hasClass('wpcf7cf-hidden')) {
250 hidden_groups.push($this.data('id'));
251 $this.find('input,select,textarea').each(function () {
252 hidden_fields.push(jQuery(this).attr('name'));
253 });
254 } else {
255 visible_groups.push($this.data('id'));
256 }
257 });
258
259 form.hidden_fields = hidden_fields;
260 form.hidden_groups = hidden_groups;
261 form.visible_groups = visible_groups;
262
263 form.$input_hidden_group_fields.val(JSON.stringify(hidden_fields));
264 form.$input_hidden_groups.val(JSON.stringify(hidden_groups));
265 form.$input_visible_groups.val(JSON.stringify(visible_groups));
266
267 return true;
268 };
269 Wpcf7cfForm.prototype.updateGroups = function() {
270 var form = this;
271 form.$groups = form.$form.find('[data-class="wpcf7cf_group"]');
272
273 form.conditions = window.wpcf7cf.get_nested_conditions(form.initial_conditions, form.$form);
274
275 };
276 Wpcf7cfForm.prototype.updateEventListeners = function() {
277
278 var form = this;
279
280 // monitor input changes, and call display_fields() if something has changed
281 jQuery('input, select, textarea, button',form.$form).not('.wpcf7cf_add, .wpcf7cf_remove').off(wpcf7cf_change_events).on(wpcf7cf_change_events,form, function(e) {
282 var form = e.data;
283 clearTimeout(wpcf7cf_timeout);
284 wpcf7cf_timeout = setTimeout(function() {
285 form.displayFields();
286 }, wpcf7cf_change_time_ms);
287 });
288
289 // PRO ONLY
290 jQuery('.wpcf7cf-togglebutton', form.$form).off('click.toggle_wpcf7cf').on('click.toggle_wpcf7cf',function() {
291 var $this = jQuery(this);
292 if ($this.text() === $this.data('val-1')) {
293 $this.text($this.data('val-2'));
294 $this.val($this.data('val-2'));
295 } else {
296 $this.text($this.data('val-1'));
297 $this.val($this.data('val-1'));
298 }
299 });
300 // END PRO ONLY
301 };
302
303 // PRO ONLY
304 function Wpcf7cfRepeater($repeater, form) {
305 var $ = jQuery;
306
307 var repeater = this;
308
309 var wpcf7cf_settings = form.settings;
310
311 repeater.form = form;
312
313 $repeater.num_subs = 0;
314 $repeater.id = $repeater.data('id');
315 $repeater.orig_id = $repeater.data('orig_data_id');
316 $repeater.min = typeof( $repeater.data('min')) !== 'undefined' ? parseInt($repeater.data('min')) : 1;
317 $repeater.max = typeof( $repeater.data('max')) !== 'undefined' ? parseInt($repeater.data('max')) : 200;
318 $repeater.initial_subs = typeof( $repeater.data('initial')) !== 'undefined' ? parseInt($repeater.data('initial')) : $repeater.min;
319 if ($repeater.initial_subs > $repeater.max) $repeater.initial_subs = $repeater.max;
320 var $repeater_sub = $repeater.children('.wpcf7cf_repeater_sub').eq(0);
321 var $repeater_controls = $repeater.children('.wpcf7cf_repeater_controls').eq(0);
322
323 var $repeater_sub_clone = $repeater_sub.clone();
324
325 $repeater_sub_clone.find('.wpcf7cf_repeater_sub').addBack('.wpcf7cf_repeater_sub').each(function() {
326 var $this = jQuery(this);
327 var prev_suffix = $this.attr('data-repeater_sub_suffix');
328 var new_suffix = prev_suffix+'__{{repeater_sub_suffix}}';
329 $this.attr('data-repeater_sub_suffix', new_suffix);
330 });
331
332 $repeater_sub_clone.find('[name]').each(function() {
333 var $this = jQuery(this);
334 var prev_name = $this.attr('name');
335 var orig_name = $this.attr('data-orig_name') != null ? $this.attr('data-orig_name') : prev_name;
336 var new_name = prev_name+'__{{repeater_sub_suffix}}';
337
338 if(prev_name.endsWith('_count')) {
339 new_name = prev_name.replace('_count','__{{repeater_sub_suffix}}_count');
340 }
341
342 $this.attr('name', new_name);
343 $this.attr('data-orig_name', orig_name);
344 $this.closest('.wpcf7-form-control-wrap').addClass(new_name);
345 });
346
347 $repeater_sub_clone.find('.wpcf7cf_repeater,[data-class="wpcf7cf_group"]').each(function() {
348 var $this = jQuery(this);
349 var prev_data_id = $this.attr('data-id');
350 var orig_data_id = $this.attr('data-orig_data_id') != null ? $this.attr('data-orig_data_id') : prev_data_id;
351 var new_data_id = prev_data_id+'__{{repeater_sub_suffix}}';
352
353 if(prev_data_id.endsWith('_count')) {
354 new_data_id = prev_data_id.replace('_count','__{{repeater_sub_suffix}}_count');
355 }
356
357 $this.attr('data-id', new_data_id);
358 $this.attr('data-orig_data_id', orig_data_id);
359 $this.closest('.wpcf7-form-control-wrap').addClass(new_data_id);
360 });
361
362 $repeater_sub_clone.find('[id]').each(function() {
363 var $this = jQuery(this);
364 var prev_id = $this.attr('id');
365 var orig_id = $this.attr('data-orig_id') != null ? $this.attr('data-orig_id') : prev_id;
366 var new_id = prev_id+'__{{repeater_sub_suffix}}';
367
368 $this.attr('id', new_id);
369 $this.attr('data-orig_id', orig_id);
370 $this.closest('.wpcf7-form-control-wrap').addClass(new_id);
371 });
372
373 $repeater_sub_clone.find('[for]').each(function() {
374 var $this = jQuery(this);
375 var prev_for = $this.attr('for');
376 var orig_for = $this.attr('data-orig_for') != null ? $this.attr('data-orig_for') : prev_for;
377 var new_for = prev_for+'__{{repeater_sub_suffix}}';
378
379 $this.attr('for', new_for);
380 $this.attr('data-orig_for', orig_for);
381 $this.closest('.wpcf7-form-control-wrap').addClass(new_for);
382 });
383
384 var repeater_sub_html = $repeater_sub_clone[0].outerHTML;
385
386 var $repeater_count_field = $repeater.find('[name='+$repeater.id+'_count]').eq(0);
387 var $button_add = $repeater_controls.find('.wpcf7cf_add').eq(0);
388 var $button_remove = $repeater_controls.find('.wpcf7cf_remove').eq(0);
389
390 var params = {
391 $repeater: $repeater,
392 $repeater_count_field: $repeater_count_field,
393 repeater_sub_html: repeater_sub_html,
394 $repeater_controls: $repeater_controls,
395 $button_add: $button_add,
396 $button_remove: $button_remove,
397 wpcf7cf_settings: wpcf7cf_settings
398 };
399
400 this.params = params;
401
402 $button_add.click( repeater, function(e) {
403 var repeater = e.data;
404 repeater.updateSubs(params.$repeater.num_subs+1);
405 });
406
407 $button_remove.click( repeater,function(e) {
408 var repeater = e.data;
409 repeater.updateSubs(params.$repeater.num_subs-1);
410 });
411
412 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).eq(0).remove(); // remove the first sub, it's just a template.
413
414 repeater.updateSubs($repeater.initial_subs);
415
416 }
417
418
419
420 Wpcf7cfRepeater.prototype.updateSubs = function(subs_to_show) {
421 var repeater = this;
422 var params = repeater.params;
423 var subs_to_add = subs_to_show - params.$repeater.num_subs;
424
425 if (subs_to_add < 0) {
426 repeater.removeSubs(-subs_to_add);
427 } else if (subs_to_add > 0) {
428 repeater.addSubs(subs_to_add);
429 }
430
431 var showButtonRemove = false;
432 var showButtonAdd = false;
433
434 if (params.$repeater.num_subs < params.$repeater.max) {
435 showButtonAdd = true;
436 }
437 if (params.$repeater.num_subs > params.$repeater.min) {
438 showButtonRemove = true;
439 }
440
441 if (showButtonAdd) {
442 params.$button_add.show();
443 } else {
444 params.$button_add.hide();
445
446 }
447
448 if (showButtonRemove) {
449 params.$button_remove.show();
450 } else {
451 params.$button_remove.hide();
452 }
453
454 params.$repeater_count_field.val(subs_to_show);
455
456 };
457 Wpcf7cfRepeater.prototype.addSubs = function(subs_to_add) {
458 var $ = jQuery;
459 var params = this.params;
460 var repeater = this;
461 var form = repeater.form;
462
463
464 var $repeater = params.$repeater;
465 var $repeater_controls = params.$repeater_controls;
466
467 //jQuery(params.repeater_sub_html.replace(/name="(.*?)"/g,'name="wpcf7cf_repeater['+$repeater.id+']['+$repeater.num_subs+'][$1]" data-original-name="$1"')).hide().insertBefore($repeater_controls).animate(wpcf7cf_show_animation, params.wpcf7cf_settings.animation_intime);
468
469 var html_str = '';
470
471 for(var i=1; i<=subs_to_add; i++) {
472 var sub_suffix = $repeater.num_subs+i;
473 html_str += params.repeater_sub_html.replace(/\{\{repeater_sub_suffix\}\}/g,sub_suffix)
474 .replace(new RegExp('\{\{'+$repeater.orig_id+'_index\}\}','g'),sub_suffix);
475 }
476
477
478 var $html = jQuery(html_str);
479
480 // Add the newly created fields to the form
481 $html.hide().insertBefore($repeater_controls).animate(wpcf7cf_show_animation, params.wpcf7cf_settings.animation_intime).trigger('wpcf7cf_repeater_added');
482
483 jQuery('.wpcf7cf_repeater', $html).each(function(){
484 form.repeaters.push(new Wpcf7cfRepeater(jQuery(this),form));
485 });
486 form.$input_repeaters.val(JSON.stringify(form.repeaters.map((item)=>item.params.$repeater.id)));
487
488 $repeater.num_subs+= subs_to_add;
489
490 window.wpcf7cf.updateMultistepState(form.multistep);
491 form.updateGroups();
492 form.updateEventListeners();
493 form.displayFields();
494
495 // Exclusive Checkbox
496 $html.on( 'click', '.wpcf7-exclusive-checkbox input:checkbox', function() {
497 var name = $( this ).attr( 'name' );
498 $html.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
499 } );
500
501 //basic compatibility with material-design-for-contact-form-7
502 if (typeof window.cf7mdInit === "function") {
503 window.cf7mdInit();
504 }
505
506 return false;
507 };
508 Wpcf7cfRepeater.prototype.removeSubs = function(num_subs) {
509 var $ = jQuery;
510 var params = this.params;
511 var form = this.form;
512
513 params.$repeater.num_subs-= num_subs;
514
515 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).slice(-num_subs).animate(wpcf7cf_hide_animation, {duration:params.wpcf7cf_settings.animation_intime, done:function() {
516 var $this = jQuery(this);
517 //remove the actual fields from the form
518 $this.remove();
519 params.$repeater.trigger('wpcf7cf_repeater_removed');
520 window.wpcf7cf.updateMultistepState(form.multistep);
521 form.updateGroups();
522 form.updateEventListeners();
523 form.displayFields();
524 }});
525
526 return false;
527 };
528
529 function Wpcf7cfMultistep($multistep, form) {
530 var multistep = this;
531 multistep.$multistep = $multistep;
532 multistep.form = form;
533 multistep.$steps = $multistep.find('.wpcf7cf_step');
534 multistep.$btn_next = $multistep.find('.wpcf7cf_next');
535 multistep.$btn_prev = $multistep.find('.wpcf7cf_prev');
536 multistep.$dots = $multistep.find('.wpcf7cf_steps-dots');
537 multistep.currentStep = 0;
538 multistep.numSteps = multistep.$steps.length;
539
540
541 multistep.$dots.html('');
542 for (var i = 1; i <= multistep.numSteps; i++) {
543 multistep.$dots.append(`
544 <div class="dot" data-step="${i}">
545 <div class="step-index">${i}</div>
546 <div class="step-title">${multistep.$steps.eq(i-1).data('title')}</div>
547 </div>
548 `);
549 }
550
551 multistep.$btn_next.on('click.wpcf7cf_step', async function() {
552
553 var result = await multistep.validateStep(multistep.currentStep);
554 if (result === 'success') {
555 multistep.moveToStep(multistep.currentStep+1);
556 }
557
558 });
559
560 // If form is submitted (by pressing retrun for example), and if we are not on the last step,
561 // then trigger click event on the $next button instead.
562 multistep.form.$form.on('submit.wpcf7cf_step', function(e) {
563
564 if (multistep.currentStep !== multistep.numSteps) {
565 multistep.$btn_next.trigger('click.wpcf7cf_step');
566
567 e.stopImmediatePropagation();
568 return false;
569 }
570 });
571
572 multistep.$btn_prev.click(function() {
573 multistep.moveToStep(multistep.currentStep-1);
574 });
575
576 multistep.moveToStep(1);
577 }
578
579 jQuery(document).ajaxComplete(function(e, xhr, settings){
580 if (
581 xhr.hasOwnProperty('responseJSON') &&
582 xhr.responseJSON != null &&
583 xhr.responseJSON.hasOwnProperty('status') &&
584 xhr.responseJSON.hasOwnProperty('into') &&
585 xhr.responseJSON.status === "mail_success"
586 ) {
587 jQuery( xhr.responseJSON.into ).trigger('reset.wpcf7cf');
588 }
589 });
590
591 Wpcf7cfMultistep.prototype.validateStep = function(step_index) {
592
593 var multistep = this;
594 var $multistep = multistep.$multistep;
595 var $form = multistep.form.$form;
596
597 $form.find('.wpcf7-response-output').addClass('wpcf7-display-none');
598
599 return new Promise(resolve => {
600
601 var fd = new FormData();
602
603 // Make sure to add file fields to FormData
604 jQuery.each($form.find('[data-id="step-'+step_index+'"] input[type="file"]'), function(index, el) {
605 if (! el.files.length) return false;
606 const file = el.files[0];
607 const fieldName = el.name;
608 fd.append(fieldName, file);
609 });
610
611 var formdata = $form.serializeArray();
612 jQuery.each(formdata,function(key, input){
613 fd.append(input.name, input.value);
614 });
615
616 jQuery.ajax({
617 url: wpcf7cf_global_settings.ajaxurl + '?action=wpcf7cf_validate_step',
618 type: 'POST',
619 data: fd,
620 processData: false,
621 contentType: false,
622 dataType: 'json',
623 }).done(function(json) {
624
625 /*
626 * Insert _form_data_id if 'json variable' has
627 */
628 // if (typeof json._cf7mls_db_form_data_id != 'undefined') {
629 // if (!form.find('input[name="_cf7mls_db_form_data_id"]').length) {
630 // form.append('<input type="hidden" name="_cf7mls_db_form_data_id" value="'+json._cf7mls_db_form_data_id+'" />');
631 // }
632 // }
633
634 //reset error messages
635 //$multistep.find('.wpcf7-form-control-wrap').removeClass('cf7mls-invalid');
636 $multistep.find('.wpcf7-form-control-wrap .wpcf7-not-valid-tip').remove();
637 $multistep.find('.wpcf7-not-valid').removeClass('wpcf7-not-valid');
638 $multistep.find('.wpcf7-response-output').remove();
639 $multistep.find('.wpcf7-response-output.wpcf7-validation-errors').removeClass('wpcf7-validation-errors');
640
641 if (!json.success) {
642 var checkError = 0;
643
644 jQuery.each(json.invalid_fields, function(index, el) {
645 if ($multistep.find('input[name="'+index+'"]').length ||
646 $multistep.find('input[name="'+index+'[]"]').length ||
647 $multistep.find('select[name="'+index+'"]').length ||
648 $multistep.find('select[name="'+index+'[]"]').length ||
649 $multistep.find('textarea[name="'+index+'"]').length ||
650 $multistep.find('textarea[name="'+index+'[]"]').length
651 ) {
652 checkError = checkError + 1;
653
654 var controlWrap = jQuery('.wpcf7-form-control-wrap.' + index, $form);
655 //controlWrap.addClass('cf7mls-invalid');
656 controlWrap.find('input').addClass('wpcf7-not-valid');
657 controlWrap.find('span.wpcf7-not-valid-tip').remove();
658 controlWrap.append('<span role="alert" class="wpcf7-not-valid-tip">' + el.reason + '</span>');
659
660 //return false;
661 }
662 });
663
664 resolve('failed');
665 //$multistep.append('<div class="wpcf7-response-output wpcf7-display-none wpcf7-validation-errors" style="display: block;" role="alert">' + json.message + '</div>');
666
667 console.log($multistep.parent().find('.wpcf7-response-output'));
668 $multistep.parent().find('.wpcf7-response-output').removeClass('wpcf7-display-none').html(json.message);
669
670 } else if (json.success) {
671 resolve('success');
672 return false;
673 }
674
675 }).fail(function() {
676 resolve('error');
677 }).always(function() {
678 // do nothing
679 });
680 });
681
682 };
683 Wpcf7cfMultistep.prototype.moveToStep = function(step_index) {
684 var multistep = this;
685 var previousStep = multistep.currentStep;
686
687 multistep.currentStep = step_index > multistep.numSteps ? multistep.numSteps
688 : step_index < 1 ? 1
689 : step_index;
690
691 // ANIMATION DISABLED FOR NOW cause it's ugly
692 // multistep.$steps.animate(wpcf7cf_hide_step_animation, multistep.form.settings.animation_outtime);
693 // multistep.$steps.eq(multistep.currentStep-1).animate(wpcf7cf_show_step_animation, multistep.form.settings.animation_intime);
694
695 multistep.$multistep.attr('data-current_step', multistep.currentStep);
696 multistep.$steps.hide();
697 multistep.$steps
698 .eq(multistep.currentStep-1)
699 .show()
700 .trigger('wpcf7cf_change_step', [previousStep, multistep.currentStep]);
701
702 const formEl = multistep.form.$form[0];
703 const topOffset = formEl.getBoundingClientRect().top;
704 if (topOffset < 0 && previousStep > 0) {
705 formEl.scrollIntoView({behavior: "smooth"});
706 }
707
708 multistep.form.updateSummaryFields();
709
710 window.wpcf7cf.updateMultistepState(multistep);
711 };
712
713 Wpcf7cfMultistep.prototype.getFieldsInStep = function(step_index) {
714 var simpleDom = window.wpcf7cf.get_simplified_dom_model(this.form.$form);
715 var inStep = false;
716 return simpleDom.filter(function(item, i) {
717 if(item.type == 'step') {
718 inStep = item.step == step_index+'';
719 }
720 return inStep && item.type == 'input';
721 }).map(function(item) {
722 return item.name;
723 });
724 };
725
726 // END PRO ONLY
727
728 window.wpcf7cf = {
729
730 // keep this for backwards compatibility
731 initForm : function($form) {
732 wpcf7cf_forms.push(new Wpcf7cfForm($form));
733 },
734
735 get_nested_conditions : function(conditions, $current_form) {
736 //loop trough conditions. Then loop trough the dom, and each repeater we pass we should update all sub_values we encounter with __index
737 var simplified_dom = window.wpcf7cf.get_simplified_dom_model($current_form);
738 var groups = simplified_dom.filter(function(item, i) {
739 return item.type==='group';
740 });
741
742 var sub_conditions = [];
743
744 for(var i = 0; i < groups.length; i++) {
745 var g = groups[i];
746 var relevant_conditions = conditions.filter(function(condition, i) {
747 return condition.then_field === g.original_name;
748 });
749
750 var relevant_conditions = relevant_conditions.map(function(item,i) {
751 return {
752 then_field : g.name,
753 and_rules : item.and_rules.map(function(and_rule, i) {
754 return {
755 if_field : and_rule.if_field+g.suffix,
756 if_value : and_rule.if_value,
757 operator : and_rule.operator
758 };
759 })
760 }
761 });
762
763 sub_conditions = sub_conditions.concat(relevant_conditions);
764 }
765 return conditions.concat(sub_conditions);
766 },
767
768 get_simplified_dom_model : function($current_form) {
769 // if the dom is something like:
770 // <form>
771 // <repeater ra>
772 // <group ga__1>
773 // <repeater rb__1>
774 // <input txta__1__1 />
775 // <input txta__1__2 />
776 // </repeater>
777 // <group gb__1>
778 // <input txtb__1 />
779 // </group>
780 // </group>
781 // <group ga__2>
782 // <repeater rb__2>
783 // <input txta__2__1 />
784 // </repeater>
785 // <group gb__2>
786 // <input txtb__2 />
787 // </group>
788 // </group>
789 // </repeater>
790 // </form>
791 //
792 // return something like:
793 // [{type:repeater, name:'ra', suffix: '__1'}, {type: group, name:'ga', suffix: '__1'}, ...]
794
795 var currentNode;
796 var ni = document.createNodeIterator($current_form[0], NodeFilter.SHOW_ELEMENT, null, false); //, NodeFilter.SHOW_ELEMENT, function(){ return NodeFilter.FILTER_ACCEPT; }
797
798 var simplified_dom = [];
799
800 while(currentNode = ni.nextNode()) {
801 if (currentNode.classList.contains('wpcf7cf_repeater')) {
802 simplified_dom.push({type:'repeater', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
803 } else if (currentNode.dataset.class == 'wpcf7cf_group') {
804 simplified_dom.push({type:'group', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
805 } else if (currentNode.className == 'wpcf7cf_step') {
806 simplified_dom.push({type:'step', name:currentNode.dataset.id, original_name:currentNode.dataset.id, step: currentNode.dataset.id.substring(5)})
807 } else if (currentNode.hasAttribute('name')) {
808 simplified_dom.push({type:'input', name:currentNode.getAttribute('name'), original_name:currentNode.getAttribute('data-orig_name')})
809 }
810 }
811
812 simplified_dom = simplified_dom.map(function(item, i){
813 var original_name_length = item.original_name == null ? item.name.length : item.original_name.length;
814 item.suffix = item.name.substring(original_name_length);
815 return item;
816 });
817
818 //console.table(simplified_dom);
819 return simplified_dom;
820
821 },
822
823 updateMultistepState: function (multistep) {
824 if (multistep == null) return;
825
826 // update hidden input field
827
828 var stepsData = {
829 currentStep : multistep.currentStep,
830 numSteps : multistep.numSteps,
831 fieldsInCurrentStep : multistep.getFieldsInStep(multistep.currentStep)
832 };
833 multistep.form.$input_steps.val(JSON.stringify(stepsData));
834
835 // update Buttons
836 multistep.$btn_prev.removeClass('disabled');
837 multistep.$btn_next.removeClass('disabled');
838 if (multistep.currentStep == multistep.numSteps) {
839 multistep.$btn_next.addClass('disabled');
840 }
841 if (multistep.currentStep == 1) {
842 multistep.$btn_prev.addClass('disabled');
843 }
844
845 // replace next button with submit button on last step.
846 // TODO: make this depend on a setting
847 var $submit_button = multistep.form.$form.find('input[type="submit"]').eq(0);
848 var $ajax_loader = multistep.form.$form.find('.ajax-loader').eq(0);
849 if (multistep.currentStep == multistep.numSteps) {
850 multistep.$btn_next.hide();
851 $ajax_loader.detach().appendTo(multistep.$btn_next.parent());
852 $submit_button.detach().appendTo(multistep.$btn_next.parent());
853 $submit_button.show();
854 } else {
855 $submit_button.hide();
856 multistep.$btn_next.show();
857 }
858
859 // update dots
860 var $dots = multistep.$dots.find('.dot');
861 $dots.removeClass('active').removeClass('completed');
862 for(var step = 1; step <= multistep.numSteps; step++) {
863 if (step < multistep.currentStep) {
864 $dots.eq(step-1).addClass('completed');
865 } else if (step == multistep.currentStep) {
866 $dots.eq(step-1).addClass('active');
867 }
868 }
869
870 },
871
872 should_group_be_shown : function(condition, $current_form) {
873
874 var $ = jQuery;
875
876 var show_group = true;
877
878 for (var and_rule_i = 0; and_rule_i < condition.and_rules.length; and_rule_i++) {
879
880 var condition_ok = false;
881
882 var condition_and_rule = condition.and_rules[and_rule_i];
883
884 var $field = jQuery('[name="' + condition_and_rule.if_field + '"], [name="' + condition_and_rule.if_field + '[]"], [data-original-name="' + condition_and_rule.if_field + '"], [data-original-name="' + condition_and_rule.if_field + '[]"]',$current_form);
885
886 var if_val = condition_and_rule.if_value;
887 var if_val_as_number = isFinite(parseFloat(if_val)) ? parseFloat(if_val):0;
888 var operator = condition_and_rule.operator;
889
890 var regex_patt = /.*/i; // fallback regex pattern
891 var isValidRegex = true;
892 try {
893 regex_patt = new RegExp(if_val, 'i');
894 } catch(e) {
895 isValidRegex = false;
896 }
897
898
899 //backwards compat
900 operator = operator === '' ? 'less than or equals' : operator;
901 operator = operator === '' ? 'greater than or equals' : operator;
902 operator = operator === '>' ? 'greater than' : operator;
903 operator = operator === '<' ? 'less than' : operator;
904
905
906 if ( $field.is(':checkbox') || $field.is(':radio') ) {
907
908 var all_values = [];
909 var checked_values = [];
910 $field.each(function () {
911 all_values.push(jQuery(this).val());
912 if (jQuery(this).is(':checked')) {
913 checked_values.push(jQuery(this).val());
914 }
915 });
916
917 condition_ok = this.isConditionTrue(checked_values,operator,if_val,$field);
918
919 } else {
920
921 condition_ok = this.isConditionTrue($field.val(),operator,if_val,$field);
922 }
923
924 show_group = show_group && condition_ok;
925 }
926
927 return show_group;
928
929 },
930 isConditionTrue(values, operator, testValue='', $field=jQuery()) {
931
932 if (!Array.isArray(values)) {
933 values = [values];
934 }
935
936 let condition_ok = false; // start by assuming that the condition is not met
937
938 if (!values || values.length == 0 || values.every((v) => !v||0)) { // no values or only empty values passed (0 is not considered empty)
939 if (operator === 'is empty') {
940 condition_ok = true;
941 }
942 if (operator === 'not empty') {
943 condition_ok = false;
944 }
945 } else {
946 if (operator === 'is empty') {
947 condition_ok = false;
948 }
949 if (operator === 'not empty') {
950 condition_ok = true;
951 }
952 }
953
954 const testValueNumber = isFinite(parseFloat(testValue)) ? parseFloat(testValue) : NaN;
955
956
957 if (operator === 'not equals' || operator === 'not equals (regex)') {
958 // start by assuming that the condition is met
959 condition_ok = true;
960 }
961
962 if (
963 operator === 'function'
964 && typeof window[testValue] == 'function'
965 && window[testValue]($field) // here we call the actual user defined function
966 ) {
967 condition_ok = true;
968 }
969
970 let regex_patt = /.*/i; // fallback regex pattern
971 let isValidRegex = true;
972 if (operator === 'equals (regex)' || operator === 'not equals (regex)') {
973 try {
974 regex_patt = new RegExp(testValue, 'i');
975 } catch(e) {
976 isValidRegex = false;
977 }
978 }
979
980
981 for(let i = 0; i < values.length; i++) {
982
983 const value = values[i];
984
985 const valueNumber = isFinite(parseFloat(value)) ? parseFloat(value) : NaN;
986 const valsAreNumbers = !isNaN(valueNumber) && !isNaN(testValueNumber);
987
988 if (
989
990 operator === 'equals' && value === testValue ||
991 operator === 'equals (regex)' && regex_patt.test(value) ||
992 operator === 'greater than' && valsAreNumbers && valueNumber > testValueNumber ||
993 operator === 'less than' && valsAreNumbers && valueNumber < testValueNumber ||
994 operator === 'greater than or equals' && valsAreNumbers && valueNumber >= testValueNumber ||
995 operator === 'less than or equals' && valsAreNumbers && valueNumber <= testValueNumber
996
997 ) {
998
999 condition_ok = true;
1000 break;
1001
1002 } else if (
1003
1004 operator === 'not equals' && value === testValue ||
1005 operator === 'not equals (regex)' && regex_patt.test(value)
1006
1007 ) {
1008
1009 condition_ok = false;
1010 break;
1011
1012 }
1013 }
1014
1015 return condition_ok;
1016
1017 }
1018
1019 };
1020
1021
1022
1023
1024 jQuery('.wpcf7-form').each(function(){
1025 wpcf7cf_forms.push(new Wpcf7cfForm(jQuery(this)));
1026 });
1027
1028 // Call displayFields again on all forms
1029 // Necessary in case some theme or plugin changed a form value by the time the entire page is fully loaded.
1030 jQuery('document').ready(function() {
1031 wpcf7cf_forms.forEach(function(f){
1032 f.displayFields();
1033 });
1034 });
1035
1036 // fix for exclusive checkboxes in IE (this will call the change-event again after all other checkboxes are unchecked, triggering the display_fields() function)
1037 var old_wpcf7ExclusiveCheckbox = jQuery.fn.wpcf7ExclusiveCheckbox;
1038 jQuery.fn.wpcf7ExclusiveCheckbox = function() {
1039 return this.find('input:checkbox').click(function() {
1040 var name = jQuery(this).attr('name');
1041 jQuery(this).closest('form').find('input:checkbox[name="' + name + '"]').not(this).prop('checked', false).eq(0).change();
1042 });
1043 };
1044
1045