I have this code which is working beautifully. It is just disabling a submit button if text input fields are empty.
$(document).ready(function() {
$('input[required]').on('keyup', function() {
var empty = false;
$('input[required]').each(function() {
var val = $(this).val().trim();
if (val.length == 0 || typeof val == 'undefined') {
empty = true;
}
})
if (empty) {
$('#register').css('opacity', '0.2').attr('disabled', 'disabled');
} else {
$('#register').css('opacity', '1').removeAttr('disabled');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" required>
<input type="text" required>
<button type="button" id="register">register</button>
However, I also have multiple checkbox groups on the page. They have different group names.
How can I also include a check in this code to check that all groups of checkboxes have at least 2 checkboxes selected?
CodePudding user response:
You could use plain JS this.checked
to check if the checkbox is checked and a simple counter:
var checked = 0;
if (this.checked) {
checked = 1;
}
Then you could instead of checking if (empty) {...}
, check if (checked < 2) {...}
.
Working example:
$(document).ready(function(){
$('input[type=checkbox][required]').on('change', function() {
var checked = 0;
$('input[type=checkbox][required]').each(function(){
if (this.checked) {
checked = 1;
}
});
if (checked < 2) {
$('#register').css('opacity', '0.2').attr('disabled', 'disabled');
} else {
$('#register').css('opacity', '1').removeAttr('disabled');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" name="test[]" required>
<input type="checkbox" name="test[]" required>
<button type="button" id="register">register</button>
If you also want to check this for multiple groups, you could first get all group names with an additional each()
loop:
var groups = [];
$('input[type=checkbox][required]').each(function() {
groups.push(this.name);
});
, filter out the duplicates:
groups = groups.filter( (x, i) => groups.indexOf(x) === i );
and then iterate over that group names, do the check like in the example above and count the checked groups:
var checked_groups = 0;
for (i = 0; i < groups.length; i ) {
...
if (checked > 1) {
checked_groups = 1;
}
}
At the end you wouldn't check for the true
var, but for:
if (checked_groups < groups.length) {...}
Working example:
$(document).ready(function() {
$('input[type=checkbox][required]').on('change', function() {
var groups = [];
$('input[type=checkbox][required]').each(function() {
groups.push(this.name);
});
groups = groups.filter( (x, i) => groups.indexOf(x) === i );
var checked_groups = 0;
for (i = 0; i < groups.length; i ) {
var checked = 0;
$('input[type=checkbox][required][name="' groups[i] '"]').each(function() {
if (this.checked) {
checked = 1;
}
});
if (checked > 1) {
checked_groups = 1;
}
}
if (checked_groups < groups.length) {
$('#register').css('opacity', '0.2').attr('disabled', 'disabled');
} else {
$('#register').css('opacity', '1').removeAttr('disabled');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" name="test[]" required>
<input type="checkbox" name="test[]" required>
<input type="checkbox" name="foo[]" required>
<input type="checkbox" name="foo[]" required>
<button type="button" id="register">register</button>
CodePudding user response:
Since you are using jQuery you can leverage that - could also use plain JavaScript.
Here is a slight mix of both. I leverage data attributes both in the code and in the CSS to manage the "2" - but this could also be altered to use true checkboxes, radio buttons etc. You mentioned checkboxes but all your inputs are text so I went with your code vs descriptions.
Lots of comments in the code that can and should be removed for a final version.
$(function() {
$('#register').on('set-allowed', function() {
let inputGroups = $('.check-wrapper');
let groupInputsWithValue = inputGroups.filter(function() {
return $(this).data("has-entry") == 'yes';
});
let hasNoEntry = !(inputGroups.length == groupInputsWithValue.length || groupInputsWithValue > 1);
//console.log("button:", hasNoEntry, inputGroups.length, groupInputsWithValue.length);
// use prop not attr
$(this).prop('disabled', hasNoEntry);
});
// use a change rather than a keyup to keep it less noisy
$('input[required]').on('change', function() {
let inputGroup = $(this).closest('.check-wrapper');
let groupCount = inputGroup.find('input[required]').length;
// now check all the inputs for a value
let groupInputsWithValue = inputGroup.find('input[required]').filter(function() {
let inputfield = $(this);
let val = inputfield.val().trim();
let notEmpty = val.length > 0;
return notEmpty;
});
let showGood = groupInputsWithValue.length > 0;
// we use attr here as .data() does show in the DOM and thus to CSS
//inputGroup.attr('data-has-entry', showGood ? 'yes' : 'no');
//native JavaScript dataset to do the same thing:
inputGroup.get(0).dataset.hasEntry = showGood ? 'yes' : 'no';
$('#register').trigger('set-allowed');
//console.log(!!groupInputsWithValue.length, groupInputsWithValue.length);
}).first().trigger("change");
});
.check-wrapper {
border: solid #ffbbbb 1px;
padding: 0.5rem;
background-color: #ffdddd;
}
.check-wrapper[data-has-entry='yes'] {
border: solid green 1px;
background-color: #ddffdd;
}
#register {
background-color: #ddffdd;
cursor: not-allowed;
border: solid #d1d1d1 1px;
cursor: crosshair;
opacity: 1;
}
#register:disabled {
background-color: #ffaaaa;
color: #000000;
cursor: not-allowed;
border: solid #ff0000 1px;
opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<input type="text" required>
<input type="text" required>
</div>
<div >
<input type="text" required>
<input type="text" required>
</div>
<div >
<input type="text" required>
<input type="text" required> <input type="text" required>
</div>
<div >
<input type="text" required>
<input type="text" required>
</div>
<button type="button" id="register">register</button>