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.
Related
I have a button which creates a pulldown in which you can select several categories.
Now i want this to close automatically when i click outside the pulldown.
Something like a lightbox or modal popup which closes if you click anywhere else on the page.
Now i have to click the button again to close it. If i dont and go elsewhere on the page, the dropdown stays visible (until i click it)
This is the code of the button:
$(function(){
$('#browse-btn').click(function(){
$('#browse-content').toggle('1000');
$(this).toggleClass('active');
if ($(this).hasClass('active')) $(this).find('span').html('▲')
else $(this).find('span').html('▼')
});
$(".scroll-top").scrollToTop();
$("#category_id").selectbox();
});
Is this possible?
thanks
Using jquery this is the code I used for a similar case scenario sometime ago:
$(document).click(function(event) {
if(!$(event.target).closest('.pulldown').length) {
if($('.pulldown').is(":visible")) {
$('.pulldown').slideUp()
}
}
})
You can read more about this in the original post How to detect a click outside an element? submitted by Art.
I'm not exactly sure of the elements you want to hide as you don't have a demo, so I cannot provide a fully working code, however you should do something like this:
$("body").click(function(event) {
if (event.target.id != "browse-btn") {
// Do something when there's a click outside of #browse-btn
// and the element you want to hide is currently visible
}
});
You can attach a click event to all chidren of the body tag that removes that active class, but you would want to make sure to unbind that event so it doesn't run every time a click takes place that doesn't have some sort of prevent default on it. Something like this:
$(function(){
var hidePulldown = function(){
$('#browse-btn').removeClass('active');
$('body *').unbind("click", hidePulldown);
}
$('#browse-btn').click(function(){
$('#browse-content').toggle('1000');
$(this).toggleClass('active');
if ($(this).hasClass('active')) $(this).find('span').html('▲')
else {
$(this).find('span').html('▼');
$(document).on('click', 'body *', hidePulldown);
}
});
$(".scroll-top").scrollToTop();
$("#category_id").selectbox();
});
Also, the
$(document).on('click', element, function(){function body})
is the preferred way to attach click events i believe: $(document).on('click', '#id', function() {}) vs $('#id').on('click', function(){})
This is what worked flawlessly for me after reading some of the answers here:
$(document).click(function(event) {
if(!$(event.target).closest('#menucontainer').length &&
!$(event.target).is('#menucontainer')) {
if($('#menucontainer').is(":visible")) {
$('#menucontainer').hide();
}
}
})
Thanks for pointing me in the right way!
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
}
});
I'm trying to achieve something similar to the bootstrap button drop downs (http://twitter.github.io/bootstrap/components.html#buttonDropdowns) but need something lightweight. Basic functionality is more or less this:
On clicking the link, corresponding dropdown div opens (works)
On clicking another link, the previous dropdown closes as well as the css class is removed (works)
On clicking on the link of the opened dropdown, close the dropdown (does not work (closes and reopens))
On clicking anywhere in the body (so outside the link and dropdown), close the dropdown (does not work)
What should be the logic behind this?
Demo: http://jsfiddle.net/fU2BZ/
Does the code below make sense?
$(document).click( function(){
$('.dropdownbox').hide(0);
$('.dropdown').removeClass('active');
});
$('.dropdown').click( function(event){
event.stopPropagation();
$('.dropdown').removeClass('active');
$('.dropdownbox').hide();
$(this).addClass('active').find('.dropdownbox').slideToggle(200);
});
Made some changes to your code, added some if else logic, seems to work.
fiddle: http://jsfiddle.net/fU2BZ/1/
Code:
$('.dropdown').click( function(event){
event.stopPropagation();
if ($(this).hasClass("active")) {
$('.dropdown').removeClass('active');
$('.dropdownbox').hide();
} else {
$('.dropdownbox').hide();
$(this).addClass('active').find('.dropdownbox').slideToggle(200);
}
});
You were pretty close. I'd store a flag if it was visible (so that you don't double-up on the same code)
$('.dropdown').click( function(event){
event.stopPropagation();
var active = false;
if ( $(this).hasClass('active') )
active = true;
$('.dropdown').removeClass('active');
$('.dropdownbox').hide();
if ( ! active )
$(this).addClass('active').find('.dropdownbox').slideToggle(200);
});
jsFiddle: http://jsfiddle.net/fU2BZ/4/
Simple code to resolve your third issue:
$('.dropdown').click(function (event) {
event.stopPropagation();
$('.dropdown').removeClass('active').not(this).find('.dropdownbox').hide();
$(this).toggleClass('active').find('.dropdownbox').slideToggle(200);
});
To resolve your last issue, do this:
$('.dropdownbox').click(function (event) {
event.stopPropagation();
});
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/
I'm kind of stuck on a problem of how to stop my menu from executing the fadeOut() function. When I click the main links on my menu to open the submenu it just fades out. Here is how the code looks at the moment:
$('a.main-menu-item').click(function(){
if($('.rtmenu:visible')){
$('.rtmenu').click(function(e) { e.stopPropagation(); });
$(document).click(function() {
$('.rtmenu').fadeOut(200);
});
}
})
Can anyone tell me how I can write 'if not clicked a.main-menu-item' where it says 'document'?
Much Appreciated
SOLUTION FOUND!
$('.rtmenu').click(function(e) { e.stopPropagation(); });
$('.rtmenu').mouseout(function(){
$(document).one('click',function() { $('.rtmenu').fadeOut(200); });
})
Have a look at Ben Alman's "outside events" plugin. It allows you to define a range of events, not just click events. With it, your code would look something like this:
$('.rtmenu').bind('clickoutside', function() {
$(this).fadeOut(200);
});
As an aside, you shouldn't set up the bind inside the click event for the menu, this will attach another handler every time the menu option is clicked. Your code should be replace with something like:
$('a.main-menu-item').click(function(){
// Show menu item
});
$('.rtmenu').bind('clickoutside', function() {
$(this).fadeOut(200);
});
use blur event to handle losing focus.
This might help also.