I am writing a toggle in pure JavaScript.
There are 2 input fields, 1 is hidden and the other is visible. When we click on the first 1, the second input should appear and when both of the input fields are visible and one of the input fields is clicked then that input field should display:block and the other input field should display:none. Also, the latest clicked input element should remain on top and the other one below it. (es6 would be also good)
if anyone knows please check ?
code
<form action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww" placeholder="Type "></form>
<form action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww1" placeholder="Type "></form>
body{
background:#873e66;
}
.input-bg{
background:white;
border:none;
color:black;
height:50px;
text-indent:15px;
width:500px;
border-radius:26px;
outline:none;
}
.neww1{
margin-top:5px;
}
::-webkit-input-placeholder {
color: black;
}
::-moz-placeholder {
color: black;
}
:-ms-input-placeholder {
color: black;
}
.neww1{
display:none;
}
function toggleClass(element, className){
if (!element || !className){
return;
}
var classString = element.className, nameIndex = classString.indexOf(className);
if (nameIndex == -1) {
classString += ' ' + className;
}
else {
classString = classString.substr(0, nameIndex) + classString.substr(nameIndex+className.length);
}
element.className = classString;
}
Thanks!
you can proceed like :
const inputs = [].slice.call(document.getElementsByClassName("input-bg"));
inputs.forEach((input) => {
console.log()
input.addEventListener("click", (event) => {
const somehidden = inputs.filter((_input) => {
return _input.getAttribute("class").match(/neww1/i);
})
if (somehidden.length > 0) {
somehidden[0].classList.remove("neww1");
} else {
inputs.forEach((i) => {
if (i !== event.target)
i.classList.add("neww1");
});
}
});
});
body {
background: #873e66;
}
.grid {
display: grid;
grid-template-areas: "up" "down";
}
form:focus-within {
grid-area: up;
}
.input-bg {
background: white;
border: none;
color: black;
height: 50px;
text-indent: 15px;
width: 500px;
border-radius: 26px;
outline: none;
}
.neww1 {
margin-top: 5px;
}
::-webkit-input-placeholder {
color: black;
}
::-moz-placeholder {
color: black;
}
:-ms-input-placeholder {
color: black;
}
.neww1 {
display: none;
}
<div class="grid">
<form action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww" placeholder="Type "></form>
<form action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww1" placeholder="Type2 "></form>
</div>
Although your requirement is not very clear but my answer might be of some help
Let's say we have two input fields like this:
<div class="input-container">
<input type="password" placeholder="Input 1" class="myInput first" />
<input type="password" placeholder="Input 2" class="myInput second hidden" />
</div>
CSS can be like:
.input-container {
display: flex;
flex-direction: column;
}
.myInput {
margin: 10px;
padding: 5px
}
.first {
order: 1;
}
.second {
order: 2;
}
.hidden {
display: none;
}
Now the toggle function (JS):
var allInputs = document.querySelectorAll('.myInput');
allInputs.forEach(function(node) {
node.addEventListener("click", function(){
var allHiddenInputs = document.querySelectorAll('.hidden');
if(allHiddenInputs.length === 0) {
allInputs.forEach(function(input) {
input.classList.add("hidden");
input.classList.add("second");
input.classList.remove("first");
});
node.classList.remove("hidden");
node.classList.remove("second");
node.classList.add("first");
} else {
allHiddenInputs.forEach(function(input) {
input.classList.remove("hidden");
});
}
});
});
https://codepen.io/tusharshukla/pen/rrqvQz?editors=1010
Something like this could help you. I'm directly changing the CSS but you can also toggle classes using the classList.
<html>
<body>
<form action="#" class="navbar-top" role="search" autocomplete="off">
<input name="p" id="input1" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww"
placeholder="Input One ">
</form>
<form action="#" class="navbar-top" role="search" autocomplete="off">
<input name="p" id="input2" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww1"
placeholder="Input Two ">
</form>
<script>
(function () {
const inputOne = document.getElementById('input1');
const inputTwo = document.getElementById('input2');
const handleClick = i => (i === inputOne ? inputTwo : inputOne)
.style.display = 'none';
const handleBlur = i => {
if (i === inputOne) {
inputTwo.style.display = 'block';
inputOne.style.display = 'none';
} else {
inputTwo.style.display = 'none';
inputOne.style.display = 'block';
}
}
[inputOne, inputTwo].forEach((i) => {
i.addEventListener('click', () => handleClick(i))
i.addEventListener('focusout', () => handleBlur(i))
});
})();
</script>
</body>
</html>
You have the classList attribute with your HTML Element.
So first you need the element reference, you can use your constructor and private variables and set the private variable with document.getElementByClassName according to initial state of your page, or set an ID. Let's take for example an ID :
<form onclick="toggleClass()" id="password1" action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww" placeholder="Type "></form>
<form onclick="toggleClass()" id="password2" action="#" class="navbar-top" role="search" autocomplete="off"><input name="p" data-hit="Type" type="text" autocomplete="new-password" value="" data-open="false" class="input-bg neww1" placeholder="Type "></form>
Then just find the reference
const password1 = document.getElementById("password1");
const password2 = document.getElementById("password2");
and after that, you can write this function :
function toggleClass() {
const password1 = document.getElementById("password1");
const password2 = document.getElementById("password2");
if (password1.classList.contains('hidden')){
password1.classList.remove('hidden');
password2.classList.add('hidden');
}
else {
password2.classList.remove('hidden');
password1.classList.add('hidden');
}
}
.neww1 {
background-color : red;
}
.neww {
background-color : green;
}
.hidden {
display:none;
}
input {
margin:5px;
}
Related
I am creating a questionnaire and to be inserted in database. I'm doing Multiple Choices type. I am in a part where choosing a choices for a correct answer.
I wan't to change the border color of choices inputs if the value is equal to correct input and make other border color black if it's not equal to correct input,
but what happening to my code is, the border style of other choices that are not equal to the correct input stays greens, also my code is not so good i think there is a better way to make it much more clean and optimize.
This is what i have tried so far, but I'm not happy about it. I'm sure there's much better approach for this kind of code.
const inp = document.querySelectorAll("#choices input");
const inpCorrect = document.querySelector("#correct");
inp.forEach(x => {
x.addEventListener("click", function () {
inpCorrect.value = this.value;
})
x.addEventListener("keyup", function () {
inpCorrect.value = this.value;
this.value == inpCorrect.value ? this.style.border = '2px solid green' : this.style.border = '2px solid black';
})
})
#choices {
display: flex;
flex-direction: column;
width: 50%;
gap: 20px;
}
input {
outline: none;
}
<div id="choices">
<div><label for="correct">Choices A:</label>
<input type="text" id="choicesA"></div>
<div><label for="correct">Choices B:</label>
<input type="text" id="choicesB"></div>
<div><label for="correct">Choices C:</label>
<input type="text" id="choicesC"></div>
<div><label for="correct">Choices D:</label>
<input type="text" id="choicesD"></div>
</div>
<br>
<br>
<label for="correct">Correct Answer:</label>
<input type="text" id="correct">
It's not quite clear what you mean. Typically multiple choice questions are answered by selecting one of the given answers, not by typing an answer.
Here's a snippet for a multiple choice question, maybe that helps? It uses data-attributes to retain the values, event delegation for the handler and some css for the styling.
document.addEventListener(`click`, handle);
function handle(evt) {
if (evt.target.classList.contains(`choice`)) {
document.querySelectorAll(`.choice`).forEach(choice =>
choice.classList.remove(`correct`, `incorrect`));
const valueElem = evt.target.closest(`[data-value]`);
if (valueElem.dataset.value === document.querySelector(`#correct`).value) {
return valueElem.classList.add(`correct`);
}
return valueElem.classList.add(`incorrect`);
}
}
#choices {
display: flex;
flex-direction: column;
max-width: 25vw;
gap: 5;
}
[data-question]:before {
content: attr(data-question);
font-size: 1.3rem;
font-weight: bold;
margin-bottom: 0.7rem;
width: 80vw;
}
.choice {
cursor: pointer;
border: 2px solid transparent;
padding: 3px;
}
.choice.correct {
border: 2px solid green;
}
.choice.incorrect {
border: 2px solid red;
}
<div id="choices" data-question="How many items do we find in a dozen?">
<div class="choice" data-value="144">A. 144</span></div>
<div class="choice" data-value="12">B. 12</span></div>
<div class="choice" data-value="24">C. 24</span></div>
<div class="choice" data-value="33">D. 33</span></div>
<input type="hidden" id="correct" value="12">
</div>
After your comments: loop the relevant input elements, compare them to the given correct value and colorize the border if the input value matches the correct value.
Play with this code #Stackblitz
document.addEventListener(`keyup`, handle);
function markCorrect(correctAnswer) {
const correct = value => value !== `` && value === correctAnswer;
document.querySelectorAll(`[data-answer]`)
.forEach(inp => correct(inp.value.trim()) ?
inp.classList.add(`correct`) :
inp.classList.remove(`correct`));
}
function handle(evt) {
if (evt.target.closest(`.choiceEdit`)) {
return markCorrect(document.querySelector(`#correctAnswer`).value);
}
}
.inp {
margin: 0.5rem auto;
}
.choice {
cursor: pointer;
border: 2px solid transparent;
padding: 3px;
}
input {
outline: none;
}
input.correct {
border: 2px solid green;
}
<div id="choices">
<div class="inp">
<input type="text" id="question" class="nocolor" value="How many is a dozen?"> The question
</div>
<div class="inp choiceEdit">
<input type="text" id="correctAnswer" value="12"> The correct answer
</div>
<div class="inp choiceEdit">
<input type="text" data-answer="a"> Answer A
</div>
<div class="inp choiceEdit">
<input type="text" data-answer="b"> Answer B
</div>
<div class="inp choiceEdit">
<input type="text" data-answer="c"> Answer C
</div>
<div class="inp choiceEdit">
<input type="text" data-answer="d"> Answer D
</div>
</div>
There are several issues with this code.
First: by assigning inpCorrect.value = this.value; you are ensuring that the value of the "correct" input will be changed every time any input receives a keyup or click event. If you are always changing the "correct" value to match the current value, then the current value will always seem correct. I am not really sure what you are going for with setting this, so I have removed those lines.
Second: It's not really a good idea to do assignment in a ternary (x = something ? foo : bar) conditional expression. Expressions like these should evaluate to a result, and not execute side effects.
Is this closer to the behavior you're looking for?
const inp = document.querySelectorAll("#choices input");
const inpCorrect = document.querySelector("#correct");
inp.forEach(x => {
x.addEventListener("keyup", function () {
if (this.value == inpCorrect.value) {
this.style.border = '2px solid green';
} else {
this.style.border = '2px solid black';
}
})
})
#choices {
display: flex;
flex-direction: column;
width: 50%;
gap: 20px;
}
input {
outline: none;
}
<div id="choices">
<div><label for="correct">Choices A:</label>
<input type="text" id="choicesA"></div>
<div><label for="correct">Choices B:</label>
<input type="text" id="choicesB"></div>
<div><label for="correct">Choices C:</label>
<input type="text" id="choicesC"></div>
<div><label for="correct">Choices D:</label>
<input type="text" id="choicesD"></div>
</div>
<br>
<br>
<label for="correct">Correct Answer:</label>
<input type="text" id="correct">
This is with regard to an ongoing question asked previously. I am trying to make a contact form to work using HTML, CSS and JavaScript. All my conditions seem to be working fine. The issue here is that whenever I fail to enter a particular field, and later re-enter it, the error message is still being displayed. Also, I want the user to be redirected to another HTML page once he clicks on Submit and once all conditions are satisfied. I would like some guidance on the same. Herewith attaching the code for reference.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register with us</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/styles.css">
</head>
<body style="position: relative;">
<div class="container"> <br>
<h1 class="text-center">Register with Us!</h1>
<form>
<div class="form-group">
<label for="fname" id="firstname">First name: </label>
<input type="text" class="form-control" id="fname" placeholder="Enter your first name">
<small id="firstnameerror" class="form-text"></small>
</div>
<div class="form-group">
<label for="lname" id="lastname">Last name: </label>
<input type="text" class="form-control" id="lname" placeholder="Enter your last name">
<small id="lastnameerror" class="form-text"></small>
</div>
<div class="form-group">
<label for="emailid" id="emailaddress">Email address:</label>
<input type="email" class="form-control" id="emailid" aria-describedby="emailHelp"
placeholder="Enter email">
<small id="emailerror" class="form-text"></small>
</div>
<div class="form-group">
<label for="pass1" id="password1">Password: </label>
<input type="password" class="form-control" id="pass1" placeholder="Enter a password">
<small id="passerror" class="form-text"></small>
</div>
<div class="form-group">
<label for="confirmpass" id="password2">Confirm Password: </label>
<input type="password" class="form-control" id="confirmpass" placeholder="Re-enter password">
<small id="passerror2" class="form-text"></small>
</div>
<div class="form-group">
<label for="phno" id="ctno">Contact number : </label>
<input type="number" class="form-control" id="phno" placeholder="Enter your number here">
<small id="phoneerror" class="form-text"></small>
</div>
<button type="submit">Submit</button>
</form>
</div>
<script src="/js/vaildate.js"></script>
</body>
</html>
#firstnameerror,
#lastnameerror,
#emailerror,
#passerror,
#phoneerror{
color: tomato;
font-size: 1.1em;
margin-left: 10%;
margin-top: 2.5%;
}
#firstname,#lastname,#emailaddress,#password1,#password2,#ctno{
padding: 0.7em;
font-size: 1.3em;
font-family: 'Noto Sans', sans-serif;
font-weight: 600;
text-align: center;
color: white;
margin-left: 9%;
}
#fname,#lname,#emailid,#pass1,#confirmpass,#phno{
margin: 0.3em 0.7em;
width: 80%;
font-family: 'Poppins', sans-serif;
margin-left: 10%;
background-color: black;
border: none;
padding: 1em;
border-radius: 2em;
color: white;
}
.container{
margin-top: 20vh;
background-image: linear-gradient(to right, rgb(46, 46, 46) , rgb(20, 20, 20));
border-radius: 5em;
}
.container h1{
color: white;
}
button{
margin-left: 10%;
margin-top: 2.5%;
font-size: 1.4em;
padding: 0.5em 1em;
font-family: 'Open Sans', sans-serif;
border-radius: 1.2em;
outline: none;
border: none;
background-color: teal;
color: white;
font-weight: bold;
}
const form = document.querySelector(".container");
const firstname = document.getElementById("fname");
const lastname = document.getElementById("lname");
const emailid = document.getElementById("emailid");
const password = document.getElementById("pass1");
const confirmpassword = document.getElementById("confirmpass");
const phoneno = document.getElementById("phno");
// Function to check if first name is entered properly
function checkfname(fname) {
let letters = /^[A-Z]+[a-z]+$/;
if (fname.match(letters)) {
document.getElementById("firstnameerror").innerHTML.style = "none";
return fname;
}
else {
document.getElementById("firstnameerror").innerHTML = "Please enter the details accurately";
return false;
}
}
// Function to check if first name is entered properly
function checklname(lname) {
let letter = /^[A-Z]+[a-z]+$/;
if (lname.match(letter)) {
document.getElementById("firstnameerror").innerHTML.style = "none";
return lname;
}
else {
document.getElementById("firstnameerror").innerHTML = "Please enter the details accurately";
return false;
}
}
//function to check if the password is entered properly
function passcheck(pass) {
var paswd = /^(?=.*[0-9])(?=.*[!##$%^&*])[a-zA-Z0-9!##$%^&*]{7,15}$/;
if (pass.match(paswd)) {
document.getElementById("passerror").innerHTML.style = "none";
return pass;
}
else {
document.getElementById("passerror").innerHTML = "Entered password does not meet the requirements";
return false;
}
}
function phonecheck(phval) {
var phonecheck = /\+?\d[\d -]{8,12}\d/;
if (phval.match(phonecheck)) {
document.getElementById("phoneerror").innerHTML.style = "none";
return phval;
}
else {
document.getElementById("phoneerror").innerHTML = "Please enter a valid phone number";
return false;
}
}
// Function to check if all parameters have been entered
function testfunc() {
if (firstname.value == "") {
document.getElementById("firstnameerror").innerHTML = "Please enter your first name";
}
else {
firstname.value = checkfname(firstname.value);
}
if (lastname.value == "") {
document.getElementById("lastnameerror").innerHTML = "Please enter your last name";
}
else {
lastname.value=checklname(lastname.value);
}
if (emailid.value == "") {
document.getElementById("emailerror").innerHTML = "Please enter your E-mail ID";
}
else {
document.getElementById("emailerror").innerHTML.style = "none";
}
if (password.value == "") {
document.getElementById("passerror").innerHTML = "Please enter a password";
}
else {
password.value=passcheck(password.value);
}
if (confirmpassword.value == "") {
document.getElementById("passerror2").innerHTML = "Enter the password again"
}
else if (confirmpassword.value == password.value) {
document.getElementById("passerror2").innerHTML.style = "none";
document.getElementById("passerror").innerHTML.style = "none";
}
else {
document.getElementById("passerror2").innerHTML = "Passwords do not match";
}
if (phoneno.value == "") {
document.getElementById("phoneerror").innerHTML = "Please enter your mobile number";
}
else {
phoneno.value = phonecheck(phoneno.value);
}
}
form.addEventListener("submit", function (e) {
e.preventDefault();
testfunc();
}
)
If I were you, I would add event listeners (on change) for each of the inputs. Then save the value of those inputs to variables and clear the error message of that particular input. This way makes the most sense to me from a user experience perspective.
As for the submit function's redirect, just use one of the ways W3Schools suggests:
// Simulate a mouse click:
window.location.href = "http://www.w3schools.com";
// Simulate an HTTP redirect:
window.location.replace("http://www.w3schools.com")
Also,
document.getElementById("firstnameerror").innerHTML.style = "none";
wont work. What you're looking for is probably either clearing the text:
document.getElementById("firstnameerror").innerHTML = "";
Or hiding the element itself:
document.getElementById("firstnameerror").style.display = "none";
.style = "none" won't work.
.style.display = "none" is probably what you want.
Also, you can probably do everything (or nearly everything) of what you're checking in Javascript via HTML form validation as well, e.g. required attribute.
function validate() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "") {
document.getElementById("message").innerHTML = "USERNAME CANNOT BE EMPTY";
document.getElementById("username").style.borderColor = "red";
return false;
}
if (password == "") {
document.getElementById("message").innerHTML = "PASSWORD CANNOT BE EMPTY";
document.getElementById("password").style.borderColor = "red";
return false;
}
}
#username:focus {
background-color: yellow;
border-color: green;
}
#password:focus {
background-color: yellow;
border-color: green;
}
#message {
color: red;
}
<form onsubmit=" return validate()">
LOGIN:-
<br>
<input id="username" type="text" name="username" placeholder="USERNAME">
<br>
<input id="password" type="password" name="password" placeholder="PASSWORD">
<br>
<input type="submit" value="SUBMIT">
<p id="message">
</form>
When i focus on the text fields, the background and border color changes to yellow and green respectively (through css).
If i click on submit without entering anything, the border color changes to red (through javascript).
But when i bring the focus on the text field again, the red border color does not go away, instead i get both green and red borders.
I want it to be green only. Can you also explain the reason for this behavior.
This is happening because you have updated the element style instead of CSS class property. Element style has the highest weight for CSS. Instead add an error class dynamically on error and remove it when the form field is valid.
As per the documentation, the order of style in decreasing order will be.
Inline style (inside an HTML element)
External and internal style sheets (in the head section)
Browser default
Here is a working example
function validate() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "") {
document.getElementById("message").innerHTML = "USERNAME CANNOT BE EMPTY";
document.getElementById("username").classList.add("invalidInput");
return false;
} else {
document.getElementById("username").classList.remove("invalidInput")
}
if (password == "") {
document.getElementById("message").innerHTML = "PASSWORD CANNOT BE EMPTY";
document.getElementById("password").classList.add("invalidInput")
return false;
} else {
document.getElementById("password").classList.remove("invalidInput")
}
}
#username:focus {
background-color: yellow;
border-color: green;
}
#password:focus {
background-color: yellow;
border-color: green;
}
.invalidInput {
border-color: red;
}
#message {
color: red;
}
<form onsubmit=" return validate()">
LOGIN:-
<br />
<input id="username" type="text" name="username" placeholder="USERNAME" />
<br />
<input id="password" type="password" name="password" placeholder="PASSWORD" />
<br />
<input type="submit" value="SUBMIT" />
<p id="message"></p>
</form>
The problem is the colors have the same level of importance to css and therefore the code does not know which one to prioritize. So, to fix that, you have to make the green more important in the css code.
To do that change the focus css code to look like this.
#username:focus {
background-color: yellow !important;
border-color: green !important;
}
#password:focus {
background-color: yellow !important;
border-color: green !important;
}
#message {
color: red;
}
Hope this helps!
Instead adding color from javascript you can use required in input box and :invalid in CSS. Check the snippet
function validate() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "") {
document.getElementById("message").innerHTML = "USERNAME CANNOT BE EMPTY";
//document.getElementById("username").style.borderColor = "red";
return false;
}
if (password == "") {
document.getElementById("message").innerHTML = "PASSWORD CANNOT BE EMPTY";
//document.getElementById("password").style.borderColor = "red";
return false;
}
}
#username:focus{
background-color: yellow;
border-color: green;
}
#username:invalid{
background-color: none;
border-color: red;
}
#password:focus{
background-color: yellow;
border-color: green;
}
#password:invalid{
background-color: none;
border-color: red;
}
#message {
color: red;
}
<form onsubmit=" return validate()">
LOGIN:-
<br>
<input id="username" type="text" name="username" placeholder="USERNAME" required>
<br>
<input id="password" type="password" name="password" placeholder="PASSWORD" required>
<br>
<input type="submit" value="SUBMIT">
<p id="message">
</form>
You can simply revert the border color on keyup and create a new class error to overwrite border color to red
function retainColor(ele){
ele.style.borderColor = "inherit";
document.getElementById("message").innerHTML = "";
}
function validate() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "") {
document.getElementById("message").innerHTML = "USERNAME CANNOT BE EMPTY";
document.getElementById("username").classList.add("error");
return false;
}else{
document.getElementById("username").classList.remove("error");
}
if (password == "") {
document.getElementById("message").innerHTML = "PASSWORD CANNOT BE EMPTY";
document.getElementById("password").classList.add("error");
return false;
}else{
document.getElementById("password").classList.remove("error");
}
}
#username:focus {
background-color: yellow;
border-color: green;
}
#password:focus {
background-color: yellow;
border-color: green;
}
.error {
border-color: red;
}
.error {
border-color: red;
}
#message {
color: red;
}
<form onsubmit=" return validate()">
LOGIN:-
<br>
<input id="username" type="text" onkeyup="retainColor(this)" name="username" placeholder="USERNAME">
<br>
<input id="password" type="password" onkeyup="retainColor(this)" name="password" placeholder="PASSWORD">
<br>
<input type="submit" value="SUBMIT">
<p id="message">
</form>
You're setting the colors via JS, but never un-setting them, so essentially they're being set permanently.
One way to stop this behavior is to also add another function that catches the OnClick event of the text fields, and "reset" or unset the colors when they're get clicked inside of.
Have a look here for an idea on how to get started handling the OnClick event:
https://jsfiddle.net/warunamanjula/qy0hvmyq/1/
Because when you add color from javascript, or any property of css, it's added inline, so just write focus border-color !important.
Just add onfocus attribute
Javascript
function validate() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "") {
document.getElementById("message").innerHTML = "USERNAME CANNOT BE EMPTY";
document.getElementById("username").style.borderColor = "red";
return false;
}
if (password == "") {
document.getElementById("message").innerHTML = "PASSWORD CANNOT BE EMPTY";
document.getElementById("password").style.borderColor = "red";
return false;
}
}
function myfunction(var id){
document.getElementById(id).style.borderColor = "green";
document.getElementById(id).style.background-color= "yellow";
}
Html
<form onsubmit=" return validate()">
LOGIN:-
<br>
<input id="username" type="text" onfocus="myFunction('username')" name="username" placeholder="USERNAME">
<br>
<input id="password" type="password" onfocus="myFunction('password')" name="password" placeholder="PASSWORD">
<br>
<input type="submit" value="SUBMIT">
<p id="message">
</form>
I want to show a tooltip on ma text input when it's not valid
function check() {
var ok = true;
regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value)) {
ok = false;
}
return ok;
}
<div class="form-group">
<label for="lastName">Last name:</label>
<input type="text" class="form-control" id="lastName" placeholder="Put your last name" name="lastName" />
</div>
and I know how to put, a text in a div under, a input by document.getElementById("wronglastnamediv").innerHTML = "Put valid last name"
But I don't know how to put a tooltip on these text area when it's not valid..
You should edit the below code accordingly, also link the jquery 1.7 or above-
<script>
$('#lastName').on('keyup', function () {
$('.text-error').remove();
var ok=true;
regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value))
{
ok=false;
$(this).parent('.form-group').append("<span class='text-error'>Please enter a valida string.</span>");
}
return ok;
});
</script>
//CSS add your own CSS for tooltip style etc
<style type="text/css">
.form-group{
position:relative;
}
.text-error{
position:absolute;
right:0;
top:0px;
background:red;
color:white;
border-radius:5px;
padding:5px 3px;
}
</style>
Hopefully the code will work for you.
Pure Javascript
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.form-control{
position:relative;
width: 100%;
float: left;
}
.text-error{
position:absolute;
right:0;
top:0px;
background:red;
color:white;
border-radius:5px;
padding:5px 3px;
display: none;
}
.display_block{
display: block;
}
</style>
</head>
<body>
<div class="form-group">
<label for ="lastName">Last name:</label>
<input type = "text" class = "form-control" id = "lastName" onkeyup="check()" placeholder = "Put your last name" name = "lastName" />
<span class="text-error" id="error_lastname"></span>
</div>
<script type="text/javascript">
function check () {
var div = document.getElementById("error_lastname");
div.setAttribute('class', 'text-error');
var ok=true;
regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value))
{
ok=false;
div.setAttribute('class', 'text-error display_block');
div.innerHTML = "Please enter a valid string.";
console.log("XXXX");
}
return ok;
}
</script>
</body>
</html>
You can add tooltip for the input field like this. Use setAttribute('title', 'some tooltip') to set the tooltip and removeAttribute('title') to remove the tooltip from the input field.
I have added input-event listener to the input field that performs validation of the input value each time you type a character and based on the result of the validation it either adds or removes the tooltip.
If you type just one character and hover over the input field, you should see the tooltip. If you type a second character it disappears (note that you need to move mouse cursor outside of the input field and then back to actually see the tooltip).
function check() {
var ok = true;
const regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value)) {
ok = false;
}
return ok;
}
const inp = document.querySelector('input');
inp.addEventListener('input', event => {
if (!check(inp.value)) {
inp.setAttribute('title', 'incorrect value');
} else {
inp.removeAttribute('title');
}
});
<div class="form-group">
<label for ="lastName">Last name:</label>
<input type = "text" class = "form-control" id = "lastName" placeholder = "Put your last name" name = "lastName" />
</div>
If you need something more sophisticated and more 'visible' then you can use css combined with data attributes. The logic is the same as with the previous code. Based on the result of validation you either add a data attribute to the input field or remove it.
function check() {
var ok = true;
const regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value)) {
ok = false;
}
return ok;
}
const inp = document.querySelector('input');
inp.addEventListener('input', event => {
if (!check(inp.value)) {
inp.parentElement.dataset.tip = 'incorrect input value';
} else {
delete inp.parentElement.dataset.tip;
}
});
[data-tip] {
position:relative;
}
[data-tip]:before {
content:'';
display:none;
content:'';
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #1a1a1a;
position:absolute;
top:30px;
left:35px;
z-index:8;
font-size:0;
line-height:0;
width:0;
height:0;
}
[data-tip]:after {
display:none;
content:attr(data-tip);
position:absolute;
top:35px;
left:0px;
padding:5px 8px;
background:#1a1a1a;
color:#fff;
z-index:9;
font-size: 0.75em;
height:18px;
line-height:18px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
white-space:nowrap;
word-wrap:normal;
}
[data-tip]:hover:before,
[data-tip]:hover:after {
display:block;
}
<div class="form-group" >
<label for ="lastName">Last name:</label>
<input type = "text" class = "form-control" id = "lastName" placeholder = "Put your last name" name = "lastName" />
</div>
To add the tooltip on form submit instead of hover, you can use submit-event listener and execute the same code as before but you need to add event.preventDefault(); as well to prevent the form from submitting if the validation fails (and you need to change the css slightly).
When you click submit button now, you should see the tooltip if the input value is incorrect.
function check() {
var ok = true;
const regLast = /^[a-zA-Z]{2,20}$/;
if (!regLast.test(document.getElementById("lastName").value)) {
ok = false;
}
return ok;
}
const inp = document.querySelector('input');
const form = document.querySelector('form');
form.addEventListener('submit', event => {
if (!check(inp.value)) {
event.preventDefault();
inp.parentElement.dataset.tip = 'incorrect input value';
} else {
delete inp.parentElement.dataset.tip;
}
});
[data-tip] {
position:relative;
}
[data-tip]:before {
content:'';
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #1a1a1a;
position:absolute;
top:30px;
left:35px;
z-index:8;
font-size:0;
line-height:0;
width:0;
height:0;
}
[data-tip]:after {
content:attr(data-tip);
position:absolute;
top:35px;
left:0px;
padding:5px 8px;
background:#1a1a1a;
color:#fff;
z-index:9;
font-size: 0.75em;
height:18px;
line-height:18px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
white-space:nowrap;
word-wrap:normal;
}
[data-tip]:hover:before,
[data-tip]:hover:after {
display:block;
}
<form>
<div class="form-group" >
<label for ="lastName">Last name:</label>
<input type = "text" class = "form-control" id = "lastName" placeholder = "Put your last name" name = "lastName" />
</div>
<input type="submit" value="submit" />
</form>
You can simply use the HTML5 Form Validation (If you don't want a custom tooltip).
See the code snippet below:
<form>
<p>
<label for="firstName">First name: </label>
<input type="text" id="firstName" placeholder="Put your first name" pattern="[a-zA-Z]{2,20}" required />
</p>
<p>
<label for="lastName">Last name: </label>
<input type="text" id="lastName" placeholder="Put your last name" pattern="[a-zA-Z]{2,20}" required />
</p>
<input type="submit" Value="Submit" />
</form>
Also you can use setCustomValidity function when oninvalid event occurs to to change the default message of the required field.
Example:
<form>
<p>
<label for="firstName">First name: </label>
<input type="text" id="firstName" placeholder="Put your first name" pattern="[a-zA-Z]{2,20}" oninvalid="this.setCustomValidity('Please enter a valid Name')" required />
</p>
<p>
<label for="lastName">Last name: </label>
<input type="text" id="lastName" placeholder="Put your last name" pattern="[a-zA-Z]{2,20}" required />
</p>
<input type="submit" Value="Submit" />
</form>
I'm trying to show an error message in the span tags using jQuery. I can get the form fields to highlight in a red box and green box if input right but the text wont show up. I'm new to coding and been looking on the web for ideas and fixes, I know I'm missing something and it maybe simple but I'm racking my brains on it.
$(document).ready(function() {
// Name can't be blank
$('#name').on('input', function() {
var input = $(this);
var is_name = input.val();
if (is_name) {
input.removeClass("invalid").addClass("valid");
}
else {
input.removeClass("valid").addClass("invalid");
}
});
// Email must be an email
$('#email').on('input', function() {
var input = $(this);
var re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
var is_email = re.test(input.val());
if (is_email) {
input.removeClass("invalid").addClass("valid");
}
else {
input.removeClass("valid").addClass("invalid");
}
});
// Message can't be blank
$('#message').keyup(function(event) {
var input = $(this);
var message = $(this).val();
console.log(message);
if (message) {
input.removeClass("invalid").addClass("valid");
}
else {
input.removeClass("valid").addClass("invalid");
}
});
// After Form Submitted Validation
$("#contact_submit button").click(function(event) {
var form_data = $("#contact").serializeArray();
var error_free = true;
for (var input in form_data) {
var element = $("#contact_submit" + form_data[input]['name'], ['email'], ['message']);
var valid = element.hasClass("valid");
var error_element = $("span", element.parent());
if (!valid) {
error_element.removeClass("error").addClass("error_show");
error_free = false;
}
else {
error_element.removeClass("error_show").addClass("error");
}
}
if (!error_free) {
event.preventDefault();
}
else {
alert('No errors: Form will be submitted');
}
});
});
.error {
display: none;
margin-left: 10px;
}
.error_show {
color: red;
margin-left: 10px;
}
input.invalid,
textarea.invalid {
border: 2px solid red;
}
input.valid,
textarea.valid {
border: 2px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<section class="body">
<form id="contact" method="post" enctype="multipart/form-data" action="">
<h1 class="title">Contact</h1>
<div>
<label for="name">Your Fullname</label>
<input type="text" id="name" name="name" required placeholder="Your Name">
<span class="error error_show">This field is required</span>
</div>
<div>
<label for="email">Your Full Email</label>
<input name="email" type="email" id="email" required placeholder="Your Email">
<span class="error error_show">This field is required</span>
</div>
<div>
<label for="message">Message</label>
<textarea id="message" name="message" cols="20" rows="5" required placeholder="Message"></textarea>
<span class="error error_show">This field is required</span>
</div>
<div id="contact_submit">
<button type="submit"></button>
</div>
</form>
</section>
I think you might have made it more complicated than it needed to be. See if the below snippet doesn't work the way you expected.
$(document).ready(function() {
$('#name').on('input', function() {
var input = $(this);
var is_name = input.val();
if (is_name) {
input.removeClass("invalid").addClass("valid");
} else {
input.removeClass("valid").addClass("invalid");
}
});
$('#email').on('input', function() {
var input = $(this);
var re = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
var is_email = re.test(input.val());
if (is_email) {
input.removeClass("invalid").addClass("valid");
} else {
input.removeClass("valid").addClass("invalid");
}
});
$('#message').keyup(function(event) {
var input = $(this);
var message = $(this).val();
console.log(message);
if (message) {
input.removeClass("invalid").addClass("valid");
} else {
input.removeClass("valid").addClass("invalid");
}
});
$("#contact_submit #submit_button").click(function(event) {
$("#name_error").hide();
$("#email_error").hide();
$("#message_error").hide();
var success = true;
if (!$("#name").hasClass("valid")) {
success = false;
$("#name_error").show();
}
if (!$("#email").hasClass("valid")) {
success = false;
$("#email_error").show();
}
if (!$("#message").hasClass("valid")) {
success = false;
$("#message_error").show();
}
if (success === false) {
event.preventDefault();
}
else {
alert('No errors: Form will be submitted');
}
});
});
.error {
display: none;
margin-left: 10px;
}
.error_show {
color: red;
margin-left: 10px;
display: none;
}
input.invalid,
textarea.invalid {
border: 2px solid red;
}
input.valid,
textarea.valid {
border: 2px solid green;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<section class="body">
<form id="contact" method="post" enctype="multipart/form-data" action="">
<h1 class="title">Contact</h1>
<div>
<label for="name">Your Fullname</label>
<input type="text" id="name" name="name" required placeholder="Your Name">
<span id="name_error" class="error_show">This field is required</span>
</div>
<div>
<label for="email">Your Full Email</label>
<input name="email" type="email" id="email" required placeholder="Your Email">
<span id="email_error" class="error_show">This field is required</span>
</div>
<div>
<label for="message">Message</label>
<textarea id="message" name="message" cols="20" rows="5" required placeholder="Message"></textarea>
<span id="message_error" class="error_show">This field is required</span>
</div>
<div id="contact_submit">
<input type="submit" id="submit_button" value="Submit">
</div>
</form>
</section>
</body>
</html>
var element = $("#contact_submit" + form_data[input]['name'], ['email'], ['message']);
var valid = element.hasClass("valid");
var error_element = $("span", element.parent());
I think these lines don't select the right span.
I got to it on logging the error_element:
console.log(error_element);
Here is a JSFIDDLE with a "working" selector.
var error_element=$("#contact div span");
Now you can change the selector that it fits your needs!