PluginProbe ʕ •ᴥ•ʔ
Conditional Fields for Contact Form 7 / 1.7
Conditional Fields for Contact Form 7 v1.7
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.js
cf7-conditional-fields / js Last commit date
scripts.js 6 years ago scripts_admin.js 6 years ago
scripts.js
475 lines
1 var cf7signature_resized = 0; // for compatibility with contact-form-7-signature-addon
2
3 var wpcf7cf_timeout;
4
5 var wpcf7cf_show_animation = { "height": "show", "marginTop": "show", "marginBottom": "show", "paddingTop": "show", "paddingBottom": "show" };
6 var wpcf7cf_hide_animation = { "height": "hide", "marginTop": "hide", "marginBottom": "hide", "paddingTop": "hide", "paddingBottom": "hide" };
7
8 var wpcf7cf_show_step_animation = { "width": "show", "marginLeft": "show", "marginRight": "show", "paddingRight": "show", "paddingLeft": "show" };
9 var wpcf7cf_hide_step_animation = { "width": "hide", "marginLeft": "hide", "marginRight": "hide", "paddingRight": "hide", "paddingLeft": "hide" };
10
11 var wpcf7cf_change_events = 'input.wpcf7cf paste.wpcf7cf change.wpcf7cf click.wpcf7cf propertychange.wpcf7cf';
12
13 wpcf7cf_forms = [];
14
15 // endswith polyfill
16 if (!String.prototype.endsWith) {
17 String.prototype.endsWith = function(search, this_len) {
18 if (this_len === undefined || this_len > this.length) {
19 this_len = this.length;
20 }
21 return this.substring(this_len - search.length, this_len) === search;
22 };
23 }
24
25 Wpcf7cfForm = function($form) {
26
27 var options_element = $form.find('input[name="_wpcf7cf_options"]').eq(0);
28 if (!options_element.length || !options_element.val()) {
29 // doesn't look like a CF7 form created with conditional fields plugin enabled.
30 return false;
31 }
32
33 var form = this;
34
35 var form_options = JSON.parse(options_element.val());
36
37 form.$form = $form;
38 form.$hidden_group_fields = $form.find('[name="_wpcf7cf_hidden_group_fields"]');
39 form.$hidden_groups = $form.find('[name="_wpcf7cf_hidden_groups"]');
40 form.$visible_groups = $form.find('[name="_wpcf7cf_visible_groups"]');
41 form.$repeaters = $form.find('[name="_wpcf7cf_repeaters"]');
42
43 form.unit_tag = $form.closest('.wpcf7').attr('id');
44 form.conditions = form_options['conditions'];
45
46 // compatibility with conditional forms created with older versions of the plugin ( < 1.4 )
47 for (var i=0; i < form.conditions.length; i++) {
48 var condition = form.conditions[i];
49 if (!('and_rules' in condition)) {
50 condition.and_rules = [{'if_field':condition.if_field,'if_value':condition.if_value,'operator':condition.operator}];
51 }
52 }
53
54 form.initial_conditions = form.conditions;
55 form.settings = form_options['settings'];
56
57 form.$groups = jQuery(); // empty jQuery set
58 form.repeaters = [];
59 form.multistep = null;
60 form.fields = [];
61
62 form.settings.animation_intime = parseInt(form.settings.animation_intime);
63 form.settings.animation_outtime = parseInt(form.settings.animation_outtime);
64
65 if (form.settings.animation === 'no') {
66 form.settings.animation_intime = 0;
67 form.settings.animation_outtime = 0;
68 }
69
70 form.updateGroups();
71 form.updateEventListeners();
72 form.displayFields();
73
74 // bring form in initial state if the reset event is fired on it.
75 form.$form.on('reset', form, function(e) {
76 var form = e.data;
77 setTimeout(function(){
78 form.displayFields();
79 },200);
80 });
81
82 //removed pro functions
83
84 }
85 Wpcf7cfForm.prototype.displayFields = function() {
86
87 var form = this;
88
89 wpcf7cf.get_simplified_dom_model(form.$form);
90
91 var unit_tag = this.unit_tag;
92 var wpcf7cf_conditions = this.conditions;
93 var wpcf7cf_settings = this.settings;
94
95 //for compatibility with contact-form-7-signature-addon
96 if (cf7signature_resized === 0 && typeof signatures !== 'undefined' && signatures.constructor === Array && signatures.length > 0 ) {
97 for (var i = 0; i < signatures.length; i++) {
98 if (signatures[i].canvas.width === 0) {
99
100 var $sig_canvas = jQuery(".wpcf7-form-control-signature-body>canvas");
101 var $sig_wrap = jQuery(".wpcf7-form-control-signature-wrap");
102 $sig_canvas.eq(i).attr('width', $sig_wrap.width());
103 $sig_canvas.eq(i).attr('height', $sig_wrap.height());
104
105 cf7signature_resized = 1;
106 }
107 }
108 }
109
110 form.$groups.addClass('wpcf7cf-hidden');
111
112 for (var i=0; i < wpcf7cf_conditions.length; i++) {
113
114 var condition = wpcf7cf_conditions[i];
115
116 var show_group = wpcf7cf.should_group_be_shown(condition, form.$form);
117
118 if (show_group) {
119 jQuery('[data-id='+condition.then_field+']',form.$form).eq(0).removeClass('wpcf7cf-hidden');
120 }
121 }
122
123 var animation_intime = wpcf7cf_settings.animation_intime;
124 var animation_outtime = wpcf7cf_settings.animation_outtime;
125
126 form.$groups.each(function (index) {
127 $group = jQuery(this);
128 if ($group.is(':animated')) $group.finish(); // stop any current animations on the group
129 if ($group.css('display') === 'none' && !$group.hasClass('wpcf7cf-hidden')) {
130 if ($group.prop('tagName') === 'SPAN') {
131 $group.show().trigger('wpcf7cf_show_group');
132 } else {
133 $group.animate(wpcf7cf_show_animation, animation_intime).trigger('wpcf7cf_show_group'); // show
134 }
135 } else if ($group.css('display') !== 'none' && $group.hasClass('wpcf7cf-hidden')) {
136
137 if ($group.attr('data-clear_on_hide') !== undefined) {
138 $inputs = jQuery(':input', $group).not(':button, :submit, :reset, :hidden');
139 // $inputs.prop('checked', false).prop('selected', false).prop('selectedIndex', 0);
140 // $inputs.not('[type=checkbox],[type=radio],select').val('');
141
142 $inputs.each(function(){
143 $this = jQuery(this);
144 $this.val(this.defaultValue);
145 $this.prop('checked', this.defaultChecked);
146 });
147
148 $inputs.change();
149 //display_fields();
150 }
151
152 if ($group.prop('tagName') === 'SPAN') {
153 $group.hide().trigger('wpcf7cf_hide_group');
154 } else {
155 $group.animate(wpcf7cf_hide_animation, animation_outtime).trigger('wpcf7cf_hide_group'); // hide
156 }
157
158 }
159 });
160
161 form.updateHiddenFields();
162 };
163 Wpcf7cfForm.prototype.updateHiddenFields = function() {
164
165 var form = this;
166
167 var hidden_fields = [];
168 var hidden_groups = [];
169 var visible_groups = [];
170
171 form.$groups.each(function () {
172 var $this = jQuery(this);
173 if ($this.hasClass('wpcf7cf-hidden')) {
174 hidden_groups.push($this.data('id'));
175 $this.find('input,select,textarea').each(function () {
176 hidden_fields.push(jQuery(this).attr('name'));
177 });
178 } else {
179 visible_groups.push($this.data('id'));
180 }
181 });
182
183 form.hidden_fields = hidden_fields;
184 form.hidden_groups = hidden_groups;
185 form.visible_groups = visible_groups;
186
187 form.$hidden_group_fields.val(JSON.stringify(hidden_fields));
188 form.$hidden_groups.val(JSON.stringify(hidden_groups));
189 form.$visible_groups.val(JSON.stringify(visible_groups));
190
191 return true;
192 };
193 Wpcf7cfForm.prototype.updateGroups = function() {
194 var form = this;
195 form.$groups = form.$form.find('[data-class="wpcf7cf_group"]');
196
197 form.conditions = wpcf7cf.get_nested_conditions(form.initial_conditions, form.$form);
198
199 };
200 Wpcf7cfForm.prototype.updateEventListeners = function() {
201
202 var form = this;
203
204 // monitor input changes, and call display_fields() if something has changed
205 jQuery('input, select, textarea, button',form.$form).not('.wpcf7cf_add, .wpcf7cf_remove').off(wpcf7cf_change_events).on(wpcf7cf_change_events,form, function(e) {
206 var form = e.data;
207 clearTimeout(wpcf7cf_timeout);
208 wpcf7cf_timeout = setTimeout(function() {
209 form.displayFields();
210 }, 100);
211 });
212
213 //removed pro functions
214 };
215
216 //removed pro functions
217
218 wpcf7cf = {
219
220 // keep this for backwards compatibility
221 initForm : function($form) {
222 wpcf7cf_forms.push(new Wpcf7cfForm($form));
223 },
224
225 get_nested_conditions : function(conditions, $current_form) {
226 //loop trough conditions. Then loop trough the dom, and each repeater we pass we should update all sub_values we encounter with __index
227 var simplified_dom = wpcf7cf.get_simplified_dom_model($current_form);
228 var groups = simplified_dom.filter(function(item, i) {
229 return item.type==='group';
230 });
231
232 var sub_conditions = [];
233
234 for(var i = 0; i < groups.length; i++) {
235 var g = groups[i];
236 var relevant_conditions = conditions.filter(function(condition, i) {
237 return condition.then_field === g.original_name;
238 });
239
240 var relevant_conditions = relevant_conditions.map(function(item,i) {
241 return {
242 then_field : g.name,
243 and_rules : item.and_rules.map(function(and_rule, i) {
244 return {
245 if_field : and_rule.if_field+g.suffix,
246 if_value : and_rule.if_value,
247 operator : and_rule.operator
248 };
249 })
250 }
251 });
252
253 sub_conditions = sub_conditions.concat(relevant_conditions);
254 }
255 return conditions.concat(sub_conditions);
256 },
257
258 get_simplified_dom_model : function($current_form) {
259 // if the dom is something like:
260 // <form>
261 // <repeater ra>
262 // <group ga__1>
263 // <repeater rb__1>
264 // <input txta__1__1 />
265 // <input txta__1__2 />
266 // </repeater>
267 // <group gb__1>
268 // <input txtb__1 />
269 // </group>
270 // </group>
271 // <group ga__2>
272 // <repeater rb__2>
273 // <input txta__2__1 />
274 // </repeater>
275 // <group gb__2>
276 // <input txtb__2 />
277 // </group>
278 // </group>
279 // </repeater>
280 // </form>
281 //
282 // return something like:
283 // [{type:repeater, name:'ra', suffix: '__1'}, {type: group, name:'ga', suffix: '__1'}, ...]
284
285 var currentNode,
286 ni = document.createNodeIterator($current_form[0], NodeFilter.SHOW_ELEMENT);
287
288 var simplified_dom = [];
289
290 while(currentNode = ni.nextNode()) {
291 if (currentNode.classList.contains('wpcf7cf_repeater')) {
292 simplified_dom.push({type:'repeater', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
293 } else if (currentNode.dataset.class == 'wpcf7cf_group') {
294 simplified_dom.push({type:'group', name:currentNode.dataset.id, original_name:currentNode.dataset.orig_data_id})
295 } else if (currentNode.hasAttribute('name')) {
296 simplified_dom.push({type:'input', name:currentNode.getAttribute('name'), original_name:currentNode.getAttribute('data-orig_name')})
297 }
298 }
299
300 simplified_dom = simplified_dom.map(function(item, i){
301 var original_name_length = item.original_name == null ? item.name.length : item.original_name.length;
302 item.suffix = item.name.substring(original_name_length);
303 return item;
304 });
305
306 // console.table(simplified_dom);
307 return simplified_dom;
308
309 },
310
311 should_group_be_shown : function(condition, $current_form) {
312
313 var $ = jQuery;
314
315 var show_group = true;
316
317 for (var and_rule_i = 0; and_rule_i < condition.and_rules.length; and_rule_i++) {
318
319 var condition_ok = false;
320
321 var condition_and_rule = condition.and_rules[and_rule_i];
322
323 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);
324
325 var if_val = condition_and_rule.if_value;
326 var if_val_as_number = isFinite(parsedval=parseFloat(if_val)) ? parsedval:0;
327 var operator = condition_and_rule.operator;
328 var regex_patt = new RegExp(if_val, 'i');
329
330
331 if ($field.length === 1) {
332
333 // single field (tested with text field, single checkbox, select with single value (dropdown), select with multiple values)
334
335 if ($field.is('select')) {
336
337 if (operator === 'not equals') {
338 condition_ok = true;
339 }
340
341 $field.find('option:selected').each(function () {
342 var $option = jQuery(this);
343 option_val = $option.val()
344 if (
345 operator === 'equals' && option_val === if_val ||
346 operator === 'equals (regex)' && regex_patt.test($option.val())
347 ) {
348 condition_ok = true;
349 } else if (
350 operator === 'not equals' && option_val === if_val ||
351 operator === 'not equals (regex)' && !regex_patt.test($option.val())
352 ) {
353 condition_ok = false;
354 return false; // break out of the loop
355 }
356 });
357
358 show_group = show_group && condition_ok;
359 }
360
361 var field_val = $field.val();
362 var field_val_as_number = isFinite(parsedval=parseFloat(field_val)) ? parsedval:0;
363
364 if ($field.attr('type') === 'checkbox') {
365 var field_is_checked = $field.is(':checked');
366 if (
367 operator === 'equals' && field_is_checked && field_val === if_val ||
368 operator === 'not equals' && !field_is_checked ||
369 operator === 'is empty' && !field_is_checked ||
370 operator === 'not empty' && field_is_checked ||
371 operator === '>' && field_is_checked && field_val_as_number > if_val_as_number ||
372 operator === '<' && field_is_checked && field_val_as_number < if_val_as_number ||
373 operator === '' && field_is_checked && field_val_as_number >= if_val_as_number ||
374 operator === '' && field_is_checked && field_val_as_number <= if_val_as_number ||
375 operator === 'equals (regex)' && field_is_checked && regex_patt.test(field_val) ||
376 operator === 'not equals (regex)' && !field_is_checked
377
378 ) {
379 condition_ok = true;
380 }
381 } else if (
382 operator === 'equals' && field_val === if_val ||
383 operator === 'not equals' && field_val !== if_val ||
384 operator === 'equals (regex)' && regex_patt.test(field_val) ||
385 operator === 'not equals (regex)' && !regex_patt.test(field_val) ||
386 operator === '>' && field_val_as_number > if_val_as_number ||
387 operator === '<' && field_val_as_number < if_val_as_number ||
388 operator === '' && field_val_as_number >= if_val_as_number ||
389 operator === '' && field_val_as_number <= if_val_as_number ||
390 operator === 'is empty' && field_val === '' ||
391 operator === 'not empty' && field_val !== '' ||
392 (
393 operator === 'function'
394 && typeof window[if_val] == 'function'
395 && window[if_val]($field)
396 )
397 ) {
398 condition_ok = true;
399 }
400
401
402 } else if ($field.length > 1) {
403
404 // multiple fields (tested with checkboxes, exclusive checkboxes, dropdown with multiple values)
405
406 var all_values = [];
407 var checked_values = [];
408 $field.each(function () {
409 all_values.push(jQuery(this).val());
410 if (jQuery(this).is(':checked')) {
411 checked_values.push(jQuery(this).val());
412 }
413 });
414
415 var checked_value_index = jQuery.inArray(if_val, checked_values);
416 var value_index = jQuery.inArray(if_val, all_values);
417
418 if (
419 ( operator === 'is empty' && checked_values.length === 0 ) ||
420 ( operator === 'not empty' && checked_values.length > 0 )
421 ) {
422 condition_ok = true;
423 }
424
425
426 for (var ind = 0; ind < checked_values.length; ind++) {
427 var checked_val = checked_values[ind];
428 var checked_val_as_number = isFinite(parsedval=parseFloat(checked_val)) ? parsedval:0;
429 if (
430 ( operator === 'equals' && checked_val === if_val ) ||
431 ( operator === 'not equals' && checked_val !== if_val ) ||
432 ( operator === 'equals (regex)' && regex_patt.test(checked_val) ) ||
433 ( operator === 'not equals (regex)' && !regex_patt.test(checked_val) ) ||
434 ( operator === '>' && checked_val_as_number > if_val_as_number ) ||
435 ( operator === '<' && checked_val_as_number < if_val_as_number ) ||
436 ( operator === '' && checked_val_as_number >= if_val_as_number ) ||
437 ( operator === '' && checked_val_as_number <= if_val_as_number )
438 ) {
439 condition_ok = true;
440 }
441 }
442 }
443
444 show_group = show_group && condition_ok;
445 }
446
447 return show_group;
448
449 }
450
451 };
452
453
454 jQuery('.wpcf7-form').each(function(){
455 wpcf7cf_forms.push(new Wpcf7cfForm(jQuery(this)));
456 });
457
458 // Call displayFields again on all forms
459 // Necessary in case some theme or plugin changed a form value by the time the entire page is fully loaded.
460 jQuery('document').ready(function() {
461 wpcf7cf_forms.forEach(function(f){
462 f.displayFields();
463 });
464 });
465
466 // fix for exclusive checkboxes in IE (this will call the change-event again after all other checkboxes are unchecked, triggering the display_fields() function)
467 var old_wpcf7ExclusiveCheckbox = jQuery.fn.wpcf7ExclusiveCheckbox;
468 jQuery.fn.wpcf7ExclusiveCheckbox = function() {
469 return this.find('input:checkbox').click(function() {
470 var name = jQuery(this).attr('name');
471 jQuery(this).closest('form').find('input:checkbox[name="' + name + '"]').not(this).prop('checked', false).eq(0).change();
472 });
473 };
474
475