jQuery click event target padding - javascript

I am trying to register clicks using jQuery and there seems to be an issue with the padding.
Here's a jsFiddle to help with seeing it.
I'm trying to get clicks on an open menu to do nothing while clicks anywhere else will close all the menus. It works well, but the biggest problem is if you click above the <li> but still within the <div> it fails. It seems to be that the padding isn't counted as part of the div or something.
The code is here as well:
HTML
Main
<div id="mainMenu" class="menu">
<ul>
<li class="menuItem">item 1
</li>
<li class="menuItem">item 2
</li>
<li class="menuItem">item 3
</li>
<li class="menuItem">item 4
</li>
<li class="menuItem">item 5
</li>
</ul>
</div>
Menu 2
<div id="menuTwo" class="menu">
<ul>
<li class="menuItem">item 1
</li>
<li class="menuItem">item 2
</li>
<li class="menuItem">item 3
</li>
<li class="menuItem">item 4
</li>
<li class="menuItem">item 5
</li>
</ul>
</div>
JS
$(document).ready(function () {
//Attach a handler to the document for clicks.
$(document).on("click", function (e) {
//Get the click's target and convert to $ object.
$target = $(e.target);
//Find out if the click occurred on a menu.
$parents = $target.parents(".menu");
if ($parents.length > 0) {
console.log(["Menu click", e]);
return;
} else {
//If it wasn't on a menu close the open menu.
console.log(["Non-menu click", e]);
$('.menu').hide();
}
});
//Handle showing the menu.
$('.menuLink').on("click", function (e) {
//Close all other menus.
$('.menu').hide();
console.log("Started");
e.stopPropagation();
e.preventDefault();
var targetMenu = $(e.target).attr("href");
$(targetMenu).show();
});
});
CSS
#mainMenu {
background-color: lightblue;
}
#menuTwo {
background-color: lightgreen;
}
.menu {
display: none;
border: 1px solid black;
}

Your problem is with this line:
$parents = $target.parents(".menu");
Change it to this:
$parents = $target.closest(".menu");
The div doesn't have a parent with the class .menu, so if you click that, it doesn't find anything. closest includes the selected element in the search.
http://jsfiddle.net/ecnGr/

Use closest to solve your issue
$parents = $target.closest(".menu");
If you still want to use parents then add an extra check to see if the clicked element is the div.
if ($parents.length > 0 || $target.is('.menu')) {
Check Fiddle
The problem with your code was that parents method does not include the element in question. So you have to do that check explicitly, or use closest which includes the element in question as well.

You can just consume all clicks on the menu, which will do the trick.
$(document).ready(function () {
//Attach a handler to the document for clicks.
$(document).on("click", function (e) {
$('.menu').hide();
});
$('.menuLink').on("click", function (e) {
$('.menu').hide();
e.stopPropagation();
e.preventDefault();
var targetMenu = $(e.target).attr("href");
$(targetMenu).show();
});
//Handle showing the menu.
$('.menu').on("click", function (e) {
e.stopPropagation();
});
});
http://jsfiddle.net/MightyPork/UCwAt/8/

Related

Hide dropdown div with jQuery on mouseout

I know there are hundreds of topics regarding this, however none of them seemed to work for me. I want for the dropdown to hide when the mouse leaves the element with jQuery, this is what I currently get:
CodePen example.
jquery:
$(document).ready(function() {
$('.expand').click(function(e) {
e.preventDefault();
$('section').slideUp('normal');
if ($(this).next().is(':hidden') === true) {
$(this).addClass('on');
$(this).next().slideDown('normal');
}
});
$('section').hide();
});
$('section').mouseleave(function(){
$(this).hide();
});
I've also tried the following:
$('section').hide();
$('.section').on('mouseout',function(){
$(this).hide();
})
Yet, nothing really seems to work correctly and gives me the same result. How can I fix this?
Working example.
You should use setTimeout()/clearTimeout() functions to solve your problem so you've to attach mouseleave event to the button with class dropbtn and both mouseleave/mouseleave events (using hover()) to the div dropdown-content so when the mouse leave the button to any other element you should check if the mouseenter is inside the dropdown, if yes clear the timeout the hide_dropdown so it will not hide the div, else your time out will hide the dropdown after 50ms :
var hide_dropdown;
$('.dropbtn').mouseleave(function(e){
var _this = $(this);
hide_dropdown = setTimeout(function(){
_this.next('.dropdown-content').removeClass('show');
},50);
});
$('.dropdown-content').hover(
function(){
clearTimeout(hide_dropdown);
},
function(){
$(this).removeClass('show');
}
);
Hope this helps.
you code it's confusing so i made a simple example for what you want.
see here snippet >
$(".dropbtn").click(function(){
var showMe = $(this).siblings(".drop-menu"),
visibleDrop = $(this).parent("li").siblings("li").find(".drop-menu").filter(":visible")
$(showMe).slideDown()
$(visibleDrop).slideUp()
$(showMe).mouseleave(function(){
$(this).slideUp()
})
})
ul { list-style:none;margin:0;padding:0}
ul li { display:inline-block;width:20%;position:Relative}
ul ul li { display:block;}
ul ul { display:none;position:absolute;top:100%;left:0;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a class="dropbtn"> Has Children1</a>
<ul class="drop-menu">
<li>SubItem1</li>
<li>SubItem2</li>
<li>SubItem3</li>
</ul>
</li>
<li><a class="dropbtn"> Has Children2</a>
<ul class="drop-menu">
<li>SubItem1</li>
<li>SubItem2</li>
<li>SubItem3</li>
</ul>
</li>
<li><a>No children</a></li>
<li><a> No children</a></li>
</ul>
or fiddle > jsFiddle
let me know if it helps
<div>
Menu
</div>
<div id="menudiv" style="position: fixed; background-color: white; display: none;">
Page 1<br />
Page 2<br />
Page 3<br />
</div>
link:-http://jsfiddle.net/5SSDz/
In your codepen example, I have added the following code snippet inside ready callback which seems to work.
$('.expand').on("mouseleave", function(e){
e.preventDefault();
$('section').slideUp('normal');
});
Here is the complete js code
$(document).ready(function() {
$('.dropbtn').on("mouseleave", function(e){
$(".dropdown-content").removeClass("show");
});
$('.expand').on("click", function(e) {
e.preventDefault();
$('section').slideUp('normal');
if ($(this).next().is(':hidden') === true) {
$(this).addClass('on');
$(this).next().slideDown('normal');
}
});
$('section').hide();
});

Toggle submenu and if child clicked go to page

I've built a simple toggle menu that when clicked once shows a list of child elements and if clicked again hides those visible elements.
If a child element is clicked however I want it to visit that page only I cant seem to get it working? Is it to do with my prevent Default?
// Language select in global nav
$('.sub-lang').on('click', function(e) {
if ($(this).hasClass('active') && $(e.target).parent().hasClass('active')) {
$(this).removeClass('active');
$(this).css('height', 'auto');
$(this).children('ul').hide();
} else {
$(this).addClass('active');
$(this).css('height', $(this).find('ul').height() + 65);
$(this).children('ul').show();
}
e.preventDefault();
});
Here is the JsFiddle
Why don't you simple transform your main menu element in paragraph tag ?
or you could put an # inside your main menu element, and delete prevent default.
In this way you don't need to prevent default on your main elements.
Although google.com doesn't load inside an iFrame, you could check this fiddle. It works.
Look at this (with # in the anchors) fiddle
HTML
<ul style=" ">
<li class="sub-lang">
English
<ul style="">
<li>International</li>
<li>UK & Ireland</li>
</ul>
</li>
<li class="sub-lang">
Espanol
<ul style="">
<li>Español</li>
<li>España</li>
</ul>
</li>
<li class="sub-lang">
Francais
<ul style="">
<li>Français</li>
<li>France</li>
</ul>
</li>
</ul>
Add this line before your code
$('.sub-lang > a').removeAttr('href');
Remove
e.preventDefault();
this should work fine
You should add one condition for that.
if($(e.target).parent().hasClass('sub-lang') )
It will allow you to click on submenu.
// Language select in global nav
$('.sub-lang').on('click', function(e) {
if($(e.target).parent().hasClass('sub-lang') ){
if ($(this).hasClass('active') && $(e.target).parent().hasClass('active')) {
$(this).removeClass('active');
$(this).css('height', 'auto');
$(this).children('ul').hide();
} else {
$(this).addClass('active');
$(this).css('height', $(this).find('ul').height() + 65);
$(this).children('ul').show();
}
e.preventDefault();
}
});
ul li ul {
display: none;
z-index: 2;
right: 0;
background-color: #fff;
width: 250px;
}
ul li.active ul {
display: block;
text-align:left;
background: #f1f1f1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul style=" ">
<li class="sub-lang">
English
<ul style="">
<li>International</li>
<li>UK & Ireland</li>
</ul>
</li>
<li class="sub-lang">
Español
<ul style="">
<li>España</li>
</ul>
</li>
<li class="sub-lang">
Français
<ul style="">
<li>France</li>
</ul>
</li>
</ul>
Working Fiddle
Hope it helps.
Here Check This Out.
Explaination.
Instead of delegating the event on the whole li, I bound the event to all the immediate <a> children of the li, and then prevent the propagation for that specific element. So we don't have to figure out how to stop the event propagation (click in our case) to the children element.
Also the JSFiddle may have loading external iframe problems, so check the solution out here.
I think you have to add stopPropagation in your inside list items.
$('.sub-lang ul li').on('click', function(e) {
e.stopPropagation();
});

Burger menu back to 3 links after menu item is clicked

I have a burger icon that when clicked turns into an X. When clicked again turns back into the 3 lines. I have it working so when the links are clicked the menu goes away, but the burger menu doesn't return back to 3 lines. Nothing I have tried is working. Here is what I have.
var burgerIcon = $('.burger-icon');
function toggleBurger(){
burgerIcon.click(function(){
if(burgerIcon.hasClass("is-active") === true)
{
burgerIcon.removeClass("is-active");
//console.log("remove");
}
else
{
burgerIcon.addClass("is-active");
//console.log("add");
}
});
}
toggleBurger();
$('.toggle-nav').click(function() {
$('body').toggleClass('show-nav');
return false;
});
$('nav ul li > a').click(function(){
//console.log("clicked");;
$('body').trigger( "click" );
burgerIcon.trigger( "click" );
});
HTML:
<nav>
<ul data-magellan-expedition="fixed">
<li data-magellan-arrival="work">
Work
</li>
<li data-magellan-arrival="about">
About
</li>
<li data-magellan-arrival="shadow">
Shadow CC
</li>
<li data-magellan-arrival="clients">
Clients
</li>
</ul>
</nav>
Here is a fiddle of what I'm trying to explain: jsFiddle
Since you are using jQuery in your code you can leverage that and then really ALL you need I believe is this:
$('nav ul li > a,.c-hamburger').click(function () {
console.log("clicked");
$('body').toggleClass('show-nav');
if ($('body').hasClass('show-nav')) {
$('.c-hamburger').addClass("is-active");
} else {
$('.c-hamburger').removeClass("is-active");
}
});
Updated fiddle: http://jsfiddle.net/qe38m0t9/2/
NOTE: this uses two selectors, one for the "hamburger" thing and another for the menu separated by a comma then does the same thing depending upon which is clicked.

Dropdown that hides on click outside of the menu

I've got a simple dropdown script and I want it to hide all open dropdowns on a click outside of the menu. But it does not seem to work, does anyone know why?
You can find it here: http://codepen.io/dr-potato/pen/rLleC?editors=101
HTML
<ul>
<li>Home</li>
<li class="Navigation-listItem is-dropdown">
About
<ul class="Navigation-list is-dropdown is-hidden">
<li>Johnny</li>
<li>Julie</li>
<li>Jamie</li>
</ul>
</li>
<li class="Navigation-listItem is-dropdown">
Contact
<ul class="Navigation-list is-dropdown is-hidden">
<li>Johnny</li>
<li>Julie</li>
<li>Jamie</li>
</ul>
</li>
</ul>
CSS
.Navigation-list {
display: block;
}
.Navigation-list.is-hidden {
display: none;
}
JS
$(document).ready(function() {
$('.Navigation-listItem').click(function() {
$(this).children('.Navigation-list.is-dropdown').toggleClass('is-hidden');
});
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function(){
$(".Navigation-listItem.is-dropdown").addClass('is-hidden');
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$(".Navigation-listItem.is-dropdown").click(function(e){
e.stopPropagation();
});
Working Fiddle
jQuery Code
$(document).ready(function () {
$('.Navigation-listItem').click(function () {
$(this).children('.Navigation-list.is-dropdown').toggleClass('is-hidden');
});
/* Anything that gets to the document
will hide the dropdown */
$(document).on('click', function (event) {
if ($(event.target).closest('#menu').length == false) {
$(".Navigation-list.is-dropdown").addClass('is-hidden');
}
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$(".Navigation-listItem.is-dropdown ").click(function (e) {
e.stopPropagation();
});
});
With help from this answer
You can change the display property of your dropdown in this manner. This is just a rough code.
if(dropDownShow.css('display') != 'block'){
dropDownShow.css('display', 'block');
dropDownShow.css('position', 'absolute');
}
else{
dropDownShow.css('display', 'none');
}
With the info you gave and the codepen I can't see it working, but I suppose that $(document).click(function() to hide won't work because the drop down is inside the document so when you click it, it'll disappear. I recommend you to see this post How to hide/show drop down list content in HTML.

Hide/show div in ul with javascript

Let me start by saying I know this is a duplicate, however I couldn't find a solution by looking through previous answers so I was hoping someone can explain what I'm doing wrong with this.
This is part of a menu output by a php script:
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0', 'mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
with the following as my script as per https://stackoverflow.com/a/11842992, which should show each submenu when hovering its parent container
function showMenu(a,b) {
$(a).hover(
function(){
$(b).show();
},
function(){
$(b).hide();
})
}
Javascript and CSS being my weak suits, could someone tell me where my problem is? I feel like onMouseOver doesn't work the way I would expect it to. However I am still learning to manipulate the DOM, please bear with me, thank you!
Edited to reflect missingno's suggestions
For simple scenarios, i'd rather stay away from using JS
Heres how
HTML
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0, mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
CSS
#mtk_main_menu:before,
#mtk_main_menu:after {
content:"";
display:table;
clear:both;
}
#mtk_main_menu {
*zoom:1;
}
#mtk_main_menu > li {
position:relative;
float:left;
}
#mtk_main_menu > li > div {
position:absolute;
left:-999px;
background:grey;
}
#mtk_main_menu > li:hover > div {
left:0;
}
That will do the trick
Fiddle: http://jsfiddle.net/Varinder/7pXSw/
Edit
If you really want to go the JS way - heres how:
HTML
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0, mtk_div_submenu_0');">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
CSS
#mtk_main_menu:before,
#mtk_main_menu:after {
content:"";
display:table;
clear:both;
}
#mtk_main_menu {
*zoom:1;
}
#mtk_main_menu > li {
position:relative;
float:left;
}
#mtk_main_menu > li > div {
position:absolute;
display:none;
/*left:-999px;*/
background:grey;
}
#mtk_main_menu > li:hover > div {
/*left:0;*/
}
JS
function showMenu( args ) {
var arguments = args.split(",");
var submenuWrapper = arguments[1].replace(" ", "");
var $subMenuWrapper = $( "#" + submenuWrapper );
$subMenuWrapper.show();
var $menuItem = $subMenuWrapper.closest("li");
$menuItem.on("mouseout", function() {
$subMenuWrapper.hide();
$(this).off("mouseout");
});
}
Fiddle: http://jsfiddle.net/Varinder/vnwy3/1/
You are calling the event handler with a single string parameter instead of two. Try changing
showMenu('mtk_submenu_0, mtk_div_submenu_0')
into
showMenu('mtk_submenu_0', 'mtk_div_submenu_0')
Additionally, inside your script you should use are using literal strings instead of using your parameters
//This looks for an element of class "a"
$("a").hover(
//This uses the contents of the `a` variable instead:
$(a).hover(
Finally, your function is using 'mtk_submenu_0' as a jquery selector. This searches for a class instead of an id. Change the selector to add a "#" on front or change your jquery logic to not need ids (for example, you could create selectors to search for the first div and ul descendants of the current element.
By doing what you are doing, every time the onMouseOver event is triggered, you're attaching the jQuery hover event. Each time you're attaching another listener.
Instead, initialize your event on document ready:
$(function () {
$("#tk_div_submenu_0").hover(
function(){
$("#mtk_submenu_0").show();
},
function(){
$("#mtk_submenu_0").hide();
})
);
});
That will initialize it when the document is ready, and it will initialize it once.
Then just remove your onMouseOver event from the HTML.
<li class="mtk_topmenu">Manager Options ... </li>
First, you're going the long way around the problem. jQuery has a built in toggle method that performs the show/hide for you. Secondly you're putting the hover call on the child element of the item you're trying to show on hover. Here's an updated version of your code:
<ul id="mtk_main_menu">
<li class="mtk_topmenu" onMouseOver="showMenu(this,'mtk_div_submenu_0');">
Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
</ul>
JS:
function showMenu(a,b) {
var divStr = '#' + a.id + " div";
$(divStr).toggle();
}
I used the hover event on the LI element as it makes more sense in this case.
Here it is in a fiddle: http://jsfiddle.net/3Ecrq/
One thing I find strange about your code is that the first div you mention, mtk_submenu_0, is inside the div you are showing / hiding, mtk_div_submenu_0. Once you hide the outer div, the inner div cannot be 'hovered over', thus preventing it from being shown again.
To ensure the inner div does not get hidden, try something like this:
HTML:
<ul id="mtk_main_menu">
<li class="mtk_topmenu">Manager Options
<div id="mtk_div_submenu_0">
<ul id="mtk_submenu_0">
<li class="mtk_submenu">Preferences</li>
<li class="mtk_submenu">Employee Options</li>
</ul>
</div>
</li>
Javascript:
$(document).ready(function() {
$('.mtk_topmenu').hover(
function() {
$('#mtk_div_submenu_0').show();
},
function() {
$('#mtk_div_submenu_0').hide();
});
});
Because of your line:
<li class="mtk_topmenu" onMouseOver="showMenu('mtk_submenu_0', 'mtk_div_submenu_0');">
I assumed you were looking to have the mtk_div_submenu_0 div show / hide whenever the text Manager Options is moused over. Hopefully this helps!

Categories

Resources