Attach click event to body via button click without immediately triggering it - javascript

What's happening:
User clicks button
Menu opens (<li>s display = block)
Close menu function is attached to <body>
Close menu function is immediately triggered and menu closes
I'm attaching a function to close the menu (hide the lis) to the body (3) so that after the menu has been opened, the user can close it by clicking anywhere off it onscreen.
The problem is the function attached to the body is immediately triggered in the button click function, so the menu opens and closes before the user even sees it.
I'm using jQuery 1.7's .on() function to bind the event.
Does anyone know a simple solution to this? 'bindAfterEvent' or something along those lines.
Code:
$(document).ready(function() {
$('#page-content div.center-block div:nth-child(1) ul li:nth-child(1)').on('click', openSubnav);
});
openSubnav = function(e) {
// Shows all li tags and attaches close function to the body
e.preventDefault();
$('#page-content div.center-block div:nth-child(1) ul li').show();
$('body').on('click', closeSubnav);
};
closeSubnav = function() {
// Hides all li tags except the first (used to open)
$('#page-content div.center-block div:nth-child(1) ul li').hide();
$('#page-content div.center-block div:nth-child(1) ul li:nth-child(1)').show();
};

Something like this ? (Updated)
$('button').off('click').on('click', functione(e) {
// stop propagation to assure the body click won't be triggered
e.stopPropagation();
$('div').show();
$('body').off('click').on('click', function(e) {
// return false if the element clicked is the button that shows the menu
if($(e.target).is('button')) return false;
$('div').hide();
$('body').off('click');
});
});

Use jquery's stopPropagation() on the click event when opening the menu. See this fiddle: http://jsfiddle.net/zoeexe5q/

Related

Javascript and focus on descendant elements

Please, check out the JSFiddle:
$('#contacts .tab-content').focusout(function () {
$('#contacts .active').removeClass('active');
});
JSFiddle
I have a (Bootstrap 3) panel at the bottom of the page which pops up when I click on its label, and goes back down when I click anywhere else outside of it. To do so, I put focus on the panel and remove the .active class when the focus is lost. The problem is that, if I click on any other focusable element inside of the panel (like inputs or buttons), it also loses the focus and triggers the function. How can I include all elements inside the panel and remove the .active class when none of them is focused?
$('#contacts > .nav-tabs a').click(function() {
$('#contacts .tab-content').focus();
$('#panel').toggleClass('active');
});
$(document).click(function(e){
if(!$(event.target).closest( ".tab-content" ).length && !$(event.target).closest( ".nav-tabs a" ).length){
$('#panel').removeClass('active');
}
});
Check this once

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.

Prevent Click on Window When Binding a Click?

I have a click event on an element that when clicked binds another click event on the window which has a callback of function with a reverse operation. In this case it's simply a menu like an OS menu where you click on a menu and then when you click on a menu item or outside the menu it closes the menu. Think right click menu, Ubuntu/Mac the top menu bar, etc.
My issue is that because im binding a click event on the window on click it's triggering the window click also. How can I "delay" it so its all "future" clicks? If you look for the app().debug('closed/clicked?','console'); you'll see two, and they both fire on click...
So my code looks like:
{..code...}
actionMenu: function(action,item){
if(action == 'open'){
$(window).bind('click.contextMenus',app().actionMenu('close'));
$(item).addClass('active').find('ol').css({display:'block',top:$(item).outerHeight()+'px'});
}
else if(action == 'close'){
app().debug('closed?','console');
$('#menu .active').removeClass('active');
$('#menu > ol > li ol').css({display:'none'});
$(window).unbind('click.contextMenus');
}
},
{..code...}
And:
$('#menu > ol > li').click(function(e){
if($(this).find('ol').is(':visible')){
app().actionMenu('close');
}
else{
app().debug('clicked?','console');
app().actionMenu('open',this);
return false;
}
});
Instead of binding on window, you can bind on <body> (I'm not sure whether or not stopping propagation would work when binding on window)
$('body').bind('click.contextMenus',app().actionMenu('close'));
and then you can prevent event propagation on your menu's onclick to stop it from firing the parent elements' onclick
$('#menu > ol > li').click(function(e){
e.stopPropagation();
if($(this).find('ol').is(':visible')){
app().actionMenu('close');
}
else{
app().debug('clicked?','console');
app().actionMenu('open',this);
return false;
}
});
EDIT
I had not looked closely enough. This is the line that's the issue:
$(window).bind('click.contextMenus',app().actionMenu('close'));
You're actually calling the actionMenu() function there. You need to do this instead:
$(window).bind('click.contextMenus', function() { app().actionMenu('close') } );

Hide div on blur

I have a jQuery function where when an element is clicked a hidden div shows.
$('.openHide').click(function(){
$(this).next('.hiddenContent').toggle();
});
I need to modify it s that I could close this div if I click back not just on the first element. Possibly on Blur, but I am not sure how to indicate the element...
$('.hiddenContent').blur(function() {
$('.hiddenContent').parent().children('.hiddenContent').hide();
});
Here's my HTML:
<span class="openHide">text here</span>
<div style="display:none" class="hiddenContent">
hidden content here
</div>
On the click on the span the div should be toggled
On the body click the div should be hidden
On the click on the div, the event should not be propagated to the body
On the click on the span the event should not be propagated to the body
$(document).ready(function() {
$('.openHide').click(function(e) {
$('.hiddenContent').toggle();
e.stopPropagation();
});
$(document.body).click(function() {
$('.hiddenContent').hide();
});
$('.hiddenContent').click(function(e) {
e.stopPropagation();
});
});
If .hiddenContent is a div you won't be able to use blur, that only works on text inputs. mouseout may be an alternative, and $(this) is what I think you are looking for in this case:
$('.hiddenContent').mouseout(function() {
$(this).hide();
});
Hide on clicking elsewhere
If you want to hide the div when you click outside the element you must watch for clicks all over the body of the page:
$('body').click(function() {
// Hide all hidden content
$('.hiddenContent').hide();
});
And then provide and exception for when you are clicking on the actually hidden content itself, and when you want to open it:
$('.hiddenContent').click(function(e) { e.stopPropagation() });
$('.openHide').click(function(e) {
$(this).next('.hiddenContent').toggle();
// this stops the event from then being caught by the body click binding
e.stopPropagation();
});

Categories

Resources