PluginProbe ʕ •ᴥ•ʔ
Conditional Fields for Contact Form 7 / 1.7.3
Conditional Fields for Contact Form 7 v1.7.3
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
527 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 //removed pro functions
86
87 }
88 Wpcf7cfForm.prototype.displayFields = function() {
89
90 var form = this;
91
92 wpcf7cf.get_simplified_dom_model(form.$form);
93
94 var unit_tag = this.unit_tag;
95 var wpcf7cf_conditions = this.conditions;
96 var wpcf7cf_settings = this.settings;
97
98 //for compatibility with contact-form-7-signature-addon
99 if (cf7signature_resized === 0 && typeof signatures !== 'undefined' && signatures.constructor === Array && signatures.length > 0 ) {
100 for (var i = 0; i < signatures.length; i++) {
101 if (signatures[i].canvas.width === 0) {
102
103 var $sig_canvas = jQuery(".wpcf7-form-control-signature-body>canvas");
104 var $sig_wrap = jQuery(".wpcf7-form-control-signature-wrap");
105 $sig_canvas.eq(i).attr('width', $sig_wrap.width());
106 $sig_canvas.eq(i).attr('height', $sig_wrap.height());
107
108 cf7signature_resized = 1;
109 }
110 }
111 }
112
113 form.$groups.addClass('wpcf7cf-hidden');
114
115 for (var i=0; i < wpcf7cf_conditions.length; i++) {
116
117 var condition = wpcf7cf_conditions[i];
118
119 var show_group = wpcf7cf.should_group_be_shown(condition, form.$form);
120
121 if (show_group) {
122 jQuery('[data-id='+condition.then_field+']',form.$form).eq(0).removeClass('wpcf7cf-hidden');
123 }
124 }
125
126 var animation_intime = wpcf7cf_settings.animation_intime;
127 var animation_outtime = wpcf7cf_settings.animation_outtime;
128
129 form.$groups.each(function (index) {
130 var $group = jQuery(this);
131 if ($group.is(':animated')) $group.finish(); // stop any current animations on the group
132 if ($group.css('display') === 'none' && !$group.hasClass('wpcf7cf-hidden')) {
133 if ($group.prop('tagName') === 'SPAN') {
134 $group.show().trigger('wpcf7cf_show_group');
135 } else {
136 $group.animate(wpcf7cf_show_animation, animation_intime).trigger('wpcf7cf_show_group'); // show
137 }
138 } else if ($group.css('display') !== 'none' && $group.hasClass('wpcf7cf-hidden')) {
139
140 if ($group.attr('data-clear_on_hide') !== undefined) {
141 var $inputs = jQuery(':input', $group).not(':button, :submit, :reset, :hidden');
142
143 $inputs.each(function(){
144 var $this = jQuery(this);
145 $this.val(this.defaultValue);
146 $this.prop('checked', this.defaultChecked);
147 });
148
149 $inputs.change();
150 //display_fields();
151 }
152
153 if ($group.prop('tagName') === 'SPAN') {
154 $group.hide().trigger('wpcf7cf_hide_group');
155 } else {
156 $group.animate(wpcf7cf_hide_animation, animation_outtime).trigger('wpcf7cf_hide_group'); // hide
157 }
158
159 }
160 });
161
162 form.updateHiddenFields();
163 };
164 Wpcf7cfForm.prototype.updateHiddenFields = function() {
165
166 var form = this;
167
168 var hidden_fields = [];
169 var hidden_groups = [];
170 var visible_groups = [];
171
172 form.$groups.each(function () {
173 var $this = jQuery(this);
174 if ($this.hasClass('wpcf7cf-hidden')) {
175 hidden_groups.push($this.data('id'));
176 $this.find('input,select,textarea').each(function () {
177 hidden_fields.push(jQuery(this).attr('name'));
178 });
179 } else {
180 visible_groups.push($this.data('id'));
181 }
182 });
183
184 form.hidden_fields = hidden_fields;
185 form.hidden_groups = hidden_groups;
186 form.visible_groups = visible_groups;
187
188 form.$input_hidden_group_fields.val(JSON.stringify(hidden_fields));
189 form.$input_hidden_groups.val(JSON.stringify(hidden_groups));
190 form.$input_visible_groups.val(JSON.stringify(visible_groups));
191
192 return true;
193 };
194 Wpcf7cfForm.prototype.updateGroups = function() {
195 var form = this;
196 form.$groups = form.$form.find('[data-class="wpcf7cf_group"]');
197
198 form.conditions = wpcf7cf.get_nested_conditions(form.initial_conditions, form.$form);
199
200 };
201 Wpcf7cfForm.prototype.updateEventListeners = function() {
202
203 var form = this;
204
205 // monitor input changes, and call display_fields() if something has changed
206 jQuery('input, select, textarea, button',form.$form).not('.wpcf7cf_add, .wpcf7cf_remove').off(wpcf7cf_change_events).on(wpcf7cf_change_events,form, function(e) {
207 var form = e.data;
208 clearTimeout(wpcf7cf_timeout);
209 wpcf7cf_timeout = setTimeout(function() {
210 form.displayFields();
211 }, 100);
212 });
213
214 //removed pro functions
215 };
216
217 //removed pro functions
218
219 var wpcf7cf = {
220
221 // keep this for backwards compatibility
222 initForm : function($form) {
223 wpcf7cf_forms.push(new Wpcf7cfForm($form));
224 },
225
226 get_nested_conditions : function(conditions, $current_form) {
227 //loop trough conditions. Then loop trough the dom, and each repeater we pass we should update all sub_values we encounter with __index
228 var simplified_dom = wpcf7cf.get_simplified_dom_model($current_form);
229 var groups = simplified_dom.filter(function(item, i) {
230 return item.type==='group';
231 });
232
233 var sub_conditions = [];
234
235 for(var i = 0; i < groups.length; i++) {
236 var g = groups[i];
237 var relevant_conditions = conditions.filter(function(condition, i) {
238 return condition.then_field === g.original_name;
239 });
240
241 var relevant_conditions = relevant_conditions.map(function(item,i) {
242 return {
243 then_field : g.name,
244 and_rules : item.and_rules.map(function(and_rule, i) {
245 return {
246 if_field : and_rule.if_field+g.suffix,
247 if_value : and_rule.if_value,
248 operator : and_rule.operator
249 };
250 })
251 }
252 });
253
254 sub_conditions = sub_conditions.concat(relevant_conditions);
255 }
256 return conditions.concat(sub_conditions);
257 },
258
259 get_simplified_dom_model : function($current_form) {
260 // if the dom is something like:
261 // <form>
262 // <repeater ra>
263 // <group ga__1>
264 // <repeater rb__1>
265 // <input txta__1__1 />
266 // <input txta__1__2 />
267 // </repeater>
268 // <group gb__1>
269 // <input txtb__1 />
270 // </group>
271 // </group>
272 // <group ga__2>
273 // <repeater rb__2>
274 // <input txta__2__1 />
275 // </repeater>
276 // <group gb__2>
277 // <input txtb__2 />
278 // </group>
279 // </group>
280 // </repeater>
281 // </form>
282 //
283 // return something like:
284 // [{type:repeater, name:'ra', suffix: '__1'}, {type: group, name:'ga', suffix: '__1'}, ...]
285
286 var currentNode;
287 var ni = document.createNodeIterator($current_form[0], NodeFilter.SHOW_ELEMENT, null, false); //, NodeFilter.SHOW_ELEMENT, function(){ return NodeFilter.FILTER_ACCEPT; }
288
289 var simplified_dom = [];
290
291 while(currentNode = ni.nextNode()) {
292 if (currentNode.classList.contains('wpcf7cf_repeater')) {
293 simplified_dom.push({type:'repeater', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
294 } else if (currentNode.dataset.class == 'wpcf7cf_group') {
295 simplified_dom.push({type:'group', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
296 } else if (currentNode.className == 'wpcf7cf_step') {
297 simplified_dom.push({type:'step', name:currentNode.dataset.id, original_name:currentNode.dataset.id, step: currentNode.dataset.id.substring(5)})
298 } else if (currentNode.hasAttribute('name')) {
299 simplified_dom.push({type:'input', name:currentNode.getAttribute('name'), original_name:currentNode.getAttribute('data-orig_name')})
300 }
301 }
302
303 simplified_dom = simplified_dom.map(function(item, i){
304 var original_name_length = item.original_name == null ? item.name.length : item.original_name.length;
305 item.suffix = item.name.substring(original_name_length);
306 return item;
307 });
308
309 //console.table(simplified_dom);
310 return simplified_dom;
311
312 },
313
314 updateMultistepState: function (multistep) {
315 if (multistep == null) return;
316
317 // update hidden input field
318
319 var stepsData = {
320 currentStep : multistep.current_step,
321 numSteps : multistep.numSteps,
322 fieldsInCurrentStep : multistep.getFieldsInStep(multistep.current_step)
323 };
324 multistep.form.$input_steps.val(JSON.stringify(stepsData));
325
326 // update Buttons
327 multistep.$btn_prev.removeClass('disabled');
328 multistep.$btn_next.removeClass('disabled');
329 if (multistep.current_step == multistep.numSteps) {
330 multistep.$btn_next.addClass('disabled');
331 }
332 if (multistep.current_step == 1) {
333 multistep.$btn_prev.addClass('disabled');
334 }
335
336 // replace next button with submit button on last step.
337 // TODO: make this depend on a setting
338 var $submit_button = jQuery('input[type="submit"]', multistep.$form).eq(0);
339 if (multistep.current_step == multistep.numSteps) {
340 var $submit_clone = $submit_button.clone();
341 $submit_button.hide();
342 multistep.$btn_next.hide();
343 multistep.$btn_next.parent().append($submit_clone);
344 } else {
345 multistep.$btn_next.parent().find('input[type=submit]').remove();
346 $submit_button.show();
347 multistep.$btn_next.show();
348 }
349
350 // update dots
351 var $dots = multistep.$dots.find('.dot');
352 $dots.removeClass('active').removeClass('completed');
353 for(var step = 1; step <= multistep.numSteps; step++) {
354 if (step < multistep.current_step) {
355 $dots.eq(step-1).addClass('completed');
356 } else if (step == multistep.current_step) {
357 $dots.eq(step-1).addClass('active');
358 }
359 }
360
361 },
362
363 should_group_be_shown : function(condition, $current_form) {
364
365 var $ = jQuery;
366
367 var show_group = true;
368
369 for (var and_rule_i = 0; and_rule_i < condition.and_rules.length; and_rule_i++) {
370
371 var condition_ok = false;
372
373 var condition_and_rule = condition.and_rules[and_rule_i];
374
375 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);
376
377 var if_val = condition_and_rule.if_value;
378 var if_val_as_number = isFinite(parseFloat(if_val)) ? parseFloat(if_val):0;
379 var operator = condition_and_rule.operator;
380 var regex_patt = new RegExp(if_val, 'i');
381
382
383 if ($field.length === 1) {
384
385 // single field (tested with text field, single checkbox, select with single value (dropdown), select with multiple values)
386
387 if ($field.is('select')) {
388
389 if (operator === 'not equals') {
390 condition_ok = true;
391 }
392
393 $field.find('option:selected').each(function () {
394 var $option = jQuery(this);
395 var option_val = $option.val()
396 if (
397 operator === 'equals' && option_val === if_val ||
398 operator === 'equals (regex)' && regex_patt.test($option.val())
399 ) {
400 condition_ok = true;
401 } else if (
402 operator === 'not equals' && option_val === if_val ||
403 operator === 'not equals (regex)' && !regex_patt.test($option.val())
404 ) {
405 condition_ok = false;
406 return false; // break out of the loop
407 }
408 });
409
410 show_group = show_group && condition_ok;
411 }
412
413 var field_val = $field.val();
414 var field_val_as_number = isFinite(parseFloat(field_val)) ? parseFloat(field_val):0;
415
416 if ($field.attr('type') === 'checkbox') {
417 var field_is_checked = $field.is(':checked');
418 if (
419 operator === 'equals' && field_is_checked && field_val === if_val ||
420 operator === 'not equals' && !field_is_checked ||
421 operator === 'is empty' && !field_is_checked ||
422 operator === 'not empty' && field_is_checked ||
423 operator === '>' && field_is_checked && field_val_as_number > if_val_as_number ||
424 operator === '<' && field_is_checked && field_val_as_number < if_val_as_number ||
425 operator === '' && field_is_checked && field_val_as_number >= if_val_as_number ||
426 operator === '' && field_is_checked && field_val_as_number <= if_val_as_number ||
427 operator === 'equals (regex)' && field_is_checked && regex_patt.test(field_val) ||
428 operator === 'not equals (regex)' && !field_is_checked
429
430 ) {
431 condition_ok = true;
432 }
433 } else if (
434 operator === 'equals' && field_val === if_val ||
435 operator === 'not equals' && field_val !== if_val ||
436 operator === 'equals (regex)' && regex_patt.test(field_val) ||
437 operator === 'not equals (regex)' && !regex_patt.test(field_val) ||
438 operator === '>' && field_val_as_number > if_val_as_number ||
439 operator === '<' && field_val_as_number < if_val_as_number ||
440 operator === '' && field_val_as_number >= if_val_as_number ||
441 operator === '' && field_val_as_number <= if_val_as_number ||
442 operator === 'is empty' && field_val === '' ||
443 operator === 'not empty' && field_val !== '' ||
444 (
445 operator === 'function'
446 && typeof window[if_val] == 'function'
447 && window[if_val]($field)
448 )
449 ) {
450 condition_ok = true;
451 }
452
453
454 } else if ($field.length > 1) {
455
456 // multiple fields (tested with checkboxes, exclusive checkboxes, dropdown with multiple values)
457
458 var all_values = [];
459 var checked_values = [];
460 $field.each(function () {
461 all_values.push(jQuery(this).val());
462 if (jQuery(this).is(':checked')) {
463 checked_values.push(jQuery(this).val());
464 }
465 });
466
467 var checked_value_index = jQuery.inArray(if_val, checked_values);
468 var value_index = jQuery.inArray(if_val, all_values);
469
470 if (
471 ( operator === 'is empty' && checked_values.length === 0 ) ||
472 ( operator === 'not empty' && checked_values.length > 0 )
473 ) {
474 condition_ok = true;
475 }
476
477
478 for (var ind = 0; ind < checked_values.length; ind++) {
479 var checked_val = checked_values[ind];
480 var checked_val_as_number = isFinite(parseFloat(checked_val)) ? parseFloat(checked_val):0;
481 if (
482 ( operator === 'equals' && checked_val === if_val ) ||
483 ( operator === 'not equals' && checked_val !== if_val ) ||
484 ( operator === 'equals (regex)' && regex_patt.test(checked_val) ) ||
485 ( operator === 'not equals (regex)' && !regex_patt.test(checked_val) ) ||
486 ( operator === '>' && checked_val_as_number > if_val_as_number ) ||
487 ( operator === '<' && checked_val_as_number < if_val_as_number ) ||
488 ( operator === '' && checked_val_as_number >= if_val_as_number ) ||
489 ( operator === '' && checked_val_as_number <= if_val_as_number )
490 ) {
491 condition_ok = true;
492 }
493 }
494 }
495
496 show_group = show_group && condition_ok;
497 }
498
499 return show_group;
500
501 }
502
503 };
504
505
506 jQuery('.wpcf7-form').each(function(){
507 wpcf7cf_forms.push(new Wpcf7cfForm(jQuery(this)));
508 });
509
510 // Call displayFields again on all forms
511 // Necessary in case some theme or plugin changed a form value by the time the entire page is fully loaded.
512 jQuery('document').ready(function() {
513 wpcf7cf_forms.forEach(function(f){
514 f.displayFields();
515 });
516 });
517
518 // fix for exclusive checkboxes in IE (this will call the change-event again after all other checkboxes are unchecked, triggering the display_fields() function)
519 var old_wpcf7ExclusiveCheckbox = jQuery.fn.wpcf7ExclusiveCheckbox;
520 jQuery.fn.wpcf7ExclusiveCheckbox = function() {
521 return this.find('input:checkbox').click(function() {
522 var name = jQuery(this).attr('name');
523 jQuery(this).closest('form').find('input:checkbox[name="' + name + '"]').not(this).prop('checked', false).eq(0).change();
524 });
525 };
526
527