I want to add slidetoggle only when screen size is less than 768px. I also want this to work when user for some reason would resize the window manually.
I have come across a bug with jQuery where my dropdown menu will keep toggling after I resize the window. I've looked up this issue and tried adding return false; to click function and adding position: relative; overflow:hidden; to toggleable div(these should be a workaround according to some forums). No luck there. What causes this bug. I will include the whole function with the click function
//Call function on ready and window resize
$(document).ready(navigationMobile);
$(window).on('resize', navigationMobile);
function navigationMobile() {
const windowWidth = $(window).width();
if (windowWidth < 768) {
//Remove href from main link and add it as a "all" link in menu
$(".js-second-title").each(function () {
const currentHref = $(this).attr('href');
$(this).removeAttr('href');
if ($(this).siblings('ul').find('.js-all-link').length === 0) {
$(this).siblings('ul').prepend(`<li><a class="js-all-link" href="${currentHref}">All</a></li>`);
}
});
//When clicked on main link open menu
$(".js-second-title").click(function () {
$(this).siblings('.js-menu').slideToggle();
$(this).toggleClass('js-open');
});
} else {
//Add href back to main link
$('.js-second-title').each(function () {
if ($(this).attr('href') === undefined) {
const allHref = $(this).siblings('ul').find('.js-all-link').attr('href');
$(this).attr('href', `${allHref}`);
$(this).siblings('ul').find('.js-all-link').remove();
}
});
}
}
Cheers!
I don't exactly know what is causing this bug. But I came up with this workaround.
//Remove href from main link and add it as a "all" link in menu
$(".js-second-title").each(function () {
$(this).addClass('js-closed');
const currentHref = $(this).attr('href');
$(this).removeAttr('href');
if ($(this).siblings('ul').find('.js-all-link').length === 0) {
$(this).siblings('ul').prepend(`<li><a class="js-all-link" href="${currentHref}">All</a></li>`);
}
});
//When clicked on main link open menu
$(document).on("click", '.js-second-title.js-closed', function (e) {
$(this).removeClass('js-closed');
$(this).siblings('.js-menu').slideDown();
$(this).addClass('js-open');
});
$(document).on("click", '.js-second-title.js-open', function (e) {
$(this).siblings('.js-menu').slideUp();
$(this).removeClass('js-open');
$(this).addClass('js-closed');
});
So here I am basically extening SlideToggle function. Before I call slide functions on click I give each js-second-title classes an extra class .js-closed so the browser is aware that the menu is closed. After that I call slideDown function when I click on closed menu title and slideUp when I click on open menu title.
I do not think that this is the best or most sematic solution so I would like to keep this topic open.
How can I edit my code so that the navbar closes when clicked outside of it but remain open if something inside of it is clicked?
$(document).ready(function() {
$('.nav-btn').on('click', function() {
$('.nav-btn').removeClass('active');
$(this).parent().find('.sub-menu').slideToggle();
$(this).toggleClass('active');
});
});
$(document).ready(function () {
$('.nav-btn').on('click', function (e) {
// Stop Document to be clicked when clicked in nav.
e.stopPropagation()
$('.nav-btn').removeClass('active');
var subMenu = $(this).parent().find('.sub-menu')
if (!$(".sub-menu").is(":visible")) {
$(this).parent().find('.sub-menu').slideToggle();
}
$(this).toggleClass('active');
});
// Toggle Sub Menu and remove active when Any vacant place is clicked
$(this).on('click', function (event) {
$('.nav-btn').removeClass('active');
$('.nav-btn').parent().find('.sub-menu').slideToggle();
});
// Prevent View close when Sub Items is clicked
$('.sub-menu').on('click', function (e) {
e.stopPropagation()
})
});
Hi, You just need to prevent the document click when clicked on the nav item and handle some additional things as done in the above code.
You can see Plunker example here also.
$(document).on('click', function (event) {
if ($(event.target).closest('.main-nav').length === 0) {
// Close button code
}
});
Another possible way is by wrapping all the content inside another div (except the header & navbar) and using the onclick tag:
<div onclick="hideNavbar()">
all your content goes here
</div>
function hideNavbar() {
$('.navbar-collapse').collapse('hide');
// getting the navbar div with jQuery
// and calling the function 'hide' of the Bootstrap class 'collapse'
}
I have a series of divs that reveal on link click. When revealed i'm trying to make them close on background click while maintaining their ability to have the different divs replace each other when different links are clicked.
JS fiddle here: http://jsfiddle.net/t593pyg9/3/
$(document).ready(function () {
$('.toggle').hide();
$('a.togglelink').on('click', function (e) {
e.preventDefault();
var elem = $(this).next('.toggle')
$('.toggle').not(elem).hide();
elem.toggle();
});
});
Listen to clicks on the entire document, to prevent this from closing the "popup" after clicking it's link due to event propagation add a return false; to the show click listener.
$('.toggle').hide();
$('a.togglelink').on('click', function (e) {
e.preventDefault();
var elem = $(this).next('.toggle')
$('.toggle').not(elem).hide();
elem.toggle();
return false;
});
$(document).on('click',function(e){
$('.toggle').hide();
});
Fiddle
Update
If you want to prevent the popup from hiding on clicking on it add this:
$('.toggle').on('click', function (e) {
return false;
});
New Fiddle
How can I close an open collapsed navbar on clicking outside of the navbar element? Currently, the only way to open or close it is by clicking on the navbar-toggle button.
See here for an example and code:
So far, I have tried the following which doesn't seem to work:
jQuery(document).click(function() {
});
jQuery('.navbar').click(function(event) {
jQuery(".navbar-collapse").collapse('hide');
event.stopPropagation();
});
Have a look that:
$(document).ready(function () {
$(document).click(function (event) {
var clickover = $(event.target);
var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
if (_opened === true && !clickover.hasClass("navbar-toggle")) {
$("button.navbar-toggle").click();
}
});
});
Your fiddle works with that: http://jsfiddle.net/52VtD/5718/
Its a modified version of this answer, which lacks the animation and is also a tiny bit more complicated.
I know, invoking the click() isn't very elegant, but collapse('hide') did not work for me either, and i think the animation is a bit nicer than adding and removing the classes hardly.
The accepted answer doesn't appear to work correctly. It only needs to check if "navbar-collapse" has the "in" class. We can then fire the collapse method as expected by using our reference to the navbar.
$(document).click(function (event) {
var clickover = $(event.target);
var $navbar = $(".navbar-collapse");
var _opened = $navbar.hasClass("in");
if (_opened === true && !clickover.hasClass("navbar-toggle")) {
$navbar.collapse('hide');
}
});
Using this works for me.
$(function() {
$(document).click(function (event) {
$('.navbar-collapse').collapse('hide');
});
});
The solution I decided to use was taken from the accepted answer here and from this answer
jQuery('body').bind('click', function(e) {
if(jQuery(e.target).closest('.navbar').length == 0) {
// click happened outside of .navbar, so hide
var opened = jQuery('.navbar-collapse').hasClass('collapse in');
if ( opened === true ) {
jQuery('.navbar-collapse').collapse('hide');
}
}
});
This hides an opened collapsed nav menu if the user clicks anywhere outside of the .navbar element. Of course clicking on .navbar-toggle still works to close the menu too.
Converted nozzleman's answer for Bootstrap 4(.3.1):
$(document).ready(function () {
$(document).click(
function (event) {
var target = $(event.target);
var _mobileMenuOpen = $(".navbar-collapse").hasClass("show");
if (_mobileMenuOpen === true && !target.hasClass("navbar-toggler")) {
$("button.navbar-toggler").click();
}
}
);
});
Placed in the ngOnInit().
When the document is loaded, this code waits for click events. If the mobile menu dropdown is open (i.e. the collapsible part of the navbar has the "show" class) and the clicked object (target) is not the mobile menu button (i.e. does not have the "navbar-toggler" class), then we tell the mobile menu button it has been clicked, and the menu closes.
stopPropagation() is not always the best solution. Rather use something like:
jQuery(document.body).on('click', function(ev){
if(jQuery(ev.target).closest('.navbar-collapse').length) return; // Not return false
// Hide navbar
});
I think it's dangerous to assume that you never want to listen to any other event from the .navbar. Which is impossible if you use stopPropagation().
I had a scenario where I had plain text and I didn't want the panel to close if a user clicks on the plain text on accident. The other answers here will close the panel even if you click on the text of an item that isn't a link.
To fix this I added on to Paul Tarr's answer by wrapping the solution in a check to see whether or not the click occurred anywhere inside:
if ($(event.target).parents(".navbar-collapse").length < 1) { }
The full code would become:
$(document).click(function (event) {
if ($(event.target).parents(".navbar-collapse").length < 1) {
var clickover = $(event.target);
var $navbar = $(".navbar-collapse");
var _opened = $navbar.hasClass("in");
if (_opened === true && !clickover.hasClass("navbar-toggle")) {
$navbar.collapse('hide');
}
}
});
In this demo fiddle you can see that if you click on a non-link inside of the panel it won't collapse it.
For latest Bootstrap, this is the correct answer.
$(document).click(function (event) {
var clickover = $(event.target);
var $navbar = $(".navbar-collapse");
var _opened = $navbar.hasClass("show");
if (_opened === true && !clickover.hasClass("navbar-toggler")) {
$navbar.collapse('hide');
}
});
It reads if .navbar-collapse has the word show in classes (which means menu is opened) and hides the navbar when you click/tap anywhere.
I've added a condition to #nozzleman's answer to check if the tap or click has been made on any element within the menu, and if that's the case, not to collapse it.
$(document).ready(function () {
$(document).click(function (event) {
var clickover = $(event.target);
var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
if (_opened === true && !clickover.hasClass("navbar-toggle") && clickover.parents('.navbar-collapse').length == 0) {
$("button.navbar-toggle").click();
}
});
});
The following code works for me and the advantage is that on small screens, it does not hide the .collapse when you click on its nav parent with .navbar .navbar-expand classes:
$(document).click(function (e) {
if($('.collapse').hasClass('show') && !$('nav').is(e.target) && $('nav').has(e.target).length === 0){
$('.navbar-toggler').click()
}
})
Vanilla Javascript.
Working on Bootstrap 5.2.
window.onload = function () {
document.addEventListener("click", function (event) {
// if the clicked element isn't child of the navbar, you must close it if is open
if (!event.target.closest("#navbar_id") && document.getElementById("navbarSupportedContent").classList.contains("show")) {
document.getElementById("hamburger_menu_button").click();
}
});
}
https://jsfiddle.net/j4tgpbxz/
You just need to add an id to the navbar element, and then check if the clicked element is a child of that same navbar and the content you want to hide (dropdown) is being shown.
For Bootstrap 4
Bootstrap 4 doesn't have an in class. This is Coffeescript.
$(document).click (e)->
#console.log e.target
unless $('#toggle-button').has(e.target).length || $('#toggle-menu').has(e.target).length
$('#toggle-menu').collapse('hide')
So basically, unless you click the button or the menu, close the menu.
Note: Strange, on iOS clicking on text doesn't register a click event, nor a mouseup event. Clicking on an image does fire events though.
For Bootstrap 4:
$(document).click(function(event) {
$(event.target).closest(".navbar").length || $(".navbar-collapse.show").length && $(".navbar-collapse.show").collapse("hide")
});
$(document).click(function (event) {
if ($('.navbar-collapse').attr('aria-expanded') == "true") {
$('.navbar-collapse:visible').click();
}
});
$(window).click(function (e) {
if ($(e.target).closest('.codehim-dropdown').length) {
return;
}
if ($(e.target).closest(offCanvas).length) {
return;
}
//check if menu really opened
if ($(hamburger).hasClass("active")) {
closeMenu();
}
$(dimOverlay).fadeOut();
$(".menu-items").slideUp();
$(".dropdown-heading").removeClass("active");
});
I had some problems with some answers here, and I would like to also be able to close the expanded menu on demand. So I did it with a simple function, and simulating the click.
function closeMenu(){
element = document.getElementById('nav_top');
if(element){
if(element.classList.contains('show')){
document.getElementById('navbar_toggler').dispatchEvent(new CustomEvent('click'));
}
}
}
$(document).ready(function () {
$(document).click(function (event) {
closeMenu();
});
});
Using this method you can close it when clicked outside, but also you can call the closeMenu() at any time from any other function.
I know its quite awhile for the answer. But I think the answer here could helps.
Lets say the condition: if user want to close the navbar when click outside but not when user click any element inside of the navbar
use the event.target and target the element's closest classname whether its has the navbar class or not. If yes which means user is clicking element inside of the navbar and not to close the navbar.
$(function() {
$(document).click(function (event) {
var clickover = $(event.target);
var _opened = $(".navbar-collapse").hasClass("navbar-collapse collapse show");
if (_opened === true && clickover.closest('.navbar').length === 0) {
$(".navbar-collapse").collapse('hide');
}
});
});
So I have your typical button to display the menu on mobile devices. The first code works great. Click the button and the menu opens and closes. The client wants the menu to close if you click on something other than the menu, including the button. Once I add the second code, the menu opens when you click on the button and closes when you click on the "content." But the menu doesn't close when you click on the button again. I've tried changing "toggleClass" to just "addClass" but it's the same issue. The button is not part of the menu so I'm kind of at a loss here. Can anyone help? Need I explain more?
$(document).ready(function(){
$("#mobile-menu-button").click(function () {
$("#mobile-nav").toggleClass("nav-open");
$(".mobile").toggleClass("to-left");
});
});
/* When Mobile Menu open, close by clicking other than menu */
$(document).mouseup(function (e) {
var container = $(".nav-open");
if (!container.is(e.target)
&& container.has(e.target).length === 0) {
container.removeClass("nav-open");
$(".mobile").removeClass("to-left");
}
});
Working Demo : http://jsfiddle.net/TSC5N/1/
Update the JS like this :
$(document).ready(function(){
$("#mobile-menu-button").click(function () {
$("#mobile-nav").toggleClass("nav-open");
$(".mobile").toggleClass("to-left");
});
});
/* When Mobile Menu open, close by clicking other than menu */
$(document).mouseup(function (e) {
var container = $(".nav-open");
var button = $('#mobile-menu-button');
if (!container.is(e.target)
&& container.has(e.target).length === 0 && !button.is(e.target)) {
container.removeClass("nav-open");
$(".mobile").removeClass("to-left");
}
});
The problem was when you click on button, Menu will toggle and nav-open class will be added. But button is considered out side of the menu. So Now when you click again on button mouseup function will remove the class nav-open. But toggle event will fire and again same class will be added. So at the end menu will have nav-open class again.
Whats the fix :
!button.is(e.target) condition will check if the clicked item is button or not.
Use this code. http://jsfiddle.net/5gcSt/
$("#mobile-menu-button").click(function () {
if($("#mobile-nav").hasClass('nav-closed')){
$("#mobile-nav").addClass("nav-open");
$("#mobile-nav").removeClass("nav-closed");
$(".mobile").addClass("to-left");
}
else{
$("#mobile-nav").addClass("nav-closed");
$("#mobile-nav").removeClass("nav-open");
$(".mobile").removeClass("to-left");
}
});
/* When Mobile Menu open, close by clicking other than menu */
$(document).mouseup(function (e) {
var container = $(".nav-open");
var button = $('#mobile-menu-button');
if (!container.is(e.target)
&& container.has(e.target).length === 0) {
container.removeClass("nav-open");
$(".mobile").removeClass("to-left");
}
});