Prevent Click on Window When Binding a Click? - javascript

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') } );

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
}
});

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

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/

jQuery - hide dropdown when DOM element is focused

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');
});

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.

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/

Categories

Resources