JQuery: Checkbox Chain not working properly - javascript

I have 'chain' of checkboxes (parent checkbox and childs), and problem is:
When first clicking on 'parent' checkbox it is working well, but after that when clicking on 'childs', the 'parent' checkbox then isn't doing what is supposed. Parent is checking/unchecking childs except the child which was pressed before.
Here is code:
JavaScript
checks_bind();
function checks_bind(){
$("#x_main").off('click');
$("#x_main").on('click',function(){
var obj = $(this);
var val = obj.is(':checked');
$("#checks").find("input[type='checkbox']").attr('checked',val);
});
}
HTML
<input id='x_main' type='checkbox'/>Main<br>
<p>--------------------------------</p>
<div id='checks'>
<input type='checkbox'/>1<br>
<input type='checkbox'/>2<br>
</div>
<p>--------------------------------</p>
<i>1 - Click on 1 or 2 <br>2 - Try <b>Main</b> checkbox. <br>
3 - Main checkbox isn't working</i>
jsfiddle example
And one more question:
Is it good to use .on('click.namespace') on checkboxes since it's working well? I can use .change() method, but I want to call .off('click.namespace') (or something to unbind) before .on() each time when calling the function.

As checked is a property, You need to use .prop() instead of .attr()
$("#checks").find("input[type='checkbox']").prop('checked', val);
Updated Fiddle, A good read .prop() vs .attr()
If you want to use .off() then its advisable to use namespaced event.

Try this: user 'prop' instead of attribute and you can check all or uncheck all as per checked condition of main check box.
Also, you can check the count of all checkbox to check /uncheck main checkbox. see below
Note: bind click handler when DOM is ready hence user $(document).ready or $(function(){})
$(function(){
$("#x_main").on("change", function(){
$("#checks").find("input[type='checkbox']").prop("checked",$(this).is(":checked"));
});
$("#checks input[type='checkbox']").on("change", function(){
var total = $("#checks").find("input[type='checkbox']").length;
var checked = $("#checks").find("input[type='checkbox']:checked").length;
$("#x_main").prop("checked",total==checked);
});
});
JSFiddle Demo

Related

Selecting all checked checkbox return all checkbox instead using JQuery

Here is my code jsfiddle
JS file
$( document ).ready(function() {
$(".test").children().filter(function(index, elem){
console.log($(elem).children(":checked"));
});
})
HTML
<ul class="test">
<li><input type="checkbox" name="1"><label>something</label></li>
<li><input type="checkbox" name="2"><label>something</label></li>
<li><input type="checkbox" name="3"><label>something</label></li>
<li><input type="checkbox" name="4" checked><label>something</label></li>
</ul>
I am trying to select all checked checkbox, but if I filtered by :checked I get all checkbox instead.
What am I doing wrong?
To be more precise
var allChecked = $('.test input[type="checkbox"]:checked');
get you all checked checkboxes under as child of element having class test and to test if checkbox is checked you can use
var bool = $(selector).is(":checked");
// return true if checked false if not
//where selector can be any jQuery selector
To select the checked inputs you simply need to use:
var checked = $("input:checked");
See the updated fiddle
If it must be limited to inputs within that ul only, you can specify the class as well:
var checked = $(".test input:checked");
See this fiddle to select all checked inputs in a given ul.
Other answers suggest better ways to select the checked checkbox you want, and I agree that those are more straight-forward methods and are preferable to your filtering approach, but here I try to explain what you're actually seeing in your code as you have it.
Going to your fiddle and running it in the Chrome debugger, it looks like it's doing the right thing, and you simply may not be seeing what you expect due to the behavior of console.log()
I split your console.log line to take two separate steps — get the child(ren) that match the :checked selector, then log that variable; so it looks like:
$( document ).ready(function() {
$(".test").children().filter(function(index, elem) {
//console.log($(elem).children(":checked"));
boxen = $(elem).children(":checked");
debugger;
console.log(boxen);
});
})
updated fiddle
This loops making the call to the filter() function four times — one for each of the originally selected $(".test").children() elements. On the first call, index will be 0 (zero) and elem will be the first <li> element.
Calling boxen = $(elem).children(":checked"); will give you [] ... that is, an empty array, since none of the children of that first li are checked.
However, when you console.log(boxen) it gives you some "weird" output because this is jQuery... it's not a plain javascript array.
When you get to the fourth iteration, looking at the fourth selected element, index will be 3 and elem will be that fourth <li>
When you $(elem).children(":checked") on that one, you'll get something like [<input type=​"checkbox" name=​"4" checked>​] (how you see it will depend some on your javascript debugger) — so this time it is selecting the one checked input element.
If you select .children(":checked") into a variable you are indeed getting the one checkbox you want, but the console.log() output is deceiving you.

Get value attribute of the clicked checkbox via JQuery

I have got this checkbox which has value 1.
<input type="checkbox" name="option_1" id="checkbox_1" value="1">
Also I use this method to make checked/unchecked it.
$('input[id^="checkbox_"]').not('#checkbox_all').click(function () {
$('#checkbox_all').prop('checked', false);
// Get 'VALUE' of the checkbox here
});
What I need is somehow get 'VALUE' of the clicked checkbox. So In that case it should be 1.
Any clue how do it could be done?
Thank you!
In your click method use this to get the value
$(this).attr("value");
$(this) is referencing to the object that has been clicked.
EDIT:
you could also use $(this).val(); but sometimes I had problems with elder versions of IE so I did recommend $(this).attr("value") in the first place.
​<html>
​<head>
​</head>
<body>
<input type="checkbox" name="option_1" id="checkbox_1" value="1">
</body>
​</html>​​​​​​​
$('input[id^="checkbox_"]').not('#checkbox_all').click(function () {
$('#checkbox_all').prop('checked', false);
alert($(this).val());
});​
http://jsfiddle.net/heten/
Working :)
I think you just need $(this).val(); in your click event.
Also, if you need to work with that value as an int later, use
var x = parseInt($(this).val(),10);
The val jQuery method should see you right.
$('#checkbox_all').val();
http://api.jquery.com/val/

How to use string argument of a function in a jQuery expression

I have some set of links and select boxes. My html code is below:
<div>
<div>
<a href='#' onclick='set_checked(false,"checkbox1")'>clear</a>
<a href='#' onclick='set_checked(true,"checkbox1")'>select</a>
</div>
<div>
<input type='checkbox' name='checkbox1'/>
</div>
</div>
<div>
<div>
<a href='#' onclick='set_checked(false,"checkbox2")'>clear</a>
<a href='#' onclick='set_checked(true,"checkbox2")'>select</a>
</div>
<div>
<input type='checkbox' name='checkbox2'/>
</div>
</div>
Now my requirement is when I click on select link I have to check the checkbox based on it's arguments, and reversal for clear. Here I'm passing two parameters. One is to pass Boolean value (i.e. if true check else uncheck) and another one is to pass name argument of a checkbox field. And I'm using the following function to check or uncheck a checkbox:
function set_checked(checked,inputFeildName){
$('input[name=inputFeildName]').attr('checked',checked);
}
but the above code is not working. And this is my fiddle http://jsfiddle.net/vu6fs/5/.
I have one more requirement, before selecting any checkbox all clear links have to be disabled, after selection of checkbox respective clear link have to be enable. I'm applying opacity and also 'disabled' property in JavaScript but it's not working,can anyone suggest me where my fault is.. Can anyone please help me?
jQuery 1.6+
function set_checked(checked,inputFeildName){
$('input[name="'+ inputFeildName +'"]').prop('checked',true);
}
jQuery 1.5 and below
function set_checked(checked,inputFeildName){
$('input[name="'+ inputFeildName +'"]').attr('checked','checked');
}
Here is an example for your extension of question (more you want, About disable/enable a tag on checkbox change)
CSS
.disButton {
background: transparent;
border: none;
}
.disButton a {
text-decoration: none;
color: #ddd;
}
jQuery
$('input:checkbox').on('change', function() {
enable_clear(this, this.checked);
}).change();
function enable_clear(el, checked) {
var target = $(el).parent('div').prev('div').find('a:contains(clear)');
if (checked) {
target.unwrap();
} else {
target.wrap($('<button/>', {
disabled: true,
'class': 'disButton',
width: target.width() + 'px'
}));
}
}
$('a').on('click', function(e) {
e.preventDefault();
var target = $(this).parent().next('div').find('input:checkbox');
if (!target.is(':checked') && $(this).text() == 'select') target.click();
if ($(this).text() == 'clear') target.click();
});
DEMO
I think this is what you are trying to do... btw you have misspelt field so be careful when using the variable/attr again.
function set_checked(checked,inputFeildName){
$('input[name="'+inputFeildName+'"]').attr('checked',checked);
}
you forget to append string that i did as below , this will resolve your issue
function set_checked(checked,inputFeildName)
{
$('input[name="'+ inputFeildName+'"]').attr('checked',checked);
}
There are some errors in your fiddle:
Your function set_checked is declared in the onLoad-Handler (as selected), and is only available in that locally and not in the global scope. Remove the wrapping function by selecting "no wrap (head)" or assign your function to window.set_checked.
Please note that the checked attribute only represents the default value of the checkbox, to change the actual state you need to use the checked property (with jQuery, you can use val()).
If you wanted to change the default value, you can't do it by setting the attribute to (the string) false. The attribute represents a checked checbox through its existence, you would need to use removeAttribute() for disabling. It's easier to use the defaultChecked property with a boolean value.
last but not least there's the obvious error detected by all others: To use a variable, you will need to use it instead of putting its name into a string (like in PHP).
You also might be more happy with ids than name attributes. I've updated your fiddle with a proper solution: http://jsfiddle.net/vu6fs/7/
To disable the clear/select link when it's not appropriate:
you can't disable a link (anchor) as you can a form element (see Disable link using javascript, jQuery disable a link, Disable link using css). OK, we don't really need to disable its functionality (nothing changes), so so I guess you only think of graying it out. This can be done with CSS, and you'll need to trigger the update both on user-change events and the setting through set_checked. Example code at http://jsfiddle.net/vu6fs/9/
It might be easier to use just one link that toggles the checked state. Its lettering may change between "clear" and "select", depending on the current state.
I now have written a plugin (i.e. a jQuery prototype function) to add those links dynamically to any checkbox elements. That means it also can use (scoped) click handlers instead of a global-scope-polluting set_checked function.
The function has a little error:
function set_checked(checked,inputFeildName){
$(**'input[name='+inputFeildName+']'**).attr('checked',checked);
}

getting individual atrributes while selecting a class with JQuery

I'm new to javascript and JQuery, and I'm working in a small project with JSP.
I create a grid dynamically with JSP and I added some buttons wich class is "select" and in the alt attribute I set the current row index. That works perfectly, I'm trying to set the onclick dynamically. This is my code
$('.select').click(function (){
alert($('.select').attr('alt'));
}
I want to each button to show its own index, but that code shows just the first index in each button. I've searched how to do it, but nothing comes out.
Is there a chance to do what I want?
change this line as:
alert($(this).attr('alt'));
When jQuery calls your event handler it sets this to be the DOM element in question, so try this:
$('.select').click(function (){
alert($(this).attr('alt'));
});
If you need to access DOM element properties you can then get them directly, e.g.:
alert( this.id );
this.value = "test";
If you need to use jQuery methods on the element you need to pass it to the jQuery function first, e.g.:
$(this).hide();
$(this).css("color","red").slideDown();
$('.select').click(function (){
alert($(this).attr('alt'));
});
Change
alert($('.select').attr('alt'));
by
alert($(this).attr('alt'));
Now you select the attr alt of the button lauch the event.
Not sure if that's what you're looking for but...
$('.select').click(function() {
$('.select').each(function() {
$(this).attr('value', $(this).attr('alt'));
});
});
This'll have every button "show" the value stored within their alt attribute when you click one button.
By the way, if you're using 1 button per row, you'd probably better go with index().

Dynamically check / uncheck checkboxes in a tree

I have a similar question to Uncheck parent node if all children unchecked in JQuery (with this solution) and have tried to modify it so that the children will also all uncheck if the parent is unchecked (which the above/below fails to do).
JSFiddle for the above (http://jsfiddle.net/fRxVs/)
jQuery.each(jQuery('#treeList ul li').find(':checkbox'), function(){
jQuery(this).change(function (){
if (jQuery(this).is(':checked')) {
jQuery(this).parentsUntil('#treeList').siblings().filter('input:checkbox').attr('checked', true).trigger('change');
}else{
jQuery(this).parents('ul:first').siblings('input:checkbox').prop('checked', $(this).parent().siblings().children('input:checked').length).trigger('change');
}
});
});
Though I'm not sure why, but I had to change prop from the last line to attr in order for it to correctly work as JSFiddle locally for some reason...
Basically I have a 3 level setup:
Grand-Parent
- Parent
-- Child
If the grandparent is checked/unchecked, then its children and grandchildren should all be checked/unchecked too.
If the parent is checked/unchecked, its children should be checked/unchecked as well as its parent.
If the children are checked, then its parent and grandparent should be checked (if no children are checked then parent shouldn't be checked).
I'm trying to change this to Continent, Country, Region - I think you will understand if I were to just say this....
Thanks
Here's the solution: Fiddle: http://jsfiddle.net/fRxVs/55/
$('#treeList :checkbox').change(function (){
$(this).siblings('ul').find(':checkbox').prop('checked', this.checked);
if (this.checked) {
$(this).parentsUntil('#treeList', 'ul').siblings(':checkbox').prop('checked', true);
} else {
$(this).parentsUntil('#treeList', 'ul').each(function(){
var $this = $(this);
var childSelected = $this.find(':checkbox:checked').length;
if (!childSelected) {
$this.prev(':checkbox').prop('checked', false);
}
});
}
});
Modifications and explanations
$ is exactely the same as jQuery. Be consistent when using it: jQuery should only be used when you're not sure whether $ === jQuery (is $ overwritten?).
:checkbox is a selector which matches every input[type="checkbox"]. It's obsolete to specify input:checbkox, since a checkbox element is always an input element.
.find(..) seeks for any element which is a child (not necessery the direct child) of the matched selector. "#treeList :checkbox" is faster, and has the equivalent result as $('#treeList').find(':checkbox').
When a property/method/event is added to a jQuery object, all elements which match the selector will be modified. Therefore, you don't have to loop through each element individually: jQuery.each(jQuery('#treeList :checkbox'), function(){ jQuery(this).change(...)}) can be shortened to jQuery('#treeList :checkbox').change(...).
You don't have to trigger change after changing a checkbox check state, because the function already takes care of the full tree.
Old question but you could just do it like this:
$('input[type=checkbox]').change(function(){
$(this).next().find('input[type=checkbox]').prop('checked', this.checked);
$(this).parents('ul').prev('input[type=checkbox]').prop('checked', function(){
return $(this).next().find(':checked').length;
});
});
Fiddle: http://jsfiddle.net/ojc1qg1f/

Categories

Resources