How to show/hide submenu with animation in vuejs - javascript

I'm new to vuejs and I want to create a menu with below html structure.
<ul>
<li>item 1
<ul class="list-unstyled">
<li>submenu 1-1</li>
<li>submenu 2-1</li>
<li>submenu 3-1</li>
</ul>
</li>
<li>item 2
<ul class="list-unstyled">
<li>submenu 1-2</li>
<li>submenu 2-2</li>
</ul>
</li>
</ul>
submenu's are hidden with css.
I want when I click on item 1 link, the child ul element will be toggled with slide down animation. And also this will happens for item 2 and others.

I wrote a demo for the first submenu. I use the transition component for the animation. you can also visit https://codesandbox.io/s/polished-butterfly-z1zf8?file=/src/App.vue:0-1263
<template>
<div id="app">
<ul>
<li>
item 1
<transition name="slideDown">
<ul class="list-unstyled" v-show="item1Visible">
<li>
<a href>submenu 1-1</a>
</li>
<li>
<a href>submenu 2-1</a>
</li>
<li>
<a href>submenu 3-1</a>
</li>
</ul>
</transition>
</li>
<li>
item 2
<ul class="list-unstyled" v-show="item2Visible">
<li>
<a href>submenu 1-2</a>
</li>
<li>
<a href>submenu 2-2</a>
</li>
</ul>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
item1Visible: true,
item2Visible: true
};
}
};
</script>
<style>
.slideDown-enter-active,
.slideDown-leave-active {
transition: all 0.5s ease-out;
overflow: hidden;
}
.slideDown-enter, .slideDown-leave-to /* .fade-leave-active below version 2.1.8 */ {
height: 0;
}
.slideDown-enter-to,
.slideDown-leave {
height: 50px;
}
</style>

Related

My sub menu is still not working properly (jQuery)

I'm creating a sub menu using jquery. I have made the code as below. But there is still something that is not working properly. What I want is, when the start, the menu is closed. Currently, all menus are open. How do I do it, can anyone help me?
$('.list-menu > li').click(function () {
var child = $(this).children('ul');
if(child.length===0){
$(this).children().addClass("active");
return;
}
$('.list-menu ul').not(child).slideUp('normal');
child.slideDown('normal');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list-menu">
<li class="menu-1">
Getting Started
<ul class="submenu">
<li id="sub-1">Child 1
</li>
<li id="sub-2">Child 2
</li>
</ul>
</li>
<li class="menu-2">
Controlling How Data is Indexed
<ul class="submenu">
<li id="sub-3">Child 1
</li>
<li id="sub-4">Child 2
</li>
</ul>
</li>
<li class="menu-3">
Uploading and Indexing Data
<ul class="submenu">
<li id="sub-5">Child 1
</li>
<li id="sub-6">Child 2
</li>
</ul>
</li>
<li>
<a href="#">
Querying For More Information
</a>
</li>
</ul>
You can set the child ul elements to display: none on page load using CSS:
ul > li > ul { display: none; }
$('.list-menu > li').click(function() {
var child = $(this).children('ul');
$(this).children().addClass("active");
$('.list-menu ul').not(child).slideUp('normal');
child.slideToggle('normal');
});
ul > li > ul { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list-menu">
<li class="menu-1">
Getting Started
<ul class="submenu">
<li id="sub-1">Child 1
</li>
<li id="sub-2">Child 2
</li>
</ul>
</li>
<li class="menu-2">
Controlling How Data is Indexed
<ul class="submenu">
<li id="sub-3">Child 1
</li>
<li id="sub-4">Child 2
</li>
</ul>
</li>
<li class="menu-3">
Uploading and Indexing Data
<ul class="submenu">
<li id="sub-5">Child 1
</li>
<li id="sub-6">Child 2
</li>
</ul>
</li>
<li>
Querying For More Information
</li>
</ul>

Changing parent width by number of its child elements?

In the following example, I have a header with logo-container on the left, menu in the middle and a button on the right. In the example, the menu has 5 top-level items, and 2 sub-menus.
<div class="container">
<div class="logo_container">
<img src="logo.png" />
</div>
<div id="top-navigation">
<div id="top-menu-nav">
<ul id="top-menu">
<li class="top-item">Top Item 1</li>
<li class="top-item">Top Item 2
<ul>
<li class="sub-item">Sub-Item 1</li>
<li class="sub-item">Sub-Item 2</li>
<li class="sub-item">Sub-Item 3</li>
<li class="sub-item">Sub-Item 4</li>
</ul>
</li>
<li class="top-item">Top Item 3
<ul>
<li class="sub-item">Sub-Item 5</li>
<li class="sub-item">Sub-Item 6</li>
<li class="sub-item">Sub-Item 7</li>
<li class="sub-item">Sub-Item 8</li>
</ul>
</li>
<li class="top-item">Top Item 4</li>
<li class="top-item">Top Item 5</li>
</ul>
</div>
<ul id="menu-button">
<li class="menu-button-cta">Button</li>
</ul>
</div>
</div>
As top-level items might be added or removed, I'd like to change the width of the parent element in accordance with the number of top-level items in menu.
For instance:
<ul id="top-menu"> has 5 <li class="top-item"> = .container {width: 100%;}
<ul id="top-menu"> has 4 <li class="top-item"> = .container {width: 90%;}
<ul id="top-menu"> has 3 <li class="top-item"> = .container {width: 80%;}
Is there a way to do it in CSS or jQuery?
You can do this in jquery using .children().length, eg:
$("ul.top-menu").each(function() {
$(this).addClass(".container-" + $(this).children(".top-item").length);
});
then css:
.container-5 { width: 100%; }
.container-4 { width: 90%; }
.container-5 { width: 80%; }
Here is my solution with jQuery. First, calculating length of children, then applying style accordingly.
var lengthOfChildren = $("#top-menu").children().length;
switch (lengthOfChildren) {
case 3:
$(".container").css("width", "80%");
break;
case 4:
$(".container").css("width", "90%");
break;
default:
$(".container").css("width", "100%");
}

Apply class to parent UL if child LI contains specific class

I'm currently working on a side menu that will list all pages in the relative section. I pretty much have this sorted apart from 1 small thing. We have 2 levels of dropdowns meaning there are an awful lot of links.
The LI that is active will have the class of .current_page_item. I'm trying to work out a way of saying:
If the UL has a child LI containing .current_page_item class then apply .side_open class to the UL.
$(document).ready(function(){
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>Demo 1
<ul>
<li class="current_page_item">Demo 11</li>
</ul>
</li>
<li>Demo 2
<ul>
<li>Demo 21</li>
</ul>
</li>
<li>Demo 3
<ul>
<li>Demo 31</li>
</ul>
</li>
<li>Demo 4
<ul>
<li>Demo 41</li>
</ul>
</li>
</ul>
If anyone has any ideas on how this can be done your help would be greatly appreciated!
From what I understand, you want to style the direct parent if the li is selected.
(Comment me if I'm wrong)
So, the following should be what you want to achieve:
(Done with some Javascript)
$(document).ready(function() {
$('ul>li>ul>li').each(function() {
if ($(this).hasClass('current_page_item')) {
$(this).parent().addClass('side_open');
}
});
});
.side_open {
background: #ddd;
}
.current_page_item {
background: #bbb;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>Demo 1
<ul>
<li class="current_page_item">Demo 11</li>
</ul>
</li>
<li>Demo 2
<ul>
<li>Demo 21</li>
</ul>
</li>
<li>Demo 3
<ul>
<li>Demo 31</li>
</ul>
</li>
<li>Demo 4
<ul>
<li>Demo 41</li>
</ul>
</li>
</ul>
You can use .parentElement property to access li's ul.
const linksArray = [...document.querySelectorAll('li')];
linksArray.forEach(link => {
link.onclick = function() {
linksArray.forEach(link => link.classList.remove('current_page_item'))
this.classList.add('current_page_item')
this.parentElement.classList.add('side_open')
}
})
.current_page_item {
background-color: aliceblue;
}
.side_open:before {
content: 'I have side open class';
}
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
You can do it using jquery. It's very simple, using each loop, traverse and check for class in each LI and add .side_open class in it's parent if that li has .current_page_item class.
$(document).ready(function(){
$('ul.main_ul>li>ul.sub_ul>li').each(function(){
if($(this).hasClass('current_page_item')){
$(this).parent().addClass('side_open');
}
});
});
.side_open {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="main_ul">
<li class="main_li">Demo 1
<ul class="sub_ul">
<li class="current_page_item">Demo 11</li>
<li class="current_page_item">Demo 12</li>
</ul>
</li>
<li class="main_li">Demo 2
<ul class="sub_ul">
<li>Demo 21</li>
<li>Demo 22</li>
</ul>
</li>
<li class="main_li">Demo 3
<ul class="sub_ul">
<li>Demo 31</li>
<li>Demo 32</li>
</ul>
</li>
<li class="main_li">Demo 4
<ul class="sub_ul">
<li>Demo 41</li>
<li>Demo 42</li>
</ul>
</li>
</ul>

Nested collapse

I'm trying to collapse a nested menu with jQuery. I read this answer and, to me, it appears to be similar to my solution. The problem is that mine doesn't work.
What I think I'm saying with my JavaScript code is: "hey, when a user clicks on a li that is the parent of a ul.submenu, get its ul.submenu children and attach the slideToggle only to it". But, as you can see from the snippet, it closes also the parent ul.submenu and I can't understand why.
$(document).ready(function () {
$('.submenu').hide();
$('.submenu').parent('li').click(function () {
$(this).children('ul.submenu').slideToggle("slow");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul class="menu">
<li>Home</li>
<li>Blog
<ul class="submenu">
<li>
Author
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Category</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Tag</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Post</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
</ul>
</li>
<li>Photo</li>
<li>Settings</li>
</ul>
</nav>
You want to stop the click event from bubbling up the DOM and triggering the click handler on the parent. Use .stopPropagation() for that:
$(document).ready(function() {
$('.submenu').hide();
$('.submenu').parent('li').click(function(e) {
e.stopPropagation()
$(this).children('ul.submenu').slideToggle("slow");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul class="menu">
<li>Home</li>
<li>Blog
<ul class="submenu">
<li>
Author
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Category</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Tag</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
<li>
<span>Post</span>
<ul class="submenu">
<li>New</li>
<li>Handle</li>
</ul>
</li>
</ul>
</li>
<li>Photo</li>
<li>Settings</li>
</ul>
</nav>

Mobile menu dropdown issue

Here is my website: http://lowandheavy.com
The problem is that when website opens in mobile the 2nd menu with name "women" not working like menu "men".
It opens the dropdown but redirecting immediately to the submenu 3. Here is the code:
<ul class="nav-menu navigation-tier navigation-tier-primary" data-navigation-tier-primary>
<li class="has-slide-out header-navigation-item navigation-item-primary">
<a class="navigation-link-primary" href="/" >Home</a>
</li>
<li class="dropdown has-slide-out header-navigation-item navigation-item-primary">
<a class="dropbtn navigation-link-primary" href="#">Men</a>
<div class="dropdown-content">
Tanks
T-shirts
</div>
</li>
<li class="dropdown has-slide-out header-navigation-item navigation-item-primary">
<a class="dropbtn navigation-link-primary" href="#">Women</a>
<div class="dropdown-content">
Leggings
Tanks
T-shirts
V-Neck
Unisex Tees
</div>
</li>
<li class="has-slide-out header-navigation-item navigation-item-primary">
<a class="navigation-link-primary" href="/hats/" >Hats</a>
</li>
<li class="has-slide-out header-navigation-item navigation-item-primary">
<a class="navigation-link-primary" href="/about/" >About</a>
</li>
<li class="has-slide-out header-navigation-item navigation-item-primary">
<a class="navigation-link-primary" href="/contact-us/" >Contact</a>
</li>
<li class="has-slide-out header-navigation-item navigation-item-primary">
<a class="navigation-link-primary" href="/news-feed/" >News</a>
</li>
</ul>
Lets DO the same on click
/***Add css in file***/
.dropdown.active .dropdown-content {
display: block;
}
/***Add Jquery in file***/
$('.navigation-link-primary').click(function(e){
$('.dropdown').removeClass('active');
$(this).parent().addClass('active');
});
By clicking on the menu name Men then same time click on menu name women you are facing issue that its not staying its redirecting
It is not the issue
It is happening because when you click on menu "Men" It opens a submenu of Men. then same time clicking on woman submenu of woman open and submenu of "Men" close so gap reduce between Men and Woman in directly you clicked upon one of the submenu of "Woman" (Maybe 2nd or 3rd submenu) not clicked upon the "Woman" menu and you are getting redirected.
Check below snippet
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<nav>
<ul class="nav">
<li>Link 1</li>
<li>Link 2 (toggle)
<ul class="nav collapse" id="submenu1" role="menu" aria-labelledby="btn-1">
<li>Link 2.1</li>
<li>Link 2.2</li>
<li>Link 2.3</li>
</ul>
</li>
<li>Link 3 (toggle)
<ul class="nav collapse" id="submenu2" role="menu" aria-labelledby="btn-1">
<li>Link 3.1</li>
<li>Link 3.2</li>
<li>Link 3.3</li>
</ul>
</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
</nav>
If you are directly open "woman" menu then you will not see your issue because at that time Submenu of "Men" menu is not open
$('.dropbtn.navigation-link-primary').click(function(e){
if($(this).hasClass('active')) {
$("a.dropbtn.navigation-link-primary").removeClass('active');
}
else {
$(this).addClass('active');
}
});
#media(max-width:850px) {
.dropdown:hover .dropdown-content {
display: none !important;
}
body.home .main-header-menu .header-navigation-item a {
width: 100% !important;
display: inline-block;
}
a.dropbtn.navigation-link-primary.active+div {
display: block !important;
}
}

Categories