Skip to content

Commit

Permalink
Remove JQuery from form validation code (#160)
Browse files Browse the repository at this point in the history
* Replace JQuery in input file and error message code

* Replace JQuery in form validation script

* Fix event listeners and clean up code

* Remove JQuery script

* Use query selectors for easier iteration

* Make error list clearing more efficient

* Use template string literals instead of concatenation

Co-authored-by: David Alexander <TheLonelyGhost@users.noreply.github.com>

* Fix form labels being deleted when displaying form errors

Co-authored-by: David Alexander <TheLonelyGhost@users.noreply.github.com>
  • Loading branch information
TimJentzsch and TheLonelyGhost committed Jun 23, 2021
1 parent a8fad24 commit 41443cd
Showing 1 changed file with 58 additions and 52 deletions.
110 changes: 58 additions & 52 deletions blossom/templates/website/generic_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,6 @@
{% load string_helpers %}

{% block content %}
{% comment %}
TODO: Rip jQuery out of this form
This has just enough jquery in it to be irritating, but it's the only
page that actually requires it. Since this is the only one, we'll
import jquery here and hopefully nuke it one of these days when someone
better at JS than me comes and looks at it.
{% endcomment %}
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"></script>
<div class="container mt-4">
{% if slim_form %}
<div class="row">
Expand Down Expand Up @@ -136,9 +125,8 @@ <h4>{{ subheader }}</h4>
</div>

<script>
document.addEventListener("DOMContentLoaded", function (event) {
const inputs = document.querySelectorAll('.inputfile');
Array.prototype.forEach.call(inputs, function (input) {
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll('.inputfile').forEach(function (input) {
let label = input.previousElementSibling

input.addEventListener('change', function (e) {
Expand All @@ -149,52 +137,70 @@ <h4>{{ subheader }}</h4>
label.innerText = fileName ? fileName : "browse";
});
});
// from https://www.tjvantoll.com/2012/08/05/html5-form-validation-showing-all-error-messages/
const createAllErrors = function () {
let form = $(this)
let errorList = $(".errorMessages");

const showAllErrorMessages = function () {
errorList.innerHTML = "";
// Adapted from https://www.tjvantoll.com/2012/08/05/html5-form-validation-showing-all-error-messages/
document.querySelectorAll("form").forEach(function (form) {
const errorList = form.querySelector(".errorMessages");

// Find all invalid fields within the form.
form.find(":invalid").each(function (index, node) {
if (errorList) {
const showAllErrorMessages = function () {
errorList.textContent = "";

// Find the field's corresponding label
let label = $("label[for=" + node.id + "] "),
// Find all invalid fields within the form.
form.querySelectorAll(":invalid").forEach(function (node) {
// Find the field's corresponding label
const label = form.querySelector(`label[for="${node.id}"]`);
// Opera incorrectly does not fill the validationMessage property.
message = node.validationMessage || 'Invalid value.';

// jquery won't add the same class multiple times, so we can have
// addClass run for each loop.
errorList.addClass("mt-3");
errorList.append(
'<div class="alert alert-danger" role="alert">\n' + label.html() + " " + message + '\n</div>'
)
const message = node.validationMessage || 'Invalid value.';

if (!errorList.classList.contains("mt-3")) {
errorList.classList.add("mt-3");
}

// Add the error message to the list
const errorMessage = document.createElement("span");
errorMessage.innerText = " " + message;

const errorElement = document.createElement("div");
errorElement.classList.add("alert");
errorElement.classList.add("alert-danger");
errorElement.role = "alert";
if (label) {
errorElement.appendChild(label.cloneNode(true));
}
errorElement.appendChild(errorMessage);

errorList.appendChild(errorElement);
});
};

// Support Safari
form.addEventListener("submit", function (event) {
if (this.checkValidity && !this.checkValidity()) {
const firstInvalid = form.querySelector(":invalid");
if (firstInvalid) {
firstInvalid.focus();
}
event.preventDefault();
}
});
};

// Support Safari
form.on("submit", function (event) {
if (this.checkValidity && !this.checkValidity()) {
$(this).find(":invalid").first().focus();
event.preventDefault();
const submitButton = form.querySelector("input[type=submit], button:not([type=button])");
if (submitButton) {
submitButton.addEventListener("click", showAllErrorMessages);
}
});

$("input[type=submit], button:not([type=button])", form)
.on("click", showAllErrorMessages);

$("input", form).on("keypress", function (event) {
let type = $(this).attr("type");
if (/date|email|month|number|search|tel|text|time|url|week/.test(type)
&& event.keyCode === 13) {
showAllErrorMessages();
}
});
};

$("form").each(createAllErrors);
form.querySelectorAll("input").forEach(function (inputElem) {
inputElem.addEventListener("keypress", function (event) {
const checkedTypes = ["date", "email", "month", "number", "search", "tel", "text", "time", "url", "week"]
if (checkedTypes.includes(inputElem.type)
&& event.code === "Enter") {
showAllErrorMessages();
}
});
});
}
});
})
</script>

Expand Down

0 comments on commit 41443cd

Please sign in to comment.