Open only the dropdown that was clicked - javascript

I'm trying to make a dropdown. Here is my code: FIDDLE
However it opens each dropdown when it's been clicked, instead of just the one that was clicked. How can I isolate it? This is the full JS:
$(function () {
$('.click-nav > ul').toggleClass('no-js js');
$('.click-nav .js ul').hide();
$('.click-nav .js').click(function (e) {
$('.click-nav .js ul').toggle();
$('.clicker').toggleClass('active');
e.stopPropagation();
});
$(document).click(function () {
if ($('.click-nav .js ul').is(':visible')) {
$('.click-nav .js ul', this).slideUp();
$('.clicker').removeClass('active');
}
});
});

Currently the whole ul element is getting clicked. Add click event on .js li as the nav elements are li., and use this to get current relevant elements.
$('.click-nav .js li').click(function (e) {
$('ul',this).toggle();
$('.clicker',this).toggleClass('active');
e.stopPropagation();
});
Updated Fiddle

You can try something like this
$(function() {
$('.click-nav > ul').toggleClass('no-js js');
$('.click-nav .js ul').hide();
// add li to findout which one is clicked
$('.click-nav .js li').click(function(e) {
// use this to find ul inside the clicked li
$(this).find('ul').toggle()
.end().find('.clicker').toggleClass('active');
e.stopPropagation();
});
$(document).click(function() {
if ($('.click-nav .js ul').is(':visible')) {
$('.click-nav .js ul', this).slideUp();
$('.clicker').removeClass('active');
}
});
});
* {
margin: 0;
padding: 0;
}
.click-nav ul {
position: relative;
display: inline-block;
}
.click-nav ul li {
position: relative;
list-style: none;
cursor: pointer;
display: inline-block;
}
.click-nav ul li ul {
position: absolute;
left: 0;
right: 0;
}
.click-nav ul .clicker {
position: relative;
color: black;
}
.click-nav ul .clicker:hover,
.click-nav ul .active {
background: #196F9A;
}
.click-nav ul li a {
display: block;
padding: 8px 10px;
background: #FFF;
color: #333;
text-decoration: none;
}
.click-nav ul li a:hover {
background: #F2F2F2;
}
/* Fallbacks */
.click-nav .no-js ul {
display: none;
}
.click-nav .no-js:hover ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="click-nav">
<ul class="no-js">
<li> Any Time
<ul>
<li>Any Time
</li>
<li>Past 3 days
</li>
<li>Past 5 days
</li>
</ul>
</li>
<li> Test
<ul>
<li>Any Time
</li>
<li>Past 3 days
</li>
<li>Past 5 days
</li>
</ul>
</li>
</ul>
</div>

Related

Create click off event on animated navigation dropdown

I have 2 problems:
I'm trying to create an click-off event, where a click off of the "nav" menu is detected, which triggers the deselection of the open list element and retracts its respective dropdown content.
My current code doesn't allow another list element/navigation item without dropdown content to be added, as doing so hinders the entirety of the code from working. I'd like to add another "nav" list element that doesn't have dropdown contents, without hindering the functionality of the other list elements and their respective dropdown content.
Here is my code (also available on JSFiddle):
$(function() {
function animate() {
$('#nav .nav-ul li').off('click', animate)
var $detected = $(this).closest('.nav-ul');
$detected.find('li.detected').removeClass('detected');
$(this).addClass('detected');
//figure out which rel to show
var ulToShow = $(this).attr('rel');
//hide current rel
if ($('.substitute .sub-child.active').length > 0) {
$('.substitute .sub-child.active').hide(700, function() {
$(this).removeClass('active');
$('#' + ulToShow).fadeIn(528, function() {
$(this).addClass('active');
$('#nav .nav-ul li').on('click', animate)
});
});
} else {
$('#' + ulToShow).fadeIn(528, function() {
$(this).addClass('active');
$('#nav .nav-ul li').on('click', animate)
});
}
}
$('#nav .nav-ul li').on('click', animate);
});
* {
margin: 0;
padding: 0;
}
#nav {
background-color: /*blue*/
;
float: right;
}
#nav .nav-ul {
list-style: none;
float: right;
background-color: /*yellow*/
;
border-left: solid 2px #000000;
border-right: solid 2px #000000;
}
#nav .nav-ul li {
float: left;
padding: 4px;
font-weight: bold;
color: #000000;
}
#nav .nav-ul li:hover {
cursor: pointer;
text-decoration: underline;
color: #E51D27;
}
#nav .nav-ul li.detected {
color: #E51D27;
}
#nav .substitute {
float: right;
background-color: /*pink*/
;
margin-right: 4px;
}
#nav .substitute .sub-child {
float: left;
display: none;
}
#nav .substitute .sub-child.active {
display: block;
}
#nav .substitute .sub-child ul {
list-style: none;
}
#nav .substitute .sub-child ul li {
float: left;
padding: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nav">
<ul class="nav-ul">
<li class="" rel="pay1">Color</li>
<li rel="pay2">Shape</li>
<li rel="pay3">Size</li>
</ul>
<div class="substitute">
<div id="pay1" class="sub-child">
<ul>
<li>Red</li>
<li>Blue</li>
<li>Green</li>
</ul>
</div>
<div id="pay2" class="sub-child">
<ul>
<li>Square</li>
<li>Circle</li>
<li>Triangle</li>
<li>Diamond</li>
</ul>
</div>
<div id="pay3" class="sub-child">
<ul>
<li>Small</li>
<li>Medium</li>
<li>Large</li>
</ul>
</div>
</div>
</div>
I'm trying to create an click-off event, where a click off of the "nav" menu is detected, which triggers the deselection of the open list element and retracts its respective dropdown content.
For this you could create a click event handler on the body that closes the menu if it's open. Something like this:
// close menu when clicking anywhere on the document
$(document).on("click", function() {
$("#nav li.detected").removeClass("detected");
$("#nav div.active").hide(700, function() { $(this).removeClass("active"); });
});
Then to avoid it from closing when you click on the menu, you can use .stopPropagation() in the animate function to stop the bubbling of the events up the DOM tree when clicking on it.
My current code doesn't allow another list element/navigation item without dropdown content to be added, as doing so hinders the entirety of the code from working. I'd like to add another "nav" list element that doesn't have dropdown contents, without hindering the functionality of the other list elements and their respective dropdown content.
This happens because you are associating and disassociating events every time that you click on the menu (something that is not really necessary), so when one of the navigation items doesn't have a dropdown associated to it, the event handler is removed (with the off() in the animate function) but it is not associated again, which causes this behavior that you don't want.
The solution is simple: there's no apparent need to be detaching and re-attaching the click event handlers every time that the animate function is called. Remove the call to off and on within the animate function and that would be it.
Here you can see both changes applied to your code:
$(function() {
function animate(e) {
e.stopPropagation();
var $detected = $(this).closest('.nav-ul');
if (!$detected.hasClass("active-animation")) {
$detected.addClass("active-animation");
$detected.find('li.detected').removeClass('detected');
$(this).addClass('detected');
//figure out which rel to show
var ulToShow = $(this).attr('rel');
//hide current rel
if ($('.substitute .sub-child.active').length > 0) {
$('.substitute .sub-child.active').hide(700, function() {
$(this).removeClass('active');
$('#' + ulToShow).fadeIn(528, function() {
$(this).addClass('active');
$detected.removeClass("active-animation");
});
});
} else {
$('#' + ulToShow).fadeIn(528, function() {
$(this).addClass('active');
$detected.removeClass("active-animation");
});
}
}
}
$('#nav .nav-ul li').on('click', animate);
// close menu when clicking anywhere on the page
$(document).on("click", function() {
$("#nav li.detected").removeClass("detected");
$("#nav div.active").hide(700, function() {
$(this).removeClass("active");
});
});
});
* {
margin: 0;
padding: 0;
}
#nav {
background-color: /*blue*/
;
float: right;
}
#nav .nav-ul {
list-style: none;
float: right;
background-color: /*yellow*/
;
border-left: solid 2px #000000;
border-right: solid 2px #000000;
}
#nav .nav-ul li {
float: left;
padding: 4px;
font-weight: bold;
color: #000000;
}
#nav .nav-ul li:hover {
cursor: pointer;
text-decoration: underline;
color: #E51D27;
}
#nav .nav-ul li.detected {
color: #E51D27;
}
#nav .substitute {
float: right;
background-color: /*pink*/
;
margin-right: 4px;
}
#nav .substitute .sub-child {
float: left;
display: none;
}
#nav .substitute .sub-child.active {
display: block;
}
#nav .substitute .sub-child ul {
list-style: none;
}
#nav .substitute .sub-child ul li {
float: left;
padding: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nav">
<ul class="nav-ul">
<li class="" rel="pay1">Color</li>
<li rel="pay2">Shape</li>
<li rel="pay3">Size</li>
<li>No Dropdown</li>
</ul>
<div class="substitute">
<div id="pay1" class="sub-child">
<ul>
<li>Red</li>
<li>Blue</li>
<li>Green</li>
</ul>
</div>
<div id="pay2" class="sub-child">
<ul>
<li>Square</li>
<li>Circle</li>
<li>Triangle</li>
<li>Diamond</li>
</ul>
</div>
<div id="pay3" class="sub-child">
<ul>
<li>Small</li>
<li>Medium</li>
<li>Large</li>
</ul>
</div>
</div>
</div>

How to change script to use more UL select boxes?

I found this code for ul select box. I need 3 different ul select boxes. So I made some changes but now is slide up only last "Year" select box. Is there a problem with "selected" tag?
ORIGINAL CODE:
$("ul").on("click", ".init", function() {
$(this).closest("ul").children('li:not(.init)').slideDown();
});
var allOptions = $("ul").children('li:not(.init)');
$("ul").on("click", "li:not(.init)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$("ul").children('.init').html($(this).html());
allOptions.slideUp();
});
ul {
height: 30px;
width: 150px;
border: 1px #000 solid;
}
ul li { padding: 5px 10px; z-index: 2; }
ul li:not(.init) { float: left; width: 130px; display: none; background: #ddd; }
ul li:not(.init):hover, ul li.selected:not(.init) { background: #09f; }
li.init { cursor: pointer; }
a#submit { z-index: 1; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul>
<li class="init">[SELECT]</li>
<li data-value="value 1">Option 1</li>
<li data-value="value 2">Option 2</li>
<li data-value="value 3">Option 3</li>
</ul>
MY CODE:
$(".day ul").on("click", ".active", function() {
$(this).closest(".day ul").children('li:not(.active)').slideDown();
});
var allOptions = $(".day ul").children('li:not(.active)');
$(".day ul").on("click", "li:not(.active)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$(".day ul").children('.active').html($(this).html());
allOptions.slideUp();
});
$(".month ul").on("click", ".active", function() {
$(this).closest(".month ul").children('li:not(.active)').slideDown();
});
var allOptions = $(".month ul").children('li:not(.active)');
$(".month ul").on("click", "li:not(.active)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$(".month ul").children('.active').html($(this).html());
allOptions.slideUp();
});
$(".year ul").on("click", ".active", function() {
$(this).closest(".year ul").children('li:not(.active)').slideDown();
});
var allOptions = $(".year ul").children('li:not(.active)');
$(".year ul").on("click", "li:not(.active)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$(".year ul").children('.active').html($(this).html());
allOptions.slideUp();
});
.day, .month, .year{
float:left;
width:100px;
display:block;
width:auto;
height: 34px;
}
.day ul, .month ul, .year ul {
list-style-type:none;
cursor: pointer;
width: 100px;
}
.day ul li, .year ul li, .month ul li {
float: left;
width:100px;
text-indent: 5px;
height: 34px;
line-height: 34px;
border:1px solid #000;
background: #fff;
}
.day ul li.active, .month ul li.active, .year ul li.active {
}
.day ul li a, .month ul li a, .year ul li a {
text-decoration: none;
color: #000;
}
.day ul li:not(.active), .month ul li:not(.active), .year ul li:not(.active) {
float: left;
display: none;
}
.day ul li:not(.active):hover, .day ul li.selected:not(.active), .month ul li:not(.active):hover, .month ul li.selected:not(.active), .year ul li:not(.active):hover, .year ul li.selected:not(.active) {
background: #f5f5f5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="day">
<ul>
<li class="active">Day</li>
<li>01.08</li>
<li>02.08</li>
<li>03.08</li>
<li>04.08</li>
<li>05.08</li>
</ul>
</div>
<div class="month">
<ul>
<li class="active">Month</li>
<li>01</li>
<li>02</li>
<li>03</li>
<li>04</li>
<li>05</li>
</ul>
</div>
<div class="year">
<ul>
<li class="active">Year</li>
<li>2016</li>
<li>2017</li>
<li>2018</li>
<li>2019</li>
<li>2020</li>
</ul>
</div>
you just need to wrap up the original code with an iterator and your problem will be solved.
I have create an example on codepen with 3 UL tags, you can copy and paste the UL blocks to have the same code work on all UL tags
This is what your js code should look like.
JS:
$(document).ready(function(){
$("ul").each(function(){
var $thisUL = $(this);
$thisUL.on("click", ".init", function() {
$(this).closest("ul").children('li:not(.init)').slideDown();
});
var allOptions = $thisUL.children('li:not(.init)');
$thisUL.on("click", "li:not(.init)", function() {
allOptions.removeClass('selected');
$(this).addClass('selected');
$thisUL.children('.init').html($(this).html());
allOptions.slideUp();
});
});
});

convert CSS Hover to JS onClick for Dropdown Menu?

I want to create a simple dropdown menu when a user clicks on an image. Currently I'm using CSS hover but it doesn't stay so I want to convert it to a JS onClick function.
<html>
<head>
<style>
ul {
text-align: left;
display: inline;
margin: 0;
list-style: none;
}
ul li {
display: inline-block;
position: relative;
}
ul li ul {
padding: 0;
position: absolute;
display: none;
opacity: 0;
visibility: hidden;
}
ul li ul li {
display: block;
}
ul li:hover ul {
display: block;
opacity: 1;
visibility: visible;
}
</style></head><body>
<ul>
<li>
<img src="https://cdn1.iconfinder.com/data/icons/thincons/100/menu-128.png" width="20px;" height="18px;"/>
<ul class="lang">
<li>Web Design</li>
<li>Web Development</li>
<li>Illustrations</li>
</ul>
</li>
</ul>
</body>
</html>
With a little jQuery, we can easily toggle a class on or off to represent 'showing' the menu:
$("#menu").click(function(){
$(this).toggleClass("activated");
});
And changing the CSS (instead of :hover) to:
ul li.activated ul {
display: block;
opacity: 1;
visibility: visible;
}
The HTML only needs that first li element to have an id, which lets us use jQuery to bind a click event to it.
<ul>
<li id="menu">
You can see it all in action on this fiddle.
Edit: For a non-jQuery solution, you can use the following Javascript code:
var myEl = document.getElementById('menu');
myEl.addEventListener('click', function() {
this.classList.toggle('activated');
}, false);

Nav bar mouseenter/mouseleave not working between li elements

I'mm trying to design a specific type of navbar in javascript/jquery.
I cannot get mouseenter() and mouseleave() to work correctly when the mouse passes between the li objects.
Here is my code. Any ideas?
http://jsfiddle.net/richofwombwell/1v8L0pdz/38/
function inversebuttonon(liId, aId) {
$(liId).css('background-color', 'white');
$(aId).css('background-color', 'white');
$(aId).css('color', '#0086CA');
}
function inversebuttonoff(liId, aId) {
$(liId).css('background-color', '#0086CA');
$(aId).css('background-color', '#0086CA');
$(aId).css('color', 'white');
}
function showselectedmenu(liclass, aclass) {
$('.menu').css('max-height', '100px');
$(liclass).css('display', 'inline');
$(aclass).css('display', 'inline');
}
function dontshowselectedmenu(liclass, aclass) {
$('.menu').css('max-height', '0px', 'none');
$(liclass).css('display', 'none');
$(aclass).css('display', 'none');
}
$('#n-2').mouseenter(function () {
inversebuttonon('#n-2', '#a2');
showselectedmenu('.tmenuli', '.tmenua1');
});
$('.menu').mouseleave(function () {
dontshowselectedmenu('.tmenuli', '.tmenua1');
inversebuttonoff('#n-2', '#a2');
});
$('#n-3').mouseenter(function () {
inversebuttonon('#n-3', '#a3');
showselectedmenu('.tmenuli2', '.tmenua2');
});
$('.menu').mouseleave(function () {
dontshowselectedmenu('.tmenuli2', '.tmenua2');
inversebuttonoff('#n-3', '#a3');
});
Your script does not work correctly because your html code is invalid (you are nesting DIVs instead of list elements. That forces the browser to correct your code (the way it wants to).
Before you continue scripting, please consider using CSS solution:
* {
box-sizing: border-box;
font-family: sans-serif;
font-size: 16px;
}
.my_menu {
height: 66px;
text-align: center;
width: 100%;
overflow:
}
.my_menu ul {
list-style: none;
}
.my_menu ul li {
display: inline-block;
}
.my_menu > ul {
position: relative;
background: none #0086CA;
}
.my_menu ul a {
text-decoration: none;
color: #fff;
display: inline-block;
}
.my_menu > ul > li > a {
padding: 15px 20px;
}
.my_menu > ul > li > a:hover,
.my_menu > ul > li a:focus {
color: #0086CA;
background: #fff;
}
.my_menu ul ul {
background: none grey;
position: absolute;
top: 100%;
left: 0;
right: 0;
width: 100%;
display: none;
}
.my_menu ul li:hover ul {
display: block;
}
.my_menu ul ul a {
padding: 5px 10px;
}
.my_menu ul ul a:hover,
.my_menu ul ul a:focus {
background: none black;
}
<header>
<nav class="my_menu">
<ul>
<li>
Home
</li>
<li>
menuitem1
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
</ul>
</li>
<li>
menuitem2
<ul>
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
</ul>
</li>
</ul>
</nav>
</header>
Also at Playground.
You can probably clean this up but if you insist on a script method, this will work: It also should be easier to extend with less id's etc. just add markup.
Working example here: http://jsfiddle.net/MarkSchultheiss/fLqs1nru/2/
function showmenu(targ, me) {
$('.menuitem').removeClass('menu-on');
$(me).parent().addClass('menu-on');
$('.menu').hide();
$('.' + targ).show();
}
$('.menuitem a').mouseenter(function () {
var targ = $(this).parent().data("targetmenu");
showmenu(targ, this);
});
$('nav').mouseleave(function () {
$('.menuitem ').removeClass('menu-on');
$('.menu').hide();
});
Adjust the markup, get rid of the div and add some classes. Add a data element for the target menu to use.
<nav>
<ul class="ulparent">
<li class="navitem" id="n-1">Home
<li class="navitem menuitem" data-targetmenu="menu1">menuitem1
</li>
<li class="navitem menuitem" data-targetmenu="menu2"><a href="#" >menuitem2</a>
</li>
<ul class="menu menu1">
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
</ul>
<ul class="menu menu2">
<li>item5</li>
<li>item6</li>
<li>item7</li>
<li>item8</li>
</ul>
</ul>
</nav>
add this to the end of you CSS (which can probably be cleaner but this is only additive:)
.menu-on {
background-color: white;
}
.menu-on a {
color:#0086CA;
}
.menu {
max-height:100px;
display:none;
}

Adding 3rd level to CSS menu

I am using very old portal where the is not defined in the begining of the html code, and also I managed to use a jquery/css horizontal drop menu, I need help adding third level to the menu here is my code
#jsddm {
margin: 0;
padding: 0
}
#jsddm li {
float: left;
list-style: none;
font: 12px Tahoma, Arial
}
#jsddm li a {
display: block;
background: #324143;
padding: 5px 12px;
text-decoration: none;
border-right: 1px solid white;
width: 70px;
color: #EAFFED;
white-space: nowrap
}
#jsddm li a:hover {
background: #24313C
}
#jsddm li ul {
margin: 0;
padding: 0;
position: absolute;
visibility: hidden;
border-top: 1px solid white
}
#jsddm li ul li {
float: none;
display: inline
}
#jsddm li ul li a {
width: auto;
background: #A9C251;
color: #24313C
}
#jsddm li ul li a:hover {
background: #8EA344
}
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
function jsddm_open()
{ jsddm_canceltimer();
jsddm_close();
ddmenuitem = $(this).find('ul').eq(0).css('visibility', 'visible');}
function jsddm_close()
{ if(ddmenuitem) ddmenuitem.css('visibility', 'hidden');}
function jsddm_timer()
{ closetimer = window.setTimeout(jsddm_close, timeout);}
function jsddm_canceltimer()
{ if(closetimer)
{ window.clearTimeout(closetimer);
closetimer = null;}}
$(document).ready(function()
{ $('#jsddm > li').bind('mouseover', jsddm_open);
$('#jsddm > li').bind('mouseout', jsddm_timer);});
document.onclick = jsddm_close;
</script>
and here is the menu
<ul id="jsddm">
<li>About us
<ul>
<li>Mission
<ul>
<li>Mission Statment 1</li>
</ul>
</li>
<li> vision </li>
<li>status </li>
</ul>
</li>
<li> Contact
<ul>
<li>Office </li>
<li> Support </li>
</ul>
</li>
</ul>
as you can see the 3rd level "Mession Statment 1" doesn't appear, and that's my problem, any suggestion ???
The problem is maybe due to these lines
$('#jsddm > li').bind('mouseover', jsddm_open);
$('#jsddm > li').bind('mouseout', jsddm_timer);
in which you set an event handler only to the direct <li> children of #jsddm element. But your third <ul> is not contained in a such <li>, so try to change the above lines in
$('#jsddm li').bind('mouseover', jsddm_open);
$('#jsddm li').bind('mouseout', jsddm_timer);
and
function jsddm_open() {
...
ddmenuitem = $(this).children('ul:first').css('visibility', 'visible');}

Categories