PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / js / formidable.js

formidable.js in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 5.1, at js/formidable.js

1,543 lines 43.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* exported frmRecaptcha, frmAfterRecaptcha, frmUpdateField, frmDeleteEntry, frmOnSubmit, frm_resend_email */
2
3 var frmFrontForm;
4
5 function frmFrontFormJS() {
6 'use strict';
7
8 /*global jQuery:false, frm_js, grecaptcha, frmProForm, tinyMCE */
9 /*global frmThemeOverride_jsErrors, frmThemeOverride_frmPlaceError, frmThemeOverride_frmAfterSubmit */
10
11 var action = '';
12 var jsErrors = [];
13
14 function maybeShowLabel() {
15 /*jshint validthis:true */
16 var $field = jQuery( this ),
17 $label = $field.closest( '.frm_inside_container' ).find( '.frm_primary_label' ),
18 val = $field.val();
19
20 if ( val !== null && val.length > 0 ) {
21 $label.addClass( 'frm_visible' );
22 } else {
23 $label.removeClass( 'frm_visible' );
24 }
25 }
26
27 /* Get the ID of the field that changed*/
28 function getFieldId( field, fullID ) {
29 var nameParts, fieldId,
30 isRepeating = false,
31 fieldName = '';
32 if ( field instanceof jQuery ) {
33 fieldName = field.attr( 'name' );
34 } else {
35 fieldName = field.name;
36 }
37
38 if ( typeof fieldName === 'undefined' ) {
39 fieldName = '';
40 }
41
42 if ( fieldName === '' ) {
43 if ( field instanceof jQuery ) {
44 fieldName = field.data( 'name' );
45 } else {
46 fieldName = field.getAttribute( 'data-name' );
47 }
48
49 if ( typeof fieldName === 'undefined' ) {
50 fieldName = '';
51 }
52
53 if ( fieldName !== '' && fieldName ) {
54 return fieldName;
55 }
56 return 0;
57 }
58
59 nameParts = fieldName.replace( 'item_meta[', '' ).replace( '[]', '' ).split( ']' );
60 //TODO: Fix this for checkboxes and address fields
61 if ( nameParts.length < 1 ) {
62 return 0;
63 }
64 nameParts = nameParts.filter( function( n ) {
65 return n !== '';
66 });
67
68 fieldId = nameParts[0];
69
70 if ( nameParts.length === 1 ) {
71 return fieldId;
72 }
73
74 if ( nameParts[1] === '[form' || nameParts[1] === '[row_ids' ) {
75 return 0;
76 }
77
78 // Check if 'this' is in a repeating section
79 if ( jQuery( 'input[name="item_meta[' + fieldId + '][form]"]' ).length ) {
80
81 // this is a repeatable section with name: item_meta[repeating-section-id][row-id][field-id]
82 fieldId = nameParts[2].replace( '[', '' );
83 isRepeating = true;
84 }
85
86 // Check if 'this' is an other text field and get field ID for it
87 if ( 'other' === fieldId ) {
88 if ( isRepeating ) {
89 // name for other fields: item_meta[370][0][other][414]
90 fieldId = nameParts[3].replace( '[', '' );
91 } else {
92 // Other field name: item_meta[other][370]
93 fieldId = nameParts[1].replace( '[', '' );
94 }
95 }
96
97 if ( fullID === true ) {
98 // For use in the container div id
99 if ( fieldId === nameParts[0]) {
100 fieldId = fieldId + '-' + nameParts[1].replace( '[', '' );
101 } else {
102 fieldId = fieldId + '-' + nameParts[0] + '-' + nameParts[1].replace( '[', '' );
103 }
104 }
105
106 return fieldId;
107 }
108
109 /**
110 * Disable the submit button for a given jQuery form object
111 *
112 * @since 2.03.02
113 *
114 * @param {object} $form
115 */
116 function disableSubmitButton( $form ) {
117 $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).attr( 'disabled', 'disabled' );
118 }
119
120 /**
121 * Enable the submit button for a given jQuery form object
122 *
123 * @since 2.03.02
124 *
125 * @param {object} $form
126 */
127 function enableSubmitButton( $form ) {
128 $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).prop( 'disabled', false );
129 }
130
131 /**
132 * Disable the save draft link for a given jQuery form object
133 *
134 * @since 4.04.03
135 *
136 * @param {object} $form
137 */
138 function disableSaveDraft( $form ) {
139 $form.find( 'a.frm_save_draft' ).css( 'pointer-events', 'none' );
140 }
141
142 /**
143 * Enable the save draft link for a given jQuery form object
144 *
145 * @since 4.04.03
146 *
147 * @param {object} $form
148 */
149 function enableSaveDraft( $form ) {
150 $form.find( 'a.frm_save_draft' ).css( 'pointer-events', '' );
151 }
152
153 function validateForm( object ) {
154 var r, rl, n, nl, fields, field, value, requiredFields,
155 errors = [];
156
157 // Make sure required text field is filled in
158 requiredFields = jQuery( object ).find(
159 '.frm_required_field:visible input, .frm_required_field:visible select, .frm_required_field:visible textarea'
160 ).filter( ':not(.frm_optional)' );
161 if ( requiredFields.length ) {
162 for ( r = 0, rl = requiredFields.length; r < rl; r++ ) {
163 if ( hasClass( requiredFields[r], 'ed_button' ) ) {
164 // skip rich text field buttons.
165 continue;
166 }
167 errors = checkRequiredField( requiredFields[r], errors );
168 }
169 }
170
171 fields = jQuery( object ).find( 'input,select,textarea' );
172 if ( fields.length ) {
173 for ( n = 0, nl = fields.length; n < nl; n++ ) {
174 field = fields[n];
175 value = field.value;
176 if ( value !== '' ) {
177 if ( field.type === 'hidden' ) {
178 // don't validate
179 } else if ( field.type === 'number' ) {
180 errors = checkNumberField( field, errors );
181 } else if ( field.type === 'email' ) {
182 errors = checkEmailField( field, errors );
183 } else if ( field.type === 'password' ) {
184 errors = checkPasswordField( field, errors );
185 } else if ( field.type === 'url' ) {
186 errors = checkUrlField( field, errors );
187 } else if ( field.pattern !== null ) {
188 errors = checkPatternField( field, errors );
189 }
190 }
191 }
192 }
193
194 errors = validateRecaptcha( object, errors );
195
196 return errors;
197 }
198
199 /**
200 * @since 5.0.10
201 *
202 * @param {object} element
203 * @param {string} targetClass
204 * @returns {boolean}
205 */
206 function hasClass( element, targetClass ) {
207 var className = ' ' + element.className + ' ';
208 return -1 !== className.indexOf( ' ' + targetClass + ' ' );
209 }
210
211 function maybeValidateChange( field ) {
212 if ( field.type === 'url' ) {
213 maybeAddHttpToUrl( field );
214 }
215 if ( jQuery( field ).closest( 'form' ).hasClass( 'frm_js_validate' ) ) {
216 validateField( field );
217 }
218 }
219
220 function maybeAddHttpToUrl( field ) {
221 var url = field.value;
222 var matches = url.match( /^(https?|ftps?|mailto|news|feed|telnet):/ );
223 if ( field.value !== '' && matches === null ) {
224 field.value = 'http://' + url;
225 }
226 }
227
228 function validateField( field ) {
229 var key,
230 errors = [],
231 $fieldCont = jQuery( field ).closest( '.frm_form_field' );
232
233 if ( $fieldCont.hasClass( 'frm_required_field' ) && ! jQuery( field ).hasClass( 'frm_optional' ) ) {
234 errors = checkRequiredField( field, errors );
235 }
236
237 if ( errors.length < 1 ) {
238 if ( field.type === 'email' ) {
239 errors = checkEmailField( field, errors );
240 } else if ( field.type === 'password' ) {
241 errors = checkPasswordField( field, errors );
242 } else if ( field.type === 'number' ) {
243 errors = checkNumberField( field, errors );
244 } else if ( field.type === 'url' ) {
245 errors = checkUrlField( field, errors );
246 } else if ( field.pattern !== null ) {
247 errors = checkPatternField( field, errors );
248 }
249 }
250
251 removeFieldError( $fieldCont );
252 if ( Object.keys( errors ).length > 0 ) {
253 for ( key in errors ) {
254 addFieldError( $fieldCont, key, errors );
255 }
256 }
257 }
258
259 function checkRequiredField( field, errors ) {
260 var checkGroup, tempVal, i, placeholder,
261 val = '',
262 fieldID = '',
263 fileID = field.getAttribute( 'data-frmfile' );
264
265 if ( field.type === 'hidden' && fileID === null && ! isAppointmentField( field ) && ! isInlineDatepickerField( field ) ) {
266 return errors;
267 }
268
269 if ( field.type === 'checkbox' || field.type === 'radio' ) {
270 checkGroup = jQuery( 'input[name="' + field.name + '"]' ).closest( '.frm_required_field' ).find( 'input:checked' );
271 jQuery( checkGroup ).each( function() {
272 val = this.value;
273 });
274 } else if ( field.type === 'file' || fileID ) {
275 if ( typeof fileID === 'undefined' ) {
276 fileID = getFieldId( field, true );
277 fileID = fileID.replace( 'file', '' );
278 }
279
280 if ( typeof errors[ fileID ] === 'undefined' ) {
281 val = getFileVals( fileID );
282 }
283 fieldID = fileID;
284 } else {
285 if ( hasClass( field, 'frm_pos_none' ) ) {
286 // skip hidden other fields
287 return errors;
288 }
289
290 val = jQuery( field ).val();
291 if ( val === null ) {
292 val = '';
293 } else if ( typeof val !== 'string' ) {
294 tempVal = val;
295 val = '';
296 for ( i = 0; i < tempVal.length; i++ ) {
297 if ( tempVal[i] !== '' ) {
298 val = tempVal[i];
299 }
300 }
301 }
302
303 if ( hasClass( field, 'frm_other_input' ) ) {
304 fieldID = getFieldId( field, false );
305
306 if ( val === '' ) {
307 field = document.getElementById( field.id.replace( '-otext', '' ) );
308 }
309 } else {
310 fieldID = getFieldId( field, true );
311 }
312
313 if ( hasClass( field, 'frm_time_select' ) ) {
314 // set id for time field
315 fieldID = fieldID.replace( '-H', '' ).replace( '-m', '' );
316 } else if ( isSignatureField( field ) ) {
317 if ( val === '' ) {
318 val = jQuery( field ).closest( '.frm_form_field' ).find( '[name="' + field.getAttribute( 'name' ).replace( '[typed]', '[output]' ) + '"]' ).val();
319 }
320 fieldID = fieldID.replace( '-typed', '' );
321 }
322
323 placeholder = field.getAttribute( 'data-frmplaceholder' );
324 if ( placeholder !== null && val === placeholder ) {
325 val = '';
326 }
327 }
328
329 if ( val === '' ) {
330 if ( fieldID === '' ) {
331 fieldID = getFieldId( field, true );
332 }
333 if ( ! ( fieldID in errors ) ) {
334 errors[ fieldID ] = getFieldValidationMessage( field, 'data-reqmsg' );
335 }
336 }
337
338 return errors;
339 }
340
341 function isSignatureField( field ) {
342 var name = field.getAttribute( 'name' );
343 return 'string' === typeof name && '[typed]' === name.substr( -7 );
344 }
345
346 function isAppointmentField( field ) {
347 return hasClass( field, 'ssa_appointment_form_field_appointment_id' );
348 }
349
350 function isInlineDatepickerField( field ) {
351 return 'hidden' === field.type && '_alt' === field.id.substr( -4 ) && hasClass( field.nextElementSibling, 'frm_date_inline' );
352 }
353
354 function getFileVals( fileID ) {
355 var val = '',
356 fileFields = jQuery( 'input[name="file' + fileID + '"], input[name="file' + fileID + '[]"], input[name^="item_meta[' + fileID + ']"]' );
357
358 fileFields.each( function() {
359 if ( val === '' ) {
360 val = this.value;
361 }
362 });
363 return val;
364 }
365
366 function checkUrlField( field, errors ) {
367 var fieldID,
368 url = field.value;
369
370 if ( url !== '' && ! /^http(s)?:\/\/(?:localhost|(?:[\da-z\.-]+\.[\da-z\.-]+))/i.test( url ) ) {
371 fieldID = getFieldId( field, true );
372 if ( ! ( fieldID in errors ) ) {
373 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
374 }
375 }
376 return errors;
377 }
378
379 function checkEmailField( field, errors ) {
380 var fieldID = getFieldId( field, true ),
381 pattern = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i;
382
383 // validate the current field we're editing first
384 if ( '' !== field.value && pattern.test( field.value ) === false ) {
385 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
386 }
387
388 confirmField( field, errors );
389 return errors;
390 }
391
392 function checkPasswordField( field, errors ) {
393 confirmField( field, errors );
394 return errors;
395 }
396
397 function confirmField( field, errors ) {
398 var value, confirmValue, firstField,
399 fieldID = getFieldId( field, true ),
400 strippedId = field.id.replace( 'conf_', '' ),
401 strippedFieldID = fieldID.replace( 'conf_', '' ),
402 confirmField = document.getElementById( strippedId.replace( 'field_', 'field_conf_' ) );
403
404 if ( confirmField === null || typeof errors[ 'conf_' + strippedFieldID ] !== 'undefined' ) {
405 return;
406 }
407
408 if ( fieldID !== strippedFieldID ) {
409 firstField = document.getElementById( strippedId );
410 value = firstField.value;
411 confirmValue = confirmField.value;
412 if ( '' !== value && '' !== confirmValue && value !== confirmValue ) {
413 errors[ 'conf_' + strippedFieldID ] = getFieldValidationMessage( confirmField, 'data-confmsg' );
414 }
415 } else {
416 validateField( confirmField );
417 }
418 }
419
420 function checkNumberField( field, errors ) {
421 var fieldID,
422 number = field.value;
423
424 if ( number !== '' && isNaN( number / 1 ) !== false ) {
425 fieldID = getFieldId( field, true );
426 if ( ! ( fieldID in errors ) ) {
427 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
428 }
429 }
430 return errors;
431 }
432
433 function checkPatternField( field, errors ) {
434 var fieldID,
435 text = field.value,
436 format = getFieldValidationMessage( field, 'pattern' );
437
438 if ( format !== '' && text !== '' ) {
439 fieldID = getFieldId( field, true );
440 if ( ! ( fieldID in errors ) ) {
441 format = new RegExp( '^' + format + '$', 'i' );
442 if ( format.test( text ) === false ) {
443 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
444 }
445 }
446 }
447 return errors;
448 }
449
450 function hasInvisibleRecaptcha( object ) {
451 var recaptcha, recaptchaID, alreadyChecked;
452
453 if ( isGoingToPrevPage( object ) ) {
454 return false;
455 }
456
457 recaptcha = jQuery( object ).find( '.frm-g-recaptcha[data-size="invisible"], .g-recaptcha[data-size="invisible"]' );
458 if ( recaptcha.length ) {
459 recaptchaID = recaptcha.data( 'rid' );
460 alreadyChecked = grecaptcha.getResponse( recaptchaID );
461 if ( alreadyChecked.length === 0 ) {
462 return recaptcha;
463 } else {
464 return false;
465 }
466 } else {
467 return false;
468 }
469 }
470
471 function executeInvisibleRecaptcha( invisibleRecaptcha ) {
472 var recaptchaID = invisibleRecaptcha.data( 'rid' );
473 grecaptcha.reset( recaptchaID );
474 grecaptcha.execute( recaptchaID );
475 }
476
477 function validateRecaptcha( form, errors ) {
478 var recaptchaID, response, fieldContainer, fieldID,
479 $recaptcha = jQuery( form ).find( '.frm-g-recaptcha' );
480 if ( $recaptcha.length ) {
481 recaptchaID = $recaptcha.data( 'rid' );
482
483 try {
484 response = grecaptcha.getResponse( recaptchaID );
485 } catch ( e ) {
486 if ( jQuery( form ).find( 'input[name="recaptcha_checked"]' ).length ) {
487 return errors;
488 } else {
489 response = '';
490 }
491 }
492
493 if ( response.length === 0 ) {
494 fieldContainer = $recaptcha.closest( '.frm_form_field' );
495 fieldID = fieldContainer.attr( 'id' ).replace( 'frm_field_', '' ).replace( '_container', '' );
496 errors[ fieldID ] = '';
497 }
498 }
499 return errors;
500 }
501
502 function getFieldValidationMessage( field, messageType ) {
503 var msg, errorHtml;
504
505 msg = field.getAttribute( messageType );
506 if ( null === msg ) {
507 msg = '';
508 }
509
510 if ( '' !== msg && shouldWrapErrorHtmlAroundMessageType( messageType ) ) {
511 errorHtml = field.getAttribute( 'data-error-html' );
512 if ( null !== errorHtml ) {
513 errorHtml = errorHtml.replace( /\+/g, '%20' );
514 msg = decodeURIComponent( errorHtml ).replace( '[error]', msg );
515 msg = msg.replace( '[key]', getFieldId( field, false ) );
516 }
517 }
518
519 return msg;
520 }
521
522 function shouldWrapErrorHtmlAroundMessageType( type ) {
523 return 'pattern' !== type;
524 }
525
526 function shouldJSValidate( object ) {
527 var validate = jQuery( object ).hasClass( 'frm_js_validate' );
528 if ( validate && typeof frmProForm !== 'undefined' && ( frmProForm.savingDraft( object ) || frmProForm.goingToPreviousPage( object ) ) ) {
529 validate = false;
530 }
531
532 return validate;
533 }
534
535 function getFormErrors( object, action ) {
536 var fieldset;
537
538 if ( typeof action === 'undefined' ) {
539 jQuery( object ).find( 'input[name="frm_action"]' ).val();
540 }
541
542 fieldset = jQuery( object ).find( '.frm_form_field' );
543 fieldset.addClass( 'frm_doing_ajax' );
544 jQuery.ajax({
545 type: 'POST', url: frm_js.ajax_url,
546 data: jQuery( object ).serialize() + '&action=frm_entries_' + action + '&nonce=' + frm_js.nonce,
547 success: function( response ) {
548 var formID, replaceContent, pageOrder, formReturned, contSubmit, delay,
549 $fieldCont, key, inCollapsedSection, frmTrigger,
550 defaultResponse = { 'content': '', 'errors': {}, 'pass': false };
551 if ( response === null ) {
552 response = defaultResponse;
553 }
554
555 response = response.replace( /^\s+|\s+$/g, '' );
556 if ( response.indexOf( '{' ) === 0 ) {
557 response = JSON.parse( response );
558 } else {
559 response = defaultResponse;
560 }
561
562 if ( typeof response.redirect !== 'undefined' ) {
563 jQuery( document ).trigger( 'frmBeforeFormRedirect', [ object, response ]);
564 window.location = response.redirect;
565 } else if ( response.content !== '' ) {
566 // the form or success message was returned
567
568 removeSubmitLoading( jQuery( object ) );
569 if ( frm_js.offset != -1 ) {
570 frmFrontForm.scrollMsg( jQuery( object ), false );
571 }
572 formID = jQuery( object ).find( 'input[name="form_id"]' ).val();
573 response.content = response.content.replace( / frm_pro_form /g, ' frm_pro_form frm_no_hide ' );
574 replaceContent = jQuery( object ).closest( '.frm_forms' );
575 removeAddedScripts( replaceContent, formID );
576 delay = maybeSlideOut( replaceContent, response.content );
577
578 setTimeout(
579 function() {
580 var container, input, previousInput;
581
582 replaceContent.replaceWith( response.content );
583
584 addUrlParam( response );
585
586 if ( typeof frmThemeOverride_frmAfterSubmit === 'function' ) { // eslint-disable-line camelcase
587 pageOrder = jQuery( 'input[name="frm_page_order_' + formID + '"]' ).val();
588 formReturned = jQuery( response.content ).find( 'input[name="form_id"]' ).val();
589 frmThemeOverride_frmAfterSubmit( formReturned, pageOrder, response.content, object );
590 }
591
592 if ( typeof response.recaptcha !== 'undefined' ) {
593 container = jQuery( '#frm_form_' + formID + '_container' ).find( '.frm_fields_container' );
594 input = '<input type="hidden" name="recaptcha_checked" value="' + response.recaptcha + '">';
595 previousInput = container.find( 'input[name="recaptcha_checked"]' );
596
597 if ( previousInput.length ) {
598 previousInput.replaceWith( input );
599 } else {
600 container.append( input );
601 }
602 }
603
604 afterFormSubmitted( object, response );
605 },
606 delay
607 );
608 } else if ( Object.keys( response.errors ).length ) {
609 // errors were returned
610
611 removeSubmitLoading( jQuery( object ), 'enable' );
612
613 //show errors
614 contSubmit = true;
615 removeAllErrors();
616
617 $fieldCont = null;
618
619 for ( key in response.errors ) {
620 $fieldCont = jQuery( object ).find( '#frm_field_' + key + '_container' );
621
622 if ( $fieldCont.length ) {
623 if ( ! $fieldCont.is( ':visible' ) ) {
624 inCollapsedSection = $fieldCont.closest( '.frm_toggle_container' );
625 if ( inCollapsedSection.length ) {
626 frmTrigger = inCollapsedSection.prev();
627 if ( ! frmTrigger.hasClass( 'frm_trigger' ) ) {
628 // If the frmTrigger object is the section description, check to see if the previous element is the trigger
629 frmTrigger = frmTrigger.prev( '.frm_trigger' );
630 }
631 frmTrigger.trigger( 'click' );
632 }
633 }
634
635 if ( $fieldCont.is( ':visible' ) ) {
636 addFieldError( $fieldCont, key, response.errors );
637 contSubmit = false;
638 }
639 }
640 }
641
642 jQuery( object ).find( '.frm-g-recaptcha, .g-recaptcha' ).each( function() {
643 var $recaptcha = jQuery( this ),
644 recaptchaID = $recaptcha.data( 'rid' );
645
646 if ( typeof grecaptcha !== 'undefined' && grecaptcha ) {
647 if ( recaptchaID ) {
648 grecaptcha.reset( recaptchaID );
649 } else {
650 grecaptcha.reset();
651 }
652 }
653 });
654
655 jQuery( document ).trigger( 'frmFormErrors', [ object, response ]);
656
657 fieldset.removeClass( 'frm_doing_ajax' );
658 scrollToFirstField( object );
659
660 if ( contSubmit ) {
661 object.submit();
662 } else {
663 jQuery( object ).prepend( response.error_message );
664 checkForErrorsAndMaybeSetFocus();
665 }
666 } else {
667 // there may have been a plugin conflict, or the form is not set to submit with ajax
668
669 showFileLoading( object );
670
671 object.submit();
672 }
673 },
674 error: function() {
675 jQuery( object ).find( 'input[type="submit"], input[type="button"]' ).prop( 'disabled', false );
676 object.submit();
677 }
678 });
679 }
680
681 function afterFormSubmitted( object, response ) {
682 var formCompleted = jQuery( response.content ).find( '.frm_message' );
683 if ( formCompleted.length ) {
684 jQuery( document ).trigger( 'frmFormComplete', [ object, response ]);
685 } else {
686 jQuery( document ).trigger( 'frmPageChanged', [ object, response ]);
687 }
688 }
689
690 function removeAddedScripts( formContainer, formID ) {
691 var endReplace = jQuery( '.frm_end_ajax_' + formID );
692 if ( endReplace.length ) {
693 formContainer.nextUntil( '.frm_end_ajax_' + formID ).remove();
694 endReplace.remove();
695 }
696 }
697
698 function maybeSlideOut( oldContent, newContent ) {
699 var c,
700 newClass = 'frm_slideout';
701 if ( newContent.indexOf( ' frm_slide' ) !== -1 ) {
702 c = oldContent.children();
703 if ( newContent.indexOf( ' frm_going_back' ) !== -1 ) {
704 newClass += ' frm_going_back';
705 }
706 c.removeClass( 'frm_going_back' );
707 c.addClass( newClass );
708 return 300;
709 }
710 return 0;
711 }
712
713 function addUrlParam( response ) {
714 var url;
715 if ( history.pushState && typeof response.page !== 'undefined' ) {
716 url = addQueryVar( 'frm_page', response.page );
717 window.history.pushState({ 'html': response.html }, '', '?' + url );
718 }
719 }
720
721 function addQueryVar( key, value ) {
722 var kvp, i, x;
723
724 key = encodeURI( key );
725 value = encodeURI( value );
726
727 kvp = document.location.search.substr( 1 ).split( '&' );
728
729 i = kvp.length;
730 while ( i-- ) {
731 x = kvp[i].split( '=' );
732
733 if ( x[0] == key ) {
734 x[1] = value;
735 kvp[i] = x.join( '=' );
736 break;
737 }
738 }
739
740 if ( i < 0 ) {
741 kvp[ kvp.length ] = [ key, value ].join( '=' );
742 }
743
744 return kvp.join( '&' );
745 }
746
747 function addFieldError( $fieldCont, key, jsErrors ) {
748 var input, id, describedBy;
749 if ( $fieldCont.length && $fieldCont.is( ':visible' ) ) {
750 $fieldCont.addClass( 'frm_blank_field' );
751 input = $fieldCont.find( 'input, select, textarea' );
752 id = 'frm_error_field_' + key;
753 describedBy = input.attr( 'aria-describedby' );
754
755 if ( typeof frmThemeOverride_frmPlaceError === 'function' ) { // eslint-disable-line camelcase
756 frmThemeOverride_frmPlaceError( key, jsErrors );
757 } else {
758 if ( -1 !== jsErrors[key].indexOf( '<div' ) ) {
759 $fieldCont.append(
760 jsErrors[key]
761 );
762 } else {
763 $fieldCont.append( '<div class="frm_error" role="alert" id="' + id + '">' + jsErrors[key] + '</div>' );
764 }
765
766 if ( typeof describedBy === 'undefined' ) {
767 describedBy = id;
768 } else if ( describedBy.indexOf( id ) === -1 ) {
769 describedBy = describedBy + ' ' + id;
770 }
771 input.attr( 'aria-describedby', describedBy );
772 }
773 input.attr( 'aria-invalid', true );
774 input.attr( 'aria-describedby', id );
775
776 jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ]);
777 }
778 }
779
780 function removeFieldError( $fieldCont ) {
781 var errorMessage = $fieldCont.find( '.frm_error' ),
782 errorId = errorMessage.attr( 'id' ),
783 input = $fieldCont.find( 'input, select, textarea' ),
784 describedBy = input.attr( 'aria-describedby' );
785
786 $fieldCont.removeClass( 'frm_blank_field has-error' );
787 errorMessage.remove();
788 input.attr( 'aria-invalid', false );
789 input.removeAttr( 'aria-describedby' );
790
791 if ( typeof describedBy !== 'undefined' ) {
792 describedBy = describedBy.replace( errorId, '' );
793 input.attr( 'aria-describedby', describedBy );
794 }
795 }
796
797 function removeAllErrors() {
798 jQuery( '.form-field' ).removeClass( 'frm_blank_field has-error' );
799 jQuery( '.form-field .frm_error' ).replaceWith( '' );
800 jQuery( '.frm_error_style' ).remove();
801 }
802
803 function scrollToFirstField( object ) {
804 var field = jQuery( object ).find( '.frm_blank_field' ).first();
805 if ( field.length ) {
806 frmFrontForm.scrollMsg( field, object, true );
807 }
808 }
809
810 function showSubmitLoading( $object ) {
811 showLoadingIndicator( $object );
812 disableSubmitButton( $object );
813 disableSaveDraft( $object );
814 }
815
816 function showLoadingIndicator( $object ) {
817 if ( ! $object.hasClass( 'frm_loading_form' ) && ! $object.hasClass( 'frm_loading_prev' ) ) {
818 addLoadingClass( $object );
819 $object.trigger( 'frmStartFormLoading' );
820 }
821 }
822
823 function addLoadingClass( $object ) {
824 var loadingClass = isGoingToPrevPage( $object ) ? 'frm_loading_prev' : 'frm_loading_form';
825
826 $object.addClass( loadingClass );
827 }
828
829 function isGoingToPrevPage( $object ) {
830 return ( typeof frmProForm !== 'undefined' && frmProForm.goingToPreviousPage( $object ) );
831 }
832
833 function removeSubmitLoading( $object, enable, processesRunning ) {
834 var loadingForm;
835
836 if ( processesRunning > 0 ) {
837 return;
838 }
839
840 loadingForm = jQuery( '.frm_loading_form' );
841 loadingForm.removeClass( 'frm_loading_form' );
842 loadingForm.removeClass( 'frm_loading_prev' );
843
844 loadingForm.trigger( 'frmEndFormLoading' );
845
846 if ( enable === 'enable' ) {
847 enableSubmitButton( loadingForm );
848 enableSaveDraft( loadingForm );
849 }
850 }
851
852 function showFileLoading( object ) {
853 var fileval,
854 loading = document.getElementById( 'frm_loading' );
855 if ( loading !== null ) {
856 fileval = jQuery( object ).find( 'input[type=file]' ).val();
857 if ( typeof fileval !== 'undefined' && fileval !== '' ) {
858 setTimeout( function() {
859 jQuery( loading ).fadeIn( 'slow' );
860 }, 2000 );
861 }
862 }
863 }
864
865 function clearDefault() {
866 /*jshint validthis:true */
867 toggleDefault( jQuery( this ), 'clear' );
868 }
869
870 function replaceDefault() {
871 /*jshint validthis:true */
872 toggleDefault( jQuery( this ), 'replace' );
873 }
874
875 function toggleDefault( $thisField, e ) {
876 // TODO: Fix this for a default value that is a number or array
877 var thisVal,
878 v = $thisField.data( 'frmval' ).replace( /(\n|\r\n)/g, '\r' );
879 if ( v === '' || typeof v === 'undefined' ) {
880 return false;
881 }
882 thisVal = $thisField.val().replace( /(\n|\r\n)/g, '\r' );
883
884 if ( 'replace' === e ) {
885 if ( thisVal === '' ) {
886 $thisField.addClass( 'frm_default' ).val( v );
887 }
888 } else if ( thisVal == v ) {
889 $thisField.removeClass( 'frm_default' ).val( '' );
890 }
891 }
892
893 function resendEmail() {
894 /*jshint validthis:true */
895 var $link = jQuery( this ),
896 entryId = this.getAttribute( 'data-eid' ),
897 formId = this.getAttribute( 'data-fid' ),
898 label = $link.find( '.frm_link_label' );
899 if ( label.length < 1 ) {
900 label = $link;
901 }
902 label.append( '<span class="frm-wait"></span>' );
903
904 jQuery.ajax({
905 type: 'POST',
906 url: frm_js.ajax_url,
907 data: {
908 action: 'frm_entries_send_email',
909 entry_id: entryId,
910 form_id: formId,
911 nonce: frm_js.nonce
912 },
913 success: function( msg ) {
914 var admin = document.getElementById( 'wpbody' );
915 if ( admin === null ) {
916 label.html( msg );
917 } else {
918 label.html( '' );
919 $link.after( msg );
920 }
921 }
922 });
923 return false;
924 }
925
926 /**********************************************
927 * General Helpers
928 *********************************************/
929
930 function confirmClick() {
931 /*jshint validthis:true */
932 var message = jQuery( this ).data( 'frmconfirm' );
933 return confirm( message );
934 }
935
936 function toggleDiv() {
937 /*jshint validthis:true */
938 var div = jQuery( this ).data( 'frmtoggle' );
939 if ( jQuery( div ).is( ':visible' ) ) {
940 jQuery( div ).slideUp( 'fast' );
941 } else {
942 jQuery( div ).slideDown( 'fast' );
943 }
944 return false;
945 }
946
947 /**********************************************
948 * Fallback functions
949 *********************************************/
950
951 function addIndexOfFallbackForIE8() {
952 var len, from;
953
954 if ( ! Array.prototype.indexOf ) {
955 Array.prototype.indexOf = function( elt /*, from*/ ) {
956 len = this.length >>> 0;
957
958 from = Number( arguments[1]) || 0;
959 from = ( from < 0 ) ? Math.ceil( from ) : Math.floor( from );
960 if ( from < 0 ) {
961 from += len;
962 }
963
964 for ( ; from < len; from++ ) {
965 if ( from in this && this[from] === elt ) {
966 return from;
967 }
968 }
969 return -1;
970 };
971 }
972 }
973
974 function addTrimFallbackForIE8() {
975 if ( typeof String.prototype.trim !== 'function' ) {
976 String.prototype.trim = function() {
977 return this.replace( /^\s+|\s+$/g, '' );
978 };
979 }
980 }
981
982 function addFilterFallbackForIE8() {
983 var t, len, res, thisp, i, val;
984
985 if ( ! Array.prototype.filter ) {
986
987 Array.prototype.filter = function( fun /*, thisp */ ) {
988
989 if ( this === void 0 || this === null ) {
990 throw new TypeError();
991 }
992
993 t = Object( this );
994 len = t.length >>> 0;
995 if ( typeof fun !== 'function' ) {
996 throw new TypeError();
997 }
998
999 res = [];
1000 thisp = arguments[1];
1001 for ( i = 0; i < len; i++ ) {
1002 if ( i in t ) {
1003 val = t[i]; // in case fun mutates this
1004 if ( fun.call( thisp, val, i, t ) ) {
1005 res.push( val );
1006 }
1007 }
1008 }
1009
1010 return res;
1011 };
1012 }
1013 }
1014
1015 function addKeysFallbackForIE8() {
1016 var keys, i;
1017
1018 if ( ! Object.keys ) {
1019 Object.keys = function( obj ) {
1020 keys = [];
1021
1022 for ( i in obj ) {
1023 if ( obj.hasOwnProperty( i ) ) {
1024 keys.push( i );
1025 }
1026 }
1027
1028 return keys;
1029 };
1030 }
1031 }
1032
1033 /**
1034 * Check for -webkit-box-shadow css value for input:-webkit-autofill selector.
1035 * If this is a match, the User is autofilling the input on a Webkit browser.
1036 * We want to delete the Honeypot field, otherwise it will get triggered as spam on autocomplete.
1037 */
1038 function onHoneypotFieldChange() {
1039 var css = jQuery( this ).css( 'box-shadow' );
1040 if ( css.match( /inset/ ) ) {
1041 this.parentNode.removeChild( this );
1042 }
1043 }
1044
1045 /**
1046 * Focus on the first sub field when clicking to the primary label of combo field.
1047 *
1048 * @since 4.10.02
1049 */
1050 function changeFocusWhenClickComboFieldLabel() {
1051 let label;
1052
1053 const comboInputsContainer = document.querySelectorAll( '.frm_combo_inputs_container' );
1054 comboInputsContainer.forEach( function( inputsContainer ) {
1055 if ( ! inputsContainer.closest( '.frm_form_field' ) ) {
1056 return;
1057 }
1058
1059 label = inputsContainer.closest( '.frm_form_field' ).querySelector( '.frm_primary_label' );
1060 if ( ! label ) {
1061 return;
1062 }
1063
1064 label.addEventListener( 'click', function( e ) {
1065 inputsContainer.querySelector( '.frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea' ).focus();
1066 });
1067 });
1068 }
1069
1070 function checkForErrorsAndMaybeSetFocus() {
1071 var errors, element, timeoutCallback;
1072
1073 errors = document.querySelectorAll( '.frm_form_field .frm_error' );
1074 if ( ! errors.length ) {
1075 return;
1076 }
1077
1078 element = errors[0];
1079 do {
1080 element = element.previousSibling;
1081 if ( -1 !== [ 'input', 'select', 'textarea' ].indexOf( element.nodeName.toLowerCase() ) ) {
1082 element.focus();
1083 break;
1084 }
1085
1086 if ( 'undefined' !== typeof element.classList ) {
1087 if ( element.classList.contains( 'html-active' ) ) {
1088 timeoutCallback = function() {
1089 var textarea = element.querySelector( 'textarea' );
1090 if ( null !== textarea ) {
1091 textarea.focus();
1092 }
1093 };
1094 } else if ( element.classList.contains( 'tmce-active' ) ) {
1095 timeoutCallback = function() {
1096 tinyMCE.activeEditor.focus();
1097 };
1098 }
1099
1100 if ( 'function' === typeof timeoutCallback ) {
1101 setTimeout( timeoutCallback, 0 );
1102 break;
1103 }
1104 }
1105 } while ( element.previousSibling );
1106 }
1107
1108 return {
1109 init: function() {
1110 jQuery( document ).off( 'submit.formidable', '.frm-show-form' );
1111 jQuery( document ).on( 'submit.formidable', '.frm-show-form', frmFrontForm.submitForm );
1112
1113 jQuery( '.frm-show-form input[onblur], .frm-show-form textarea[onblur]' ).each( function() {
1114 if ( jQuery( this ).val() === '' ) {
1115 jQuery( this ).trigger( 'blur' );
1116 }
1117 });
1118
1119 jQuery( document ).on( 'focus', '.frm_toggle_default', clearDefault );
1120 jQuery( document ).on( 'blur', '.frm_toggle_default', replaceDefault );
1121 jQuery( '.frm_toggle_default' ).trigger( 'blur' );
1122
1123 jQuery( document.getElementById( 'frm_resend_email' ) ).on( 'click', resendEmail );
1124
1125 jQuery( document ).on( 'change', '.frm-show-form input[name^="item_meta"], .frm-show-form select[name^="item_meta"], .frm-show-form textarea[name^="item_meta"]', frmFrontForm.fieldValueChanged );
1126 jQuery( document ).on( 'change keyup', '.frm-show-form .frm_inside_container input, .frm-show-form .frm_inside_container select, .frm-show-form .frm_inside_container textarea', maybeShowLabel );
1127
1128 jQuery( document ).on( 'change', '[id^=frm_email_]', onHoneypotFieldChange );
1129
1130 jQuery( document ).on( 'click', 'a[data-frmconfirm]', confirmClick );
1131 jQuery( 'a[data-frmtoggle]' ).on( 'click', toggleDiv );
1132
1133 checkForErrorsAndMaybeSetFocus();
1134
1135 // Focus on the first sub field when clicking to the primary label of combo field.
1136 changeFocusWhenClickComboFieldLabel();
1137
1138 // Add fallbacks for the beloved IE8
1139 addIndexOfFallbackForIE8();
1140 addTrimFallbackForIE8();
1141 addFilterFallbackForIE8();
1142 addKeysFallbackForIE8();
1143 },
1144
1145 getFieldId: function( field, fullID ) {
1146 return getFieldId( field, fullID );
1147 },
1148
1149 renderRecaptcha: function( captcha ) {
1150 var formID, recaptchaID,
1151 size = captcha.getAttribute( 'data-size' ),
1152 rendered = captcha.getAttribute( 'data-rid' ) !== null,
1153 params = {
1154 'sitekey': captcha.getAttribute( 'data-sitekey' ),
1155 'size': size,
1156 'theme': captcha.getAttribute( 'data-theme' )
1157 };
1158
1159 if ( rendered ) {
1160 return;
1161 }
1162
1163 if ( size === 'invisible' ) {
1164 formID = jQuery( captcha ).closest( 'form' ).find( 'input[name="form_id"]' ).val();
1165 jQuery( captcha ).closest( '.frm_form_field .frm_primary_label' ).hide();
1166 params.callback = function( token ) {
1167 frmFrontForm.afterRecaptcha( token, formID );
1168 };
1169 }
1170
1171 recaptchaID = grecaptcha.render( captcha.id, params );
1172
1173 captcha.setAttribute( 'data-rid', recaptchaID );
1174 },
1175
1176 afterSingleRecaptcha: function() {
1177 var object = jQuery( '.frm-show-form .g-recaptcha' ).closest( 'form' )[0];
1178 frmFrontForm.submitFormNow( object );
1179 },
1180
1181 afterRecaptcha: function( token, formID ) {
1182 var object = jQuery( '#frm_form_' + formID + '_container form' )[0];
1183 frmFrontForm.submitFormNow( object );
1184 },
1185
1186 submitForm: function( e ) {
1187 frmFrontForm.submitFormManual( e, this );
1188 },
1189
1190 submitFormManual: function( e, object ) {
1191 var isPro, errors,
1192 invisibleRecaptcha = hasInvisibleRecaptcha( object ),
1193 classList = object.className.trim().split( /\s+/gi );
1194
1195 if ( classList && invisibleRecaptcha.length < 1 ) {
1196 isPro = classList.indexOf( 'frm_pro_form' ) > -1;
1197 if ( ! isPro ) {
1198 return;
1199 }
1200 }
1201
1202 if ( jQuery( 'body' ).hasClass( 'wp-admin' ) && jQuery( object ).closest( '.frmapi-form' ).length < 1 ) {
1203 return;
1204 }
1205
1206 e.preventDefault();
1207
1208 if ( typeof frmProForm !== 'undefined' && typeof frmProForm.submitAllowed === 'function' ) {
1209 if ( ! frmProForm.submitAllowed( object ) ) {
1210 return;
1211 }
1212 }
1213
1214 if ( invisibleRecaptcha.length ) {
1215 showLoadingIndicator( jQuery( object ) );
1216 executeInvisibleRecaptcha( invisibleRecaptcha );
1217 } else {
1218
1219 errors = frmFrontForm.validateFormSubmit( object );
1220
1221 if ( Object.keys( errors ).length === 0 ) {
1222 showSubmitLoading( jQuery( object ) );
1223
1224 frmFrontForm.submitFormNow( object, classList );
1225 }
1226 }
1227 },
1228
1229 submitFormNow: function( object ) {
1230 var hasFileFields, antispamInput,
1231 classList = object.className.trim().split( /\s+/gi );
1232
1233 if ( object.hasAttribute( 'data-token' ) && null === object.querySelector( '[name="antispam_token"]' ) ) {
1234 // include the antispam token on form submit.
1235 antispamInput = document.createElement( 'input' );
1236 antispamInput.type = 'hidden';
1237 antispamInput.name = 'antispam_token';
1238 antispamInput.value = object.getAttribute( 'data-token' );
1239 object.appendChild( antispamInput );
1240 }
1241
1242 if ( classList.indexOf( 'frm_ajax_submit' ) > -1 ) {
1243 hasFileFields = jQuery( object ).find( 'input[type="file"]' ).filter( function() {
1244 return !! this.value;
1245 }).length;
1246 if ( hasFileFields < 1 ) {
1247 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1248 frmFrontForm.checkFormErrors( object, action );
1249 } else {
1250 object.submit();
1251 }
1252 } else {
1253 object.submit();
1254 }
1255 },
1256
1257 validateFormSubmit: function( object ) {
1258 if ( typeof tinyMCE !== 'undefined' && jQuery( object ).find( '.wp-editor-wrap' ).length ) {
1259 tinyMCE.triggerSave();
1260 }
1261
1262 jsErrors = [];
1263
1264 if ( shouldJSValidate( object ) ) {
1265 frmFrontForm.getAjaxFormErrors( object );
1266
1267 if ( Object.keys( jsErrors ).length ) {
1268 frmFrontForm.addAjaxFormErrors( object );
1269 }
1270 }
1271
1272 return jsErrors;
1273 },
1274
1275 getAjaxFormErrors: function( object ) {
1276 var customErrors, key;
1277
1278 jsErrors = validateForm( object );
1279 if ( typeof frmThemeOverride_jsErrors === 'function' ) { // eslint-disable-line camelcase
1280 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1281 customErrors = frmThemeOverride_jsErrors( action, object );
1282 if ( Object.keys( customErrors ).length ) {
1283 for ( key in customErrors ) {
1284 jsErrors[ key ] = customErrors[ key ];
1285 }
1286 }
1287 }
1288
1289 return jsErrors;
1290 },
1291
1292 addAjaxFormErrors: function( object ) {
1293 var key, $fieldCont;
1294 removeAllErrors();
1295
1296 for ( key in jsErrors ) {
1297 $fieldCont = jQuery( object ).find( '#frm_field_' + key + '_container' );
1298
1299 if ( $fieldCont.length ) {
1300 addFieldError( $fieldCont, key, jsErrors );
1301 } else {
1302 // we are unable to show the error, so remove it
1303 delete jsErrors[ key ];
1304 }
1305 }
1306
1307 scrollToFirstField( object );
1308 checkForErrorsAndMaybeSetFocus();
1309 },
1310
1311 checkFormErrors: function( object, action ) {
1312 getFormErrors( object, action );
1313 },
1314
1315 checkRequiredField: function( field, errors ) {
1316 return checkRequiredField( field, errors );
1317 },
1318
1319 showSubmitLoading: function( $object ) {
1320 showSubmitLoading( $object );
1321 },
1322
1323 removeSubmitLoading: function( $object, enable, processesRunning ) {
1324 removeSubmitLoading( $object, enable, processesRunning );
1325 },
1326
1327 scrollToID: function( id ) {
1328 var object = jQuery( document.getElementById( id ) );
1329 frmFrontForm.scrollMsg( object, false );
1330 },
1331
1332 scrollMsg: function( id, object, animate ) {
1333 var newPos, m, b, screenTop, screenBottom,
1334 scrollObj = '';
1335 if ( typeof object === 'undefined' ) {
1336 scrollObj = jQuery( document.getElementById( 'frm_form_' + id + '_container' ) );
1337 if ( scrollObj.length < 1 ) {
1338 return;
1339 }
1340 } else if ( typeof id === 'string' ) {
1341 scrollObj = jQuery( object ).find( '#frm_field_' + id + '_container' );
1342 } else {
1343 scrollObj = id;
1344 }
1345
1346 jQuery( scrollObj ).trigger( 'focus' );
1347 newPos = scrollObj.offset().top;
1348 if ( ! newPos || frm_js.offset === '-1' ) {
1349 return;
1350 }
1351 newPos = newPos - frm_js.offset;
1352
1353 m = jQuery( 'html' ).css( 'margin-top' );
1354 b = jQuery( 'body' ).css( 'margin-top' );
1355 if ( m || b ) {
1356 newPos = newPos - parseInt( m ) - parseInt( b );
1357 }
1358
1359 if ( newPos && window.innerHeight ) {
1360 screenTop = document.documentElement.scrollTop || document.body.scrollTop;
1361 screenBottom = screenTop + window.innerHeight;
1362
1363 if ( newPos > screenBottom || newPos < screenTop ) {
1364 // Not in view
1365 if ( typeof animate === 'undefined' ) {
1366 jQuery( window ).scrollTop( newPos );
1367 } else {
1368 jQuery( 'html,body' ).animate({ scrollTop: newPos }, 500 );
1369 }
1370 return false;
1371 }
1372 }
1373 },
1374
1375 fieldValueChanged: function( e ) {
1376 /*jshint validthis:true */
1377
1378 var fieldId = frmFrontForm.getFieldId( this, false );
1379 if ( ! fieldId || typeof fieldId === 'undefined' ) {
1380 return;
1381 }
1382
1383 if ( e.frmTriggered && e.frmTriggered == fieldId ) {
1384 return;
1385 }
1386
1387 jQuery( document ).trigger( 'frmFieldChanged', [ this, fieldId, e ]);
1388
1389 if ( e.selfTriggered !== true ) {
1390 maybeValidateChange( this );
1391 }
1392 },
1393
1394 savingDraft: function( object ) {
1395 console.warn( 'DEPRECATED: function frmFrontForm.savingDraft in v3.0 use frmProForm.savingDraft' );
1396 if ( typeof frmProForm !== 'undefined' ) {
1397 return frmProForm.savingDraft( object );
1398 }
1399 },
1400
1401 goingToPreviousPage: function( object ) {
1402 console.warn( 'DEPRECATED: function frmFrontForm.goingToPreviousPage in v3.0 use frmProForm.goingToPreviousPage' );
1403 if ( typeof frmProForm !== 'undefined' ) {
1404 return frmProForm.goingToPreviousPage( object );
1405 }
1406 },
1407
1408 hideOrShowFields: function() {
1409 console.warn( 'DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields' );
1410 if ( typeof frmProForm !== 'undefined' ) {
1411 frmProForm.hideOrShowFields();
1412 }
1413 },
1414
1415 hidePreviouslyHiddenFields: function() {
1416 console.warn( 'DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields' );
1417 if ( typeof frmProForm !== 'undefined' ) {
1418 frmProForm.hidePreviouslyHiddenFields();
1419 }
1420 },
1421
1422 checkDependentDynamicFields: function( ids ) {
1423 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields' );
1424 if ( typeof frmProForm !== 'undefined' ) {
1425 frmProForm.checkDependentDynamicFields( ids );
1426 }
1427 },
1428
1429 checkDependentLookupFields: function( ids ) {
1430 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields' );
1431 if ( typeof frmProForm !== 'undefined' ) {
1432 frmProForm.checkDependentLookupFields( ids );
1433 }
1434 },
1435
1436 loadGoogle: function() {
1437 console.warn( 'DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle' );
1438 frmProForm.loadGoogle();
1439 },
1440
1441 escapeHtml: function( text ) {
1442 return text
1443 .replace( /&/g, '&amp;' )
1444 .replace( /</g, '&lt;' )
1445 .replace( />/g, '&gt;' )
1446 .replace( /"/g, '&quot;' )
1447 .replace( /'/g, '&#039;' );
1448 },
1449
1450 invisible: function( classes ) {
1451 jQuery( classes ).css( 'visibility', 'hidden' );
1452 },
1453
1454 visible: function( classes ) {
1455 jQuery( classes ).css( 'visibility', 'visible' );
1456 }
1457 };
1458 }
1459 frmFrontForm = frmFrontFormJS();
1460
1461 jQuery( document ).ready( function() {
1462 frmFrontForm.init();
1463 });
1464
1465 function frmRecaptcha() {
1466 var c, cl,
1467 captchas = jQuery( '.frm-g-recaptcha' );
1468 for ( c = 0, cl = captchas.length; c < cl; c++ ) {
1469 frmFrontForm.renderRecaptcha( captchas[c]);
1470 }
1471 }
1472
1473 function frmAfterRecaptcha( token ) {
1474 frmFrontForm.afterSingleRecaptcha( token );
1475 }
1476
1477 function frmUpdateField( entryId, fieldId, value, message, num ) {
1478 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).html( '<span class="frm-loading-img"></span>' );
1479 jQuery.ajax({
1480 type: 'POST',
1481 url: frm_js.ajax_url,
1482 data: {
1483 action: 'frm_entries_update_field_ajax',
1484 entry_id: entryId,
1485 field_id: fieldId,
1486 value: value,
1487 nonce: frm_js.nonce
1488 },
1489 success: function() {
1490 if ( message.replace( /^\s+|\s+$/g, '' ) === '' ) {
1491 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).fadeOut( 'slow' );
1492 } else {
1493 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).replaceWith( message );
1494 }
1495 }
1496 });
1497 }
1498
1499 function frmDeleteEntry( entryId, prefix ) {
1500 console.warn( 'DEPRECATED: function frmDeleteEntry in v2.0.13 use frmFrontForm.deleteEntry' );
1501 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( '<span class="frm-loading-img" id="frm_delete_' + entryId + '"></span>' );
1502 jQuery.ajax({
1503 type: 'POST',
1504 url: frm_js.ajax_url,
1505 data: {
1506 action: 'frm_entries_destroy',
1507 entry: entryId,
1508 nonce: frm_js.nonce
1509 },
1510 success: function( html ) {
1511 if ( html.replace( /^\s+|\s+$/g, '' ) === 'success' ) {
1512 jQuery( document.getElementById( prefix + entryId ) ).fadeOut( 'slow' );
1513 } else {
1514 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( html );
1515 }
1516 }
1517 });
1518 }
1519
1520 function frmOnSubmit( e ) {
1521 console.warn( 'DEPRECATED: function frmOnSubmit in v2.0 use frmFrontForm.submitForm' );
1522 frmFrontForm.submitForm( e, this );
1523 }
1524
1525 function frm_resend_email( entryId, formId ) { // eslint-disable-line camelcase
1526 var $link = jQuery( document.getElementById( 'frm_resend_email' ) );
1527 console.warn( 'DEPRECATED: function frm_resend_email in v2.0' );
1528 $link.append( '<span class="spinner" style="display:inline"></span>' );
1529 jQuery.ajax({
1530 type: 'POST',
1531 url: frm_js.ajax_url,
1532 data: {
1533 action: 'frm_entries_send_email',
1534 entry_id: entryId,
1535 form_id: formId,
1536 nonce: frm_js.nonce
1537 },
1538 success: function( msg ) {
1539 $link.replaceWith( msg );
1540 }
1541 });
1542 }
1543