functional version - sans webpack and linting
This commit is contained in:
parent
4accf027c3
commit
f81ca65798
13 changed files with 2627 additions and 0 deletions
1
.gitignore
vendored
Executable file
1
.gitignore
vendored
Executable file
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
||||||
28
index.html
Normal file
28
index.html
Normal 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
2306
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
20
package.json
Normal file
20
package.json
Normal 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
14
src/emailValidation.js
Normal 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
5
src/index.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { makeWindow } from "./makeWindow.js";
|
||||||
|
|
||||||
|
const NEWBUTTON = document.getElementById('newButton');
|
||||||
|
|
||||||
|
NEWBUTTON.onclick = () => makeWindow();
|
||||||
11
src/inputValidation.js
Normal file
11
src/inputValidation.js
Normal 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
165
src/makeWindow.js
Normal 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
12
src/passwordValidation.js
Normal 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
36
src/style.css
Normal 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;
|
||||||
|
}
|
||||||
17
src/submissionValidation.js
Normal file
17
src/submissionValidation.js
Normal 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
BIN
src/thumbsup.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 342 KiB |
12
src/zipValidation.js
Normal file
12
src/zipValidation.js
Normal 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();
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue