How to change a class when one of the elements classname change? - javascript

I have this menu of elements, what is the best approach to change the last div element from hidden to visible when one of the elements with class closed changes to open using Jquery, What i want is when i click on one of the li and change it from closed to , i want to change the dynamic ul to display none or block, do i need to loop over all the elements and check their class?
<ul class="groupmenu">
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
<ul class="level1"></ul>
<li class="closed"></li>
</ul>
<div class="dynamic hidden"></div>

First of all, your ul.level1 elements should be wrapped in li elements.
Then, on click of a li.closed element, you could :
toggle the visibility of its ul.level1 child element.
toggle the visibility of your div.dynamic element using !$("ul.level1:not(.hidden)").length. It will return a boolean whose value will be false if there is at least 1 ul.level1 element that does not have the .hidden class. Otherwise it will return true.
$("li.closed").click(function() {
$(this).find("ul.level1").toggleClass("hidden");
$("div.dynamic").toggleClass("hidden",!$("ul.level1:not(.hidden)").length);
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="groupmenu">
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
<li class="closed">
ul closed
<ul class="level1 hidden">
<li>visible</li>
</ul>
</li>
</ul>
<div class="dynamic hidden">
dynamic
</div>

Related

How to get the value from li on click from menu for dynamic routing in vuejs?

**For time being I created a component for each li. I need this to be dynamic. This takes lot of time to load. I have no idea how to do this **
<nav class="navbar navbar-expand-lg navbar-light bg-light">
....
<div class="category">
<li class="dropdown menu-large nav-item"> Categories
<ul class="dropdown-menu megamenu">
<div class="row">
<li class="col-md-3 dropdown-item">
<li class="col-md-3 dropdown-item">
<ul>
<li class="dropdown-header">Boys</li>
<li class="disabled"><li><router-link to="Pajama_kurta">Pajama kurta</router-link>
<li class="disabled"><li><router-link to="Track_pants">Track pants</router-link>
<li class="disabled"><li><router-link to="Inner_Wears">Inner Wears</router-link>
<li class="divider"></li>
<li class="dropdown-header">Home Essentials</li>
<li class="disabled"><li><router-link to="Kitchen_appliances">Kitchen appliances</router-link></li>
<li class="disabled"><li><router-link to="Doormats">Doormats</router-link></li>
<li class="disabled"><li><router-link to="Bedsheets">Bedsheets</router-link></li>
</ul>
</li>
<li class="col-md-3 dropdown-item">
<ul>
<li class="dropdown-header">Girls</li>
<li class="disabled"><li><router-link to="Frocks_party_wear">Frocks party wear</router-link></li>
<li class="disabled"><li><router-link to="Cotton_frocks">Cotton frocks</router-link></li>
<li class="disabled"><li><router-link to="Summer_collections">Summer collections</router-link></li>
<li class="disabled"><li><router-link to="Inner_wear">Inner wear</router-link></li>
</ul>
</li>
</div>
</ul>
</li>
</div>
.......
</nav>
I was actually working on something similar (I think) today.
If you don't have one already, wrap the li elements in a parent div and add a click listener to it:
<div #click="handleClicks($event)">
<li></li>
<li></li>
<li></li>
...
</div>
Now, in methods, add a handleClicks() function:
methods: {
handleClicks(click) {
if (click.target.tagName == "LI") { //Check if clicked element is a <li>
let value = click.target.value //Get li's value
router.push('name of view you want to navigate to') //Navigate to different page. Also note that the router must be imported to use it.
}
}
}
Let me know if you have any other questions

how to find all class name in ul > li

I have to change my html code by javascript.
I want to add span tag for a tag if it contains has-children in class for li tag
<span> <a></a> <span class="sub-menu-toggle"></span></span>
it is my code that I can change first step li.has-children
how can I change all ? class=has-children
$('.has-children').each(function(i, e) {
var aTag = $(this).find('a')[0].outerHTML;
var ulTag = $(this).find('ul')[0].outerHTML;
$(this).html('<span>' + aTag + '<span class="sub-menu-toggle"></span></span>' + ulTag);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="site-menu">
<ul style="display: none">
<li class="has-children">
Menu
<ul class="sub-menu">
<li class="has-children">
First Sub Menu
<ul class="sub-menu">
<li class="">
Second Sub Menu
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
How about this?
Use a better selector
wrap
after
$('.has-children>a').each(function() {
$(this).wrap('<span/>')
.after('<span class="sub-menu-toggle"/>');
});
a { text-decoration: none }
span a { text-decoration: underline }
.sub-menu-toggle::after { content: " ʘ" }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav class="site-menu">
<ul style="display">
<li class="has-children">
Menu
<ul class="sub-menu">
<li class="has-children">
First Sub Menu
<ul class="sub-menu">
<li class="">
Second Sub Menu
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>

Slide down in each list

I need ul.list-group-subshould display none on first glance and when I click on "Click" (.dd), only one "list-group-sub" should display block from current li while "list-group-sub" should display none from other li and vice versa, only one is one "list-group-sub" open at a time
Fiddle Demo :
https://fiddle.jshell.net/alpeshlahad/zv3vpzew/3/
$(".list-group-item .dd").click(function() {
$("ul.list-group-sub").slideToggle();
});
ul.list-group-sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>
The issue is because your ul.list-group-sub selector is calling slideToggle() on all elements. You instead need to traverse the DOM to find the one related to the clicked .dd element. To do that you can use closest() to get the parent li, then find() to get the element you need.
To only display one menu at at time you also need to call slideUp() on them whilst toggling the target one. Try this:
$(".list-group-item .dd").click(function(e) {
e.preventDefault();
var $target = $(this).closest('li').find("ul.list-group-sub").slideToggle();
$('ul.list-group-sub').not($target).slideUp();
});
ul.list-group-sub { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>
Also note that I removed the use of javascript; in the href attribute of your a elements. You can instead call preventDefault() on the event to stop the default behaviour. This method has the benefit of de-coupling the JS logic from the HTML.
$("ul.list-group-sub").slideToggle() targets all sub-items. Use this:
$(this).closest('.list-group-item').find('.list-group-sub').slideToggle();
to target the corresponding list sub-items.
See demo below and updated fiddle here:
$(".list-group-item .dd").click(function() {
$(this).closest('.list-group-item').find('.list-group-sub').slideToggle();
});
ul.list-group-sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-group member-list trainers-data ot-box">
<li class="list-group-item">
List 1
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
<li class="list-group-item">
List 2
<span class="label">
Click
</span>
<ul class="list-group-sub">
<li class="list-group-item checked">Sublist 1</li>
<li class="list-group-item checked">Sublist 2</li>
<li class="list-group-item checked">Sublist 3</li>
</ul>
</li>
</ul>

Make sub menus expandable using JavaScript

I am working on a navigation menu with nested sub menus. I was wondering if there is a way I can achieve the menus to be expandable when I click the parent menu item
This is my HTML code, as you guys can see I have 2 ng-repeat inside the parent menu item and another one if the sub menu item has one or more sub menus
<div id="sidebar-wrapper" ng-controller="navigationController" style="overflow-y: auto; margin-top:-20px;" class="hidden-print" ng-hide="hideSidebar()">
<nav role="navigation" class="navbar navbar-default navbar-bigfont" style="border-width: 0">
<ul class="nav nav-pills nav-stacked">
<li class="portal-text-19b" ng-repeat="item in newMenu" ng-class="{active: hightlight === item.title && item.path !== '#'}" ng-show="showItem(item.path, item.allowAll)">
<a style="text-transform: uppercase" href="{{item.path}}" ng-click="item.fn()">
<span class="{{item.icon}}"></span> {{item.title}}
<span style="font-size: 7px;" ng-if="item.childs" class="glyphicon glyphicon-play"></span>
</a>
<ul class="nav nav-pills nav-stacked">
<li style="list-style-type: none;" ng-repeat="child in item.childs" ng-class="{active: hightlight === child.title && child.path !== '#'}" ng-show="showItem(child.path, child.allowAll)">
<a href="{{child.path}}" ng-click="child.fn()">
<span class="{{child.icon}}"></span> {{child.title}}
</a>
<ul class="nav nav-pills nav-stacked">
<li style="list-style-type: none;" ng-repeat="child2 in child.childs" ng-class="{active: hightlight === child2.title && child2.path !== '#'}" ng-show="showItem(child2.path, child2.allowAll)">
<a href="{{child2.path}}" ng-click="child2.fn()">
<span class="{{child2.icon}}"></span> {{child2.title}}
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
You can simply set the inner ul elements as hidden, and then use the following code to show/hide them:
$("ul li").has("ul").click(function() {
$(this).find("ul").toggle();
});
This will toggle hiding and showing the sub ul elements on their parent li click.
Explanation:
It uses .has() method to attach the click event handler to only li having ul children, and .toggle() method to show/hide the child list of the clicked li element.
Demo:
This is a working Demo Snippet:
$("ul li").has("ul").click(function() {
$(this).find("ul").toggle();
});
ul li {
cursor: pointer;
}
ul li ul {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>list item 1</li>
<li>list item 2
<ul>
<li>list item 2-a</li>
<li>list item 2-b</li>
</ul>
</li>
<li>list item 3</li>
<li>list item 4</li>
</ul>

Get all list items that do not have a data attribute that starts with value

I have a list of elements that each have a data-name attribute. I want to select all elements that do not start with the prefix "arc" and hide them.
<ul id="slides">
<li data-name="arc_1">...</li>
<li data-name="arc_2">...</li>
<li data-name="biz_1">...</li>
<li data-name="biz_2">...</li>
<li data-name="cas_1">...</li>
<li data-name="cas_2">...</li>
<li data-name="cas_3">...</li>
<li data-name="prd_1">...</li>
</ul>
I have tried to use $('#slides li[data-name^="arc"]') but it selects the opposite of what it need.
Use :not():
$('#slides li:not([data-name^="arc"])')
$('#slides li:not([data-name^="arc"])').css('color','red')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="slides">
<li data-name="arc_1">...</li>
<li data-name="arc_2">...</li>
<li data-name="biz_1">...</li>
<li data-name="biz_2">...</li>
<li data-name="cas_1">...</li>
<li data-name="cas_2">...</li>
<li data-name="cas_3">...</li>
<li data-name="prd_1">...</li>
</ul>

Categories