I have a button that when clicked will popup a menu to the right of the button. This menu is a rather large UL of list items. The page that this menu is on contains lots of other elements.
Once the menu pops up, a user can click an option on the menu and the menu will disappear (menu.hide()).
However, it feels wierd not being able to get rid of the menu any other way. I like the idea of "if the user clicks on anything but the menu, the menu will hide." But i hate doing a "clickoutside" event that binds events to everything but the menu.
Another option is "mouseout" but "mouseout" always gets fired too early, because the mouse has to travel across the screen to get to the menu.
Any ideas on what event I can bind to the menu, so the user can get rid of it naturally, and at will? (not just when he clicks an option)
You can bind one event to the body when the menu is open. Use the click event to determine if the click occurred outside of the menu. If outside of the menu, hide the menu and remove the bind.
// binding function
closeMe = function(e) {
var $target = $(e.target);
// click is not inside the menu
if(!$target.hasClass('menu') && $target.parents('.menu').length !== 1) {
// hide menu
menu.hide();
// unbind events
$('body').unbind('mousedown.menuhide', closeMe);
}
};
// show menu
menu.show(function() {
// bind menu hide event
$('body').bind('mousedown.menuhide', closeMe);
});
Very easy, just use something like this
$('html').click(function() {
menu.close();
});
$('#menu').click(function(e){
e.stopPropagation();
// do stuff
// maybe some nice animation or w/e
menu.close();
});
Related
I have created a dropdown functionality using Jquery with one event listener that allows me to close the dropdown when clicked anywhere outside the dropdown container and another event listener which handles the submenu items.
By design the dropdown should stay open even if the submenu items are clicked and should only close if the toggle button is clicked or the user clicks outside the dropdown container.
The problem
Lets say that general.js has the click event listener as follows
$('document').on('click.namespace',function(e){ // do stuff });
Now anotherscript.js has an event listener which handles the actual sub menu clicks
$('#clickbutton').on('click', function(e){
// Remove all html from inside the .dropdown container
// Recreate the html using another js function
$('.container').html(recreatedhtml);
});
The problem occurs when I try to identify who the parent of the submenu button click target is, because I want to know if the click was inside the container or outside.
Since a click on #clickbutton removes html from the container and reinserts it I believe this causes problems for the parents() function therefore the parents('.dropdown') function returns false even though the sub menu item is a descendent of the dropdown class.
Check the target of the event
$(document).on('click.namespace',function(e){
if(!$(e.target).closest(dropdownContainerSelector).length){
// click is not in dropdown container
}
});
Note that document is not a string, it is a global object within window
I'm trying to create a top-nav menu as follows:
The idea is that when you click a tab, the tab itself gets highlighted in black and an associated menu shows up beneath it. This works fine.
I also want the menu to disappear and the tab to be unhighlighted if the mouse leaves either the tab or the menu. This is where I'm running into trouble. At the moment, the JQuery I use to handle this is roughly as follows:
$('.item-support a').click(function(e){
// removeClass('curr') from all other tabs
$('.item-support').addClass('curr');
$('#submenu-support').fadeIn('fast');
$('.item-support').mouseleave(function(e) {
$('.item-support').removeClass('curr');
$('#submenu-products').fadeOut('fast');
});
}else{ // Click again
$('.item-support').removeClass('curr');
$('#submenu-support').fadeOut('fast');
}
return false;
});
$('#submenu-products').mouseleave(function(e) {
$('.item-support').removeClass('curr');
$('#submenu-products').fadeOut('fast');
});
// Similar code for the other tabs
The problem is that the mouseleave events for the tab and sub-menu are not synchronized. So, for example, if the mouse leaves the support tab and enters the submenu below it, the submenu vanishes. I've tried many different approaches to get around this and even have one that crudely works using pageX and pageY co-ordinates, but I'm looking for a more elegant solution. How do I get the tab and its associated submenu to work in tandem? Is there a way to bind the two divs together? Or make mouseleave recognize an exception when entering a certain div?
You can check if either element is hovered, and do something like this:
$('.item-support, #submenu-support').mouseleave(function() {
setTimeout(function() {
if (!$('.item-support').is(':hover') && !$('#submenu-support').is(':hover')) {
$('.item-support').removeClass('curr');
$('#submenu-support').hide();
}
}, 50);
});
You also shouldn't bind your mouseleave event in the callback of another event. Currently every time you click item-support, you are binding another mouseleave event to it.
I'm binding a mouse click listener to serveral SVG elements and - on a click- trigger the open method of a kendo context menu. If the menu is already open (I listening to the activate/deactivate events to check if the menu is open), and the user clicks on the same element , it shall close.
The problem is: the context menu closes by default on mouse down. So when it is open, the user clicks on the same element it closes on mousedown and reopen on mouseup - but it shall close on click, not mousedown. Is there a way to tell this to the context menu directly or do I have to control this by the events of the SVG elements?
thanks!
Not sure I understand what you're trying to do, but you can influence whether the menu closes when you click outside of the menu like this:
kendo.ui.ContextMenu.fn._closeHandler = function (closeHandler) {
return function(e) {
var clickInMenu = $.contains(this.element[0], e.target);
if (clickInMenu) { // click outside will do nothing
closeHandler.call(this, e);
}
}
}(kendo.ui.ContextMenu.fn._closeHandler);
var contextMenu =$("#context-menu").kendoContextMenu({
target: "#target"
});
(demo)
I have a customized dropdown in html coded in "ul" and "li", I show options when a user clicks on the head of "ul" I would like to hide these elements when the user clicks outside the menu area.
Is something like this possible with javascript/YUI not Jquery?
I'm not a YUI guy, so I suspect this could be written a bit better, but I have tested it and it works.
Hide the dropdown anytime the document is clicked:
Y.one(document).on("click", function(){
Y.one("#menu").hide();
});
Prevent clicks on the ul from propagating to the document:
Y.one("#menu").on("click", function(e){
e.stopPropagation();
});
If the visitor clicks anywhere, the click will bubble up to the document, and hide the menu. If they click on the menu, the event will be prevented from bubbling up to the document, and as such the menu will not be hidden.
Demo: http://jsfiddle.net/nHnZT/
use('event-outside') adds support for "outside" events. See the user guide for details: http://yuilibrary.com/yui/docs/event/outside.html
I have a menu in jQuery when you click on a link it opens up, but I want it so when you click somewhere else, anywhere else that is not the menu, it becomes hidden.
At the moment I'm binding a click event to
$(':not(#the_menu)')
But this seems like I'm binding a click event to the entire minus the menu, is there a more efficient way of doing something like this?
The best way to do this is with bubbling capture, like this:
$(document).click(function() {
//close menu
})
$("#the_menu").click(function(e) {
e.stopPropagation();
});
How this works is every click bubbles (unless you stop it, usually by return false; or event.stopPopagation()), so whatever you click bubbles all the way up to DOM...if a click does that, we close the menu. If it came from inside the menu, we stop the bubble...so the click doesn't bubble up, triggering a close. This approach uses only 2 event handlers instead of 1 on everything but the menu, so very lightweight :)
Attach event to document's body ($(body)). Also attach another event to #the_menu that's block event propagation:
$(document.body).click(function() {
//close menu if opened
});
$("#the_menu").click(function(e) {
//code heere
e.stopPropagation();
});
How about binding the menu display to hovering over the element in which it is contained?
$("#parentId").hover(
function() { //!! on hovering in
$("#targetId").attr("display","block") ;
} ,
function() { //!! on hovering out
$("#targetId").attr("display","none") ;
}
) ;
If it fits your goal, this seems easier to maintain.