I am using stopPropegation to aid me in the way my dropdowns work.
I am using it for multiple dropdowns to help me keep the dropdown open but if the user clicks anywhere else on the page then it will slide up the menu.
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
<div class="clear"></div>
<div id="login-top">Login</div>
<div id="user">roooar</div>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
.clear {
clear:both;
}
#login-top {
background:blue;
padding:10px;
color:white;
margin-top:30px
}
#user {
background:pink;
margin-top:10px;
padding:50px;
}
SCRIPT
$('#login-top').click(function () {
var $user = $('#user');
if ($('#user').is(':visible')) {
$user.slideUp(300);
} else {
$user.slideUp(300);
$user.slideDown(300);
}
});
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function () {
$(".dropdown").hide();
$("#user").slideUp();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
I have 2 questions really about this.
Say if I click open the dropdown menu because I have included certain elements to be exempt from clicking elsewhere on the page - If I click anywhere else it will slide back up exactly how I want.
However, if I happen to click on the #login-top this will not make it slide up as I have added it to the code for the stopPropagation
Is there a may of making it work so that when ".dropdown" is active then you can click absolutely everywhere (including on the <div id='login'> And then when "#login" and "#user" is active you can click anywhere on "nav" and it will still slide up the div?
Is it the right thing to be doing by grouping all the classes and id's into the code:
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
(I am struggling to explain this but hopefully you can see what I mean if you look at the fiddle version)
http://jsfiddle.net/susannalarsen/Nt2ZM/1/
Related
i refer to this thread: JS using onclick event on li to display block
From desktop is ok but how do i do the same thing but that from the mobile you can touch the "disappearing" menu and make sure that it remains visible until the next touch?
I'm currently using this code here:
function dropdown() {
document.getElementById("Menuitems").style.display = "block";
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul {
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
I just added an active class onclick .. the active class toggles on every click. and just add the same hover effect to active class
function dropdown() {
document.getElementById("Menuitems").classList.toggle("active");
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul,
#dropdown ul li>ul.active{
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
I have been trying to fix this problem for a while. Basically I am creating a drop down menu that has divs that contain the ul's so that I can have a box with a fixed width which will allow me to have images within the box.
An example of this would be BestBuy.com's navigation menu. I really like the design, but I'm having a difficult time replicating it.
My CSS works without trouble ONLY when the li's are not links. Example: It works when it is <li>Link</li> and not <li>Link</li>.
Of course inside that <li> is another list.
Anyway, I decided to use JQuery to fix the issue and I am about halfway there.
Here is my JQuery:
$(document).ready(function () {
$(".navbar ul li").hover(function() {
$(".navlink > div:first").addClass("active");
}, function() {
$(".navlink > div:first").removeClass("active");
});
$(".secondarylink").hover(function() {
$(".secondarylink > div").addClass("active");
}, function() {
$(".secondarylink > div").removeClass("active");
});
});
Here is my markup:
<div class="navbar">
<ul>
<li class="navlink"> Products
<div class="secondlevel">
<ul>
<li class="secondarylink">Testing 1
<div class="thirdlevel two-columns">
<div class="column">
<ul>
<li>Testing 1 </li>
<li>Testing 2 </li>
<li>Testing 3 </li>
<li>Testing 4 </li>
</ul>
</div>
<div class="column">
<ul>
<li>Testing 1 </li>
<li>Testing 2 </li>
<li>Testing 3 </li>
<li>Testing 4 </li>
</ul>
</div>
</div>
</li>
<li class="secondarylink">Testing 2
<div class="thirdlevel">
<ul>
<li>Testing 1</li>
<li>Testing 2</li>
<li>Testing 3</li>
<li>Testing 4</li>
</ul>
</div>
</li>
<li>Testing 3</li>
<li>Testing 4</li>
</ul>
</div>
</li>
<li class="navlink">Test Link</li>
</ul>
</div>
And my styling:
body {
font-family:sans-serif;
background: #eee;
}
.navlink {
display:block;
}
.navbar {
background:lightblue;
width: 100%;
padding:0;
}
.navbar ul {
list-style:none;
padding:0;
margin:0;
}
.navbar ul>li {
display:inline-block;
}
.navbar ul li ul>li {
display:block;
}
.secondlevel {
position:absolute;
width:350px;
height:477px;
background:#fff;
padding:0;
border: 1px solid #c3c4c4;
}
.thirdlevel {
position:absolute;
width:350px;
height:477px;
background:lightgreen;
left:350px;
border: 1px solid #c3c4c4;
top:-1px;
}
.thirdlevel.two-columns {
width:700px;
}
.thirdlevel div:first-child {
position:absolute;
left:0;
}
.thirdlevel div {
position:absolute;
right:0;
}
.column {
width:350px;
}
.thirdlevel {
display:none;
}
.secondlevel {
display:none;
}
/*
.navbar ul li:hover > div:first-child {
display:block;
}
*/
.active {
display:block;
}
.hidden {
display:none;
}
.navbar ul li a {
display:block;
}
Demo
As you can see, in my CSS I had .navbar ul li:hover > div:first-child { display:block;}. This works, but without the links... Someone told me to try making the <a> display:block; but that didn't work either.
All I need to do(I think) is be able to select div:first-child for this to work, but so far I haven't found anything that works. What am I doing wrong?
Any help is greatly appreciated. Thank you people!
I'm not entirely sure what you're after, but maybe this helps.
With CSS:
.navbar > ul > li:hover > .secondlevel {
display: block;
}
.navbar .secondarylink:hover > .thirdlevel {
display: block;
}
Demo
With jQuery:
$(".navbar ul li").hover(function () {
$(this).find('.secondlevel').show();
}, function () {
$(this).find('.secondlevel').hide();
});
$(".secondarylink").hover(function () {
$(this).find('.thirdlevel').show();
}, function () {
$(this).find('.thirdlevel').hide();
});
Demo
It's doesn't matter with the <li>item</li> or <li>item</li> as long as you have the correct script.
As I looked into your script, the action you trigger is to add 'active' class to all the second/third level.
I've updated the script and now it only add class to the second level / third level accordingly.
$(this).find().addClass();
DEMO
I really like the way Stack Overflow has done their dropdown menus on the top. Notice how you must click in order for the dropdown to trigger, but you still must hover to get the dropdown. There is also what seems to be groups - once you click, hover will activate the menus shown in the picture. It is hard to explain, but if you play around for a minute you'll see what I mean. Also, it is important that the last hovered menu will show until a user clicks off again.
Here is what I have so far; note that I almost have the same functionality, except for the last menu hovered doesn't stay dropped (it closes on mouseout when it shouldn't until off-click) and the toggle functionality is sketchy:
$(document).ready(function() {
var depressed = false;
$('.menu').click(function() {
depressed = true;
$('.menu').toggleClass('active');
});
$('.menu').hover(function() {
if (depressed) {
$('.menu').toggleClass('active');
}
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li.active:hover ul {
display: block;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu">button 1
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 2
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 3
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
My JS is not cuttin git.
So, what is the best way to go about this?
I haven't peeked into the SO menu, so I don't know how they did it. But this seems to work nicely.
A click on one of the buttons opens the dropdown.
The dropdown is not closed by a 'mouseout', like in your code, but only when another menu is hovered. If you hover outside of the menu area, the lastly hovered menu remains open.
Clicking anywhere closes the menu.
So showing the menu is not directly done by using a :hover pseudo element in CSS, but by adding a class, which remains there even when the menu is unhovered. I think the net result behaves pretty close to Stack Overflow's.
$(function(){
// The event to handle clicks outside of the menu. This will close the menu.
var offEvent =
function(event){
$('.menu-bar').removeClass('active');
$(document).off('click', offEvent);
};
// The click event on the menu buttons, to toggle 'menu mode' as it were.
$(document).on('click', '.menu-bar .menu',
function(event){
event.preventDefault();
$('.menu-bar').addClass('active');
$(this).addClass('active');
// Leave menu mode by clicking anywhere of the menu.
$(document).on('click',
offEvent
);
});
// Hover toggles between the dropdowns of the separate menus.
$('.menu-bar .menu').hover(
function(event){
var $current = $(this);
$('.menu').each(
function(index, element){
var $element = $(this);
if ($element.get(0) == $current.get(0)) {
$element.addClass('active');
} else {
$element.removeClass('active');
}
});
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
.menu .dropdown {
display: none;
}
.menu-bar.active .menu.active .dropdown {
display: block;
}
.menu {
display: inline-block;
position: relative;
border: 1px solid grey;
}
.menu .dropdown {
position: absolute;
top: 100%;
left: 0;
border: 2px solid #555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu-bar">
<li class="menu">button 1
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 2
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 3
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
$(document).ready(function() {
$('#M1').click(function() {
$('#M1').toggleClass('active');
$('#M2').removeClass('active');
$('#M3').removeClass('active');
});
$('#M2').click(function() {
$('#M2').toggleClass('active');
$('#M1').removeClass('active');
$('#M3').removeClass('active');
});
$('#M3').click(function() {
$('#M3').toggleClass('active');
$('#M1').removeClass('active');
$('#M2').removeClass('active');
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li.active ul {
display: block;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu" id='M1'>button 1
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu" id='M2'>button 2
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu" id='M3'>button 3
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
This works for me.
I've just removed :hover from the end of the .active class and made an individual function for each button.
I don’t quite understand javascript, but managed to have a tabbed area thanks to google god.
When the tab button is clicked, corresponding contents are displayed. I wish to add one more function as below.
Even if no tab button is clicked, switch to the next tab every 5 seconds.
If current active tab is Tab 4 and 5 seconds have passed, switch back to Tab 1.
Below is my current code.
/* CSS for Tabs */
.tabs { list-style: none; margin-top: 30px; }
.tabs li { display: inline; }
.tabs li a { min-width: 20%; color: black; float: left; display: block; padding: 1%; margin-left: 1%; margin-right: 1%; position: relative; text-decoration: none; text-align: center; border-top: 1px solid #333; border-bottom: 1px solid #333; }
.tabs li a:hover { font-weight: bold; background: #fff; border-top: 1px solid #333; border-bottom: 1px solid #333; }
.tabs li a:active { font-weight: bold; background: #fff; border-top: 1px solid #333; border-bottom: 1px solid #333; }
/* HTML */
<div id="tabs">
<ul class="tabs" id="tabsnav">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
<li>Tab 4</li>
</ul>
<div id="tab-1">
Contents for tab 1
</div>
<div id="tab-2">
Contents for tab 2
</div>
<div id="tab-3">
Contents for tab 3
</div>
<div id="tab-4">
Contents for tab 4
</div>
</div>
/* JAVA */
<script>
jQuery(document).ready(function() {
jQuery('#tabs > div').hide(); // hide all child divs
jQuery('#tabs div:first').show(); // show first child div
jQuery('#tabsnav li:first').addClass('active');
jQuery('.menu-internal').click(function(){
jQuery('#tabsnav li').removeClass('active');
var currentTab = jQuery(this).attr('href');
jQuery('#tabsnav li a[href="'+currentTab+'"]').parent().addClass('active');
jQuery('#tabs > div').hide();
jQuery(currentTab).show();
return false;
});
// Create a bookmarkable tab link
hash = window.location.hash;
elements = jQuery('a[href="'+hash+'"]'); // look for tabs that match the hash
if (elements.length === 0) { // if there aren't any, then
jQuery("ul.tabs li:first").addClass("active").show(); // show the first tab
} else { elements.click(); } // else, open the tab in the hash
});
</script>
I guess I need to add more codes to the above script, such as “go to the next tab after 5 seconds, and go back to tab 1 after tab 4”. However, I don’t know how to programming and at a loss.
A professional help will be highly appreciated.
Thank you.
Try this
DEMO
This one is pretty much what you want.
Add your own css to it
HTML :
<div id="tabs">
<ul class="tabs" id="tabsnav">
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
<li>Tab 4</li>
</ul>
<div id="tab-1">
Contents for tab 1
</div>
<div id="tab-2">
Contents for tab 2
</div>
<div id="tab-3">
Contents for tab 3
</div>
<div id="tab-4">
Contents for tab 4
</div>
</div>
JAVASCRIPT:
jQuery(document).ready(function() {
jQuery('#tabs > div').hide(); // hide all child divs
jQuery('#tabs div:first').show(); // show first child div
jQuery('#tabsnav li:first').addClass('active');
jQuery('.menu-internal').click(function(){
jQuery('#tabsnav li').removeClass('active');
var currentTab = jQuery(this).attr('href');
jQuery('#tabsnav li a[href="'+currentTab+'"]').parent().addClass('active');
jQuery('#tabs > div').hide();
jQuery(currentTab).show();
return false;
});
// Create a bookmarkable tab link
hash = window.location.hash;
elements = jQuery('a[href="'+hash+'"]'); // look for tabs that match the hash
if (elements.length === 0) { // if there aren't any, then
jQuery("ul.tabs li:first").addClass("active").show(); // show the first tab
} else { elements.click(); } // else, open the tab in the hash
});
Hope this helps
I am attempting to make a dropdown menu that when clicked stays down but also, when clicking anywhere within the dropdown area, it will not slide up. Only when clicked elsewhere on the page should it disappear.
I am struggling to make this happen though. You can see what I am doing here:
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
SCRIPT
$('nav li').click(function () {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
$('.dropdown').slideUp(300);
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function(){
$(".dropdown").hide();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav").click(function(e){
e.stopPropagation();
});
Here is fiddle version:
http://jsfiddle.net/susannalarsen/buNq9/
You will need to work with the event target property and traverse up its parents to find out what element has triggered the event. if it's an element inside ".dropdown" class, then no sliding-up should be applied, otherwise close dropdown.
example
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} ...
Notice that i changed the selection in $('nav > ul > li'), which will apply only to the LI elements of the upper level.