jQuery: get descendants doesn't work - javascript

I'm currently trying to code a nested checkbox. I already figured out to get the parent checkbox of a child checkbox, but whatever I try it doesn't work to get it vice versa.
I already tried to it with .children(), .find() etc, which works only when it comes to something else than a checkbox. When $(this) is a the object of a checkbox, it won't give me the previous element. How can I access to the first descendants object? Thank you !
HTML:
<ul class='main'>
<li><input type="checkbox" name="settings_overview" value="overview">Settings
<ul class="sub">
<li><input type="checkbox" name="delete" value="add">Add device</li>
<li><input type="checkbox" name="add" value="delete">Delete device</li>
</ul>
</li>
</ul>
JS:
$(document).ready(function () {
$('input:checkbox').click(function () {
var child = $(this).find(':first'); // not working
var parent = $(this).closest("ul").siblings('input:checkbox'); // works
console.log(parent);
console.log(child);
});
});
https://jsfiddle.net/v36xyfdn/11/

There are different scenerios, and those above code won't work at all times, and you might have to do fallbacks if it doesn't.
I've made the changes, perhaps this is what you were trying to achieve:
HTML:
<ul class='main'>
<li><input type="checkbox" name="settings_overview" value="overview">Settings
<ul class="sub">
<li><input type="checkbox" name="delete" value="add">Add device</li>
<li><input type="checkbox" name="add" value="delete">Delete device</li>
</ul>
</li>
</ul>
JS:
$(document).ready(function () {
$('input:checkbox').click(function () {
var nextUl = $(this).next("ul"); // not working
var children = nextUl.find("input:checkbox");
// if the clicked element was the child, then we won't get any children using above method
if(children.length == 0){
children = $(this).parents(".sub").find("input:checkbox");
}
var parent = $(this).closest("ul").siblings('input:checkbox'); // works
// Works
//console.log(parent);
//console.log(children);
// If there's a parent, then that means we're in the child
if(parent.length){
var activeChildren = 0;
children.each(function(){
if($(this).is(":checked"))
activeChildren++;
});
if(activeChildren == children.length){
parent.prop("checked", true);
} else {
parent.prop("checked", false);
}
}
// if the clicked element doesn't have any parent, means we clicked on the parent checkbox
if(parent.length == 0){
if($(this).is(":checked")){
children.each(function(){
$(this).prop("checked", true);
});
} else {
children.each(function(){
$(this).prop("checked", false);
})
}
}
});
});
JSFiddle: https://jsfiddle.net/v36xyfdn/14/

Related

How can I check if a specific input type is checked?

I have two checkbox forms in my HTML-template, one of them allows multiple options and the other one only allows one option to be selected.
I am trying to limit the first checkbox form to only allow 2 boxes, but the current code affects both checkbox forms.
I can't use id or name since these are generated by the DB, id_something1, id_something2 etc.
How do people use to tackle this issue?
Current JS
<script>
$('input[type=checkbox]').on('change', function (e) {
if ($('input[type=checkbox]:checked').length > 2)) {
$(this).prop('checked', false);
}
});
</script>
The form I am trying to limit to 2 checkboxes
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<label>Test</label></label><input type="checkbox" name="orange" id="id_orange" checked>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<label>Test2</label><input type="checkbox" name="banana" id="id_banana" checked>
</div>
</li>
Second form that also gets affected
<ul id="id_someform">
<li>
<label for="id_someform_1"></label><input type="checkbox name="someForm" value=1" id="id_someform_1"
</li>
<li>
<label for="id_someform_2"></label><input type="checkbox name="someForm" value=2" id="id_someform_2"
</li>
</ul>
Limit the scope of your inner selector to the surrounding form:
$('input[type=checkbox]').change(function() {
const form = $(this).closest('form');
if ( form.find('input[type=checkbox]:checked').length > 2) ) {
$(this).prop('checked', false);
}
});
Note that I've simplified your syntax with jQuery's change() method.
<script>
$('input[type=checkbox]').on('change', function (e) {
if ($('input[type=checkbox]:checked').length > 2)) {
$(this).prop('checked', false);
}
});
</script>
The above code snippet will listen for all checkbox events, instead, use different id property on your checkbox and change the selector to use the id of the checkbox you'd want to listen for the event, eg
<script>
$('input#id_orange').on('change', function (e) {
if ($('input[type=checkbox]:checked').length > 2)) {
$(this).prop('checked', false);
}
});
</script>
If the form is different you can try replacing the following line:
$('input[type=checkbox]').on('change', function (e) {
with:
$('#form-id input[type=checkbox]').on('change', function (e) {
or:
$('form.class input[type=checkbox]').on('change', function (e) {
or any other parent element that is different from one form to another.
For example:
$('#form-id input[type=checkbox]').on('change', function (e) {
if ( $('#form-id input[type=checkbox]:checked').length > 2 ) {
$(this).prop('checked', false);
}
});
I have tested it and it works for me.

Jquery onclick function called two time on dynamically added button element

I have created a code on my HTML page that their multiple checkboxes and created one button dynamically in js snippet for performing some event, but when I clicked on the button to perform that even that, then it's making calls to that event snippet two times. I wanted to know how to add the event to that button.
Here is the js code:-
$(".panel-body").on("click", '#select_none', function(event) {
$("input[name='nodelevel']:checkbox").each(function() {
this.checked = false;
});
});
Make sure there is only one parent with .panel-body class name. maybe there is two of .panel-body and it makes this happen. like this:
<div class="panel-body">
...
<div class="panel-body">
...
<!-- your selectors -->
</div>
</div>
try stoppropagation to avoid second parent event listener call:
$(".panel-body").on("click", '#select_none', function(event) {
event.stopPropagation();
$("input[name='nodelevel']:checkbox").each(function() {
this.checked = false;
});
});
EDIT : and of course you can add listener to document instead of .panel-body :)
Example:
<input class="itemClass" type="checkbox" name="Items" value="Bike"> I have a bike<br>
<input class="itemClass" type="checkbox" name="Items" value="Car" checked> I have a car<br>
<button name="submit" onclick="getValue()" value="Submit">
Then:
function getValue() {
var id;
var name;
var temp = [];
$('.itemClass').each(function () {
var sThisVal = (this.checked ? $(this).val() : "");
console.log(sThisVal);
if (this.checked) {
// $("input[name=Items]:checked").map(function () {
temp.push(sThisVal);
}
});
console.log(temp);
$('.itemCheckboxClass').prop('checked', false);
}

checkbox javascript doesnt work in asp.net

I need to check the checkbox status for my web in ASP.Net but I can't get the javascript work:
<li>
<a id="link" href="/ControlHoras">Control Horas</a>
<input onchange="favButton()" name="checkbox" type="checkbox" id="ControlHoras"/>
</li>
function favButton() {
if ($(this).is(":checked")) {
var id = this.id;
alert('checked');
} else {
alert('unchecked');
}
};
this in favButton will be the window, not the clicked checkbox, as you're using an outdated onchange event attribute.
You can improve your code and avoid the issue by attaching your event handler using an unobtrusive event handler, like this:
$('#ControlHoras').change(function() {
if ($(this).is(":checked")) {
var id = this.id;
alert('checked');
} else {
alert('unchecked');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<a id="link" href="/ControlHoras">Control Horas</a>
<input name="checkbox" type="checkbox" id="ControlHoras" />
</li>
</ul>
<li>
<a id="link" href="/ControlHoras">Control Horas</a>
<input onclick="favButton()" name="checkbox" type="checkbox" id="ControlHoras"/>
</li>
The proper way to get the caller/sender is through the event argument. In fact Firefox ignores events if they don't have the event argument.
function favButton(event) {
if ($(event.currentTarget).is(":checked")) {
var id = event.currentTarget.id;
alert('checked');
} else {
alert('unchecked');
}
};

Prevent parent category radio button from being clicked

I've got this function/script that converts the checkboxes into radio buttons (in the Categories metabox), but I need to extend the functionality a little but I'm unsure how to go about it.
The script:
function convert_root_cats_to_radio() {
global $post_type;
?>
<script type="text/javascript">
jQuery("#categorychecklist>li>input").each(function(){
this.disabled = "disabled";
});
jQuery("#categorychecklist>li>ul>li>input").each(function(){
this.disabled = "disabled";
});
jQuery("#categorychecklist>li>label input").each(function(){
this.type = 'radio';
});
jQuery("#categorychecklist>li>ul>li>label input").each(function(){
this.type = 'radio';
});
// Hide the 'most used' tab
jQuery("#category-tabs li:odd").hide();
</script> <?php
}
add_action( 'admin_footer-post.php', 'convert_root_cats_to_radio' );
add_action( 'admin_footer-post-new.php', 'convert_root_cats_to_radio' );
What is needed now: to prevent users from selecting a parent category.
In the image shown below for example, you should be able to select anything except Bandicoot, because Bandicoot is a parent (it has children). Oh and the children items for Bandicoot are allowed to be selected.
So the rule should be: if you're a parent you can't be selected, but your children can.
Depends on how your output html looks you can make it in one of below options:
jQuery("#categorychecklist > li > ul").each(function(){
jQuery(this).parent('li').children('label').children('input').attr('disabled', true);
});
or:
jQuery("#categorychecklist > li > ul").each(function(){
jQuery(this).prev('label').children('input').attr('disabled', true);
});
or even better, remove radio:
jQuery("#categorychecklist > li > ul").each(function(){
jQuery(this).prev('label').children('input').remove();
});
Please check the comment in the script code.
$(function() {
$('input[type=radio]').on('click', function() {
//assumes that radio button > wrapped around a label > wrapped around li
var liObj = $(this).parent().parent();
if (liObj != undefined && $(liObj).is('li') && $(liObj).has('ul').length > 0) {
return false;
}
});
})
ul {
list-style: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='test'>
<li>
<label>
<input type='radio' name='cat' />1</label>
</li>
<li>
<label>
<input type='radio' name='cat' />2</label>
</li>
<li>
<label>
<input type='radio' name='cat' />3</label>
<ul>
<li>
<label>
<input type='radio' name='cat' />3-1</label>
</li>
<li>
<label>
<input type='radio' name='cat' />3-2</label>
<ul id='test'>
<li>
<label>
<input type='radio' name='cat' />3-2-1</label>
</li>
<li>
<label>
<input type='radio' name='cat' />3-2-2</label>
</li>
</ul>
</li>
</ul>
</li>
</ul>

Jquery Check parent checkboxes in nested ul li

I have a script that will check and uncheck all children checkboxes in a nested list. I am now trying to get it so I can check a low level checkbox and it will check all the parents only back up to the highest level. Here is a JSFiddle
<ul class="tree" id="tree">
<li><input type="checkbox" name="account_settings" value="yes">Account Settings <!-- AND SHOULD CHECK HERE -->
<ul>
<li><input type="checkbox" name="one" value="one">AS One</li>
<li><input type="checkbox" name="two" value="two">AS Two</li>
<li><input type="checkbox" name="user_roles" value="user_roles">Users & Roles <!-- SHOULD CHECK HERE -->
<ul>
<li><input type="checkbox" name="user_role" value="add">Add</li>
<li><input type="checkbox" name="user_role" value="delete">Delete</li> <!-- CHECK HERE -->
</ul>
</li>
</ul>
</li>
<li><input type="checkbox" name="rl_module" value="yes">RL Module</li>
<li><input type="checkbox" name="rl_module" value="yes">Accounting
<ul>
<li><input type="checkbox" name="vat" value="yes">VAT</li>
<li><input type="checkbox" name="bank_account" value="yes">Banking
<ul>
<li><input type="checkbox" name="view" value="yes">View</li>
<li><input type="checkbox" name="crud" value="yes">CRUD</li>
</ul>
</li>
</ul>
</li>
</ul>
And the corresponding javascript:
$('input[type=checkbox]').click(function(){
// if is checked
if($(this).is(':checked')){
// check all children
$(this).parent().find('li input[type=checkbox]').prop('checked', true);
// check all parents
$(this).parent().prev().prop('checked', true);
} else {
// uncheck all children
$(this).parent().find('li input[type=checkbox]').prop('checked', false);
}
});
It looks like you want something like this
$('input[type=checkbox]').click(function(){
if(this.checked){ // if checked - check all parent checkboxes
$(this).parents('li').children('input[type=checkbox]').prop('checked',true);
}
// children checkboxes depend on current checkbox
$(this).parent().find('input[type=checkbox]').prop('checked',this.checked);
});
FIDDLE
If you want to check up and down hierarchy - you can do it like this
$('input[type=checkbox]').click(function(){
// children checkboxes depend on current checkbox
$(this).next().find('input[type=checkbox]').prop('checked',this.checked);
// go up the hierarchy - and check/uncheck depending on number of children checked/unchecked
$(this).parents('ul').prev('input[type=checkbox]').prop('checked',function(){
return $(this).next().find(':checked').length;
});
});
FIDDLE
This should do it:
$('input[type=checkbox]').click(function () {
$(this).parent().find('li input[type=checkbox]').prop('checked', $(this).is(':checked'));
var sibs = false;
$(this).closest('ul').children('li').each(function () {
if($('input[type=checkbox]', this).is(':checked')) sibs=true;
})
$(this).parents('ul').prev().prop('checked', sibs);
});
jsFiddle example
Latest update handles up and down the hierarchy, and siblings.
Just use jquery.parents(). It is somewhat similar to find() except it searches all parents. Something like this might be close to what you are looking for:
$(this).parents('li').each(function() {
$(this).children('input').prop('checked', true);
});
See http://api.jquery.com/parents/ for more information.
EDIT: Alright, here is a solution that works:
http://jsfiddle.net/3y3Pb/12/
EDIT2: And a more streamlined solution here:
http://jsfiddle.net/3y3Pb/14/
Have a JSFiddle: http://jsfiddle.net/3y3Pb/16/
I would recommend adding a parent attribute to the checkboxes. This parent attribute will reference the parent checkbox's id so that you don't have to worry about your structure changing:
$('input type=[checkbox]').change(function () {
$('#' + $(this).attr('parent')).prop('checked', this.checked);
});
Ex:
<input type="checkbox" name="account_settings" value="yes" id="as">Account Settings
<ul>
<li><input type="checkbox" name="one" value="one" parent="as" id="one">AS One</li>
You can use prevAll() also
I have the same issue. In my case there are multiple checkboxes in li with labels, and each checkbox above target have class parent (generated in js)
$(this).parents().prevAll('input:checkbox.parent').each(function () {
$(this).attr('checked', true);
});

Categories