Ok, so I really don't think I'm structuring my JS properly, and am hoping someone can point me in the right direction. I don't think sequentially naming the classes for each list item is an effective, or proper way of accomplishing this.
I have a list of checkboxes that, when clicked, need to perform two actions:
1) Toggle the class name of a div located directly below it.
2) Post via AJAX the state.
Here is my current markup:
<ol class="toolkitList">
<li>
<label><input class="inlineCheckers" type="checkbox" id="checkers" onchange="setCheck();" /><b id="grayTitle">List Title 1</b></label>
<i id="hiddenDiv">Div content can go here.</i>
</li>
<li>
<label><input class="inlineCheckers" type="checkbox" id="checkers2" onchange="setCheck2();" /><b id="grayTitle2">List title 2</b></label>
<i id="hiddenDiv2">Div content can go here.</i>
</li>
<li>
<label><input class="inlineCheckers" type="checkbox" id="checkers3" onchange="setCheck3();" /><b id="grayTitle3">List title 3</b></label>
<i id="hiddenDiv3">Div content can go here.</i>
</li>
<li>
<label><input class="inlineCheckers" type="checkbox" id="checkers4" onchange="setCheck4();" /><b id="grayTitle4">List Title 4</b></label>
<i id="hiddenDiv4">Div content can go here.</i>
</li>
</ol>
Here is my current JS:
function setCheck() {
var el = document.getElementById("checkers");
if (el.checked) {
document.getElementById("hiddenDiv").className = "main";
document.getElementById("grayTitle").className = "titleGray";
} else {
document.getElementById("hiddenDiv").className = "";
document.getElementById("grayTitle").className = "";
}
}
function setCheck2() {
var el2 = document.getElementById("checkers2");
if (el2.checked) {
document.getElementById("hiddenDiv2").className = "main";
document.getElementById("grayTitle2").className = "titleGray";
} else {
document.getElementById("hiddenDiv2").className = "";
document.getElementById("grayTitle2").className = "";
}
}
function setCheck3() {
var el3 = document.getElementById("checkers3");
if (el3.checked) {
document.getElementById("hiddenDiv3").className = "main";
document.getElementById("grayTitle3").className = "titleGray";
} else {
document.getElementById("hiddenDiv3").className = "";
document.getElementById("grayTitle3").className = "";
}
}
function setCheck4() {
var el4 = document.getElementById("checkers4");
if (el4.checked) {
document.getElementById("hiddenDiv4").className = "main";
document.getElementById("grayTitle4").className = "titleGray";
} else {
document.getElementById("hiddenDiv4").className = "";
document.getElementById("grayTitle4").className = "";
}
}
I realize I don't have the AJAX portion of this setup yet, but I wanted to make that requirement known, as I will be adding that part into the code shortly. Thanks for any guidance you can provide!
This is how I would do it:
$toolkitlist.on( 'change', '.inlineCheckers', function () {
$( this ).closest( 'li' ).toggleClass( 'checked', this.checked );
});
where $toolkitlist is a jQuery object containing the OL element. Notice how I set the class on the LI element, because that is the outermost element which represents the checked item. You can use these selectors to style the "checked" states:
/* how they look like initially */
.grayTitle { ... }
.hiddenDiv { ... }
/* how they look like when their check-box is checked */
li.checked .grayTitle { ... }
li.checked .hiddenDiv { ... }
use jQuery's addClass
$('#grayTitle3').addClass('titleGray');
Update, using ^=:
$('[id^=grayTitle]').addClass('titleGray');
You could also apply the class to outer div
CSS:
.selected label b {
color:blue
}
.selected i {
color:red
}
JS:
$(".inlineCheckers").on('click',function(){
$(this).parents("li").toggleClass('selected',$(this).is(":checked"));
})
jsfiddle : http://jsfiddle.net/y2rHF/3/
remove the inline .onchange.. and bind the change event to your class .inlineCheckers - then you can usethis` so you don't have to make multiple functions for each set
$('.inlineCheckers').on('change', function {
$el = $(this);
var $hd = $el.closest('label').next('i');
var $gt = $el.next('b');
$hd.toggleClass('main', $el[0].checked);
$gt.toggleClass('checkers', $el[0].checked);
}
http://jsfiddle.net/KYzgB/
Related
I would like to display creating product in admin section sub categories in tree only when selected else closed in woocommerce product categoreis. How can I achieve this ? Presently it appears like this. Tried css but didn't work.
<li id="tire_sizes-52"><label class="radiall"><input value="52" type="checkbox" name="tax_input[tire_sizes][]" id="in-tire_sizes-52"> 145</label><ul class="children">
<li id="tire_sizes-62"><label class="radiall"><input value="62" type="checkbox" name="tax_input[tire_sizes][]" id="in-tire_sizes-62"> 65</label> <ul class="children">
<li id="tire_sizes-87"><label class="radiall"><input value="87" type="checkbox" name="tax_input[tire_sizes][]" id="in-tire_sizes-87"> 15</label></li>
</ul>
</li>
</ul>
</li>
I want it closed and open only if selected
// if a checkbox has a child, add a css class="has-children"
// select them
const parents = document.querySelectorAll('.has-children')
const caches = parents.map(() => ([]))
function clear(parent) {
const id = parent.getAttribute('id');
const ul = parent.querySelector('.children');
ul.css.display = 'none'; // hide from the DOM
// you may also need to remove it from the DOM
/*
children = [];
while (parent.firstChild) {
const firstChild = parent.firstChild
parent.removeChild(firstChild)
caches[id].push(firstChild);
}*/
}
// inital setup
parents.forEach(function (parent) {
const id = parent.getAttribute('id');
clear(parent);
// setup listen for changes to parents
parent.addEventListener('change', function() {
let child;
if (child = parent.querySelector('children')) {
if (child.css.display === 'block') {
clear(parent)
} else {
//caches[this.getAttribute('id')].forEach(c =>
// this.appendChild(c)
delete caches[this.getAttribute('id')]
const ul = parent.querySelector('.children');
ul.css.display = 'block'; // show from bom
}
});
})
something like this. Checkout jquery it may be easier
If this is right, please give me points, i'm a nooob
I haven't executed this code , so it will need your attentions. but that is the essance of it. As I say. look into jquery. This can be accomplished in 3 lines of code.
Hi sorry in advance if this has already been asked but I can't find the answer.
I have a set of links that trigger certain ids to show onclick, it works but the one link is suppose to trigger 2 ids to show. My javascript knowledge is not great. Thanks for any help.
Here is my codepen https://codepen.io/louise-fourie/pen/abVdwyZ
<li>
Fitness & Wellness
</li>
<li>
Business
</li>
<li>
Arts & Entertainment
</li>
</ul>
<div class="articles">
<div id="el-57d5b6f71db32029">fitness</div>
<div id="el-e881a23a64890108">business</div>
<div id="el-65ebd7b2380005a1">art</div>
</div>
<script>
var divs = ["el-57d5b6f71db32029", "el-e881a23a64890108", "el-65ebd7b2380005a1"];
var visibleId = null;
function show(id) {
for(i = 0; i < divs.length; i++) {
if(visibleId !== id) {
visibleId = id;
}
}
hide();
}
function hide() {
var div, i, id;
for(i = 0; i < divs.length; i++) {
id = divs[i];
div = document.getElementById(id);
if(visibleId === id) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
</script>
There is something fishy with your show-hide logic.
Check out my suggestion below, where you can pass an array of IDs, which you want to show. All other elements will be hidden.
function onClick(elements) {
document.querySelectorAll('.articles div').forEach(articleDiv => articleDiv.style.display = 'none');
elements.forEach(element => {
const domEl = document.querySelector('#' + element)
domEl.style.display = 'block';
})
}
<ul>
<li>
Fitness & Wellness
</li>
<li>
Business
</li>
<li>
Arts & Entertainment
</li>
</ul>
<div class="articles">
<div id="fitness">fitness</div>
<div id="business">business</div>
<div id="art">art</div>
</div>
<script>
</script>
Your function seems to be running, but every time you receive an ID in your function, you hide everything else with the "hide" function, so in the end, the last ID sent, is the only one that will show, try this:
Call the function once, but pass the IDs as one string separated by commas
Business
Then change your "show" function like this:
function show(ids) {
let idArr = ids.split(",");
divs.forEach( x => {
div = document.getElementById(x);
div.style.display = (idArr.includes(x) ? "block" : "none");
});
}
What this does, is that it will create an array of IDs based on the parameter you send, and for each item it will check if the ID was sent and show/hide it.
Please let me know if this helps or if you need more details.
EDIT: Formatting in the JavaScript code and simplifying it. Please also note that here I am not validating if the an element with the ID exists, it is only to show you how it can work. It will need additional validations
You can try it
<ul>
<li>
Fitness & Wellness
</li>
<li>
Business
</li>
<li>
Arts & Entertainment
</li>
</ul>
<div class="articles">
<div id="el-57d5b6f71db32029" style="display:none;">fitness</div>
<div id="el-e881a23a64890108" style="display:none;">business</div>
<div id="el-65ebd7b2380005a1" style="display:none;">art</div>
</div>
<script>
document.querySelectorAll('.article-btn').forEach(item => {
item.addEventListener('click', event => {
show((item.getAttribute('data-id')).split(";"));
})
})
const show = (id) => {
document.querySelectorAll('.articles>div').forEach(item => {
if(id.includes(item.getAttribute('id'))){
item.style["display"] = "block";
}else{
item.style["display"] = "none";
}
});
}
</script>
Inline JavaScript is generally discouraged these days, so here's a solution that removes that dependency. It puts the ids of the list items into the dataset instead. You can then create an array from that dataset, iterate over the articles, and if the id is included in the array of ids either hide or show it.
// Cache the list and the articles
const ul = document.querySelector('ul');
const articles = document.querySelectorAll('.articles div');
// Add an event listener to the list
ul.addEventListener('click', handleClick, false);
function handleClick(e) {
// Get the node name and the dataset
// from the element that was clicked
const { nodeName, dataset } = e.target;
// Check that it was an anchor
if (nodeName === 'A') {
// Get an array of ids from the dataset
const ids = dataset
.ids.split(',')
.map(id => id.trim());
// Hide all the articles
articles.forEach(article => {
article.classList.add('hide');
});
// Show the articles where the id is in
// the list of ids
articles.forEach(div => {
if (ids.includes(div.id)) {
div.classList.remove('hide');
}
});
}
}
.hide { display: none; }
ul li:hover { cursor: pointer; color: red; }
<ul>
<li>
<a data-ids="el-57d5b6f71db32029">Fitness & Wellness</a>
</li>
<li>
<a data-ids="el-57d5b6f71db32029, el-e881a23a64890108">Business</a>
</li>
<li>
<a data-ids= "el-65ebd7b2380005a1">Arts & Entertainment</a>
</li>
</ul>
<div class="articles">
<div id="el-57d5b6f71db32029" class="hide">fitness</div>
<div id="el-e881a23a64890108" class="hide">business</div>
<div id="el-65ebd7b2380005a1" class="hide">art</div>
</div>
I am currently using the function below to toggle the class of ".card-header" based on a shared data-target with it's corresponding ".seating-map_section". My hope is to adjust this so that when either the ".seating-map_section" and/or ".card-header" element is clicked, it add/removes the variable activeClass of both elements. I'm not sure what the best approach would be to something like this so any help would be greatly appreciated!
For context, this is the effect I'm going for: https://www.nba.com/timberwolves/tickets/memberships
var $activeItem = $(".seating-map_section");
var activeClass = "active";
$activeItem.click(function() {
const id = $(this).attr('data-target');
const $collapse = $(`.card-header[data-target=${id}]`);
if ($collapse) {
$collapse.toggleClass(activeClass);
}
$(this).toggleClass(activeClass);
});
Please look at the code below. It may work.
Check: http://jsfiddle.net/mehdi354/5yvds8t2/1/
You could do it like this:
var $activeItem = $(".seating-map_section, .card-header");
var activeClass = "active";
$activeItem.click(function() {
const id = $(this).attr('data-target');
const $collapse = $(`.card-header[data-target=${id}], .seating-map_section[data-target=${id}]`);
if ($collapse) {
$collapse.toggleClass(activeClass);
}
});
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="seating-map_section" data-target="1">
Seating map section
</div>
<div class="card-header" data-target="1">
Card header
</div>
I have a class amt and when that class is clicked I want to get the values of the clicked <h6>, <span> and <label> tags.
How do I do this in jquery? I have already seen a question here Get value of List Item with jQuery but it uses same under tag but i have to get different elemet value under same tag
<li class="amt" id="diecut_am1">
<h6>50</h6>
<span>$59.00</span>
<label>$51.30</label>
</li>
<li class="amt" id="diecut_am2">
<h6>100</h6>
<span>$68.00</span>
<label>$61.20</label>
</li>
Try this
$(".amt").click(function() {
var elem1 = $(this).find("h6").html();
var elem2 = $(this).find("span").html();
var elem3 = $(this).find("label").html();
alert(elem1);
alert(elem2);
alert(elem3);
});
https://jsfiddle.net/kLe5kLc3/1/
You could do something like this:
$( document ).ready(function() {
$('.amt').on("click", function() {
var h6 = $(this).find('h6').text();
var span = $(this).find('span').text();
var label = $(this).find('label').text();
});
});
Demo: https://jsfiddle.net/12q12k52/
here's the JS way :
var amt = document.querySelectorAll('.amt')
//add event listener to all .amt elements
var amtArr = [].slice.call(amt)
amtArr.forEach(function (x) {
x.addEventListener('click', listChilds, true)
});
//we retrive the target properties
function listChilds(e) {
console.log(e.path[1]) //all the children
//if you want one in particular it would be
console.log(e.target.childNodes[0])
}
<li class="amt" id="diecut_am1">
<h6>50</h6>
<span>$59.00</span>
<label>$51.30</label>
</li>
<li class="amt" id="diecut_am2">
<h6>100</h6>
<span>$68.00</span>
<label>$61.20</label>
</li>
You can iterate over the children of the clicked elements
$(this).children()
I want to toggle the visibility of classes of list items and also toggle the visibility of all the list items. With help of another stack overflow post, I am able to toggle specific classes of list items.
Here's the Javascript I have that toggles specific classes of list items:
var switcher = [false, false, false];
var classes = ['easy', 'fun', 'silly'];
$('.toggler').click(function () {
var x = $(this).hasClass('checked');
switcher[$(this).data('switch')] = !x;
$(this).toggleClass("checked", !x);
$('li').each(function () {
var cur = $(this);
cur.addClass('hidden');
$.each(switcher, function (index, data) {
if (data && cur.hasClass(classes[index])) {
cur.removeClass('hidden');
}
});
});
});
I added the basic functionality to hide and show all the list items, but the function brakes the individual class toggles:
$('.select_all').click(function () {
$(".toggler").toggleClass("checked");
$('li').toggleClass("hidden");
});
How can I keep class toggles, and add another button that toggles all the items?
Here's a fiddle example: http://jsfiddle.net/BMT4x/1/
I'm not sure if this is exactly what you're trying to do, but it should give you a push in the right direction (at least the direction I'd go). I prefer toggling everything with classes. Something like:
<button class="toggler" data-class="easy">Easy</button>,
<button class="toggler" data-class="fun">Fun</button>,
<button class="toggler" data-class="silly">Silly</button>,
<button class="toggler" data-class="all">Select All</button>
<ul id="list">
<li class="easy">Bowling</li>
<li class="fun">Balooning</li>
<li class="fun easy">Boating</li>
<li class="silly">Barfing</li>
<li class="easy fun">Bafooning</li>
</ul>
The CSS:
#list li {
display: none;
}
#list.easy li.easy {
display: block;
}
#list.fun li.fun {
display: block;
}
#list.silly li.silly {
display: block;
}
#list.all li {
display: block;
}
The JS:
$('.toggler').click(function () {
var category = $(this).data('class');
$('#list').toggleClass(category);
});
And a fiddle for reference: http://jsfiddle.net/qLLYj/
You can explicitly add/remove a class by passing a second, switch, parameter to toggleClass (see here).
So, you can change the state of all the individual switches and list items when clicking the .select_all button.
$('.select_all').click(function () {
$('.select_all').toggleClass("checked");
var allChecked = $('.select_all').hasClass("checked");
switcher = [allChecked, allChecked, allChecked];
$(".toggler").toggleClass("checked", allChecked);
$('li').toggleClass("hidden", !allChecked);
});
Some further changes made to get more intuitive behaviour
(e.g. if all checked, clicking one of the toggles deselects .select_all as well as itself; checking all individual toggles means .select_all is automatically checked):
$('.toggler').click(function () {
var x = $(this).hasClass('checked');
switcher[$(this).data('switch')] = !x;
$(this).toggleClass("checked");
$('li').each(function () {
var cur = $(this);
cur.addClass('hidden');
$.each(switcher, function (index, data) {
if (data && cur.hasClass(classes[index])) {
cur.removeClass('hidden');
}
});
});
var allChecked = switcher.indexOf(false) < 0;
$('.select_all').toggleClass("checked", allChecked);
});
Fiddle: http://jsfiddle.net/ET33B/