How can I get my validation fields to go red and green? - javascript

I literally started coding two days ago. I'm working on a project for a job application in which I have to create a form that goes green and red depending on success/error, and I used a YouTube tutorial to guide me through. Everything was going fine until I tried to code the error and success classes (i.e. the fields turning red or green) for the inputs, and after clicking submit nothing happens!
Here is the code I have written so far. Where have I gone wrong?
HTML:
<div class="container">
<form class="form" id="form"; action="mailto:changed#email.com"
method="POST"
enctype="text/plain:
name="EmailForm>
<div class="form-control">
<label>Name</label>
<input type="text" name="Name" placeholder="Enter Your Name" id="name">
</div>
<div class="form-control">
<label>Email</label>
<input type="email" name="Email" placeholder="Enter Your Email" id="email">
</div>
<div class="form-control">
<label>Card</label>
<input type="tel" inputmode="numeric" pattern="[0-9\s]{13,19}"
autocomplete="cc-number" maxlength="19"
placeholder="Enter A Proxy Credit Card Number" id="ccn">
</div>
<button type="submit"; style="background-color:#e70064;
border-color:#3c3c3b; color:#3c3c3b">Submit</button>
</form>
</div>
CSS:
* {
box-sizing: border-box;
}
body {
background-color:fff;
display:flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.container {
background-color:#89c82e;
border: 5px solid #3c3c3b;
border-radius:20px;
margin-top:15px;
margin-bottom:15px;
width:300px;
max-width:100%;
}
.form{
padding: 30px 40px;
font-family:"calibri"
}
.form-control.success input {
border-color: #2ecc71;
}
.form-control.error input {
border-color:#e74c3c
}
JS:
const form = document.getElementById('form');
const name = document.getElementById('name');
const email = document.getElementById('email');
const ccn = document.getElementById('ccn');
form.addEventListener('submit', (e) => {
e.preventDefault();
checkInputs();
});
function checkInputs() {
// get the values from the inputs
const nameValue = name.value.trim();
const emailValue = email.value.trim();
const ccnValue = ccn.value.trim();
if(nameValue === "") {
// show error
// add error class
setErrorFor(name)
} else {
// add success class
setSuccessFor(name)
}
}
function setErrorFor(input) {
const formControl = input.parentElement; // .form-control
// add error class
formControl.classname = 'form-control error'
}
thanks so much!

By doing
.form-control.error input {
border-color:#e74c3c
}
You are setting any divs with a class name of form-control error that has an input inside to have a border color of red. But by default divs don't have a visible border. If you want the input field to turn red or green based on success/failure, set the inputs to have a border-color. You have the inputs already at the top of the js file, you can use those.
Also, in the setErrorFor function, it is .className, not .classname.

Related

My Form isn't working with my Javascript validation

I don't know if the problem is with my form or my javascript but the validation isn't working and I'm not getting any errors in the console. Can anyone check and see the form is working or the problem is with the javascript
const formSection = document.getElementById('davididhere');
const mailInput = document.getElementById('email');
const messageError = document.getElementById('error-messages');
formSection.addEventListener('submit', (e) => {
if (mailInput.value === mailInput.value.toLowerCase()) {
messageError.textContent = '';
} else {
e.preventDefault();
messageError.textContent = '*email must be in lower case <br> * form not sent';
}
})
<section id="contactpage" class="form-section">
<div class="form-container">
<form action="https://formspree.io/f/myyvzkag" method="post" id="davididhere">
<ul class="form-info">
<li>
<input type="text" maxlength="30" name="user_name" class="name-text-box" id="full-name" placeholder="Full Name" required="" />
</li>
<li>
<input type="email" name="user_email" class="name-last-text-box" id="email" placeholder="Email Address" required="" />
</li>
<li>
<textarea id="text-box" name="message" maxlength="500" class="enter-form" cols="30" rows="10" placeholder="Enter text here" required=""></textarea>
</li>
</ul>
<input type="submit" value="Get in touch" class="send-btn" />
<small id="error-messages"></small>
</form>
my css
#media screen and (min-width: 768px) {
.greet {
background: url(desktop2.svg) no-repeat 100% 0%;
}
.grid-containers {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.picture-box {
background: url(planeleft.svg) no-repeat 0% 20%,
url(planeright.svg) no-repeat 100% 100%;
}
.send-btn {
display: none;
}
the .send-btn is the problem when it doesn't display in the desktop version it stops working with my function. So I need to figure out how to use media queries to work both breakpoints.
Code snipped is working here. Now the question is do you expect some kind of an error in the console since you stated that you are not receiving anything there. You can throw an error in addition to already defined textContent.
const formSection = document.getElementById('davididhere');
const mailInput = document.getElementById('email');
const messageError = document.getElementById('error-messages');
formSection.addEventListener('submit', (e) => {
if (mailInput.value === mailInput.value.toLowerCase()) {
messageError.textContent = '';
} else {
e.preventDefault();
messageError.textContent = '*email must be in lower case <br> * form not sent';
throw new Error('Email must be in lower case!');
}
})

How do I make my javascript code for adding a new class to HTML more responsive?

<div class="control">
<input
type="email"
id="email"
class="email-address"
onblur="getValEmail()"
/>
<label for="email">Email</label>
</div>
<div class="control box">
<textarea id="message" onblur="getValMsg()"></textarea>
<label for="message">message</label>
</div>
function getValEmail() {
const valEmail = document.getElementById("email");
valEmail.addEventListener("blur", function () {
if (valEmail.value) valEmail.parentElement.classList.add("filled");
else valEmail.parentElement.classList.remove("filled");
});
}
function getValMsg() {
const valMsg = document.getElementById("message");
valMsg.addEventListener("blur", function () {
if (valMsg.value) valMsg.parentElement.classList.add("filled");
else valMsg.parentElement.classList.remove("filled");
});
}
.filled label,
input:focus + label,
textarea:focus + label {
top: 0;
font-size: 1.2rem;
}
These are HTML, Javascript and CSS codes in order.
What I'm trying to achieve here is that once user writes email address/message, labels that are inside of input/textarea go up. So, when input/textarea are filled up, labels should disappear to the top. It does its job but not responsively. "filled" class is added after a couple of more clicks happen, which means that labels only go up to the top after I click the box again.
Result looks like this.
This is only achieved after a few more clicks in the box.
You don't need js here at all. The :placeholder-shown pseudo-class will do what you actually need to achieve (note the non-empty placeholder attrs required for chrome):
.control {
position: relative;
margin-top: 20px;
}
input+label,
textarea+label {
position: absolute;
left: 0;
top: 0;
transition: 300ms;
}
input:focus+label,
input:not(:placeholder-shown)+label,
textarea:focus+label,
textarea:not(:placeholder-shown)+label {
top: -20px;
}
<div class="control">
<input type="email" id="email" class="email-address" placeholder=" " />
<label for="email">Email</label>
</div>
<div class="control box">
<textarea id="message" placeholder=" "></textarea>
<label for="message">message</label>
</div>
Here's a codepen.
In your css use:
transform:translateY(-2em)
change accordingly to your adjustment.

Javascript & HTML unit converter - how to use one input field as constant

I am trying to convert a Python script into an HTML/Javascript web based converter. The script is very simple and I followed the steps at https://www.w3schools.com/howto/howto_js_length_converter.asp, which work great, if all fields are dynamic. In my case, I need one variable to not change. On an example: user provides the "AssayWeight" value and one of the following: PPM or Grav. After that, scripts calculates the other value from PPM/Grav that the user didn't provide. Here's the code I have so far:
<script>
function ppmtoGravConverter(source,valNum) {
valNum = parseFloat(valNum);
var inputPPMtoGrav = document.getElementById("inputPPMtoGrav");
var inputAssayWeight = document.getElementById("inputAssayWeight");
var inputGravtoPPM = document.getElementById("inputGravtoPPM");
if (source=="inputPPMtoGrav") {
inputGravtoPPM.value=(valNum*inputAssayWeight/1000).toFixed(4);
}
if (source=="inputGravtoPPM") {
inputPPMtoGrav.value=(valNum*1000/inputAssayWeight).toFixed(4);
}
}
</script>
and html from w3schools:
<label>Assay Weight</label>
<input id="inputAssayWeight" type="number" placeholder="Assay Weight" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">
<br><br>
<label>PPM</label>
<input id="inputPPMtoGrav" type="number" placeholder="PPM" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">
<label>Grav (mg)</label>
<input id="inputGravtoPPM" type="number" placeholder="Grav (mg)" oninput="ppmtoGravConverter(this.id,this.value)" onchange="ppmtoGravConverter(this.id,this.value)">
Please let me know what am I missing. This is my 2nd day looking at Javascript. Thanks!
The issue is that in your formula, you are using inputAssayWeight instead of actually taking its value and using it. Replace those two if conditions with
if (source=="inputPPMtoGrav") {
inputGravtoPPM.value=(valNum*parseFloat(inputAssayWeight.value)/1000).toFixed(4);
}
if (source=="inputGravtoPPM") {
inputPPMtoGrav.value=(valNum*1000/parseFloat(inputAssayWeight.value)).toFixed(4);
}
That should fix your issue.
Wrap everything in a <form> tag and give it an #id.
<form id='main'><!-- EVERYTHING --></form>
Bind "input" event to the <form> and call an event handler (i.e. a function to handle a triggered event). Refer to: JavaScript Event Handling
document.forms.main.oninput = inputHandler;
Define function inputHandler() -- remember to pass the Event Object
function inputHandler(event) {...
Define all variables -- refer to: Obtaining References to Forms and Form Elements in JavaScript
// Collect all form controls into a NodeList
const field = this.elements;
// Find the element user interacted with
const input = event.target;
// Reference any form control by #id or [name] attribute by prefixing it with `field`
const aW = field.assayWeight;
// Assign a variable to form control values and convert them into a real Number
let AWT = parseFloat(aW.value);
Delegate "input" event by using if/else flow control statements. By explicitly allowing specific elements to react to an event and implicitly preventing other elements by simple omission is an important part of a programming paradigm called Event Delegation.
if (input.matches('#assayWeight')) {...
The HTML/CSS layout and styling features a toggling system in which it allows the user to enter "assay weight" and either "PPM" or "Grav". Hover over the titles and then click one and then the other to see the toggling. Refer to: Exposing Form Fields Via Checked Radio Buttons
[name=conv],
.mask {
display: none
}
[name=conv]:checked + fieldset .mask {
display: inline-block;
}
Demo
document.forms.convPpmG.oninput = convert;
function convert(event) {
const field = this.elements;
const input = event.target;
const awt = field.aWt;
const ppm = field.pPM;
const grv = field.grv;
const gtp = field.gToP;
const ptg = field.pToG;
let AWT = parseFloat(awt.value);
let PPMin = parseFloat(ppm.value);
let GRVin = parseFloat(grv.value);
if (input.matches('#aWt')) {
// log(AWT, "Assay Weight");
}
if (input.matches('#pPM')) {
// log(PPMin, "PPM Input");
let GRVout = PPMin * AWT / 1000;
// log(GRVout, "Grav Output");
ptg.value = GRVout.toFixed(4);
}
if (input.matches('#grv')) {
// log(GRVin, "Grav Input");
let PPMout = GRVin * 1000 / AWT;
// log(PPMout, "PPM Output");
gtp.value = PPMout.toFixed(4);
}
}
// A utility logger - not required
const log = (data, key = 'Field') => console.log(JSON.stringify(key + ': ' + data));
root,
body {
font: 400 3vw/1.5 Consolas, monospace;
}
fieldset fieldset {
min-height: 20vh;
}
input,
output {
width: 10ch;
margin-right: 5px;
margin-bottom: 8px;
font: inherit;
text-align: right;
}
#aWt {
display: inline-block;
}
[type=reset] {
text-align: center;
}
.switch {
padding: 3px 5px;
}
[type=reset]:hover,
.switch:hover {
color: tomato;
background: rgba(56, 87, 199, 0.4);
cursor: pointer;
}
[name=conv],
.mask {
display: none
}
[name=conv]:checked+fieldset .mask {
display: inline-block;
}
<form id='convPpmG'>
<fieldset>
<legend>PPM / Grav Convertor</legend>
<label>Assay Weight</label>
<input id="aWt" type="number" min='0' value="0">
<input type='reset'>
<br>
<input id='ppmToGrav' name='conv' type='radio'>
<fieldset>
<legend>
<label for='ppmToGrav' class='switch'>PPM to Grav</label>
</legend>
<label class='mask'>
PPM: <input id="pPM" type="number" min='0' value="0">
to Grav: <output id='pToG'>0</output> mg
</label>
</fieldset>
<hr>
<input id='gravToPPM' name='conv' type='radio'>
<fieldset>
<legend>
<label for='gravToPPM' class='switch'>Grav to PPM</label>
</legend>
<label class='mask'>
Grav: <input id="grv" type="number" min='0' value="0">
mg to PPM: <output id='gToP'>0</output>
</label>
</fieldset>
</fieldset>
</form>

How to prevent css from coloring an element

I'm making a sign up form, and when the password & confirm password match, the sign up button turns green on hover, but when you hover over the button when it's green and delete a number from the password field (so the password & confirm don't match) and you move away the mouse the button remains green instead of changing back to it's original color.
Button is green when passwords match
Button remains green when passwords don't match
Codepen: https://codepen.io/makeyka/pen/oVQPOV
HTML:
<form>
<p class="font"><span id="movePassword">Password</span></p>
<input id="password" type="password" name="password" placeholder="Password.." onfocus="this.placeholder=''" onblur="this.placeholder='Password..'" required>
<p class="font"><span id="movePassword">Confirm Password</span></p>
<input id="confirm_password" type="password" name="password" placeholder="Confirm.." onfocus="this.placeholder=''" onblur="this.placeholder='Confirm..'" onkeyup="check();" required><span id="msg"></span>
<br><br>
<input type="submit" name="submit" value="SIGN UP" id="submit">
</form>
CSS:
#msg {
left: 3%;
font-size: 1.5em;
font-weight: bold;
position: relative;
}
#submit {
position: relative;
left: 3%;
width: 120px;
color: #4e5463;
background-color: #e8ecf7;
cursor: pointer;
}
JS:
var check = function() {
if (document.getElementById("password").value == document.getElementById("confirm_password").value) {
document.getElementById("msg").style.color = "#009FFD"; // Green
document.getElementById("msg").innerHTML = "&#10004"; // Sign
document.getElementById("submit").disabled = false; // Able to login (passwords match)
$("#submit").mouseenter(function() {
$(this).css("background", "#009FFD").css("borderRadius", "10px").css("color", "#423d3d"); // Green button background
}).mouseleave(function() {
$(this).css("background", "#e8ecf7").css("borderRadius", "0px").css("color", "#4e5463"); // Button default background color
});
} else {
document.getElementById("msg").style.color = "red";
document.getElementById("msg").innerHTML = "&#9888"; // Sign
document.getElementById("submit").disabled = true; // Unable to login (passwords do not match)
}
}
This is happening because mouseenter and mouseleave events don't work on disabled elements. When the passwords do not match, you disable the submit button, which means mouseleave never gets fired and the styles are never returned to normal.
You can fix this by using the css enabled and hover properties instead of jquery's mouseenter and mouseleave.
In your css, add this rule:
#submit:enabled:hover {
background-color: #009FFD;
border-radius: 10px;
color: 423d3d;
}
And in your javascript, remove your event listeners:
var check = function() {
if (document.getElementById("password").value == document.getElementById("confirm_password").value) {
document.getElementById("msg").style.color = "#009FFD"; // Green
document.getElementById("msg").innerHTML = "&#10004"; // Sign
document.getElementById("submit").disabled = false; // Able to login (passwords match)
} else {
document.getElementById("msg").style.color = "red";
document.getElementById("msg").innerHTML = "&#9888"; // Sign
document.getElementById("submit").disabled = true; // Unable to login (passwords do not match)
}
}
Codepen
Benjamin's description about the mouseenter and mouseleave events are right on, and his use of the :hover pseudo-class is indeed the way to handle it, but I like to keep the styles out of the javascript too; instead of manipulating the .style on an element, I prefer to set classes describing the state of things, then use CSS.
You can do this with almost all CSS and just the tiniest bit of javascript.
Below, all I do is toggle the classes valid and invalid on the <form> element, and enable/disable the submit button. Everything else is done with styles applied based on whether the form is .valid or .invalid
// Get the elements we're going to use just once.
let password = document.getElementById('password');
let confirm = document.getElementById('confirm_password');
let submit = document.getElementById('submit');
let form = password.parentElement;
let check = function() {
if (password.value === confirm.value) {
form.classList.remove('invalid');
form.classList.add('valid');
submit.disabled = false;
}
else {
form.classList.remove('valid');
form.classList.add('invalid');
submit.disabled = true;
}
}
#msg {
left: 3%;
font-size: 1.5em;
font-weight: bold;
position: relative;
}
#submit {
position: relative;
left: 3%;
width: 120px;
color: #4e5463;
background-color: #e8ecf7;
cursor: pointer;
}
form.valid #msg:before {
content: '\2714';
color: #009FFD;
}
form.invalid #msg:before {
content: '\0026A0';
color: red;
}
form.valid #submit:hover {
background-color: #009FFD;
color: #423d3d;
border-radius: 10px;
}
<form class=""> <!-- form starts as neither valid or invalid -->
<p class="font">
<span id="movePassword">Password</span>
</p>
<input id="password" type="password" name="password"
placeholder="Password.." required>
<p class="font">
<span id="movePassword">Confirm Password</span>
</p>
<input id="confirm_password" type="password" name="password"
placeholder="Confirm.." onkeyup="check();" required>
<span id="msg"></span>
<br><br>
<input type="submit" name="submit"
value="SIGN UP" id="submit">
</form>
The <p class="font"> prompts really should use <label for="password"> -- that's what label is for -- then style them with CSS, and class="font" is not very descriptive; classes should describe the state of something, or what it is, not how it looks, so if you're not using <label> it might be <p class="label">
One way to solve this is to run the check() function again on keyup:
<input id="password" onkeyup="check()" type="password" name="password" placeholder="Password.." onfocus="this.placeholder=''" onblur="this.placeholder='Password..'" required>

JQuery addClass working in a very odd manner

I have a form with 3 inputs: 2 text inputs for a Username and E-mail and a third password input for, you guessed it, a password.
I'm validating these input fields in JQuery and when an input is either empty or doesn't match it's format, it adds a class to the input with a red border. The code goes as follows:
if ($("input#username").val().length < 6) {
$("input#username").addClass('input-error');
next_step = false;
} else if (!isEmail($("#email").val())) {
$("#email").addClass('input-error');
next_step = false;
} else if (!isPassword($("#pwd").val())) {
$("#pwd").addClass('input-error');
next_step = false;
}
else {
$(this).removeClass('input-error');
next_step = true;
}
It works perfectly with both Username and E-mail fields, and it also works if the Password field is empty, but even though it validates perfectly, the addClass() doesn't work if the Password doesn't meet it's requirements (At least one Uppercase letter and one number).
This is what the browser console shows:
As you can see, it kind of adds the class, but then not really.
What is happening? If you need the HTML code and/or the CSS code, tell me!
Thanks for your attention!
EDIT
Here is the HTML and CSS as requested:
<fieldset>
<div class="form-bottom">
<img src="img/gbsnlogo.svg" alt="GBSN Research" name="GBSN Research" width="50%" class="signupLogo" />
<br>
<br>
<br>
<div class="form-group">
<label for="username"><h1>USERNAME:</h1></label>
<input type="text" class="form-control" id="username" placeholder="Enter username..." name="username">
</div>
<div class="form-group">
<label for="email"><h1>E-MAIL:</h1></label>
<input type="text" class="form-control" id="email" placeholder="Enter e-mail..." name="email">
</div>
<div class="form-group">
<label for="pwd"><h1>PASSWORD:</h1></label>
<input type="password" class="form-control" id="pwd" placeholder="Enter password..." name="pwd">
</div>
<div class="text-center">
<button type="button" class="btn-next btn-nav"><h1>NEXT</h1></button>
</div>
</div>
</fieldset>
and the CSS:
.form-control {
height: 40px;
border: 2px solid black;
border-radius: 0;
font-size: 14px;
}
.form-control:focus {
border: 2px solid black;
box-shadow: 0;
}
.input-error {
border-color: #FF2859;
}
This is working for me.
Please comment what is still not working if you have this kind of setup?
function isEmail(email) { // dummy example
return email.indexOf("#")>1;
}
function isPassword(passwd) { // dummy example
return passwd.indexOf("x")>=0; // must contain x
}
$(function() {
$(".btn-next").on("click", function() {
$(".form-group input").removeClass('input-error');
var next_step = true,
user = $("#username").val(),
email = $("#email").val(),
pwd=$("#pwd").val();
if (user.length < 6) {
$("#username").addClass('input-error');
next_step = false;
} else if (!isEmail(email)) {
$("#email").addClass('input-error');
next_step = false;
} else if (!isPassword(pwd)) {
$("#pwd").addClass('input-error');
next_step = false;
}
console.log(next_step);
});
});
.form-control {
height: 40px;
border: 2px solid black;
border-radius: 0;
font-size: 14px;
}
.form-control:focus {
border: 2px solid black;
box-shadow: 0;
}
.input-error {
border-color: #FF2859;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<fieldset>
<div class="form-bottom">
<img src="img/gbsnlogo.svg" alt="GBSN Research" name="GBSN Research" width="50%" class="signupLogo" />
<br>
<br>
<br>
<div class="form-group">
<label for="username"><h1>USERNAME:</h1></label>
<input type="text" class="form-control" id="username" placeholder="Enter username..." name="username">
</div>
<div class="form-group">
<label for="email"><h1>E-MAIL:</h1></label>
<input type="text" class="form-control" id="email" placeholder="Enter e-mail..." name="email">
</div>
<div class="form-group">
<label for="pwd"><h1>PASSWORD:</h1></label>
<input type="text" class="form-control" id="pwd" placeholder="Enter password..." name="pwd">
</div>
<div class="text-center">
<button type="button" class="btn-next btn-nav"><h1>NEXT</h1></button>
</div>
</div>
</fieldset>
From what I see from the image you posted
I can only speculate this is what happened.
The line [input#pwd.form-control.input-error] was evaluated immediately when it got printed to the console. So that mean at that time, the dom does have the class input error in it. However, when you expand it, the dom got re-evaluated again. And at that time, the dom's class input-error got removed, so you don't see it anymore. I was able to prove this by running $('#pwd').addClass('input-error') and $('#pwd').removeClass('input-error') in that order, image below
Based on that, I suspect you have another logic in the code that remove the class shortly after you have added the class to the dom, highly possibly $(this).removeClass('input-error');.

Categories

Resources