Skip to content

Commit

Permalink
Edit: repeat code (#37371)
Browse files Browse the repository at this point in the history
* Edit: repeat code

This commit will extract out repeat code into a new function and call that function from the event handlers. This will improve code readability.

* Edit: variable scope

This commit will tightly scope variable because it is not referenced anywhere else outside the function.

* Refactor: functions for readability and separation of concerns

This commit will refactor functions with the goal of being readable for viewers.
This commit will also separate functions that check if input is of valid
email type and functions that will set the email class name based on that validation.
This commit will also set and/or remove error class name based on the value of email validation function.

* Refactor: functions for readability and separation of concerns

This commit will refactor functions with the goal of being readable for viewers.
This commit will also fix validation result when email value length is 0.
This commit will also separate functions that check if input is of valid
email type and functions that will set the email class name based on
that validation.
This commit will also set and/or remove error class name based on the value of email validation function.

* Fix: email regex and error element attr

This commit will change the attribute of error span element from className to id.
This commit will also declare the email regex pattern outside the check email validation function.

* Edit: formatting whitespace

* Edit: formatting suggestion by linter/formatter

* Update index.md

* Update index.md

---------

Co-authored-by: Chris Mills <[email protected]>
  • Loading branch information
sazk07 and chrisdavidmills authored Dec 31, 2024
1 parent 99e1dec commit ddbd648
Showing 1 changed file with 58 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,9 @@ The HTML is almost the same; we just removed the HTML validation features.
<p>
<label for="mail">
<span>Please enter an email address:</span>
<input type="text" id="mail" name="mail" />
<span class="error" aria-live="polite"></span>
</label>
<input type="text" id="mail" name="mail" />
<span id="error" aria-live="polite"></span>
</p>
<button>Submit</button>
</form>
Expand All @@ -740,7 +740,7 @@ p * {
display: block;
}

input#mail {
input {
appearance: none;
width: 100%;
border: 1px solid #333;
Expand All @@ -753,29 +753,29 @@ input#mail {
}

/* invalid fields */
input#mail.invalid {
border-color: #900;
input.invalid {
border: 2px solid #900;
background-color: #fdd;
}

input:focus.invalid {
outline: none;
/* make sure keyboard-only users see a change when focusing */
border-style: dashed;
}

/* error messages */
.error {
#error {
width: 100%;
padding: 0;

font-size: 80%;
color: white;
background-color: #900;
border-radius: 0 0 5px 5px;
box-sizing: border-box;
}

.error.active {
padding: 0.3em;
.active {
padding: 0.3rem;
}
```

Expand All @@ -784,54 +784,69 @@ The big changes are in the JavaScript code, which needs to do much more heavy li
```js
const form = document.querySelector("form");
const email = document.getElementById("mail");
const error = email.nextElementSibling;
const error = document.getElementById("error");

// As per the HTML Specification
// Regular expression for email validation as per HTML specification
const emailRegExp =
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

// Now we can rebuild our validation constraint
// Because we do not rely on CSS pseudo-class, we have to
// explicitly set the valid/invalid class on our email field
window.addEventListener("load", () => {
// Here, we test if the field is empty (remember, the field is not required)
// If it is not, we check if its content is a well-formed email address.
const isValid = email.value.length === 0 || emailRegExp.test(email.value);
// Check if the email is valid
const isValidEmail = () => {
const validity = email.value.length !== 0 && emailRegExp.test(email.value);
return validity;
};

// Update email input class based on validity
const setEmailClass = (isValid) => {
email.className = isValid ? "valid" : "invalid";
});
};

// This defines what happens when the user types in the field
email.addEventListener("input", () => {
const isValid = email.value.length === 0 || emailRegExp.test(email.value);
if (isValid) {
email.className = "valid";
// Update error message and visibility
const updateError = (isValidInput) => {
if (isValidInput) {
error.textContent = "";
error.className = "error";
error.removeAttribute("class");
} else {
email.className = "invalid";
error.textContent = "I expect an email, darling!";
error.setAttribute("class", "active");
}
});

// This defines what happens when the user tries to submit the data
form.addEventListener("submit", (event) => {
};

// Initialize email validity on page load
const initializeValidation = () => {
const emailInput = isValidEmail();
setEmailClass(emailInput);
};

// Handle input event to update email validity
const handleInput = () => {
const emailInput = isValidEmail();
setEmailClass(emailInput);
updateError(emailInput);
};

// Handle form submission to show error if email is invalid
const handleSubmit = (event) => {
event.preventDefault();

const isValid = email.value.length === 0 || emailRegExp.test(email.value);
if (!isValid) {
email.className = "invalid";
error.textContent = "I expect an email, darling!";
error.className = "error active";
} else {
email.className = "valid";
error.textContent = "";
error.className = "error";
}
});
const emailInput = isValidEmail();
setEmailClass(emailInput);
updateError(emailInput);
};

// Now we can rebuild our validation constraint
// Because we do not rely on CSS pseudo-class, we have to
// explicitly set the valid/invalid class on our email field
window.addEventListener("load", initializeValidation);
// This defines what happens when the user types in the field
email.addEventListener("input", handleInput);
// This defines what happens when the user tries to submit the data
form.addEventListener("submit", handleSubmit);
```

The result looks like this:

{{EmbedLiveSample("An_example_that_doesnt_use_the_constraint_validation_API", "100%", 130)}}
{{EmbedLiveSample("An_example_that_doesnt_use_the_constraint_validation_API", "100%", 150)}}

As you can see, it's not that hard to build a validation system on your own. The difficult part is to make it generic enough to use both cross-platform and on any form you might create. There are many libraries available to perform form validation, such as [Validate.js](https://rickharrison.github.io/validate.js/).

Expand Down

0 comments on commit ddbd648

Please sign in to comment.