Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove JQuery from form validation code #160

Merged
merged 8 commits into from
Jun 23, 2021
116 changes: 64 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,9 @@ <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 () {
const inputs = Array.from(document.getElementsByClassName('inputfile'));
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved
inputs.forEach(function (input) {
let label = input.previousElementSibling

input.addEventListener('change', function (e) {
Expand All @@ -149,52 +138,75 @@ <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/
const forms = Array.from(document.getElementsByTagName("form"));
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved

// Find all invalid fields within the form.
form.find(":invalid").each(function (index, node) {
forms.forEach(function (form) {
const errorLists = form.getElementsByClassName("errorMessages");

// Find the field's corresponding label
let label = $("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>'
)
});
};
if (errorLists.length > 0) {
const errorList = errorLists[0];

// Support Safari
form.on("submit", function (event) {
if (this.checkValidity && !this.checkValidity()) {
$(this).find(":invalid").first().focus();
event.preventDefault();
}
});
const showAllErrorMessages = function () {
errorList.innerHTML = "";
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved

$("input[type=submit], button:not([type=button])", form)
.on("click", showAllErrorMessages);
// Find all invalid fields within the form.
form.querySelectorAll(":invalid").forEach(function (node) {
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved
// Find the field's corresponding label
const label = form.querySelector('label[for="' + node.id + '"]');
TimJentzsch marked this conversation as resolved.
Show resolved Hide resolved
// Opera incorrectly does not fill the validationMessage property.
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);
}
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();
}
});

$("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();
const submitButton = form.querySelector("input[type=submit], button:not([type=button])");
if (submitButton) {
submitButton.addEventListener("click", showAllErrorMessages);
}
});
};

$("form").each(createAllErrors);
const inputElems = Array.from(form.getElementsByTagName("input"));
inputElems.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