mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-07-21 19:21:18 -04:00
some client-side validation on contact form
exactly identical errors to the one the server sends, but saves a few requests
This commit is contained in:
@@ -10,9 +10,12 @@ if (contactForm) {
|
||||
// immediately prevent <form> from actually submitting to a new page
|
||||
event.preventDefault();
|
||||
|
||||
const submitButton = document.getElementById("contact-form-btn-submit");
|
||||
// feedback <span>s for later
|
||||
const successSpan = document.getElementById("contact-form-result-success");
|
||||
const errorSpan = document.getElementById("contact-form-result-error");
|
||||
|
||||
// disable the whole form if the button has been disabled below (on success)
|
||||
const submitButton = document.getElementById("contact-form-btn-submit");
|
||||
if (submitButton.disabled === true) {
|
||||
return;
|
||||
}
|
||||
@@ -22,58 +25,66 @@ if (contactForm) {
|
||||
submitButton.disabled = true; // prevent accidental multiple submissions
|
||||
submitButton.style.cursor = "default";
|
||||
|
||||
// feedback <span>s for later
|
||||
const successSpan = document.getElementById("contact-form-result-success");
|
||||
const errorSpan = document.getElementById("contact-form-result-error");
|
||||
try {
|
||||
// https://simonplend.com/how-to-use-fetch-to-post-form-data-as-json-to-your-api/
|
||||
const formData = Object.fromEntries(new FormData(event.currentTarget).entries());
|
||||
|
||||
// https://simonplend.com/how-to-use-fetch-to-post-form-data-as-json-to-your-api/
|
||||
const formData = Object.fromEntries(new FormData(event.currentTarget).entries());
|
||||
// some client-side validation, these are all also checked on the server
|
||||
// to be safe but we can save some unnecessary requests here.
|
||||
// we throw identical error messages to the server's so they're caught in
|
||||
// the same way below.
|
||||
if (!formData.name || !formData.email || !formData.message) {
|
||||
throw new Error("missingData");
|
||||
}
|
||||
if (!formData["h-captcha-response"]) {
|
||||
throw new Error("invalidCaptcha");
|
||||
}
|
||||
|
||||
fetch(contactForm.action, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.success === true) {
|
||||
// handle successful submission
|
||||
// we can disable submissions & hide the send button now
|
||||
submitButton.disabled = true;
|
||||
submitButton.style.display = "none";
|
||||
|
||||
// just in case there *was* a PEBCAK error and it was corrected
|
||||
errorSpan.style.display = "none";
|
||||
|
||||
// let user know we were successful
|
||||
successSpan.innerText = "Success! You should hear from me soon. :)";
|
||||
} else {
|
||||
// pass on an error sent by the server
|
||||
throw new Error(data.message);
|
||||
}
|
||||
// post JSONified form input to /api/contact/
|
||||
fetch(contactForm.action, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
})
|
||||
.catch((error) => {
|
||||
const message = error instanceof Error ? error.message : "Unknown";
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
if (data.success === true) {
|
||||
// handle successful submission
|
||||
// we can disable submissions & hide the send button now
|
||||
submitButton.disabled = true;
|
||||
submitButton.style.display = "none";
|
||||
|
||||
// give user feedback based on the error message returned
|
||||
if (message === "invalidCaptcha") {
|
||||
errorSpan.innerText = "Error: Did you remember to click the CAPTCHA?";
|
||||
} else if (message === "invalidEmail") {
|
||||
errorSpan.innerText = "Error: Please double check your email address.";
|
||||
} else if (message === "missingData") {
|
||||
errorSpan.innerText = "Error: Please make sure that all fields are filled in.";
|
||||
} else {
|
||||
// something else went wrong, and it's probably my fault...
|
||||
errorSpan.innerText = "Internal server error. Try again later?";
|
||||
}
|
||||
// just in case there *was* a PEBCAK error and it was corrected
|
||||
errorSpan.style.display = "none";
|
||||
|
||||
// reset submit button to let user try again
|
||||
submitButton.innerText = "Try Again";
|
||||
submitButton.disabled = false;
|
||||
submitButton.style.cursor = "pointer";
|
||||
});
|
||||
// let user know we were successful
|
||||
successSpan.innerText = "Success! You should hear from me soon. :)";
|
||||
} else {
|
||||
// pass on an error sent by the server
|
||||
throw new Error(data.message);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unknown";
|
||||
|
||||
// give user feedback based on the error message returned
|
||||
if (message === "invalidCaptcha") {
|
||||
errorSpan.innerText = "Did you complete the CAPTCHA? (If you're human, that is...)";
|
||||
} else if (message === "missingData") {
|
||||
errorSpan.innerText = "Please make sure that all fields are filled in.";
|
||||
} else {
|
||||
// something else went wrong, and it's probably my fault...
|
||||
errorSpan.innerText = "Internal server error. Try again later?";
|
||||
}
|
||||
|
||||
// reset submit button to let user try again
|
||||
submitButton.innerText = "Try Again";
|
||||
submitButton.disabled = false;
|
||||
submitButton.style.cursor = "pointer";
|
||||
submitButton.blur(); // remove keyboard focus from the button
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user