How to uncheck only one checkbox in list of checkboxes? - javascript

I have a list of products that will get checked if I click select all. What I want to do is when all the checkboxes are checked and I uncheck just one checkbox, it should only uncheck the clicked element not all of the elements.
$('#selectAll').change(function () {
$('#pfilters li input').prop('checked', this.checked);
});

Do you mean like that?
$('#selectAll').change(function () {
$('#pfilters li input').prop('checked', this.checked);
});
function isAllSelected() {
return $('#pfilters li input').length === $('#pfilters li input:checked').length;
}
$('#pfilters li input').on('change', function() {
$('#selectAll').prop('checked', isAllSelected());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<ul>
<li>
<label><input type="checkbox" id="selectAll"/>Select All</label>
</li>
</ul>
<ul id="pfilters">
<li><label><input type="checkbox">Select Product 1</label></li>
<li><label><input type="checkbox">Select Product 2</label></li>
<li><label><input type="checkbox">Select Product 3</label></li>
</ul>
</form>

Related

Issue with 'click' function in 'each' loop

Basically, I have multiple UL's with a class "list". Each of them has multiple radio buttons. I would like to do something with span element upon the last radio option of individual UL's being checked. And undo it after another radio button of that same UL is being checked.
The code essentially works but it is triggering for all of the UL's instead of the one in which the click occurred.
I used alert (which is commented out) to check if I'm getting everything with 'each' and it seems to work fine.
$(document).ready(function() {
$('ul.list').each(function() {
//alert($(this).text());
$("ul.list input[type$='radio']").click(function() {
if ($("li:last-of-type input[type$='radio']").prop("checked")) {
// do something with span
} else {
// do something with span
}
});
});
});
<ul class="list">
<li><input type="radio">Option 1</input>
</li>
<li><input type="radio">Option 2</input>
</li>
<li><input type="radio">Bonus</input><span>Bonus text</span></li>
</ul>
<ul class="list">
<li><input type="radio">Option 1</input>
</li>
<li><input type="radio">Option 2</input>
</li>
<li><input type="radio">Bonus</input><span>Bonus text</span></li>
</ul>
Actually you don't need the loop in this case just attach the click directly to the selector :
$(document).ready(function() {
$("ul.list :radio").click(function() {
if ( $(this).prop("checked") )
{
// do something with span
} else {
// do something with span
}
});
});
NOTE 1 : The input are self-closing tags so thsy should be like :
<input type="radio"/>Option 1
Instead of :
<input type="radio">Option 1</input>
NOTE 2 : Use this keyword to target the clicked element instead :
if( $(this).prop("checked") ){
Hope this helps.
$(document).ready(function() {
$("ul.list :radio").change(function() {
if ( !$(this).is(':last-child') && $(this).is(":checked") )
{
$(this).closest("ul").find('span').show();
}else{
$(this).closest("ul").find('span').hide();
}
});
});
ul.list li>span{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list">
<li><input type="radio" name="same_name_1" checked/>Option 1</li>
<li><input type="radio" name="same_name_1" />Option 2</li>
<li><input type="radio" name="same_name_1" />Bonus<br><span>Bonus text</span></li>
</ul>
<ul class="list">
<li><input type="radio" name="same_name_2" checked/>Option 1</li>
<li><input type="radio" name="same_name_2" />Option 2</li>
<li><input type="radio" name="same_name_2" />Bonus<br><span>Bonus text</span></li>
</ul>

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>

finding the order of which checkboxes have been checked

I'm trying to get the order of which checkboxes have been checked.
<ul class="dropdown-content checkboxes">
<li><label><input type="checkbox" />Billy</label></li>
<li><label><input type="checkbox" />Jacob</label></li>
<li><label><input type="checkbox" />Bob</label></li>
<li><label><input type="checkbox" />Alexandren</label></li>
<li><label><input type="checkbox" />Erren</label></li>
<li><label><input type="checkbox" />Stewgart</label></li>
<li><label><input type="checkbox" />Jillian</label></li>
<li><label><input type="checkbox" />Other</label></li>
</ul>
I came up with this but i'm unable to get the order of when the checkboxes were checked. I'm only able to get the list of which ones are checked only.
$(":checkbox").click(function() {
console.log($(":checked").length);
var i = 0;
checked = true;
$(':checkbox').each(function() {
if (this.checked == false) {
i++;
if (i === 8) {
checked = false;
}
}
});
});
How would I get the data of what order they were checked? for instance "Checkboxes 1, 6, 3 ,2 were checked in this order"
You'll have keep track of what checkboxes are checked, for instance in an array
var order = [];
$("[type=checkbox]").on('change', function() { // always use change event
var idx = order.indexOf(this);
if (idx !== -1) { // if already in array
order.splice(idx, 1); // make sure we remove it
}
if (this.checked) { // if checked
order.push(this); // add to end of array
}
// <------------------------------------For demonstration
$('#result').html(JSON.stringify($.map(order, function(elem) {
return $(elem).closest('label').text().trim();
})));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="dropdown-content checkboxes">
<li><label><input type="checkbox" />Billy</label></li>
<li><label><input type="checkbox" />Jacob</label></li>
<li><label><input type="checkbox" />Bob</label></li>
<li><label><input type="checkbox" />Alexandren</label></li>
<li><label><input type="checkbox" />Erren</label></li>
<li><label><input type="checkbox" />Stewgart</label></li>
<li><label><input type="checkbox" />Jillian</label></li>
<li><label><input type="checkbox" />Other</label></li>
</ul>
<div id="result"></div>
To get the index of each checkbox, or more accurately the parent LI, you could just map them
var map = $.map(order, function(elem) {
return $(elem).closest('li').index();
});
FIDDLE
You can do it in pure JavaScript too:
var result = document.getElementById('result');
var order = [];
[].forEach.call(document.querySelectorAll('input[type="checkbox"]'), function (checkbox) {
'use strict';
checkbox.addEventListener('change', function () {
var previousLi = checkbox.parentNode.parentNode.previousElementSibling;
var index = 0;
while (previousLi !== null) {
previousLi = previousLi.previousElementSibling;
index += 1;
}
if (checkbox.checked) {
order.push(index);
} else {
order.splice(order.indexOf(index), 1);
}
result.textContent = order;
});
});
<ul class="dropdown-content checkboxes">
<li><label><input type="checkbox"/>Billy</label></li>
<li><label><input type="checkbox"/>Jacob</label></li>
<li><label><input type="checkbox"/>Bob</label></li>
<li><label><input type="checkbox"/>Alexandren</label></li>
<li><label><input type="checkbox"/>Erren</label></li>
<li><label><input type="checkbox"/>Stewgart</label></li>
<li><label><input type="checkbox"/>Jillian</label></li>
<li><label><input type="checkbox"/>Other</label></li>
</ul>
<p id="result"></p>
In the above code, for each checkbox we invoke function, which on it's change will:
get index of our input's li in it's parent,
either
add it at the end of an array on check, or
remove appropriate element of an array on uncheck, and
present an array (for demonstration purposes).
You would need to bind to the checkboxes being clicked, and push to an array some information corresponding to the checkboxes, then search through the array, their position would be the order in which they were checked.

How to delete list of checked item from a specific list

I have here 2 ul list which contains inside two lists of items and 2 delete buttons. I use here only one button click function for both delete buttons and I would like to have something like: when the user checks the items in the List 1 then only the items in the List 1 will be deleted after pressing the delete button no matter items in List 2 are checked or not and vice versa. Because now I can use the delete button in List 1 to delete items in List 2. What I have read on the internet is after pressing the delete button I might use something call: $(event.currentTarget).parent() to get the exact content list belongs to this button and then process inside of this list. Am I right?
$(document).ready(function() {
$("#delete").click(function() {
var deleteItem = [];
$("input:checkbox").each(function() {
var $this = $(this);
if ($this.is(":checked")) {
deleteItem.push($this.attr("name"));
}
});
if (deleteItem != []) {
if (deleteItem.indexOf("cbox1") > -1 && deleteItem.indexOf("cbox2") > -1) {
$("#box1").remove();
$("#box2").remove();
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>List 1
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button id="delete">Delete</button>
</ul>
<ul>List 2
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button id="delete">Delete</button>
</ul>
As I mentioned in my comment, you should use a class instead of id's because id's must be unique.
Here is a Fiddle Demo.
JQUERY:
$('.delete').click(function() {
var items = $(this).parent('ul').find('input:checked');
items.closest('li').remove();
});
When an element with the class 'delete' is clicked, it finds the parent ul and then looks for checked inputs. Once those are found, it looks for the closest li for those inputs and removes them.
HTML:
<ul>List 1
<li class="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li class="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li class="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button class="delete">Delete</button>
</ul>
<ul>List 2
<li class="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span></li>
<li class="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span></li>
<li class="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span></li>
<button class="delete">Delete</button>
</ul>
OP asked how to find the name of the checked inputs. Here is one way to do it:
$('.delete').click(function() {
var items = $(this).parent('ul').find('input:checked');
//iterate over objects and log the name
$.each(items, function( index, value ) {
console.log($(this).attr('name'));
});
items.closest('li').remove();
});
I've added an iterator which will go through the objects in items and output the name attribute to the console (F12 in most browsers). Here is an updated Fiddle Demo.
Note :Id must be unique. If you are tending to use same Id convert that to a class
Working Demo
$(document).ready(function() {
$(".delete").click(function() {
var deleteItem = [];
$("input:checkbox").each(function() {
var $this = $(this);
if ($this.is(":checked")) {
$(this).parent().parent().remove()
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>List 1
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span>
</li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span>
</li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span>
</li>
<button class="delete">Delete</button>
</ul>
<ul>List 2
<li id="box1"><span><input type="checkbox" name="cbox1" value="1" />Visit W3Schools1.com!</span>
</li>
<li id="box2"><span><input type="checkbox" name="cbox2" value="2" />Visit W3Schools2.com!</span>
</li>
<li id="box3"><span><input type="checkbox" name="cbox3" value="3" />Visit W3Schools3.com!</span>
</li>
<button class="delete">Delete</button>
</ul>
Yeah you are right in the use of .parent() jquery method. If i understand what you trie to do, you can maybe improve your code in this way :
$(document).ready(function() {
$("#delete").click(function() {
var parentUl = $(this).parent(); // get the parent url of the clicked button
var li_items = parentUl.find('li'); // get the li in the parent ul
li_items.each(function() { // for each li retrieved
if ($(this).children('input:checkbox').is(':checked')) // if the input is checked
$(this).remove(); // we remove it
});
});
Hope it helps ! :)
EDIT :
As other says, you should use a class instead of an id. per definition, an id should be considers as an unique block identifier in your html. in your case, you have 2 buttons so it's better to do this : <button class="delete"></button>

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