Dropdown menu not closing? - javascript

I'm coding a very basic menu in JQuery. My basic idea is that when I click a button, I want my menu to pop up. When that menu pops up, two things happen: 1) the menu is shown, and 2) the button is given a new class to be able to close. It's like JQuery is completely ignoring this new class. What do?
http://codepen.io/asilhavy/pen/apjvYo?editors=1010
$(".dropdown").click(function () {
$(".drop-item").addClass("show").removeClass("hide");
$(".fa-drop").addClass("fa-angle-double-down").removeClass("fa-angle-double-right");
$(".dropdown").addClass("close-dropdown").removeClass("dropdown");
});
$(".close-dropdown").click(function () {
$(".drop-item").removeClass("show").addClass("hide");
$(".fa-drop").removeClass("fa-angle-double-down").addClass("fa-angle-double-right");
$(".close-dropdown").removeClass("close-dropdown").addClass("dropdown");
});
ul {
list-style: none;
}
.hide {
display: none;
}
.show {
display: block;
}
<script src="https://use.fontawesome.com/f19ebae6ca.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="popup">
<li class="dropdown"><i class="fa fa-drop fa-angle-double-right" aria-hidden="true"></i> Click to Dropdown</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>

so the problem is when you do $(".close-dropdown").click(function () {
there is no .close-dropdown in the dom to attach that event listener ,so when after some time you attach the class close-dropdown to div, there is no event listener to it.
this is a known problem and one solution is event delegation
read more about it here ... https://learn.jquery.com/events/event-delegation/
i have delegated event to body tag , but you can decide for that after understanding the delegation
$('body').on('click', ".dropdown", function () {
//console.log(2)
$(".drop-item").addClass("show").removeClass("hide");
$(".fa-drop").addClass("fa-angle-double-down").removeClass("fa-angle-double-right");
$(".dropdown").addClass("close-dropdown").removeClass("dropdown");
})
$('body').on('click', ".close-dropdown", function () {
//console.log(1)
$(".drop-item").removeClass("show").addClass("hide");
$(".fa-drop").removeClass("fa-angle-double-down").addClass("fa-angle-double-right");
$(".close-dropdown").removeClass("close-dropdown").addClass("dropdown");
});
ul {
list-style: none;
}
.hide {
display: none;
}
.show {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="popup">
<li class="dropdown"><i class="fa fa-drop fa-angle-double-right" aria-hidden="true"></i> Click to Dropdown</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>

Don't add and or delete classes.
The Javascript code needs to be initialized when the document is ready.
If you use .addClass() or you delete the associated class it won't reinitialize without reloading the page.
Using your Code:
$('.dropdown').click(function(e){
e.preventDefault();
$('.drop-item').toggle();
})

I would rather use 1 function to handle this instead of 2. Check my jsfiddle.
var on = false;
$(".toggle").click(function () {
if(on) {
$(".drop-item").removeClass("show").addClass("hide");
$(".fa-drop").removeClass("fa-angle-double-down").addClass("fa-angle-double-right");
on = !on;
} else {
$(".drop-item").addClass("show").removeClass("hide");
$(".fa-drop").addClass("fa-angle-double-down").removeClass("fa-angle-double-right");
on = !on;
}
});
https://jsfiddle.net/yw7ff0wz/

Use jQuery's event delegation syntax with .on() instead of using .click(). When you use .click() and add and remove the dropdown class, your bindings are lost.
$("#popup").on("click", ".dropdown", function () {
$(".drop-item").addClass("show").removeClass("hide");
$(".fa-drop").addClass("fa-angle-double-down").removeClass("fa-angle-double-right");
$(".dropdown").addClass("close-dropdown").removeClass("dropdown");
});
$("#popup").on("click", ".close-dropdown", function () {
$(".drop-item").removeClass("show").addClass("hide");
$(".fa-drop").removeClass("fa-angle-double-down").addClass("fa-angle-double-right");
$(".close-dropdown").removeClass("close-dropdown").addClass("dropdown");
});
ul {
list-style: none;
}
.hide {
display: none;
}
.show {
display: block;
}
<script src="https://use.fontawesome.com/f19ebae6ca.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="popup">
<li class="dropdown"><i class="fa fa-drop fa-angle-double-right" aria-hidden="true"></i> Click to Dropdown</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>

Related

Disable mouseenter when over element on page load

I'm trying to find a way to disable mouseenter when the top-level navigation item is clicked & on pageload and re-enable again when the mouse leaves and enters the element again.
User hovers over element = show submenu
User clicks menu = hide submenu and only show submenu when user leaves menu elements and enters again.
If user is over the element onLoad then only show submenu when user leaves element and enters again.
$('.navmenu li').on('mouseenter', function(e) {
$(e.target).next().addClass('js-hover')
}).on('mouseleave', function(e) {
$(e.target).next().removeClass('js-hover')
});
$('.navmenu').on('click', function(e) {
$(e.target).next().removeClass('js-hover')
location.reload(true);
})
.navmenu .submenu {
display:none;
}
.navmenu li {
display: inline;
}
.navmenu .submenu {
position:absolute;
top:40px;
left:0
}
.navmenu li:hover .js-hover {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu">
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
<li>
Menu 2
<nav class="submenu">
<ul>
<li>Submenu 4</li>
<li>Submenu 5</li>
<li>Submenu 6</li>
</ul>
</nav>
</li>
</ul>
</nav>
this could be done using variables and storing a state of element (if it should be hidden or not). But since you tried to do this through class attributes, I did the same. Here is simle example of one menu item, everything should be clear.
<nav class="navmenu">
<ul>
<li>
Menu
<nav class="submenu" hidden>
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
<li>Submenu 3</li>
</ul>
</nav>
</li>
</ul>
</nav>
and javascript:
$menuLink = $("nav.navmenu li > a");
$menuLink.click(function () {
$(this).addClass("dontHide");
});
$menuLink.mouseenter(function () {
$(this).next("nav.submenu").removeAttr("hidden");
$(this).removeClass("dontHide");
});
$menuLink.mouseleave(function () {
if(!$(this).hasClass("dontHide")) {
$(this).next("nav.submenu").attr("hidden", true);
}
});
Live demo: https://jsfiddle.net/g3fua461/24/

jquery slidetoggle not working with div, ul, and display: none

I'm trying to toggle a menu dropdown with slideToggle but I can't seem to get it working. My goal is to click on "Attack" and have the list of attack options show. Here is my code.
<div class="turn-option" id="attack">
<h2>Attack</h2>
<div class="attack-menu">
<ul>
<li class="attack-type">Attack 1</li>
<li class="attack-type">Attack 2</li>
<li class="attack-type">Attack 3</li>
<li class="attack-type">Attack 4</li>
</ul>
</div>
</div>
.attack-menu {
display: none;
}
$(document).ready(function() {
$("#attack").click(function() {
$(".attack-menu").slideToggle("fast");
});
});
This works fine. Your jquery library might be causing the error. Try including this script :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
Refer this link : Example

Jquery Nested Accordion to Show Only one Level

Suppose I have a following structure:
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3
<ul>
<li>Item11</li>
<li>Item12</li>
<li>Item13</li>
</ul>
</li>
This tree structure can have many levels.
Initially, I want to show following list:
Item 1
Item 2
Item 3 +
When I click on + list becomes
Item 3 -
Item 11
Item 12
Item 13
So, parent list disappears and sublist is shown.
If I click -, then everything is returned to the previous list.
Is there some jquery plugin for doing this?
Perhaps, some options in accordion?
Thanks in advance.
Used Dkouk his version to create what you need.
EDIT 1: Hide other menu items
EDIT 2: Second level menu
$(function () {
$('ul li').each(function () {
if ( $(this).find('ul').length > 0 ){
$(this).addClass('child');
}
});
$('ul li.child span').click(function() {
$(this).parent().toggleClass('open').find('ul').first().slideToggle();
$(this).parent().siblings().slideToggle();
});
});
ul {
list-style:none;
}
ul li.child span:after {
content:"+";
}
ul li.child.open span:after {
content:"-";
}
li ul { display:none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul class="main">
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>
<span>Item 2</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</li>
<li>Item 3</li>
</ul>
</li>
</ul>
You can add a class to your list when it's have a sublist, and toggle the list and toggle another class for parent of list so can change the '+' to '-'.
You can as many levels, and the code will work,
I've add a span to the list have child, but so can trigger the click only at text, if you trigger click for LI list and have sublist open then will close again.
You can style the content.
Here a simple example :
$(function () {
$('ul li').each(function () {
if ( $(this).find('ul').length > 0 ){
$(this).addClass('child');
}
});
$('ul li.child span').click(function() {
$(this).toggleClass('open').parent().find('ul:first').slideToggle();
$(this).parent().siblings().slideToggle();
});
});
ul {
list-style:none;
}
ul li.child span:after {
content:"+";
}
ul li.child span.open:after {
content:"-";
}
ul li ul { display:none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>
<span>Item 3</span>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</li>
</ul>
</li>
</ul>

Parsing JSON with jQuery Mustache template [duplicate]

I have a list, and each item is linked, is there a way I can alternate the background colors for each item?
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
How about some lovely CSS3?
li { background: green; }
li:nth-child(odd) { background: red; }
If you want to do this purely in CSS then you'd have a class that you'd assign to each alternate list item. E.g.
<ul>
<li class="alternate">Link 1</li>
<li>Link 2</li>
<li class="alternate">Link 3</li>
<li>Link 4</li>
<li class="alternate">Link 5</li>
</ul>
If your list is dynamically generated, this task would be much easier.
If you don't want to have to manually update this content each time, you could use the jQuery library and apply a style alternately to each <li> item in your list:
<ul id="myList">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
And your jQuery code:
$(document).ready(function(){
$('#myList li:nth-child(odd)').addClass('alternate');
});
You can achieve this by adding alternating style classes to each list item
<ul>
<li class="odd">Link 1</li>
<li>Link 2</li>
<li class="odd">Link 2</li>
<li>Link 2</li>
</ul>
And then styling it like
li { backgorund:white; }
li.odd { background:silver; }
You can further automate this process with javascript (jQuery example below)
$(document).ready(function() {
$('table tbody tr:odd').addClass('odd');
});
This is set background color on even and odd li:
li:nth-child(odd) { background: #ffffff; }
li:nth-child(even) { background: #80808030; }
Try adding a pair of class attributes, say 'even' and 'odd', to alternating list elements, e.g.
<ul>
<li class="even">Link 1</li>
<li class="odd">Link 2</li>
<li class="even">Link 3</li>
<li class="odd">Link 4</li>
<li class="even">Link 5</li>
</ul>
In a <style> section of the HTML page, or in a linked stylesheet, you would define those same classes, specifying your desired background colours:
li.even { background-color: red; }
li.odd { background-color: blue; }
You might want to use a template library as your needs evolve to provide you with greater flexibility and to cut down on the typing. Why type all those list elements by hand?
Since you using standard HTML you will need to define separate class for and manual set the rows to the classes.
You can do it by specifying alternating class names on the rows. I prefer using row0 and row1, which means you can easily add them in, if the list is being built programmatically:
for ($i = 0; $i < 10; ++$i) {
echo '<tr class="row' . ($i % 2) . '">...</tr>';
}
Another way would be to use javascript. jQuery is being used in this example:
$('table tr:odd').addClass('row1');
Edit: I don't know why I gave examples using table rows... replace tr with li and table with ul and it applies to your example
If you use the jQuery solution it will work on IE8:
jQuery
$(document).ready(function(){
$('#myList li:nth-child(odd)').addClass('alternate');
});
CSS
.alternate {
background: black;
}
If you use the CSS soloution it won't work on IE8:
li:nth-child(odd) {
background: black;
}
You can by hardcoding the sequence, like so:
li, li + li + li, li + li + li + li + li {
background-color: black;
}
li + li, li + li + li + li {
background-color: white;
}

JS using onclick event on li to display block

HTML:
<script>function dropdown()
{ console.getElementById("").style.display="block";
}</script>
<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>
Css:
#dropdown ul{
display: block;
}
#dropdown ul li {
display: block;
background-color: #558c89;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover > ul { /*this is what the onclick event should do*/
display: block;
}
The onclick should start the function "dropdown()" which needs to: "display: block;" on #dropdown ul li
You're missing the list ID and you're calling the selector on the console (when you want to be selecting on the document).
<script>
function dropdown()
{
document.getElementById("Menuitems").style.display="block";
}
</script>
<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>
JSFiddle: http://jsfiddle.net/tmaB9/
Try:
<li onClick="dropDown(this);">
This is important, so your function knows which element you clicked on. Then...
function dropDown(li) {
var submenu = li.getElementsByTagName('ul')[0];
if( submenu) {
submenu.style.display = submenu.style.display == "block" ? "" : "block";
}
}
This will toggle the visibility of the submenu :)
here is a quick example of what i think you want (provided you can use JQuery):
$(document).ready(function () {
$('#dropdown ul li').on('click', function dropdown() {
//console.getElementById("").style.display = "block";
});
});
<div id="dropdown" class="dropdown">
<ul>
<li>menu 1</li>
<li>menu 2</li>
<li>menu 3</li>
<li>menu 4</li>
</ul>
</div>

Categories