Compare commits

..

No commits in common. "13e64304d4790a4bc9eeca97050138fd50611996" and "2cd537a54712eeb2738cb33b5a33f682cf4ebab6" have entirely different histories.

2 changed files with 52 additions and 82 deletions

View File

@ -117,8 +117,6 @@ pageScripts:
<button type="reset">Reset Form</button> <button type="reset">Reset Form</button>
</div> </div>
<div class="h-captcha" data-sitekey="b63e5b64-c6f2-4154-b5a6-77169a924022E"></div>
<div class="honeypot-field" aria-hidden="true"> <div class="honeypot-field" aria-hidden="true">
<label for="url">Website URL</label> <label for="url">Website URL</label>
<input type="text" name="url" id="url" autocomplete="off" tabindex="-1"> <input type="text" name="url" id="url" autocomplete="off" tabindex="-1">

View File

@ -3,30 +3,6 @@
const form = document.getElementById("contact-form"); const form = document.getElementById("contact-form");
const resetButton = form.querySelector('button[type="reset"]'); const resetButton = form.querySelector('button[type="reset"]');
// Add a div for non-blocking messages
const messageDiv = document.createElement('div');
messageDiv.id = 'form-message';
messageDiv.style.display = 'none';
messageDiv.style.padding = '10px';
messageDiv.style.marginTop = '10px';
messageDiv.style.border = '1px solid';
form.parentNode.insertBefore(messageDiv, form);
// Utility: Show a message to the user
function showMessage(text, isError = false) {
messageDiv.textContent = text;
messageDiv.style.display = 'block';
if (isError) {
messageDiv.style.backgroundColor = '#f8d7da';
messageDiv.style.borderColor = '#f5c6cb';
messageDiv.style.color = '#721c24';
} else {
messageDiv.style.backgroundColor = '#d4edda';
messageDiv.style.borderColor = '#c3e6cb';
messageDiv.style.color = '#155724';
}
}
// Utility: Show error for specific input // Utility: Show error for specific input
function showError(inputId, message) { function showError(inputId, message) {
@ -36,12 +12,10 @@ function showError(inputId, message) {
if (errorSpan) errorSpan.textContent = message; if (errorSpan) errorSpan.textContent = message;
} }
// Utility: Clear all errors and messages // Utility: Clear all errors
function clearErrors() { function clearErrors() {
document.querySelectorAll(".error-message").forEach(span => span.textContent = ""); document.querySelectorAll(".error-message").forEach(span => span.textContent = "");
document.querySelectorAll("input, textarea").forEach(input => input.classList.remove("error")); document.querySelectorAll("input, textarea").forEach(input => input.classList.remove("error"));
messageDiv.style.display = 'none';
messageDiv.textContent = '';
} }
form.addEventListener("submit", function(event) { form.addEventListener("submit", function(event) {
@ -50,13 +24,15 @@ form.addEventListener("submit", function(event) {
clearErrors(); // Clear previous errors clearErrors(); // Clear previous errors
const honeypotField = document.getElementById("url").value.trim(); const honeypotField = document.getElementById("url").value.trim();
// Add the honeypot check at the top
if (honeypotField.length > 0) { if (honeypotField.length > 0) {
console.warn("Honeypot field was filled. Blocking submission."); console.warn("Honeypot field was filled. Blocking submission.");
// Fail silently to avoid alerting the bot. // You might want to display a message to the user,
return; // but it's often better to fail silently to not alert the bot.
return; // This is the most important part: stop the function here.
} }
// Get values, including the hCaptcha response token // Get values
const firstName = document.getElementById("first-name").value.trim(); const firstName = document.getElementById("first-name").value.trim();
const lastName = document.getElementById("last-name").value.trim(); const lastName = document.getElementById("last-name").value.trim();
const organization = document.getElementById("organization").value.trim(); const organization = document.getElementById("organization").value.trim();
@ -64,12 +40,10 @@ form.addEventListener("submit", function(event) {
const phone = document.getElementById("phone").value.trim(); const phone = document.getElementById("phone").value.trim();
const contactMethod = document.querySelector('input[name="contact-method"]:checked')?.value; const contactMethod = document.querySelector('input[name="contact-method"]:checked')?.value;
const message = document.getElementById("message").value.trim(); const message = document.getElementById("message").value.trim();
// Get the hCaptcha token from the global hcaptcha object
const hCaptchaResponse = hcaptcha.getResponse();
let hasErrors = false; let hasErrors = false;
// Validation logic... // First Name
if (!firstName) { if (!firstName) {
showError("first-name", "Please enter your first name."); showError("first-name", "Please enter your first name.");
hasErrors = true; hasErrors = true;
@ -78,6 +52,7 @@ form.addEventListener("submit", function(event) {
hasErrors = true; hasErrors = true;
} }
// Last Name
if (!lastName) { if (!lastName) {
showError("last-name", "Please enter your last name."); showError("last-name", "Please enter your last name.");
hasErrors = true; hasErrors = true;
@ -85,82 +60,79 @@ form.addEventListener("submit", function(event) {
showError("last-name", "Last name must be at least 2 characters."); showError("last-name", "Last name must be at least 2 characters.");
hasErrors = true; hasErrors = true;
} }
// Organization (optional) // Organization (optional)
if (organization.length > 0 && organization.length < 2) { if (organization.length > 0 && organization.length < 2) {
showError("organization", "Organization name must be at least 2 characters."); showError("organization", "Organization name must be at least 2 characters.");
hasErrors = true; hasErrors = true;
} }
// Email
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(email)) { if (!emailPattern.test(email)) {
showError("email", "Please enter a valid email address."); showError("email", "Please enter a valid email address.");
hasErrors = true; hasErrors = true;
} }
// Phone — match format: 123-456-7890
const phonePattern = /^(\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4})$/; const phonePattern = /^(\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4})$/;
if (!phonePattern.test(phone)) { if (!phonePattern.test(phone)) {
showError("phone", "Phone number must be in the format 123-456-7890."); showError("phone", "Phone number must be in the format 123-456-7890.");
hasErrors = true; hasErrors = true;
} }
// Message
if (message.length < 10) { if (message.length < 10) {
showError("message", "Message must be at least 10 characters long."); showError("message", "Message must be at least 10 characters long.");
hasErrors = true; hasErrors = true;
} }
// Check for hCaptcha token
if (!hCaptchaResponse) {
showMessage("Please complete the CAPTCHA.", true);
hasErrors = true;
}
if (!hasErrors) { if (!hasErrors) {
// Package the form data, including the hCaptcha token // Package the form data into an object
const formData = { const formData = {
firstName: firstName, firstName: firstName,
lastName: lastName, lastName: lastName,
organization: organization, organization: organization,
email: email, email: email,
phone: phone, phone: phone,
contactMethod: contactMethod, contactMethod: contactMethod,
message: message, message: message,
url: honeypotField, url: honeypotField,
hCaptchaResponse: hCaptchaResponse // <-- THIS IS THE NEW PART };
};
// Send the data to the backend using fetch() // Send the data to the backend using fetch()
fetch('/submit-form', { fetch('/api/submit-form', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(formData), body: JSON.stringify(formData), // Convert the data object to a JSON string
}) })
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
return response.json(); return response.json(); // Parse the JSON response
} }
throw new Error('Network response was not ok.'); throw new Error('Network response was not ok.');
}) })
.then(data => { .then(data => {
console.log('Success:', data); // Success: handle the server's response
showMessage('Form submitted successfully!', false); console.log('Success:', data);
form.reset(); alert('Form submitted successfully!');
}) form.reset(); // Optionally, reset the form after successful submission
.catch((error) => { })
console.error('Error:', error); .catch((error) => {
showMessage('An error occurred during submission. Please try again.', true); // Error: handle any network or server errors
}); console.error('Error:', error);
} alert('An error occurred during submission. Please try again.');
});
}
}); });
form.addEventListener("reset", function (event) { form.addEventListener("reset", function (event) {
const confirmed = window.confirm("Are you sure you want to clear the form?"); const confirmed = confirm("Are you sure you want to clear the form?");
if (!confirmed) { if (!confirmed) {
event.preventDefault(); event.preventDefault();
return; return;
} }
clearErrors(); clearErrors();
}); });