Javascript validation - group validation - if one entered, then all required - javascript

Using just jQuery (not validation plugin) I have devised a way to do a "if one, then all" requirement, but it's not at all elegant.
I'm wondering if someone can come up with a more elegant solution? This one uses some loop nesting and I'm really not pleased with it.
if ($("[data-group]")) {
//Store a simple array of objects, each representing one group.
var groups = [];
$("[data-group]").each(function () {
//This function removes an '*' that is placed before the field to validate
removeCurError($(this));
var groupName = $(this).attr('data-group');
//If this group is already in the array, don't add it again
var exists = false;
groups.forEach(function (group) {
if (group.name === groupName)
exists = true;
});
if (!exists) {
var groupElements = $("[data-group='" + groupName + "']");
var group = {
name: groupName,
elements: groupElements,
trigger: false
}
group.elements.each(function () {
if (!group.trigger) {
group.trigger = $(this).val().length !== 0;
}
});
groups.push(group);
}
});
//Now apply the validation and alert the user
groups.forEach(function (group) {
if (group.trigger) {
group.elements.each(function () {
//Make sure it's not the one that's already been filled out
if ($(this).val().length === 0)
// This function adds an '*' to field and puts it into a
// a sting that can be alerted
appendError($(this));
});
}
});

You don't have to store the groups in an array, just call the validateGroups function whenever you want to validate the $elements. Here is a working example http://jsfiddle.net/BBcvk/2/.
HTML
<h2>Group 1</h2>
<div>
<input data-group="group-1" />
</div>
<div>
<input data-group="group-1" />
</div>
<h2>Group 2</h2>
<div>
<input data-group="group-2" value="not empty" />
</div>
<div>
<input data-group="group-2" />
</div>
<div>
<input data-group="group-2" />
</div>
<button>Validate</button>
Javascript
function validateGroups($elements) {
$elements.removeClass('validated');
$elements.each(function() {
// Return if the current element has already been validated.
var $element = $(this);
if ($element.hasClass('validated')) {
return;
}
// Get all elements in the same group.
var groupName = $element.attr('data-group');
var $groupElements = $('[data-group=' + groupName + ']');
var hasOne = false;
// Check to see if any of the elements in the group is not empty.
$groupElements.each(function() {
if ($(this).val().length > 0) {
hasOne = true;
return false;
}
});
// Add an error to each empty element if the group
// has a non-empty element, otherwise remove the error.
$groupElements.each(function() {
var $groupElement = $(this);
if (hasOne && $groupElement.val().length < 1) {
appendError($groupElement);
} else {
removeCurError($groupElement);
}
$groupElement.addClass('validated');
});
});
}
function appendError($element) {
if ($element.next('span.error').length > 0) {
return;
}
$element.after('<span class="error">*</span>');
}
function removeCurError($element) {
$element.next().remove();
}
$(document).ready(function() {
$('button').on('click', function() {
validateGroups($("[data-group]"));
});
});

You might get some milage out of this solution. Basically, simplify and test your solution on submit click before sending the form (which this doesn't do). In this case, I simply test value of the first checkbox for truth, and then alert or check the required boxes. These can be anything you like. Good luck.
http://jsfiddle.net/YD6nW/1/
<form>
<input type="button" onclick="return checkTest()" value="test"/>
</form>
and with jquery:
checkTest = function(){
var isChecked = $('input')[0].checked;
if(isChecked){
alert('form is ready: input 0 is: '+isChecked);
}else{
$('input')[1].checked = true;
$('input')[2].checked = true;
}
};
//create a bunch of checkboxes
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');

Related

Show div when all fields are filled

i am trying to show a div when all inputs are filled , but unfortunately it shows nothing here is my JS , it works on the JS FIDDLE but not on the website
$('#name, #prenom, #password,#confirm_password, #email,#confirm_email').bind('keyup', function() {
if(allFilled()) $('.next2').show();
});
function allFilled() {
var filled = true;
$('body input').each(function() {
if($(this).val() == '') filled = false;
});
return filled;
}
You can turn the jQuery collection into an an array and then use the native JS array method every to check to see if all the inputs contain values.
const inputs = $('input');
inputs.on('keyup', function() {
const notEmpty = inputs.toArray().every(input => {
return input.value !== '';
});
if (notEmpty) {
$('div').show();
} else {
$('div').hide();
}
});
div { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input />
<input />
<input />
<input />
<div>All the values!</div>

prevent users from entering duplicate entries in text inputs in javascript

I have a DOM in which I want to prevent users from entering duplicate entries in html text input.
The above DOM is not in user's control. It is coming through php.
At this moment, I am focussing only on name="code[]".
This is what I have tried:
$(function(){
$('input[name^="code"]').change(function() {
var $current = $(this);
$('input[name^="code"]').each(function() {
if ($(this).val() == $current.val())
{
alert('Duplicate code Found!');
}
});
});
});
Problem Statement:
I am wondering what changes I should make in javascript code above so that when a duplicate code is entered, alert message "Duplicate code Found" should come up.
you need to add an eventlistener to each item, not an eventlistener for all. Then count inputs with same value, if there's more than 1, it's a duplicate.
Also ignore not-filled inputs.
Check following snippet:
$('input[name*="code"]').each(function() {
$(this).change(function(){
let value = $(this).val();
let count = 0;
$('input[name*="code"]').each(function() {
if ($(this).val() != '' && $(this).val() == value) {
count++;
if (count > 1) alert('duplicate');
}
});
});
$(this).addClass('e');
});
$('#createInput').on('click', function(){
let newInput = document.createElement("input");
newInput.name = 'code[]';
newInput.type = 'text';
newInput.className = 'whatever';
$('#inputGroup').append(newInput);
// repeat the eventlistener again:
$('input[name*="code"]:not(.e').each(function() {
$(this).change(function(){
let value = $(this).val();
let count = 0;
$('input[name*="code"]').each(function() {
if ($(this).val() != '' && $(this).val() == value) {
count++;
if (count > 1) alert('duplicate');
}
});
});
$(this).addClass('e');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="inputGroup">
<input name="code-1" type="text" class="whatever">
<input name="code-2" type="text" class="whatever2">
<input name="code-3" type="text" class="whatever3">
</div>
<input type="button" id="createInput" value="Add input">
Edit:
now works with dynamically created elements. The class 'e' works as flag to not insert 2 event listeners to the same node element, otherwise they will run in cascade, provoking unwanted behaviour.
You can use something like this, that converts the jQuery object to an Array to map the values and find duplicates. I added an option to add a style to the duplicated inputs, so the user knows which ones are duplicated.
function checkDuplicates(){
var codes = $('input[name^="code"]').toArray().map(function(element){
return element.value;
})
var duplicates = codes.some(function(element, index, self){
return element && codes.indexOf(element) !== index;
});
return duplicates;
}
function flagDuplicates(){
var inputs = $('input[name^="code"]').toArray();
var codes = inputs.map(function(element){
return element.value;
});
var duplicates = 0;
codes.forEach(function(element, index){
var duplicate = element && codes.indexOf(element) !== index;
if(duplicate){
inputs[index].style.backgroundColor = "red";
inputs[codes.indexOf(element)].style.backgroundColor = "red";
duplicates++
}
});
return duplicates;
}
$('input[name^="code"]').on("change", function(){
//var duplicates = checkDuplicates(); // use this if you only need to show if there are duplicates, but not highlight which ones
var duplicates = flagDuplicates(); // use this to flag duplicates
if(duplicates){
alert(duplicates+" duplicate code(s)");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="code-1" type="text">
<input name="code-2" type="text">
<input name="code-3" type="text">

Validating different types of form inputs with criterias

I want to get the answers to a form upon submission and parse them to JSON.
This works quite good but I want some validation before sending the data.
I tried a lot of variations of the snippet down below but am still stuck.
Steps:
Prevent default event on "send"
Get Form
Iterate through the elements of the form
Eliminate empty items and their value
If checkbox is checked: value = true
Store correct items in data
Return data
Somehow I can't get to work steps 4 and 5 work at the same time, every time I get one of them to work I screw over the other one.
In this snippet, the checkbox works as intented but the textfield doesn't:
If anybody can point me in the right direction with the if/else statements or something like that it would be greatly appreciated.
document.addEventListener('DOMContentLoaded', function(){
var data = {};
var formToJSON = function formToJSON(form) {
var data = {};
for (var i = 0; i < form.length; i++) {
var item = form[i];
//looking for checkbox
if (item.value =="") {
continue;
}
else {
if (item.checked == false) {
data[item.name] = false;
}
else {
data[item.name] = item.value;
}
}
}
return data; };
var dataContainer = document.getElementsByClassName('results__display')[0];
form = document.getElementById('formular').querySelectorAll('input,select,textarea');
butt = document.getElementById('knopfabsenden');
butt.addEventListener('click', function (event) {
event.preventDefault();
handleFormSubmit(form = form);
});
var handleFormSubmit = function handleFormSubmit(event) {
var data = formToJSON(form);
dataContainer.textContent = JSON.stringify(data, null, " ");
}
}, false);
<div id="formular">
<label class="formular__label" for="machineName">Textfield Test</label>
<input class="formular__input formular__input--text" id="machineNumber" name="machineNumber" type="text"/>
<br>
<input class="formular__input formular__input--checkbox" id="checkTest" name="checkTest" type="checkbox" value="true"/>
<label class="formular__label formular__label--checkbox" for="checkTest">Checkbox Test</label>
<br>
<button class="formular__button" id="knopfabsenden" type="submit">Submit</button>
</div>
<div class="results">
<h2 class="results__heading">Form Data</h2>
<pre class="results__display-wrapper"><code class="results__display"></code></pre>
</div>
The problem is .checked will always be false if it doesn't exist. So the text field gets the value false.
for (var i = 0; i < form.length; i++) {
var item = form[i];
//looking for checkbox
if (item.value ==="") {
continue;
}
else {
if (item.type === "text") {
data[item.name] = item.value;
}
else if (item.type === "checkbox"){
data[item.name] = item.checked;
}
}
}
In this code snippet I check the type of the input and handle it accordingly. also notice I use the === operator and not the == operator as a best practice (Difference between == and === in JavaScript)

Add another condition to Show/Hide Divs

I have the follow script on a form.
jQuery(document).ready(function($) {
$('#bizloctype').on('change',function() {
$('#packages div').show().not(".package-" + this.value).hide();
});
});
</script>
Basically, depending on the value of the select box #bizloctype (value="1","2","3" or "4") the corresponding div shows and the rest are hidden (div class="package-1","package-2","package-3", or "package-4"). Works perfectly.
BUT, I need to add an additional condition. I need the text box #annualsales to be another condition determining which div shows (if the value is less than 35000 then it should show package-1 only, and no other packages.
I think the below script works fine when independent of the other script but I need to find out how to marry them.
<script>
$("#annualsales").change(function(){
$(".package-1,.package-2,.package-3,.package-4").hide();
var myValue = $(this).val();
if(myValue <= 35000){
$(".package-1").show();
}
else
{
$(".package-2").show();
}
});
</script>
Help please?
I would remove the logic from the anonymous functions and do something like this:
// handle display
function displayPackage( fieldID ) {
var packageType = getPackageType(fieldID);
$('#packages div').show().not(".package-" + packageType).hide();
}
// getting the correct value (1,2,3 or 4)
function getPackageType( fieldID ) {
// default displayed type
var v = 1;
switch(fieldID) {
case 'bizloctype':
// first check it annualsales is 1
v = (getPackageType('annualsales') == 1) ?
1 : $('#' + fieldID).val();
break;
case 'annualsales':
v = (parseInt($('#' + fieldID).val(),10) <= 35000) ? 1 : 2;
break;
}
return v;
}
jQuery(document).ready(function($) {
$('#bizloctype,#annualsales').on('change',function() {
displayPackage($(this).attr('id'));
});
});
If I understand your question properly, try this code out. It first adds an onChange listener to #annualsales which is the code you originally had. Then, for the onChange listener for #bizloctype, it simply checks the value of #annualsales before displaying the other packages.
jQuery(document).ready(function($) {
// Check value of #annualsales on change
$("#annualsales").change(function(){
$(".package-1,.package-2,.package-3,.package-4").hide();
var myValue = $(this).val();
if(myValue <= 35000){
$(".package-1").show();
}
// Only show other packages if value is > 35000
$('#bizloctype').on('change',function() {
$(".package-1,.package-2,.package-3,.package-4").hide();
if ($('#annualsales').val() <= 35000) {
$(".package-1").show();
} else {
$('#packages div').show().not(".package-" + this.value).hide();
}
});
});
Since you already use JQuery you can use the data() function to create a simple but dynamic condition system. For example, you could annotate each element with the required conditions and then attach change listeners to other elements to make the condition active or inactive for the elements.
For example, with this HTML:
<div id="conditions">
Condition 1: <input type="checkbox" id="check1" /> <= check this<br/>
Condition 2: <input type="checkbox" id="check2" /><br/>
Condition 3: <input type="text" id="value1" /> <= introduce 1001 or greater<br/>
Condition 4: <input type="text" id="value2" /><br/>
</div>
<p id="thing" data-show-conditions="check1 value1-gt-1000"
style="display: none;">
The thing to show.
</p>
And this Javascript:
function setShowCondition(el, condition, active) {
var conditions = $(el).data('conditions') || {};
conditions[condition] = active;
$(el).data('conditions', conditions);
var required = ($(el).data('show-conditions') || "").split(" ");
var visible = required.every(function (c) {
return conditions[c];
});
if (visible) {
$(el).show();
} else {
$(el).hide();
}
}
$("#conditions input[type='checkbox'").change(function () {
setShowCondition('#thing',
$(this).attr('id'),
$(this).is(':checked'));
});
$("#value1").change(function () {
var number = parseInt($(this).val());
setShowCondition('#thing', 'value1-gt-1000', number > 1000);
});
You can maintain conditions easily without having to nest and combine several if statements.
I've prepared a sample to show this in https://jsfiddle.net/2L5brd80/.

How to alert user for blank form fields?

I have this form that has 3 inputs and when a user leaves a field blank a dialogue box pops up to alert the user a field is blank. The code I have below only works for 2 specific input. When i try adding another input to the code it doesnt work. It only works for 2 inputs. How can I make it work for all three?
<script type="text/javascript">
function val(){
var missingFields = false;
var strFields = "";
var mileage=document.getElementById("mile").value;
var location=document.getElementById("loc").value;
if(mileage=='' || isNaN(mileage))
{
missingFields = true;
strFields += " Your Google Map's mileage\n";
}
if(location=='' )
{
missingFields = true;
strFields += " Your business name\n";
}
if( missingFields ) {
alert( "I'm sorry, but you must provide the following field(s) before continuing:\n" + strFields );
return false;
}
return true;
}
</script>
Showing 3 alerts may be disturbing, use something like this:
$(document).on('submit', 'form', function () {
var empty = $(this).find('input[type=text]').filter(function() {
return $.trim(this.value) === "";
});
if(empty.length) {
alert('Please fill in all the fields');
return false;
}
});
Inspired by this post.
Or you can do validation for each field this way using HTML data attributes:
<form data-alert="You must provide:" action="" method="post">
<input type="text" id="one" data-alert="Your Google Map's mileage" />
<input type="text" id="two" data-alert="Your business name" />
<input type="submit" value="Submit" />
</form>
... combined with jQuery:
$('form').on('submit', function () {
var thisForm = $(this);
var thisAlert = thisForm.data('alert');
var canSubmit = true;
thisForm.find('input[type=text]').each(function(i) {
var thisInput = $(this);
if ( !$.trim(thisInput.val()) ) {
thisAlert += '\n' + thisInput.data('alert');
canSubmit = false;
};
});
if( !canSubmit ) {
alert( thisAlert );
return false;
}
});
Take a look at this script in action.
Of course, you can select/check only input elements that have attribute data-alert (which means they are required). Example with mixed input elements.
You can add the required tag in the input fields. No jQuery needed.
<input required type="text" name="name"/>
Try this
var fields = ["a", "b", "c"]; // "a" is your "mile"
var empties= [];
for(var i=0; i<fields.length; i++)
{
if(!$('#'+fields[i]).val().trim())
empties.push(fields[i]);
}
if(empties.length)
{
alert('you must enter the following fields '+empties.join(', '));
return false;
}
else
return true;
instead of this
var name = $('#mile').val();
if (!name.trim()) {
alert('you must enter in your mile');
return false;
}

Categories

Resources