I have made a dropdown menu and it works fine, except the anchor (a href="#") does not work.
I think the script has something wrong, but I can't figure it out.
Can anyone can help me please?
<ul class="menu">
<li class="listMenu on">
<a class="depth1" href="#">aaa</a>
<div class="depth2Wrap">
<ul class="depth2">
<li>bbb</li>
<li>ccc</li>
</ul>
</div>
</li>
<li class="listMenu"><a class="depth1" href="d.html">ddd</a></li>
</ul>
$(function($) {
var li = $('.menu>.listMenu');
li.addClass('off');
$('.menu .on').find('.depth2Wrap').show();
$('.menu>.listMenu>a').click(function() {
var myArticle = $(this).parents('.listMenu:first');
if(myArticle.hasClass('off')){
li.addClass('off').removeClass('on');
li.find('.depth2Wrap').slideUp(100);
myArticle.removeClass('off').addClass('on');
myArticle.find('.depth2Wrap').slideDown(100);
li.removeClass('fir_sele');
} else {
myArticle.removeClass('on').addClass('off');
myArticle.find('.depth2Wrap').slideUp(100);
li.removeClass('fir_sele');
}
return false;
});
});
Remove the following
return false;
return false tells the browser not to complete the default action, which is following the link.
See What's the effect of adding 'return false' to a click event listener?
Related
I want that my unordered list stays open if I click a list-item/link or I refresh/reload the page/site. And the list-item/link should have the class active.
Saw something, that I can store data in local-storage, but I do not know how.
HTML:
<aside id="sidebar" class="col-12 col-lg-4 col-xxl-3">
<div class="just-padding">
<ul>
<li id="server">Server</li>
<ul>
<li id="multiCollapseExample1">
<span>
Start
</span>
</li>
<li id="multiCollapseExample2">
<span>
Security
</span>
</li>
</ul>
<li id="git">GIT</li>
<ul>
<li id="multiCollapseExample3">
<span>
blub
</span>
</li>
<li id="multiCollapseExample4">
<span>
wurst
</span>
</li>
</ul>
</ul>
</div>
</aside>
jQuery:
$(document).ready(function () {
$("#multiCollapseExample1").hide();
$("#multiCollapseExample2").hide();
$("#multiCollapseExample3").hide();
$("#multiCollapseExample4").hide();
$("#server").click(function() {
localStorage.setItem('clickedItem', '#server');
$("#multiCollapseExample3, #multiCollapseExample4").hide();
$("#multiCollapseExample1, #multiCollapseExample2").show();
});
$("#git").click(function() {
localStorage.setItem('clickedItem', '#git');
$("#multiCollapseExample1, #multiCollapseExample2").hide();
$("#multiCollapseExample3, #multiCollapseExample4").show();
});
$("#multiCollapseExample1").click(function() {
localStorage.setItem('clickedSub', '#multiCollapseExample1');
$("#multiCollapseExample1, #multiCollapseExample2").show();
});
$("#multiCollapseExample2").click(function() {
localStorage.setItem('clickedSub', '#multiCollapseExample2');
$("#multiCollapseExample1, #multiCollapseExample2").show();
});
if(localStorage.getItem('clickedSub')) {
var test = $(localStorage.getItem('clickedSub')).click()
$(test).addClass("active");
};
if(localStorage.getItem('clickedItem')) {
$(localStorage.getItem('clickedItem')).click()
$(this).addClass("active");
};
});
I have edited my answer (the jquery part)
A new JSFiddle:
JSFiddle
The active list item in red do not save the state if I go back (backwards / browser arrow). But it keep the state on reload/refresh.
I have modified your code as you wanted. Please check jsfiddle
What i did was just set the clicked item to localstorage. I have saved its id..
Then when refresh the page i check does localstorage exist the key added to localstorage(it should exist if you clicked a item). Then based on that value I have clicked the related item via click() method.
Just modified your Jquery as bellow
$(document).ready(function () {
$("#multiCollapseExample1").hide();
$("#multiCollapseExample2").hide();
$("#multiCollapseExample3").hide();
$("#multiCollapseExample4").hide();
$("#server").click(function() {
localStorage.setItem('clickedItem', '#server');
$("#multiCollapseExample3, #multiCollapseExample4").hide();
$("#multiCollapseExample1, #multiCollapseExample2").show();
});
$("#multiCollapseExample1").click(function() {
$("#multiCollapseExample1, #multiCollapseExample2").show();
$("#multiCollapseExample1").addClass('active');
});
$("#git").click(function() {
localStorage.setItem('clickedItem', '#git');
$("#multiCollapseExample1, #multiCollapseExample2").hide();
$("#multiCollapseExample3, #multiCollapseExample4").show();
});
$("li span").click(function() {
$(this).addClass("active");
});
if(localStorage.getItem('clickedItem')) {
$(localStorage.getItem('clickedItem')).click()
}
});
By the way I dont recommend you to use ids to click event. So if there are 100 items then based on your code you need to write more and more logic. Instead of that use another mechanism to achieve this. Thanks
I'm working on a basic dropdown element in HTML and jQuery and I'm trying to get better at understanding JavaScript and jQuery so this questions is a bit about code refactoring as well.
So here is what I've gotten so far:
HTML
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
...
</div>
</li>
JavaScript
const navLink = $('.nav-link');
navLink.each(function () {
let $this = $(this);
$this.click(function (e) {
let hasSubnav = $this.parent().find('.subnav');
if(hasSubnav.length !== 0) {
e.preventDefault();
$this.toggleClass('dropdown-active');
}
hasSubnav.stop(true, true).slideToggle(200);
})
});
This solutions works fine. So what I want to do next is to check if another element in my loop is active, close is accordingly and then open the one I just clicked.
I thought about just putting a default click function before the each function like this:
navLink.click(function () {
$('.subnav').slideUp();
});
navLink.each(function () {
let $this = $(this);
$this.click(function (e) {
let hasSubnav = $this.parent().find('.subnav');
if(hasSubnav.length !== 0) {
e.preventDefault();
$this.toggleClass('dropdown-active');
}
hasSubnav.stop(true, true).slideDown(200);
})
});
But this does not seem to work. So my question is, is there a pretty way to achieve this maybe even inside of the each function? I've red about .not(this) in this post, which will maybe work (haven't tried it yet) but I thought that this would be duplicated code and that there might be a better way to get this to work.
Your code is now looping through every single nav-link and adding a click handler to them one by one. It is possible to remove the each loop, since you can just add a click handler to all nav-links at once.
All you have to do is add a click handler to the nav-link and then remove the active class and slide up all open dropdowns before executing your logic. See working code example below for reference:
// Collapse all initially
$(".subnav").slideUp();
// Add click handler to all nav-links
const navLink = $('.nav-link');
navLink.click(function(e) {
// Remove active classes on other elements & slide up
const otherLinks = navLink.not(this);
otherLinks.removeClass('dropdown-active');
otherLinks.parent().find('.subnav').slideUp();
// Slide down the subnav of selected element
let hasSubnav = $(this).parent().find('.subnav');
if (hasSubnav.length !== 0) {
e.preventDefault();
$(this).addClass('dropdown-active');
}
hasSubnav.stop(true, true).slideToggle(200);
})
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
Link1
Link2
Link3
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Foo</a>
<div class="subnav">
Link1
Link2
Link3
</div>
</li>
I am making a menu that has submenu. When I click on a menu item I am using prevent default because it is a tags, but on the submenu level I don't want to prevent default. I haven't been able to figure out how to make it work so it doesn't affect the top level.
<div id="block-menu-block-2">
<ul class="menu">
<li>
1
</li>
<li>
2
<ul class="menu">
<li>2.1</li>
<li>2.2</li>
<li>2.3</li>
<li>2.4</li>
</ul>
</li>
<li>
3
<ul class="menu">
<li>3.1</li>
<li>3.2</li>
<li>3.3</li>
<li>3.4</li>
</ul>
</li>
<li>
4
</li>
<li>
5
</li>
<li>
6
<ul class="menu">
<li>6.1</li>
</ul>
</li>
</ul>
</div>
Here is the jQuery
$('#block-menu-block-2 ul li').on("click", function() {
if ($(this).children().is('ul')) {
if ($(this).find('ul').is(':visible')) {
$(this).find('ul').hide("blind");
$(this).removeClass('menuItemSelected');
$(this).find('ul').removeClass('menuItemSelected');
} else {
$(this).parent().find('li ul').hide("blind");
$(this).parent().find('.menuItemSelected').removeClass('menuItemSelected');
$(this).find('ul').show("blind");
$(this).addClass('menuItemSelected');
$(this).find('ul').addClass('menuItemSelected');
};
event.preventDefault()
}
});
Here is a codepen for reference: http://codepen.io/mathiasha/pen/bVpMyo
Added some stuff. Changed some stuff. Couldn't paste into codepen from my phone so this might not work. Code first, then word wall.
$('#block-menu-block-2 ul li').each (function () {
var $this = $(this);
if ($this.find ('ul:first').length > 0) {
$this.click (function () {
if ($this.find ('ul:visible').length > 0) {
$this.removeClass ('menuItemSelected').find ('ul').removeClass('menuItemSelected').hide ('blind');
} else {
$this.parent ().find ('ul li').hide ('blind');
$this.parent ().find('.menuItemSelected').removeClass ('menuItemSelected');
$this.addClass ('menuItemSelected').find ('ul').show ('blind').addClass ('menuItemSelected');
}
});
}
});
$('#block-menu-block-2 > ul > li > a').click (function (e) {
if ($(this).find ('ul:first').length > 0)
e.preventDefault ();
});
The real answer lies in only putting the preventDefault only on the a tag and only when it is the immediate child of a li tag tjat is the immediate child of a ul tag that is the immediate child of the block-menu. See the last 3 lines.
The rest of the code below should only add the click listener to li tags with ul tags inside. Tried to use chaining to limit the number of jQuery objects created. Might have messed up what it was doing. You only really need to remove preventDefault from where it is and than use the last 3 lines.
Can you not add a class to your submenu triggers, e.g. .submenu-trigger, and then use the following jQuery:
$(document).on('click', function(e) {
if ($(e.target).hasClass('submenu-trigger')) e.preventDefault();
});
Ignoring all the other menu manipulation and putting the event on <a> tags you can simply check if the <a> has a sibling <ul> and if it does prevent default
$('#block-menu-block-2 a').click(function(e){
if( $(this).siblings('ul').length ){
e.preventDefault();
}
// menu manipulation code
});
I have my markup like this:
<div class="wrapper-header">
<div class="container">
<div class="navbar">
<ul class="nav navbar-nav">
<li class="">Show Categories</li>
</ul>
</div>
</div>
<div class="wrapper-categories">
<div class="container">
Content Here
</div>
</div>
The .wrapper-categories is display: none; by default, so it only shows once clicked with:
$(".toggle").on('click', function (event){
event.preventDefault();
$(".wrapper-categories").slideToggle("fast");
$(this).html(function(i,html) {
if (html.indexOf('Browse') != -1 ){
html = html.replace('Show','Hide');
} else {
html = html.replace('Hide','Show');
}
return html;
});
});
Now, I'd like to change that to showing on hover instead of on click, with the .wrapper-categories staying open if someone moves their mouse over and closing if it's not on the link or the content div anymore.
I tried replacing changing it to $(".toggle").hover(function() { and that worked, but it's not staying open. What else must I do?
Your code isn't working the way you desire is because the hover event of .toggle works only for itself. As soon as you try to move the mouse cursor over its contents i.e, under .wrapper-categories, the cursor goes out of the .toggle scope.
Here's a working example of how you need to implement this. You need to slightly change the structure of the menu you want to create using a simple structure of ul and li.
Here's is the FIDDLE.
HTML:
<ul class="nav navbar-nav">
<li class="menu">Show Categories
<ul>
<li>
Content Here
</li>
<li>
Content Here
</li>
<li>
Content Here
</li>
</ul>
</li>
</ul>
JS:
$(".menu").mouseover(function(){
$(this).find('ul').css('visibility', 'visible');
});
$(".menu").mouseout(function(){
$(this).find('ul').css('visibility', 'hidden');
});
CSS:
.menu > ul{
visibility:hidden;
}
.menu > ul > li:hover{
font-weight:bold;
}
Here is the solution for your problem.
https://jsfiddle.net/44wrL4g4/2/
I wrapped all in a menu class.
And I have used mouseleave() instead of mouseout(). See the Jquery documentation for these functions.
See the code for further understanding.
i have this javascript code:
var x="#wrapper"
//var xyz;
$(document).ready(function(){
$("#about").click(function(){
if (!(x=="#about")){
$(x).slideUp("slow",function(){
$("#aboutus").slideDown("slow");
});
x="#aboutus";
}
});
});
$(document).ready(function(){
$("#home").click(function(){
if(!(x=="#wrapper")){
$(x).slideUp("slow", function(){
$("#wrapper").slideDown("slow");
});
dd="#wrapper";
}
});
});
with this "menu"
<nav>
<div class="menu">
<ul class="ul">
<h6>
<li id="home" >Home</li >
<li id="about">About</li >
<li >performance</li >
<li >testimonials</li >
<li >faqs</li >
<li >forum</li >
<li onclick="slideUpDown()">Contact </li >
</ul>
</h6>
</div>
</nav>
I must use the the li tags as links and when I click the about "link" the home div must slide up slowly and the about div is supposed to come down slowly.
please help!
thank you in advance
In the last line of your code, set x to #wrapper not dd:
var x="#wrapper"
//var xyz;
$(document).ready(function(){
$("#about").click(function(){
if (!(x=="#about")){
$(x).slideUp("slow",function(){
$("#aboutus").slideDown("slow");
});
x="#aboutus";
}
});
$("#home").click(function(){
if(!(x=="#wrapper")){
$(x).slideUp("slow", function(){
$("#wrapper").slideDown("slow");
});
x="#wrapper";
}
});
});
I came on this nice one a while ago. It is simple and works.
function toggleForm(x) {
if ($('#'+x).is(":hidden")) {
$('#'+x).slideDown(200);
} else {
$('#'+x).slideUp(200);
}
}
Then to call it ...
onmousedown="javascript:toggleForm('div_ID');
and to not change your URL add this in front on the same call
onclick="return false"
with this, you can use one script to call as many slid operations as you want. The div to be targeted is the one that has its ID in the call.
EDIT: sorry ... Just noted that it is jQuery, but should not affect anything. I used it where other jQuery did not. So does not seem to conflict anywere.