I have a function that when a user clicks outside of the mobile navigation close the mobile menu. I don't think I've got the code just right as when I click the mobile menu it opens and closes straight away.
What I want to happen is when the user clicks outside of the nav slideToggle the menu back.
Current code is:
// Responsive menu
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideToggle('slow');
});
// Close out the menu on click outside
window.addEventListener('mouseup', function(event) {
var box = document.getElementById('nav');
if(event.target != box && event.target.parentNode != box) {
$('nav').slideToggle('slow');
}
});
I think it's somewhere to do with mouseup however I don't see a mouseclick in the available parameters.
Thanks
I can give you a cleaner approach to this.
The window's listener should only be bound after the menu is expanded. When it's collapsed, the listener should be removed. This will prevent a lot of hassle and possible bug due to asynchronous execution of 2 event listeners.
With that in mind:
// First we define a callback function to be called after the nav complete showing, which will close the nav when a user tap outside.
var bindEventListener = function(event) {
var box = document.getElementById('nav');
if(event.target != box && event.target.parentNode != box) {
$('nav').slideUp('slow', function(){
// remove the window's event listener after the nav is closed
window.removeEventListener('mouseup', bindEventListener);
});
}
});
// Now we set the button's onclick event and bind the above defined callback for mouseup event.
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideDown('slow', function(){
window.addEventListener('mouseup', bindEventListener);
});
});
The target of the click event is not necessarily the nav or it's first level child, so if there is a click event on the nav you will slide it open and then slide it close.
You need to check if the nav contains the target element or equals to it, so inside the event listener, change your condition to this:
if(!(event.target == box || $.contains(box, event.target))) {
...
The problem is that when you mousedown on .mobile-menu it shows the nav, then when you mouseup on anything outside the nav, including .mobile-menu, it hides the nav again. You should check that the click event's target also isn't .mobile-menu. Try the following code:
// Responsive menu
$('.mobile-menu').click(function(e) {
e.preventDefault();
$('nav').slideToggle('slow');
});
// Close out the menu on click outside
$(window).on('mouseup', function(event) {
if(!$(event.target).is("nav") && $.contains(event.target, $("nav")) && !$(event.target).is('.mobile-menu')) {
$('nav').slideToggle('slow');
}
});
Related
I have a menu that needs to obey the following behavior:
Open with an external button press
Close when there is a click outside it's boundaries
The problem is, that the button to open is also outside the boundaries of the menu and so currently, the button press is opening the editor menu, and then the click listener is immediately closing it again. I've tried using variables and element data so that the click listener only activates if the menu is already open, but the event listener is slower than the button click and so the menu has already been expanded (as far as the listener knows) by the time it is activated. I know I can solve this using timeout so the data isn't changed to "expanded = true" until after the click listener has activated, but this seems kind of clunky and I'm wondering if there is a better option.
Here is a code snippet to demonstrate the problem.
And the js code that accompanies it:
document.addEventListener("click", (event) => {
if (!document.getElementById("menu").contains(event.target) && document.getElementById("menu").dataset.open) {
closeMenu();
}
});
//Expand menu
function openMenu() {
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
//Collapse menu
function closeMenu() {
document.getElementById("menu").dataset.open = false;
document.getElementById("menu").style.height = "0";
console.log("close");
}
Thanks for your help!
You can have the button prevent its parent element from registering the click by taking the event parameter in openMenu, and calling the stopPropogation method on it.
function openMenu(e) {
e.stopPropogation()
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
How do I prevent a parent's onclick event from firing when a child anchor is clicked?
Thanks for the answers! Here's my solution based on #Addison Schmidt's answer that fixes a couple of errors:
function openMenu(e) {
if (!event) var e = window.event
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
document.getElementById("menu").dataset.open = true;
document.getElementById("menu").style.height = "80vh";
console.log("open");
}
Source: Event.stopPropagation Not Working
I click on the button in red rectangle to show the windows. Now, if want want to close the windows, i just click on other part of the grey bar. What I want to do is to modify the code to click the button in red rectangle 2nd time to close the windows, but it does not work.
I have put the html and related files here.
The main html is chat.html, where the main javascript lies in
assets\plugins\emojiarea\jquery.emojiarea.js
Following is portion of the code:
EmojiMenu.prototype.hide = function(callback) {
if (this.emojiarea) {
this.emojiarea.menu = null;
this.emojiarea.$button.removeClass('on');
this.emojiarea = null;
}
this.visible = false;
this.$menu.hide();
};
EmojiMenu.prototype.show = function(emojiarea) {
if (this.emojiarea && this.emojiarea === emojiarea) return;
this.emojiarea = emojiarea;
this.emojiarea.menu = this;
this.reposition();
this.$menu.show();
this.visible = true;
};
I try to use this.visible to detect the whether the windows has been opened, if yes, then close it, but it does not work out. Is there a possibility to make the windows closed when I click the button in red rectangle 2nd time?
So I went through the plugin. This piece of code:
$body.on('mouseup', function() {
self.hide();
});
is why you couldn't use this.visible to check if it was already open or not,because every time you click on the button too this mouseup is triggered effectively hiding and then showing the popup.
Right after this:$button.on('click', function(e) {
EmojiMenu.show(self);
e.stopPropagation();
});Add this:$button.on('mouseup', function(e) {
e.stopPropagation();
});This will prevent the bubbling of the mouseup event from the button itself.Now you can use "this.visible to detect the whether the windows has been opened, if yes, then close it."
Im trying to hide my dropdown menu when the user clicks outside of its open state, Im using a flag isActive that determines whether or not the menu is open and then I have added a click event on the document to hide the menu if open and stop propogation on the menu if it is clicked. Right now however when I click my dropdown anchor tag the document click event is fired. Can anyone advise how I fix this?
JS
//User profile share tooltip
$('.btn-social-share').on('click', function(e){
e.preventDefault();
if( !isActive ){
$('.social-share-options').show();
isActive = true;
} else {
$('.social-share-options').hide();
isActive = false;
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).on('click', function(){
if( isActive ){
$('.social-share-options').hide();
isActive = false;
}
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$('.social-share-options').click(function(e){
e.stopPropagation();
});
Make a condition that checks if whatever was clicked is within the dropdown or not, and then hide the dropdown if whatever was clicked is not within the dropdown :
$(document).on('click', function(e){
if( isActive && $(e.target).closest('.social-share-options').length === 0 ){
$('.social-share-options').removeClass('is-active');
isActive = false;
}
});
I haven't tested it but I think you need to add e.stopPropagation(), that will prevent your event from bubbling up :
$('.btn-social-share').on('click', function(e){
e.preventDefault();
e.stopPropagation();
//...
http://api.jquery.com/event.stopPropagation/
I'm struggling with this javascript at the moment.
$(document).ready(function () {
var visible = false;
var body = false;
$("body").mouseup(function () {
if (visible) {
$(this).parent().find("ul.subnav").slideUp('slow');
visible = false;
$(this).removeClass("clicked-background");
body = true;
}
});
$("ul.topnav li a").click(function () { //When trigger is clicked...
var menu = $(this).parent().find('ul.subnav');
if (!visible && !body) {
$(this).parent().find("ul.subnav").slideDown('fast').show();
visible = true;
$(this).addClass("clicked-background");
}
// else if (visible)
//{
// $(this).parent().find("ul.subnav").slideUp('slow');
// visible = false;
// $(this).removeClass("clicked-background");
// }
body = false;
});
});
I wanted to add the feature, so if you clicked outside the menu/navigation the dropdown would hide.
The current problem with this code is, that if you click the menu and then click outside the menu - you have to double click the menu again to get it showen. This is caused by the body variable is set too 'True' ofc.
I made the body variable trying to fix the problem if you clicked the menu - and then clicked the same link again. The menu would first open correctly, and then close and open again.
Soo main problem is. My navigation open -> closes -> open
Don't use global variables. Check if the actual element is visible by checking
.is(':visible');
You can use that on the various selectors you have now.
I would be tempted to use onmouseout of the 'now visible' menu as the event of choice..
I dont think that running events off of the body tag is the good way to go.
the flow should be..
click (menu button or link)
show menu
set onmouseout for button and menu on click
onmouseout, remove onmouseout events
I am trying to run the following code on IE but not able to get the 'event.which' as '3' / event that alert itself is not coming, when I right click.
$(document).bind('click', function(event) {
alert("event.which = "+event.which);
});
My Base requirement is to bind a click event as above and then if it is a anchor link on which i have clicked then I want to restrict a default options which we usually get on right click like 'Open in new window','BookMark this link' etc.
Thx
If you mean you want to disable right click then:
$(document).ready(function() {
//disable the right mouse click menu
$(document)[0].oncontextmenu = function() {return false;}
});
Did you mean something like that.
Below code should work: (tested in IE 7)
$(document).mousedown(function () {
if (event.button == 2 && event.srcElement.id == 'your element id') {
alert('right click not allowed');
return false;
}
});
if you want to block context menu on anchor element then
This will prevent the context menu from appearing on a particular element
$('a').observe("contextmenu", function(e){
e.stop();
});
So, if you wish to stop all anchor tags from showing a context menu
$('a').each(function(anch){
$(anch).observe("contextmenu", function(e){
e.stop();
});
})
i think you want something different then this but
see if this is your need