1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-13 01:45:30 -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:
2021-10-15 08:30:54 -04:00
parent 22dedf640a
commit 0b5c95ac42
4 changed files with 71 additions and 60 deletions
+23 -12
View File
@@ -10,9 +10,12 @@ if (contactForm) {
// immediately prevent <form> from actually submitting to a new page // immediately prevent <form> from actually submitting to a new page
event.preventDefault(); 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) // 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) { if (submitButton.disabled === true) {
return; return;
} }
@@ -22,13 +25,22 @@ if (contactForm) {
submitButton.disabled = true; // prevent accidental multiple submissions submitButton.disabled = true; // prevent accidental multiple submissions
submitButton.style.cursor = "default"; submitButton.style.cursor = "default";
// feedback <span>s for later try {
const successSpan = document.getElementById("contact-form-result-success");
const errorSpan = document.getElementById("contact-form-result-error");
// https://simonplend.com/how-to-use-fetch-to-post-form-data-as-json-to-your-api/ // 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()); 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");
}
// post JSONified form input to /api/contact/
fetch(contactForm.action, { fetch(contactForm.action, {
method: "POST", method: "POST",
headers: { headers: {
@@ -54,17 +66,15 @@ if (contactForm) {
// pass on an error sent by the server // pass on an error sent by the server
throw new Error(data.message); throw new Error(data.message);
} }
}) });
.catch((error) => { } catch (error) {
const message = error instanceof Error ? error.message : "Unknown"; const message = error instanceof Error ? error.message : "Unknown";
// give user feedback based on the error message returned // give user feedback based on the error message returned
if (message === "invalidCaptcha") { if (message === "invalidCaptcha") {
errorSpan.innerText = "Error: Did you remember to click the CAPTCHA?"; errorSpan.innerText = "Did you complete the CAPTCHA? (If you're human, that is...)";
} else if (message === "invalidEmail") {
errorSpan.innerText = "Error: Please double check your email address.";
} else if (message === "missingData") { } else if (message === "missingData") {
errorSpan.innerText = "Error: Please make sure that all fields are filled in."; errorSpan.innerText = "Please make sure that all fields are filled in.";
} else { } else {
// something else went wrong, and it's probably my fault... // something else went wrong, and it's probably my fault...
errorSpan.innerText = "Internal server error. Try again later?"; errorSpan.innerText = "Internal server error. Try again later?";
@@ -74,6 +84,7 @@ if (contactForm) {
submitButton.innerText = "Try Again"; submitButton.innerText = "Try Again";
submitButton.disabled = false; submitButton.disabled = false;
submitButton.style.cursor = "pointer"; submitButton.style.cursor = "pointer";
}); submitButton.blur(); // remove keyboard focus from the button
}
}); });
} }
+1 -1
View File
@@ -77,7 +77,7 @@ $themes: (
super-duper-light: #1f1f1f, super-duper-light: #1f1f1f,
links: #88c7ff, links: #88c7ff,
success: #78df55, success: #78df55,
error: #f54545, error: #ff5151,
), ),
); );
+5 -5
View File
@@ -13,14 +13,14 @@ div.layout-contact {
p { p {
font-size: 0.9em; font-size: 0.9em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
}
a code { code {
background: none; background: none !important;
border: 0; border: 0;
padding: 0; padding: 0;
word-spacing: -0.2em; word-spacing: -0.175em;
white-space: normal; white-space: normal; // re-enable "word" wrapping
}
} }
input[type="text"], input[type="text"],
+3 -3
View File
@@ -6,10 +6,10 @@
<p>🔐 You can grab my public key here: <a href="/pubkey.asc" title="My Public PGP Key" target="_blank" rel="pgpkey authn noopener"><code>6BF3 79D3 6F67 1480 2B0C 9CF2 51E6 9A39</code></a>.</p> <p>🔐 You can grab my public key here: <a href="/pubkey.asc" title="My Public PGP Key" target="_blank" rel="pgpkey authn noopener"><code>6BF3 79D3 6F67 1480 2B0C 9CF2 51E6 9A39</code></a>.</p>
<form id="contact-form" action="/api/contact/" method="POST"> <form id="contact-form" action="/api/contact/" method="POST">
<input type="text" id="name" name="name" placeholder="Name"> <input type="text" name="name" placeholder="Name">
<input type="email" id="email" name="email" placeholder="Email"> <input type="email" name="email" placeholder="Email">
<textarea name="message" placeholder="Write something..."></textarea>
<textarea id="message" name="message" placeholder="Write something..."></textarea>
<span id="contact-form-md-info">Basic <a href="https://commonmark.org/help/" title="Markdown reference sheet" target="_blank" rel="noopener">Markdown syntax</a> is allowed here, e.g.: <strong>**bold**</strong>, <em>_italics_</em>, [<a href="https://jarv.is" target="_blank" rel="noopener">links</a>](https://jarv.is), and <code>`code`</code>.</span> <span id="contact-form-md-info">Basic <a href="https://commonmark.org/help/" title="Markdown reference sheet" target="_blank" rel="noopener">Markdown syntax</a> is allowed here, e.g.: <strong>**bold**</strong>, <em>_italics_</em>, [<a href="https://jarv.is" target="_blank" rel="noopener">links</a>](https://jarv.is), and <code>`code`</code>.</span>
<h-captcha <h-captcha