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.
Related
So I have a menu, I want it to display information accordingly, for example:
<ul id="menu-list">
<li id="about-me">About Me</li>
<li id="skills">Skills</li>
<li id="experience">Experience</li>
<li id="education">Education</li>
<li id="projects">Projects</l>
<li id="contacts">Contacts</li>
</ul>
and on my JS file I did this in order to access "li" elements:
let navMenu = document.getElementById("menu-list");
let menuList = navMenu.getElementsByTagName("li");
let skillsButton = document.getElementById("skills");
let skillsEvent = document.getElementById('main-section-skills').hidden = true;
(text that will display on click is pre-set to hidden = true)
The goal is to iterate through "li" items to find which one of those has ".hidden = false" value and change it to ".hidden = true" so that when you click on different menu buttons, each button will so only relevant info and others that are not relevant will bi hidden.
Thanks for your help.
You can get the array of children using element.children
https://developer.mozilla.org/en-US/docs/Web/API/Element/children
for (let child of navMenu.children) {
your logic here
}
For checking the class you can use element.hasClass or even:
element.style.display = 'none'
element.style.display = 'block'
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>
Just staring to lean js here. Is it possible to move child elements from one parent under another parent if parent name is duplicate?
Example:
How to put Something else & Something like under a single Composition parent, and Someone else under one Content, and delete the duplicates.
Is this possible with javascript or jquery? Thank you!
<li>
<h4>Composition</h4>
<p>Something</p>
</li>
<li>
<h4>Composition</h4>
<p>Something else</p>
</li>
<li>
<h4>Composition</h4>
<p>Something like</p>
</li>
<li>
<h4>Content</h4>
<p>Someone</p>
</li>
<h4>Content</h4>
<p>Someone else</p>
</li>
here is the js I got so far, I'm stuck at moving p items to the first element that repeats, each under it's parent. thing is parent elements don't have certain id's or classes:
const $technicalProp = $("[data-surface-prop]");
const technicalVal = $("[data-surface-val]");
let duplicate = {};
$technicalProp.each(function() {
let txt = $(this).text();
if (duplicate[txt]) {
$(this).remove(); // this only removes the dulicate names I also need to move chlidren
}
else {
duplicate[txt] = true;
}
});
yes you can i dont know if this is the best way but this works, my approach is by making an arrayobject (js) as a new model of what you want
the logic is i extract the text of h4 and check if the data variable has been registered there, if not registered yet then i push it to the data and the child text (p)
if registered already then i push the child text only
let data = [];
const lists = document.querySelectorAll('li').forEach( (li, liIdx) => {
let parentName = li.querySelector('h4').innerHTML;
let childName = li.querySelector('p').innerHTML;
let isRegistered = data.find( x => x.parentName === parentName);
if(!isRegistered) {
childName = [childName];
data.push({ parentName, childName});
}else {
console.log(isRegistered)
isRegistered.childName.push(childName);
}
});
and this is what we got
0:
childName: (3) ["Something", "Something else", "Something like"]
parentName: "Composition"
1:
childName: (2) ["Someone", "Someone else"]
parentName: "Content"
then reset the ol tag and rebuild its item
let ol = document.querySelector('ol');
ol.innerHTML = '';
data.map( d => {
let p = d.childName.map( c => `<p>${c}</p>`).join('');
ol.insertAdjacentHTML('beforeend', `
<li>
<h4>${d.parentName}</h4>
${p}
</li>
`);
})
With jQuery you can remove and add elements with detach(), append() and prepend()
Like here: https://stackoverflow.com/a/19802593/11265780 (but replace jQuery with $)
I have a list which users can add items to using a drop down of items. I'm tracking user behavior and want to execute a function each time a user ADDS something to this list (not removes it). The list looks like this:
<ul class="items-list" id="user-items">
<li id="newitem1"></li>
<li id="newitem2"></li>
</ul>
They can add more items to the list with the dropdown, the issue is there are no Jquery selectors for the links to those items, so I am instead trying to detect when items are added to the list.
My attempts so far are:
var listOfItems = $("#user-items").children() - I can count how many items are currently in the list. However I can't work out how to check whether the user has added more items. I am new to Jquery and would appreciate if someone could point me in the right direction here? Thanks
Use DOMSubtreeModified event and check if new element added to DOM.
$("#a").bind("DOMSubtreeModified", function() {
alert("list updated");
});
Demo:
Fiddle
All the values of dropdown can be checked using Jquery .each() before adding new item.
<ul class="items-list" id="user-items">
<li id="newitem1"></li>
<li id="newitem2"></li>
</ul>
Jquery:
$( "li" ).each(function( index ) {
console.log( index + ": " + $( this ).text() );
});
Reference : https://api.jquery.com/each/
You can observe mutations in that specific part of the DOM and do whatever you want when they occur.
Documentation here: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
Example:
const itemsList = document.querySelector("#user-items");
const observer = new MutationObserver((mutationList, observer) => {
mutationList.forEach((mutation) => {
if (mutation.type === "childList") {
// Do whatever you want here, I'm just logging that
// a child of the <ul> has been added.
console.log("A child node has been added");
}
});
});
observer.observe(itemsList, { childList: true, subtree: true });
/**
* Just some basic code to add items to the list. Not jQuery, but
* you already have this code I assume, so this is just here to make
* the demo work
*/
const itemAdder = document.querySelector("#add-item");
let itemNumber = 0;
itemAdder.addEventListener("click", (e) => {
itemNumber++;
const listItem = document.createElement("LI");
listItem.setAttribute("id", `user-item-${itemNumber}`);
const listItemText = document.createTextNode(`List item ${itemNumber}`);
listItem.appendChild(listItemText);
itemsList.appendChild(listItem);
});
<ul id="user-items">
</ul>
<button id="add-item">Add Item</button>
You can achieve so by using MutationObserver.The MutationObserver interface provides the ability to watch for changes being made to the DOM tree . It is designed as a replacement for the older Mutation Events feature which was part of the DOM3 Events specification.
here is a working example.
var targetNode = $("#user-items");
function createObserver(callback) {
return new MutationObserver(function (mutationRecords) {
mutationRecords.forEach(callback);
});
}
$("#user-items").each(function () {
var obs = createObserver(function (mutation) {
$(mutation.addedNodes).css("background-color", "green");
});
obs.observe(this, { childList: true });
});
setTimeout(function(){
$("#user-items").append('<li id="newitem3">New One</li>');
},1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<ul class="items-list" id="user-items">
<li id="newitem1">Old One</li>
<li id="newitem2">Old two</li>
</ul>
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()