links in toggled nested list not clickable - javascript

I'm totally stuck and tried several days to solve my problem.
Below you see the html-structure I'm working with.
I'm inserting the nested list via JS.
My problem is that I want to display Link1a and Link1b like in this fiddle.
As you can see here the text of the last div is overwritten by the nested list.
But in my case on the site I'm trying to manipulate the links are not clickable.
I guess I'm missing an attribute, but can't figure out which one.
Can you help me?
<div id="main">
<ul>
<li style="display: inline-block; vertical-align: top; padding: 0px;">
Link1
</li>
<li style="display: inline-block; vertical-align: top; padding: 0px;">
Disabled link
<ul style="position: absolute; margin-top: 5px;" class="tohover">
<li>
Link1a
</li>
<li>
Link1b
</li>
</ul>
</li>
</ul>
</div>
$(document).ready(function(){
$("#main > ul > li").css({'display':'inline-block','vertical-align':'top','padding':'0px'});
$("<ul class='tohover' style='display:none;'>
<li><a href='#'>Link 1a</a></li>
<li><a href='#'>Link 1a</a></li>
</ul>").insertAfter("#main a[href$='link1']");
$("#main a[href$='link1']").click(function(e){
e.preventDefault();
$(".tohover").toggle().css("position","absolute").css("margin-top","5px");
});
});

I think it is a problem with z-index just try to set: <ul class='tohover' style='display:none; z-index: 999;'>

You can use event.preventDefault();
Example:
$("a").click(function(event) {
event.preventDefault();
});

Related

Select current element and change values on click

I'm new to Javascript and I've been trying to program a code that changes the value of an attribute and a style when its element is clicked. I have this code and I want that when you click on "<li class="has-sub">" it changes to "<li class="has-sub show">"... and inside it, that "<ul class="sub-menu m-sub" style="display: none;">" changes to "<ul class="sub-menu m-sub" style="display: block;">":
<li class="has-sub">
Hi
<ul class="sub-menu m-sub" style="display: none;">
<li>
Hi
</li>
</ul>
<div class="submenu-toggle"></div>
</li>
When clicked, it should look like this:
<li class="has-sub show">
Hi
<ul class="sub-menu m-sub" style="display: block;">
<li>
Hi
</li>
</ul>
<div class="submenu-toggle"></div>
</li>
I have made the attempt on my own, and tried to place this:
<script type='text/javascript'>
$(document).ready(function change() {
$(this).attr('has-sub','has-sub show');
$(this > ul).css('display','block');
})
</script>
And call the function with "onclick":
<li class="has-sub" onclick"change();">
But I haven't been able to achieve it yet...
Thanks for the help :)
You can use the parent to toggle a class that has display: none applied to it. $(this).children('ul').toggleClass('hide') will target the class hide and then toggle its class on click using toggleClass(). Set the hide class by default on the HTML sub-menu element.
$(document).ready(function(){
$('.has-sub').on('click', function(){
$(this).children('ul').toggleClass('hide')
})
})
.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="has-sub show">
Hi
<ul class="sub-menu m-sub hide">
<li>
Hi
</li>
</ul>
<div class="submenu-toggle"></div>
</li>
First of all, you need to add click listener on .has-sub and after that you can add class show.
You need to add class show. It is not an attribute.
Just use .has-sub > ul to get the ul that is direct child of .has-sub.
$(document).ready(function change() {
// $(this).attr("has-sub", "has-sub show");
$(".has-sub").click(function() {
$(this).addClass("show");
$(".has-sub > ul").css("display", "block");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="has-sub">
Hi
<ul class="sub-menu m-sub" style="display: none;">
<li>
Hi
</li>
</ul>
<div class="submenu-toggle"></div>
</li>
You can use this as click handler, then you can remove the onclick"change();"
$(document).ready(function() {
$(".has-sub > a").on("click", function() {
// here you can use
// - $(this).parent() to do something with the li.has-sub
// - $(this).next("ul") to do something with the ul.sub-menu
});
});

Appended content do not get the proper CSS effect

I want append an HTML element into a DIV, but this one do not get the proper CSS like the original ones.
I have a dropdown menu, and want append on it new <li> rows.
My HTML code:
<br/><br/>
Append it
<div class="container">
<div class="row">
<div class="col-sm-3">
<h5>Normal Dropdown Button</h5>
<div class="panel panel-default">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<div id="append">
</div>
<li>Item 1</li>
<li>Another item</li>
<li>This is a longer item that will not fit properly</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<br/><br/>
My Javascript code:
$( document.body ).on( 'click', '.append', function( event ) {
$("#append").append("<li>Item 1</li>");
return false;
});
Here a live example: http://jsfiddle.net/dJDHd/2136/
EDITED WITH MY MAIN PROBLEM:
https://jsfiddle.net/Lr7gn020/1/
Click on APPEND IT, and then check the appended element by clicking on Select One button (Dropdown menu), and you will see that it do not get the proper CSS like the others (Item Test).
You've nested a div in the ul and the styles target .dropdown-menu>li>a so the div is breaking that. A div can't be a direct child of a ul and li can't be a direct child of a div. Instead of nesting a div in the ul, then appending li's to the div, you can $.prepend() li's directly to the menu, if you want them to appear at the beginning of the menu when you add them. If you don't care where they appear, you can $.append() them to the bottom instead.
$(document.body).on('click', '.append', function(event) {
$(".dropdown-menu").prepend("<li>Item Test</li>");
return false;
});
.btn-input {
display: block;
}
.btn-input .btn.form-control {
text-align: left;
}
.btn-input .btn.form-control span:first-child {
left: 10px;
overflow: hidden;
position: absolute;
right: 25px;
}
.btn-input .btn.form-control .caret {
margin-top: -1px;
position: absolute;
right: 10px;
top: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br/><br/>
Append it
<div class="container">
<div class="row">
<div class="col-sm-3">
<h5>Normal Dropdown Button</h5>
<div class="panel panel-default">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Item 1</li>
<li>Another item</li>
<li>This is a longer item that will not fit properly</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<br/><br/>
The reason behind the appended option having different css is due to the fact that you are appending it inside a div element.
The current CSS of the li elements comes from the bootstrap css with this selector.
dropdown-menu>li>a
Since you have a div node inside ul (which is wrong and make html invalid) and you are appending a new li inside this div with JS, the above selector will not reach this node and CSS will not be applied.
You should add the li node directly under the ul node.
Fiddle : http://jsfiddle.net/9med3Lou/
Change your jquery part.
$( document.body ).on( 'click', '.append', function( event ) {
$(".dropdown-menu").append("<li>Item 1</li>"); //append with ul, not div
return false;
});

Getting/changing class of an element with other elements in it. JavaScript/JQuery

I made a blog archive in the format of this:
+Year
+Month
Title
Sample code:
<ul>
<span class="toggle">+</span>
<li class="year">$year
<ul>
<span class="toggle">+</span>
<li class="month active">$month
<ul>
<li class="title active">$title</li>
</ul>
</li>
</ul>
</li>
</ul>
I used $(this).next().toggle(), which works fine toggling the lists, but the entire list is expanded in the beginning when the page loads, and I don't want that.
So I changed to changing class names (active/inactive). I want to change the class of the month/title lists to inactive and back when the + span is clicked. The problem is using $(this).next() doesn't work.
If I try $(this).next().hasClass("active");
It will return a false. Or console.log($(this).next().attr("class"));, which gives undefined.
$(this).next().html(); gives:
<li class="month active"><span class="toggle">+</span><ul><li class="title active">...</li></ul></li></ul></li></ul>
The very next thing that follows the + span is the list with class of active, but it doesn't recognize the class? I don't understand why .toggle() works, but this doesn't.
What option do I have to make this work?
The idea is to capture the click event on the span class and toggle active/inactive on the year so that it shows correctly. Here's some psuedo code:
$('.toggle').on('click', function(){
$(this).next().toggleClass('active').toggleClass('inactive');
});
This will only work if the element has a class of inactive on page load, like this:
<ul>
<span class="toggle">+</span>
<li class="year inactive">$year
<ul>
<span class="toggle">+</span>
<li class="month active">$month
<ul>
<li class="title active">$title</li>
</ul>
</li>
</ul>
</li>
</ul>
When you had your initial toggle working but it displayed the items on load, you could have set the next element (the unordered list) to
style="display: none"
As for
console.log($(this).next().attr("class");
You are missing a parenthesis:
console.log( $(this).next().attr("class") );
Hope this helps.
By using little bit of CSS and toggling the class of ul to active only on click will fix your issue. Below is a working example.
$('.toggle').on('click', function() {
$(this).parent().toggleClass('active');
});
ul {
list-style-type: none;
}
ul:not(#MainNode) {
display: none;
}
ul.active > li > ul {
display: block !important;
}
.toggle {
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="MainNode">
<span class="toggle">+</span>
<li class="year">Year
<ul>
<span class="toggle">+</span>
<li class="month active">Month
<ul>
<li class="title active">Title</li>
</ul>
</li>
</ul>
</li>
</ul>

Hide a div on hovering over menu bar

Whenever I hover over the second button in the menu, a "submenu" appears. When it appears, it partially covers the images in a div "container".
The styling of the submenu is such that it is semi-transparent so the images inside the div "container" also appear in the background of the menu, which doesnt look that good.
I know that the simple solution would be to change the location of the div but then the images would not be centered so that is not an option. I was wondering if it is possible that whenever I hover over the buttons that have a submenu, the div "container" hide and appear again when I move my mouse away from the menu. The div "container" should not hide when hovering over first Home button since it does not have a submenu and images should remain hidden as long as the menu is open. Is it possible in javascript or jQuery or CSS3??
HTML Code:
<div id="menu">
<ul class="menu" id="tempMenu">
<li class="Home">Home</li>
<li class="HOme2"><a id="secondElement" href="www.google.com">Home2</a><div>
<ul class="submenu">
<li>
<a id="one" href="">One</a>
</li></br>
<li>
<a id="two" href="">two</a>
</li>
<li>
<a id="three" href="">three</a>
</li>
<li>
<a id="four" href="">four</a>
</li>
<li>
<a id="five" href="">five</a>
</li>
<li>
<a id="six" href="">six</a>
</li>
<li>
<a id="seven" href="">seven</a>
</li>
<li>
<a id="eight" href="">eight</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div id="container">
<div id="box1" class="box">Image1<img src="images/image1.png"></div>
<div id="box2" class="box">Image2<img src="images/image2.png"></div>
</div>
CSS Code:
ul.menu .submenu{
display: none;
position: absolute;
}
ul.menu li:hover .submenu{
display: block;
}
$('.submenu').hover(function() {
$('#container').hide()
}, function() {
$('#container').show()
});
You basically want to detect on the hover event whenever the current menu item (one of the .menu > a elements) contains a submenu (.submenu).
What about :
$('.menu > a').hover(function(){
if ($(this).find('.submenu').length != 0) {
$('#container').hide();
}
}, function(){
$('#container').show();
});
Also, some of your html closing tags have issues, you should ensure that they are all closing in a correct order to prevent unexpected glitches.
firstly give that div 2 class names like-class1,class2
in Css :
.class1{
display: none;
position: absolute;
}
.class2{
display : block;
}
in jquery :
//this would track mouse pointer in/out events
$("#menu").hover( function(event){ $("#div").attr("class","class1"); },
function(event){ $("#div").attr("class","class1"); } );
You forgot to close this
<li class="HOme2"><a id="secondElement" href="www.google.com">Home2</a><div>
to
<li class="HOme2"><a id="secondElement" href="www.google.com">Home2</a></li><div>
for the Jquery i think this will help
$('.submenu').mouseenter(function() {
$('#container').hide()
}).mouseleave(function(){
$('#container').show()
});

How to properly hide a sliding menu?

I have the following menu:
<div id="menuItem">Item1</div>
<div id="subMenu">
<ul>
<li>subitem1</li>
<li>subitem2</li>
<li>subitem3</li>
</ul>
</div>
​
Animated like this:
$('#menuItem').mouseenter(function() {
$('#subMenu').slideDown(400);
}).mouseleave(function() {
$('#subMenu').hide(400);
});
​
Unfortunately, as the mouse leave the submenu, the submenu dissapears. How do I make the submenu only disapears when the mouse leave the menuitem OR the submenu list ? I would like to be able to hover the mouse on the submenu. Notice that there is a gap bewteen the two menus.
jsFiddle here
make the sub-menu actually "inside" the menu-item you are attaching the event to, this way the in/out event only happen when the user actually leaves the menu area
like this:
css
#menuItem {
cursor: pointer;
width: 100px;
}
#menuItem .title {
background-color: orange;
}
#subMenu {
background-color: grey;
margin-top: 5px;
cursor: pointer;
display:none;
width: 80px;
}​
html
<div id="menuItem">
<div class="title">Item1</div>
<div id="subMenu">
<ul>
<li>subitem1</li>
<li>subitem2</li>
<li>subitem3</li>
</ul>
</div>
</div>​​​​​​​​​
js
$('#menuItem').mouseenter(function() {
$('#subMenu').slideDown(400);
}).mouseleave(function() {
$('#subMenu').hide(400);
});
friendly note:
you might want to use some form of .stop(true, true) prior to animating the menu, or else moving a cursor back and forth rapidly over the menu will cause the animations to "stack" and it will just feel strange to the user. see discussion here: Where to put clearQueue in jQuery code
so it would look like this:
$('#menuItem').hover(function() {
$('#subMenu').stop(true, true).slideDown(200);
}, function() {
$('#subMenu').stop(true, true).slideUp(200);
});
Try this:
<div id="menuItem">Item1
<div id="subMenu">
<ul>
<li>subitem1</li>
<li>subitem2</li>
<li>subitem3</li>
</ul>
</div>
</div>
This works in my browser (firefox)
Assuming you wanted to keep the exact same html structure, you could use the following code:
$('#menuItem').mouseenter(function() {
$('#subMenu').slideDown(400);
}).next('#subMenu').mouseleave(function() {
$('#subMenu').hide(400);
});
Notice that I've told jQuery to hide the #subMenu only when the mouse has left the #subMenu.
It is always good to have the Menu and Sub Menu inside the same container so you don't need to have a separate mouse handler when navigating sub menu.
DEMO
HTML:
<div id="subMenu">
<div id="menuItem">Item1</div>
<ul>
<li>subitem1</li>
<li>subitem2</li>
<li>subitem3</li>
</ul>
</div>
JS:
$('#subMenu').mouseenter(function() {
$('#subMenu ul').slideDown(400);
isInsideSubMenu = true;
}).mouseleave(function() {
$('#subMenu ul').hide(400);
});
CSS:
#subMenu ul { display:none;}
Alternatively if you don't want to have the submenu inside menuitem (which could mess with your CSS, you can wrap everything in a parent div like:
HTML:
<div id="all">
<div id="menuItem">Item1</div>
<div id="subMenu">
<ul>
<li>subitem1</li>
<li>subitem2</li>
<li>subitem3</li>
</ul>
</div>
​</div>​
jQuery:
$('#all').mouseenter(function() {
$('#subMenu').slideDown(400);
}).mouseleave(function() {
$('#subMenu').hide(400);
});
​

Categories