jquery use .stopPropagation() on hover menu - javascript

How to use event .stopPropagation() (or something else) in the following situation.
I have a standard menu with submenu. In the submenu background, I have background image which I need to overlay adding pseuso-element (background:green) on the parent. Because with jquery I cant control css pseudo-elements (I need control opacity), I add another class to my parent.
Everything works as I need, but adding / removing the class on parent makes the image background blink.
jsfiddle
my site live (top menu is my problem)
HTML:
<ul class="top-menu">
<li>
link 1
<div class="submenu">
<ul>
<li>sublink 1</li>
<li>sublink 2</li>
<li>sublink 3</li>
<li>sublink 4</li>
<li>sublink 5</li>
</ul>
</div>
</li>
<li>link 2</li>
<li>link 3</li>
</ul>
jquery
$(".submenu a").mouseover(function(e){
$(".submenu").addClass("myclass");
}).mouseout(function(e){
var cover = $(".submenu");
cover.data('timer', setTimeout(function(){
cover.removeClass("myclass");
}, 2000)
);
e.stopPropagation();
});
css
*{
box-sizing:border-box;
}
ul.top-menu {
display:flex;
list-style:none;
text-transform:uppercase;
width:100%;
justify-content:center;
background:white;
position:relative;
}
ul.top-menu li a {
color:black;
padding:10px;
text-decoration:none;
display:block;
}
.submenu {
position:absolute;
background:red url("http://www.metalclays.com/content/images/thumbs/0002871_texture-tile-fireworks_100.jpeg");
background-position:right top;
background-size:200px auto;
background-repeat:no-repeat;
width:100%;
top:100%;
left:0;
z-index:0;
}
.submenu:after {
content:"";
background:green;
width:100%;
height:100%;
position:absolute;
top:0;
left:0;
opacity:0;
z-index:-1;
}
.submenu.myclass:after {
opacity:1;
}
.submenu ul {
list-style:none;
}
.submenu a {
color:white;
display:block;
}

have you tried this?
$(".submenu a").mouseover(function(e){
$(".submenu").addClass("myclass");
}).mouseout(function(e){
e.preventDefault();
$(".submenu").removeClass("myclass");
});

but adding / removing the class on parent makes the image background blink
This happens because on mouseover you add and add the class. Change from:
$(".submenu a").mouseover(function(e){
$(".submenu").addClass("myclass");
})
to:
$(".submenu a").mouseover(function(e){
if ($(".submenu.myclass").length == 0) {
$(".submenu").addClass("myclass");
}
})
The updated fiddle.

Related

Open child div on hover parent and close other child divs ( w/ Javascript)

When I open a child div on hover with Javascript it works, also when I hover over the next parent div that child div opens but when I go back to the first parent the second one stays open (on top) and doesn't fade-out.
What I would like is that the other child div('s) close when hovering to a new one. Maybe good to know is that I only want the other child div(s) to close when hovering to a new parent with a child div not when im just hovering out of the current parent.
Does anyone know the trick?
$('li.menu-item-has-children').hover(function () {
$('ul.dropdown-menu-main', this).fadeIn('slow');
});
ul, ul li {
list-style:none;
padding:0;
margin:0;
}
li {
display: inline-block;
position: relative;
margin-right:20px !important;
}
ul.dropdown-menu-main {
display:none;
position:fixed;
top:0px;
left:0px;
width:100%;
height:100vh;
background:black;
z-index:-1;
padding:50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="menu-item-has-children">
<a href="#">Main 1</div>
<ul class="dropdown-menu-main">
<li>Sub 1</li>
</ul>
</li>
<li class="menu-item-has-children">
<a href="#">Main 2</div>
<ul class="dropdown-menu-main">
<li>Sub 2</li>
</ul>
</li>
</ul>
I found the solution when 'parent()' and 'children()' are not 'this'.
$('li.menu-item-has-children').hover(function () {
$('ul.dropdown-menu-main', this).fadeIn('slow');
$(this).parent().children().not(this).find('ul.dropdown-menu-main').fadeOut('fast');
});
ul, ul li {
list-style:none;
padding:0;
margin:0;
}
li {
display: inline-block;
position: relative;
margin-right:20px !important;
}
ul.dropdown-menu-main {
display:none;
position:fixed;
top:0px;
left:0px;
width:100%;
height:100vh;
background:black;
z-index:-1;
padding:50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="menu-item-has-children">
<a href="#">Main 1</div>
<ul class="dropdown-menu-main">
<li>Sub 1</li>
</ul>
</li>
<li class="menu-item-has-children">
<a href="#">Main 2</div>
<ul class="dropdown-menu-main">
<li>Sub 2</li>
</ul>
</li>
</ul>
Sorry have just re-read your question and realised you wanted the menu to stay active. I've created a demonstration which does this by adding an .active class and toggling the submenus are you initially wanted using fadeIn and fadeOut. This will also allow you to attribute css styles to the dropdown if you would rather use that rather than jquery.
// Toggle function on hover, ignore if already active
$(".menu-item-has-children:not('.active')").hover( function() {
// Remove active class from all menus
$(".menu-item-has-children.active").toggleClass();
// Add toggle class to this menu
$(this).toggleClass("active");
// Fade out existing dropdown menus
$(".dropdown-menu-main").fadeOut('slow');
// Fade in this child dropdown menu
$(this).find(".dropdown-menu-main").fadeIn('slow');
});
The second example I will leave up for others, it shows how to do a more traditional dropdown where it fades out once the hover leaves the parent. You can use the exit function as well as the entry function of hover, the first function you provide is ran on mouseenter and the second on mouseleave.
Jquery .hover()
EXAMPLE WITH PERSISTENT DROPDOWNS
// Toggle function on hover, ignore if already active
$(".menu-item-has-children:not('.active')").hover( function() {
// Remove active class from all menus
$(".menu-item-has-children.active").toggleClass();
// Add toggle class to this menu
$(this).toggleClass("active");
// Fade out existing dropdown menus
$(".dropdown-menu-main").fadeOut('slow');
// Fade in this child dropdown menu
$(this).find(".dropdown-menu-main").fadeIn('slow');
});
ul, ul li {
list-style:none;
padding:0;
margin:0;
}
li {
display: inline-block;
position: relative;
margin-right:20px !important;
}
ul.dropdown-menu-main {
display:none;
position:fixed;
top:0px;
left:0px;
width:100%;
height:100vh;
background:black;
z-index:-1;
padding:50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="menu-item-has-children">
<a href="#">Main 1</div>
<ul class="dropdown-menu-main">
<li>Sub 1</li>
</ul>
</li>
<li class="menu-item-has-children">
<a href="#">Main 2</div>
<ul class="dropdown-menu-main">
<li>Sub 2</li>
</ul>
</li>
</ul>
EXAMPLE WITH TRADITIONAL DROPDOWNS
These collapse when the hovering over the parent ends.
// Hover function
$('li.menu-item-has-children').hover(
// Hover in function
function() {
$('ul.dropdown-menu-main', this).fadeIn('slow');
},
// Hover exit function
function() {
$('ul.dropdown-menu-main', this).fadeOut('slow');
}
);
ul,
ul li {
list-style: none;
padding: 0;
margin: 0;
}
li {
display: inline-block;
position: relative;
margin-right: 20px !important;
}
ul.dropdown-menu-main {
display: none;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100vh;
background: black;
z-index: -1;
padding: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="menu-item-has-children">
<a href="#">Main 1</div>
<ul class="dropdown-menu-main">
<li>Sub 1</li>
</ul>
</li>
<li class="menu-item-has-children">
<a href="#">Main 2</div>
<ul class="dropdown-menu-main">
<li>Sub 2</li>
</ul>
</li>
</ul>

How to replace hover for mobile device

I tried to use :active for the mobile device but it doesn't seem to work. Can I do this with css or do I need to create mouseover listeners in javascript?
#major{
display:flex;
justify-content:space-around;
list-style-type:none;
}
#minor1,#minor2{
display:none;
}
#about:hover, #take:hover{
background-color:#538231;
color:white;
}
#take:hover #minor2, #take:active #minor2 {
display:flex;
position:absolute;
justify-content:start;
left:0 ;
list-style-type:none;
background-color:#538231;
color:white;
width:100%;
}
#about:hover #minor1, #about:active #minor1{
display:flex;
position:absolute;
justify-content:start;
left:0;
list-style-type:none;
background-color:#538231;
color:white;
width:100%;
}
#navbar{
position:relative;
font-size:3.5vw;
color:#538231;
background-color:#b3d7f7;
}
li{
margin:0!important;
}
#minor1 li{
margin-left:3vw!important;
}
#minor2 li{
margin-left:1vw!important;
margin-right:5vw!important;
}
<div id="navbar">
<ul id="major">
<li>HOME</li>
<li id="about">ABOUT US
<ul id="minor1">
<li>OUR STORY</li>
<li>OUR WORK</li>
<li>SWAG LEADERS</li>
<li>IN THE NEWS</li>
</ul>
</li>
<li>CALENDAR</li>
<li id="take">TAKE ACTION
<ul id="minor2">
<li>GET INVOLVED</li>
<li>DONATE</li>
</ul>
</li>
<li>RESOURCES</li>
</ul>
</div>
If I have to go on only pure HTML and CSS, I have two options for this.
First is to put an attribute tabindex="0" on li tag then add :focus selector on the css. But the problem with this is that you have to click somewhere else to display none the sub-menus.
Second is to have a checkbox to accommodate the click/unclick event. I just set an example for mobile view, #media query of max-width: 800px. So please resize the browser when you check this.
Please check my code below:
#major{
display:flex;
justify-content:space-around;
list-style-type:none;
}
#minor1,#minor2{
display:none;
}
#about:hover, #take:hover{
background-color:#538231;
color:white;
}
#take:hover #minor2, #take:active #minor2 {
display:flex;
position:absolute;
justify-content:start;
left:0 ;
list-style-type:none;
background-color:#538231;
color:white;
width:100%;
}
#about:hover #minor1, #about:active #minor1{
display:flex;
position:absolute;
justify-content:start;
left:0;
list-style-type:none;
background-color:#538231;
color:white;
width:100%;
}
#navbar{
position:relative;
font-size:3.5vw;
color:#538231;
background-color:#b3d7f7;
}
li{
margin:0!important;
}
#minor1 li{
margin-left:3vw!important;
}
#minor2 li{
margin-left:1vw!important;
margin-right:5vw!important;
}
input[type="checkbox"] {
position: absolute;
opacity: 0;
}
#media only screen and (max-width: 800px) {
#about input[type="checkbox"]:checked ~ label, #take input[type="checkbox"]:checked ~ label {
background-color:#538231;
color:white;
}
#about input[type="checkbox"]:checked ~ ul, #take input[type="checkbox"]:checked ~ ul {
display:flex;
position:absolute;
justify-content:start;
left:0;
list-style-type:none;
background-color:#538231;
color:white;
width:100%;
}
}
<div id="navbar">
<ul id="major">
<li>HOME</li>
<li id="about">
<input type="checkbox" id="check">
<label for="check">ABOUT US</label>
<ul id="minor1">
<li>OUR STORY</li>
<li>OUR WORK</li>
<li>SWAG LEADERS</li>
<li>IN THE NEWS</li>
</ul>
</li>
<li>CALENDAR</li>
<li id="take">
<input type="checkbox" id="check2">
<label for="check2">TAKE ACTION</label>
<ul id="minor2">
<li>GET INVOLVED</li>
<li>DONATE</li>
</ul>
</li>
<li>RESOURCES</li>
</ul>
</div>

Dropdown animation icon

Assuming I have a dropdown menu just like this one:
http://jsfiddle.net/1fb9nqb1/
$('#toggle').click(function () {
$('#dropdown').slideToggle();
$('#opt-slide').toggleClass('open');
});
$('#dropdown > li').click(function () {
$('#dropdown').slideUp();
$('#opt-slide').removeClass('open');
});
* {
margin:0;
padding:0;
font-family:Arial, Helvetica, sans-serif;
}
header {
height:200px;
background:#39F;
z-index:4;
}
#opt-slide {
width:300px;
}
#toggle {
background:#099;
display:block;
height:50px;
color:#FFF;
line-height:50px;
z-index:4;
}
#dropdown {
background:#0C9;
list-style:none;
margin-top:0px;
z-index:2;
display:none;
}
#dropdown li {
height:40px;
line-height:40px;
}
#dropdown li:hover {
background:#FAFAFA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="opt-slide"> <span id="toggle">OPTIONS</span>
<ul id="dropdown">
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
<li>Option 4</li>
<li>Option 5</li>
</ul>
</div>
how can I add animation just like this one:
https://dribbble.com/shots/1621359-Open-Close-Icon-Animation
to support the expand / collapse of the menu?
another thing, is there any way to do the dropdown menu without jQuery?
Thanks
If you check this JS Fiddle, you'll see that I've added two spans #s1 and #s2, with a container div#sign, the span is rotated 45deg but opposite to each others, when the menu is hidden the two spans are position in a way representing an arrow shape, if you click on the toggle span, .class1 and .class2 are added to to #s1 and #s2 respectively, these classes has different margin-left values making the two spans forming the X-shape with transitio, where original margin-left valeus set in each span css with transition to make them moving in and out smoothly instead of just jumping all in css, you could however animate these spans with jquery .animate() setting same values with easing too but since it could be done with css I'd go with it:
Edit-1: Code changed upon a comment, changed div#sign to span#sign and made it a child of span#toggle JS Fiddle 2
Updated Code:
$('#toggle').click(function() {
$('#dropdown').slideToggle();
$('#opt-slide').toggleClass('open');
$('#sign #s1').toggleClass('close1');
$('#sign #s2').toggleClass('close2');
});
$('#dropdown > li').click(function() {
$('#dropdown').slideUp();
$('#opt-slide').removeClass('open');
});
* {
margin:0;
padding:0;
font-family:Arial, Helvetica, sans-serif;
}
header {
height:200px;
background:#39F;
z-index:4;
}
#opt-slide {
width:300px;
position:relative;
}
#toggle {
background:#099;
display:block;
height:50px;
color:#FFF;
line-height:50px;
z-index:4;
position:relative;
}
#dropdown {
background:#0C9;
list-style:none;
margin-top:0px;
z-index:2;
display:none;
}
#dropdown li {
height:40px;
line-height:40px;
}
#dropdown li:hover {
background:#FAFAFA;
}
#sign{
width:50px;
height:25px;
display:inline-block;
position:absolute;
top:25px;
right:10px;
}
#sign .s{
width:25px;
height:4px;
display:inline-block;
border-radius:2px;
background-color:white;
position:absolute;
}
#sign #s1{
transform:rotate(45deg);
z-index:100;
margin-left:0;
transition:all 0.5s ease-out;
}
#sign #s2{
transform:rotate(-45deg);
z-index:200;
margin-left:16px;
transition:all 0.5s ease-in;
}
#sign #s2.close2{
margin-left:7px;
transition:all 0.5s ease-out;
}
#sign #s1.close1{
margin-left:7px;
transition:all 0.5s ease-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="opt-slide"> <span id="toggle">OPTIONS<span id="sign"><span id="s1" class="s"></span><span id="s2" class="s"></span></span>
</span>
<ul id="dropdown">
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
<li>Option 4</li>
<li>Option 5</li>
</ul>
</div>

Making a drop-down menu scrollable

I am trying to implement a drop down menu in a HTML page using CSS and jquery. Here is a sample of the HTML and javascript code.
<nav id="topNav">
<ul>
<li>Menu 1</li>
<li>
Menu 2
<ul>
<li>Sub Nav Link 1</li>
<li>Sub Nav Link 2</li>
<li>Sub Nav Link 3</li>
<li>Sub Nav Link 4</li>
<li class="last">Sub Nav Link 5</li>
</ul>
</li>
<li>
Menu 3
</li>
</ul>
</nav>
Here is the Javascript code:
var nav = $("#topNav");
//add indicators and hovers to submenu parents
nav.find("li").each(function() {
if ($(this).find("ul").length > 0) {
$("<span>").text("^").appendTo($(this).children(":first"));
//show subnav on hover
$(this).click(function() {
$(this).find("ul").stop(true, true).slideToggle();
});
}
});
I will be adding content to menu programmatically, and I want the dropdown menus to be scrollable when the content of the dropdown menu gets too large.
How can I do this?
Try this using css like,
#topNav ul li ul{
max-height:250px;/* you can change as you need it */
overflow:auto;/* to get scroll */
}
Demo
There is a css property max-height you can use it:
#topNav ul ul{
max-height:150px; // you choice of number in pixels
overflow-x:hidden; // hides the horizontal scroll
overflow-y:auto; // enables the vertical scroll
}
Why not use a purely CSS solution?
FIDDLE
You can change the transition property to have the style of animation for the slide you prefer, and the max-height value to limit the size of the dropdown before scrolling occurs.
HTML
<ul id='menu'>
<li>item</li>
<li>item</li>
<li>dropdown
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
</li>
</ul>
CSS
body, html {
width:100%;
}
ul {
list-style:none;
margin:0;
padding:0
}
#menu > li {
display:inline-block;
border:1px solid grey;
position:relative;
}
#menu li ul {
position:absolute;
border:1px solid grey;
width:100%;
max-height:0;
overflow:hidden;
-moz-transition: 1s;
-ms-transition: 1s;
-o-transition: 1s;
-webkit-transition: 1s;
transition: 1s;
}
#menu li:hover ul {
overflow:auto;
max-height:50px;
}
use CSS style:
#topNav{
overflow:scroll;
}
Isn't it possible to set a height and then overflow: auto, as CSS a property? and the scroll will automatically appear?

Submenu disappears as soon as I reach it with a mouse

I have a menu and a submenu. I got it toggled in Jquery by combining some answers from stackoverflow and from api.jQuery. But now I am really stuck and I cant find a way out to solve it.
Whenever I reach the menu, submenu toggles(Good thing), but whenever I reach for the submenu links it disappears.
And it doesnot work in fiddle because of the styling, thats why I didnt put it there.
HTML
<ul id="menüü">
<li class="menu">
<p>Meist
</p>
<ul class="submenu">
<li class="asi1">Asi 1</li>
<li class="asi2">Asi 2</li>
<li class="asi3">Asi 3</li>
</ul>
</li>
<li class="menu">
<p>Seadmed
</p>
<ul class="submenu">
<li class="item1">Item 1</li>
<li class="item2">Item 2</li>
<li class="item3">Item 3</li>
</ul>
</li>
</ul>
<div id="submenu"></div>
CSS
.menu {
display: inline;
float:left;
width:180px;
height:50px;
color:#191919;
text-align:center;
background:#990000;
-moz-border-radius-top-left: 50px;
border-top-left-radius: 50px;
position:relative;
}
.submenu {
font-size:14px;
display:none;
position:absolute;
top:62px;
right:25%;
z-index:300
}
.submenu {
background-color:#cecece;
}
.submenu > li {
list-style-type:none;
background-color:#fff;
color:blue;
cursor:pointer;
}
#submenu {
color:white;
height:40px;
width:900px;
background:#630000;
margin-top:50px;
position:relative;
}
JS
$(document).ready(function () {
$("li.menu").mouseenter(function () {
$(this).find(".submenu").toggle();
});
});
Change mouseenter to mouseover then when you hover a child element it will not close. And use mouseover to show and mouseout to hide.
Example on jsFiddle
$(document).ready(function ()
{
$(".menu").mouseover(function ()
{
$(this).find(".submenu").show();
});
$(".menu").mouseout(function ()
{
$(this).find(".submenu").hide();
});
});
Toggling toggles between show and hide, so the first time the mouseenter event is triggered it will show and the second time it hides. You need to add a conditional statement to make sure it doesn't hide it if the mouse is over it. Better way to do it is to use mouseenter to show and mouseout to hide.
Not a perfect example by any means, but this pure css version should provide a good base to get you started?
http://jsfiddle.net/bNpnZ/2/
<ul class="menu">
<li> Meist
<ul class="submenu">
<li class="asi1">Asi 1</li>
<li class="asi2">Asi 2</li>
<li class="asi3">Asi 3</li>
</ul>
</li>
<li> Seadmed
<ul class="submenu">
<li class="item1">Item 1</li>
<li class="item2">Item 2</li>
<li class="item3">Item 3</li>
</ul>
</li>
</ul>
ul {
margin:0;
list-style:none;
}
.menu {
width:100%;
float:left;
background:#eee;
}
.menu > li {
float:left;
margin:0 0 0 10px;
position:relative;
}
.menu > li:first-child {
margin:0;
}
.menu > li > a {
padding:10px 20px;
float:left;
color:#666;
}
.submenu {
position:absolute;
top:-9999em;
left:0;
font-size:14px;
background-color:#ccc;
}
.menu > li:hover .submenu {
top:30px;
}
I have update the jquery and added style for .menu a, also <p> in not required in side the li.
jQuery
$('.menu').hover(
function () {
$(this).children('.submenu').fadeIn('fast');
},
function () {
$(this).children('.submenu').fadeOut();
});
css
.menu a{
display:block;
line-height:50px;
}
.submenu {
font-size:14px;
display:none;
position:absolute;
top:50px;
right:25%;
z-index:300
}
html
<ul id="menüü">
<li class="menu">
Meist
<ul class="submenu">
<li class="asi1">Asi 1</li>
<li class="asi2">Asi 2</li>
<li class="asi3">Asi 3</li>
</ul>
</li>
<li class="menu">
Seadmed
<ul class="submenu">
<li class="item1">Item 1</li>
<li class="item2">Item 2</li>
<li class="item3">Item 3</li>
</ul>
</li>
</ul>
jsFiddle File

Categories