Build and manipulate array based on required fields populated - javascript

I'm trying to figure out a sensible way to display and manipulate an array/list of required fields which are yet to be populated in a form - this is just so i can output this info to the user and remove each item from the list as the user goes through and populates the fields (as a sort of progress indicator). Any thoughts on how best to handle this?
I'm thinking of something along the lines of the following:
var reqFields = [];
jQuery('label.required').each(function() {
console.log(jQuery(this).text());
reqFields.push(jQuery(this).text());
});
jQuery('.custom-field').on('input', function() {
if (jQuery('.required-entry').filter(function() {
return this.value.length === 0;
}).length === 0) {
// Remove this from the list/array
} else {
}
});

On input event check the value and accordingly add/remove item in array.
var reqFields = [];
jQuery('label.required').each(function() {
console.log(jQuery(this).text());
reqFields.push(jQuery(this).text());
});
jQuery('.custom-field').on('input', function() {
if (this.value) {
// Remove this from the list/array
reqFields.splice(jQuery(this).index(),1);
// jQuery(this).index() havent tried, else just compute index some other way
} else {
// add back if cleared out
reqFields.push( jQuery('label.required').eq(jQuery(this).index()).text());
}
});

Instead of removing the entries, every time there's a change in input of the required fields, you can simply re-assign the reqFields array to the list of required fields with empty input.
var reqFields = [];
jQuery(function() {
jQuery('.requiredFields').on('input', function() {
reqFields = jQuery('.requiredFields').filter(function() {
return this.value.length === 0;
});
});
});

Check this basic example bellow using each on input to loop through all the fields with class required-entry and check the empty ones to finally append message to span #msg to inform the user which fields are required.
Hope this helps.
$('.required-entry').on('input', function() {
$('#msg').empty();
$('.required-entry').each(function() {
if ( $(this).val().length == 0 )
$('#msg').append('Field <b>'+$(this).prev('label').text()+'</b> is required.<br/>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class='required'>First Name</label>
<input type='text' id='first_name' name='first_name' class='required-entry' required/>
<br/>
<label class='required'>Last Name</label>
<input type='text' id='last_name' name='last_name' class='required-entry' required/>
<br/>
<label class='required'>Email Address</label>
<input type='text' id='email' name='email' class='required-entry' required/>
<hr/>
<br/>
<span id='msg'></span>

Related

How get the Count of Empty Input fields?

How can I check the Number of Incomplete Input fields in Particular ID, (form1, form2).
If 2 input fields are empty, in i want a msg saying something like "Incomplete Input 2"
How is it Possible to do this in JS ?
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test">
<input type="text" value="">
</div>
This is the JS, which is working, i have have multiple JS with class named assigned to each inputs and get the value, but i need to make this check all the Input fields inside just the ID.
$(document).on("click", "#form1", function() {
var count = $('input').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
Your html structure, especially form structure is not correct, so you should first add some submit button to form that can be clicked. Then you can add event listener on form's submission. In the event handler you should select children inputs inside the form tag using $(this).children("input"). Now you can filter them.
$(document).on("submit", "#form1", function (e) {
e.preventDefault();
var count = $(this)
.children("input")
.filter(function (input) {
return $(this).val() == "";
}).length;
alert(count);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
<button type="submit">Submit</button>
</form>
This is the JS, which is working, if I have have multiple JS with class named assigned to each inputs and Im getting the value, but i have multiple JS for this to work.
How can i make this Simpler say like, when user clicks on Div, it only checks the input fields inside that div.
$(document).on("click", "#form1", function() {
var count = $('.input_field1').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
HTML
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="" class="input_field1">
<input type="text" value=""class="input_field1">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test" class="input_field2">
<input type="text" value="" class="input_field2">
</div>
See snippet below:
It has commented and if you put some effort on it, you can have a jQuery plugin out of it.
(function () {
'use strict';
var
// this use to prevent event conflict
namespace = 'customValidation',
submitResult = true;
var
input,
inputType,
inputParent,
inputNamePlaceholder,
//-----
writableInputTypes = ['text', 'password'],
checkboxInputType = 'checkbox';
var
errorContainerCls = 'error-container';
// Add this function in global scope
// Change form status with this function
function changeFormStatus(status) {
submitResult = submitResult && status;
}
// Check if a radio input in a
// group is checked
function isRadioChecked(form, name) {
if(!form || !name) return true;
var radio = $(form).find('input[type="radio"][name="' + name.toString() + '"]:checked');
return typeof radio !== 'undefined' && radio.length
? true
: false;
}
function eachInputCall(inp, isInSubmit) {
input = $(inp);
inputType = input.attr('type');
// assume that we have a name placeholder in
// attributes named data-name-placeholder
inputNamePlaceholder = input.attr('data-name-placeholder');
// if it is not present,
// we should have backup placeholder
inputNamePlaceholder = inputNamePlaceholder ? inputNamePlaceholder : 'input';
if(!inputType) return;
// you have three type of inputs in simple form
// that you can make realtime validation for them
// 1. writable inputs ✓
// 2. checkbox inputs ✓
// 3. radio inputs ✕
// for item 3 you should write
// another `else if` condition
// but you should have it for
// each name (it was easier if it was a plugin)
// radio inputs is not good for realtime
// unchecked validation.
// You can check radios through submit event
// let make it lowercase
inputType = inputType.toLowerCase();
// first check type of input
if ($.inArray(inputType, writableInputTypes) !== -1) {
if(!isInSubmit) {
input.on('input.' + namespace, function () {
writableInputChange(this);
});
} else {
writableInputChange(inp);
}
} else if ('checkbox' == inputType) { // if it is checkbox
if(!isInSubmit) {
input.on('change.' + namespace, function () {
checkboxInputChange(this);
});
} else {
checkboxInputChange(inp);
}
}
}
// Check if an input has some validation
// (here we have just required or not empty)
function writableInputChange(inp) {
// I use $(this) instead of input
// to prevent conflict if selector
// is a class for an input
if('' == $.trim($(inp).val())) {
changeFormStatus(false);
// your appropriate message
// you can use bootstrap's popover
// to modefy just input element
// and make your html structure
// more flexible
// or
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(inp).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please fill ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(inp).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
// Check if an checkbox is checked
function checkboxInputChange(chk) {
if(!$(chk).is(':checked')) {
changeFormStatus(false);
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(chk).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please check ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(chk).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
$(function () {
var
form = $('#form'),
// you can change this selector with your classes
formInputs = form.find('> .input-group > input');
formInputs.each(function () {
eachInputCall(this);
});
form.submit(function () {
submitResult = true;
// check all inputs after form submission
formInputs.each(function () {
eachInputCall(this, true);
});
// Because of radio grouping by name,
// we should select them separately
var selectedGender = isRadioChecked($(this), 'gender');
var parent;
if(selectedGender) {
changeFormStatus(true);
parent = $(this).find('input[type="radio"][name="gender"]').parent();
parent.children('.' + errorContainerCls).remove();
} else {
changeFormStatus(false);
// I assume that all radios are in
// a separate container
parent = $(this).find('input[type="radio"][name="gender"]').parent();
if(!parent.children('.' + errorContainerCls).length) {
parent.append($('<div class="' + errorContainerCls + '" />').text('Please check your gender'));
}
}
if(!submitResult) {
console.log('There are errors during validations!');
}
return submitResult;
});
});
})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
<div class="input-group">
<input type="text" name="input1" data-name-placeholder="name">
</div>
<div class="input-group">
<input type="checkbox" name="input2" data-name-placeholder="agreement">
</div>
<div class="input-group">
<input type="radio" name="gender">
<input type="radio" name="gender">
</div>
<button type="submit">
submit
</button>
</form>

I'm trying to validate multiple HTML Form inputs with javascript, and change css for invalid ones, what is the best way to do this?

I'm trying to validate an HTML form, trying to check if answers are filled in, and an e-mail is an actual e-mail adress. I want to proceed when all fields are valid. When some fields are not valid, change the css in to another class (so it becomes red to show that it is wrong.)
I have tried to validate each input seperately, but i believe there should be an easier way. Can somebody show me?
Current HTML:
<div class="form-group" id="stage1">
<div class="row">
<input type="text" id="firstname" class="form-control" placeholder="Firstname*">
<input type="text" id="lastname" class="form-control" placeholder="Lastname*">
<input type="email" id="email" class="form-control" placeholder="E-mail*">
<input type="text" id="regnr" class="form-control" placeholder="Registration number">
</div>
</div
I can't use HTML default validation, since I have created a multi-step form.
Thanks in advance,
Brandon
You can iterate through inputs this will assist validating your messy items:
window.onload = () => {
const allInputs = document.querySelectorAll(".form-control"); // or you may assign custom class or select by input tag..
let isAllvaild = true;
allInputs.forEach((element) => {
if (!validateAll(element.value, element.type)) { isAllvaild = false; break; }
});
if (isAllvaild) {
afterValidation(); // to keep things clean
}
}
function validateAll(value, type) {
if (type === "text") {
} else if (type === "email") {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
let ck = re.test(String(value).toLowerCase());
if (ck) {
// set errors here..
} else {
// maybe remove errors if added previously..
}
return ck;
} else if (type === "phone") {
} else if (type === "other") {
} // add whatever needed..
}
function afterValidation() {
// at this point each input contains valid data.. proceed to next step..
// document.querySelector("#my_id").classList.add("display-block");
// ..
}
you can validate based on their type, so i think u would have two functions, one for email and another one for text fields. for instance:
if(textValidation() && emailValidation()){
submit()
}
emailValidation(){
return email ? true : false
}
textValidation(){
return text ? true : false
}
What about that? It will let you loop through every input and you can also do some specific validations. I know, it is not the smartest function ever, but it can be useful. (ofc you should make some better checking for email pattern (regular expressions are good for that /^.+?#.+..+$/m) and registration number (regex could be cool for that too: /^[\d]*$/m)
function validateInputs ()
{
const inputs = document.querySelectorAll('div[class=row] input');
for (let index = 0; index < inputs.length; index++)
{
const input = inputs[index];
let valid = false;
if (input.value && input.value.trim() !== '')
{
//here you can add specific validations for each id, maybe you can also use switch here
if (input.getAttribute('id') === 'email')
{
//of course, email also need to validate, if dot is present, regular expression might be the best option
if (input.value.indexOf('#') !== -1)
{
valid = true;
}
}
else
{
valid = true;
}
}
if (!valid)
{
input.classList.add('error');
}
else
{
input.classList.remove('error');
}
}
};
window.addEventListener('load', function () {
document.querySelector('button').addEventListener('click', validateInputs)
});
input.error {
background-color: red;
}
<div class="row">
<input type="text" id="firstname" class="form-control" placeholder="Firstname*">
<input type="text" id="lastname" class="form-control" placeholder="Lastname*">
<input type="email" id="email" class="form-control" placeholder="E-mail*">
<input type="text" id="regnr" class="form-control" placeholder="Registration number">
</div>
<button>validate</button>
For fields like text you need to write your own validation, since it is totally up to you. But in case of fields like email or url you can use build in functions like the HTMLFormElement.checkValidity() method to see if the form contains a field that does not have a valid input, for example a input with type email and a value of foobar would return false from the validity check.
Then you can look inside the form and search for all inputs that are invalid with the :invalid selector in querySelectorAll(). It will return a NodeList with the invalid form elements inside of it.
const form = document.querySelector('form');
form.addEventListener('input', event => {
if (form.checkValidity() === false) {
const invalids = form.querySelectorAll(':invalid');
for (const input of invalids) {
console.log(`${input.id} is invalid`);
}
}
});
<form>
<input type="text" id="firstname" class="form-control" placeholder="Firstname*">
<input type="text" id="lastname" class="form-control" placeholder="Lastname*">
<input type="email" id="email" class="form-control" placeholder="E-mail*">
<input type="url" id="website" class="form-control" placeholder="Website*">
<input type="text" id="regnr" class="form-control" placeholder="Registration number">
</form>
You can use this code between a script tag :
const form = document.querySelector('form'); form.addEventListener('input', event => { if (form.checkValidity() === false) { const invalids = form.querySelectorAll(':invalid'); for (const input of invalids) { console.log(`${input.id} is invalid`); } } });
Or use a Bootstrap classes to validate your form

Compare input text with person name belongs to only one input number id

Im trying to write a validation for 2 groups of fields. I have 6 inputs, 3 for text name and 3 more for id number... the validation should do this "if input name="RE_SignedByID" has an input type name="RE_SignedByName", then other inputs name="RE_SignedByID", should NOT contain the same name="RE_SignedByName" More easy explanation... one ID number should have only one Person Name (Id number is unique for one person name). What can I use for that? Should I map() all the inputs?
Those are my inputs:
<div id="signedBy" class="clearfix">
<label>Signer, person ID & name</label>
<span id="signedByID" class="ids half">
<input type="text" name="RE_SignedByID" placeholder="personID, person1" data-validate="" tabindex="101" required>
<input type="text" name="RE_SignedByID" placeholder="personID, person2" data-validate="" tabindex="103">
<input type="text" name="RE_SignedByID" placeholder="personID, person3" data-validate="" tabindex="105">
</span>
<span class="names half">
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" required>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="104">
<input type="text" name="RE_SignedByName" placeholder="name, person3" tabindex="106">
</span>
</div>
I guess it should also be an "on change" function? or can I make the validation on click? Some ideas...? Im actually compleatley lost here...
Thanks in advance!!!
Maybe use different class names for all 3 of them to make them unique?
<input class="name1">
<input class="name2">
<input class="name3">
I'm not sure what you mean but if you want to make the input types unique and not call them all when you write class="names half", then you should give them all unique class names.
So from my understanding you don't want multiple fields to have the same value.
My approach would be this:
let inputTimeout = null; //set an empty timeout object
let vars = [null, null, null, null]; // create an array containing as many nulls as you have inputs
$('.nameInput').on('keyup', function(){
let self = $(this);
clearTimeout(inputTimeout); //clear the timeout
inputTimeout = setTimeout(function(){ //set a timeout to check whether there is a dupe after the user has stopped typing
if (vars.indexOf(self.val()) == -1){ //check if the vals array contains the newly entered string
vars[self.attr('data-inputnum')] = self.val(); //insert the value into the array
}else{
//handle duplicates here
}
}, 500); //500ms is a sensible value for end of user input, change it if users complain that your app is too fast/slow
});
You then just have to edit your HTML a bit so that all name inputs have a class in common (i used .nameInput) and have a data-inputnum attr.
This would look something like this:
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" class='nameInput' data-whichinput='0'/>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="103" class='nameInput' data-whichinput='1'/>
<!--and so on-->
Of course, never rely on JavaScript verification alone, always also check inside your backend. However this would be out of scope for this answer.
Hi Thanks all for the help, made me realize a couple of things till I got the answer. This is my working code:
var valSignedID = $("[name=SignedByID]").map(function() {
return this.value.trim();
}).get();
var valOwnersID = $("[name=OwnersID]").map(function() {
return this.value.trim();
}).get();
valSignedID.sort();
valOwnersID.sort();
for (var i = 0; i < valSignedID.length - 1; i++) {
if (valSignedID[i] == valSignedID[i + 1] && valSignedID[i] != "") {
alert(" You can not have duplicated signers ID's");
return false;
// break;
}
}
for (var i = 0; i < valSingedName.length; i++) {
if (valSingedName[i] == valSingedName[i + 1] && valSingedName[i] != "") {
alert(valSingedName[i] + " should not have different ID");
//return false;
}
}

How do I take the value of an input field and make sure that it matches the value of a list item?

I have a list of values:
<ul>
<li>Value1</li>
<li>Value2</li>
<li>Value3</li>
</ul>
I then have a series of input fields
<form>
<input type="text" class="textinput" />
<input type="text" class="textinput" />
<input type="text" class="textinput" />
</form>
When it's fully styled it would then be laid out like:
list item input field
list item input field
list item input field
What I would like to do is create a memorization exercise where the user inputs the text as shown in the list item into the corresponding input field next to it. Using JavaScript I then want to validate that the value typed into each input correctly corresponds to the list item. Once the entire exercise is complete then it would allow you to move on to the next exercise.
var ip = document.getElementsByTagName('form')[0];
var lis = document.getElementsByTagName('ul')[0];
for (var i = 0, len = ip.children.length; i < len; i++) {
(function (index) {
ip.children[i].onblur = function () {
var lisText = lis.children[index].innerHTML;
if (this.value == lisText) {
alert("Valid");
} else {
alert("Not Valid");
}
}
})(i);
}
JSFiddle
Use list item as id of textbox.
<ul>
<li>item1<input type="text" id="item1"></li>
</ul>
Now using java script get value of thw textbox.
Var textbox1=document.getElementById(item1);
Var textboxval1=textbox1.value;
Google the java script code.may be mine is wrong.but u can follow this logic.I hope it will work.
you can try this, but keep in mind that the total number of list and text boxes must be equal
<ul id="matcher">
<li>Value1</li>
<li>Value2</li>
<li>Value3</li>
</ul>
<form>
<input type="text" class="textinput" id="inpuText0"/>
<input type="text" class="textinput" id="inpuText1"/>
<input type="text" class="textinput" id="inpuText2"/>
</form>
JavaScript
function validate()
{
var ul = document.getElementById('matcher');
var ele = ul.getElementsByTagName('li');
for( var i=0;i<ele.length;i++)
{
var text = ele[i].textContent || ele[i].innerText;
if(text != document.getElementById('inputText'+i).value)
{
alert('value not matching for '+i+' row');
ele[i].focus();
return false;
}
}
}

adjusting default value script to work with multiple rows

I am using a default value script (jquery.defaultvalue.js) to add default text to various input fields on a form:
<script type='text/javascript'>
jQuery(function($) {
$("#name, #email, #organisation, #position").defaultvalue("Name", "Email", "Organisation", "Position");
});
</script>
The form looks like this:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]" id="name">
<input type="text" name="email[]" id="email">
<input type="text" name="organisation[]" id="organisation">
<input type="text" name="position[]" id="position">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I am also using a script so that users can dynamically add (clone) rows to the form:
<script>
$(document).ready(function() {
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
x.find('input').each(function() { this.value = ''; });
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
});
</script>
So, when the page loads there is one row with the default values. The user would then start adding information to the inputs. I am wondering if there is a way of having the default values show up in subsequent rows that are added as well.
You can see the form in action here.
Thanks,
Nick
Just call .defaultValue this once the new row is created. The below assumes the format of the columns is precticable/remains the same.
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
x.find('input:not(:submit)').defaultvalue("Name", "Email", "Organisation", "Position");
return false;
});
You should remove ids from the input fields because once these are cloned, the ids, classes, everything about the elements are cloned. So you'll basically end up with multiple elements in the DOM with the same id -- not good.
A better "set defaults"
Personally I would remove the "set defaults plugin" if it's used purely on the site for this purpose. It can easily be re-created with the below and this is more efficient because it doesn't care about ordering of input elements.
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements)
{
$(inputElements).each(function() {
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true);
}
});
};
Then you can simply do (once page is loaded):
setDefaults(jQuery('form[name=booking] input'));
And once a row is added:
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input')); // <-- let the magic begin
return false;
});
For the toggling of default values you can simply delegate events and with the help of setDefault
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
if ($(this).data('isDefault'))
$(this).val('').removeData('isDefault');
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
Fiddle: http://jsfiddle.net/garreh/zEmhS/3/ (shows correct toggling of default values)
Okey, first of all; ids must be unique so change your ids to classes if you intend to have more then one of them.
and then in your add function before your "return false":
var
inputs = x.getElementsByTagName('input'),
defaults = ["Name", "Email", "Organisation", "Position"];
for(var i in inputs){
if(typeof inputs[i] == 'object'){
$(inputs[i]).defaultvalue(defaults[i]);
}
}

Categories

Resources