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

1,243 lines 34.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 function frmFrontFormJS(){
2 'use strict';
3
4 /*global jQuery:false, frm_js */
5
6 var action = '';
7 var jsErrors = [];
8
9 function maybeShowLabel(){
10 /*jshint validthis:true */
11 var $field = jQuery(this);
12 var $label = $field.closest('.frm_inside_container').find('.frm_primary_label');
13
14 if ( $field.val().length > 0 ) {
15 $label.addClass('frm_visible');
16 } else {
17 $label.removeClass('frm_visible');
18 }
19 }
20
21 /* Get the ID of the field that changed*/
22 function getFieldId( field, fullID ) {
23 var fieldName = '';
24 if ( field instanceof jQuery ) {
25 fieldName = field.attr('name');
26 } else {
27 fieldName = field.name;
28 }
29
30 if ( typeof fieldName === 'undefined' ) {
31 fieldName = '';
32 }
33
34 if ( fieldName === '' ) {
35 if ( field instanceof jQuery ) {
36 fieldName = field.data('name');
37 } else {
38 fieldName = field.getAttribute('data-name');
39 }
40
41 if ( typeof fieldName === 'undefined' ) {
42 fieldName = '';
43 }
44
45 if ( fieldName !== '' && fieldName ) {
46 return fieldName;
47 }
48 return 0;
49 }
50
51 var nameParts = fieldName.replace('item_meta[', '').replace('[]', '').split(']');
52 //TODO: Fix this for checkboxes and address fields
53 if ( nameParts.length < 1 ) {
54 return 0;
55 }
56 nameParts = nameParts.filter(function(n){ return n !== ''; });
57
58 var field_id = nameParts[0];
59 var isRepeating = false;
60
61 if ( nameParts.length === 1 ) {
62 return field_id;
63 }
64
65 if ( nameParts[1] === '[form' || nameParts[1] === '[row_ids' ) {
66 return 0;
67 }
68
69
70 // Check if 'this' is in a repeating section
71 if ( jQuery('input[name="item_meta['+ field_id +'][form]"]').length ) {
72
73 // this is a repeatable section with name: item_meta[repeating-section-id][row-id][field-id]
74 field_id = nameParts[2].replace('[', '');
75 isRepeating = true;
76 }
77
78 // Check if 'this' is an other text field and get field ID for it
79 if ( 'other' === field_id ) {
80 if ( isRepeating ) {
81 // name for other fields: item_meta[370][0][other][414]
82 field_id = nameParts[3].replace('[', '');
83 } else {
84 // Other field name: item_meta[other][370]
85 field_id = nameParts[1].replace('[', '');
86 }
87 }
88
89 if ( fullID === true ) {
90 // For use in the container div id
91 if ( field_id === nameParts[0] ) {
92 field_id = field_id +'-'+ nameParts[1].replace('[', '');
93 } else {
94 field_id = field_id +'-'+ nameParts[0] +'-'+ nameParts[1].replace('[', '');
95 }
96 }
97
98 return field_id;
99 }
100
101 /**
102 * Disable the submit button for a given jQuery form object
103 *
104 * @since 2.03.02
105 *
106 * @param {object} $form
107 */
108 function disableSubmitButton( $form ) {
109 $form.find('input[type="submit"], input[type="button"], button[type="submit"]').attr('disabled','disabled');
110 }
111
112 /**
113 * Enable the submit button for a given jQuery form object
114 *
115 * @since 2.03.02
116 *
117 * @param {object} $form
118 */
119 function enableSubmitButton( $form ) {
120 $form.find( 'input[type="submit"], input[type="button"], button[type="submit"]' ).removeAttr( 'disabled' );
121 }
122
123 function validateForm( object ) {
124 var errors = [];
125
126 // Make sure required text field is filled in
127 var requiredFields = jQuery(object).find(
128 '.frm_required_field:visible input, .frm_required_field:visible select, .frm_required_field:visible textarea'
129 ).filter(':not(.frm_optional)');
130 if ( requiredFields.length ) {
131 for ( var r = 0, rl = requiredFields.length; r < rl; r++ ) {
132 errors = checkRequiredField( requiredFields[r], errors );
133 }
134 }
135
136 var emailFields = jQuery(object).find('input[type=email]').filter(':visible');
137 var fields = jQuery(object).find('input,select,textarea');
138 if ( fields.length ) {
139 for ( var n = 0, nl = fields.length; n < nl; n++ ) {
140 var field = fields[n];
141 var value = field.value;
142 if ( value !== '' ) {
143 if ( field.type === 'hidden' ) {
144 // don't validate
145 } else if ( field.type === 'number' ) {
146 errors = checkNumberField( field, errors );
147 } else if ( field.type === 'email' ) {
148 errors = checkEmailField( field, errors, emailFields );
149 } else if ( field.pattern !== null ) {
150 errors = checkPatternField( field, errors );
151 }
152 }
153 }
154 }
155
156 errors = validateRecaptcha( object, errors );
157
158 return errors;
159 }
160
161 function maybeValidateChange( field_id, field ) {
162 if ( field.type === 'url' ) {
163 maybeAddHttpToUrl( field );
164 }
165 if ( jQuery(field).closest('form').hasClass('frm_js_validate') ) {
166 validateField( field_id, field );
167 }
168 }
169
170 function maybeAddHttpToUrl( field ) {
171 var url = field.value;
172 var matches = url.match( /^(https?|ftps?|mailto|news|feed|telnet):/ );
173 if ( field.value !== '' && matches === null ) {
174 field.value = 'http://' + url;
175 }
176 }
177
178 function validateField( fieldId, field ) {
179 var errors = [];
180
181 var $fieldCont = jQuery(field).closest('.frm_form_field');
182 if ( $fieldCont.hasClass('frm_required_field') && ! jQuery(field).hasClass('frm_optional') ) {
183 errors = checkRequiredField( field, errors );
184 }
185
186 if ( errors.length < 1 ) {
187 if ( field.type === 'email' ) {
188 var emailFields = jQuery(field).closest('form').find('input[type=email]');
189 errors = checkEmailField( field, errors, emailFields );
190 } else if ( field.type === 'number' ) {
191 errors = checkNumberField( field, errors );
192 } else if ( field.pattern !== null ) {
193 errors = checkPatternField( field, errors );
194 }
195 }
196
197 removeFieldError( $fieldCont );
198 if ( Object.keys(errors).length > 0 ) {
199 for ( var key in errors ) {
200 addFieldError( $fieldCont, key, errors );
201 }
202 }
203 }
204
205 function checkRequiredField( field, errors ) {
206 var fileID = field.getAttribute('data-frmfile');
207 if ( field.type === 'hidden' && fileID === null ) {
208 return errors;
209 }
210
211 var val = '';
212 var fieldID = '';
213 if ( field.type === 'checkbox' || field.type === 'radio' ) {
214 var checkGroup = jQuery('input[name="'+field.name+'"]').closest('.frm_required_field').find('input:checked');
215 jQuery(checkGroup).each(function() {
216 val = this.value;
217 });
218 } else if ( field.type === 'file' || fileID ) {
219 if ( typeof fileID === 'undefined' ) {
220 fileID = getFieldId( field, true );
221 fileID = fileID.replace('file', '');
222 }
223
224 if ( typeof errors[ fileID ] === 'undefined' ) {
225 val = getFileVals( fileID );
226 }
227 fieldID = fileID;
228 } else {
229 var fieldClasses = field.className;
230 if ( fieldClasses.indexOf('frm_pos_none') !== -1 ) {
231 // skip hidden other fields
232 return errors;
233 }
234
235 val = jQuery(field).val();
236 if ( val === null ) {
237 val = '';
238 } else if ( typeof val !== 'string' ) {
239 var tempVal = val;
240 val = '';
241 for ( var i = 0; i < tempVal.length; i++ ) {
242 if ( tempVal[i] !== '' ) {
243 val = tempVal[i];
244 }
245 }
246 }
247
248 if ( fieldClasses.indexOf('frm_other_input') === -1 ) {
249 fieldID = getFieldId( field, true );
250 } else {
251 fieldID = getFieldId( field, false );
252 }
253
254 if ( fieldClasses.indexOf('frm_time_select') !== -1 ) {
255 // set id for time field
256 fieldID = fieldID.replace('-H', '').replace('-m', '');
257 }
258
259 var placeholder = field.getAttribute('data-frmplaceholder');
260 if ( placeholder !== null && val === placeholder ) {
261 val = '';
262 }
263 }
264
265 if ( val === '' ) {
266 if ( fieldID === '' ) {
267 fieldID = getFieldId( field, true );
268 }
269 if ( !(fieldID in errors) ) {
270 errors[ fieldID ] = getFieldValidationMessage( field, 'data-reqmsg' );
271 }
272 }
273
274 return errors;
275 }
276
277 function getFileVals( fileID ) {
278 var val = '';
279 var fileFields = jQuery('input[name="file'+ fileID +'"], input[name="file'+ fileID +'[]"], input[name^="item_meta['+ fileID +']"]');
280 fileFields.each(function(){
281 if ( val === '' ) {
282 val = this.value;
283 }
284 });
285 return val;
286 }
287
288 function checkEmailField( field, errors, emailFields ) {
289 var emailAddress = field.value;
290 var fieldID = getFieldId( field, true );
291 if ( fieldID in errors ) {
292 return errors;
293 }
294
295 var isConf = (fieldID.indexOf('conf_') === 0);
296 if ( emailAddress !== '' || isConf ) {
297 var re = /^(([^<>()\[\]\\.,;:\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;
298 var invalidMsg = getFieldValidationMessage( field, 'data-invmsg' );
299 if ( emailAddress !== '' && re.test( emailAddress ) === false ) {
300 errors[ fieldID ] = invalidMsg;
301 if ( isConf ) {
302 errors[ fieldID.replace('conf_', '') ] = '';
303 }
304 } else if ( isConf ) {
305 var confName = field.name.replace('conf_', '');
306 var match = emailFields.filter('[name="'+ confName +'"]').val();
307 if ( match !== emailAddress ) {
308 errors[ fieldID ] = '';
309 errors[ fieldID.replace('conf_', '') ] = '';
310 }
311 }
312 }
313 return errors;
314 }
315
316 function checkNumberField( field, errors ) {
317 var number = field.value;
318 if ( number !== '' && isNaN(number / 1) !== false ) {
319 var fieldID = getFieldId( field, true );
320 if ( !(fieldID in errors) ) {
321 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
322 }
323 }
324 return errors;
325 }
326
327 function checkPatternField( field, errors ) {
328 var text = field.value;
329 var format = getFieldValidationMessage( field, 'pattern' );
330
331 if ( format !== '' && text !== '' ) {
332 var fieldID = getFieldId( field, true );
333 if ( !(fieldID in errors) ) {
334 format = new RegExp( '^'+ format +'$', 'i' );
335 if ( format.test( text ) === false ) {
336 errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
337 }
338 }
339 }
340 return errors;
341 }
342
343 function hasInvisibleRecaptcha( object ) {
344 if ( isGoingToPrevPage( object ) ) {
345 return false;
346 }
347
348 var recaptcha = jQuery(object).find('.frm-g-recaptcha[data-size="invisible"], .g-recaptcha[data-size="invisible"]');
349 if ( recaptcha.length ) {
350 var recaptchaID = recaptcha.data('rid');
351 var alreadyChecked = grecaptcha.getResponse( recaptchaID );
352 if ( alreadyChecked.length === 0 ) {
353 return recaptcha;
354 } else {
355 return false;
356 }
357 } else {
358 return false;
359 }
360 }
361
362 function executeInvisibleRecaptcha( invisibleRecaptcha ) {
363 var recaptchaID = invisibleRecaptcha.data('rid');
364 grecaptcha.reset( recaptchaID );
365 grecaptcha.execute( recaptchaID );
366 }
367
368 function validateRecaptcha( form, errors ) {
369 var $recaptcha = jQuery(form).find('.frm-g-recaptcha');
370 if ( $recaptcha.length ) {
371 var recaptchaID = $recaptcha.data('rid');
372 var response = grecaptcha.getResponse( recaptchaID );
373
374 if ( response.length === 0 ) {
375 var fieldContainer = $recaptcha.closest('.frm_form_field');
376 var fieldID = fieldContainer.attr('id').replace('frm_field_', '').replace('_container', '');
377 errors[ fieldID ] = '';
378 }
379 }
380 return errors;
381 }
382
383 function getFieldValidationMessage( field, messageType ) {
384 var msg = field.getAttribute(messageType);
385 if ( msg === null ) {
386 msg = '';
387 }
388 return msg;
389 }
390
391 function shouldJSValidate( object ) {
392 var validate = jQuery(object).hasClass('frm_js_validate');
393 if ( validate && typeof frmProForm !== 'undefined' && ( frmProForm.savingDraft( object ) || frmProForm.goingToPreviousPage( object ) ) ) {
394 validate = false;
395 }
396
397 return validate;
398 }
399
400 function getFormErrors(object, action){
401 if(typeof action === 'undefined'){
402 jQuery(object).find('input[name="frm_action"]').val();
403 }
404
405 var fieldset = jQuery(object).find('.frm_form_field');
406 fieldset.addClass('frm_doing_ajax');
407 jQuery.ajax({
408 type:'POST',url:frm_js.ajax_url,
409 data:jQuery(object).serialize() +'&action=frm_entries_'+ action +'&nonce='+frm_js.nonce,
410 success:function(response){
411 var defaultResponse = {'content':'', 'errors':{}, 'pass':false };
412 if ( response === null ) {
413 response = defaultResponse;
414 }
415
416 response = response.replace(/^\s+|\s+$/g,'');
417 if ( response.indexOf('{') === 0 ) {
418 response = jQuery.parseJSON(response);
419 }else{
420 response = defaultResponse;
421 }
422
423 if ( typeof response.redirect !== 'undefined' ) {
424 jQuery(document).trigger( 'frmBeforeFormRedirect', [ object, response ] );
425 window.location = response.redirect;
426 } else if ( response.content !== '' ) {
427 // the form or success message was returned
428
429 removeSubmitLoading( jQuery(object) );
430 if ( frm_js.offset != -1 ) {
431 frmFrontForm.scrollMsg( jQuery(object), false );
432 }
433 var formID = jQuery(object).find('input[name="form_id"]').val();
434 response.content = response.content.replace(/ frm_pro_form /g, ' frm_pro_form frm_no_hide ');
435 var replaceContent = jQuery( object ).closest( '.frm_forms' );
436 removeAddedScripts( replaceContent, formID );
437 replaceContent.replaceWith( response.content );
438
439 addUrlParam(response);
440
441 if(typeof(frmThemeOverride_frmAfterSubmit) === 'function'){
442 var pageOrder = jQuery('input[name="frm_page_order_'+ formID +'"]').val();
443 var formReturned = jQuery(response.content).find('input[name="form_id"]').val();
444 frmThemeOverride_frmAfterSubmit(formReturned, pageOrder, response.content, object);
445 }
446
447 afterFormSubmitted( object, response );
448
449 } else if ( Object.keys(response.errors).length ) {
450 // errors were returned
451
452 removeSubmitLoading( jQuery(object), 'enable' );
453
454 //show errors
455 var cont_submit = true;
456 removeAllErrors();
457
458 var show_captcha = false;
459 var $fieldCont = null;
460
461 for ( var key in response.errors ) {
462 $fieldCont = jQuery(object).find('#frm_field_'+key+'_container');
463
464 if ( $fieldCont.length ) {
465 if ( ! $fieldCont.is(':visible') ) {
466 var inCollapsedSection = $fieldCont.closest('.frm_toggle_container');
467 if ( inCollapsedSection.length ) {
468 var frmTrigger = inCollapsedSection.prev();
469 if ( ! frmTrigger.hasClass('frm_trigger') ) {
470 // If the frmTrigger object is the section description, check to see if the previous element is the trigger
471 frmTrigger = frmTrigger.prev('.frm_trigger');
472 }
473 frmTrigger.click();
474 }
475 }
476
477 if ( $fieldCont.is(':visible') ) {
478 addFieldError( $fieldCont, key, response.errors );
479
480 cont_submit = false;
481
482 var $recaptcha = jQuery(object).find('#frm_field_'+key+'_container .frm-g-recaptcha, #frm_field_'+key+'_container .g-recaptcha');
483 if ( $recaptcha.length ) {
484 show_captcha = true;
485 var recaptchaID = $recaptcha.data('rid');
486 if ( jQuery().grecaptcha ) {
487 if ( recaptchaID ) {
488 grecaptcha.reset( recaptchaID );
489 } else {
490 grecaptcha.reset();
491 }
492 }
493 }
494 }
495 }
496 }
497
498 jQuery(document).trigger( 'frmFormErrors', [ object, response ] );
499
500 fieldset.removeClass('frm_doing_ajax');
501 scrollToFirstField( object );
502
503 if(show_captcha !== true){
504 replaceCheckedRecaptcha( object, false );
505 }
506
507 if(cont_submit){
508 object.submit();
509 }else{
510 jQuery(object).prepend(response.error_message);
511 }
512 } else {
513 // there may have been a plugin conflict, or the form is not set to submit with ajax
514
515 showFileLoading( object );
516 replaceCheckedRecaptcha( object, true );
517
518 object.submit();
519 }
520 },
521 error:function(){
522 jQuery(object).find('input[type="submit"], input[type="button"]').removeAttr('disabled');
523 object.submit();
524 }
525 });
526 }
527
528 function afterFormSubmitted( object, response ) {
529 var formCompleted = jQuery(response.content).find('.frm_message');
530 if ( formCompleted.length ) {
531 jQuery(document).trigger( 'frmFormComplete', [ object, response ] );
532 } else {
533 jQuery(document).trigger( 'frmPageChanged', [ object, response ] );
534 }
535 }
536
537 function removeAddedScripts( formContainer, formID ) {
538 var endReplace = jQuery( '.frm_end_ajax_' + formID );
539 if ( endReplace.length ) {
540 formContainer.nextUntil( '.frm_end_ajax_' + formID ).remove();
541 endReplace.remove();
542 }
543 }
544
545 function addUrlParam(response){
546 if ( history.pushState && typeof response.page !== 'undefined' ) {
547 var url = addQueryVar('frm_page', response.page);
548 window.history.pushState({"html":response.html}, '', '?'+ url);
549 }
550 }
551
552 function addQueryVar(key, value) {
553 key = encodeURI(key);
554 value = encodeURI(value);
555
556 var kvp = document.location.search.substr(1).split('&');
557
558 var i=kvp.length; var x; while(i--) {
559 x = kvp[i].split('=');
560
561 if (x[0]==key) {
562 x[1] = value;
563 kvp[i] = x.join('=');
564 break;
565 }
566 }
567
568 if (i<0) {
569 kvp[kvp.length] = [key,value].join('=');
570 }
571
572 return kvp.join('&');
573 }
574
575 function addFieldError( $fieldCont, key, jsErrors ) {
576 if ( $fieldCont.length && $fieldCont.is(':visible') ) {
577 $fieldCont.addClass('frm_blank_field');
578 var input = $fieldCont.find( 'input, select, textarea' ),
579 id = 'frm_error_field_' + key,
580 describedBy = input.attr( 'aria-describedby' );
581
582 if ( typeof frmThemeOverride_frmPlaceError === 'function' ) {
583 frmThemeOverride_frmPlaceError( key, jsErrors );
584 } else {
585 $fieldCont.append( '<div class="frm_error" id="' + id + '">'+ jsErrors[key] +'</div>' );
586
587 if ( typeof describedBy === 'undefined' ) {
588 describedBy = id;
589 } else if ( describedBy.indexOf( id ) === -1 ) {
590 describedBy = describedBy + ' ' + id;
591 }
592 input.attr( 'aria-describedby', describedBy );
593 }
594 input.attr( 'aria-invalid', true );
595
596 jQuery(document).trigger('frmAddFieldError', [ $fieldCont, key, jsErrors ] );
597 }
598 }
599
600 function removeFieldError( $fieldCont ) {
601 var errorMessage = $fieldCont.find('.frm_error'),
602 errorId = errorMessage.attr('id'),
603 input = $fieldCont.find( 'input, select, textarea' ),
604 describedBy = input.attr( 'aria-describedby' );
605
606 $fieldCont.removeClass('frm_blank_field has-error');
607 errorMessage.remove();
608 input.attr( 'aria-invalid', false );
609
610 if ( typeof describedBy !== 'undefined' ) {
611 describedBy = describedBy.replace( errorId, '' );
612 input.attr( 'aria-describedby', describedBy );
613 }
614 }
615
616 function removeAllErrors() {
617 jQuery('.form-field').removeClass('frm_blank_field has-error');
618 jQuery('.form-field .frm_error').replaceWith('');
619 jQuery('.frm_error_style').remove();
620 }
621
622 function scrollToFirstField( object ) {
623 var field = jQuery(object).find('.frm_blank_field:first');
624 if ( field.length ) {
625 frmFrontForm.scrollMsg( field, object, true );
626 }
627 }
628
629 function showSubmitLoading( $object ) {
630 showLoadingIndicator( $object );
631 disableSubmitButton( $object );
632 }
633
634 function showLoadingIndicator( $object ) {
635 if ( ! $object.hasClass( 'frm_loading_form' ) && ! $object.hasClass( 'frm_loading_prev' ) ) {
636 addLoadingClass( $object );
637 $object.trigger( 'frmStartFormLoading' );
638 }
639 }
640
641 function addLoadingClass( $object ) {
642 var loading_class = isGoingToPrevPage( $object ) ? 'frm_loading_prev' : 'frm_loading_form';
643
644 $object.addClass( loading_class );
645 }
646
647 function isGoingToPrevPage( $object ) {
648 return ( typeof frmProForm !== 'undefined' && frmProForm.goingToPreviousPage( $object ) );
649 }
650
651 function removeSubmitLoading( $object, enable, processesRunning ) {
652 if ( processesRunning > 0 ) {
653 return;
654 }
655
656 var loadingForm = jQuery( '.frm_loading_form' );
657 loadingForm.removeClass('frm_loading_form');
658 loadingForm.removeClass( 'frm_loading_prev' );
659
660 loadingForm.trigger( 'frmEndFormLoading' );
661
662 if ( enable === 'enable' ) {
663 enableSubmitButton( loadingForm );
664 }
665 }
666
667 function showFileLoading( object ) {
668 var loading = document.getElementById('frm_loading');
669 if ( loading !== null ) {
670 var file_val = jQuery(object).find('input[type=file]').val();
671 if ( typeof file_val !== 'undefined' && file_val !== '' ) {
672 setTimeout(function(){
673 jQuery(loading).fadeIn('slow');
674 },2000);
675 }
676 }
677 }
678
679 function replaceCheckedRecaptcha( object, checkPage ) {
680 var $recapField = jQuery(object).find('.frm-g-recaptcha, .g-recaptcha');
681 if($recapField.length ){
682 if ( checkPage ) {
683 var morePages = jQuery(object).find('.frm_next_page').length < 1 || jQuery(object).find('.frm_next_page').val() < 1;
684 if ( ! morePages ) {
685 return;
686 }
687 }
688 $recapField.closest('.frm_form_field').replaceWith('<input type="hidden" name="recaptcha_checked" value="'+ frm_js.nonce +'">');
689 }
690 }
691
692 function clearDefault(){
693 /*jshint validthis:true */
694 toggleDefault(jQuery(this), 'clear');
695 }
696
697 function replaceDefault(){
698 /*jshint validthis:true */
699 toggleDefault(jQuery(this), 'replace');
700 }
701
702 function toggleDefault($thisField, e){
703 // TODO: Fix this for a default value that is a number or array
704 var v = $thisField.data('frmval').replace(/(\n|\r\n)/g, '\r');
705 if ( v === '' || typeof v === 'undefined' ) {
706 return false;
707 }
708 var thisVal = $thisField.val().replace(/(\n|\r\n)/g, '\r');
709
710 if ( 'replace' == e ) {
711 if ( thisVal === '' ) {
712 $thisField.addClass('frm_default').val(v);
713 }
714 } else if ( thisVal == v ) {
715 $thisField.removeClass('frm_default').val('');
716 }
717 }
718
719 function resendEmail(){
720 /*jshint validthis:true */
721 var $link = jQuery(this),
722 entry_id = this.getAttribute( 'data-eid' ),
723 form_id = this.getAttribute( 'data-fid' ),
724 label = $link.find( '.frm_link_label' );
725 if ( label.length < 1 ) {
726 label = $link;
727 }
728 label.append('<span class="frm-wait"></span>');
729
730 jQuery.ajax({
731 type:'POST',
732 url:frm_js.ajax_url,
733 data:{
734 action:'frm_entries_send_email',
735 entry_id:entry_id,
736 form_id:form_id,
737 nonce:frm_js.nonce
738 },
739 success:function(msg){
740 label.html(msg);
741 }
742 });
743 return false;
744 }
745
746 /**********************************************
747 * General Helpers
748 *********************************************/
749
750 function confirmClick() {
751 /*jshint validthis:true */
752 var message = jQuery(this).data('frmconfirm');
753 return confirm(message);
754 }
755
756 function toggleDiv(){
757 /*jshint validthis:true */
758 var div = jQuery( this ).data( 'frmtoggle' );
759 if ( jQuery( div ).is( ':visible' ) ) {
760 jQuery( div ).slideUp( 'fast' );
761 } else {
762 jQuery( div ).slideDown( 'fast' );
763 }
764 return false;
765 }
766
767 /**********************************************
768 * Fallback functions
769 *********************************************/
770
771 function addIndexOfFallbackForIE8() {
772 if ( !Array.prototype.indexOf ) {
773 Array.prototype.indexOf = function(elt /*, from*/) {
774 var len = this.length >>> 0;
775
776 var from = Number(arguments[1]) || 0;
777 from = (from < 0) ? Math.ceil(from) : Math.floor(from);
778 if (from < 0) {
779 from += len;
780 }
781
782 for (; from < len; from++) {
783 if ( from in this && this[from] === elt ) {
784 return from;
785 }
786 }
787 return -1;
788 };
789 }
790 }
791
792 function addTrimFallbackForIE8(){
793 if ( typeof String.prototype.trim !== 'function' ) {
794 String.prototype.trim = function() {
795 return this.replace(/^\s+|\s+$/g, '');
796 };
797 }
798 }
799
800 function addFilterFallbackForIE8(){
801 if ( !Array.prototype.filter ) {
802
803 Array.prototype.filter = function(fun /*, thisp */) {
804
805 if ( this === void 0 || this === null ) {
806 throw new TypeError();
807 }
808
809 var t = Object( this );
810 var len = t.length >>> 0;
811 if ( typeof fun !== 'function' ) {
812 throw new TypeError();
813 }
814
815 var res = [];
816 var thisp = arguments[1];
817 for (var i = 0; i < len; i++) {
818 if ( i in t ) {
819 var val = t[i]; // in case fun mutates this
820 if (fun.call(thisp, val, i, t))
821 res.push(val);
822 }
823 }
824
825 return res;
826 };
827 }
828 }
829
830 function addKeysFallbackForIE8(){
831 if ( !Object.keys ) {
832 Object.keys = function(obj) {
833 var keys = [];
834
835 for (var i in obj) {
836 if (obj.hasOwnProperty(i)) {
837 keys.push(i);
838 }
839 }
840
841 return keys;
842 };
843 }
844 }
845
846 return{
847 init: function(){
848 jQuery(document).off('submit.formidable','.frm-show-form');
849 jQuery(document).on('submit.formidable','.frm-show-form', frmFrontForm.submitForm);
850
851 jQuery( '.frm-show-form input[onblur], .frm-show-form textarea[onblur]' ).each( function() {
852 if ( jQuery( this ).val() === '' ) {
853 jQuery( this ).blur();
854 }
855 } );
856
857 jQuery(document).on('focus', '.frm_toggle_default', clearDefault);
858 jQuery(document).on('blur', '.frm_toggle_default', replaceDefault);
859 jQuery('.frm_toggle_default').blur();
860
861 jQuery(document.getElementById('frm_resend_email')).click(resendEmail);
862
863 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 );
864 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);
865
866 jQuery(document).on('click', 'a[data-frmconfirm]', confirmClick);
867 jQuery('a[data-frmtoggle]').click(toggleDiv);
868
869 // Add fallbacks for the beloved IE8
870 addIndexOfFallbackForIE8();
871 addTrimFallbackForIE8();
872 addFilterFallbackForIE8();
873 addKeysFallbackForIE8();
874 },
875
876 getFieldId: function( field, fullID ) {
877 return getFieldId( field, fullID );
878 },
879
880 renderRecaptcha: function( captcha ) {
881 var size = captcha.getAttribute('data-size'),
882 rendered = captcha.getAttribute('data-rid') !== null,
883 params = {
884 'sitekey': captcha.getAttribute('data-sitekey'),
885 'size': size,
886 'theme': captcha.getAttribute('data-theme')
887 };
888
889 if ( rendered ) {
890 return;
891 }
892
893 if ( size === 'invisible' ) {
894 var formID = jQuery(captcha).closest('form').find('input[name="form_id"]').val();
895 jQuery(captcha).closest('.frm_form_field .frm_primary_label').hide();
896 params.callback = function(token) {
897 frmFrontForm.afterRecaptcha(token, formID);
898 };
899 }
900
901 var recaptchaID = grecaptcha.render( captcha.id, params );
902
903 captcha.setAttribute('data-rid', recaptchaID);
904 },
905
906 afterSingleRecaptcha: function(token){
907 var object = jQuery('.frm-show-form .g-recaptcha').closest('form')[0];
908 frmFrontForm.submitFormNow( object );
909 },
910
911 afterRecaptcha: function(token, formID){
912 var object = jQuery('#frm_form_'+ formID +'_container form')[0];
913 frmFrontForm.submitFormNow( object );
914 },
915
916 submitForm: function(e){
917 frmFrontForm.submitFormManual( e, this );
918 },
919
920 submitFormManual: function(e, object){
921 var invisibleRecaptcha = hasInvisibleRecaptcha(object);
922
923 var classList = object.className.trim().split(/\s+/gi);
924 if ( classList && invisibleRecaptcha.length < 1 ) {
925 var isPro = classList.indexOf('frm_pro_form') > -1;
926 if ( ! isPro ) {
927 return;
928 }
929 }
930
931 if ( jQuery('body').hasClass('wp-admin') && jQuery(object).closest('.frmapi-form').length < 1 ) {
932 return;
933 }
934
935 e.preventDefault();
936
937 if ( typeof frmProForm !== 'undefined' && typeof frmProForm.submitAllowed === 'function' ) {
938 if ( ! frmProForm.submitAllowed( object ) ) {
939 return;
940 }
941 }
942
943 if ( invisibleRecaptcha.length ) {
944 showLoadingIndicator( jQuery(object) );
945 executeInvisibleRecaptcha( invisibleRecaptcha );
946 } else {
947
948 var errors = frmFrontForm.validateFormSubmit( object );
949
950 if ( Object.keys(errors).length === 0 ) {
951 showSubmitLoading( jQuery(object) );
952
953 frmFrontForm.submitFormNow( object, classList );
954 }
955 }
956 },
957
958 submitFormNow: function(object) {
959 var classList = object.className.trim().split(/\s+/gi);
960 if ( classList.indexOf('frm_ajax_submit') > -1 ) {
961 var hasFileFields = jQuery(object).find('input[type="file"]').filter(function () {
962 return !!this.value;
963 }).length;
964 if ( hasFileFields < 1 ) {
965 action = jQuery(object).find('input[name="frm_action"]').val();
966 frmFrontForm.checkFormErrors( object, action );
967 } else {
968 object.submit();
969 }
970 } else {
971 object.submit();
972 }
973 },
974
975 validateFormSubmit: function( object ){
976 if ( typeof tinyMCE !== 'undefined' && jQuery(object).find('.wp-editor-wrap').length ) {
977 tinyMCE.triggerSave();
978 }
979
980 jsErrors = [];
981
982 if ( shouldJSValidate( object ) ) {
983 frmFrontForm.getAjaxFormErrors( object );
984
985 if ( Object.keys(jsErrors).length ) {
986 frmFrontForm.addAjaxFormErrors( object );
987 }
988 }
989
990 return jsErrors;
991 },
992
993 getAjaxFormErrors: function( object ) {
994 jsErrors = validateForm( object );
995 if ( typeof frmThemeOverride_jsErrors === 'function' ) {
996 action = jQuery(object).find('input[name="frm_action"]').val();
997 var customErrors = frmThemeOverride_jsErrors( action, object );
998 if ( Object.keys(customErrors).length ) {
999 for ( var key in customErrors ) {
1000 jsErrors[ key ] = customErrors[ key ];
1001 }
1002 }
1003 }
1004
1005 return jsErrors;
1006 },
1007
1008 addAjaxFormErrors: function( object ) {
1009 removeAllErrors();
1010
1011 for ( var key in jsErrors ) {
1012 var $fieldCont = jQuery(object).find('#frm_field_'+key+'_container');
1013
1014 if ( $fieldCont.length ) {
1015 addFieldError( $fieldCont, key, jsErrors );
1016 } else {
1017 // we are unable to show the error, so remove it
1018 delete jsErrors[ key ];
1019 }
1020 }
1021
1022 scrollToFirstField( object );
1023 },
1024
1025 checkFormErrors: function(object, action){
1026 getFormErrors( object, action );
1027 },
1028
1029 checkRequiredField: function( field, errors ){
1030 return checkRequiredField( field, errors );
1031 },
1032
1033 showSubmitLoading: function( $object ){
1034 showSubmitLoading( $object );
1035 },
1036
1037 removeSubmitLoading: function( $object, enable, processesRunning ){
1038 removeSubmitLoading( $object, enable, processesRunning );
1039 },
1040
1041 scrollToID: function(id){
1042 var object = jQuery(document.getElementById(id));
1043 frmFrontForm.scrollMsg( object, false );
1044 },
1045
1046 scrollMsg: function( id, object, animate ) {
1047 var scrollObj = '';
1048 if(typeof(object) === 'undefined'){
1049 scrollObj = jQuery(document.getElementById('frm_form_'+id+'_container'));
1050 if(scrollObj.length < 1 ){
1051 return;
1052 }
1053 } else if ( typeof id === 'string' ) {
1054 scrollObj = jQuery(object).find('#frm_field_'+id+'_container');
1055 } else {
1056 scrollObj = id;
1057 }
1058
1059 var newPos = scrollObj.offset().top;
1060 if ( !newPos ){
1061 return;
1062 }
1063 newPos = newPos-frm_js.offset;
1064
1065 var m=jQuery('html').css('margin-top');
1066 var b=jQuery('body').css('margin-top');
1067 if(m || b){
1068 newPos = newPos - parseInt(m) - parseInt(b);
1069 }
1070
1071 if ( newPos && window.innerHeight ) {
1072 var screenTop = document.documentElement.scrollTop || document.body.scrollTop;
1073 var screenBottom = screenTop + window.innerHeight;
1074
1075 if( newPos > screenBottom || newPos < screenTop ) {
1076 // Not in view
1077 if ( typeof animate === 'undefined' ) {
1078 jQuery(window).scrollTop(newPos);
1079 }else{
1080 jQuery('html,body').animate({scrollTop: newPos}, 500);
1081 }
1082 return false;
1083 }
1084 }
1085 },
1086
1087 fieldValueChanged: function(e){
1088 /*jshint validthis:true */
1089
1090 var field_id = frmFrontForm.getFieldId( this, false );
1091 if ( ! field_id || typeof field_id === 'undefined' ) {
1092 return;
1093 }
1094
1095 if ( e.frmTriggered && e.frmTriggered == field_id ) {
1096 return;
1097 }
1098
1099 jQuery(document).trigger( 'frmFieldChanged', [ this, field_id, e ] );
1100
1101 if ( e.selfTriggered !== true ) {
1102 maybeValidateChange( field_id, this );
1103 }
1104 },
1105
1106 savingDraft: function(object){
1107 console.warn('DEPRECATED: function frmFrontForm.savingDraft in v3.0 use frmProForm.savingDraft');
1108 if ( typeof frmProForm !== 'undefined' ) {
1109 return frmProForm.savingDraft(object);
1110 }
1111 },
1112
1113 goingToPreviousPage: function(object){
1114 console.warn('DEPRECATED: function frmFrontForm.goingToPreviousPage in v3.0 use frmProForm.goingToPreviousPage');
1115 if ( typeof frmProForm !== 'undefined' ) {
1116 return frmProForm.goingToPreviousPage(object);
1117 }
1118 },
1119
1120 hideOrShowFields: function(ids, event ){
1121 console.warn('DEPRECATED: function frmFrontForm.hideOrShowFields in v3.0 use frmProForm.hideOrShowFields');
1122 if ( typeof frmProForm !== 'undefined' ) {
1123 frmProForm.hideOrShowFields();
1124 }
1125 },
1126
1127 hidePreviouslyHiddenFields: function(){
1128 console.warn('DEPRECATED: function frmFrontForm.hidePreviouslyHiddenFields in v3.0 use frmProForm.hidePreviouslyHiddenFields');
1129 if ( typeof frmProForm !== 'undefined' ) {
1130 frmProForm.hidePreviouslyHiddenFields();
1131 }
1132 },
1133
1134 checkDependentDynamicFields: function(ids){
1135 console.warn('DEPRECATED: function frmFrontForm.checkDependentDynamicFields in v3.0 use frmProForm.checkDependentDynamicFields');
1136 if ( typeof frmProForm !== 'undefined' ) {
1137 frmProForm.checkDependentDynamicFields(ids);
1138 }
1139 },
1140
1141 checkDependentLookupFields: function(ids){
1142 console.warn('DEPRECATED: function frmFrontForm.checkDependentLookupFields in v3.0 use frmProForm.checkDependentLookupFields');
1143 if ( typeof frmProForm !== 'undefined' ) {
1144 frmProForm.checkDependentLookupFields(ids);
1145 }
1146 },
1147
1148 loadGoogle: function(){
1149 console.warn('DEPRECATED: function frmFrontForm.loadGoogle in v3.0 use frmProForm.loadGoogle');
1150 frmProForm.loadGoogle();
1151 },
1152
1153 removeUsedTimes: function( obj, timeField ) {
1154 console.warn('DEPRECATED: function frmFrontForm.removeUsedTimes in v3.0 use frmProForm.removeUsedTimes');
1155 if ( typeof frmProForm !== 'undefined' ) {
1156 frmProForm.removeUsedTimes();
1157 }
1158 },
1159
1160 escapeHtml: function(text){
1161 return text
1162 .replace(/&/g, '&amp;')
1163 .replace(/</g, '&lt;')
1164 .replace(/>/g, '&gt;')
1165 .replace(/"/g, '&quot;')
1166 .replace(/'/g, '&#039;');
1167 },
1168
1169 invisible: function(classes) {
1170 jQuery(classes).css('visibility', 'hidden');
1171 },
1172
1173 visible: function(classes) {
1174 jQuery(classes).css('visibility', 'visible');
1175 }
1176 };
1177 }
1178 var frmFrontForm = frmFrontFormJS();
1179
1180 jQuery(document).ready(function($){
1181 frmFrontForm.init();
1182 });
1183
1184 function frmRecaptcha() {
1185 var captchas = jQuery('.frm-g-recaptcha');
1186 for ( var c = 0, cl = captchas.length; c < cl; c++ ) {
1187 frmFrontForm.renderRecaptcha( captchas[c] );
1188 }
1189 }
1190
1191 function frmAfterRecaptcha(token){
1192 frmFrontForm.afterSingleRecaptcha(token);
1193 }
1194
1195 function frmUpdateField(entry_id,field_id,value,message,num){
1196 jQuery(document.getElementById('frm_update_field_'+entry_id+'_'+field_id+'_'+num)).html('<span class="frm-loading-img"></span>');
1197 jQuery.ajax({
1198 type:'POST',url:frm_js.ajax_url,
1199 data:{action:'frm_entries_update_field_ajax', entry_id:entry_id, field_id:field_id, value:value, nonce:frm_js.nonce},
1200 success:function(){
1201 if(message.replace(/^\s+|\s+$/g,'') === ''){
1202 jQuery(document.getElementById('frm_update_field_'+entry_id+'_'+field_id+'_'+num)).fadeOut('slow');
1203 }else{
1204 jQuery(document.getElementById('frm_update_field_'+entry_id+'_'+field_id+'_'+num)).replaceWith(message);
1205 }
1206 }
1207 });
1208 }
1209
1210 function frmDeleteEntry(entry_id,prefix){
1211 console.warn('DEPRECATED: function frmDeleteEntry in v2.0.13 use frmFrontForm.deleteEntry');
1212 jQuery(document.getElementById('frm_delete_'+entry_id)).replaceWith('<span class="frm-loading-img" id="frm_delete_'+entry_id+'"></span>');
1213 jQuery.ajax({
1214 type:'POST',url:frm_js.ajax_url,
1215 data:{action:'frm_entries_destroy', entry:entry_id, nonce:frm_js.nonce},
1216 success:function(html){
1217 if(html.replace(/^\s+|\s+$/g,'') === 'success')
1218 jQuery(document.getElementById(prefix+entry_id)).fadeOut('slow');
1219 else
1220 jQuery(document.getElementById('frm_delete_'+entry_id)).replaceWith(html);
1221
1222 }
1223 });
1224 }
1225
1226 function frmOnSubmit(e){
1227 console.warn('DEPRECATED: function frmOnSubmit in v2.0 use frmFrontForm.submitForm');
1228 frmFrontForm.submitForm(e, this);
1229 }
1230
1231 function frm_resend_email(entry_id,form_id){
1232 console.warn('DEPRECATED: function frm_resend_email in v2.0');
1233 var $link = jQuery(document.getElementById('frm_resend_email'));
1234 $link.append('<span class="spinner" style="display:inline"></span>');
1235 jQuery.ajax({
1236 type:'POST',url:frm_js.ajax_url,
1237 data:{action:'frm_entries_send_email', entry_id:entry_id, form_id:form_id, nonce:frm_js.nonce},
1238 success:function(msg){
1239 $link.replaceWith(msg);
1240 }
1241 });
1242 }
1243