I'm new to Javascript so this may be a stupid question, but I'm at a loss. I've been trying to get my dropdown to hide/close when the right list item is selected. I'm using the hover dropdown provided by W3Schools. I've copied the CSS they've provided and my HTML and JS look like this:
<div class="dropdown" id = "menu3">
<button class="dropbtn" id = "menu3btn">Menu 3</button>
<div class="dropdown-content" id = "menu3c">
<ul>
<li><a id="item30">Cheese</a></li>
<li><a id="item31">Pepperoni</a></li>
<li><a id="item32">Sausage</a></li>
</ul>
</div>
</div>
And JS:
$(document).ready(function(){
$('li').click(function(){
if($(this).text() == "Sausage"){
$(this).parent().parent().hide();
}
}
}
The current Javascript is closing the dropdown if the user clicks "Sausage", which is what I want. But when I hover over the menu again, the dropdown doesn't open/show. I've tried changing
$(this).parent().parent().hide();
to
$(this).parent().hide();
and the results are the same.
I've also tried to toggle the dropbtn by replacing the parent().hide() code with:
var btnName = "#"+$(this).parent().parent().parent().attr("id")+"btn";
$(btnName).toggle();
This removed the button and dropdown menu from the screen entirely.
I've also tried forcing the hover to show hidden dropdown-content by adding this method to my JS:
$(".dropdown").hover(function() {
if($(this).attr("id") == "menu3"){
$("#menu3c").show();
}
}
This didn't do anything either (the hidden content stayed hidden).
Any help would be much appreciated.
Instead of $(this).parent().parent().hide();, you can use this to hide the parent
$(this).closest('div').hide();
To show the menu again,
$('#menu3btn').on('click', function() {
$('#menu3c').toggle();
});
Related
I'm simply creating a nav menu and have a basic unordered list with a "sub-menu" within. Here's the Jquery. The reason for the "active" class and if statement is that I want the slider to remain open if choosing another item on the list, so that it doesn't close and open again each iteration.
The problem part here for me in the code is here.
$('.slider').html( $(this).find('ul') );
The main issue is that on('click',), is only updating the first time it's clicked. On a second click on another item in the menu, it doesn't update itself with the new selection and therefore doesn't show the new sub-menu list? Console log shows that it is undefined. But it should be like the first time?
I don't understand why this is happening or the reasons behind it! Logic tells me the same thing that happens the first time, should keep happening, and therefore work?! Help appreciated before I make a hole in the wall with me forehead!
$(document).ready(function() {
$('ul > li > ul').hide();
$('.slider').hide();
// Menu
$('.menuNav > ul > li').on('click', function() {
// if active
if ( $(this).hasClass('active') ) {
$(this).parents().children().removeClass('active');
$('.slider').hide('slide', 200);
}
// if unactive
else {
$(this).addClass('active');
$('.slider').show('slide', 200);
$(this).siblings().removeClass('active');
// Show related list
$('.slider').html( $(this).find('ul') );
}
});
});
HTML
<div class="menuNav">
<ul>
<li><span>item_1</span>
<div class="sub_position">
<ul>
<li>sub-item_1-1</li>
<li>sub-item_1-2</li>
<li>sub-item_1-3</li>
<li>sub-item_1-4</li>
</ul>
</div>
</li>
<li><span>item_2</span>
<div class="sub_position">
<ul>
<li>sub-item_2-1</li>
<li>sub-item_2-2</li>
<li>sub-item_2-3</li>
<li>sub-item_2-4</li>
</ul>
</div>
</li>
.... etc
</ul>
</div>
Your issue likely arises from the fact that you are actually moving the entire submenu into .slider, instead of cloning it. This means that the submenu will be removed from the original menu the first time you click it, and clicking on it again will mean that the nested submenu selector $(this).find('ul') will return an empty set.
To circumvent this issue, I suggest that you do the following:
Append the outerHTML of the submenu to slider, i.e. $(this).find('ul')[0].outerHTML
If you want to hide the submenu in the menu when this is done, simply hide/unhide it when appropriate.
You can always use $(this).find('ul').html() for the same effect, but remember that <li> elements must be immediate children of <ul>. Therefore, we need to clone the outerHTML as well (i.e. copy the <ul>) to ensure that you have a valid HTML being injected into your slider.
$(document).ready(function() {
$('ul > li > ul').hide();
$('.slider').hide();
// Menu
$('.menuNav > ul > li').on('click', function() {
// if active
if ($(this).hasClass('active')) {
$(this).parents().children().removeClass('active');
$('.slider').hide('slide', 200);
}
// if unactive
else {
$(this).addClass('active');
$('.slider').show('slide', 200);
$(this).siblings().removeClass('active');
// Show related list (changed: now we use HTML's native outerHTML object
$('.slider').html($(this).find('ul')[0].outerHTML);
}
});
});
.slider {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="slider"></div>
<div class="menuNav">
<ul>
<li><span>item_1</span>
<div class="sub_position">
<ul>
<li>sub-item_1-1</li>
<li>sub-item_1-2</li>
<li>sub-item_1-3</li>
<li>sub-item_1-4</li>
</ul>
</div>
</li>
<li><span>item_2</span>
<div class="sub_position">
<ul>
<li>sub-item_2-1</li>
<li>sub-item_2-2</li>
<li>sub-item_2-3</li>
<li>sub-item_2-4</li>
</ul>
</div>
</li>
</ul>
</div>
You have to fix this line
$('.slider').html( $(this).find('ul') );
I am not sure what you are trying to achieve here, but you cannot treat a DOM object as HTML code. The reason your code works once is that this line is does not fire the first time (your first IF statement fires). The second time ELSE kicks in and this evil line messes things up.
Solution 1: Comment out or remove this line
//$('.slider').html( $(this).find('ul') );
Solution 2: Figure out what you want to do with this line and do it the proper way.
I have a bit of jQuery code I am trying to get to work here. I basically have a vertical nav menu with two items that have jQuery dropdown menus that pop out to the side. However, when you hover over them both quickly they are displayed overlapping each other. So what I am trying to accomplish is that if one is hovered on and pops out, if the other one is already displayed it will slideUp and be hidden. The dropdown trucks already existed I am adding on the engines one. I will keep working on it but if anyone can help out I would appreciate it.
/* Dropdown Menu Trucks*/
$("#menu-main-menu .show-dropdown").hover(function(){
$("#dropdown").slideDown('fast');
});
$("#dropdown").mouseenter(function(){
$("#dropdown").show();
});
$("#dropdown").mouseleave(function(){
$("#dropdown").slideUp('fast');
});
// ----------------------------
/* Dropdown Menu Engines */
$("#menu-main-menu .show-dropdown2").hover(function(){
$(".dropdown-engines").slideDown('fast');
});
$(".dropdown-engines").mouseenter(function(){
$(".dropdown-engines").show();
});
$(".dropdown-engines").mouseleave(function(){
$(".dropdown-engines").slideUp('fast');
});
if ($('#dropdown').is(':visible')) {
$(".dropdown-engines").slideUp();
}
else if ($('.dropdown-engines').is(':visible')) {
$("#dropdown").slideUp();
}
edit: let me approach this another way that seems easier to accomplish..
$("#menu-main-menu .dropdown2").hover(function(){ // hover over .dropdown2
// show #dropdown-engine
$("#dropdown-engine").slideDown('fast');
});
$("#dropdown-engine").mouseenter(function(){ // mouse enter #dropdown-engine
// show #dropdown-engine
$("#dropdown-engine").show();
});
$(".dropdown2" || "#dropdown-engine").mouseleave(function(){
$("#dropdown-engine").slideUp('fast'); // mouse leave #dropdown-engine
// *or .dropdown2 slideup
}); // but only if not hovering on either
The question isn't completely clear to me, but I think this is want.
I noticed that you used id's that are not present in your jsfiddle and are using classes and id's mixed. Try to be consistent and think DRY, by using data-target and the classes like in the example, the code is cleaner and shorter.
$(function(){
$(".dropdown").hide();//hide all dropdowns on start
$(".show-dropdown").mouseenter(function(){
//on mouse enter of a .show-dropdown, we slideup all .dropdowns
$(".dropdown").slideUp("fast");
//then we get the ID of the dropdown we want to show through the data-target attribute, and slide it down.
$("#"+$(this).attr("data-target")).slideDown("fast");
});
});
<ul>
<li class="show-dropdown" data-target="dropdown-trucks"><!--data target is the ID of dropdown you want to show-->
Trucks
</li>
<li class="show-dropdown" data-target="dropdown-engines">
Engines
</li>
</ul>
<ul id="dropdown-trucks" class="dropdown">
<li>Truck 1</li>
<li>Truck 2</li>
</ul>
<ul id="dropdown-engines" class="dropdown">
<li>Detroit Series 60 Engine</li>
<li>Cummins N14 Engine</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I ended up just using hide(); on hover to hide the element I didn't want to see. I was severely overthinking this. Thanks to anyone who answered.
I'm having trouble figuring out how to use session storage for list items. This doesn't seem to be working and because of the styling, I can't use the basic select/option:
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span data-bind="label">Day</span><span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" name="country">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var item = window.localStorage.getItem('country');
$('ul[name=country]').val(item);
$('ul[name=country]').change(function() {
window.localStorage.setItem('country', $(this).val());
});
fiddle
It is a basic click() event. You should not use change():
$('ul[name=country] li').click(function() {
window.localStorage.setItem('country', $(this).text());
});
Check in the console, using localStorage.getItem("country").
Fiddle: https://jsfiddle.net/5z0nkdjb/
You're trying to use val in a ul tag, and it does not have value property.
Also, you're trying to use a change event on it, and it does not have that event either.
First, you must understand what you're doing there. You've probably copied this Dropdown Picker from anywhere else, and you don't understand what it's doing.
It's simulating a select behavior by using a label inside a button, and anytime a li inside the ul tag is clicked, your code changes the label text to the li's one.
So, firstly, when your page is loaded, you must see if anything is already in your localStorage, and if it is, you must change the label's text to the value saved in the localStorage.
var item = localStorage.getItem('country');
if (item) $('span[data-bind="label"]').text(item);
After that, inside your li's click event, you must save the clicked li's text into the localStorage for persisting purposes later.
// Dropdown picker
$('.dropdown-menu').on('click', 'li', function(e) {
var $target = $(e.currentTarget);
/* the rest of your code */
localStorage.setItem('country', $target.text());
});
I've updated your fiddle with the code working.
I am having several links in asp pages and all links are having respected CSS. the 1st links is highlighted on the Home page with Different CSS. I want to toggle the CSS class on the the Click event whenever i pressed the 2nd or the the 3rd link respectively it should get highlighted and other one become Normal with Normal CSS.
<ul>
<li><a href="../Admin/Home.aspx" id="a_Home" class="homeactive" onclick="ChangeSelectedMenuCss(this.id);">
Home</a></li>
<li><a href="../Admin/subadmindetails.aspx" id="a_Report" class="home" onclick="ChangeSelectedMenuCss(this.id);">
SubAdmin</a></li>
<li><a href="../Admin/control_panel.aspx" id="a_User" class="home" onclick="ChangeSelectedMenuCss(this.id);">
Control Panel</a></li>
<li><a href="../Admin/admin_master.aspx" id="a_CntrlPnl" class="home" onclick="ChangeSelectedMenuCss(this.id);">
Master Data</a></li>
<li>Logout</li>
</ul>
please help me out i m stucked
Thanx and regards.
I think you're confusing how ASP.NET and Javascript interact with each other. When a user clicks on one of those links, the onclick event will fire, but then ASP.NET will load the page that relates to the link, therefore resetting the navigation menu.
What you probably want to do instead of using onclick events is to have a class on your Masterpage that identifies what page it is on, and then add the homeactive class to whatever link it needs to be on.
In order to change class using javascript you can do something like this:
function ChangeSelectedMenuCss(id){
document.getElementByClassName('homeactive').className ="home";
document.getElementById(id).className = "homeactive";
}
If you use JQuery, then this code may be useful for you.
First of all like this code-
$(function() {
var links = $('a.link').click(function() {
links.removeClass('active');
$(this).addClass('active');
});
});
And then in your CSS File, Add tis class-
a, a:visited { color:black }
a.link.active { color:blue; }
It might Help you....
or you can see this fiddle - http://jsfiddle.net/gHb9F/
I have a Div within a Div within a span like this:
<div id="container">
<a class="tooltips" href="#">XBOX
<span class="tooltip-container">
<div class="tooltip-item">Controller</div>
<div class="tooltip-item">Console
<div class="filter-item">In Stock</div>
<div class="filter-item">Pre-Order</div>
</div>
<div class="tooltip-item">Kinect</div>
</span>
</a>
<a class="tooltips" href="#">PS4
<span class="tooltip-container">
<div class="tooltip-item">Controller</div>
<div class="tooltip-item">Console</div>
</span>
</a>
</div>
I added a click function that shows or hides the div. When I click the items within my outer div I would like to expand another filter-item list within the inner div. In other words, when I click "XBOX" it will expand and if I click "Console" that will expand to show more items. How can I achieve this? jsfiddle example listed below.
jsfiddle.net example
Here:
Fiddle: http://jsfiddle.net/zNV8T/
The main changes are in the JS...
$(window).on('load',function(){
//click PS4 or XBOX
$('.tooltips').click(function(){
if ($(this).find('.tooltip-container').css('display') == 'none') {
//first deactivate any active tooltip
$('.tooltip-container').hide();
$('.tooltips').removeClass('clickedSortFilter');
//then activate the clicked tooltip
$(this).find('.tooltip-container').show();
$(this).addClass('clickedSortFilter');
} else {
//deactivate the clicked tooltip
$(this).find('.tooltip-container').hide();
$(this).removeClass('clickedSortFilter');
}
});
//expand tooltip-item if it contains filter-item
$('.tooltip-item').click(function(e){
e.stopPropagation();
if ($(this).children().length > 0) {
if ($(this).find('.filter-item').css('display') == 'none') {
//first deactivate any active tooltip-item
$('.tooltip-item').css('z-index','0');
$('.filter-item').hide();
//then activate the clicked tooltip-item
$(this).css('z-index','1');
$(this).find('.filter-item').show();
} else {
//deactivate the clicked tooltip-item
$(this).find('.filter-item').hide();
}
}
});
});
...although I did make a few changes in the CSS as well, adding position:relative and display:none in one or two places, and I removed z-index somewhere.
I think the comments in the code explain the general functionality pretty well, if you don't understand some details, just ask me in a comment and I will try to clarify (I fixed adding the clickedSortFilter class to the tooltips too btw).
UPDATE:
Here is an updated fiddle: http://jsfiddle.net/FAZLu/
The spans are changed to divs, and the alignment is fixed (the way I would do it, see the comments for other options).
I also cleaned up your CSS a whole lot.