PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.8
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.8
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
← All changes | js/formidable.js +177 -27 6.36.8 View file →
@@ -201,11 +201,12 @@
201 201 $form.find( 'a.frm_save_draft' ).css( 'pointer-events', '' );
202 202 }
203 203
204 204 function validateForm( object ) {
205 - var r, rl, n, nl, fields, field, value, requiredFields,
206 - errors = [];
205 + var errors, r, rl, n, nl, fields, field, requiredFields;
207 206
207 + errors = [];
208 +
208 209 // Make sure required text field is filled in
209 210 requiredFields = jQuery( object ).find(
210 211 '.frm_required_field:visible input, .frm_required_field:visible select, .frm_required_field:visible textarea'
211 212 ).filter( ':not(.frm_optional)' );
@@ -222,11 +223,18 @@
222 223 fields = jQuery( object ).find( 'input,select,textarea' );
223 224 if ( fields.length ) {
224 225 for ( n = 0, nl = fields.length; n < nl; n++ ) {
225 226 field = fields[n];
226 - if ( '' !== field.value ) {
227 - validateFieldValue( field, errors );
227 + if ( '' === field.value ) {
228 + if ( 'number' === field.type ) {
229 + // A number field will return an empty string when it is invalid.
230 + checkValidity( field, errors );
231 + }
232 + continue;
228 233 }
234 +
235 + validateFieldValue( field, errors );
236 + checkValidity( field, errors );
229 237 }
230 238 }
231 239
232 240 errors = validateRecaptcha( object, errors );
@@ -234,8 +242,33 @@
234 242 return errors;
235 243 }
236 244
237 245 /**
246 + * Check the ValidityState interface for the field.
247 + * If it is invalid, show an error for it.
248 + *
249 + * @param {HTMLElement} field
250 + * @param {Array} errors
251 + * @returns
252 + */
253 + function checkValidity( field, errors ) {
254 + var fieldID;
255 + if ( 'object' !== typeof field.validity || false !== field.validity.valid ) {
256 + return;
257 + }
258 +
259 + fieldID = getFieldId( field, true );
260 + if ( 'undefined' === typeof errors[ fieldID ]) {
261 + errors[ fieldID ] = getFieldValidationMessage( field, 'data-invmsg' );
262 + }
263 +
264 + if ( 'function' === typeof field.reportValidity ) {
265 + // This triggers an error pop up.
266 + field.reportValidity();
267 + }
268 + }
269 +
270 + /**
238 271 * @since 5.0.10
239 272 *
240 273 * @param {object} element
241 274 * @param {string} targetClass
@@ -490,8 +523,45 @@
490 523 }
491 524 }
492 525 }
493 526
527 + /**
528 + * Set color for select placeholders.
529 + *
530 + * @since 6.5.1
531 + */
532 + function setSelectPlaceholderColor() {
533 + var selects = document.querySelectorAll( '.form-field select' ),
534 + styleElement = document.querySelector( '.with_frm_style' ),
535 + textColorDisabled = styleElement ? getComputedStyle( styleElement ).getPropertyValue( '--text-color-disabled' ).trim() : '',
536 + changeSelectColor;
537 +
538 + // Exit if there are no select elements or the textColorDisabled property is missing
539 + if ( ! selects.length || ! textColorDisabled ) {
540 + return;
541 + }
542 +
543 + // Function to change the color of a select element
544 + changeSelectColor = function( select ) {
545 + if ( select.options[select.selectedIndex] && hasClass( select.options[select.selectedIndex], 'frm-select-placeholder' ) ) {
546 + select.style.setProperty( 'color', textColorDisabled, 'important' );
547 + } else {
548 + select.style.color = '';
549 + }
550 + };
551 +
552 + // Use a loop to iterate through each select element
553 + Array.prototype.forEach.call( selects, function( select ) {
554 + // Apply the color change to each select element
555 + changeSelectColor( select );
556 +
557 + // Add an event listener for future changes
558 + select.addEventListener( 'change', function() {
559 + changeSelectColor( select );
560 + });
561 + });
562 + }
563 +
494 564 function hasInvisibleRecaptcha( object ) {
495 565 var recaptcha, recaptchaID, alreadyChecked;
496 566
497 567 if ( isGoingToPrevPage( object ) ) {
@@ -590,9 +660,9 @@
590 660 shouldTriggerEvent = object.classList.contains( 'frm_trigger_event_on_submit' );
591 661
592 662 success = function( response ) {
593 663 var defaultResponse, formID, replaceContent, pageOrder, formReturned, contSubmit, delay,
594 - $fieldCont, key, inCollapsedSection, frmTrigger;
664 + $fieldCont, key, inCollapsedSection, frmTrigger, newTab;
595 665
596 666 defaultResponse = {
597 667 content: '',
598 668 errors: {},
@@ -616,10 +686,23 @@
616 686 return;
617 687 }
618 688
619 689 jQuery( document ).trigger( 'frmBeforeFormRedirect', [ object, response ]);
620 - window.location = response.redirect;
621 - } else if ( response.content !== '' ) {
690 +
691 + if ( ! response.openInNewTab ) {
692 + // We return here because we're redirecting there is no need to update content.
693 + window.location = response.redirect;
694 + return;
695 + }
696 +
697 + // We don't return here because we're opening in a new tab, the old tab will still update.
698 + newTab = window.open( response.redirect, '_blank' );
699 + if ( ! newTab && response.fallbackMsg && response.content ) {
700 + response.content = response.content.trim().replace( /(<\/div><\/div>)$/, ' ' + response.fallbackMsg + '</div></div>' );
701 + }
702 + }
703 +
704 + if ( response.content !== '' ) {
622 705 // the form or success message was returned
623 706
624 707 if ( shouldTriggerEvent ) {
625 708 triggerCustomEvent( object, 'frmSubmitEvent' );
@@ -1115,11 +1198,10 @@
1115 1198 }
1116 1199
1117 1200 function makeHoneypotFieldsUntabbable() {
1118 1201 document.querySelectorAll( '.frm_verify' ).forEach(
1119 - function( wrapper ) {
1120 - var input = wrapper.querySelector( 'input[id^=frm_email]' );
1121 - if ( input ) {
1202 + function( input ) {
1203 + if ( input.id && 0 === input.id.indexOf( 'frm_email_' ) ) {
1122 1204 input.setAttribute( 'tabindex', -1 );
1123 1205 }
1124 1206 }
1125 1207 );
@@ -1347,8 +1429,66 @@
1347 1429 runOnLoad();
1348 1430 });
1349 1431 }
1350 1432
1433 + function shouldUpdateValidityMessage( target ) {
1434 + if ( 'INPUT' !== target.nodeName ) {
1435 + return false;
1436 + }
1437 +
1438 + if ( ! target.dataset.invmsg ) {
1439 + return false;
1440 + }
1441 +
1442 + if ( 'text' !== target.getAttribute( 'type' ) ) {
1443 + return false;
1444 + }
1445 +
1446 + if ( target.classList.contains( 'frm_verify' ) ) {
1447 + return false;
1448 + }
1449 +
1450 + return true;
1451 + }
1452 +
1453 + function maybeClearCustomValidityMessage( event, field ) {
1454 + var key,
1455 + isInvalid = false;
1456 +
1457 + if ( ! shouldUpdateValidityMessage( field ) ) {
1458 + return;
1459 + }
1460 +
1461 + for ( key in field.validity ) {
1462 + if ( 'customError' === key ) {
1463 + continue;
1464 + }
1465 + if ( 'valid' !== key && field.validity[ key ] === true ) {
1466 + isInvalid = true;
1467 + break;
1468 + }
1469 + };
1470 +
1471 + if ( ! isInvalid ) {
1472 + field.setCustomValidity( '' );
1473 + }
1474 + }
1475 +
1476 + function maybeShowNewTabFallbackMessage() {
1477 + var messageEl;
1478 +
1479 + if ( ! window.frmShowNewTabFallback ) {
1480 + return;
1481 + }
1482 +
1483 + messageEl = document.querySelector( '#frm_form_' + frmShowNewTabFallback.formId + '_container .frm_message' );
1484 + if ( ! messageEl ) {
1485 + return;
1486 + }
1487 +
1488 + messageEl.insertAdjacentHTML( 'beforeend', ' ' + frmShowNewTabFallback.message );
1489 + }
1490 +
1351 1491 function setCustomValidityMessage() {
1352 1492 var forms, length, index;
1353 1493
1354 1494 forms = document.getElementsByClassName( 'frm-show-form' );
@@ -1359,25 +1499,11 @@
1359 1499 'invalid',
1360 1500 function( event ) {
1361 1501 var target = event.target;
1362 1502
1363 - if ( 'INPUT' !== target.nodeName ) {
1364 - return;
1503 + if ( shouldUpdateValidityMessage( target ) ) {
1504 + target.setCustomValidity( target.dataset.invmsg );
1365 1505 }
1366 -
1367 - if ( ! target.dataset.invmsg ) {
1368 - return;
1369 - }
1370 -
1371 - if ( 'text' !== target.getAttribute( 'type' ) ) {
1372 - return;
1373 - }
1374 -
1375 - if ( target.classList.contains( 'frm_verify' ) ) {
1376 - return;
1377 - }
1378 -
1379 - target.setCustomValidity( target.dataset.invmsg );
1380 1506 },
1381 1507 true
1382 1508 );
1383 1509 }
@@ -1382,8 +1508,21 @@
1382 1508 );
1383 1509 }
1384 1510 }
1385 1511
1512 + function enableSubmitButtonOnBackButtonPress() {
1513 + window.addEventListener( 'pageshow', function( event ) {
1514 + if ( event.persisted ) {
1515 + document.querySelectorAll( '.frm_loading_form' ).forEach(
1516 + function( form ) {
1517 + enableSubmitButton( jQuery( form ) );
1518 + }
1519 + );
1520 + removeSubmitLoading();
1521 + }
1522 + });
1523 + }
1524 +
1386 1525 return {
1387 1526 init: function() {
1388 1527 maybeAddPolyfills();
1389 1528
@@ -1419,11 +1558,20 @@
1419 1558 addTrimFallbackForIE(); // Trim only works in IE10+.
1420 1559 addFilterFallbackForIE(); // Filter is not supported in any version of IE.
1421 1560
1422 1561 initFloatingLabels();
1562 + maybeShowNewTabFallbackMessage();
1423 1563
1424 1564 jQuery( document ).on( 'frmAfterAddRow', setCustomValidityMessage );
1425 1565 setCustomValidityMessage();
1566 + jQuery( document ).on( 'frmFieldChanged', maybeClearCustomValidityMessage );
1567 +
1568 + setSelectPlaceholderColor();
1569 +
1570 + // Elementor popup show event. Fix Elementor Popup && FF Captcha field conflicts
1571 + jQuery( document ).on( 'elementor/popup/show', frmRecaptcha );
1572 +
1573 + enableSubmitButtonOnBackButtonPress();
1426 1574 },
1427 1575
1428 1576 getFieldId: function( field, fullID ) {
1429 1577 return getFieldId( field, fullID );
@@ -1735,9 +1883,11 @@
1735 1883 },
1736 1884
1737 1885 visible: function( classes ) {
1738 1886 jQuery( classes ).css( 'visibility', 'visible' );
1739 - }
1887 + },
1888 +
1889 + triggerCustomEvent: triggerCustomEvent
1740 1890 };
1741 1891 }
1742 1892 frmFrontForm = frmFrontFormJS();
1743 1893