PluginProbe ʕ •ᴥ•ʔ
Conditional Fields for Contact Form 7 / 1.7.6
Conditional Fields for Contact Form 7 v1.7.6
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
933 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 // wpcf7cf.updateMultistepState(form.multistep);
98 }
99
100 // END PRO ONLY
101
102 }
103 Wpcf7cfForm.prototype.displayFields = function() {
104
105 var form = this;
106
107 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 = 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 = 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.min = typeof( $repeater.data('min')) !== 'undefined' ? parseInt($repeater.data('min')) : 1;
256 $repeater.max = typeof( $repeater.data('max')) !== 'undefined' ? parseInt($repeater.data('max')) : 200;
257 $repeater.initial_subs = typeof( $repeater.data('initial')) !== 'undefined' ? parseInt($repeater.data('initial')) : $repeater.min;
258 if ($repeater.initial_subs > $repeater.max) $repeater.initial_subs = $repeater.max;
259 var $repeater_sub = $repeater.children('.wpcf7cf_repeater_sub').eq(0);
260 var $repeater_controls = $repeater.children('.wpcf7cf_repeater_controls').eq(0);
261
262 var $repeater_sub_clone = $repeater_sub.clone();
263
264 $repeater_sub_clone.find('.wpcf7cf_repeater_sub').addBack('.wpcf7cf_repeater_sub').each(function() {
265 var $this = jQuery(this);
266 var prev_suffix = $this.attr('data-repeater_sub_suffix');
267 var new_suffix = prev_suffix+'__{{repeater_sub_suffix}}';
268 $this.attr('data-repeater_sub_suffix', new_suffix);
269 });
270
271 $repeater_sub_clone.find('[name]').each(function() {
272 var $this = jQuery(this);
273 var prev_name = $this.attr('name');
274 var orig_name = $this.attr('data-orig_name') != null ? $this.attr('data-orig_name') : prev_name;
275 var new_name = prev_name+'__{{repeater_sub_suffix}}';
276
277 if(prev_name.endsWith('_count')) {
278 new_name = prev_name.replace('_count','__{{repeater_sub_suffix}}_count');
279 }
280
281 $this.attr('name', new_name);
282 $this.attr('data-orig_name', orig_name);
283 $this.closest('.wpcf7-form-control-wrap').addClass(new_name);
284 });
285
286 $repeater_sub_clone.find('.wpcf7cf_repeater,[data-class="wpcf7cf_group"]').each(function() {
287 var $this = jQuery(this);
288 var prev_data_id = $this.attr('data-id');
289 var orig_data_id = $this.attr('data-orig_data_id') != null ? $this.attr('data-orig_data_id') : prev_data_id;
290 var new_data_id = prev_data_id+'__{{repeater_sub_suffix}}';
291
292 if(prev_data_id.endsWith('_count')) {
293 new_data_id = prev_data_id.replace('_count','__{{repeater_sub_suffix}}_count');
294 }
295
296 $this.attr('data-id', new_data_id);
297 $this.attr('data-orig_data_id', orig_data_id);
298 $this.closest('.wpcf7-form-control-wrap').addClass(new_data_id);
299 });
300
301 $repeater_sub_clone.find('[id]').each(function() {
302 var $this = jQuery(this);
303 var prev_id = $this.attr('id');
304 var orig_id = $this.attr('data-orig_id') != null ? $this.attr('data-orig_id') : prev_id;
305 var new_id = prev_id+'__{{repeater_sub_suffix}}';
306
307 $this.attr('id', new_id);
308 $this.attr('data-orig_id', orig_id);
309 $this.closest('.wpcf7-form-control-wrap').addClass(new_id);
310 });
311
312 $repeater_sub_clone.find('[for]').each(function() {
313 var $this = jQuery(this);
314 var prev_for = $this.attr('for');
315 var orig_for = $this.attr('data-orig_for') != null ? $this.attr('data-orig_for') : prev_for;
316 var new_for = prev_for+'__{{repeater_sub_suffix}}';
317
318 $this.attr('for', new_for);
319 $this.attr('data-orig_for', orig_for);
320 $this.closest('.wpcf7-form-control-wrap').addClass(new_for);
321 });
322
323 var repeater_sub_html = $repeater_sub_clone[0].outerHTML;
324
325 var $repeater_count_field = $repeater.find('[name='+$repeater.id+'_count]').eq(0);
326 var $button_add = $repeater_controls.find('.wpcf7cf_add').eq(0);
327 var $button_remove = $repeater_controls.find('.wpcf7cf_remove').eq(0);
328
329 var params = {
330 $repeater: $repeater,
331 $repeater_count_field: $repeater_count_field,
332 repeater_sub_html: repeater_sub_html,
333 $repeater_controls: $repeater_controls,
334 $button_add: $button_add,
335 $button_remove: $button_remove,
336 wpcf7cf_settings: wpcf7cf_settings
337 };
338
339 this.params = params;
340
341 $button_add.click( repeater, function(e) {
342 var repeater = e.data;
343 repeater.updateSubs(params.$repeater.num_subs+1);
344 });
345
346 $button_remove.click( repeater,function(e) {
347 var repeater = e.data;
348 repeater.updateSubs(params.$repeater.num_subs-1);
349 });
350
351 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).eq(0).remove(); // remove the first sub, it's just a template.
352
353 repeater.updateSubs($repeater.initial_subs);
354
355 }
356
357
358
359 Wpcf7cfRepeater.prototype.updateSubs = function(subs_to_show) {
360 var repeater = this;
361 var params = repeater.params;
362 var subs_to_add = subs_to_show - params.$repeater.num_subs;
363
364 if (subs_to_add < 0) {
365 repeater.removeSubs(-subs_to_add);
366 } else if (subs_to_add > 0) {
367 repeater.addSubs(subs_to_add);
368 }
369
370 var showButtonRemove = false;
371 var showButtonAdd = false;
372
373 if (params.$repeater.num_subs < params.$repeater.max) {
374 showButtonAdd = true;
375 }
376 if (params.$repeater.num_subs > params.$repeater.min) {
377 showButtonRemove = true;
378 }
379
380 if (showButtonAdd) {
381 params.$button_add.show();
382 } else {
383 params.$button_add.hide();
384
385 }
386
387 if (showButtonRemove) {
388 params.$button_remove.show();
389 } else {
390 params.$button_remove.hide();
391 }
392
393 params.$repeater_count_field.val(subs_to_show);
394
395 };
396 Wpcf7cfRepeater.prototype.addSubs = function(subs_to_add) {
397 var $ = jQuery;
398 var params = this.params;
399 var repeater = this;
400 var form = repeater.form;
401
402
403 var $repeater = params.$repeater;
404 var $repeater_controls = params.$repeater_controls;
405
406 //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);
407
408 var html_str = '';
409
410 for(var i=1; i<=subs_to_add; i++) {
411 var sub_suffix = $repeater.num_subs+i;
412 html_str += params.repeater_sub_html.replace(/\{\{repeater_sub_suffix\}\}/g,sub_suffix);
413 }
414
415
416 var $html = jQuery(html_str);
417
418 // Add the newly created fields to the form
419 $html.hide().insertBefore($repeater_controls).animate(wpcf7cf_show_animation, params.wpcf7cf_settings.animation_intime).trigger('wpcf7cf_repeater_added');
420
421 jQuery('.wpcf7cf_repeater', $html).each(function(){
422 form.repeaters.push(new Wpcf7cfRepeater(jQuery(this),form));
423 });
424 form.$input_repeaters.val(JSON.stringify(form.repeaters.map((item)=>item.params.$repeater.id)));
425
426 $repeater.num_subs+= subs_to_add;
427
428 wpcf7cf.updateMultistepState(form.multistep);
429 form.updateGroups();
430 form.updateEventListeners();
431 form.displayFields();
432
433 // Exclusive Checkbox
434 $html.on( 'click', '.wpcf7-exclusive-checkbox input:checkbox', function() {
435 var name = $( this ).attr( 'name' );
436 $html.find( 'input:checkbox[name="' + name + '"]' ).not( this ).prop( 'checked', false );
437 } );
438
439 //basic compatibility with material-design-for-contact-form-7
440 if (typeof window.cf7mdInit === "function") {
441 window.cf7mdInit();
442 }
443
444 return false;
445 };
446 Wpcf7cfRepeater.prototype.removeSubs = function(num_subs) {
447 var $ = jQuery;
448 var params = this.params;
449 var form = this.form;
450
451 params.$repeater.num_subs-= num_subs;
452
453 jQuery('> .wpcf7cf_repeater_sub',params.$repeater).slice(-num_subs).animate(wpcf7cf_hide_animation, {duration:params.wpcf7cf_settings.animation_intime, done:function() {
454 var $this = jQuery(this);
455 //remove the actual fields from the form
456 $this.remove();
457 form.$form.trigger('wpcf7cf_repeater_removed');
458 wpcf7cf.updateMultistepState(form.multistep);
459 form.updateGroups();
460 form.updateEventListeners();
461 form.displayFields();
462 }});
463
464 return false;
465 };
466
467 function Wpcf7cfMultistep($multistep, form) {
468 var multistep = this;
469 multistep.$multistep = $multistep;
470 multistep.form = form;
471 multistep.$steps = $multistep.find('.wpcf7cf_step');
472 multistep.$btn_next = $multistep.find('.wpcf7cf_next');
473 multistep.$btn_prev = $multistep.find('.wpcf7cf_prev');
474 multistep.$dots = $multistep.find('.wpcf7cf_steps-dots');
475 multistep.current_step = 0;
476 multistep.numSteps = multistep.$steps.length;
477
478
479 multistep.$dots.html('');
480 for (var i = 1; i <= multistep.numSteps; i++) {
481 multistep.$dots.append(`
482 <div class="dot" data-step="${i}">
483 <div class="step-index">${i}</div>
484 <div class="step-title">${multistep.$steps.eq(i-1).data('title')}</div>
485 </div>
486 `);
487 }
488
489 multistep.$btn_next.on('click.wpcf7cf_step', async function() {
490
491 var result = await multistep.validateStep(multistep.current_step);
492 console.log('got this result: ' + result);
493 if (result === 'success') {
494 multistep.moveToStep(multistep.current_step+1);
495 }
496 });
497
498 multistep.$btn_prev.click(function() {
499 multistep.moveToStep(multistep.current_step-1);
500 });
501
502 multistep.moveToStep(1);
503 }
504
505 Wpcf7cfMultistep.prototype.validateStep = function(step_index) {
506
507 return new Promise(resolve => {
508 var multistep = this;
509 var $multistep = multistep.$multistep;
510
511 //validation
512 var $form = multistep.form.$form;
513
514 var fd = new FormData();
515
516 // TEST IF FILES UPLOADS WORK? THEN REMOVE THIS
517 // jQuery.each($form.find('[data-id="step'+step_index+'"] input[type="file"]'), function(index, el) {
518 // fd.append(jQuery(el).attr('name'), jQuery(el)[0].files[0]);
519 // });
520
521 var formdata = $form.serializeArray();
522 jQuery.each(formdata,function(key, input){
523 fd.append(input.name, input.value);
524 });
525
526 jQuery.ajax({
527 url: wpcf7cf_global_settings.ajaxurl + '?action=wpcf7cf_validate_step',
528 type: 'POST',
529 data: fd,
530 processData: false,
531 contentType: false,
532 dataType: 'json',
533 }).done(function(json) {
534
535 /*
536 * Insert _form_data_id if 'json variable' has
537 */
538 if (typeof json._cf7mls_db_form_data_id != 'undefined') {
539 if (!form.find('input[name="_cf7mls_db_form_data_id"]').length) {
540 form.append('<input type="hidden" name="_cf7mls_db_form_data_id" value="'+json._cf7mls_db_form_data_id+'" />');
541 }
542 }
543
544 //reset error messages
545 $multistep.find('.wpcf7-form-control-wrap').removeClass('cf7mls-invalid');
546 $multistep.find('.wpcf7-form-control-wrap .wpcf7-not-valid-tip').remove();
547 $multistep.find('.wpcf7-response-output').remove();
548 $multistep.find('.wpcf7-response-output.wpcf7-validation-errors').removeClass('wpcf7-validation-errors');
549
550 if (!json.success) {
551 var checkError = 0;
552
553 jQuery.each(json.invalid_fields, function(index, el) {
554 if ($multistep.find('input[name="'+index+'"]').length ||
555 $multistep.find('input[name="'+index+'[]"]').length ||
556 $multistep.find('select[name="'+index+'"]').length ||
557 $multistep.find('select[name="'+index+'[]"]').length ||
558 $multistep.find('textarea[name="'+index+'"]').length ||
559 $multistep.find('textarea[name="'+index+'[]"]').length
560 ) {
561 checkError = checkError + 1;
562
563 var controlWrap = jQuery('.wpcf7-form-control-wrap.' + index, $form);
564 controlWrap.addClass('cf7mls-invalid');
565 controlWrap.find('span.wpcf7-not-valid-tip').remove();
566 controlWrap.append('<span role="alert" class="wpcf7-not-valid-tip">' + el.reason + '</span>');
567
568 //return false;
569 }
570 });
571
572 resolve('failed');
573 $multistep.append('<div class="wpcf7-response-output wpcf7-display-none wpcf7-validation-errors" style="display: block;" role="alert">' + json.message + '</div>');
574
575 } else if (json.success) {
576 resolve('success');
577 return false;
578 }
579
580 }).fail(function() {
581 resolve('error');
582 }).always(function() {
583 // do nothing
584 });
585 });
586
587 };
588 Wpcf7cfMultistep.prototype.moveToStep = function(step_index) {
589 var multistep = this;
590 multistep.current_step = step_index > multistep.numSteps ? multistep.numSteps
591 : step_index < 1 ? 1
592 : step_index;
593
594 // ANIMATION DISABLED FOR NOW cause it's ugly
595 // multistep.$steps.animate(wpcf7cf_hide_step_animation, multistep.form.settings.animation_outtime);
596 // multistep.$steps.eq(multistep.current_step-1).animate(wpcf7cf_show_step_animation, multistep.form.settings.animation_intime);
597
598 multistep.$steps.hide();
599 multistep.$steps.eq(multistep.current_step-1).show();
600
601 wpcf7cf.updateMultistepState(multistep);
602 };
603
604 Wpcf7cfMultistep.prototype.getFieldsInStep = function(step_index) {
605 var simpleDom = wpcf7cf.get_simplified_dom_model(this.form.$form);
606 var inStep = false;
607 return simpleDom.filter(function(item, i) {
608 if(item.type == 'step') {
609 inStep = item.step == step_index+'';
610 }
611 return inStep && item.type == 'input';
612 }).map(function(item) {
613 return item.name;
614 });
615 };
616
617 // END PRO ONLY
618
619 var wpcf7cf = {
620
621 // keep this for backwards compatibility
622 initForm : function($form) {
623 wpcf7cf_forms.push(new Wpcf7cfForm($form));
624 },
625
626 get_nested_conditions : function(conditions, $current_form) {
627 //loop trough conditions. Then loop trough the dom, and each repeater we pass we should update all sub_values we encounter with __index
628 var simplified_dom = wpcf7cf.get_simplified_dom_model($current_form);
629 var groups = simplified_dom.filter(function(item, i) {
630 return item.type==='group';
631 });
632
633 var sub_conditions = [];
634
635 for(var i = 0; i < groups.length; i++) {
636 var g = groups[i];
637 var relevant_conditions = conditions.filter(function(condition, i) {
638 return condition.then_field === g.original_name;
639 });
640
641 var relevant_conditions = relevant_conditions.map(function(item,i) {
642 return {
643 then_field : g.name,
644 and_rules : item.and_rules.map(function(and_rule, i) {
645 return {
646 if_field : and_rule.if_field+g.suffix,
647 if_value : and_rule.if_value,
648 operator : and_rule.operator
649 };
650 })
651 }
652 });
653
654 sub_conditions = sub_conditions.concat(relevant_conditions);
655 }
656 return conditions.concat(sub_conditions);
657 },
658
659 get_simplified_dom_model : function($current_form) {
660 // if the dom is something like:
661 // <form>
662 // <repeater ra>
663 // <group ga__1>
664 // <repeater rb__1>
665 // <input txta__1__1 />
666 // <input txta__1__2 />
667 // </repeater>
668 // <group gb__1>
669 // <input txtb__1 />
670 // </group>
671 // </group>
672 // <group ga__2>
673 // <repeater rb__2>
674 // <input txta__2__1 />
675 // </repeater>
676 // <group gb__2>
677 // <input txtb__2 />
678 // </group>
679 // </group>
680 // </repeater>
681 // </form>
682 //
683 // return something like:
684 // [{type:repeater, name:'ra', suffix: '__1'}, {type: group, name:'ga', suffix: '__1'}, ...]
685
686 var currentNode;
687 var ni = document.createNodeIterator($current_form[0], NodeFilter.SHOW_ELEMENT, null, false); //, NodeFilter.SHOW_ELEMENT, function(){ return NodeFilter.FILTER_ACCEPT; }
688
689 var simplified_dom = [];
690
691 while(currentNode = ni.nextNode()) {
692 if (currentNode.classList.contains('wpcf7cf_repeater')) {
693 simplified_dom.push({type:'repeater', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
694 } else if (currentNode.dataset.class == 'wpcf7cf_group') {
695 simplified_dom.push({type:'group', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
696 } else if (currentNode.className == 'wpcf7cf_step') {
697 simplified_dom.push({type:'step', name:currentNode.dataset.id, original_name:currentNode.dataset.id, step: currentNode.dataset.id.substring(5)})
698 } else if (currentNode.hasAttribute('name')) {
699 simplified_dom.push({type:'input', name:currentNode.getAttribute('name'), original_name:currentNode.getAttribute('data-orig_name')})
700 }
701 }
702
703 simplified_dom = simplified_dom.map(function(item, i){
704 var original_name_length = item.original_name == null ? item.name.length : item.original_name.length;
705 item.suffix = item.name.substring(original_name_length);
706 return item;
707 });
708
709 //console.table(simplified_dom);
710 return simplified_dom;
711
712 },
713
714 updateMultistepState: function (multistep) {
715 if (multistep == null) return;
716
717 // update hidden input field
718
719 var stepsData = {
720 currentStep : multistep.current_step,
721 numSteps : multistep.numSteps,
722 fieldsInCurrentStep : multistep.getFieldsInStep(multistep.current_step)
723 };
724 multistep.form.$input_steps.val(JSON.stringify(stepsData));
725
726 // update Buttons
727 multistep.$btn_prev.removeClass('disabled');
728 multistep.$btn_next.removeClass('disabled');
729 if (multistep.current_step == multistep.numSteps) {
730 multistep.$btn_next.addClass('disabled');
731 }
732 if (multistep.current_step == 1) {
733 multistep.$btn_prev.addClass('disabled');
734 }
735
736 // replace next button with submit button on last step.
737 // TODO: make this depend on a setting
738 var $submit_button = multistep.form.$form.find('input[type="submit"]').eq(0);
739 if (multistep.current_step == multistep.numSteps) {
740 var $submit_clone = $submit_button.clone();
741 $submit_button.hide();
742 multistep.$btn_next.hide();
743 multistep.$btn_next.parent().append($submit_clone);
744 } else {
745 multistep.$btn_next.parent().find('input[type=submit]').remove();
746 $submit_button.show();
747 multistep.$btn_next.show();
748 }
749
750 // update dots
751 var $dots = multistep.$dots.find('.dot');
752 $dots.removeClass('active').removeClass('completed');
753 for(var step = 1; step <= multistep.numSteps; step++) {
754 if (step < multistep.current_step) {
755 $dots.eq(step-1).addClass('completed');
756 } else if (step == multistep.current_step) {
757 $dots.eq(step-1).addClass('active');
758 }
759 }
760
761 },
762
763 should_group_be_shown : function(condition, $current_form) {
764
765 var $ = jQuery;
766
767 var show_group = true;
768
769 for (var and_rule_i = 0; and_rule_i < condition.and_rules.length; and_rule_i++) {
770
771 var condition_ok = false;
772
773 var condition_and_rule = condition.and_rules[and_rule_i];
774
775 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);
776
777 var if_val = condition_and_rule.if_value;
778 var if_val_as_number = isFinite(parseFloat(if_val)) ? parseFloat(if_val):0;
779 var operator = condition_and_rule.operator;
780 var regex_patt = new RegExp(if_val, 'i');
781
782 //backwards compat
783 operator = operator === '' ? 'less than or equals' : operator;
784 operator = operator === '' ? 'greater than or equals' : operator;
785 operator = operator === '>' ? 'greater than' : operator;
786 operator = operator === '<' ? 'less than' : operator;
787
788
789 if ($field.length === 1) {
790
791 // single field (tested with text field, single checkbox, select with single value (dropdown), select with multiple values)
792
793 if ($field.is('select')) {
794
795 if (operator === 'not equals') {
796 condition_ok = true;
797 }
798
799 $field.find('option:selected').each(function () {
800 var $option = jQuery(this);
801 var option_val = $option.val()
802 if (
803 operator === 'equals' && option_val === if_val ||
804 operator === 'equals (regex)' && regex_patt.test($option.val())
805 ) {
806 condition_ok = true;
807 } else if (
808 operator === 'not equals' && option_val === if_val ||
809 operator === 'not equals (regex)' && !regex_patt.test($option.val())
810 ) {
811 condition_ok = false;
812 return false; // break out of the loop
813 }
814 });
815
816 show_group = show_group && condition_ok;
817 }
818
819 var field_val = $field.val();
820 var field_val_as_number = isFinite(parseFloat(field_val)) ? parseFloat(field_val):0;
821
822 if ($field.attr('type') === 'checkbox') {
823 var field_is_checked = $field.is(':checked');
824 if (
825 operator === 'equals' && field_is_checked && field_val === if_val ||
826 operator === 'not equals' && !field_is_checked ||
827 operator === 'is empty' && !field_is_checked ||
828 operator === 'not empty' && field_is_checked ||
829 operator === 'greater than' && field_is_checked && field_val_as_number > if_val_as_number ||
830 operator === 'less than' && field_is_checked && field_val_as_number < if_val_as_number ||
831 operator === 'greater than or equals' && field_is_checked && field_val_as_number >= if_val_as_number ||
832 operator === 'less than or equals' && field_is_checked && field_val_as_number <= if_val_as_number ||
833 operator === 'equals (regex)' && field_is_checked && regex_patt.test(field_val) ||
834 operator === 'not equals (regex)' && !field_is_checked
835
836 ) {
837 condition_ok = true;
838 }
839 } else if (
840 operator === 'equals' && field_val === if_val ||
841 operator === 'not equals' && field_val !== if_val ||
842 operator === 'equals (regex)' && regex_patt.test(field_val) ||
843 operator === 'not equals (regex)' && !regex_patt.test(field_val) ||
844 operator === 'greater than' && field_val_as_number > if_val_as_number ||
845 operator === 'less than' && field_val_as_number < if_val_as_number ||
846 operator === 'greater than or equals' && field_val_as_number >= if_val_as_number ||
847 operator === 'less than or equals' && field_val_as_number <= if_val_as_number ||
848 operator === 'is empty' && field_val === '' ||
849 operator === 'not empty' && field_val !== '' ||
850 (
851 operator === 'function'
852 && typeof window[if_val] == 'function'
853 && window[if_val]($field)
854 )
855 ) {
856 condition_ok = true;
857 }
858
859
860 } else if ($field.length > 1) {
861
862 // multiple fields (tested with checkboxes, exclusive checkboxes, dropdown with multiple values)
863
864 var all_values = [];
865 var checked_values = [];
866 $field.each(function () {
867 all_values.push(jQuery(this).val());
868 if (jQuery(this).is(':checked')) {
869 checked_values.push(jQuery(this).val());
870 }
871 });
872
873 var checked_value_index = jQuery.inArray(if_val, checked_values);
874 var value_index = jQuery.inArray(if_val, all_values);
875
876 if (
877 ( operator === 'is empty' && checked_values.length === 0 ) ||
878 ( operator === 'not empty' && checked_values.length > 0 )
879 ) {
880 condition_ok = true;
881 }
882
883
884 for (var ind = 0; ind < checked_values.length; ind++) {
885 var checked_val = checked_values[ind];
886 var checked_val_as_number = isFinite(parseFloat(checked_val)) ? parseFloat(checked_val):0;
887 if (
888 ( operator === 'equals' && checked_val === if_val ) ||
889 ( operator === 'not equals' && checked_val !== if_val ) ||
890 ( operator === 'equals (regex)' && regex_patt.test(checked_val) ) ||
891 ( operator === 'not equals (regex)' && !regex_patt.test(checked_val) ) ||
892 ( operator === 'greater than' && checked_val_as_number > if_val_as_number ) ||
893 ( operator === 'less than' && checked_val_as_number < if_val_as_number ) ||
894 ( operator === 'greater than or equals' && checked_val_as_number >= if_val_as_number ) ||
895 ( operator === 'less than or equals' && checked_val_as_number <= if_val_as_number )
896 ) {
897 condition_ok = true;
898 }
899 }
900 }
901
902 show_group = show_group && condition_ok;
903 }
904
905 return show_group;
906
907 }
908
909 };
910
911
912 jQuery('.wpcf7-form').each(function(){
913 wpcf7cf_forms.push(new Wpcf7cfForm(jQuery(this)));
914 });
915
916 // Call displayFields again on all forms
917 // Necessary in case some theme or plugin changed a form value by the time the entire page is fully loaded.
918 jQuery('document').ready(function() {
919 wpcf7cf_forms.forEach(function(f){
920 f.displayFields();
921 });
922 });
923
924 // fix for exclusive checkboxes in IE (this will call the change-event again after all other checkboxes are unchecked, triggering the display_fields() function)
925 var old_wpcf7ExclusiveCheckbox = jQuery.fn.wpcf7ExclusiveCheckbox;
926 jQuery.fn.wpcf7ExclusiveCheckbox = function() {
927 return this.find('input:checkbox').click(function() {
928 var name = jQuery(this).attr('name');
929 jQuery(this).closest('form').find('input:checkbox[name="' + name + '"]').not(this).prop('checked', false).eq(0).change();
930 });
931 };
932
933