PluginProbe ʕ •ᴥ•ʔ
Conditional Fields for Contact Form 7 / 1.8
Conditional Fields for Contact Form 7 v1.8
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
946 lines
1 "use strict";
2
3 var cf7signature_resized = 0; // for compatibility with contact-form-7-signature-addon
4
5 var wpcf7cf_timeout;
6
7 var wpcf7cf_show_animation = { "height": "show", "marginTop": "show", "marginBottom": "show", "paddingTop": "show", "paddingBottom": "show" };
8 var wpcf7cf_hide_animation = { "height": "hide", "marginTop": "hide", "marginBottom": "hide", "paddingTop": "hide", "paddingBottom": "hide" };
9
10 var wpcf7cf_show_step_animation = { "opacity": "show" };
11 var wpcf7cf_hide_step_animation = { "opacity": "hide" };
12
13 var wpcf7cf_change_events = 'input.wpcf7cf paste.wpcf7cf change.wpcf7cf click.wpcf7cf propertychange.wpcf7cf';
14
15 var wpcf7cf_forms = [];
16
17 // endswith polyfill
18 if (!String.prototype.endsWith) {
19 String.prototype.endsWith = function(search, this_len) {
20 if (this_len === undefined || this_len > this.length) {
21 this_len = this.length;
22 }
23 return this.substring(this_len - search.length, this_len) === search;
24 };
25 }
26
27 var Wpcf7cfForm = function($form) {
28
29 var options_element = $form.find('input[name="_wpcf7cf_options"]').eq(0);
30 if (!options_element.length || !options_element.val()) {
31 // doesn't look like a CF7 form created with conditional fields plugin enabled.
32 return false;
33 }
34
35 var form = this;
36
37 var form_options = JSON.parse(options_element.val());
38
39 form.$form = $form;
40 form.$input_hidden_group_fields = $form.find('[name="_wpcf7cf_hidden_group_fields"]');
41 form.$input_hidden_groups = $form.find('[name="_wpcf7cf_hidden_groups"]');
42 form.$input_visible_groups = $form.find('[name="_wpcf7cf_visible_groups"]');
43 form.$input_repeaters = $form.find('[name="_wpcf7cf_repeaters"]');
44 form.$input_steps = $form.find('[name="_wpcf7cf_steps"]');
45
46 form.unit_tag = $form.closest('.wpcf7').attr('id');
47 form.conditions = form_options['conditions'];
48
49 // compatibility with conditional forms created with older versions of the plugin ( < 1.4 )
50 for (var i=0; i < form.conditions.length; i++) {
51 var condition = form.conditions[i];
52 if (!('and_rules' in condition)) {
53 condition.and_rules = [{'if_field':condition.if_field,'if_value':condition.if_value,'operator':condition.operator}];
54 }
55 }
56
57 form.initial_conditions = form.conditions;
58 form.settings = form_options['settings'];
59
60 form.$groups = jQuery(); // empty jQuery set
61 form.repeaters = [];
62 form.multistep = null;
63 form.fields = [];
64
65 form.settings.animation_intime = parseInt(form.settings.animation_intime);
66 form.settings.animation_outtime = parseInt(form.settings.animation_outtime);
67
68 if (form.settings.animation === 'no') {
69 form.settings.animation_intime = 0;
70 form.settings.animation_outtime = 0;
71 }
72
73 form.updateGroups();
74 form.updateEventListeners();
75 form.displayFields();
76
77 // bring form in initial state if the reset event is fired on it.
78 form.$form.on('reset', form, function(e) {
79 var form = e.data;
80 setTimeout(function(){
81 form.displayFields();
82 },200);
83 });
84
85 // PRO ONLY
86
87 jQuery('.wpcf7cf_repeater:not(.wpcf7cf_repeater .wpcf7cf_repeater)', $form).each(function(){
88 form.repeaters.push(new Wpcf7cfRepeater(jQuery(this),form));
89 });
90
91 form.$input_repeaters.val(JSON.stringify(form.repeaters.map((item)=>item.params.$repeater.id)));
92
93 var $multistep = jQuery('.wpcf7cf_multistep', $form);
94
95 if ($multistep.length) {
96 form.multistep = new Wpcf7cfMultistep($multistep, form);
97 // window.wpcf7cf.updateMultistepState(form.multistep);
98 }
99
100 // END PRO ONLY
101
102 }
103 Wpcf7cfForm.prototype.displayFields = function() {
104
105 var form = this;
106
107 window.wpcf7cf.get_simplified_dom_model(form.$form);
108
109 var unit_tag = this.unit_tag;
110 var wpcf7cf_conditions = this.conditions;
111 var wpcf7cf_settings = this.settings;
112
113 //for compatibility with contact-form-7-signature-addon
114 if (cf7signature_resized === 0 && typeof signatures !== 'undefined' && signatures.constructor === Array && signatures.length > 0 ) {
115 for (var i = 0; i < signatures.length; i++) {
116 if (signatures[i].canvas.width === 0) {
117
118 var $sig_canvas = jQuery(".wpcf7-form-control-signature-body>canvas");
119 var $sig_wrap = jQuery(".wpcf7-form-control-signature-wrap");
120 $sig_canvas.eq(i).attr('width', $sig_wrap.width());
121 $sig_canvas.eq(i).attr('height', $sig_wrap.height());
122
123 cf7signature_resized = 1;
124 }
125 }
126 }
127
128 form.$groups.addClass('wpcf7cf-hidden');
129
130 for (var i=0; i < wpcf7cf_conditions.length; i++) {
131
132 var condition = wpcf7cf_conditions[i];
133
134 var show_group = window.wpcf7cf.should_group_be_shown(condition, form.$form);
135
136 if (show_group) {
137 jQuery('[data-id='+condition.then_field+']',form.$form).eq(0).removeClass('wpcf7cf-hidden');
138 }
139 }
140
141 var animation_intime = wpcf7cf_settings.animation_intime;
142 var animation_outtime = wpcf7cf_settings.animation_outtime;
143
144 form.$groups.each(function (index) {
145 var $group = jQuery(this);
146 if ($group.is(':animated')) $group.finish(); // stop any current animations on the group
147 if ($group.css('display') === 'none' && !$group.hasClass('wpcf7cf-hidden')) {
148 if ($group.prop('tagName') === 'SPAN') {
149 $group.show().trigger('wpcf7cf_show_group');
150 } else {
151 $group.animate(wpcf7cf_show_animation, animation_intime).trigger('wpcf7cf_show_group'); // show
152 }
153 } else if ($group.css('display') !== 'none' && $group.hasClass('wpcf7cf-hidden')) {
154
155 if ($group.attr('data-clear_on_hide') !== undefined) {
156 var $inputs = jQuery(':input', $group).not(':button, :submit, :reset, :hidden');
157
158 $inputs.each(function(){
159 var $this = jQuery(this);
160 $this.val(this.defaultValue);
161 $this.prop('checked', this.defaultChecked);
162 });
163
164 $inputs.change();
165 //display_fields();
166 }
167
168 if ($group.prop('tagName') === 'SPAN') {
169 $group.hide().trigger('wpcf7cf_hide_group');
170 } else {
171 $group.animate(wpcf7cf_hide_animation, animation_outtime).trigger('wpcf7cf_hide_group'); // hide
172 }
173
174 }
175 });
176
177 form.updateHiddenFields();
178 };
179 Wpcf7cfForm.prototype.updateHiddenFields = function() {
180
181 var form = this;
182
183 var hidden_fields = [];
184 var hidden_groups = [];
185 var visible_groups = [];
186
187 form.$groups.each(function () {
188 var $this = jQuery(this);
189 if ($this.hasClass('wpcf7cf-hidden')) {
190 hidden_groups.push($this.data('id'));
191 $this.find('input,select,textarea').each(function () {
192 hidden_fields.push(jQuery(this).attr('name'));
193 });
194 } else {
195 visible_groups.push($this.data('id'));
196 }
197 });
198
199 form.hidden_fields = hidden_fields;
200 form.hidden_groups = hidden_groups;
201 form.visible_groups = visible_groups;
202
203 form.$input_hidden_group_fields.val(JSON.stringify(hidden_fields));
204 form.$input_hidden_groups.val(JSON.stringify(hidden_groups));
205 form.$input_visible_groups.val(JSON.stringify(visible_groups));
206
207 return true;
208 };
209 Wpcf7cfForm.prototype.updateGroups = function() {
210 var form = this;
211 form.$groups = form.$form.find('[data-class="wpcf7cf_group"]');
212
213 form.conditions = window.wpcf7cf.get_nested_conditions(form.initial_conditions, form.$form);
214
215 };
216 Wpcf7cfForm.prototype.updateEventListeners = function() {
217
218 var form = this;
219
220 // monitor input changes, and call display_fields() if something has changed
221 jQuery('input, select, textarea, button',form.$form).not('.wpcf7cf_add, .wpcf7cf_remove').off(wpcf7cf_change_events).on(wpcf7cf_change_events,form, function(e) {
222 var form = e.data;
223 clearTimeout(wpcf7cf_timeout);
224 wpcf7cf_timeout = setTimeout(function() {
225 form.displayFields();
226 }, 100);
227 });
228
229 // PRO ONLY
230 jQuery('.wpcf7cf-togglebutton', form.$form).off('click.toggle_wpcf7cf').on('click.toggle_wpcf7cf',function() {
231 var $this = jQuery(this);
232 if ($this.text() === $this.data('val-1')) {
233 $this.text($this.data('val-2'));
234 $this.val($this.data('val-2'));
235 } else {
236 $this.text($this.data('val-1'));
237 $this.val($this.data('val-1'));
238 }
239 });
240 // END PRO ONLY
241 };
242
243 // PRO ONLY
244 function Wpcf7cfRepeater($repeater, form) {
245 var $ = jQuery;
246
247 var repeater = this;
248
249 var wpcf7cf_settings = form.settings;
250
251 repeater.form = form;
252
253 $repeater.num_subs = 0;
254 $repeater.id = $repeater.data('id');
255 $repeater.orig_id = $repeater.data('orig_data_id');
256 $repeater.min = typeof( $repeater.data('min')) !== 'undefined' ? parseInt($repeater.data('min')) : 1;
257 $repeater.max = typeof( $repeater.data('max')) !== 'undefined' ? parseInt($repeater.data('max')) : 200;
258 $repeater.initial_subs = typeof( $repeater.data('initial')) !== 'undefined' ? parseInt($repeater.data('initial')) : $repeater.min;
259 if ($repeater.initial_subs > $repeater.max) $repeater.initial_subs = $repeater.max;
260 var $repeater_sub = $repeater.children('.wpcf7cf_repeater_sub').eq(0);
261 var $repeater_controls = $repeater.children('.wpcf7cf_repeater_controls').eq(0);
262
263 var $repeater_sub_clone = $repeater_sub.clone();
264
265 $repeater_sub_clone.find('.wpcf7cf_repeater_sub').addBack('.wpcf7cf_repeater_sub').each(function() {
266 var $this = jQuery(this);
267 var prev_suffix = $this.attr('data-repeater_sub_suffix');
268 var new_suffix = prev_suffix+'__{{repeater_sub_suffix}}';
269 $this.attr('data-repeater_sub_suffix', new_suffix);
270 });
271
272 $repeater_sub_clone.find('[name]').each(function() {
273 var $this = jQuery(this);
274 var prev_name = $this.attr('name');
275 var orig_name = $this.attr('data-orig_name') != null ? $this.attr('data-orig_name') : prev_name;
276 var new_name = prev_name+'__{{repeater_sub_suffix}}';
277
278 if(prev_name.endsWith('_count')) {
279 new_name = prev_name.replace('_count','__{{repeater_sub_suffix}}_count');
280 }
281
282 $this.attr('name', new_name);
283 $this.attr('data-orig_name', orig_name);
284 $this.closest('.wpcf7-form-control-wrap').addClass(new_name);
285 });
286
287 $repeater_sub_clone.find('.wpcf7cf_repeater,[data-class="wpcf7cf_group"]').each(function() {
288 var $this = jQuery(this);
289 var prev_data_id = $this.attr('data-id');
290 var orig_data_id = $this.attr('data-orig_data_id') != null ? $this.attr('data-orig_data_id') : prev_data_id;
291 var new_data_id = prev_data_id+'__{{repeater_sub_suffix}}';
292
293 if(prev_data_id.endsWith('_count')) {
294 new_data_id = prev_data_id.replace('_count','__{{repeater_sub_suffix}}_count');
295 }
296
297 $this.attr('data-id', new_data_id);
298 $this.attr('data-orig_data_id', orig_data_id);
299 $this.closest('.wpcf7-form-control-wrap').addClass(new_data_id);
300 });
301
302 $repeater_sub_clone.find('[id]').each(function() {
303 var $this = jQuery(this);
304 var prev_id = $this.attr('id');
305 var orig_id = $this.attr('data-orig_id') != null ? $this.attr('data-orig_id') : prev_id;
306 var new_id = prev_id+'__{{repeater_sub_suffix}}';
307
308 $this.attr('id', new_id);
309 $this.attr('data-orig_id', orig_id);
310 $this.closest('.wpcf7-form-control-wrap').addClass(new_id);
311 });
312
313 $repeater_sub_clone.find('[for]').each(function() {
314 var $this = jQuery(this);
315 var prev_for = $this.attr('for');
316 var orig_for = $this.attr('data-orig_for') != null ? $this.attr('data-orig_for') : prev_for;
317 var new_for = prev_for+'__{{repeater_sub_suffix}}';
318
319 $this.attr('for', new_for);
320 $this.attr('data-orig_for', orig_for);
321 $this.closest('.wpcf7-form-control-wrap').addClass(new_for);
322 });
323
324 var repeater_sub_html = $repeater_sub_clone[0].outerHTML;
325
326 var $repeater_count_field = $repeater.find('[name='+$repeater.id+'_count]').eq(0);
327 var $button_add = $repeater_controls.find('.wpcf7cf_add').eq(0);
328 var $button_remove = $repeater_controls.find('.wpcf7cf_remove').eq(0);
329
330 var params = {
331 $repeater: $repeater,
332 $repeater_count_field: $repeater_count_field,
333 repeater_sub_html: repeater_sub_html,
334 $repeater_controls: $repeater_controls,
335 $button_add: $button_add,
336 $button_remove: $button_remove,
337 wpcf7cf_settings: wpcf7cf_settings
338 };
339
340 this.params = params;
341
342 $button_add.click( repeater, function(e) {
343 var repeater = e.data;
344 repeater.updateSubs(params.$repeater.num_subs+1);
345 });
346
347 $button_remove.click( repeater,function(e) {
348 var repeater = e.data;
349 repeater.updateSubs(params.$repeater.num_subs-1);
350 });
351
352 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).eq(0).remove(); // remove the first sub, it's just a template.
353
354 repeater.updateSubs($repeater.initial_subs);
355
356 }
357
358
359
360 Wpcf7cfRepeater.prototype.updateSubs = function(subs_to_show) {
361 var repeater = this;
362 var params = repeater.params;
363 var subs_to_add = subs_to_show - params.$repeater.num_subs;
364
365 if (subs_to_add < 0) {
366 repeater.removeSubs(-subs_to_add);
367 } else if (subs_to_add > 0) {
368 repeater.addSubs(subs_to_add);
369 }
370
371 var showButtonRemove = false;
372 var showButtonAdd = false;
373
374 if (params.$repeater.num_subs < params.$repeater.max) {
375 showButtonAdd = true;
376 }
377 if (params.$repeater.num_subs > params.$repeater.min) {
378 showButtonRemove = true;
379 }
380
381 if (showButtonAdd) {
382 params.$button_add.show();
383 } else {
384 params.$button_add.hide();
385
386 }
387
388 if (showButtonRemove) {
389 params.$button_remove.show();
390 } else {
391 params.$button_remove.hide();
392 }
393
394 params.$repeater_count_field.val(subs_to_show);
395
396 };
397 Wpcf7cfRepeater.prototype.addSubs = function(subs_to_add) {
398 var $ = jQuery;
399 var params = this.params;
400 var repeater = this;
401 var form = repeater.form;
402
403
404 var $repeater = params.$repeater;
405 var $repeater_controls = params.$repeater_controls;
406
407 //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);
408
409 var html_str = '';
410
411 for(var i=1; i<=subs_to_add; i++) {
412 var sub_suffix = $repeater.num_subs+i;
413 html_str += params.repeater_sub_html.replace(/\{\{repeater_sub_suffix\}\}/g,sub_suffix)
414 .replace(new RegExp('\{\{'+$repeater.orig_id+'_index\}\}','g'),sub_suffix);
415 }
416
417
418 var $html = jQuery(html_str);
419
420 // Add the newly created fields to the form
421 $html.hide().insertBefore($repeater_controls).animate(wpcf7cf_show_animation, params.wpcf7cf_settings.animation_intime).trigger('wpcf7cf_repeater_added');
422
423 jQuery('.wpcf7cf_repeater', $html).each(function(){
424 form.repeaters.push(new Wpcf7cfRepeater(jQuery(this),form));
425 });
426 form.$input_repeaters.val(JSON.stringify(form.repeaters.map((item)=>item.params.$repeater.id)));
427
428 $repeater.num_subs+= subs_to_add;
429
430 window.wpcf7cf.updateMultistepState(form.multistep);
431 form.updateGroups();
432 form.updateEventListeners();
433 form.displayFields();
434
435 // Exclusive Checkbox
436 $html.on( 'click', '.wpcf7-exclusive-checkbox input:checkbox', function() {
437 var name = $( this ).attr( 'name' );
438 $html.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
439 } );
440
441 //basic compatibility with material-design-for-contact-form-7
442 if (typeof window.cf7mdInit === "function") {
443 window.cf7mdInit();
444 }
445
446 return false;
447 };
448 Wpcf7cfRepeater.prototype.removeSubs = function(num_subs) {
449 var $ = jQuery;
450 var params = this.params;
451 var form = this.form;
452
453 params.$repeater.num_subs-= num_subs;
454
455 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).slice(-num_subs).animate(wpcf7cf_hide_animation, {duration:params.wpcf7cf_settings.animation_intime, done:function() {
456 var $this = jQuery(this);
457 //remove the actual fields from the form
458 $this.remove();
459 params.$repeater.trigger('wpcf7cf_repeater_removed');
460 window.wpcf7cf.updateMultistepState(form.multistep);
461 form.updateGroups();
462 form.updateEventListeners();
463 form.displayFields();
464 }});
465
466 return false;
467 };
468
469 function Wpcf7cfMultistep($multistep, form) {
470 var multistep = this;
471 multistep.$multistep = $multistep;
472 multistep.form = form;
473 multistep.$steps = $multistep.find('.wpcf7cf_step');
474 multistep.$btn_next = $multistep.find('.wpcf7cf_next');
475 multistep.$btn_prev = $multistep.find('.wpcf7cf_prev');
476 multistep.$dots = $multistep.find('.wpcf7cf_steps-dots');
477 multistep.current_step = 0;
478 multistep.numSteps = multistep.$steps.length;
479
480
481 multistep.$dots.html('');
482 for (var i = 1; i <= multistep.numSteps; i++) {
483 multistep.$dots.append(`
484 <div class="dot" data-step="${i}">
485 <div class="step-index">${i}</div>
486 <div class="step-title">${multistep.$steps.eq(i-1).data('title')}</div>
487 </div>
488 `);
489 }
490
491 multistep.$btn_next.on('click.wpcf7cf_step', async function() {
492
493 var result = await multistep.validateStep(multistep.current_step);
494 console.log('got this result: ' + result);
495 if (result === 'success') {
496 multistep.moveToStep(multistep.current_step+1);
497 }
498 });
499
500 multistep.$btn_prev.click(function() {
501 multistep.moveToStep(multistep.current_step-1);
502 });
503
504 multistep.moveToStep(1);
505 }
506
507 Wpcf7cfMultistep.prototype.validateStep = function(step_index) {
508
509 return new Promise(resolve => {
510 var multistep = this;
511 var $multistep = multistep.$multistep;
512
513 //validation
514 var $form = multistep.form.$form;
515
516 var fd = new FormData();
517
518 // TEST IF FILES UPLOADS WORK? THEN REMOVE THIS
519 // jQuery.each($form.find('[data-id="step'+step_index+'"] input[type="file"]'), function(index, el) {
520 // fd.append(jQuery(el).attr('name'), jQuery(el)[0].files[0]);
521 // });
522
523 var formdata = $form.serializeArray();
524 jQuery.each(formdata,function(key, input){
525 fd.append(input.name, input.value);
526 });
527
528 jQuery.ajax({
529 url: wpcf7cf_global_settings.ajaxurl + '?action=wpcf7cf_validate_step',
530 type: 'POST',
531 data: fd,
532 processData: false,
533 contentType: false,
534 dataType: 'json',
535 }).done(function(json) {
536
537 /*
538 * Insert _form_data_id if 'json variable' has
539 */
540 if (typeof json._cf7mls_db_form_data_id != 'undefined') {
541 if (!form.find('input[name="_cf7mls_db_form_data_id"]').length) {
542 form.append('<input type="hidden" name="_cf7mls_db_form_data_id" value="'+json._cf7mls_db_form_data_id+'" />');
543 }
544 }
545
546 //reset error messages
547 $multistep.find('.wpcf7-form-control-wrap').removeClass('cf7mls-invalid');
548 $multistep.find('.wpcf7-form-control-wrap .wpcf7-not-valid-tip').remove();
549 $multistep.find('.wpcf7-response-output').remove();
550 $multistep.find('.wpcf7-response-output.wpcf7-validation-errors').removeClass('wpcf7-validation-errors');
551
552 if (!json.success) {
553 var checkError = 0;
554
555 jQuery.each(json.invalid_fields, function(index, el) {
556 if ($multistep.find('input[name="'+index+'"]').length ||
557 $multistep.find('input[name="'+index+'[]"]').length ||
558 $multistep.find('select[name="'+index+'"]').length ||
559 $multistep.find('select[name="'+index+'[]"]').length ||
560 $multistep.find('textarea[name="'+index+'"]').length ||
561 $multistep.find('textarea[name="'+index+'[]"]').length
562 ) {
563 checkError = checkError + 1;
564
565 var controlWrap = jQuery('.wpcf7-form-control-wrap.' + index, $form);
566 controlWrap.addClass('cf7mls-invalid');
567 controlWrap.find('span.wpcf7-not-valid-tip').remove();
568 controlWrap.append('<span role="alert" class="wpcf7-not-valid-tip">' + el.reason + '</span>');
569
570 //return false;
571 }
572 });
573
574 resolve('failed');
575 $multistep.append('<div class="wpcf7-response-output wpcf7-display-none wpcf7-validation-errors" style="display: block;" role="alert">' + json.message + '</div>');
576
577 } else if (json.success) {
578 resolve('success');
579 return false;
580 }
581
582 }).fail(function() {
583 resolve('error');
584 }).always(function() {
585 // do nothing
586 });
587 });
588
589 };
590 Wpcf7cfMultistep.prototype.moveToStep = function(step_index) {
591 var multistep = this;
592 var previousStep = multistep.current_step;
593
594 multistep.current_step = step_index > multistep.numSteps ? multistep.numSteps
595 : step_index < 1 ? 1
596 : step_index;
597
598 // ANIMATION DISABLED FOR NOW cause it's ugly
599 // multistep.$steps.animate(wpcf7cf_hide_step_animation, multistep.form.settings.animation_outtime);
600 // multistep.$steps.eq(multistep.current_step-1).animate(wpcf7cf_show_step_animation, multistep.form.settings.animation_intime);
601
602 multistep.$multistep.attr('data-current_step', multistep.current_step);
603 multistep.$steps.hide();
604 multistep.$steps.eq(multistep.current_step-1).show().trigger('wpcf7cf_change_step', [previousStep, multistep.current_step]); // change step;
605
606 window.wpcf7cf.updateMultistepState(multistep);
607 };
608
609 Wpcf7cfMultistep.prototype.getFieldsInStep = function(step_index) {
610 var simpleDom = window.wpcf7cf.get_simplified_dom_model(this.form.$form);
611 var inStep = false;
612 return simpleDom.filter(function(item, i) {
613 if(item.type == 'step') {
614 inStep = item.step == step_index+'';
615 }
616 return inStep && item.type == 'input';
617 }).map(function(item) {
618 return item.name;
619 });
620 };
621
622 // END PRO ONLY
623
624 window.wpcf7cf = {
625
626 // keep this for backwards compatibility
627 initForm : function($form) {
628 wpcf7cf_forms.push(new Wpcf7cfForm($form));
629 },
630
631 get_nested_conditions : function(conditions, $current_form) {
632 //loop trough conditions. Then loop trough the dom, and each repeater we pass we should update all sub_values we encounter with __index
633 var simplified_dom = window.wpcf7cf.get_simplified_dom_model($current_form);
634 var groups = simplified_dom.filter(function(item, i) {
635 return item.type==='group';
636 });
637
638 var sub_conditions = [];
639
640 for(var i = 0; i < groups.length; i++) {
641 var g = groups[i];
642 var relevant_conditions = conditions.filter(function(condition, i) {
643 return condition.then_field === g.original_name;
644 });
645
646 var relevant_conditions = relevant_conditions.map(function(item,i) {
647 return {
648 then_field : g.name,
649 and_rules : item.and_rules.map(function(and_rule, i) {
650 return {
651 if_field : and_rule.if_field+g.suffix,
652 if_value : and_rule.if_value,
653 operator : and_rule.operator
654 };
655 })
656 }
657 });
658
659 sub_conditions = sub_conditions.concat(relevant_conditions);
660 }
661 return conditions.concat(sub_conditions);
662 },
663
664 get_simplified_dom_model : function($current_form) {
665 // if the dom is something like:
666 // <form>
667 // <repeater ra>
668 // <group ga__1>
669 // <repeater rb__1>
670 // <input txta__1__1 />
671 // <input txta__1__2 />
672 // </repeater>
673 // <group gb__1>
674 // <input txtb__1 />
675 // </group>
676 // </group>
677 // <group ga__2>
678 // <repeater rb__2>
679 // <input txta__2__1 />
680 // </repeater>
681 // <group gb__2>
682 // <input txtb__2 />
683 // </group>
684 // </group>
685 // </repeater>
686 // </form>
687 //
688 // return something like:
689 // [{type:repeater, name:'ra', suffix: '__1'}, {type: group, name:'ga', suffix: '__1'}, ...]
690
691 var currentNode;
692 var ni = document.createNodeIterator($current_form[0], NodeFilter.SHOW_ELEMENT, null, false); //, NodeFilter.SHOW_ELEMENT, function(){ return NodeFilter.FILTER_ACCEPT; }
693
694 var simplified_dom = [];
695
696 while(currentNode = ni.nextNode()) {
697 if (currentNode.classList.contains('wpcf7cf_repeater')) {
698 simplified_dom.push({type:'repeater', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
699 } else if (currentNode.dataset.class == 'wpcf7cf_group') {
700 simplified_dom.push({type:'group', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
701 } else if (currentNode.className == 'wpcf7cf_step') {
702 simplified_dom.push({type:'step', name:currentNode.dataset.id, original_name:currentNode.dataset.id, step: currentNode.dataset.id.substring(5)})
703 } else if (currentNode.hasAttribute('name')) {
704 simplified_dom.push({type:'input', name:currentNode.getAttribute('name'), original_name:currentNode.getAttribute('data-orig_name')})
705 }
706 }
707
708 simplified_dom = simplified_dom.map(function(item, i){
709 var original_name_length = item.original_name == null ? item.name.length : item.original_name.length;
710 item.suffix = item.name.substring(original_name_length);
711 return item;
712 });
713
714 //console.table(simplified_dom);
715 return simplified_dom;
716
717 },
718
719 updateMultistepState: function (multistep) {
720 if (multistep == null) return;
721
722 // update hidden input field
723
724 var stepsData = {
725 currentStep : multistep.current_step,
726 numSteps : multistep.numSteps,
727 fieldsInCurrentStep : multistep.getFieldsInStep(multistep.current_step)
728 };
729 multistep.form.$input_steps.val(JSON.stringify(stepsData));
730
731 // update Buttons
732 multistep.$btn_prev.removeClass('disabled');
733 multistep.$btn_next.removeClass('disabled');
734 if (multistep.current_step == multistep.numSteps) {
735 multistep.$btn_next.addClass('disabled');
736 }
737 if (multistep.current_step == 1) {
738 multistep.$btn_prev.addClass('disabled');
739 }
740
741 // replace next button with submit button on last step.
742 // TODO: make this depend on a setting
743 var $submit_button = multistep.form.$form.find('input[type="submit"]').eq(0);
744 if (multistep.current_step == multistep.numSteps) {
745 var $submit_clone = $submit_button.clone();
746 $submit_button.hide();
747 multistep.$btn_next.hide();
748 multistep.$btn_next.parent().append($submit_clone);
749 } else {
750 multistep.$btn_next.parent().find('input[type=submit]').remove();
751 $submit_button.show();
752 multistep.$btn_next.show();
753 }
754
755 // update dots
756 var $dots = multistep.$dots.find('.dot');
757 $dots.removeClass('active').removeClass('completed');
758 for(var step = 1; step <= multistep.numSteps; step++) {
759 if (step < multistep.current_step) {
760 $dots.eq(step-1).addClass('completed');
761 } else if (step == multistep.current_step) {
762 $dots.eq(step-1).addClass('active');
763 }
764 }
765
766 },
767
768 should_group_be_shown : function(condition, $current_form) {
769
770 var $ = jQuery;
771
772 var show_group = true;
773
774 for (var and_rule_i = 0; and_rule_i < condition.and_rules.length; and_rule_i++) {
775
776 var condition_ok = false;
777
778 var condition_and_rule = condition.and_rules[and_rule_i];
779
780 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);
781
782 var if_val = condition_and_rule.if_value;
783 var if_val_as_number = isFinite(parseFloat(if_val)) ? parseFloat(if_val):0;
784 var operator = condition_and_rule.operator;
785
786 var regex_patt = /.*/i; // fallback regex pattern
787 var isValidRegex = true;
788 try {
789 regex_patt = new RegExp(if_val, 'i');
790 } catch(e) {
791 isValidRegex = false;
792 }
793
794
795 //backwards compat
796 operator = operator === '' ? 'less than or equals' : operator;
797 operator = operator === '' ? 'greater than or equals' : operator;
798 operator = operator === '>' ? 'greater than' : operator;
799 operator = operator === '<' ? 'less than' : operator;
800
801
802 if ($field.length === 1) {
803
804 // single field (tested with text field, single checkbox, select with single value (dropdown), select with multiple values)
805
806 if ($field.is('select')) {
807
808 if (operator === 'not equals') {
809 condition_ok = true;
810 }
811
812 $field.find('option:selected').each(function () {
813 var $option = jQuery(this);
814 var option_val = $option.val()
815 if (
816 operator === 'equals' && option_val === if_val ||
817 operator === 'equals (regex)' && regex_patt.test($option.val())
818 ) {
819 condition_ok = true;
820 } else if (
821 operator === 'not equals' && option_val === if_val ||
822 operator === 'not equals (regex)' && !regex_patt.test($option.val())
823 ) {
824 condition_ok = false;
825 return false; // break out of the loop
826 }
827 });
828
829 show_group = show_group && condition_ok;
830 }
831
832 var field_val = $field.val();
833 var field_val_as_number = isFinite(parseFloat(field_val)) ? parseFloat(field_val):0;
834
835 if ($field.attr('type') === 'checkbox') {
836 var field_is_checked = $field.is(':checked');
837 if (
838 operator === 'equals' && field_is_checked && field_val === if_val ||
839 operator === 'not equals' && !field_is_checked ||
840 operator === 'is empty' && !field_is_checked ||
841 operator === 'not empty' && field_is_checked ||
842 operator === 'greater than' && field_is_checked && field_val_as_number > if_val_as_number ||
843 operator === 'less than' && field_is_checked && field_val_as_number < if_val_as_number ||
844 operator === 'greater than or equals' && field_is_checked && field_val_as_number >= if_val_as_number ||
845 operator === 'less than or equals' && field_is_checked && field_val_as_number <= if_val_as_number ||
846 operator === 'equals (regex)' && field_is_checked && regex_patt.test(field_val) ||
847 operator === 'not equals (regex)' && !field_is_checked
848
849 ) {
850 condition_ok = true;
851 }
852 } else if (
853 operator === 'equals' && field_val === if_val ||
854 operator === 'not equals' && field_val !== if_val ||
855 operator === 'equals (regex)' && regex_patt.test(field_val) ||
856 operator === 'not equals (regex)' && !regex_patt.test(field_val) ||
857 operator === 'greater than' && field_val_as_number > if_val_as_number ||
858 operator === 'less than' && field_val_as_number < if_val_as_number ||
859 operator === 'greater than or equals' && field_val_as_number >= if_val_as_number ||
860 operator === 'less than or equals' && field_val_as_number <= if_val_as_number ||
861 operator === 'is empty' && field_val === '' ||
862 operator === 'not empty' && field_val !== '' ||
863 (
864 operator === 'function'
865 && typeof window[if_val] == 'function'
866 && window[if_val]($field)
867 )
868 ) {
869 condition_ok = true;
870 }
871
872
873 } else if ($field.length > 1) {
874
875 // multiple fields (tested with checkboxes, exclusive checkboxes, dropdown with multiple values)
876
877 var all_values = [];
878 var checked_values = [];
879 $field.each(function () {
880 all_values.push(jQuery(this).val());
881 if (jQuery(this).is(':checked')) {
882 checked_values.push(jQuery(this).val());
883 }
884 });
885
886 var checked_value_index = jQuery.inArray(if_val, checked_values);
887 var value_index = jQuery.inArray(if_val, all_values);
888
889 if (
890 ( operator === 'is empty' && checked_values.length === 0 ) ||
891 ( operator === 'not empty' && checked_values.length > 0 )
892 ) {
893 condition_ok = true;
894 }
895
896
897 for (var ind = 0; ind < checked_values.length; ind++) {
898 var checked_val = checked_values[ind];
899 var checked_val_as_number = isFinite(parseFloat(checked_val)) ? parseFloat(checked_val):0;
900 if (
901 ( operator === 'equals' && checked_val === if_val ) ||
902 ( operator === 'not equals' && checked_val !== if_val ) ||
903 ( operator === 'equals (regex)' && regex_patt.test(checked_val) ) ||
904 ( operator === 'not equals (regex)' && !regex_patt.test(checked_val) ) ||
905 ( operator === 'greater than' && checked_val_as_number > if_val_as_number ) ||
906 ( operator === 'less than' && checked_val_as_number < if_val_as_number ) ||
907 ( operator === 'greater than or equals' && checked_val_as_number >= if_val_as_number ) ||
908 ( operator === 'less than or equals' && checked_val_as_number <= if_val_as_number )
909 ) {
910 condition_ok = true;
911 }
912 }
913 }
914
915 show_group = show_group && condition_ok;
916 }
917
918 return show_group;
919
920 }
921
922 };
923
924
925 jQuery('.wpcf7-form').each(function(){
926 wpcf7cf_forms.push(new Wpcf7cfForm(jQuery(this)));
927 });
928
929 // Call displayFields again on all forms
930 // Necessary in case some theme or plugin changed a form value by the time the entire page is fully loaded.
931 jQuery('document').ready(function() {
932 wpcf7cf_forms.forEach(function(f){
933 f.displayFields();
934 });
935 });
936
937 // fix for exclusive checkboxes in IE (this will call the change-event again after all other checkboxes are unchecked, triggering the display_fields() function)
938 var old_wpcf7ExclusiveCheckbox = jQuery.fn.wpcf7ExclusiveCheckbox;
939 jQuery.fn.wpcf7ExclusiveCheckbox = function() {
940 return this.find('input:checkbox').click(function() {
941 var name = jQuery(this).attr('name');
942 jQuery(this).closest('form').find('input:checkbox[name="' + name + '"]').not(this).prop('checked', false).eq(0).change();
943 });
944 };
945
946