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

1,569 lines 43.5 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, data, success, error;
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
545 data = jQuery( object ).serialize() + '&action=frm_entries_' + action + '&nonce=' + frm_js.nonce;
546
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
675 error = function() {
676 jQuery( object ).find( 'input[type="submit"], input[type="button"]' ).prop( 'disabled', false );
677 object.submit();
678 };
679
680 postToAjaxUrl( object, data, success, error );
681 }
682
683 function postToAjaxUrl( form, data, success, error ) {
684 var ajaxUrl, action, ajaxParams;
685
686 ajaxUrl = frm_js.ajax_url;
687 action = form.getAttribute( 'action' );
688
689 if ( 'string' === typeof action && -1 !== action.indexOf( '?action=frm_forms_preview' ) ) {
690 ajaxUrl = action.split( '?action=frm_forms_preview' )[0];
691 }
692
693 ajaxParams = {
694 type: 'POST',
695 url: ajaxUrl,
696 data: data,
697 success: success
698 };
699
700 if ( 'function' === typeof error ) {
701 ajaxParams.error = error;
702 }
703
704 jQuery.ajax( ajaxParams );
705 }
706
707 function afterFormSubmitted( object, response ) {
708 var formCompleted = jQuery( response.content ).find( '.frm_message' );
709 if ( formCompleted.length ) {
710 jQuery( document ).trigger( 'frmFormComplete', [ object, response ]);
711 } else {
712 jQuery( document ).trigger( 'frmPageChanged', [ object, response ]);
713 }
714 }
715
716 function removeAddedScripts( formContainer, formID ) {
717 var endReplace = jQuery( '.frm_end_ajax_' + formID );
718 if ( endReplace.length ) {
719 formContainer.nextUntil( '.frm_end_ajax_' + formID ).remove();
720 endReplace.remove();
721 }
722 }
723
724 function maybeSlideOut( oldContent, newContent ) {
725 var c,
726 newClass = 'frm_slideout';
727 if ( newContent.indexOf( ' frm_slide' ) !== -1 ) {
728 c = oldContent.children();
729 if ( newContent.indexOf( ' frm_going_back' ) !== -1 ) {
730 newClass += ' frm_going_back';
731 }
732 c.removeClass( 'frm_going_back' );
733 c.addClass( newClass );
734 return 300;
735 }
736 return 0;
737 }
738
739 function addUrlParam( response ) {
740 var url;
741 if ( history.pushState && typeof response.page !== 'undefined' ) {
742 url = addQueryVar( 'frm_page', response.page );
743 window.history.pushState({ 'html': response.html }, '', '?' + url );
744 }
745 }
746
747 function addQueryVar( key, value ) {
748 var kvp, i, x;
749
750 key = encodeURI( key );
751 value = encodeURI( value );
752
753 kvp = document.location.search.substr( 1 ).split( '&' );
754
755 i = kvp.length;
756 while ( i-- ) {
757 x = kvp[i].split( '=' );
758
759 if ( x[0] == key ) {
760 x[1] = value;
761 kvp[i] = x.join( '=' );
762 break;
763 }
764 }
765
766 if ( i < 0 ) {
767 kvp[ kvp.length ] = [ key, value ].join( '=' );
768 }
769
770 return kvp.join( '&' );
771 }
772
773 function addFieldError( $fieldCont, key, jsErrors ) {
774 var input, id, describedBy;
775 if ( $fieldCont.length && $fieldCont.is( ':visible' ) ) {
776 $fieldCont.addClass( 'frm_blank_field' );
777 input = $fieldCont.find( 'input, select, textarea' );
778 id = 'frm_error_field_' + key;
779 describedBy = input.attr( 'aria-describedby' );
780
781 if ( typeof frmThemeOverride_frmPlaceError === 'function' ) { // eslint-disable-line camelcase
782 frmThemeOverride_frmPlaceError( key, jsErrors );
783 } else {
784 if ( -1 !== jsErrors[key].indexOf( '<div' ) ) {
785 $fieldCont.append(
786 jsErrors[key]
787 );
788 } else {
789 $fieldCont.append( '<div class="frm_error" role="alert" id="' + id + '">' + jsErrors[key] + '</div>' );
790 }
791
792 if ( typeof describedBy === 'undefined' ) {
793 describedBy = id;
794 } else if ( describedBy.indexOf( id ) === -1 ) {
795 describedBy = describedBy + ' ' + id;
796 }
797 input.attr( 'aria-describedby', describedBy );
798 }
799 input.attr( 'aria-invalid', true );
800 input.attr( 'aria-describedby', id );
801
802 jQuery( document ).trigger( 'frmAddFieldError', [ $fieldCont, key, jsErrors ]);
803 }
804 }
805
806 function removeFieldError( $fieldCont ) {
807 var errorMessage = $fieldCont.find( '.frm_error' ),
808 errorId = errorMessage.attr( 'id' ),
809 input = $fieldCont.find( 'input, select, textarea' ),
810 describedBy = input.attr( 'aria-describedby' );
811
812 $fieldCont.removeClass( 'frm_blank_field has-error' );
813 errorMessage.remove();
814 input.attr( 'aria-invalid', false );
815 input.removeAttr( 'aria-describedby' );
816
817 if ( typeof describedBy !== 'undefined' ) {
818 describedBy = describedBy.replace( errorId, '' );
819 input.attr( 'aria-describedby', describedBy );
820 }
821 }
822
823 function removeAllErrors() {
824 jQuery( '.form-field' ).removeClass( 'frm_blank_field has-error' );
825 jQuery( '.form-field .frm_error' ).replaceWith( '' );
826 jQuery( '.frm_error_style' ).remove();
827 }
828
829 function scrollToFirstField( object ) {
830 var field = jQuery( object ).find( '.frm_blank_field' ).first();
831 if ( field.length ) {
832 frmFrontForm.scrollMsg( field, object, true );
833 }
834 }
835
836 function showSubmitLoading( $object ) {
837 showLoadingIndicator( $object );
838 disableSubmitButton( $object );
839 disableSaveDraft( $object );
840 }
841
842 function showLoadingIndicator( $object ) {
843 if ( ! $object.hasClass( 'frm_loading_form' ) && ! $object.hasClass( 'frm_loading_prev' ) ) {
844 addLoadingClass( $object );
845 $object.trigger( 'frmStartFormLoading' );
846 }
847 }
848
849 function addLoadingClass( $object ) {
850 var loadingClass = isGoingToPrevPage( $object ) ? 'frm_loading_prev' : 'frm_loading_form';
851
852 $object.addClass( loadingClass );
853 }
854
855 function isGoingToPrevPage( $object ) {
856 return ( typeof frmProForm !== 'undefined' && frmProForm.goingToPreviousPage( $object ) );
857 }
858
859 function removeSubmitLoading( $object, enable, processesRunning ) {
860 var loadingForm;
861
862 if ( processesRunning > 0 ) {
863 return;
864 }
865
866 loadingForm = jQuery( '.frm_loading_form' );
867 loadingForm.removeClass( 'frm_loading_form' );
868 loadingForm.removeClass( 'frm_loading_prev' );
869
870 loadingForm.trigger( 'frmEndFormLoading' );
871
872 if ( enable === 'enable' ) {
873 enableSubmitButton( loadingForm );
874 enableSaveDraft( loadingForm );
875 }
876 }
877
878 function showFileLoading( object ) {
879 var fileval,
880 loading = document.getElementById( 'frm_loading' );
881 if ( loading !== null ) {
882 fileval = jQuery( object ).find( 'input[type=file]' ).val();
883 if ( typeof fileval !== 'undefined' && fileval !== '' ) {
884 setTimeout( function() {
885 jQuery( loading ).fadeIn( 'slow' );
886 }, 2000 );
887 }
888 }
889 }
890
891 function clearDefault() {
892 /*jshint validthis:true */
893 toggleDefault( jQuery( this ), 'clear' );
894 }
895
896 function replaceDefault() {
897 /*jshint validthis:true */
898 toggleDefault( jQuery( this ), 'replace' );
899 }
900
901 function toggleDefault( $thisField, e ) {
902 // TODO: Fix this for a default value that is a number or array
903 var thisVal,
904 v = $thisField.data( 'frmval' ).replace( /(\n|\r\n)/g, '\r' );
905 if ( v === '' || typeof v === 'undefined' ) {
906 return false;
907 }
908 thisVal = $thisField.val().replace( /(\n|\r\n)/g, '\r' );
909
910 if ( 'replace' === e ) {
911 if ( thisVal === '' ) {
912 $thisField.addClass( 'frm_default' ).val( v );
913 }
914 } else if ( thisVal == v ) {
915 $thisField.removeClass( 'frm_default' ).val( '' );
916 }
917 }
918
919 function resendEmail() {
920 /*jshint validthis:true */
921 var $link = jQuery( this ),
922 entryId = this.getAttribute( 'data-eid' ),
923 formId = this.getAttribute( 'data-fid' ),
924 label = $link.find( '.frm_link_label' );
925 if ( label.length < 1 ) {
926 label = $link;
927 }
928 label.append( '<span class="frm-wait"></span>' );
929
930 jQuery.ajax({
931 type: 'POST',
932 url: frm_js.ajax_url,
933 data: {
934 action: 'frm_entries_send_email',
935 entry_id: entryId,
936 form_id: formId,
937 nonce: frm_js.nonce
938 },
939 success: function( msg ) {
940 var admin = document.getElementById( 'wpbody' );
941 if ( admin === null ) {
942 label.html( msg );
943 } else {
944 label.html( '' );
945 $link.after( msg );
946 }
947 }
948 });
949 return false;
950 }
951
952 /**********************************************
953 * General Helpers
954 *********************************************/
955
956 function confirmClick() {
957 /*jshint validthis:true */
958 var message = jQuery( this ).data( 'frmconfirm' );
959 return confirm( message );
960 }
961
962 function toggleDiv() {
963 /*jshint validthis:true */
964 var div = jQuery( this ).data( 'frmtoggle' );
965 if ( jQuery( div ).is( ':visible' ) ) {
966 jQuery( div ).slideUp( 'fast' );
967 } else {
968 jQuery( div ).slideDown( 'fast' );
969 }
970 return false;
971 }
972
973 /**********************************************
974 * Fallback functions
975 *********************************************/
976
977 function addIndexOfFallbackForIE8() {
978 var len, from;
979
980 if ( ! Array.prototype.indexOf ) {
981 Array.prototype.indexOf = function( elt /*, from*/ ) {
982 len = this.length >>> 0;
983
984 from = Number( arguments[1]) || 0;
985 from = ( from < 0 ) ? Math.ceil( from ) : Math.floor( from );
986 if ( from < 0 ) {
987 from += len;
988 }
989
990 for ( ; from < len; from++ ) {
991 if ( from in this && this[from] === elt ) {
992 return from;
993 }
994 }
995 return -1;
996 };
997 }
998 }
999
1000 function addTrimFallbackForIE8() {
1001 if ( typeof String.prototype.trim !== 'function' ) {
1002 String.prototype.trim = function() {
1003 return this.replace( /^\s+|\s+$/g, '' );
1004 };
1005 }
1006 }
1007
1008 function addFilterFallbackForIE8() {
1009 var t, len, res, thisp, i, val;
1010
1011 if ( ! Array.prototype.filter ) {
1012
1013 Array.prototype.filter = function( fun /*, thisp */ ) {
1014
1015 if ( this === void 0 || this === null ) {
1016 throw new TypeError();
1017 }
1018
1019 t = Object( this );
1020 len = t.length >>> 0;
1021 if ( typeof fun !== 'function' ) {
1022 throw new TypeError();
1023 }
1024
1025 res = [];
1026 thisp = arguments[1];
1027 for ( i = 0; i < len; i++ ) {
1028 if ( i in t ) {
1029 val = t[i]; // in case fun mutates this
1030 if ( fun.call( thisp, val, i, t ) ) {
1031 res.push( val );
1032 }
1033 }
1034 }
1035
1036 return res;
1037 };
1038 }
1039 }
1040
1041 function addKeysFallbackForIE8() {
1042 var keys, i;
1043
1044 if ( ! Object.keys ) {
1045 Object.keys = function( obj ) {
1046 keys = [];
1047
1048 for ( i in obj ) {
1049 if ( obj.hasOwnProperty( i ) ) {
1050 keys.push( i );
1051 }
1052 }
1053
1054 return keys;
1055 };
1056 }
1057 }
1058
1059 /**
1060 * Check for -webkit-box-shadow css value for input:-webkit-autofill selector.
1061 * If this is a match, the User is autofilling the input on a Webkit browser.
1062 * We want to delete the Honeypot field, otherwise it will get triggered as spam on autocomplete.
1063 */
1064 function onHoneypotFieldChange() {
1065 var css = jQuery( this ).css( 'box-shadow' );
1066 if ( css.match( /inset/ ) ) {
1067 this.parentNode.removeChild( this );
1068 }
1069 }
1070
1071 /**
1072 * Focus on the first sub field when clicking to the primary label of combo field.
1073 *
1074 * @since 4.10.02
1075 */
1076 function changeFocusWhenClickComboFieldLabel() {
1077 let label;
1078
1079 const comboInputsContainer = document.querySelectorAll( '.frm_combo_inputs_container' );
1080 comboInputsContainer.forEach( function( inputsContainer ) {
1081 if ( ! inputsContainer.closest( '.frm_form_field' ) ) {
1082 return;
1083 }
1084
1085 label = inputsContainer.closest( '.frm_form_field' ).querySelector( '.frm_primary_label' );
1086 if ( ! label ) {
1087 return;
1088 }
1089
1090 label.addEventListener( 'click', function( e ) {
1091 inputsContainer.querySelector( '.frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea' ).focus();
1092 });
1093 });
1094 }
1095
1096 function checkForErrorsAndMaybeSetFocus() {
1097 var errors, element, timeoutCallback;
1098
1099 errors = document.querySelectorAll( '.frm_form_field .frm_error' );
1100 if ( ! errors.length ) {
1101 return;
1102 }
1103
1104 element = errors[0];
1105 do {
1106 element = element.previousSibling;
1107 if ( -1 !== [ 'input', 'select', 'textarea' ].indexOf( element.nodeName.toLowerCase() ) ) {
1108 element.focus();
1109 break;
1110 }
1111
1112 if ( 'undefined' !== typeof element.classList ) {
1113 if ( element.classList.contains( 'html-active' ) ) {
1114 timeoutCallback = function() {
1115 var textarea = element.querySelector( 'textarea' );
1116 if ( null !== textarea ) {
1117 textarea.focus();
1118 }
1119 };
1120 } else if ( element.classList.contains( 'tmce-active' ) ) {
1121 timeoutCallback = function() {
1122 tinyMCE.activeEditor.focus();
1123 };
1124 }
1125
1126 if ( 'function' === typeof timeoutCallback ) {
1127 setTimeout( timeoutCallback, 0 );
1128 break;
1129 }
1130 }
1131 } while ( element.previousSibling );
1132 }
1133
1134 return {
1135 init: function() {
1136 jQuery( document ).off( 'submit.formidable', '.frm-show-form' );
1137 jQuery( document ).on( 'submit.formidable', '.frm-show-form', frmFrontForm.submitForm );
1138
1139 jQuery( '.frm-show-form input[onblur], .frm-show-form textarea[onblur]' ).each( function() {
1140 if ( jQuery( this ).val() === '' ) {
1141 jQuery( this ).trigger( 'blur' );
1142 }
1143 });
1144
1145 jQuery( document ).on( 'focus', '.frm_toggle_default', clearDefault );
1146 jQuery( document ).on( 'blur', '.frm_toggle_default', replaceDefault );
1147 jQuery( '.frm_toggle_default' ).trigger( 'blur' );
1148
1149 jQuery( document.getElementById( 'frm_resend_email' ) ).on( 'click', resendEmail );
1150
1151 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 );
1152 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 );
1153
1154 jQuery( document ).on( 'change', '[id^=frm_email_]', onHoneypotFieldChange );
1155
1156 jQuery( document ).on( 'click', 'a[data-frmconfirm]', confirmClick );
1157 jQuery( 'a[data-frmtoggle]' ).on( 'click', toggleDiv );
1158
1159 checkForErrorsAndMaybeSetFocus();
1160
1161 // Focus on the first sub field when clicking to the primary label of combo field.
1162 changeFocusWhenClickComboFieldLabel();
1163
1164 // Add fallbacks for the beloved IE8
1165 addIndexOfFallbackForIE8();
1166 addTrimFallbackForIE8();
1167 addFilterFallbackForIE8();
1168 addKeysFallbackForIE8();
1169 },
1170
1171 getFieldId: function( field, fullID ) {
1172 return getFieldId( field, fullID );
1173 },
1174
1175 renderRecaptcha: function( captcha ) {
1176 var formID, recaptchaID,
1177 size = captcha.getAttribute( 'data-size' ),
1178 rendered = captcha.getAttribute( 'data-rid' ) !== null,
1179 params = {
1180 'sitekey': captcha.getAttribute( 'data-sitekey' ),
1181 'size': size,
1182 'theme': captcha.getAttribute( 'data-theme' )
1183 };
1184
1185 if ( rendered ) {
1186 return;
1187 }
1188
1189 if ( size === 'invisible' ) {
1190 formID = jQuery( captcha ).closest( 'form' ).find( 'input[name="form_id"]' ).val();
1191 jQuery( captcha ).closest( '.frm_form_field .frm_primary_label' ).hide();
1192 params.callback = function( token ) {
1193 frmFrontForm.afterRecaptcha( token, formID );
1194 };
1195 }
1196
1197 recaptchaID = grecaptcha.render( captcha.id, params );
1198
1199 captcha.setAttribute( 'data-rid', recaptchaID );
1200 },
1201
1202 afterSingleRecaptcha: function() {
1203 var object = jQuery( '.frm-show-form .g-recaptcha' ).closest( 'form' )[0];
1204 frmFrontForm.submitFormNow( object );
1205 },
1206
1207 afterRecaptcha: function( token, formID ) {
1208 var object = jQuery( '#frm_form_' + formID + '_container form' )[0];
1209 frmFrontForm.submitFormNow( object );
1210 },
1211
1212 submitForm: function( e ) {
1213 frmFrontForm.submitFormManual( e, this );
1214 },
1215
1216 submitFormManual: function( e, object ) {
1217 var isPro, errors,
1218 invisibleRecaptcha = hasInvisibleRecaptcha( object ),
1219 classList = object.className.trim().split( /\s+/gi );
1220
1221 if ( classList && invisibleRecaptcha.length < 1 ) {
1222 isPro = classList.indexOf( 'frm_pro_form' ) > -1;
1223 if ( ! isPro ) {
1224 return;
1225 }
1226 }
1227
1228 if ( jQuery( 'body' ).hasClass( 'wp-admin' ) && jQuery( object ).closest( '.frmapi-form' ).length < 1 ) {
1229 return;
1230 }
1231
1232 e.preventDefault();
1233
1234 if ( typeof frmProForm !== 'undefined' && typeof frmProForm.submitAllowed === 'function' ) {
1235 if ( ! frmProForm.submitAllowed( object ) ) {
1236 return;
1237 }
1238 }
1239
1240 if ( invisibleRecaptcha.length ) {
1241 showLoadingIndicator( jQuery( object ) );
1242 executeInvisibleRecaptcha( invisibleRecaptcha );
1243 } else {
1244
1245 errors = frmFrontForm.validateFormSubmit( object );
1246
1247 if ( Object.keys( errors ).length === 0 ) {
1248 showSubmitLoading( jQuery( object ) );
1249
1250 frmFrontForm.submitFormNow( object, classList );
1251 }
1252 }
1253 },
1254
1255 submitFormNow: function( object ) {
1256 var hasFileFields, antispamInput,
1257 classList = object.className.trim().split( /\s+/gi );
1258
1259 if ( object.hasAttribute( 'data-token' ) && null === object.querySelector( '[name="antispam_token"]' ) ) {
1260 // include the antispam token on form submit.
1261 antispamInput = document.createElement( 'input' );
1262 antispamInput.type = 'hidden';
1263 antispamInput.name = 'antispam_token';
1264 antispamInput.value = object.getAttribute( 'data-token' );
1265 object.appendChild( antispamInput );
1266 }
1267
1268 if ( classList.indexOf( 'frm_ajax_submit' ) > -1 ) {
1269 hasFileFields = jQuery( object ).find( 'input[type="file"]' ).filter( function() {
1270 return !! this.value;
1271 }).length;
1272 if ( hasFileFields < 1 ) {
1273 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1274 frmFrontForm.checkFormErrors( object, action );
1275 } else {
1276 object.submit();
1277 }
1278 } else {
1279 object.submit();
1280 }
1281 },
1282
1283 validateFormSubmit: function( object ) {
1284 if ( typeof tinyMCE !== 'undefined' && jQuery( object ).find( '.wp-editor-wrap' ).length ) {
1285 tinyMCE.triggerSave();
1286 }
1287
1288 jsErrors = [];
1289
1290 if ( shouldJSValidate( object ) ) {
1291 frmFrontForm.getAjaxFormErrors( object );
1292
1293 if ( Object.keys( jsErrors ).length ) {
1294 frmFrontForm.addAjaxFormErrors( object );
1295 }
1296 }
1297
1298 return jsErrors;
1299 },
1300
1301 getAjaxFormErrors: function( object ) {
1302 var customErrors, key;
1303
1304 jsErrors = validateForm( object );
1305 if ( typeof frmThemeOverride_jsErrors === 'function' ) { // eslint-disable-line camelcase
1306 action = jQuery( object ).find( 'input[name="frm_action"]' ).val();
1307 customErrors = frmThemeOverride_jsErrors( action, object );
1308 if ( Object.keys( customErrors ).length ) {
1309 for ( key in customErrors ) {
1310 jsErrors[ key ] = customErrors[ key ];
1311 }
1312 }
1313 }
1314
1315 return jsErrors;
1316 },
1317
1318 addAjaxFormErrors: function( object ) {
1319 var key, $fieldCont;
1320 removeAllErrors();
1321
1322 for ( key in jsErrors ) {
1323 $fieldCont = jQuery( object ).find( '#frm_field_' + key + '_container' );
1324
1325 if ( $fieldCont.length ) {
1326 addFieldError( $fieldCont, key, jsErrors );
1327 } else {
1328 // we are unable to show the error, so remove it
1329 delete jsErrors[ key ];
1330 }
1331 }
1332
1333 scrollToFirstField( object );
1334 checkForErrorsAndMaybeSetFocus();
1335 },
1336
1337 checkFormErrors: function( object, action ) {
1338 getFormErrors( object, action );
1339 },
1340
1341 checkRequiredField: function( field, errors ) {
1342 return checkRequiredField( field, errors );
1343 },
1344
1345 showSubmitLoading: function( $object ) {
1346 showSubmitLoading( $object );
1347 },
1348
1349 removeSubmitLoading: function( $object, enable, processesRunning ) {
1350 removeSubmitLoading( $object, enable, processesRunning );
1351 },
1352
1353 scrollToID: function( id ) {
1354 var object = jQuery( document.getElementById( id ) );
1355 frmFrontForm.scrollMsg( object, false );
1356 },
1357
1358 scrollMsg: function( id, object, animate ) {
1359 var newPos, m, b, screenTop, screenBottom,
1360 scrollObj = '';
1361 if ( typeof object === 'undefined' ) {
1362 scrollObj = jQuery( document.getElementById( 'frm_form_' + id + '_container' ) );
1363 if ( scrollObj.length < 1 ) {
1364 return;
1365 }
1366 } else if ( typeof id === 'string' ) {
1367 scrollObj = jQuery( object ).find( '#frm_field_' + id + '_container' );
1368 } else {
1369 scrollObj = id;
1370 }
1371
1372 jQuery( scrollObj ).trigger( 'focus' );
1373 newPos = scrollObj.offset().top;
1374 if ( ! newPos || frm_js.offset === '-1' ) {
1375 return;
1376 }
1377 newPos = newPos - frm_js.offset;
1378
1379 m = jQuery( 'html' ).css( 'margin-top' );
1380 b = jQuery( 'body' ).css( 'margin-top' );
1381 if ( m || b ) {
1382 newPos = newPos - parseInt( m ) - parseInt( b );
1383 }
1384
1385 if ( newPos && window.innerHeight ) {
1386 screenTop = document.documentElement.scrollTop || document.body.scrollTop;
1387 screenBottom = screenTop + window.innerHeight;
1388
1389 if ( newPos > screenBottom || newPos < screenTop ) {
1390 // Not in view
1391 if ( typeof animate === 'undefined' ) {
1392 jQuery( window ).scrollTop( newPos );
1393 } else {
1394 jQuery( 'html,body' ).animate({ scrollTop: newPos }, 500 );
1395 }
1396 return false;
1397 }
1398 }
1399 },
1400
1401 fieldValueChanged: function( e ) {
1402 /*jshint validthis:true */
1403
1404 var fieldId = frmFrontForm.getFieldId( this, false );
1405 if ( ! fieldId || typeof fieldId === 'undefined' ) {
1406 return;
1407 }
1408
1409 if ( e.frmTriggered && e.frmTriggered == fieldId ) {
1410 return;
1411 }
1412
1413 jQuery( document ).trigger( 'frmFieldChanged', [ this, fieldId, e ]);
1414
1415 if ( e.selfTriggered !== true ) {
1416 maybeValidateChange( this );
1417 }
1418 },
1419
1420 savingDraft: function( object ) {
1421 console.warn( 'DEPRECATED: function frmFrontForm.savingDraft in v3.0 use frmProForm.savingDraft' );
1422 if ( typeof frmProForm !== 'undefined' ) {
1423 return frmProForm.savingDraft( object );
1424 }
1425 },
1426
1427 goingToPreviousPage: function( object ) {
1428 console.warn( 'DEPRECATED: function frmFrontForm.goingToPreviousPage in v3.0 use frmProForm.goingToPreviousPage' );
1429 if ( typeof frmProForm !== 'undefined' ) {
1430 return frmProForm.goingToPreviousPage( object );
1431 }
1432 },
1433
1434 hideOrShowFields: function() {
1435 console.warn( 'DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields' );
1436 if ( typeof frmProForm !== 'undefined' ) {
1437 frmProForm.hideOrShowFields();
1438 }
1439 },
1440
1441 hidePreviouslyHiddenFields: function() {
1442 console.warn( 'DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields' );
1443 if ( typeof frmProForm !== 'undefined' ) {
1444 frmProForm.hidePreviouslyHiddenFields();
1445 }
1446 },
1447
1448 checkDependentDynamicFields: function( ids ) {
1449 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields' );
1450 if ( typeof frmProForm !== 'undefined' ) {
1451 frmProForm.checkDependentDynamicFields( ids );
1452 }
1453 },
1454
1455 checkDependentLookupFields: function( ids ) {
1456 console.warn( 'DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields' );
1457 if ( typeof frmProForm !== 'undefined' ) {
1458 frmProForm.checkDependentLookupFields( ids );
1459 }
1460 },
1461
1462 loadGoogle: function() {
1463 console.warn( 'DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle' );
1464 frmProForm.loadGoogle();
1465 },
1466
1467 escapeHtml: function( text ) {
1468 return text
1469 .replace( /&/g, '&amp;' )
1470 .replace( /</g, '&lt;' )
1471 .replace( />/g, '&gt;' )
1472 .replace( /"/g, '&quot;' )
1473 .replace( /'/g, '&#039;' );
1474 },
1475
1476 invisible: function( classes ) {
1477 jQuery( classes ).css( 'visibility', 'hidden' );
1478 },
1479
1480 visible: function( classes ) {
1481 jQuery( classes ).css( 'visibility', 'visible' );
1482 }
1483 };
1484 }
1485 frmFrontForm = frmFrontFormJS();
1486
1487 jQuery( document ).ready( function() {
1488 frmFrontForm.init();
1489 });
1490
1491 function frmRecaptcha() {
1492 var c, cl,
1493 captchas = jQuery( '.frm-g-recaptcha' );
1494 for ( c = 0, cl = captchas.length; c < cl; c++ ) {
1495 frmFrontForm.renderRecaptcha( captchas[c]);
1496 }
1497 }
1498
1499 function frmAfterRecaptcha( token ) {
1500 frmFrontForm.afterSingleRecaptcha( token );
1501 }
1502
1503 function frmUpdateField( entryId, fieldId, value, message, num ) {
1504 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).html( '<span class="frm-loading-img"></span>' );
1505 jQuery.ajax({
1506 type: 'POST',
1507 url: frm_js.ajax_url,
1508 data: {
1509 action: 'frm_entries_update_field_ajax',
1510 entry_id: entryId,
1511 field_id: fieldId,
1512 value: value,
1513 nonce: frm_js.nonce
1514 },
1515 success: function() {
1516 if ( message.replace( /^\s+|\s+$/g, '' ) === '' ) {
1517 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).fadeOut( 'slow' );
1518 } else {
1519 jQuery( document.getElementById( 'frm_update_field_' + entryId + '_' + fieldId + '_' + num ) ).replaceWith( message );
1520 }
1521 }
1522 });
1523 }
1524
1525 function frmDeleteEntry( entryId, prefix ) {
1526 console.warn( 'DEPRECATED: function frmDeleteEntry in v2.0.13 use frmFrontForm.deleteEntry' );
1527 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( '<span class="frm-loading-img" id="frm_delete_' + entryId + '"></span>' );
1528 jQuery.ajax({
1529 type: 'POST',
1530 url: frm_js.ajax_url,
1531 data: {
1532 action: 'frm_entries_destroy',
1533 entry: entryId,
1534 nonce: frm_js.nonce
1535 },
1536 success: function( html ) {
1537 if ( html.replace( /^\s+|\s+$/g, '' ) === 'success' ) {
1538 jQuery( document.getElementById( prefix + entryId ) ).fadeOut( 'slow' );
1539 } else {
1540 jQuery( document.getElementById( 'frm_delete_' + entryId ) ).replaceWith( html );
1541 }
1542 }
1543 });
1544 }
1545
1546 function frmOnSubmit( e ) {
1547 console.warn( 'DEPRECATED: function frmOnSubmit in v2.0 use frmFrontForm.submitForm' );
1548 frmFrontForm.submitForm( e, this );
1549 }
1550
1551 function frm_resend_email( entryId, formId ) { // eslint-disable-line camelcase
1552 var $link = jQuery( document.getElementById( 'frm_resend_email' ) );
1553 console.warn( 'DEPRECATED: function frm_resend_email in v2.0' );
1554 $link.append( '<span class="spinner" style="display:inline"></span>' );
1555 jQuery.ajax({
1556 type: 'POST',
1557 url: frm_js.ajax_url,
1558 data: {
1559 action: 'frm_entries_send_email',
1560 entry_id: entryId,
1561 form_id: formId,
1562 nonce: frm_js.nonce
1563 },
1564 success: function( msg ) {
1565 $link.replaceWith( msg );
1566 }
1567 });
1568 }
1569