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

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