I am trying to change the color of an LI when I click on it.
this is the code:
todosUl.addEventListener('click', function(event) {
//get the element that was clicked on
var elementClicked = event.target;
//check if the elemenClicked is a Delete button
if (elementClicked.className === 'completedButton') {
var element = document.getElementById(elementClicked.parentNode.id);
var lis = document.getElementById(element.id);
console.log(lis);
lis.style.color = "red";
}
});
When i put console.log(lis), the console gives the Li element, so it selects it properly when you click on the element, but it does not change the color of it.
when I inspect the Li, this is what appears:
<li class="li-class" id="0">( ) 1<input class="editor" id="editor0"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton0">X</button><button class="saveButton" id="saveButton0">save changes</button></li>
Your logic seems correct however you might want to consider another approach as shown in the code snippet below:
const todosUl = document.querySelector("ul.todos");
/* Select all li elements of todos ul, and set each up inside of
forEach callback */
todosUl.querySelectorAll("li.li-class").forEach((li) => {
/* Logic that changes li color when completed checkbox clicked */
const onClickCompleted = () => {
li.style.color = "red";
}
/* Bind click completed callback logic to the checkbox of this current li element */
li.querySelector("input.completedButton").addEventListener('click', onClickCompleted);
/* Bind click logic for other buttons of li element
li.querySelector("button.deleteButton").addEventListener('click', onClickDeleted);
li.querySelector("button.saveButton").addEventListener('click', onClickSave);
*/
});
<ul class="todos">
<li class="li-class">( ) 1<input class="editor">
<input type="checkbox" class="completedButton">
<button class="deleteButton" class="deleteButton">X</button>
<button class="saveButton" class="saveButton">save changes</button>
</li>
<li class="li-class">( ) 2<input class="editor">
<input type="checkbox" class="completedButton">
<button class="deleteButton" class="deleteButton">X</button>
<button class="saveButton" class="saveButton">save changes</button>
</li>
</ul>
This method takes advantage of document queries that are relative to each li element of your list. The benifit of this is that event logic binding is not reliant on specific element id's (ie deleteButton0, editor1, etc), which tends towards more maintainable code in the long term. Hope that helps!
You can catch the clicks on the parent ul and if it is the li itself or one of it's children color it:
const ulElement = document.querySelectorAll('ul')[0];
ulElement.addEventListener('click', function (event) { // catch all click event on parent ul
if (!event.target || !event.target.parentElement) {return} // if the click not on li or one of the child ignore it
else if (event.target.parentElement.classList.contains('li-class')) { // if clicked element's parent is li with the class
event.target.parentElement.style.color = 'red';
}
else if (event.target.classList.contains('li-class')) { // if clicked element is li with the class
event.target.style.color = 'red'
}
}, false);
<ul>
<li class="li-class" id="0">( ) 1<input class="editor" id="editor0"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton0">X</button><button class="saveButton" id="saveButton0">save changes</button></li>
<li class="li-class" id="1">( ) 1<input class="editor" id="editor1"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton1">X</button><button class="saveButton" id="saveButton1">save changes</button></li>
<li class="li-class" id="2">( ) 1<input class="editor" id="editor2"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton2">X</button><button class="saveButton" id="saveButton2">save changes</button></li>
</ul>
OLD ANSWER:
I guess there are lot of ways achieve this behavior, this solution catchs all clicked events and if it .li-class itself, or a child of this class - change the color.
Snippet:
document.addEventListener('click', function (event) { // catch all click event on the documnt
if (!event.target || !event.target.parentElement) {return} // if the click is on the document ignore it
else if (event.target.parentElement.classList.contains('li-class')) { // if clicked element's parent is li with the class
event.target.parentElement.style.color = 'red';
}
else if (event.target.classList.contains('li-class')) { // if clicked element is li with the class
event.target.style.color = 'red'
}
}, false);
<ul>
<li class="li-class" id="0">( ) 1<input class="editor" id="editor0"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton0">X</button><button class="saveButton" id="saveButton0">save changes</button></li>
<li class="li-class" id="1">( ) 1<input class="editor" id="editor1"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton1">X</button><button class="saveButton" id="saveButton1">save changes</button></li>
<li class="li-class" id="2">( ) 1<input class="editor" id="editor2"><input type="checkbox" class="completedButton"><button class="deleteButton" id="deleteButton2">X</button><button class="saveButton" id="saveButton2">save changes</button></li>
</ul>
Related
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>
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>
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>
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/
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);
});