jQuery - hide dropdown when DOM element is focused - javascript

i got to show a dropdown menu, now i would like to hide that when anoher element (not dropdown or dropdown's children) in the DOM is focused.
(hide dropdpown when element !== dropdown||dropdown's childrens is focused in the DOM)
i tryed with focusout() with no results:
$('a').on('click',function(){
$('.drop.user-menu').fadeIn();
});
$('.drop.user-menu').on('focusout',function(){
$(this).fadeOut();
alert('antani');
});
any idea?
jsfiddle here : example

event.target() will be useful in this scenario:
$('.drop.user-menu').on('focusout',function(e){
if(e.target !== this){
$(this).fadeOut();
alert('antani');
}
});
Update:
Check this out and see if helps:
$('.a').on('click', function (e) {
e.stopPropagation();
$('.drop.user-menu').fadeToggle();
});
$('.drop.user-menu').on('click', function (e) {
e.stopPropagation();
$('.drop.user-menu').fadeIn();
});
$(document).on('click', function (e) {
if (e.target !== $('.drop.user-menu') && e.target !== $('.a')) {
$('.drop.user-menu').fadeOut();
}
});
The above script done with click in this fiddle

A DIV cannot take or lose focus (unless it has a tabindex). You'll have to give it a tabindex or add a focusable element into your div.drop.user-menu. See Which HTML elements can receive focus?.
You then also have to explicitly give that element (or an element within it) focus (with .focus()) as simply fading it in doesn't give it focus.
When the element blurs, then check if the new active element is still part of the menu. If it's not, fade out the menu.
See a working example.

There is no focus or focusout events triggered, because you're not operating on form fields.
This is probably what you want : How do I detect a click outside an element?
var menu = $('.drop.user-menu');
menu.on('click',function(e){
e.stopPropagation(); // stop clicks on menu from bubbling to document
});
$('a').on('click', function (e) {
menu.fadeIn();
e.stopPropagation(); // stop clicks on <a> from bubbling to document
});
$(document).on('click',function(e){
// any other click
if (menu.is(":visible")) {
menu.fadeOut();
}
});
http://jsfiddle.net/BBxEN/10/
Update
As Derek points out, this is not very friendly for keyboard users. Consider implementing a way for users to both open and close the menu using keyboard shortcuts.

You can tru with blur, is what you want?
Try this:
$('.drop.user-menu').on('blur',function(){
$(this).fadeOut();
alert('antani');
});

Related

jQuery if body hasClass then sidemenu toggleClass issue

What I'm trying to achieve is toggling the sidemenu on click anywhere in the body except inside sidemenu div itself. I currently can toggle the sidemenu from its toggle link (comment out line 13-14 in js fiddle) but not by clicking anywhere on body. This is the concerned code:
$('body').bind('click', function (e) {
var opened = $('body').hasClass('sidemenu-open');
if (opened === true) {
$('.sidemenu').removeClass('is-visible');
$('body').removeClass('sidemenu-open');
}
});
JSFIDDLE
I know I can add a wrapper for the content but I don't have much flexibility in the HTML structure.
There are two problems. First, when you click on the link, the click is bubbling out to the body. So the menu toggles open, then it toggles closed again, so nothing happens. Use event.stopPropagation() to prevent that.
Second, when the side menu is closed, <body> is just the one line containing the link. If you want to be able to click anywhere in the window, use $(document) rather than $('body').
$(function () {
$('.sidemenu-toggle').on('click', function (event) {
event.preventDefault();
event.stopPropagation();
$('.sidemenu').toggleClass('is-visible');
$('body.sidemenu-enabled').toggleClass('sidemenu-open');
$('.sidemenu').toggleClass('sidemenu-open');
});
});
$(document).on('click', function (e) {
var opened = $('body').hasClass('sidemenu-open');
if (opened === true) {
$('.sidemenu').removeClass('is-visible');
$('body').removeClass('sidemenu-open');
}
});
DEMO
Your click on the side menu is propagating down to the body and activating that handler as well - preventDefault isn't what you're after, you need to return false as well. Try this click handler instead.
$(function () {
$('.sidemenu-toggle').on('click', function (event) {
$('.sidemenu').toggleClass('is-visible');
$('body.sidemenu-enabled').toggleClass('sidemenu-open');
$('.sidemenu').toggleClass('sidemenu-open');
return false;
});
});
You can get the target element in click event by which you can have further conditions.
$('body').click(function(evt){
if(evt.target.id == "your_sidemenu_id"){
//do nothing
}
else{
//do the toggle here as this will be implemented whenever any element is clicked other than your sidemenu
}
});

jQuery blur()....How exactly does it work?

I've created a mobile dropdown menu for a responsive website, that essentially shows a hidden unordered list when you click on a certain element. It works great, except for the fact that I can't get the blur() function to work, so that when a user clicks anywhere on the page other than inside the menu, it hides the menu. Here's a codepen: http://codepen.io/trevanhetzel/pen/wIrkH
My javascript looks like so:
$(function() {
var pull = $('#pull');
menu = $('header ul');
$(pull).on('click', function(e) {
e.preventDefault();
$('.close-menu').toggle();
$('.mobi-nav span').toggle();
menu.slideToggle(250);
});
$(menu).blur(function() {
$(this).slideToggle();
});
});
I've struggled with blur() in the past, so would really like to figure out once and for all how exactly it works, and whether or not I'm using it in the right context here. Thanks!
You have to watch for clicks yourself. And use $.contains to see if the clicked thing is within your menu:
$(document).click(function (ev) {
if (ev.target !== menu.get(0) && !$.contains(menu.get(0), ev.target)) {
menu.slideUp();
}
});
Just be sure to call ev.stopPropagation() in your toggle click handler to prevent the handler above from immediately closing the menu when the event bubbles up.

jQuery click anywhere in the page except on 1 div

How can I trigger a function when I click anywhere on my page except on one div (id=menu_content) ?
You can apply click on body of document and cancel click processing if the click event is generated by div with id menu_content, This will bind event to single element and saving binding of click with every element except menu_content
$('body').click(function(evt){
if(evt.target.id == "menu_content")
return;
//For descendants of menu_content being clicked, remove this check if you do not want to put constraint on descendants.
if($(evt.target).closest('#menu_content').length)
return;
//Do processing of click event here for every element except with id menu_content
});
See the documentation for jQuery Event Target. Using the target property of the event object, you can detect where the click originated within the #menu_content element and, if so, terminate the click handler early. You will have to use .closest() to handle cases where the click originated in a descendant of #menu_content.
$(document).click(function(e){
// Check if click was triggered on or within #menu_content
if( $(e.target).closest("#menu_content").length > 0 ) {
return false;
}
// Otherwise
// trigger your click function
});
try this
$('html').click(function() {
//your stuf
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
you can also use the outside events
I know that this question has been answered, And all the answers are nice.
But I wanted to add my two cents to this question for people who have similar (but not exactly the same) problem.
In a more general way, we can do something like this:
$('body').click(function(evt){
if(!$(evt.target).is('#menu_content')) {
//event handling code
}
});
This way we can handle not only events fired by anything except element with id menu_content but also events that are fired by anything except any element that we can select using CSS selectors.
For instance in the following code snippet I am getting events fired by any element except all <li> elements which are descendants of div element with id myNavbar.
$('body').click(function(evt){
if(!$(evt.target).is('div#myNavbar li')) {
//event handling code
}
});
here is what i did. wanted to make sure i could click any of the children in my datepicker without closing it.
$('html').click(function(e){
if (e.target.id == 'menu_content' || $(e.target).parents('#menu_content').length > 0) {
// clicked menu content or children
} else {
// didnt click menu content
}
});
my actual code:
$('html').click(function(e){
if (e.target.id != 'datepicker'
&& $(e.target).parents('#datepicker').length == 0
&& !$(e.target).hasClass('datepicker')
) {
$('#datepicker').remove();
}
});
You could try this:
$(":not(#menu_content)").on("click", function(e) {
e.stopPropagation();
// Run your function when clicked anywhere except #menu_content
// Use with caution, 'cause it will prevent clicking on other elements
});
$("#menu_content").on("click", function(e) {
e.stopPropagation();
// Run when clicked on #menu_content
});

Dropdown More errors

I have a script here that if i click on it drops down, as well on if i clickoutside it drops down. But i want to make it so that if i click on bottom it scrolls up. For some reason it doesnt work here. It only scrolls up if i click outside the box.
Heres an example. http://jsfiddle.net/w8mfx/
If i click on bottom it wont scroll up only if i click on outside. But i want it to work both ways.
$(document).ready(function() {
$('#bottom').click(function(event) {
event.stopPropagation();
$('#content').slideDown();
});
$('html').click(function(e) {
//alert(1);
if (e.target.id != 'bottom') {
$('#content').slideUp();
}
});
});
http://jsfiddle.net/w8mfx/7/
I added:
$('#content').click(function (event) {
event.stopPropagation();
});
so the user can click on the #content element and not trigger the slide function. That also means that the event handler for the html element can be simpler:
$('html').click(function(e) {
$('#content').slideUp();
});
In the jsfiddle you may notice I cached the $('#content') selector in a variable since it was being used in more than one place.
Use slideToggle(). http://jsfiddle.net/w8mfx/5/

Hide a DIV when it loses focus/blur

I have a JavaScript that displays a DIV (sets its display css property from 'none' to 'normal'. Is there a way to give it focus as well so that when I click somewhere else on the page, the DIV loses focus and its display property is set to none (basically hiding it). I'm using JavaScript and jQuery
For the hide the div when clicking any where on page except the selecteddiv
$(document).not("#selecteddiv").click(function() {
$('#selecteddiv').hide();
});
if you want to hide the div with lost focus or blur with animation then also
$("#selecteddiv").focusout(function() {
$('#selecteddiv').hide();
});
with animation
$("#selecteddiv").focusout(function() {
$('#selecteddiv').animate({
display:"none"
});
});
May this will help you
The examples already given unfortunately do not work if you have an iframe on your site and then click inside the iframe. Attaching the event to the document will only attach it to same document that your element is in.
You could also attach it to any iframes you're using, but most browsers won't let you do this if the iframe has loaded content from another domain.
The best way to do this is to copy what's done in the jQuery UI menubar plugin.
Basic example HTML:
<div id="menu">Click here to show the menu
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
And the jQuery needed to make it work:
var timeKeeper;
$('#menu').click(function()
{
$('#menu ul').show();
});
$('#menu ul').click(function()
{
clearTimeout(timeKeeper);
});
$('#menu').focusout(function()
{
timeKeeper = setTimeout(function() {$('#menu ul').hide()}, 150);
});
$('#menu').attr('tabIndex', -1);
$('#menu ul').hide();
What it does is give the menu a tab index, so that it can be considered to have focus. Now that you've done that you can use the focusout event handler on the menu. This will fire whenever it has been considered to lose focus. Unfortunately, clicking some child elements will trigger the focusout event (example clicking links) so we need to disable hiding the menu if any child elements have been clicked.
Because the focusout event gets called before the click event of any children, the way to achieve this is by setting a small timeout before hiding the element, and then a click on any child elements should clear this timeout, meaning the menu doesn't get hidden.
Here is my working jsfiddle example
$(document).mouseup(function (e)
{
var container = $("YOUR CONTAINER SELECTOR");
if (!container.is(e.target)&& container.has(e.target).length === 0)
{
container.hide();
}
});
You can bind a function on click of body and check if its the current div using e.target (e is the event)
$(document).ready(function () {
$("body").click(function(e) {
if($(e.target).attr('id') === "div-id") {
$("#div-id").show();
}
else {
$("#div-id").hide();
}
});
});
Regarding mouse clicks, see the other answers.
However regarding lost focus, .focusout is not the event to attach to, but rather .focusin. Why? Consider the following popup:
<div class="popup">
<input type="text" name="t1">
<input type="text" name="t2">
</div>
What happens on moving from t1 to t2:
t1 sends focusout, which bubbles up to $('.popup').focusout
t2 sends focusin, which bubbles up to $('.popup').focusin
... so you get both types of event even though the focus stayed completely inside the popup.
The solution is to analogous to the magic trick done with .click:
$(document).ready(function() {
$('html').focusin(function() {
$('.popup').hide();
});
$('.popup').focusin(function(ev) {
ev.stopPropagation();
});
});
(side note: I found the .not(...) solution not working bc. of event bubbling).
Bonus: working fiddle click me - open the popup, then try tabbing through the inputs.
I was also looking for this and here I found the solution https://api.jquery.com/mouseleave/. This may be useful for future readers.
The mouseleave event differs from mouseout in the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleave event, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant.
On triggering mouseup() event, we can check the click is inside the div or a descendant and take action accordingly.
$(document).mouseup(function (e) {
var divContent= $(".className");
if(!divContent.is(e.target) && divContent.has(e.target).length === 0) {
$(".className").hide();
}
});
I personally haven't tried blur on divs, only on inputs etc. If blur eventhandler works, it's perfect and use it. If it doesn't, you could check this out:
jQuery animate when <div> loses focus
$('.menu > li').click(function() {
$(this).children('ul').stop().slideDown('fast',function()
{
$(document).one('click',function()
{
$('.menu > li').children('ul').stop().slideUp('fast');
});
});
});
Showing is easy
$('somewhere').click(function {$('#foo').show();})
For hiding
How do I hide a div when it loses its focus?
With jQuery you can hide elements with hide(), ex: $("#foo").hide()
Hide element in event listener:
$("#foo").blur(function() {
$("#foo").hide();
});

Categories

Resources