I have a nested list, as shown below. I'm struggling to find a specific CSS selector that I can use in querySelectorAll() JavaScript function, which will only affect all <li> tags that do NOT contain <ul> tag. So in this case it should be just the lines
<li>foot</li>
<li>leg</li>
<li>tiger</li>
<li>elephant</li>
<li>food</li>
I tried querySelectorAll("ol > li") and some others ways with the :not() selector, but to no success.
querySelectorAll("ol > li ul") is the opposite of what I want, because when I use
console.log(document.getElementById("translation").querySelectorAll("ol > li ul").length) it returns 3.
I need code of the following type console.log(document.getElementById("translation").querySelectorAll(blank).length) which will return 5. I don't know if that's possible, and I can't find it anywhere online.
Another way of looking at it is to let this code of CSS only color items which do not contain other nested lists (so that only points 2-6 will have colored background):
#translation ol > li ul{
background-color: cyan;
}
The entire list:
<div id="translation">
<ol>
<li>
<ul>
<li>parting</li>
<li>parting</li>
<li>parting</li>
<li>separation</li>
<li>separation</li>
<li>separation</li>
<li>farewell</li>
<li>(lateral) branch</li>
<li>fork</li>
<li>offshoot</li>
</ul>
</li>
<li>foot</li>
<li>leg</li>
<li>tiger</li>
<li>elephant</li>
<li>food</li>
<li>
<ul>
<li>branch</li>
<li>parting</li>
<li>disaffiliation</li>
<li>disaffiliation</li>
<li>separation</li>
<li>(lateral) branch</li>
<li>farewell</li>
<li>branch</li>
<li>division</li>
</ul>
</li>
<li>
<ul>
<li>dissociation</li>
<li>disaffiliation</li>
<li>dissociation</li>
</ul>
</li>
</ol>
</div>
You need to check each li is childNodes has ul. For example like this:
const test = [...document.querySelectorAll("ol > li")].filter(
li => ![...li.childNodes].find(child => child.localName === "ul")
);
if you are able to use jQuery then make the :not selector to catch elements that have ul as childs.
something like this:
$("translation").find("ol > li:not(:has(>ul))")
Notice this solution will work for jQuery selectors but not for the Vanilla JS (Vanilla JS doesn't support :has as a seclctor).
With Vanilla JS you might want to do something like this:
const elems = document.getElementById("translation").querySelectorAll('ol > li');
let items = Array.from(elems); // convert to Array type
items.filter(item => { // filter the array
item.querySelectorAll('ul').length == 0
})
I have a d3 nodes hierarchy root-parent-child that I need to output as ul-li so that anything that has d.depth = max(d.depth) becomes a li element, and they are all wrapped by ul elements up to d.depth = 0, e.g.
<ul>
<ul>
<ul>
<li>
<li>
</ul>
</ul>
<ul>
<li>
<li>
</ul>
</ul> ...
I reckon I must somehow iterate through the data and see if there are children and if not append an li, otherwise append an ul... but how? Thanks!
You can do it like this:
//here chart is the div on which you want to attach the ul and li.
var myDiv = d3.select('#chart')/
.append("ul")//root ul
.append("li")//root li
.text(data.name)//root li name
.append("ul");//to this add ul
//note i am iterating through the data via recursion.
function makeElements(parentDOM, myData){
myData.children.forEach(function(child){
//add li element
parentDOM.append("li").text(child.name);
//if children then make ul
if (child.children.length > 0){
var ul = parentDOM.append("ul");
//recurse pass ul as parentDOM
makeElements(ul, child);
}
});
}
Working code here
Let me start by saying I know this is a duplicate, however I couldn't find a solution by looking through previous answers so I was hoping someone can explain what I'm doing wrong with this.
This is part of a menu output by a php script:
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0', 'mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
with the following as my script as per https://stackoverflow.com/a/11842992, which should show each submenu when hovering its parent container
function showMenu(a,b) {
$(a).hover(
function(){
$(b).show();
},
function(){
$(b).hide();
})
}
Javascript and CSS being my weak suits, could someone tell me where my problem is? I feel like onMouseOver doesn't work the way I would expect it to. However I am still learning to manipulate the DOM, please bear with me, thank you!
Edited to reflect missingno's suggestions
For simple scenarios, i'd rather stay away from using JS
Heres how
HTML
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0, mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
CSS
#mtk_main_menu:before,
#mtk_main_menu:after {
content:"";
display:table;
clear:both;
}
#mtk_main_menu {
*zoom:1;
}
#mtk_main_menu > li {
position:relative;
float:left;
}
#mtk_main_menu > li > div {
position:absolute;
left:-999px;
background:grey;
}
#mtk_main_menu > li:hover > div {
left:0;
}
That will do the trick
Fiddle: http://jsfiddle.net/Varinder/7pXSw/
Edit
If you really want to go the JS way - heres how:
HTML
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0, mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
CSS
#mtk_main_menu:before,
#mtk_main_menu:after {
content:"";
display:table;
clear:both;
}
#mtk_main_menu {
*zoom:1;
}
#mtk_main_menu > li {
position:relative;
float:left;
}
#mtk_main_menu > li > div {
position:absolute;
display:none;
/*left:-999px;*/
background:grey;
}
#mtk_main_menu > li:hover > div {
/*left:0;*/
}
JS
function showMenu( args ) {
var arguments = args.split(",");
var submenuWrapper = arguments[1].replace(" ", "");
var $subMenuWrapper = $( "#" + submenuWrapper );
$subMenuWrapper.show();
var $menuItem = $subMenuWrapper.closest("li");
$menuItem.on("mouseout", function() {
$subMenuWrapper.hide();
$(this).off("mouseout");
});
}
Fiddle: http://jsfiddle.net/Varinder/vnwy3/1/
You are calling the event handler with a single string parameter instead of two. Try changing
showMenu('mtk_submenu_0, mtk_div_submenu_0')
into
showMenu('mtk_submenu_0', 'mtk_div_submenu_0')
Additionally, inside your script you should use are using literal strings instead of using your parameters
//This looks for an element of class "a"
$("a").hover(
//This uses the contents of the `a` variable instead:
$(a).hover(
Finally, your function is using 'mtk_submenu_0' as a jquery selector. This searches for a class instead of an id. Change the selector to add a "#" on front or change your jquery logic to not need ids (for example, you could create selectors to search for the first div and ul descendants of the current element.
By doing what you are doing, every time the onMouseOver event is triggered, you're attaching the jQuery hover event. Each time you're attaching another listener.
Instead, initialize your event on document ready:
$(function () {
$("#tk_div_submenu_0").hover(
function(){
$("#mtk_submenu_0").show();
},
function(){
$("#mtk_submenu_0").hide();
})
);
});
That will initialize it when the document is ready, and it will initialize it once.
Then just remove your onMouseOver event from the HTML.
<li class="mtk_topmenu">Manager Options ... </li>
First, you're going the long way around the problem. jQuery has a built in toggle method that performs the show/hide for you. Secondly you're putting the hover call on the child element of the item you're trying to show on hover. Here's an updated version of your code:
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu(this,'mtk_div_submenu_0');">
Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
</ul>
JS:
function showMenu(a,b) {
var divStr = '#' + a.id + " div";
$(divStr).toggle();
}
I used the hover event on the LI element as it makes more sense in this case.
Here it is in a fiddle: http://jsfiddle.net/3Ecrq/
One thing I find strange about your code is that the first div you mention, mtk_submenu_0, is inside the div you are showing / hiding, mtk_div_submenu_0. Once you hide the outer div, the inner div cannot be 'hovered over', thus preventing it from being shown again.
To ensure the inner div does not get hidden, try something like this:
HTML:
<ul id="mtk_main_menu">
<li class="mtk_topmenu">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
Javascript:
$(document).ready(function() {
$('.mtk_topmenu').hover(
function() {
$('#mtk_div_submenu_0').show();
},
function() {
$('#mtk_div_submenu_0').hide();
});
});
Because of your line:
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0', 'mtk_div_submenu_0');">
I assumed you were looking to have the mtk_div_submenu_0 div show / hide whenever the text Manager Options is moused over. Hopefully this helps!
I have a menu that looks like this:
<ul class="menu">
<li>zing</li>
<li>
page
<ul>
<li>foo</li>
<li>bar</li>
</ul>
</li>
</ul>
I'd like the sub menu to fadeIn when I hover over the page link.
This is my code so far but for some reason it's not working and I don't think this is the correct way to achieve this anyways:
$('.menu li a:nth-child(2)').hover(function(){
$('.menu li ul').fadeIn(150);
}, function(){
$('.menu li ul').fadeOut(150);
});
Anyone know how I can reach my goal according to best standards to make the submenu of the 2nd li to appear when I hover over page?
It would probably be a good idea to have your hovers only apply to menus that have a submenu. You could do something like this:
$('.menu > li > a').filter(function(){
if( $(this).siblings('ul').length ){ return true; }
}).hover(
function(){ $(this).siblings('ul').fadeIn(150); }
,function(){ $(this).siblings('ul').fadeOut(150); }
);
The nth-child selector needs to be applied to the <li> element not the <a>.
$('.menu li ul li:nth-child(2)').hover(function(){
$('.menu li ul').fadeIn(150);
}, function(){
$('.menu li ul').fadeOut(150);
});
Fiddle: http://jsfiddle.net/9u3V7/
Check this fiddle out: http://jsfiddle.net/vPLAc/3/
No need for counting children that way. Every list item with a submenu will react to this code.
I have a series of unordered lists wrapped in another unordered list. The task is to separate the individual li tags with commas and omitting the each list's last li tag.
I can do it on an individual list level i.e. When testing with just one list I was able to remove the last comma from the last element. But when I'm trying to apply the JavaScript in affects the last li element of the wrapping ul...
Here is my code:
<script type="text/javascript">
$(document).ready(function () {
$('.tagsList li span').each(function () {
$(this).append(',');
});
var lTag = $('.tagsList li:last span').text().replace(',','');
$('.tagsList li:last span').text(lTag);
});
</script>
<ul class="postsList">
<li>
<ul class="tagsList">
<li><span>tag1</span></li>
<li><span>tag2</span></li>
</ul>
</li>
<li>
<ul class="tagsList">
<li><span>tag1</span></li>
<li><span>tag2</span></li>
</ul>
</li>
</ul>
You should use a slightly modified selector
$('.tagsList li:not(:last-child) span').each(function () {
$(this).append(',');
});
This directly target all the span elements inside a li except the last li of each list.
demo http://jsfiddle.net/gaby/wwTjH/2/