Sequentially enabling fieldsets in a form - javascript

I know how to enable next fieldset in a sequence when fieldsets have id attributes:
function enableFieldset(element) {
document.getElementById(element).disabled = false;
}
<fieldset id="foo" onchange="enableFieldset('bar', event)">
<label><input type="radio" name="foo">Apples</label>
<label><input type="radio" name="foo">Oranges</label>
</fieldset>
<fieldset id="bar" disabled>
<label><input type="radio" name="bar">Bus</label>
<label><input type="radio" name="bar">Airplane</label>
</fieldset>
…
I would like to enable the next sibling fieldset in a multi-step form, that has no set id (by using .nextElementSibling or similar), after input is checked in the current fieldset. I would also like to separate JavaScript from HTML code (with addEventListener).

You can attach the change event listener to all the fieldsets by selecting them using document.querySelectorAll. This will separate the JS code from HTML.
In the event handler, you can get the next sibling, which is disabled, and enable it. Use nextElementSibling for that.
document.querySelectorAll('fieldset').forEach(fs => {
fs.addEventListener('change', function() {
var next = this.nextElementSibling;
while (next && !next.disabled) {
next = next.nextElementSibling;
}
if (next) {
next.disabled = false;
}
});
})
<fieldset id="foo">
<label><input type="radio" name="foo">Apples</label>
<label><input type="radio" name="foo">Oranges</label>
</fieldset>
<fieldset id="bar" disabled>
<label><input type="radio" name="bar">Bus</label>
<label><input type="radio" name="bar">Airplane</label>
</fieldset>
<fieldset id="bar" disabled>
<label><input type="radio" name="x">Bus1</label>
<label><input type="radio" name="x">Airplane1</label>
</fieldset>
<fieldset id="bar" disabled>
<label><input type="radio" name="y">Bus2</label>
<label><input type="radio" name="y">Airplane2</label>
</fieldset>

Related

jQuery Selectors or 'if' trouble

This code should prohibit clicking more than two radiobuttons in total (there are three groups of such buttons).
This works when there is no container 'label', but when it is, it doesn't work (it looks like that 'if' construct is not working; everything that is written outside of it works fine)
how to make it work without removing the label? Is there any solutions?
var radio_limit = 2;
$('.pricing-levels-3 label input').on('change', function(evt) {
if($(this).siblings(':checked').length >= radio_limit) {
this.checked = false;
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="pricing-levels-3">
<p><strong>Select 2 Levels</strong></p>
<label>
<input type="radio" name="vehicle" value="1">Level 1<br>
<input type="radio" name="vehicle" value="2">Level 2<br>
<input type="radio" name="vehicle" value="3">Level 3<br>
</label>
<label>
<br>
<input type="radio" name="vehicle2" value="1">Level 1<br>
<input type="radio" name="vehicle2" value="2">Level 2<br>
<input type="radio" name="vehicle2" value="3">Level 3<br>
</label>
<label>
<br>
<input type="radio" name="vehicle3" value="1">Level 1<br>
<input type="radio" name="vehicle3" value="2">Level 2<br>
<input type="radio" name="vehicle3" value="3">Level 3<br>
<br>
</label>
</div>
You are looking for siblings, which they were without labels. Now with labels they are not sibling they are cousins. To fix we read all radio buttons in same div using closest(). Also use prop to check a radio button. Do this:
var radio_limit = 2;
$('.pricing-levels-3 label input').on('change', function(evt) {
if($(this).closest('div').find('input:checked').length >= radio_limit) {
$(this).prop('checked', false);
};
});

jQuery multi-row form: disable submit until each row has a radio checked

I have a multi-row form with single choice radio buttons in each row. I'd like the final <button> tag to be disabled until a radio button as been checked from each row.
I currently have a solution from a previous question (jQuery multi-step form: disable 'next' button until input is filled in each section) that removes the disabled attribute from the button when you select any radio button but i'd like to be more specific if possible.
Is this possible? Here's a Codepen of what I'm working on currently: https://codepen.io/abbasarezoo/pen/vdoMGX - as you can see when hit any radio in any row the disabled attribute comes off.
HTML:
<form>
<fieldset>
<div class="radio-group">
<h2>Select one answer per row</h2>
<h3>Row 1</h3>
<label for="radio-1">Radio 1</label>
<input type="radio" id="radio-2" name="radio-row-1" />
<label for="radio-2">Radio 2</label>
<input type="radio" id="radio-2" name="radio-row-2" />
<label for="radio-3">Radio 3</label>
<input type="radio" id="radio-3" name="radio-row-3" />
</div>
<div class="radio-group">
<h3>Row 2</h3>
<label for="radio-4">Radio 1</label>
<input type="radio" id="radio-4" name="radio-row-4" />
<label for="radio-5">Radio 2</label>
<input type="radio" id="radio-5" name="radio-row-5" />
<label for="radio-6">Radio 3</label>
<input type="radio" id="radio-6" name="radio-row-6" />
</div>
<button disabled>Next</button>
</fieldset>
</form>
jQuery:
$('fieldset input').click(function () {
if ($('input:checked').length >= 1) {
$(this).closest('fieldset').find('button').prop("disabled", false);
}
else {
$('button').prop("disabled", true);
}
});
You need to specify the same name for the radio button group so that only one radio button is selected per row. Then, you can simply compare the length of the checked radio button with the length of the radio button group like this,
$('fieldset input').click(function () {
var radioLength = $('.radio-group').length;
if ($('input:checked').length == radioLength) {
$('fieldset button').prop("disabled", false);
}
else {
$('button').prop("disabled", true);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<fieldset>
<div class="radio-group">
<h2>Select one answer per row</h2>
<h3>Row 1</h3>
<label for="radio-1">Radio 1</label>
<input type="radio" id="radio-2" name="radio-row-1" />
<label for="radio-2">Radio 2</label>
<input type="radio" id="radio-2" name="radio-row-1" />
<label for="radio-3">Radio 3</label>
<input type="radio" id="radio-3" name="radio-row-1" />
</div>
<div class="radio-group">
<h3>Row 2</h3>
<label for="radio-4">Radio 1</label>
<input type="radio" id="radio-4" name="radio-row-2" />
<label for="radio-5">Radio 2</label>
<input type="radio" id="radio-5" name="radio-row-2" />
<label for="radio-6">Radio 3</label>
<input type="radio" id="radio-6" name="radio-row-2" />
</div>
<button disabled>Next</button>
</fieldset>
</form>

jQuery - Add combinations to the string and repeat this for many input fields of a form

I have a form where I request a lot of data for a join table in cakePHP3.5 project. The string consists of combinations of factors A, B, C and D separated by space. For example: BD AC ABCD AD B CD. I found out how to compose this string for the one such field.
First I write a required combination to textbox Result, then use Add button to stitch them together.
How to repeat this for many without writing a long jQuery? Basically I need to repeat what is below 50 times, but I cannot find proper selectors for all these multiple checkboxes. Checkbox 1 down there is for illustrating purposes to emphasize that I will have different checkboxes and many such input fields.
This is my first jQuery, so please, be patient :)
$(document).ready(function() {
$('.factor-checkbox').click(function() {
var text = $('#result0');
text.val('');
$(".factor-checkbox:checked").each(function() {
text.val(text.val() + $(this).val());
});
});
$("#btn0").click(function(){
var text1 = $('#combinations0');
text1.val(text1.val() + ' ' + $('#result0').val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" name="A" value="A" class="factor-checkbox">A</label>
<label><input type="checkbox" name="B" value="B" class="factor-checkbox">B</label>
<label><input type="checkbox" name="C" value="C" class="factor-checkbox">C</label>
<label><input type="checkbox" name="D" value="D" class="factor-checkbox">D</label>
<label for="result0">Result </label><input type="text" id="result0"/>
<button type="button" id="btn0">Add</button>
<div class="input checkbox"><label for="items-0-id"><input type="checkbox" name="items[0][id]" value="1" id="items-0-id">1</label></div>
<div class="input text"><label for="Combinations">Combinations</label><input type="text" id="combinations0"/></div>
I would suggest to:
Wrap each repeating block (each with 4 checkboxes, ...etc) in a separate container element: that will facilitate to address the different elements that belong together.
Don't use id attributes where not necessary: for labels you don't need them when you wrap the input inside the label element. Instead use class names. This will facilitate the generation of all the 50 blocks
In each event handler determine the section the click happened in, and then use that as the scope of every other jQuery selection you do (by using the second argument of $() -- or .find().
Here is working snippet with two such blocks:
$(function() {
function mapValues(elem) {
return $(elem).val();
}
$(".factor-checkbox").click(function() {
var $section = $(this).closest(".section");
var $text = $(".result", $section);
$text.val($.map($(".factor-checkbox:checked", $section), mapValues).join(""));
});
$(".add").click(function() {
var $section = $(this).closest(".section");
var $combi = $(".combinations", $section);
$combi.val(($combi.val() + " " + $(".result", $section).val()).trim());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="section">
<label><input type="checkbox" name="A" value="A" class="factor-checkbox">A</label>
<label><input type="checkbox" name="B" value="B" class="factor-checkbox">B</label>
<label><input type="checkbox" name="C" value="C" class="factor-checkbox">C</label>
<label><input type="checkbox" name="D" value="D" class="factor-checkbox">D</label>
<label>Result <input type="text" class="result"></label>
<button type="button" class="add">Add</button>
<div class="input text">
<label>Combinations <input type="text" class="combinations"></label>
</div>
</div>
<div class="section">
<label><input type="checkbox" name="A" value="A" class="factor-checkbox">A</label>
<label><input type="checkbox" name="B" value="B" class="factor-checkbox">B</label>
<label><input type="checkbox" name="C" value="C" class="factor-checkbox">C</label>
<label><input type="checkbox" name="D" value="D" class="factor-checkbox">D</label>
<label>Result <input type="text" class="result"></label>
<button type="button" class="add">Add</button>
<div class="input text">
<label>Combinations <input type="text" class="combinations"></label>
</div>
</div>

Make only 2 checkboxes checked per form

I have multiple forms in one page with the same input names. The only difference between forms is the forms that contain them.
For the groups of checkboxes on my form, I only want to allow two checkboxes out of three to be checked but I don't want the checkboxes in one form to affect another.
I have a jsFiddle of what I have now.
I have it setup now that only two checkboxes can be checked out of three but that's for the entire document, not form specific.
The forms in my page are created with a loop and the id of the form is the only difference between them.
Anyone able to help with this?
https://jsfiddle.net/likwidmonster/3zbs61q5/
$('input[type=checkbox][name=group]').on('change', function(e) {
if ($('input[type=checkbox][name=group]:checked').length < 2) {
$('input[type=checkbox][name=group]:not(:checked)').prop('disabled', false);
}
if ($('input[type=checkbox][name=group]:checked').length == 2) {
$('input[type=checkbox][name=group]:not(:checked)').prop('disabled', 'disabled');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>
Form 1
</h4>
<form id="form_1">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
<div>
<h4>
Form 2
</h4>
<form id="form_2">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
Since your forms are dynamic maybe this will be of better use.
I did create a jsfiddle and post it in the comment but that's only good for those two forms. Maybe you want to add more? JSFiddle Demo
this.parentNode.id;
this is used to target the element triggering the function, .parentNode is used to get the form element and .id is used to get the ID of the form so you can target that specific form meaning you only need one if condition to run this for all the forms!
$('form input[type=checkbox][name=group]').on('change', function(e) {
var MyForm=this.parentNode.id;
if ($('form[id='+MyForm+'] input[type=checkbox][name=group]:checked').length == 2) {
$('form[id='+MyForm+'] input[type=checkbox][name=group]:not(:checked)').prop('disabled', 'disabled');
}else{
$('form[id='+MyForm+'] input[type=checkbox][name=group]:not(:checked)').prop('disabled', false);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>
Form 1
</h4>
<form id="form_1">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
<div>
<h4>
Form 2
</h4>
<form id="form_2">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
If you have any questions please leave a comment below and I will get back to you as soon as possible.
I hope this help. Happy coding!
Here's a working solution. Hope it helps!
$('input[type=checkbox][name=group]').on('change', function(e) {
if ($('#form_1 input[type=checkbox][name=group]:checked').length === 2) {
$('#form_1 input[type=checkbox][name=group]:not(:checked)').prop('disabled', 'disabled');
}else{
$('#form_1 input[type=checkbox][name=group]:not(:checked)').prop('disabled', false);
}
if ($('#form_2 input[type=checkbox][name=group]:checked').length === 2) {
$('#form_2 input[type=checkbox][name=group]:not(:checked)').prop('disabled', 'disabled');
}else{
$('#form_2 input[type=checkbox][name=group]:not(:checked)').prop('disabled', false);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div>
<h4>
Form 1
</h4>
<form id="form_1">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
<div>
<h4>
Form 2
</h4>
<form id="form_2">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
Use a function to initialize your event handler for each group. Also use a different group name.
https://jsfiddle.net/3zbs61q5/3/
function setupCheckboxGroup(grpName){
$('input[type=checkbox][name='+grpName+']').on('change', function(e) {
if ($('input[type=checkbox][name='+grpName+']:checked').length < 2) {
$('input[type=checkbox][name='+grpName+']:not(:checked)').prop('disabled', false);
}
if ($('input[type=checkbox][name='+grpName+']:checked').length == 2) {
$('input[type=checkbox][name='+grpName+']:not(:checked)').prop('disabled', 'disabled');
}
});
}
setupCheckboxGroup('group');
setupCheckboxGroup('group2');
<div>
<h4>
Form 1
</h4>
<form id="form_1">
<input type="checkbox" name="group" value="1">
<input type="checkbox" name="group" value="2">
<input type="checkbox" name="group" value="3">
</form>
</div>
<div>
<h4>
Form 2
</h4>
<form id="form_2">
<input type="checkbox" name="group2" value="1">
<input type="checkbox" name="group2" value="2">
<input type="checkbox" name="group2" value="3">
</form>
</div>

Two groups of checkboxes, if first one is checked second can not be

I have two "groups" of checkboxes (although the first group only contains one checkbox), but if user checks the checkbox from the first group I want to restrict the ability of checking the checkboxes from second group...
<div>
<h3>First group</h3>
<label>
<input type="checkbox" value="1" name="group1" />If checked, checks all the checkboxes in 2nd group</label>
<label>
</div>
<div>
<h3>Second Group</h3>
<label>
<input type="checkbox" class="radio" value="1" name="group2" />1</label>
<label>
<input type="checkbox" class="radio" value="1" name="group2" />1</label>
</div>
<div>
<h3>First group</h3>
<label>
<input type="checkbox" value="1" name="group1" id='Grp1'/>If checked, checks all the checkboxes in 2nd group</label>
<label>
</div>
<div>
<h3>Second Group</h3>
<label>
<input type="checkbox" class="radio Grp2" value="1" name="group2" />1</label>
<label>
<input type="checkbox" class="radio Grp2" value="1" name="group2" />1</label>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$('#Grp1').change(function() {
if($(this).is(":checked"))
{
$('.Grp2').prop('disabled', true);
}
else
{
$('.Grp2').prop('disabled', false);
}
});
</script>
I've used a simple jQuery script to solve it.
initially it didn't exactly do what I wanted it to do, but I've managed to work around it with php as I had to make sure that if someone checked the checkbox from the second group that it didn't go to the database.
$('#checkbox1').click(function() {
if( $(this).is(':checked')) {
$("#checkbox2").hide();
} else {
$("#checksbox2").show();
}
});
As for php I simply used a ternary operator to make sure that if checkbox with id checkbox1 is checked then I want to ignore the rest of the checkboxes...
$smnrs = !empty($_POST['all']) ? explode(';', $_POST['all']) : $_POST['seminars'];
in this case $_POST['all'] refers to the first checkbox that if clicked it hides the div holding the other checkboxes.

Categories

Resources