I have a simple button that toggles a menu onclick
If the menu is expanded/visible I hide it when clicking anywhere on the page (a part from the menu itself).
var menuBtn = $(".btn-menu"),
menuContainer = $(".menu"),
menuChildren = $(".menu").find("*");
menuBtn.on("click", function() {
menuContainer.toggle();
});
$(window).mouseup(function(e){
if(!menuContainer.is(e.target) && !menuChildren.is(e.target)){
menuContainer.hide();
}
});
When applying that function on mouseup, my toggle function no longer works. Menu will always stay open if clicking multiple times on the button (whereas it should hide & show).
jsfiddle here
Any idea how I could fix this?
mouseup event was fired before click.
try this
$(window).mouseup(function(e){
if(!menuContainer.is(e.target) && !menuChildren.is(e.target) && !menuBtn.is(e.target)){
menuContainer.hide();
}
});
fiddle js
Related
I have a burger nav. After clicking the burger sidebar nav shows up and hides after clicking once more. I want to make it so I don't have to click the burger button, but I can click somewhere else (main container, etc.) and hide the sidebar.
This is the burger button code:
function navBurger() {
var element = document.querySelector(".navbar");
var burger = document.querySelector(".burger-btn");
element.classList.toggle("extended");
burger.classList.toggle("open");
}
This part works just fine, but when I add this:
window.onclick = function() {
var element = document.querySelector(".navbar");
var burger = document.querySelector(".burger-btn");
if (element.classList.contains("extended")) {
window.onclick = function() {
element.classList.remove("extended");
burger.classList.remove("open");
}
}
}
Navigation will hide after the first click, but I am not able to show and then hide it after that first click. It's like the script thinks that navigation still has that class (but it was removed) and won't let the navbar be opened.
Is there a way to solve this?
In your original code, after clicking the first time to open the nav, the window onclick would then remove the classes added by clicking on the menu button as the event bubbled up. To fix this, add event.stopPropagation() to your menu click handler.
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
I also removed the re-bind of the onclick handler, as it was causing the first click to not close the menu properly.
function navBurger(e) {
console.log('button clicked')
var element = document.querySelector(".navbar");
var burger = document.querySelector(".burger-btn");
element.classList.toggle("extended");
burger.classList.toggle("open");
// Prevents the window onclick from firing after this function runs
// try commenting this out
e.stopPropagation();
}
window.onclick = function() {
console.log('onclick triggered');
var element = document.querySelector(".navbar");
var burger = document.querySelector(".burger-btn");
if (element.classList.contains("extended")) {
element.classList.remove("extended");
burger.classList.remove("open");
}
}
document.querySelector(".burger-btn").addEventListener("click", navBurger);
.navbar.extended {
background: green;
}
.burger-btn.open::after {
content: "Open";
display: inline;
}
<nav class="navbar"><button class="burger-btn" type="button">Nav</button></nav>
The cause of the problem is that the global click handler replaces itself with a nested, unconditional function to turn off the burger menu. A second click will open the menu but bubble up to the window handler and turn it off again.
The global handler needs to determine if the click is inside or outside the extended menu before turning it off. Applying the closest method to the click event target can help with this.
window.onload = function() {
var element = document.querySelector(".navbar");
var burger = document.querySelector(".burger-btn");
window.onclick = function(event) {
if( burger.classList.contains("open")
&& !event.target.closest(".extended") ) {
// the click is outside an open extended element
element.classList.remove("extended");
burger.classList.remove("open");
}
};
};
The above should close the burger menu if the user clicks outside the element with class "extended". JQuery documentation covers the jQuery closest method and event.target if you wish to write the code in jQuery.
Note setting window.onclick is set in window.onload to avoid confusion, and that using oneventname properties of elements is better replaced by using addEventListener calls in JavaScript.
I have this code for toggling menus on my site. It will open a menu on click, close others open when you click another and close them all if you click outside.
The issue is, I'm now using this for my search bar to appear too, but if you click inside the search box it vanishes - woops. Would it be possible to amend the hiding code to detect if the user wasn't clicking inside a specific area of the code?
// navbar toggle menu
$(document).on('click', ".toggle-nav > a", function(event) {
event.preventDefault();
event.stopPropagation();
var $toggle = $(this).closest('.toggle-nav').children('.toggle-content');
if ($toggle.hasClass('toggle-active'))
{
$($toggle).removeClass('toggle-active');
}
else
{
$(".toggle-content").removeClass('toggle-active');
$($toggle).addClass('toggle-active');
}
});
// hide the toggle-nav if you click outside of it
$(document).on("click", function ()
{
$(".toggle-content").removeClass('toggle-active');
});
Instead of using click, this uses mouseup. If the target is, for example #search-bar, it won't remove toggle-active from toggle-content elements.
$(document).mouseup(function(e) {
if (!$(e.target).is('#search-bar')) {
$(".toggle-content").removeClass('toggle-active');
}
});
You can see it in action with this jsFiddle.
Hopefully this helps.
I am developing my first firefox extension so I created a menu-button element and menu items.
Exactly like the FireBug button, I would like an event to be triggered when clicking on the main button, but also when clicking on a menu item. The problem is that when I click on the arrow next to the main button to display the menu items the main event is triggered. So my question is:
How do I differentiate the main button (the menu-button) and the arrow displaying the menu?
Here is my code generating the button:
function addToolbarButton() {
var document = mediator.getMostRecentWindow('navigator:browser').document;
var navBar = document.getElementById('nav-bar');
if (!navBar) {
return;
};
//main button
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', 'reportButton');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', data.url('img/BookmarkKitchen.png'));
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', 'Report');
btn.addEventListener('click', function() {
console.log("this=" + this.id);
event.stopPropagation();
}
, false);
//menu popup
var menupopup = document.createElement('menupopup');
menupopup.setAttribute('id', 'menupopup');
menupopup.addEventListener('click', function(event) {
console.log("this=" + this.id);
event.stopPropagation();
}
, false);
//menu items
var menuitem1 = document.createElement('menuitem');
menuitem1.setAttribute('id', 'menuitem1');
menuitem1.setAttribute('label', 'Test1');
menuitem1.setAttribute('class', 'menuitem-iconic');
menuitem1.addEventListener('click', function(event) {
console.log("this=" + this.id);
event.stopPropagation();
}
, false);
menupopup.appendChild(menuitem1);
btn.appendChild(menupopup);
navBar.appendChild(btn);
}
When I click on the main button, the console will write "this=reportButton". This is normal but when I click on the arrow next to the main button, the console will also write "this=reportButton". That means if I want to access the menu, the main event will be triggered. The only way I found to prevent this, is to press the button on the arrow, wait for the menu to show up and release it on a menu Item. This is not very user friendly and Firebug doesn't have this problem...
I hope I was clear enough. Thanks for answering this :)
Don't use the click event - in XUL it really means a mouse click. So if the user triggers a button by other means (e.g. keyboard), the click event will not be triggered. You should use the command event instead - and it has the additional advantage that it won't fire if the dropdown arrow is clicked.
I have a sliding JS menu that opens when you click the noty_menu link, then closes when you click that link again. Is there a way to set it so that the menu closes when you click ANYWHERE on the page?
Here's the relevant code:
$('.noty_menu').click(function () {
$('ul.the_menu').slideToggle('medium');
});
You could catch a click on the body:
$('body').click(function() {
/* close menu */
});
But then in your menu click you have to prevent propagation of the click up to body. Otherwise the menu will open, the click will propagate up, and the menu will immediately close. return false; should suffice here:
$('.noty_menu').click(function () {
$('ul.the_menu').slideToggle('medium');
return false;
});
(You could also read in the event argument to the handler function like function(ev) { ... } and call ev.stopPropagation()).
You may also want to prevent clicks inside the menu from closing it:
$('ul.the_menu').click(function () {
return false;
});
Note that this solution comes with a caveat that any other click event that stops propagation will also prevent the menu close.
u can use
$('body').click(function(){
//ur code
});
to do this
You can check the entire document, however that includes clicks on the menu (if you have any spacing, this could annoy the user) by something like this:
var menu=$('ul.the_menu');
$(document).on('click',function(){
if(menu.height>0) {
menu.slideToggle('medium');
}
});
I have a div which opens when I click a menu button, I am trying to close it if the user clicks anywhere after it is open. The issue I am having is that with my code the show div and the close div when a user clicks I guess are firing at the same time for some reason. The code for the click event is below. How can I make it so they do not fire at the same time and when I open the div that does not fire the click function. Thanks!
//if user clicks and menu is open then hide menu div
$(document).click(function() {
if($("menu").hasClass("menu_closed") == false ) {
//will hide the menu div
closeMenu();
}
}
I think what you want actually is to stop propagation in the other click handler, something like:
$("your_menu_selector").bind("click", function(e){
//your code to open the menu
e.stopPropagation();
return false;
})
You might want to consider adding the event handler to close the menu in the handler that opens the menu. Have it execute only once using the one method. In the handler that opens the menu, simply check to see if it is open already and do a no-op if it is.
$('.openButton').click( function() {
var $menu = $('#menu').
if ($menu.hasClass('menu_closed')) {
$menu.removeClass('menu_closed').addClass('menu_open');
$(document).one( function() {
$menu.removeClass('menu_open').addClass('menu_closed');
});
}
});