functional version - sans webpack and linting

This commit is contained in:
ak 2023-06-21 21:50:29 -07:00
parent 4accf027c3
commit f81ca65798
13 changed files with 2627 additions and 0 deletions

1
.gitignore vendored Executable file
View file

@ -0,0 +1 @@
node_modules/

28
index.html Normal file
View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="Description" content="Enter your description here"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<link rel="stylesheet" href="../src/style.css">
<title>Validation Form</title>
</head>
<body class="d-flex h-100 text-center bg-dark">
<div class="cover-container d-flex w-100 h-100 px-3 flex-column">
<header class="d-flex flex-wrap justify-content-center py-3 align-items-center">
<button class="btn btn-primary btn-lg" type="button" id="newButton">
New
</button>
</header>
<center>
<main class="col-sm-6 py-3"></main>
</center>
</div>
<script type="module" src="/src/index.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.2/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/js/bootstrap.min.js"></script>
</body>
</html>

2306
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

20
package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "js-validationform",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "ssh://_gitea@git.alexanderk.net:3022/ak/js-validationform.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.88.0",
"webpack-cli": "^5.1.4"
}
}

14
src/emailValidation.js Normal file
View file

@ -0,0 +1,14 @@
// email field validation
export function emailValidation () {
// finds "@"" and "." in inputted email address
const findAt = new RegExp(/[@]/, 'gi');
const findDot = new RegExp(/[\.]/, 'gi');
if (findAt.test(this.value) && findDot.test(this.value)) {
this.setCustomValidity('');
this.reportValidity();
return;
}
// otherwise highlights field and pops up message
this.setCustomValidity("Please insert a valid e-mail address");
this.reportValidity();
}

5
src/index.js Normal file
View file

@ -0,0 +1,5 @@
import { makeWindow } from "./makeWindow.js";
const NEWBUTTON = document.getElementById('newButton');
NEWBUTTON.onclick = () => makeWindow();

11
src/inputValidation.js Normal file
View file

@ -0,0 +1,11 @@
// input validation for input fields without specific requirements
export function inputValidation (originalValue) {
// if the user has not entered a value different from the original, highlight and pop up message
if (this.value === originalValue || this.value === '') {
this.setCustomValidity("Please fill out this field");
this.reportValidity();
return;
}
this.setCustomValidity('');
this.reportValidity();
}

165
src/makeWindow.js Normal file
View file

@ -0,0 +1,165 @@
import { zipValidation } from "./zipValidation.js"
import { emailValidation } from "./emailValidation.js";
import { inputValidation } from "./inputValidation.js";
import { passwordValidation } from "./passwordValidation.js";
import { submissionValid } from "./submissionValidation.js";
const BODY = document.querySelector('main');
// close button functionality
const closeWindow = (headDiv) => {
headDiv.parentElement.removeChild(headDiv);
}
// handy way of making new elements
const makeElement = (passedClass, passedType = 'div') => {
const newElement = document.createElement(passedType);
newElement.setAttribute('class', passedClass);
return newElement;
}
const thumbsUp = () => {
// remove input fields
for (let i = 0; i < 5; i++) {
formWindow.removeChild(document.getElementById(`input-${i + 1}`));
}
// remove submit button
formWindow.removeChild(formWindow.lastChild);
// add thumbs up
const thumbsUpGIF = document.createElement('img');
thumbsUpGIF.src = "/src/thumbsup.gif";
formWindow.appendChild(thumbsUpGIF);
}
export const makeWindow = () => {
// *make window itself*
// 1. window body
const formWindow = makeElement('card-body', 'form');
formWindow.id = 'formWindow';
BODY.appendChild(makeElement('card')).appendChild(formWindow);
// 2. close button div
const closeButton = makeElement('mb-3 d-flex');
formWindow.appendChild(closeButton);
// the close button is SVG
// 3. container for SVG - 24x24
const closeButtonSVGContainer = document.createElementNS("http://www.w3.org/2000/svg","svg");
closeButtonSVGContainer.style = "width: 24px; height: 24px";
closeButtonSVGContainer.setAttribute('viewbox', '0 0 24 24');
closeButtonSVGContainer.id = 'closeButton';
closeButton.appendChild(closeButtonSVGContainer);
// 4. the actual SVG path
const closeButtonSVGPath = document.createElementNS("http://www.w3.org/2000/svg","path");
closeButtonSVGPath.setAttribute('d', "M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z");
closeButtonSVGPath.fill = "#6c757d";
closeButtonSVGContainer.appendChild(closeButtonSVGPath);
// add event listeners to close the window if button is clicked
closeButtonSVGContainer.onclick = () => closeWindow(formWindow.parentElement);
// *make input fields*
// generate container divs
for (let i = 0; i < 5; i++) {
const inputContainer = makeElement('mb-3');
inputContainer.id = `input-${i + 1}`;
formWindow.appendChild(inputContainer);
}
const originalValues = [];
// 5. email field
const userEmail = makeElement('form-control', 'input');
userEmail.type = 'text';
userEmail.value = 'Email address';
originalValues.push(userEmail.value);
document.getElementById('input-1').appendChild(userEmail);
// 6. country field
const userCountry = makeElement('form-control', 'input');
userCountry.type = 'text';
userCountry.value = 'Country';
originalValues.push(userCountry.value);
document.getElementById('input-2').appendChild(userCountry);
// 7. zip code field
const userZip = makeElement('form-control', 'input');
userZip.type = 'text';
userZip.value = 'Zip code';
originalValues.push(userZip.value);
document.getElementById('input-3').appendChild(userZip);
// only allow numeric input
userZip.oninput = (e) => {
let numericValue = e.target.value.replace(new RegExp(/[^\d]/,'gi'), "");
numericValue = numericValue.substring(0,5);
e.target.value = numericValue;
}
// 8. password field
const userPass = makeElement('form-control', 'input');
userPass.type = 'text';
userPass.value = 'Password';
originalValues.push(userPass.value);
document.getElementById('input-4').appendChild(userPass);
// 9. password confirmation field
const userPassConfirm = makeElement('form-control', 'input');
userPassConfirm.type = 'text';
userPassConfirm.value = 'Confirm password';
originalValues.push(userPassConfirm.value);
document.getElementById('input-5').appendChild(userPassConfirm);
// blank out the input fields when focused and change back when not focused
document.querySelectorAll('.form-control').forEach(inputField => {
// keep original value for validation purposes
const originalValue = inputField.value;
let oldValue = '';
inputField.onfocus = () => {
// erases characters from input field when focused
oldValue = inputField.value;
inputField.value = '';
// change password fields to hide password characters
if (inputField === userPass || inputField === userPassConfirm) {
inputField.type = 'password';
}
}
inputField.onblur = (e) => {
// change back input field value to the old value if unmodified
if (inputField.value === '') {
inputField.value = oldValue;
}
// email validation
if (inputField === userEmail) {
emailValidation.call(e.target);
return;
}
// zip validation
if (inputField === userZip) {
zipValidation.call(e.target);
}
// general input field validation
inputValidation.call(e.target, originalValue);
// password validation
if (inputField === userPassConfirm) {
passwordValidation.call(e.target, userPass.value);
}
}
});
// 10. submit button
const submitButton = makeElement('btn btn-primary', 'button');
submitButton.type = 'submit';
submitButton.textContent = "Submit";
formWindow.appendChild(submitButton);
// prevent default
submitButton.onclick = (event) => {
event.preventDefault();
if (submissionValid(document.querySelectorAll('.form-control'), originalValues)) {
// give em a thumbs up
thumbsUp();
return;
}
// or tell them to fix it
alert("Please properly fill out all fields");
};
}

12
src/passwordValidation.js Normal file
View file

@ -0,0 +1,12 @@
// password validation
export function passwordValidation (origPassword) {
// check if passwords match
if (this.value === origPassword) {
this.setCustomValidity('');
this.reportValidity();
return;
}
// otherwise highlight and pop up message
this.setCustomValidity("Please ensure passwords match");
this.reportValidity();
}

36
src/style.css Normal file
View file

@ -0,0 +1,36 @@
.card {
width: 30rem;
}
.form-control {
color: #6c757d !important;
}
.form-control:focus {
color: black !important;
}
#formWindow {
background-color: white;
}
.card-body > .d-flex {
justify-content: end;
}
#closeButton {
cursor: pointer;
}
input:invalid {
border: none;
outline: 2px solid red;
}
img {
max-height:100%;
max-width:100%;
border-radius: 1%;
border: 1px solid black;
box-shadow: 1px 1px 5px black;
}

View file

@ -0,0 +1,17 @@
// submit button validation
export const submissionValid = (inputFields, originalValues) => {
// checks each field for validity
let bool = true;
let arrNum = 0;
inputFields.forEach(inputField => {
// if the field is previously invalid, unchanged or blank declare validity to be false
if (!(inputField.validity.valid) ||
inputField.value === originalValues[arrNum] ||
inputField === '') {
bool = false;
}
arrNum++;
});
// returns final validity
return bool;
}

BIN
src/thumbsup.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

12
src/zipValidation.js Normal file
View file

@ -0,0 +1,12 @@
// zip field validation
const LENGTH = 5
export function zipValidation () {
// if zip code is under 5 digits, highlight field and pop up message
if (this.value.length < LENGTH) {
this.setCustomValidity("Please enter a valid zip code");
this.reportValidity();
return;
}
this.setCustomValidity('');
this.reportValidity();
}