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>
Related
I have radio button
Html code:
<input type="radio" class="first" name="bright" checked>
<input type="radio" class="second" name="bright" >
<input type="radio" class="third" name="bright">
<input type="radio" class="four" name="bright">
And i have a nav bar
Html code
<ul class="nav">
<li class="st st1 active" data-cont="first">
<h2 class="inner">وزارة الاستثمار</h2>
</li>
<li class="st st2" data-cont="second">
<h2 class="inner">وزارة التجارة</h2>
</li>
<li class="st st3" data-cont="third">
<h2 class="inner">جهات حكومية اخرى</h2>
</li>
<li class="st st4" data-cont="four">
<h2 class="inner">مكتب هندسي</h2>
</li>
</ul>
These 2 are conected with the data-cont that have the class of the radio button
I want when i click on the li the correct radio button be checked using javascript
I tried to make it using this code in JavaScript
let radio = document.querySelectorAll("input");
let radioArray = Array.from(radio);
let tabs = document.querySelectorAll(".nav li");
let tabsArray = Array.from(tabs);
tabsArray.forEach((ele) => {
ele.addEventListener("click", function (e) {
tabsArray.forEach((ele) => {
ele.classList.remove("active");
});
e.currentTarget.classList.add("active");
document.querySelector(e.currentTarget.dataset.cont).checked = true;
});
});
I try to remove the active class from li and put it on the li where i click then i want the radio button be checked
Any body can help me on this?
the last querySelector is where your code is failing you're not referencing the class for your input it needs to be document.querySelector('.' + e.currentTarget.dataset.cont).checked = true; note the "." prefix
Although that answers your question there is probably more value in pointing out that by changing your html markup to be a little more accessible you can eliminate the need for all of the javascript in your example
e.g.
input:checked + label {
color:Red;
}
<div><input type="radio" id="first" name="bright" checked>
<label for='first'>وزارة الاستثما</label>
</div>
<div>
<input type="radio" id="second" name="bright" >
<label for='second'>وزارة التجارة</label>
</div>
<div>
<input type="radio" id="third" name="bright">
<label for='third'>جهات حكومية اخرى</label>
</div>
<div>
<input type="radio" id="four" name="bright">
<label for='four'>مكتب هندسي</label>
</div>
The use of labels associated with your radio buttons is now significantly more accessible and you can drastically reduce a lot of your markup ( though to be accessible you would need to provide a more meaningful name for for attribute.
I have html code of dropdown choice with checkbox like this:
<ul id="channelFieldUL" class="dropdown-menu channelFieldUL">
<li class="sourceFieldRecordClass" onclick="goNext("account")">
<a class>
<label>
<input type="checkbox" value="account" class="apiFieldRecord" id="account0">" account "
</label>
</a>
</li>
...
//another li
<ul>
then the function :
function goNext(source){
//content
}
what i want to ask is, what do i need to put in the function to get all the <ul> option, and then uncheck the other options beside selected option?
P.S: i tried using .parent() or .closest, but it doesnt work (maybe because wrong usage)
you can use query selector to get the all the li elements inside ul element
like
let lis = document.getElementById('channelFieldUL').getElementsByTagName('li');
you can select the specific input of li element and can check and uncheck them like this
document.getElementById("checkbox").checked = true;
// Uncheck
document.getElementById("checkbox").checked = false;
This should work:
$('.apiFieldRecord').change(function() {
if (this.checked) {
$('.apiFieldRecord').not(this).prop('checked', false);
$(this).prop('checked', true);
}
})
li {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="channelFieldUL" class="dropdown-menu channelFieldUL">
<li class="sourceFieldRecordClass">
<a class>
<label>
<input type="checkbox" value="account" class="apiFieldRecord" id="account1">account 1
</label>
</a>
</li>
<li class="sourceFieldRecordClass">
<a class>
<label>
<input type="checkbox" value="account" class="apiFieldRecord" id="account2">account 2
</label>
</a>
</li>
<li class="sourceFieldRecordClass">
<a class>
<label>
<input type="checkbox" value="account" class="apiFieldRecord" id="account3">account 3
</label>
</a>
</li>
<ul>
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>
Posted a question on about the same project in the morning. After battling it for a while came up with a bit different approach.
Trying to build a filter. And the idea is that a filter checkboxes have matching id's with filtered items classes. So, once a filter item clicked, filtration is applied to item class. Classes (except for inditem) and ids are dynamic
simplified html of it
<div class="itemswrap">
<div class="inditem dynamic1"></div>
<div class="inditem dynamic2"></div>
<div class="inditem dynamic3"></div>
<div class="inditem dynamic2"></div>
</div>
<ul class="subnav">
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic1" />
<label for="dynamic1">whatever label</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic2" />
<label for="dynamic1">whatever label</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic3" />
<label for="dynamic1">whatever label</label>
</li>
</ul>
js
$(".lifilter").each(function() {
var filter1 = $(this).find('.filtercheck').attr('id');
if ( $(this).find('.filtercheck').attr('checked') ) {
$(this).find('.filtercheck').click(function(){
$('.' + filter1).removeClass('checkeditem').hide();
});
}
else
{
$(this).find('.filtercheck').click(function(){
$('.inditem').hide();
$('.' + filter1).addClass('checkeditem');
});
}
});
and this one marked as important not to be hidden when extra items are added into filtration
.checkeditem {display:block !important}
Initial filtration works fine. But when I click on checked item the associated div does not hide.
Do you mean something like
var $filters = $('.filtercheck').change(function() {
var $items = $('.inditem').hide();
var filters = $filters.filter(':checked').map(function() {
return '.' + this.id;
}).get();
if (filters.length) {
$items.filter(filters.join()).show();
} else {
$items.show();
}
});
.checkeditem {
display: block !important
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="itemswrap">
<div class="inditem dynamic1">dynamic1</div>
<div class="inditem dynamic2">dynamic2</div>
<div class="inditem dynamic3">dynamic3</div>
<div class="inditem dynamic2">dynamic2</div>
</div>
<ul class="subnav">
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic1" />
<label for="dynamic1">whatever label</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic2" />
<label for="dynamic1">whatever label</label>
</li>
<li class="lifilter">
<input type="checkbox" class="filtercheck" id="dynamic3" />
<label for="dynamic1">whatever label</label>
</li>
</ul>
The problem with the code is that the event handler attaches the second click event on the first successful case. This means that the "click" on the checkbox is being given the "addclass" case, and all subsequent clicks are being handled by that handler instead of the intended one.
Using the same HTML. I created this:
$(document).ready(function() {
$(".filtercheck").click(function(){
$('.inditem').hide();
var filter1 = $(this).attr('id');
$('.' + filter1).toggleClass('checkeditem');
});
});
which I think is the intended behavior? Instead of individually attaching click handlers, I simply attached a single handler to all of them. It would be fairly easy to do something like
$(this).prop()
to determine if the currently clicked on item had was active or not. For this simple example, I opted to just use a class toggle to illustrate the point.
I have this script that runs when a user selects an element in a dropdown list:
<script type="text/javascript">
var seSelection = [];
$(document).ready(function() {
$(".dropdown-menu input").click(function() {
var value = $(this).val();
$(this).closest("#seButton").data();
if (this.checked) {
seSelection.push(this.value);
}
});
console.log("se equals " + seSelection);
});
</script>
<button id ="seButton" data-toggle="dropdown" class="btn btn-primary dropdown-toggle">
Options<span class="caret"></span>
</button>
<ul class="dropdown-menu noclose">
<li>
<input type="checkbox" id="ex3_1" name="ex3" value="A" checked="">
<label for="ex3_1">Option 1</label>
</li>
<li>
<input type="checkbox" id="ex3_2" name="ex3" value="B">
<label for="ex3_2">Option 2</label>
</li>
<li>
<input type="checkbox" id="ex3_3" name="ex3" value="C">
<label for="ex3_3">Option 3</label>
</li>
</ul>
I'm using the Twitter Bootstrap noclose, so dropdown-menu stays open until I click out of it. This is designed to allow a user to select multiple options. So as I select various options, my console looks like this, as the script fires on each click:
se equals
se equals A
se equals A,B
se equals A,B,C
This is great - and it's functioning properly, but in the same dropdown, if I deselect C after I have selected it, it doesn't REMOVE c as a value from the array seSelection.
I'm not sure how to write the code that does the inverse of what my script's code above does since I can't find any unclick(function) or unpush(this.value) that exists in jQuery.
How do I write this?
On unchecking you can remove the item from the array just like this http://jsfiddle.net/93zL0ae9/
<script type="text/javascript">
var seSelection = [];
$(document).ready(function(){
$(".dropdown-menu input").click(function() {
var value = $(this).val();
$(this).closest("#seButton").data();
if (this.checked) {
seSelection.push(this.value);
}
else
{
var index = seSelection.indexOf(this.value);
if(index>=0)
{
seSelection.splice(index,1);
}
}
console.log("se equals " + seSelection);
});
});
</script>
<button id ="seButton" data-toggle="dropdown" class="btn btn-primary dropdown-toggle">Options<span class="caret"></span></button>
<ul class="dropdown-menu noclose">
<li>
<input type="checkbox" id="ex3_1" name="ex3" value="A" checked="">
<label for="ex3_1">Option 1</label>
</li>
<li>
<input type="checkbox" id="ex3_2" name="ex3" value="B">
<label for="ex3_2">Option 2</label>
</li>
<li>
<input type="checkbox" id="ex3_3" name="ex3" value="C">
<label for="ex3_3">Option 3</label>
</li>
</ul>
</div>
It's because the instance is still being saved in your global variable, seSelection. I bet you if you unselect and then re-select an option it would show up twice.
It depends what your requirements are, but you probably instead want to generate that array of results from scratch after each click. You can do this by moving your var seSelection = []; line within the anonymous callback function, as well as that console.log statement.