Goodmorning everyone,
I have a problem with a script for validating a form.
Given that the module has server-side validation in PHP, what I want to achieve, too, is client-side validation.
This validation is very simple.
When you click on the SUBMIT button, you must check if all the mandatory fields have been filled in.
If they are not:
must add a class to the input to make it change color;
must change the content of the icon next to the input field.
I use this script which works with regards to check and class on input. However, it uses a check on the NAME of the fields.
HTML
<form id="signinform" method="post" action="" class="wp-user-form" autocomplete="off" onsubmit="event.preventDefault(); validateMyForm();" novalidate>
<div class="msc-login-form-input">
<input type="text" name="log" value="" size="20" id="user_login" placeholder="Username o Email" autocomplete="off" required onkeyup="validateElement(this)"/>
<span id="errorsign"></span> </div>
<div class="msc-login-form-input">
<input type="password" name="pwd" value="" size="20" id="user_pass" placeholder="Password" autocomplete="off" required onkeyup="validateElement(this)"/>
<span id="errorsign"></span> </div>
<div class="msc-login-form-input-sendh">
<input type="submit" id="submit-login" name="submit-login" value="" class="user-submit" />
</div>
</form>
JS
<script lang="javascript">
function validateMyForm(){
let isFormValid = true;
let elems = document.getElementsByName("namefield");
for(let i=0; i< elems.length; i++)
{
let elem = elems[i];
if(elem.value.length < 1)
{
if(isFormValid){
isFormValid = false;
}
}
validateElement(elem);
}
if(isFormValid)
{
document.getElementById("signinform").submit();
return true;
}
}
function validateElement(elem){
if(elem.value.length < 1)
{
elem.className = "errorClass";
}else{
elem.className = "okClass";
}
}
</script>
CSS
<style>
.msc-login-form-input input.okClass {
background-color: #ffffff;
color: #3F4254;
}
.msc-login-form-input input.errorClass {
background-color: #4d40ff;
color: #ffffff;
}
.msc-login-form-input #errorsign {
width: 35px;
background-color: rgba(0,0,0,0.05);
min-height: 100%;
align-items: center;
justify-content: center;
text-align: center;
display: flex;
}
.msc-login-form-input #errorsign::before {
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f100";
}
.msc-login-form-input #errorsign.fail::before {
content: "\f00d";
color:#4d40ff;
}
.msc-login-form-input #errorsign.okay::before {
content: "\f00c";
color:#FF1493;
}
</style>
The problem is that the NAMEs of my fields are not the same and therefore that loop cannot work.
How can I solve without duplicating the loop for each form field?
How can I also add the control on the class of the icon next to it?
Thank you.
If you don't want to use the builtin validation, I'd do it as follows
let formvalid = true;
//these are the divs surrounding your elements to be validated
let elements = document.getElementsByClassName("msc-login-form-input")
for (let i = 0; i < elements.length; i++) {
//this is the input to be validated
let input = elements[i].getElementsByTagName("input")[0];
//this is the span element holding the icon
let icon = elements[i].getElementsByTagName("span")[0];
let valid = validateElement(input);
//set the classes input and span according to the validation result
input.classList.Add(valid ? "okClass" :"errorClass");
span.classList.Add(valid ? "okay" :"fail");
input.classList.Remove(valid ? "errorClass": "okClass");
span.classList.Remove(valid ? "fail" : "okay" );
//the form is only valid if ALL elements are valid
formvalid &= valid;
}
function validateElement(element) {
if (input.value.length === 0) return false;
//any other validations you want to do
return true;
}
Furhtermore you have a problem in your DOM tree. You have mutliple <span> elements with the same id="errorsign". That's not gonna work, because an id has to be unique. So remove the ids and grab the <spans> from their parents as shown above.
You could also just add the "okay" and "fail" to the surrounding <div> and adapt your css accordingly. Ie something like the following CSS
.msc-login-form-input.okay input {
...
}
.msc-login-form-input.fail input {
...
}
.msc-login-form-input.okay span::before {
...
}
.msc-login-form-input.fail span::before {
...
}
And the following JS
let formvalid = true;
//these are the divs surrounding your elements to be validated
let elements = document.getElementsByClassName("msc-login-form-input")
for (let i = 0; i < elements.length; i++) {
//this is the input to be validated
let input = elements[i].getElementsByTagName("input")[0];
let valid = validateElement(input);
element.classList.Add(valid ? "okay" : "fail");
element.classList.Remove(valid ? "fail": "okay");
formvalid &= valid;
}
Related
I tried to change the background color of the input field with an if statement. I dont know why it isnt working. What can I do to get it working?
function increment() {
var textbox = document.
getElementById("inc");
textbox.value++;
}
var inputfield = document.getElementById("inc")
// trying to change bg color of inputfield if number higher or lower -- doesnt work yet
if (inputfield.value > 3) {
inputfield.style.backgroundColor = "#AA0000";
}
<div class = wrapper>
<button onclick="increment()">Click to + 1!</button>
<input class="inputfield" id="inc" type="text" value="0" />
</div>
While your javascript function increment() gets executed each click of the button, the rest of your javascript code gets only executed once after the document has been loaded. Initially input field #inc value is 0 and will not change color as it never becomes > 3 this way.
In your Javascript:
you only have to get the reference to input element #inc once (const textBox) and use that in your increment function. In the snippet I defined the constant textBox as global because the reference does not change, just its .value. Consequently method .getElementById does not have to be executed each click of the button.
After the button has been clicked, increment textBox.value and change the color when the value > 3.
Snippet
// Get a reference to the textbox
const textbox = document.getElementById("inc");
function increment() {
textbox.value++; // increment its value
if (textbox.value > 3) {
// change its color
textbox.style.backgroundColor = "#AA0000";
}
}
<div class=wrapper>
<button onclick="increment()">Click to + 1!</button>
<input class="inputfield" id="inc" type="text" value="0" />
</div>
Check this out.
const inputfield = document.getElementById("change_color_example")
inputfield.addEventListener("keyup", function() {
if (this.value > 3) {
this.classList.add("active-math")
} else {
this.classList.remove("active-math")
}
if (this.value.length > 3) {
this.classList.add("active-length")
} else {
this.classList.remove("active-length")
}
})
.example-input {
color: #333333;
background-color: #ffffff;
border: 1px solid #000000;
transition: all 300ms linear;
}
.example-input.active-math {
color: #f8f8f8;
background-color: #AA0000;
}
.example-input.active-length {
color: blue;
background-color: bisque;
}
<input type="text" id="change_color_example" class="example-input" />
We can start of by grabbing the input element from the DOM.
const input = document.querySelector('input');
Once we have the element to work with we can, we can add an event listener (blur) so whenever a user moves out of the box the action in the code will be performed.
JS:
const input = document.getElementById("input");
input.addEventListener("blur", () => {
if (input.value.length > 3) {
input.style.backgroundColor = "red";
}
});
HTML:
<input type="text" id="input" />
I want to show the error message of required if mandatory fields are left blank. I implement it using the following way but every time the function checkinput() is invoked it adds a new span element due to which "required" message is outputted multiple times. I want the span element to be added once and disappears when user fills in the requirement. Here is my code.
const checkinput=(event)=>{
if(event.target.value===""){
event.target.insertAdjacentHTML('afterend','<span class="text-danger">Required</span>')
}
if(event.target.value!==""){
var child=document.querySelector('span');
child.remove();
}
}
document.getElementById("username").addEventListener('blur',checkinput);
document.getElementById("password").addEventListener('blur',checkinput);
document.getElementById("confirmPassword").addEventListener('blur',checkinput);
Reason why new span element is added each time you have a empty input field is because you are calling insertAdjacentHTML each time and inserting a new span element.
What you should do is add span elements with each input field in the html and initially they should be empty.When you want to validate the input fields, if any of the input is empty, select the span element next to that input element and show the error message in that span element using .textContent property. To clear the error message, you just need to set .textContent of the span element to an empty string.
Following code snippets show different ways of validating form inputs.
Form validation on form submit
Following code snippet validates form inputs when form is submitted.
const form = document.querySelector('form');
const usernameError = document.querySelector('#usernameError');
const passwordError = document.querySelector('#passwordError');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username', usernameError);
const passwordValid = validateField(form, 'password', passwordError);
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
function validateField(form, fieldName, errorEl) {
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
<button>Submit</button>
</form>
Form validation on input focus loose
Following code snippet validates form inputs when any of the input looses focus.
const form = document.querySelector('form');
const inputsContainer = document.getElementById('formInputsContainer');
const submitBtn = document.querySelector('button');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username');
const passwordValid = validateField(form, 'password');
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
submitBtn.addEventListener('focus', () => {
form.requestSubmit();
});
inputsContainer.addEventListener('focusout', (event) => {
validateField(form, event.target.name);
});
function validateField(form, fieldName) {
const errorEl = document.getElementById(`${fieldName}Error`);
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div id="formInputsContainer">
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
</div>
<button>Submit</button>
</form>
Form validation as user types in the input field
Following code snippet validates form input as user types in any input field.
const form = document.querySelector('form');
const inputsContainer = document.getElementById('formInputsContainer');
form.addEventListener('submit', (event) => {
event.preventDefault();
const usernameValid = validateField(form, 'username');
const passwordValid = validateField(form, 'password');
if (usernameValid && passwordValid) {
console.log('form submitted');
form.reset();
}
});
inputsContainer.addEventListener('input', (event) => {
validateField(form, event.target.name);
});
function validateField(form, fieldName) {
const errorEl = document.getElementById(`${fieldName}Error`);
if (form.elements[fieldName].value == '') {
errorEl.textContent = `${fieldName} is required`;
return false;
} else {
errorEl.textContent = '';
return true;
}
}
form div {
margin: 0 0 10px;
display: flex;
flex-direction: column;
max-width: 200px;
}
form label { margin: 0 0 5px; }
span { color: red; }
<form>
<div id="formInputsContainer">
<div>
<label>Username</label>
<input type="text" name="username" />
<span id="usernameError"></span>
</div>
<div>
<label>Password</label>
<input type="password" name="password" />
<span id="passwordError"></span>
</div>
</div>
<button>Submit</button>
</form>
You need something like
if(event.target.value==="" && document.querySelector('span') === null){
event.target.insertAdjacentHTML('afterend','<span class="text-danger">Required</span>')
}
if(event.target.value!==""){
var child=document.querySelector('span');
child.remove();
}
You only want to add a span IF the value is an empty string AND the span hsan't been added yet.
You can use this code which create a span which is add to the DOM with the ID which is based on the form element'sname attribute. And that element can be refered to based on the ID which was attach to it before It's been add to the DOM
const checkinput=(event)=>{
if(event.target.value===""){
let spanId = `input-${event.target.name}`
let span = `<span id="${spanId}" class="text-danger">Required</span>`
setTimeout(() =>{
document.getElementById(spanId).remove();
}, 5000);
event.target.insertAdjacentHTML('afterend',span)
}
}
document.getElementById("username").addEventListener('blur',checkinput);
document.getElementById("password").addEventListener('blur',checkinput);
document.getElementById("confirmPassword").addEventListener('blur',checkinput);
<form>
<input type="text" name="username" id="username"/>
<input type="text" name="password" id="password"/>
<input type="text" name="confirmPassword" id="confirmPassword"/>
</form>
May it help
<style>
.errorMsg {
border: 1px solid red;
}
.err {
color: red;
}
</style>
<form>
<input type="text" name="name" id="name">
<input type="password" name="password" id="password">
<button id="submit" type="submit">Submit</button>
</form>
<script>
let nameTag = document.querySelector('#name');
let passwordTag = document.querySelector('#password');
let submitBtn = document.querySelector('#submit');
nameTag.addEventListener('blur', e => validation(e));
passwordTag.addEventListener('blur', e => validation(e));
function validation(e) {
if (e.target.value == '') {
e.target.classList.add('errorMsg')
submitBtn.setAttribute('disabled', true) // Disable submit that user cannot submit
e.target.insertAdjacentHTML('afterend', `<span class="err ${e.target.id}">It is required</span>`)
// In the above line we are inserting an element with class same as id of input that in the remove we remove a particular error message only
} else {
e.target.classList.remove('errorMsg')
submitBtn.removeAttribute('disabled')
document.querySelector(`.err.${e.target.id}`).remove();
//Here code is saying that the element with if 'err' and 'class same as id of input' if both class present then remove it
}
}
</script>
Adding the class = id that a special error message delete
I have a Radio button. I want to implement a validation on "Submit" Anchor tag that displays an error if no selection is made on the radio button and redirects to the URL provided in the href attribute if the radio button selection is made.
Below is the code for radio button -
<div>
<input required="" type="radio" id="group02-0" name="group02" value="Yes" onclick="yesnoCheck();">
<label for="group02-0" >Yes</label>
<input type="radio" id="group02-1" name="group02" value="No" onclick="yesnoCheck();">
<label for="group02-1">No</label>
</div>
<script>
var radio_value = "";
function yesnoCheck() {
radio_value = document.querySelector('input[name="group02"]:checked').value;
}
</script>
In the same HTML file, I have code for the Submit Anchor tag -
<span>Submit</span>
<script>
function submitCheck() {
if (radio_value === "") {
//Display an error. The user should not be taken to the next page
return false;
} else {
//User should be taken to the URL in the href attribute
return true;
}
}
</script>
Irrespective of whether I make a selection on the radio button, the anchor tag always takes me to the next page. Please help!
You don't need two radio buttons. Only one Checkbox.
Use Event.preventDefault() to prevent default browser navigation
Use the input element's checked state to determine the outcome
Finally use document.location to navigate to a EL_submitBtn.getAttribute('href')
PS: Don't use inline JavaScript (in HTML). JS should be in one place and that's your JS file or inside a <script> tag. It's easier to debug and maintain.
Single checkbox
const EL_submitBtn = document.querySelector('#submitBtn');
const EL_acceptCkb = document.querySelector('[name="accept"]');
function submitCheck(ev) {
ev.preventDefault(); // prevent follow link
if (!EL_acceptCkb.checked) { // Unchecked
alert("You will not get a better UX");
} else { // Checked
alert("Yes! Buckle up!")
document.location = EL_submitBtn.getAttribute('href');
}
}
EL_submitBtn.addEventListener('click', submitCheck);
<div>
<h3>Would you like a better UX?</h3>
<label>
<input type="checkbox" name="accept"> Yes I do
</label>
</div>
<a id="submitBtn" href="https://www.google.com">Submit</a>
Two radio buttons
Use document.querySelector('[name="accept"]:checked') to get the checked one, if any.
const EL_submitBtn = document.querySelector('#submitBtn');
function submitCheck(ev) {
ev.preventDefault(); // prevent follow link
const EL_acceptCkd = document.querySelector('[name="accept"]:checked');
if (!EL_acceptCkd) { // None checked
alert("You must select Yes or No.");
} else if (EL_acceptCkd.value === 'no') { // "NO" checked
alert("You will not get a better UX");
} else { // "YES" checked
alert("Yes! Buckle up!")
document.location = EL_submitBtn.getAttribute('href');
}
}
EL_submitBtn.addEventListener('click', submitCheck);
<div>
<h3>Would you like a better UX?</h3>
<label>
<input type="radio" name="accept" value="yes"> Yes
</label>
<label>
<input type="radio" name="accept" value="no"> No
</label>
</div>
<a id="submitBtn" href="https://www.google.com">Submit</a>
use css pointer-events: none; -> https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
If you absolutely want to use button radios (even if it's a bit twisted as an idea) here is the code:
const aHrefGoogle = document.getElementById('aHrefGoogle');
document.querySelectorAll('input[name=group02]').forEach(el=>
{
el.onchange=_=>{ if (el.checked) setLinkOnOff(el.value) }
})
function setLinkOnOff(val)
{
if (val==='yes') { aHrefGoogle.classList.remove('adisableHref') }
else { aHrefGoogle.classList.add('adisableHref') }
}
.adisableHref {
color: grey;
pointer-events: none;
cursor: default;
text-decoration-line: none;
}
make link Google active ?
<label ><input type="radio" name="group02" value="yes">Yes </label>
<label ><input type="radio" name="group02" value="no" checked>No! </label>
<br><br>
<span> Google </span>
for memo here is the initial code with a checkbox :
const yesnoCheck = document.getElementById('yesnoCheck')
, aHrefGoogle = document.getElementById('aHrefGoogle')
;
// init
yesnoCheck.checked = false
aHrefGoogle.classList.add('adisableHref')
yesnoCheck.oninput =_=>
{
if (yesnoCheck.checked) { aHrefGoogle.classList.remove('adisableHref') }
else { aHrefGoogle.classList.add('adisableHref') }
}
#yesnoCheck { display: none; }
#yesnoCheck + label { display: inline-block; background: #cd3c3c; color: white; padding: .17em .2em; cursor: pointer; }
#yesnoCheck:checked + label { background: #378b2c; }
#yesnoCheck + label::before { content: 'NO'; display: inline-block; width:2.6em; text-align: center; }
#yesnoCheck + label::after { content: ''; display: inline-block; width:0; text-align: center; }
#yesnoCheck:checked + label::before { content: ''; width:0; }
#yesnoCheck:checked + label::after { content: 'YES'; width:2.6em; }
.adisableHref {
color: grey;
pointer-events: none;
cursor: default;
text-decoration-line: none;
}
make link Google active ?
<input type="checkbox" id="yesnoCheck"><label for="yesnoCheck">▉</label>
<br><br>
<span> Google </span>
I am trying to change the display property of some text using JS, upon button click.
I have confirmed that the function is firing and running correctly using debugger, but for some reason, I can't grab the specific element I need to change, and assign it to a variable. I also have jquery set up on the page.
I have tried using the console, and document.getElementById('warning-textID') returns the correct element, but when I try to set it to a variable in console, it returns undefined. Am I missing something super obvious here?
Here is the HTML, function and css.
//adding event listener
$(function() {
document.getElementById("submitdiscount").addEventListener("click", putCookie);
});
// click function
function putCookie() {
var enteredValue = document.getElementById("nameBox").value;
var validParam = "test";
var warning = document.getElementById("warning-textID");
var cookieCreated = false;
if(enteredValue == validParam){
console.log('do the thing')
if(cookieCreated == false && enteredValue == validParam){
warning.innerText = "Please enable cookies";
warning.style.display = "";
return;
} else {
warning.innerText = "Please enter the correct code."
warning.style.display = "";
enteredValue.value = "";
return;
}
}
.warning-text {
color: red; text-align: center;
margin-bottom: 0px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="employee-code-input-wrapper" id="employee-code-input">
<div class="employee-code-input-header">
<h2>Enter the employee code you received via email</h2>
</div>
<div class="search-bar emplyoee-code-input-input-wrapper" >
<input class="emplyoee-code-input-input" type="text" placeholder="Enter Employee Code" code="" id="nameBox" name="pass">
<button class="btn btn--submit-employee-form" value="Submit" id="submitdiscount" type="button">submit</button>
</div>
<h2 class="warning-text" id="warning-textID">
Please enter the correct code.
</h2>
</div>
I fixed some mistakes and it worked.
//adding event listener
$(function() {
document.getElementById("submitdiscount").addEventListener("click", putCookie);
// click function
function putCookie() {
var enteredValue = document.getElementById("nameBox").value;
var validParam = "test";
var warning = document.getElementById("warning-textID");
var cookieCreated = false;
if (enteredValue === validParam) {
console.log('do the thing')
if (cookieCreated == false && enteredValue === validParam) {
warning.innerText = "Please enable cookies";
warning.style.display = "block";
return;
}
} else {
warning.innerText = "Please enter the correct code."
warning.style.display = "block";
enteredValue.value = "";
return;
}
}
});
.warning-text {
color: red;
text-align: center;
margin-bottom: 0px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="employee-code-input-wrapper" id="employee-code-input">
<div class="employee-code-input-header">
<h2>Enter the employee code you received via email</h2>
</div>
<div class="search-bar emplyoee-code-input-input-wrapper">
<input class="emplyoee-code-input-input" type="text" placeholder="Enter Employee Code" code="" id="nameBox" name="pass">
<button class="btn btn--submit-employee-form" value="Submit" id="submitdiscount" type="button">submit</button>
</div>
<h2 class="warning-text" id="warning-textID">
Please enter the correct code.
</h2>
</div>
Ok, so I have a filterable search form that returns certain images in a grid, which works great, it resets when I delete the text in the search input, but when I click the "Clear" button, which should do the same thing as deleting the text, it doesn't work. Here is the HTML and JQuery used:
<form id="live-search" action="" class="styled" method="post" style="margin: 2em 0;">
<div class="form-group">
<input type="text" class="form-control" id="filter" value="" style="width: 80%; float: left;" placeholder="Type to search"/>
<span id="filter-count"></span>
<input type="button" class="clear-btn" value="Clear" style="background: transparent; border: 2px solid #af2332; color: #af2332; padding: 5px 15px; border-radius: 3px; font-size: 18px; height: 34px;">
</div>
</form>
This is the JQuery for the clearing text:
jQuery(document).ready(function(){
jQuery("#filter").keyup(function(){
// Retrieve the input field text and reset the count to zero
var filter = jQuery(this).val(), count = 0;
// Loop through the comment list
jQuery(".watcheroo").each(function(){
jQuery(this).removeClass('active');
// If the list item does not contain the text phrase fade it out
if (jQuery(this).text().search(new RegExp(filter, "i")) < 0) {
jQuery(this).fadeOut();
// Show the list item if the phrase matches and increase the count by 1
} else {
jQuery(this).show();
count++;
}
});
// Update the count
var numberItems = count;
});
//clear button remove text
jQuery(".clear-btn").click( function() {
jQuery("#filter").value = "";
});
});
Any help would greatly be appreciated.
value is a property on a DOMElement, not a jQuery object. Use val('') instead:
jQuery(document).ready(function($) {
$("#filter").keyup(function() {
var filter = $(this).val(),
count = 0;
$(".watcheroo").each(function(){
var $watcheroo = $(this);
$watcheroo.removeClass('active');
if ($watcheroo.text().search(new RegExp(filter, "i")) < 0) {
$watcheroo.fadeOut();
} else {
$watcheroo.show();
count++;
}
});
var numberItems = count;
});
$(".clear-btn").click(function() {
$("#filter").val(''); // <-- note val() here
});
});
Note that I amended your code to alias the instance of jQuery passed in to the document.ready handler. This way you can still use the $ variable safely within the scope of that function.
As the accepted answer doesn't solve the problem.
Try input event instead of keyup
$("#filter").on("input", function() {.....
& then clear the filter input field on which event you want.
$(".clear-btn").on("click", function() {
$("#filter").val("").trigger("input");
});
Add this to your CSS:
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: searchfield-cancel-button;
}
<form>
<input type="search" name="search" placeholder="Search...">
</form>