CSS and jQuery universal tree menu - javascript

I want to create universal tree menu, with ul li ul. And I've made something like this using just CSS:
CSS
.category-list {
}
.category-list li ul {
display: none;
}
.category-list li:hover > ul {
display: block;
}
HTML
<ul class="category-list">
<li>
Category 1
<ul>
<li>Sub-category 1</li>
<li>Sub-cateagory 1</li>
<li>Sub-category 1</li>
</ul>
</li>
<li>
Category 2
<ul>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
</ul>
</li>
</ul>
https://jsfiddle.net/usz9ycmj/1/
--
And I want to make similar effect, but on click, so just current clicked tab displays its parent content.
Even more important for me is the ability to add and remove class on specific action:
.category-list li.current -- while is currently clicked (active)
.category-list li -- removed while different li is clicked (active)
Just, the trigger li has two different states for active and inactive. It changes the colors and arrow from closed to opened to give it a look of a tree menu - I bet You get the point.
I want the simple jquery code, if someone has time to help. feel welcome.

Here is a working code.
Please read the comments and let me know if something not clear.
// listen to the click event
var all_items = $('.category-list>li').click(function(event) {
// stop the propagation - this will abort the function when you click on the child li
event.stopPropagation();
var elm = $(this);
// remove the class from all the items
all_items.not(elm).removeClass('current');
// add class if it's not the current item
elm.toggleClass('current', !elm.is('.current'));
});
.category-list {
}
.category-list li ul {
display: none;
}
.category-list li.current > ul {
display: block;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<ul class="category-list">
<li>
Category 1
<ul>
<li>Sub-category 1</li>
<li>Sub-category 1</li>
<li>Sub-category 1</li>
</ul>
</li>
<li>
Category 2
<ul>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
<li>Sub-category 2</li>
</ul>
</li>
</ul>
http://jsbin.com/tocewe/edit?html,css,js

Related

Bold submenu items in sidebar menu

I followed the explanation below to create what I needed, but there is an additional requirement i am trying to fulfill.
highlight the navigation menu for the current page
My submenu items are anchor links on the same page as the main menu item. Example:
$(function() {
var url = window.location.href;
$(".imagingmenu a").each(function() {
if (url == (this.href)) {
$(this).closest("li").addClass("active");
$(this).closest("li").parent().parent().addClass("active");
}
});
});
.imagingmenu ul li.active a, .imagingmenu ul li a:hover {
font-weight:bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="imagingmenu">
<ul>
<li>Menu item 1
<li>Menu item 2
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
</ul>
</div>
You can see the bolding works when you hover over the submenu items, but when they are clicked and active, I want just that submenu item to be bolded and the other not to be. However, when any of the submenu items are active, all of them in the list are bolded. How can I achieve what I'm looking for?
Thanks.
This is your problem: $(this).closest("li").parent().parent().addClass("active");
When you click on a "Submenu Item" such as "Submenu Item 2" your code adds the active class to that item, but it also adds the active class to the parent-of-the-parent of the <li> that was clicked.
The parent of the <li> is the enclosing <ul> and the parent of that is the <li>Menu item 2 so what you end up with is this (notice the places where the active class was added)
<ul>
<li>Menu item 1
<li class="active">Menu item 2
<ul>
<li>Submenu Item 1</li>
<li class="active">Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
</ul>
The <li> for "Menu item 2" gets the active class so it is bold according to the CSS rule.imagingmenu ul li.active a
That is, the whole <li> including all its children — the inner <ul> and all its <li>s are bold.
Try commenting out that line as below (I also added some console.log()s so I could see what it was doing)
$(function() {
var url = window.location.href;
$(".imagingmenu a").each(function() {
console.log(`this.href=${this.href} compare to url ${url}`);
if (url == (this.href)) {
console.log('this is', $(this));
console.log('this.closest(li) is', $(this).closest('li'));
$(this).closest("li").addClass("active");
//$(this).closest("li").parent().parent().addClass("active");
}
});
});
You may also have a problem because adding the hash # target doesn't reload the page so it doesn't re-run your function.
In reality I, personally, would handle this completely differently — I'd add a click handler to the list items; the handler receives an event parameter, and you can use the event.target to add the "active" class to the one list item that was clicked.

Disable mouseenter when over element on page load

I'm trying to find a way to disable mouseenter when the top-level navigation item is clicked & on pageload and re-enable again when the mouse leaves and enters the element again.
User hovers over element = show submenu
User clicks menu = hide submenu and only show submenu when user leaves menu elements and enters again.
If user is over the element onLoad then only show submenu when user leaves element and enters again.
$('.navmenu li').on('mouseenter', function(e) {
$(e.target).next().addClass('js-hover')
}).on('mouseleave', function(e) {
$(e.target).next().removeClass('js-hover')
});
$('.navmenu').on('click', function(e) {
$(e.target).next().removeClass('js-hover')
location.reload(true);
})
.navmenu .submenu {
display:none;
}
.navmenu li {
display: inline;
}
.navmenu .submenu {
position:absolute;
top:40px;
left:0
}
.navmenu li:hover .js-hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu">
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
<li>
Menu 2
<nav class="submenu">
<ul>
<li>Submenu 4</li>
<li>Submenu 5</li>
<li>Submenu 6</li>
</ul>
</nav>
</li>
</ul>
</nav>
this could be done using variables and storing a state of element (if it should be hidden or not). But since you tried to do this through class attributes, I did the same. Here is simle example of one menu item, everything should be clear.
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu" hidden>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
</ul>
</nav>
and javascript:
$menuLink = $("nav.navmenu li > a");
$menuLink.click(function () {
$(this).addClass("dontHide");
});
$menuLink.mouseenter(function () {
$(this).next("nav.submenu").removeAttr("hidden");
$(this).removeClass("dontHide");
});
$menuLink.mouseleave(function () {
if(!$(this).hasClass("dontHide")) {
$(this).next("nav.submenu").attr("hidden", true);
}
});
Live demo: https://jsfiddle.net/g3fua461/24/

jquery add tag around unnested text

This is a really hard question to find a title for, but here is it.
I got this HTML, that I can't change
<ul>
<li>
First part of the list
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</li>
<li>
Second part of the list
<ul>
<li>item 3</li>
</ul>
</li>
</ul>
And I'd like to apply things to the "first part of the list" and "Second part of the list" part, but not the nested ul part, like CSS transform scaleY, and a custom Jquery onClick method.
So, the solution I'd like would be a way to JQueryly add around those.
Is this possible?
Thank you a lot
To achieve this you can filter() the li contents() to retrieve the text nodes within it, then wrap that in a span and apply the needed CSS rules. Something like this:
$('#container > ul > li').each(function() {
var foo = $(this).contents().filter(function() {
return this.nodeType == 3 && this.textContent
}).wrap('<span />');
});
#container > ul > li > span {
color: red;
display: inline-block;
transform: scaleY(2);
margin: 0 0 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<ul>
<li>
First part of the list
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</li>
<li>
Second part of the list
<ul>
<li>item 3</li>
</ul>
</li>
</ul>
</div>

HTML/jQuery on click show/hide ul ul

I have this HTML code
<ul>
<li>link
<ul>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</li>
<li>link
<ul>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</li>
</ul>
now I want -> hide all sub menus -> if I click to main li element -> show current li's sub menu and next if I click to another main li element show sub menu and hide previously displayed sub menu.
Can anyone help me?
You can do it like this DEMO
$('li ul').hide();
$('li a').click(function() {
$(this).next('ul').slideToggle();
$('ul li ul').not($(this).next('ul')).slideUp();
});
You can do something simple like this with click event
$('#main>li>a').click(function() { // bind click event to a tag
$(this)
.next() // get ul inside
.stop() // stop any previous animation
.slideToggle() // toggle the visibility
.end() // back to previous selector , here the clicked element
.parent() // get parent li
.siblings() // get its siblings
.find('ul') // get ul inside them
.stop() // stop any previous animation
.slideUp() // hide them
});
#main>li>ul {
/* hide sub ul initially */
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="main">
<li>link
<ul>
<li>link
</li>
<li>link
</li>
<li>link
</li>
</ul>
</li>
<li>link
<ul>
<li>link
</li>
<li>link
</li>
<li>link
</li>
</ul>
</li>
</ul>

Navigator with html doesn't work javascript

I have this code and when i press the link with a element i want to hide the ul with class name tab and show the ul with class tab-1 without hidding the both of ul elements.I have tried with jquery but with no success. The jQuery code is the following.
$("a").click(function() {
$(".tab").hide("slide", {direction: "left"}, "slow");
$(".tab-1").show("slide", {direction: "left"}, "slow");
});
How can i do it?
<ul class="tab">
<li>
Link 1
<ul class="tab-1">
<li>List 1</li>
<li>List 2</li>
</ul>
</li>
</ul>
You can't show a child of an element that is set to display:none. If parent is not displayed...anything inside parent can't be either
However you can set visibility:hidden on parent and visibility:visible on descendants
.tab {visibility:hidden}
.tab-1 {visibility:visible}
Note that this is very uncommon practice. It would help to have a better description of what you want to acheive
DEMO
Just hide all elements that match .tab > li > a.
Demo :
.tab, .tab ul {
list-style-type: none;
}
.tab > li > a {
display : none;
}
<ul class="tab">
<li>
Link 1
<ul class="tab-1">
<li>List 1</li>
<li>List 2</li>
</ul>
</li>
</ul>

Categories