jQuery( document ).ready( function( $ ) {
let form = $( '.sailthru-contact-form' );
if( form.length ) {
$( form ).on( 'submit', function ( e ) {
e.preventDefault();
let form = $( e.target ),
action = $( e.target ).find( 'input[name="action"]' ).val() || 'contact';
// Validate form on front-end
if ( !validateForm( e.target )) {
return;
}
if ( 'undefined' !== typeof amiSailthruContact.recaptcha ) {
if ( !window.amiSailthruReCaptchaInit ) {
window.amiSailthruReCaptchaInit = true;
let recaptcha_script = document.createElement( 'script' );
recaptcha_script.id = 'sailthru-recaptcha';
recaptcha_script.src = amiSailthruContact.recaptcha.script_src;
recaptcha_script.async = true;
recaptcha_script.onload = function () {
grecaptcha.enterprise.ready( function () {
grecaptcha.enterprise.execute( amiSailthruContact.recaptcha.site_key, { action: action } ).then( function ( token ) {
submit_form( form, token );
} );
} );
};
document.body.appendChild( recaptcha_script );
} else {
grecaptcha.enterprise.ready( function () {
grecaptcha.enterprise.execute( amiSailthruContact.recaptcha.site_key, { action: action } ).then( function ( token ) {
submit_form( form, token );
} );
} );
}
} else {
submit_form( form );
}
} );
}
/**
* Submits a form via AJAX request
*
* @param {Object} form - The form element or selector
* @param {boolean} [token=false] - The token to add to the form data
*
* @return {void}
*/
function submit_form( form, token = false ) {
let submit_form = $( form ),
submit = $( submit_form ).find( '.contact-submit' ),
messaging = $( submit_form ).parent().find( '.contact__messaging' ),
success = $( submit_form ).parent().find( '.contact__success' ),
success_message = $( success ).find( '.contact-success' );
$( submit ).prop( 'disabled', true );
$( messaging ).text( amiSailthruContact.messages.process ).removeClass( 'error' );
$( submit_form ).find( 'input.error' ).removeClass( 'error' ).attr('aria-invalid', 'false');
let prepare_form_data = $( submit_form ).serializeArray(),
form_data = {};
$.map( prepare_form_data, function( n, i ){
form_data[ n['name'] ] = n['value'];
} );
// add token
if( token ) {
form_data['token'] = token;
}
$.ajax( {
url: amiSailthruContact.endpoint,
type: 'POST',
data: form_data,
dataType: 'json',
success: function ( response ) {
if( response.success ) {
$( submit_form ).hide();
$( messaging ).hide();
$( success ).show()
if ( success_message.length ) {
success_message.scrollIntoView( {
behavior: 'smooth',
block: 'center'
} );
}
} else {
$( submit ).prop( 'disabled', false );
$( messaging ).text( amiSailthruContact.messages.default_error ).addClass( 'error' );
}
},
error: function( error ) {
$( submit ).prop( 'disabled', false );
let errors_data = error.responseJSON;
if( 'rest_invalid_param' === errors_data.code || 'rest_missing_callback_param' === errors_data.code ) {
let invalid_param = 'rest_invalid_param' === errors_data.code ? Object.keys( errors_data.data.params )[0] : errors_data.data.params[0];
$( messaging ).text( amiSailthruContact.messages[ 'invalid_' + invalid_param ] ).addClass( 'error' );
$( submit_form ).find( 'input[name="' + invalid_param + '"]' ).addClass( 'error' ).attr('aria-invalid', 'true');
} else {
$( messaging ).text( amiSailthruContact.messages.default_error ).addClass( 'error' );
}
}
} );
}
/**
* Form field validation
*
* @param field
* @returns {boolean}
*/
function validateField( field ) {
let isValid = true;
const fieldType = field.type;
if ( ( fieldType === 'text' ) || ( fieldType === 'textarea' ) ) {
if ( field.value.trim() === '' ) {
isValid = false;
}
} else if ( fieldType === 'email' ) {
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if ( !emailPattern.test( field.value ) ) {
isValid = false;
}
}
return isValid;
}
/**
* Front-end form validation
*/
function validateForm( form ) {
const messaging = form.parentNode.querySelector( '.contact__messaging' );
let formIsValid = true;
let errorMessages = '';
messaging.classList.remove( 'error' );
messaging.innerHTML = '';
form.querySelectorAll( '[aria-required="true"]' ).forEach(field => {
if ( validateField( field ) ) {
field.classList.remove( 'error' );
field.setAttribute( 'aria-invalid', 'false' );
} else {
formIsValid = false;
field.classList.add( 'error' );
field.setAttribute( 'aria-invalid', 'true' );
const nextEl = field.nextElementSibling;
errorMessages += nextEl?.classList?.contains( 'error-message' ) ? nextEl.textContent + '
' : amiSailthruContact.messages['invalid_field'] + ` ${field?.name}.
`;
}
});
if ( !formIsValid ) {
displayFormMessage().then( () => {
messaging.classList.add( 'error' );
messaging.innerHTML = errorMessages;
} );
}
return formIsValid;
}
// Display form message with a delay (needed for screen readers)
function displayFormMessage() {
return new Promise( resolve => setTimeout( resolve, 50 ) );
}
} );