PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0.14
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0.14
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.0.14, at js/formidable.js

1,533 lines 42.7 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 && ! hasClass( field, 'ssa_appointment_form_field_appointment_id' ) ) {
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 getFileVals( fileID ) {
347 var val = '',
348 fileFields = jQuery( 'input[name="file' + fileID + '"], input[name="file' + fileID + '[]"], input[name^="item_meta[' + fileID + ']"]' );
349
350 fileFields.each( function() {
351 if ( val === '' ) {
352 val = this.value;
353 }
354 });
355 return val;
356 }
357
358 function checkUrlField( field, errors ) {
359 var fieldID,
360 url = field.value;
361
362 if ( url !== '' && ! /^http(s)?:\/\/(?:localhost|(?:[\da-z\.-]+\.[\da-z\.-]+))/i.test( url ) ) {
363 fieldID = getFieldId( field, true );
364 if ( ! ( fieldID in errors ) ) {
365 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
366 }
367 }
368 return errors;
369 }
370
371 function checkEmailField( field, errors ) {
372 var fieldID = getFieldId( field, true ),
373 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;
374
375 // validate the current field we're editing first
376 if ( '' !== field.value && pattern.test( field.value ) === false ) {
377 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
378 }
379
380 confirmField( field, errors );
381 return errors;
382 }
383
384 function checkPasswordField( field, errors ) {
385 confirmField( field, errors );
386 return errors;
387 }
388
389 function confirmField( field, errors ) {
390 var value, confirmValue, firstField,
391 fieldID = getFieldId( field, true ),
392 strippedId = field.id.replace( 'conf_', '' ),
393 strippedFieldID = fieldID.replace( 'conf_', '' ),
394 confirmField = document.getElementById( strippedId.replace( 'field_', 'field_conf_' ) );
395
396 if ( confirmField === null || typeof errors[ 'conf_' + strippedFieldID ] !== 'undefined' ) {
397 return;
398 }
399
400 if ( fieldID !== strippedFieldID ) {
401 firstField = document.getElementById( strippedId );
402 value = firstField.value;
403 confirmValue = confirmField.value;
404 if ( '' !== value && '' !== confirmValue && value !== confirmValue ) {
405 errors[ 'conf_' + strippedFieldID ] = getFieldValidationMessage( confirmField, 'data-confmsg' );
406 }
407 } else {
408 validateField( confirmField );
409 }
410 }
411
412 function checkNumberField( field, errors ) {
413 var fieldID,
414 number = field.value;
415
416 if ( number !== '' && isNaN( number / 1 ) !== false ) {
417 fieldID = getFieldId( field, true );
418 if ( ! ( fieldID in errors ) ) {
419 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
420 }
421 }
422 return errors;
423 }
424
425 function checkPatternField( field, errors ) {
426 var fieldID,
427 text = field.value,
428 format = getFieldValidationMessage( field, 'pattern' );
429
430 if ( format !== '' && text !== '' ) {
431 fieldID = getFieldId( field, true );
432 if ( ! ( fieldID in errors ) ) {
433 format = new RegExp( '^' + format + '$', 'i' );
434 if ( format.test( text ) === false ) {
435 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
436 }
437 }
438 }
439 return errors;
440 }
441
442 function hasInvisibleRecaptcha( object ) {
443 var recaptcha, recaptchaID, alreadyChecked;
444
445 if ( isGoingToPrevPage( object ) ) {
446 return false;
447 }
448
449 recaptcha = jQuery( object ).find( '.frm-g-recaptcha[data-size="invisible"], .g-recaptcha[data-size="invisible"]' );
450 if ( recaptcha.length ) {
451 recaptchaID = recaptcha.data( 'rid' );
452 alreadyChecked = grecaptcha.getResponse( recaptchaID );
453 if ( alreadyChecked.length === 0 ) {
454 return recaptcha;
455 } else {
456 return false;
457 }
458 } else {
459 return false;
460 }
461 }
462
463 function executeInvisibleRecaptcha( invisibleRecaptcha ) {
464 var recaptchaID = invisibleRecaptcha.data( 'rid' );
465 grecaptcha.reset( recaptchaID );
466 grecaptcha.execute( recaptchaID );
467 }
468
469 function validateRecaptcha( form, errors ) {
470 var recaptchaID, response, fieldContainer, fieldID,
471 $recaptcha = jQuery( form ).find( '.frm-g-recaptcha' );
472 if ( $recaptcha.length ) {
473 recaptchaID = $recaptcha.data( 'rid' );
474
475 try {
476 response = grecaptcha.getResponse( recaptchaID );
477 } catch ( e ) {
478 if ( jQuery( form ).find( 'input[name="recaptcha_checked"]' ).length ) {
479 return errors;
480 } else {
481 response = '';
482 }
483 }
484
485 if ( response.length === 0 ) {
486 fieldContainer = $recaptcha.closest( '.frm_form_field' );
487 fieldID = fieldContainer.attr( 'id' ).replace( 'frm_field_', '' ).replace( '_container', '' );
488 errors[ fieldID ] = '';
489 }
490 }
491 return errors;
492 }
493
494 function getFieldValidationMessage( field, messageType ) {
495 var msg, errorHtml;
496
497 msg = field.getAttribute( messageType );
498 if ( null === msg ) {
499 msg = '';
500 }
501
502 if ( '' !== msg && shouldWrapErrorHtmlAroundMessageType( messageType ) ) {
503 errorHtml = field.getAttribute( 'data-error-html' );
504 if ( null !== errorHtml ) {
505 errorHtml = errorHtml.replace( /\+/g, '%20' );
506 msg = decodeURIComponent( errorHtml ).replace( '[error]', msg );
507 msg = msg.replace( '[key]', getFieldId( field, false ) );
508 }
509 }
510
511 return msg;
512 }
513
514 function shouldWrapErrorHtmlAroundMessageType( type ) {
515 return 'pattern' !== type;
516 }
517
518 function shouldJSValidate( object ) {
519 var validate = jQuery( object ).hasClass( 'frm_js_validate' );
520 if ( validate && typeof frmProForm !== 'undefined' && ( frmProForm.savingDraft( object ) || frmProForm.goingToPreviousPage( object ) ) ) {
521 validate = false;
522 }
523
524 return validate;
525 }
526
527 function getFormErrors( object, action ) {
528 var fieldset;
529
530 if ( typeof action === 'undefined' ) {
531 jQuery( object ).find( 'input[name="frm_action"]' ).val();
532 }
533
534 fieldset = jQuery( object ).find( '.frm_form_field' );
535 fieldset.addClass( 'frm_doing_ajax' );
536 jQuery.ajax({
537 type: 'POST', url: frm_js.ajax_url,
538 data: jQuery( object ).serialize() + '&action=frm_entries_' + action + '&nonce=' + frm_js.nonce,
539 success: function( response ) {
540 var formID, replaceContent, pageOrder, formReturned, contSubmit, delay,
541 $fieldCont, key, inCollapsedSection, frmTrigger,
542 defaultResponse = { 'content': '', 'errors': {}, 'pass': false };
543 if ( response === null ) {
544 response = defaultResponse;
545 }
546
547 response = response.replace( /^\s+|\s+$/g, '' );
548 if ( response.indexOf( '{' ) === 0 ) {
549 response = JSON.parse( response );
550 } else {
551 response = defaultResponse;
552 }
553
554 if ( typeof response.redirect !== 'undefined' ) {
555 jQuery( document ).trigger( 'frmBeforeFormRedirect', [ object, response ]);
556 window.location = response.redirect;
557 } else if ( response.content !== '' ) {
558 // the form or success message was returned
559
560 removeSubmitLoading( jQuery( object ) );
561 if ( frm_js.offset != -1 ) {
562 frmFrontForm.scrollMsg( jQuery( object ), false );
563 }
564 formID = jQuery( object ).find( 'input[name="form_id"]' ).val();
565 response.content = response.content.replace( / frm_pro_form /g, ' frm_pro_form frm_no_hide ' );
566 replaceContent = jQuery( object ).closest( '.frm_forms' );
567 removeAddedScripts( replaceContent, formID );
568 delay = maybeSlideOut( replaceContent, response.content );
569
570 setTimeout(
571 function() {
572 var container, input, previousInput;
573
574 replaceContent.replaceWith( response.content );
575
576 addUrlParam( response );
577
578 if ( typeof frmThemeOverride_frmAfterSubmit === 'function' ) { // eslint-disable-line camelcase
579 pageOrder = jQuery( 'input[name="frm_page_order_' + formID + '"]' ).val();
580 formReturned = jQuery( response.content ).find( 'input[name="form_id"]' ).val();
581 frmThemeOverride_frmAfterSubmit( formReturned, pageOrder, response.content, object );
582 }
583
584 if ( typeof response.recaptcha !== 'undefined' ) {
585 container = jQuery( '#frm_form_' + formID + '_container' ).find( '.frm_fields_container' );
586 input = '<input type="hidden" name="recaptcha_checked" value="' + response.recaptcha + '">';
587 previousInput = container.find( 'input[name="recaptcha_checked"]' );
588
589 if ( previousInput.length ) {
590 previousInput.replaceWith( input );
591 } else {
592 container.append( input );
593 }
594 }
595
596 afterFormSubmitted( object, response );
597 },
598 delay
599 );
600 } else if ( Object.keys( response.errors ).length ) {
601 // errors were returned
602
603 removeSubmitLoading( jQuery( object ), 'enable' );
604
605 //show errors
606 contSubmit = true;
607 removeAllErrors();
608
609 $fieldCont = null;
610
611 for ( key in response.errors ) {
612 $fieldCont = jQuery( object ).find( '#frm_field_' + key + '_container' );
613
614 if ( $fieldCont.length ) {
615 if ( ! $fieldCont.is( ':visible' ) ) {
616 inCollapsedSection = $fieldCont.closest( '.frm_toggle_container' );
617 if ( inCollapsedSection.length ) {
618 frmTrigger = inCollapsedSection.prev();
619 if ( ! frmTrigger.hasClass( 'frm_trigger' ) ) {
620 // If the frmTrigger object is the section description, check to see if the previous element is the trigger
621 frmTrigger = frmTrigger.prev( '.frm_trigger' );
622 }
623 frmTrigger.trigger( 'click' );
624 }
625 }
626
627 if ( $fieldCont.is( ':visible' ) ) {
628 addFieldError( $fieldCont, key, response.errors );
629 contSubmit = false;
630 }
631 }
632 }
633
634 jQuery( object ).find( '.frm-g-recaptcha, .g-recaptcha' ).each( function() {
635 var $recaptcha = jQuery( this ),
636 recaptchaID = $recaptcha.data( 'rid' );
637
638 if ( typeof grecaptcha !== 'undefined' && grecaptcha ) {
639 if ( recaptchaID ) {
640 grecaptcha.reset( recaptchaID );
641 } else {
642 grecaptcha.reset();
643 }
644 }
645 });
646
647 jQuery( document ).trigger( 'frmFormErrors', [ object, response ]);
648
649 fieldset.removeClass( 'frm_doing_ajax' );
650 scrollToFirstField( object );
651
652 if ( contSubmit ) {
653 object.submit();
654 } else {
655 jQuery( object ).prepend( response.error_message );
656 checkForErrorsAndMaybeSetFocus();
657 }
658 } else {
659 // there may have been a plugin conflict, or the form is not set to submit with ajax
660
661 showFileLoading( object );
662
663 object.submit();
664 }
665 },
666 error: function() {
667 jQuery( object ).find( 'input[type="submit"], input[type="button"]' ).prop( 'disabled', false );
668 object.submit();
669 }
670 });
671 }
672
673 function afterFormSubmitted( object, response ) {
674 var formCompleted = jQuery( response.content ).find( '.frm_message' );
675 if ( formCompleted.length ) {
676 jQuery( document ).trigger( 'frmFormComplete', [ object, response ]);
677 } else {
678 jQuery( document ).trigger( 'frmPageChanged', [ object, response ]);
679 }
680 }
681
682 function removeAddedScripts( formContainer, formID ) {
683 var endReplace = jQuery( '.frm_end_ajax_' + formID );
684 if ( endReplace.length ) {
685 formContainer.nextUntil( '.frm_end_ajax_' + formID ).remove();
686 endReplace.remove();
687 }
688 }
689
690 function maybeSlideOut( oldContent, newContent ) {
691 var c,
692 newClass = 'frm_slideout';
693 if ( newContent.indexOf( ' frm_slide' ) !== -1 ) {
694 c = oldContent.children();
695 if ( newContent.indexOf( ' frm_going_back' ) !== -1 ) {
696 newClass += ' frm_going_back';
697 }
698 c.removeClass( 'frm_going_back' );
699 c.addClass( newClass );
700 return 300;
701 }
702 return 0;
703 }
704
705 function addUrlParam( response ) {
706 var url;
707 if ( history.pushState && typeof response.page !== 'undefined' ) {
708 url = addQueryVar( 'frm_page', response.page );
709 window.history.pushState({ 'html': response.html }, '', '?' + url );
710 }
711 }
712
713 function addQueryVar( key, value ) {
714 var kvp, i, x;
715
716 key = encodeURI( key );
717 value = encodeURI( value );
718
719 kvp = document.location.search.substr( 1 ).split( '&' );
720
721 i = kvp.length;
722 while ( i-- ) {
723 x = kvp[i].split( '=' );
724
725 if ( x[0] == key ) {
726 x[1] = value;
727 kvp[i] = x.join( '=' );
728 break;
729 }
730 }
731
732 if ( i < 0 ) {
733 kvp[ kvp.length ] = [ key, value ].join( '=' );
734 }
735
736 return kvp.join( '&' );
737 }
738
739 function addFieldError( $fieldCont, key, jsErrors ) {
740 var input, id, describedBy;
741 if ( $fieldCont.length && $fieldCont.is( ':visible' ) ) {
742 $fieldCont.addClass( 'frm_blank_field' );
743 input = $fieldCont.find( 'input, select, textarea' );
744 id = 'frm_error_field_' + key;
745 describedBy = input.attr( 'aria-describedby' );
746
747 if ( typeof frmThemeOverride_frmPlaceError === 'function' ) { // eslint-disable-line camelcase
748 frmThemeOverride_frmPlaceError( key, jsErrors );
749 } else {
750 if ( -1 !== jsErrors[key].indexOf( '<div' ) ) {
751 $fieldCont.append(
752 jsErrors[key]
753 );
754 } else {
755 $fieldCont.append( '<div class="frm_error" id="' + id + '">' + jsErrors[key] + '</div>' );
756 }
757
758 if ( typeof describedBy === 'undefined' ) {
759 describedBy = id;
760 } else if ( describedBy.indexOf( id ) === -1 ) {
761 describedBy = describedBy + ' ' + id;
762 }
763 input.attr( 'aria-describedby', describedBy );
764 }
765 input.attr( 'aria-invalid', true );
766
767 jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ]);
768 }
769 }
770
771 function removeFieldError( $fieldCont ) {
772 var errorMessage = $fieldCont.find( '.frm_error' ),
773 errorId = errorMessage.attr( 'id' ),
774 input = $fieldCont.find( 'input, select, textarea' ),
775 describedBy = input.attr( 'aria-describedby' );
776
777 $fieldCont.removeClass( 'frm_blank_field has-error' );
778 errorMessage.remove();
779 input.attr( 'aria-invalid', false );
780
781 if ( typeof describedBy !== 'undefined' ) {
782 describedBy = describedBy.replace( errorId, '' );
783 input.attr( 'aria-describedby', describedBy );
784 }
785 }
786
787 function removeAllErrors() {
788 jQuery( '.form-field' ).removeClass( 'frm_blank_field has-error' );
789 jQuery( '.form-field .frm_error' ).replaceWith( '' );
790 jQuery( '.frm_error_style' ).remove();
791 }
792
793 function scrollToFirstField( object ) {
794 var field = jQuery( object ).find( '.frm_blank_field' ).first();
795 if ( field.length ) {
796 frmFrontForm.scrollMsg( field, object, true );
797 }
798 }
799
800 function showSubmitLoading( $object ) {
801 showLoadingIndicator( $object );
802 disableSubmitButton( $object );
803 disableSaveDraft( $object );
804 }
805
806 function showLoadingIndicator( $object ) {
807 if ( ! $object.hasClass( 'frm_loading_form' ) && ! $object.hasClass( 'frm_loading_prev' ) ) {
808 addLoadingClass( $object );
809 $object.trigger( 'frmStartFormLoading' );
810 }
811 }
812
813 function addLoadingClass( $object ) {
814 var loadingClass = isGoingToPrevPage( $object ) ? 'frm_loading_prev' : 'frm_loading_form';
815
816 $object.addClass( loadingClass );
817 }
818
819 function isGoingToPrevPage( $object ) {
820 return ( typeof frmProForm !== 'undefined' && frmProForm.goingToPreviousPage( $object ) );
821 }
822
823 function removeSubmitLoading( $object, enable, processesRunning ) {
824 var loadingForm;
825
826 if ( processesRunning > 0 ) {
827 return;
828 }
829
830 loadingForm = jQuery( '.frm_loading_form' );
831 loadingForm.removeClass( 'frm_loading_form' );
832 loadingForm.removeClass( 'frm_loading_prev' );
833
834 loadingForm.trigger( 'frmEndFormLoading' );
835
836 if ( enable === 'enable' ) {
837 enableSubmitButton( loadingForm );
838 enableSaveDraft( loadingForm );
839 }
840 }
841
842 function showFileLoading( object ) {
843 var fileval,
844 loading = document.getElementById( 'frm_loading' );
845 if ( loading !== null ) {
846 fileval = jQuery( object ).find( 'input[type=file]' ).val();
847 if ( typeof fileval !== 'undefined' && fileval !== '' ) {
848 setTimeout( function() {
849 jQuery( loading ).fadeIn( 'slow' );
850 }, 2000 );
851 }
852 }
853 }
854
855 function clearDefault() {
856 /*jshint validthis:true */
857 toggleDefault( jQuery( this ), 'clear' );
858 }
859
860 function replaceDefault() {
861 /*jshint validthis:true */
862 toggleDefault( jQuery( this ), 'replace' );
863 }
864
865 function toggleDefault( $thisField, e ) {
866 // TODO: Fix this for a default value that is a number or array
867 var thisVal,
868 v = $thisField.data( 'frmval' ).replace( /(\n|\r\n)/g, '\r' );
869 if ( v === '' || typeof v === 'undefined' ) {
870 return false;
871 }
872 thisVal = $thisField.val().replace( /(\n|\r\n)/g, '\r' );
873
874 if ( 'replace' === e ) {
875 if ( thisVal === '' ) {
876 $thisField.addClass( 'frm_default' ).val( v );
877 }
878 } else if ( thisVal == v ) {
879 $thisField.removeClass( 'frm_default' ).val( '' );
880 }
881 }
882
883 function resendEmail() {
884 /*jshint validthis:true */
885 var $link = jQuery( this ),
886 entryId = this.getAttribute( 'data-eid' ),
887 formId = this.getAttribute( 'data-fid' ),
888 label = $link.find( '.frm_link_label' );
889 if ( label.length < 1 ) {
890 label = $link;
891 }
892 label.append( '<span class="frm-wait"></span>' );
893
894 jQuery.ajax({
895 type: 'POST',
896 url: frm_js.ajax_url,
897 data: {
898 action: 'frm_entries_send_email',
899 entry_id: entryId,
900 form_id: formId,
901 nonce: frm_js.nonce
902 },
903 success: function( msg ) {
904 var admin = document.getElementById( 'wpbody' );
905 if ( admin === null ) {
906 label.html( msg );
907 } else {
908 label.html( '' );
909 $link.after( msg );
910 }
911 }
912 });
913 return false;
914 }
915
916 /**********************************************
917 * General Helpers
918 *********************************************/
919
920 function confirmClick() {
921 /*jshint validthis:true */
922 var message = jQuery( this ).data( 'frmconfirm' );
923 return confirm( message );
924 }
925
926 function toggleDiv() {
927 /*jshint validthis:true */
928 var div = jQuery( this ).data( 'frmtoggle' );
929 if ( jQuery( div ).is( ':visible' ) ) {
930 jQuery( div ).slideUp( 'fast' );
931 } else {
932 jQuery( div ).slideDown( 'fast' );
933 }
934 return false;
935 }
936
937 /**********************************************
938 * Fallback functions
939 *********************************************/
940
941 function addIndexOfFallbackForIE8() {
942 var len, from;
943
944 if ( ! Array.prototype.indexOf ) {
945 Array.prototype.indexOf = function( elt /*, from*/ ) {
946 len = this.length >>> 0;
947
948 from = Number( arguments[1]) || 0;
949 from = ( from < 0 ) ? Math.ceil( from ) : Math.floor( from );
950 if ( from < 0 ) {
951 from += len;
952 }
953
954 for ( ; from < len; from++ ) {
955 if ( from in this && this[from] === elt ) {
956 return from;
957 }
958 }
959 return -1;
960 };
961 }
962 }
963
964 function addTrimFallbackForIE8() {
965 if ( typeof String.prototype.trim !== 'function' ) {
966 String.prototype.trim = function() {
967 return this.replace( /^\s+|\s+$/g, '' );
968 };
969 }
970 }
971
972 function addFilterFallbackForIE8() {
973 var t, len, res, thisp, i, val;
974
975 if ( ! Array.prototype.filter ) {
976
977 Array.prototype.filter = function( fun /*, thisp */ ) {
978
979 if ( this === void 0 || this === null ) {
980 throw new TypeError();
981 }
982
983 t = Object( this );
984 len = t.length >>> 0;
985 if ( typeof fun !== 'function' ) {
986 throw new TypeError();
987 }
988
989 res = [];
990 thisp = arguments[1];
991 for ( i = 0; i < len; i++ ) {
992 if ( i in t ) {
993 val = t[i]; // in case fun mutates this
994 if ( fun.call( thisp, val, i, t ) ) {
995 res.push( val );
996 }
997 }
998 }
999
1000 return res;
1001 };
1002 }
1003 }
1004
1005 function addKeysFallbackForIE8() {
1006 var keys, i;
1007
1008 if ( ! Object.keys ) {
1009 Object.keys = function( obj ) {
1010 keys = [];
1011
1012 for ( i in obj ) {
1013 if ( obj.hasOwnProperty( i ) ) {
1014 keys.push( i );
1015 }
1016 }
1017
1018 return keys;
1019 };
1020 }
1021 }
1022
1023 /**
1024 * Check for -webkit-box-shadow css value for input:-webkit-autofill selector.
1025 * If this is a match, the User is autofilling the input on a Webkit browser.
1026 * We want to delete the Honeypot field, otherwise it will get triggered as spam on autocomplete.
1027 */
1028 function onHoneypotFieldChange() {
1029 var css = jQuery( this ).css( 'box-shadow' );
1030 if ( css.match( /inset/ ) ) {
1031 this.parentNode.removeChild( this );
1032 }
1033 }
1034
1035 /**
1036 * Focus on the first sub field when clicking to the primary label of combo field.
1037 *
1038 * @since 4.10.02
1039 */
1040 function changeFocusWhenClickComboFieldLabel() {
1041 let label;
1042
1043 const comboInputsContainer = document.querySelectorAll( '.frm_combo_inputs_container' );
1044 comboInputsContainer.forEach( function( inputsContainer ) {
1045 if ( ! inputsContainer.closest( '.frm_form_field' ) ) {
1046 return;
1047 }
1048
1049 label = inputsContainer.closest( '.frm_form_field' ).querySelector( '.frm_primary_label' );
1050 if ( ! label ) {
1051 return;
1052 }
1053
1054 label.addEventListener( 'click', function( e ) {
1055 inputsContainer.querySelector( '.frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea' ).focus();
1056 });
1057 });
1058 }
1059
1060 function checkForErrorsAndMaybeSetFocus() {
1061 var errors, element, timeoutCallback;
1062
1063 errors = document.querySelectorAll( '.frm_form_field .frm_error' );
1064 if ( ! errors.length ) {
1065 return;
1066 }
1067
1068 element = errors[0];
1069 do {
1070 element = element.previousSibling;
1071 if ( -1 !== [ 'input', 'select', 'textarea' ].indexOf( element.nodeName.toLowerCase() ) ) {
1072 element.focus();
1073 break;
1074 }
1075
1076 if ( 'undefined' !== typeof element.classList ) {
1077 if ( element.classList.contains( 'html-active' ) ) {
1078 timeoutCallback = function() {
1079 var textarea = element.querySelector( 'textarea' );
1080 if ( null !== textarea ) {
1081 textarea.focus();
1082 }
1083 };
1084 } else if ( element.classList.contains( 'tmce-active' ) ) {
1085 timeoutCallback = function() {
1086 tinyMCE.activeEditor.focus();
1087 };
1088 }
1089
1090 if ( 'function' === typeof timeoutCallback ) {
1091 setTimeout( timeoutCallback, 0 );
1092 break;
1093 }
1094 }
1095 } while ( element.previousSibling );
1096 }
1097
1098 return {
1099 init: function() {
1100 jQuery( document ).off( 'submit.formidable', '.frm-show-form' );
1101 jQuery( document ).on( 'submit.formidable', '.frm-show-form', frmFrontForm.submitForm );
1102
1103 jQuery( '.frm-show-form input[onblur], .frm-show-form textarea[onblur]' ).each( function() {
1104 if ( jQuery( this ).val() === '' ) {
1105 jQuery( this ).trigger( 'blur' );
1106 }
1107 });
1108
1109 jQuery( document ).on( 'focus', '.frm_toggle_default', clearDefault );
1110 jQuery( document ).on( 'blur', '.frm_toggle_default', replaceDefault );
1111 jQuery( '.frm_toggle_default' ).trigger( 'blur' );
1112
1113 jQuery( document.getElementById( 'frm_resend_email' ) ).on( 'click', resendEmail );
1114
1115 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 );
1116 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 );
1117
1118 jQuery( document ).on( 'change', '[id^=frm_email_]', onHoneypotFieldChange );
1119
1120 jQuery( document ).on( 'click', 'a[data-frmconfirm]', confirmClick );
1121 jQuery( 'a[data-frmtoggle]' ).on( 'click', toggleDiv );
1122
1123 checkForErrorsAndMaybeSetFocus();
1124
1125 // Focus on the first sub field when clicking to the primary label of combo field.
1126 changeFocusWhenClickComboFieldLabel();
1127
1128 // Add fallbacks for the beloved IE8
1129 addIndexOfFallbackForIE8();
1130 addTrimFallbackForIE8();
1131 addFilterFallbackForIE8();
1132 addKeysFallbackForIE8();
1133 },
1134
1135 getFieldId: function( field, fullID ) {
1136 return getFieldId( field, fullID );
1137 },
1138
1139 renderRecaptcha: function( captcha ) {
1140 var formID, recaptchaID,
1141 size = captcha.getAttribute( 'data-size' ),
1142 rendered = captcha.getAttribute( 'data-rid' ) !== null,
1143 params = {
1144 'sitekey': captcha.getAttribute( 'data-sitekey' ),
1145 'size': size,
1146 'theme': captcha.getAttribute( 'data-theme' )
1147 };
1148
1149 if ( rendered ) {
1150 return;
1151 }
1152
1153 if ( size === 'invisible' ) {
1154 formID = jQuery( captcha ).closest( 'form' ).find( 'input[name="form_id"]' ).val();
1155 jQuery( captcha ).closest( '.frm_form_field .frm_primary_label' ).hide();
1156 params.callback = function( token ) {
1157 frmFrontForm.afterRecaptcha( token, formID );
1158 };
1159 }
1160
1161 recaptchaID = grecaptcha.render( captcha.id, params );
1162
1163 captcha.setAttribute( 'data-rid', recaptchaID );
1164 },
1165
1166 afterSingleRecaptcha: function() {
1167 var object = jQuery( '.frm-show-form .g-recaptcha' ).closest( 'form' )[0];
1168 frmFrontForm.submitFormNow( object );
1169 },
1170
1171 afterRecaptcha: function( token, formID ) {
1172 var object = jQuery( '#frm_form_' + formID + '_container form' )[0];
1173 frmFrontForm.submitFormNow( object );
1174 },
1175
1176 submitForm: function( e ) {
1177 frmFrontForm.submitFormManual( e, this );
1178 },
1179
1180 submitFormManual: function( e, object ) {
1181 var isPro, errors,
1182 invisibleRecaptcha = hasInvisibleRecaptcha( object ),
1183 classList = object.className.trim().split( /\s+/gi );
1184
1185 if ( classList && invisibleRecaptcha.length < 1 ) {
1186 isPro = classList.indexOf( 'frm_pro_form' ) > -1;
1187 if ( ! isPro ) {
1188 return;
1189 }
1190 }
1191
1192 if ( jQuery( 'body' ).hasClass( 'wp-admin' ) && jQuery( object ).closest( '.frmapi-form' ).length < 1 ) {
1193 return;
1194 }
1195
1196 e.preventDefault();
1197
1198 if ( typeof frmProForm !== 'undefined' && typeof frmProForm.submitAllowed === 'function' ) {
1199 if ( ! frmProForm.submitAllowed( object ) ) {
1200 return;
1201 }
1202 }
1203
1204 if ( invisibleRecaptcha.length ) {
1205 showLoadingIndicator( jQuery( object ) );
1206 executeInvisibleRecaptcha( invisibleRecaptcha );
1207 } else {
1208
1209 errors = frmFrontForm.validateFormSubmit( object );
1210
1211 if ( Object.keys( errors ).length === 0 ) {
1212 showSubmitLoading( jQuery( object ) );
1213
1214 frmFrontForm.submitFormNow( object, classList );
1215 }
1216 }
1217 },
1218
1219 submitFormNow: function( object ) {
1220 var hasFileFields, antispamInput,
1221 classList = object.className.trim().split( /\s+/gi );
1222
1223 if ( object.hasAttribute( 'data-token' ) && null === object.querySelector( '[name="antispam_token"]' ) ) {
1224 // include the antispam token on form submit.
1225 antispamInput = document.createElement( 'input' );
1226 antispamInput.type = 'hidden';
1227 antispamInput.name = 'antispam_token';
1228 antispamInput.value = object.getAttribute( 'data-token' );
1229 object.appendChild( antispamInput );
1230 }
1231
1232 if ( classList.indexOf( 'frm_ajax_submit' ) > -1 ) {
1233 hasFileFields = jQuery( object ).find( 'input[type="file"]' ).filter( function() {
1234 return !! this.value;
1235 }).length;
1236 if ( hasFileFields < 1 ) {
1237 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1238 frmFrontForm.checkFormErrors( object, action );
1239 } else {
1240 object.submit();
1241 }
1242 } else {
1243 object.submit();
1244 }
1245 },
1246
1247 validateFormSubmit: function( object ) {
1248 if ( typeof tinyMCE !== 'undefined' && jQuery( object ).find( '.wp-editor-wrap' ).length ) {
1249 tinyMCE.triggerSave();
1250 }
1251
1252 jsErrors = [];
1253
1254 if ( shouldJSValidate( object ) ) {
1255 frmFrontForm.getAjaxFormErrors( object );
1256
1257 if ( Object.keys( jsErrors ).length ) {
1258 frmFrontForm.addAjaxFormErrors( object );
1259 }
1260 }
1261
1262 return jsErrors;
1263 },
1264
1265 getAjaxFormErrors: function( object ) {
1266 var customErrors, key;
1267
1268 jsErrors = validateForm( object );
1269 if ( typeof frmThemeOverride_jsErrors === 'function' ) { // eslint-disable-line camelcase
1270 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1271 customErrors = frmThemeOverride_jsErrors( action, object );
1272 if ( Object.keys( customErrors ).length ) {
1273 for ( key in customErrors ) {
1274 jsErrors[ key ] = customErrors[ key ];
1275 }
1276 }
1277 }
1278
1279 return jsErrors;
1280 },
1281
1282 addAjaxFormErrors: function( object ) {
1283 var key, $fieldCont;
1284 removeAllErrors();
1285
1286 for ( key in jsErrors ) {
1287 $fieldCont = jQuery( object ).find( '#frm_field_' + key + '_container' );
1288
1289 if ( $fieldCont.length ) {
1290 addFieldError( $fieldCont, key, jsErrors );
1291 } else {
1292 // we are unable to show the error, so remove it
1293 delete jsErrors[ key ];
1294 }
1295 }
1296
1297 scrollToFirstField( object );
1298 checkForErrorsAndMaybeSetFocus();
1299 },
1300
1301 checkFormErrors: function( object, action ) {
1302 getFormErrors( object, action );
1303 },
1304
1305 checkRequiredField: function( field, errors ) {
1306 return checkRequiredField( field, errors );
1307 },
1308
1309 showSubmitLoading: function( $object ) {
1310 showSubmitLoading( $object );
1311 },
1312
1313 removeSubmitLoading: function( $object, enable, processesRunning ) {
1314 removeSubmitLoading( $object, enable, processesRunning );
1315 },
1316
1317 scrollToID: function( id ) {
1318 var object = jQuery( document.getElementById( id ) );
1319 frmFrontForm.scrollMsg( object, false );
1320 },
1321
1322 scrollMsg: function( id, object, animate ) {
1323 var newPos, m, b, screenTop, screenBottom,
1324 scrollObj = '';
1325 if ( typeof object === 'undefined' ) {
1326 scrollObj = jQuery( document.getElementById( 'frm_form_' + id + '_container' ) );
1327 if ( scrollObj.length < 1 ) {
1328 return;
1329 }
1330 } else if ( typeof id === 'string' ) {
1331 scrollObj = jQuery( object ).find( '#frm_field_' + id + '_container' );
1332 } else {
1333 scrollObj = id;
1334 }
1335
1336 jQuery( scrollObj ).trigger( 'focus' );
1337 newPos = scrollObj.offset().top;
1338 if ( ! newPos || frm_js.offset === '-1' ) {
1339 return;
1340 }
1341 newPos = newPos - frm_js.offset;
1342
1343 m = jQuery( 'html' ).css( 'margin-top' );
1344 b = jQuery( 'body' ).css( 'margin-top' );
1345 if ( m || b ) {
1346 newPos = newPos - parseInt( m ) - parseInt( b );
1347 }
1348
1349 if ( newPos && window.innerHeight ) {
1350 screenTop = document.documentElement.scrollTop || document.body.scrollTop;
1351 screenBottom = screenTop + window.innerHeight;
1352
1353 if ( newPos > screenBottom || newPos < screenTop ) {
1354 // Not in view
1355 if ( typeof animate === 'undefined' ) {
1356 jQuery( window ).scrollTop( newPos );
1357 } else {
1358 jQuery( 'html,body' ).animate({ scrollTop: newPos }, 500 );
1359 }
1360 return false;
1361 }
1362 }
1363 },
1364
1365 fieldValueChanged: function( e ) {
1366 /*jshint validthis:true */
1367
1368 var fieldId = frmFrontForm.getFieldId( this, false );
1369 if ( ! fieldId || typeof fieldId === 'undefined' ) {
1370 return;
1371 }
1372
1373 if ( e.frmTriggered && e.frmTriggered == fieldId ) {
1374 return;
1375 }
1376
1377 jQuery( document ).trigger( 'frmFieldChanged', [ this, fieldId, e ]);
1378
1379 if ( e.selfTriggered !== true ) {
1380 maybeValidateChange( this );
1381 }
1382 },
1383
1384 savingDraft: function( object ) {
1385 console.warn( 'DEPRECATED: function frmFrontForm.savingDraft in v3.0 use frmProForm.savingDraft' );
1386 if ( typeof frmProForm !== 'undefined' ) {
1387 return frmProForm.savingDraft( object );
1388 }
1389 },
1390
1391 goingToPreviousPage: function( object ) {
1392 console.warn( 'DEPRECATED: function frmFrontForm.goingToPreviousPage in v3.0 use frmProForm.goingToPreviousPage' );
1393 if ( typeof frmProForm !== 'undefined' ) {
1394 return frmProForm.goingToPreviousPage( object );
1395 }
1396 },
1397
1398 hideOrShowFields: function() {
1399 console.warn( 'DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields' );
1400 if ( typeof frmProForm !== 'undefined' ) {
1401 frmProForm.hideOrShowFields();
1402 }
1403 },
1404
1405 hidePreviouslyHiddenFields: function() {
1406 console.warn( 'DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields' );
1407 if ( typeof frmProForm !== 'undefined' ) {
1408 frmProForm.hidePreviouslyHiddenFields();
1409 }
1410 },
1411
1412 checkDependentDynamicFields: function( ids ) {
1413 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields' );
1414 if ( typeof frmProForm !== 'undefined' ) {
1415 frmProForm.checkDependentDynamicFields( ids );
1416 }
1417 },
1418
1419 checkDependentLookupFields: function( ids ) {
1420 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields' );
1421 if ( typeof frmProForm !== 'undefined' ) {
1422 frmProForm.checkDependentLookupFields( ids );
1423 }
1424 },
1425
1426 loadGoogle: function() {
1427 console.warn( 'DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle' );
1428 frmProForm.loadGoogle();
1429 },
1430
1431 escapeHtml: function( text ) {
1432 return text
1433 .replace( /&/g, '&amp;' )
1434 .replace( /</g, '&lt;' )
1435 .replace( />/g, '&gt;' )
1436 .replace( /"/g, '&quot;' )
1437 .replace( /'/g, '&#039;' );
1438 },
1439
1440 invisible: function( classes ) {
1441 jQuery( classes ).css( 'visibility', 'hidden' );
1442 },
1443
1444 visible: function( classes ) {
1445 jQuery( classes ).css( 'visibility', 'visible' );
1446 }
1447 };
1448 }
1449 frmFrontForm = frmFrontFormJS();
1450
1451 jQuery( document ).ready( function() {
1452 frmFrontForm.init();
1453 });
1454
1455 function frmRecaptcha() {
1456 var c, cl,
1457 captchas = jQuery( '.frm-g-recaptcha' );
1458 for ( c = 0, cl = captchas.length; c < cl; c++ ) {
1459 frmFrontForm.renderRecaptcha( captchas[c]);
1460 }
1461 }
1462
1463 function frmAfterRecaptcha( token ) {
1464 frmFrontForm.afterSingleRecaptcha( token );
1465 }
1466
1467 function frmUpdateField( entryId, fieldId, value, message, num ) {
1468 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).html( '<span class="frm-loading-img"></span>' );
1469 jQuery.ajax({
1470 type: 'POST',
1471 url: frm_js.ajax_url,
1472 data: {
1473 action: 'frm_entries_update_field_ajax',
1474 entry_id: entryId,
1475 field_id: fieldId,
1476 value: value,
1477 nonce: frm_js.nonce
1478 },
1479 success: function() {
1480 if ( message.replace( /^\s+|\s+$/g, '' ) === '' ) {
1481 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).fadeOut( 'slow' );
1482 } else {
1483 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).replaceWith( message );
1484 }
1485 }
1486 });
1487 }
1488
1489 function frmDeleteEntry( entryId, prefix ) {
1490 console.warn( 'DEPRECATED: function frmDeleteEntry in v2.0.13 use frmFrontForm.deleteEntry' );
1491 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( '<span class="frm-loading-img" id="frm_delete_' + entryId + '"></span>' );
1492 jQuery.ajax({
1493 type: 'POST',
1494 url: frm_js.ajax_url,
1495 data: {
1496 action: 'frm_entries_destroy',
1497 entry: entryId,
1498 nonce: frm_js.nonce
1499 },
1500 success: function( html ) {
1501 if ( html.replace( /^\s+|\s+$/g, '' ) === 'success' ) {
1502 jQuery( document.getElementById( prefix + entryId ) ).fadeOut( 'slow' );
1503 } else {
1504 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( html );
1505 }
1506 }
1507 });
1508 }
1509
1510 function frmOnSubmit( e ) {
1511 console.warn( 'DEPRECATED: function frmOnSubmit in v2.0 use frmFrontForm.submitForm' );
1512 frmFrontForm.submitForm( e, this );
1513 }
1514
1515 function frm_resend_email( entryId, formId ) { // eslint-disable-line camelcase
1516 var $link = jQuery( document.getElementById( 'frm_resend_email' ) );
1517 console.warn( 'DEPRECATED: function frm_resend_email in v2.0' );
1518 $link.append( '<span class="spinner" style="display:inline"></span>' );
1519 jQuery.ajax({
1520 type: 'POST',
1521 url: frm_js.ajax_url,
1522 data: {
1523 action: 'frm_entries_send_email',
1524 entry_id: entryId,
1525 form_id: formId,
1526 nonce: frm_js.nonce
1527 },
1528 success: function( msg ) {
1529 $link.replaceWith( msg );
1530 }
1531 });
1532 }
1533