I'm firing the bootstrap dropdown menu by using the javascript function dropdown('toggle') as stated in their docs.
Usually dropdowns would hide whenever you click outside them or you select one of their options.
This doesn't happen when firing it through javascript.
In this reproduction you'll see two menus:
One which works as expected as its fired using the "components" trigger
And another one, using the right click, which doesn't work as expected. (it doesn't get closed on click outside or even on element click)
I was able to "manually" get rid of the dropdown menu when clicking outside it by using the following:
$('body').removeClass('open');
But I'm not quite sure why dropdown menus don't work in the same way as when you fire them by the normal procedure.
And having to manually hide them doesn't seem like the best solution...
I got an answer from boostrap issues forum in which they explained how to deal with it:
B. You're missing a <div class="dropdown"> around the <ul class="dropdown-menu">
C. You're missing an element with data-toggle="dropdown" (Not explicitly documented, but followed by all the examples and related to the warning in http://getbootstrap.com/javascript/#callout-dropdowns-data-required )
Here's a reproduction of the solution. (right anywhere click to see the dropdown menu)
HTML markup
<div class="wrapper">
<span data-toggle="dropdown"></span>
<ul class="dropdown-menu" id="menu">
<li>Download file</li>
<li>Upload file</li>
</ul>
</div>
Javascript
//context menu for orders table
$(document).on("contextmenu", "body", function (event) {
//we won't show the default context menu
event.preventDefault();
//showing it close to our cursor
$('#menu').dropdown('toggle').css({
top: (event.pageY) + "px",
left: (event.pageX) + "px"
});
});
Opening in Javascript does not work well with data-toggles. I once used this code to activate the dropdown from Javascript:
$(document).on("contextmenu", "body", function (event) {
//we won't show the default context menu
event.preventDefault();
//showing it close to our cursor
$('#menu').css({
top: (event.pageY) + "px",
left: (event.pageX) + "px"
}).show();
$(document).on('click.contextmenu', function () {
$('#menu').hide();
$(document).off('click.contextmenu');
});
});
I have added a listener on the mouse up to close it without closing it when you click inside, so it closes just when you want or when you click outside it: http://jsfiddle.net/q6po6jzh/1/
$(document).mousedown(function (e) {
var container = $("#menu");
if (!container.is(e.target) && container.has(e.target).length === 0 && container.parent().hasClass('open')) {
container.dropdown('toggle')
container.parent().removeClass('open');
}
});
But if you want to be closed as well when clicked in it I guess #wero answer is probably better.
This will solve your issue. It will close all opened dropdowns.
$('.in,.open').removeClass('in open');
Reference:
https://stackoverflow.com/a/22632931/6488619
Related
I've got a problem with the navigation dropdown on my site that I've almost solved but can't quite fix. I'm worried I may have just made a mess out of my code.
When I introduced a "scroll to anchor tags" function with a preventDefault event, it broke my nav menu. The menu wouldn't close unless you clicked on the menu button again. I've finally got it to close after you click one of the links, but that's now the only way to close it. How do I have it close when clicking on the menu button or anywhere else on the site? I'm sure that bit of jQuery is the culprit, but don't know how to fix it or work around it.
HTML for the menu:
<div class="main-nav navbtn">
<div class="dropdown"><i onclick="myFunction()" class="dropbtn material-icons md-48"></i>
<div id="myDropdown" class="dropdown-content">
Home
About
Services
Work
Testimonials
Contact
Blog
</div>
</div>
</div>
And the related jQuery:
// When the user clicks on the button, toggle between hiding and showing the dropdown content
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
//// Close the dropdown menu if the user clicks outside of it
window.onclick = function (event) {
if (!event.target.matches('.dropbtn')) {
dropdowns.forEach(function (openDropdown) {
dropdown.classList.contains('show') && dropdown.classList.remove('show');
});
}
};
////This is the section I made for it to close after clicking a link
jQuery(document).ready(function ($) {
$('.dropbtn').on('click', function () {
$(".dropdown-content").show();
});
$('.navlink').on('click', function () {
$(".dropdown-content").hide();
});
});
This is the potential problem that's screwing the other functions up.
//Scroll to anchor tags
$(document).on('click', 'a:not(.external)', function (event) {
event.preventDefault();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top
}, 500);
});
var $root = $('html, body');
$('a').click(function () {
$root.animate({
scrollTop: $($.attr(this, 'href')).offset().top
}, 500);
return false;
});
What in the world should I do to fix my menu?
You can take a look at the work-in-progress site at http://idpdx.kreigd.com
Update: I think I've got a lead on where things are getting confused. The function I'm using to add the dropdown functionality requires that the class "show" be added once the .dropbtn element is clicked, and removed when it is clicked again.
So what I really need to do is rework the code so that clicking .dropbtn opens the dropdown, and clicking on anything else, including the nav buttons and the .dropbtn element, will close it.
Update 2: Trying a different method. Ignore that first update.
Try this & let me know
$(document).click(function() {
$(".dropdown-content").hide();
// $(".dropdown-content").removeClass("show");
});
$(".dropdown-content").click(function(e) {
e.stopPropagation(); // if you click on the div itself it will cancel the click event.
});
you can try with something like this
$('body').not("#myDropdown").off('click').on('click',function(){$("#myDropdown").removeClass("show")});
I tried the code in your website but you have written some code on window.click which is causing issue.
#Nikhil's answer got me further but has it's downsides. I came up with the following solution:
$(document).click(function (e) {
var target = $(e.target);
// check the actual element being clicked is not the dropdown trigger itself
if (!target.hasClass('dropdown-trigger') && !target.closest('.dropdown-trigger').length) {
// use the framework to close the dropdown instead of just hiding it: hiding it will require you to click the trigger 2 times to reopen!
$('dropdown-trigger').dropdown('close');
}
});
I guess this is a noob question. I want Bootstrap "navbar-collapse" to close by clicking away or by clicking one of list items. I found this code somewhere and it works.
$(document).on('click',function() {
$('.collapse').collapse('hide');
});
But this code also makes Bootstrap "panel-collapse" elements close by clicking away and of course I don't want this to happen.
How can I specify that I want this code to work only for "navbar-collapse" elements?
Give your navbar collapse elements a new class and assign it inside:
$('.NewClassName').collapse('hide');
Note that you ADD that class to the navbar collapse elements without removing the old class.
Your code is correct.
The above displayed a weird behavior for me where sometimes a scroll bar would appear on the nav. That could be from some fancy css but the below fixed it for me.
$(document).on('click',function(e){
if($('#navbar-collapse').hasClass('in')){
$('.collapse').collapse('hide');
}
})
Also, make sure you have the
<script src="/js/bootstrap.min.js"></script>
in your file.
Check whether you are clicking outside the navbar. Collapse method can be fired expectedly by using our reference to the navbar
$(document).click(function (event) {
var target = $(event.target);
var $navbar = $(".navbar-collapse");
var opened = $navbar.hasClass("in");
if (opened === true && !target.hasClass("navbar-toggle")) {
$navbar.collapse('hide');
}
});
If you are using the bootstrap navbar class, you can simply do:
$('.navbar .collapse').collapse('hide');
This will hide all collapse elements which are children of the navbar class.
I am working with Bootstrap and date picker. I added a datepicker in boostrap dowpdown. When selecting the date the dropdown closes automatically. Refer the image for more info:
Action 1: Click the dropdown button, We see the dropdown list.
Action 2: When clicking on the fiel. I will dynamically add datepicker.
After the action 3: When selecting on the Date. The Dropdown is getting close so The user is back to Action 1.
What i am trying to do is After the user click the Date. The dropdown should not close.
I am using the following code to prevent the click which workes on the table inside the dropdown but not with the date picker.
$(document).on('click', '.dropdown-menu', function(e) {
if ($(this).hasClass('keep-open-on-click')) { e.stopPropagation(); }
});
Can some one help me to prevent the dropdown close.
<div class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true"><span class="icon16 icomoon-icon-bell"></span><span class="notification" id="notification_count">11</span>
</a>
<ul class="dropdown-menu keep-open-on-click">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</div>
Note: The datepicker will be added dynamically when the user clicks on the table to end it the date. So is that the problem?
This one was very troublesome. I also have a couple of datepickers located within some Bootstrap drop-down menus. I solved this using two ways.
The first uses jQuery to stop the event from bubbling up one time when the DatePicker is clicked
$('.yourDatePicker').on('hide', function(event) {
event.stopPropagation();
$(this).closest('.yourDropDown').one('hide.bs.dropdown', function(ev) {
return false;
});
});
The other, more permant solution was to change the datepicker.js file itself. If you crack it open you will find code that looks like this
click: function(e){
e.preventDefault();
var target = $(e.target).closest('span, td, th'),
year, month, day;
if (target.length === 1){
switch (target[0].nodeName.toLowerCase()){
...ect...
If you add a e.stopPropagation() function to this area, like this
click: function(e){
e.preventDefault();
e.stopPropagation(); // <-- add this
var target = $(e.target).closest('span, td, th'),
year, month, day;
if (target.length === 1){
switch (target[0].nodeName.toLowerCase()){
your datepickers will stop interfering with your other DOM elements, though this solution is more widespread, and I would test to make sure it doesn't impact other areas in your code.
Try this code,
$(document).on('click', '.dropdown-menu', function(e) {
if ($(this).hasClass('keep-open-on-click')) {
e.hide();
}
});
Your code should work BUT
$(document).on('click', '.dropdown-menu', function(e) {
if ($(this).hasClass('keep-open-on-click')) { e.stopPropagation(); }
});
This is looking for the class('keep-open-on') on the datepicker, not the dropdown. You need to find it in the parent I believe.
$(document).on('click', '.datepicker', function(e) {
if ($(this).parents().find('keep-open-on-click')) { e.stopPropagation(); }
});
Should work.
If I understand your question correctly, you are trying to capture the change event of the datepicker selection and prevent the default actions from finishing. Try this:
$('#your-datepicker-input').datepicker({
}).on('change', function(e) {
console.log("changed");
e.preventDefault();
});
Example here: https://jsfiddle.net/shanabus/a5f82nsy/
Update 1
Without your code for an example, I'm guessing its something like this: https://jsfiddle.net/shanabus/oghgwa5j/1/ - here we have a dropdown with a datepicker inside of it. When I add code so that clicking that table cell turns it into an input with a datepicker, it hijacks the functionality of the dropdown - probably because its a dropdown within a dropdown.
Perhaps you will need a better UI design to handle this type of scenario. A datepicker dropdown inside of a table, inside of an accordion panel, inside of a dropdown might be as tricky to use as it is to code.
Update 2
Here is a great answer on how to better control the dropdown in basic use cases: https://stackoverflow.com/a/19797577/88732
I could not able to solve this issue so I changed my solution from drop-down to Modal.
<div class="dropdown">
<a href="#" data-toggle="modal" data-target="#NModal"><span class="icon16 icomoon-icon-bell"></span><span class="notification" id="notification_count">11</span>
</a>
<div id="NModal" class="modal fade" role="dialog" style="min-width: 650px;">
<div class="modal-dialog">
<!-- My Code -->
</div>
</div>
I am working on a project for a client that requires a custom drop-down menu, accessible by clicking to open it, or using the keyboard to tab across to it.
Currently, my solution works almost perfectly, but there is one problem: the first time you click the drop-down menu, it flashes open and then closes again. I'm sure there's a simple glitch with my JavaScript and jQuery here!
The required functionality is this:
The user must be able to click to open a drop-down menu. (DONE, but with problems)
The user must be able to click another menu, and have the previous one close and the new one open. (DONE)
The user must be able to click anywhere else on the page and have the open menu close. (DONE)
The user must be able to tab along the menu bar, highlighting each link, and opening the menu when it is tabbed to. (DONE)
The tabbing must then tab down the entire menu, before leaving onto the next menu or link, closing the previous menu. (DONE)
As I say here, I have it almost entirely working, but the keyboard focus recognition also detects mouse focusing, meaning that when I click, it triggers a keyboard focus instantly after the mouse one, closing it again.
Or so I think. Please help!
JavaScript Code
$(document).ready(function() {
function toggle(select) {
closeAll(select);
if(select.hasClass("expanded")) {
select.removeClass("expanded");
} else {
select.addClass("expanded");
}
}
function closeAll(select) {
var close = $(document).find("#navigation li.select.expanded");
if(select != null) {
close = close.not(select);
}
close.removeClass("expanded")
}
$("#navigation > ul > li.select > a").click(function(event) {
event.preventDefault();
toggle($(this).parent());
});
$(document).mouseup(function(event) {
var select = $("#navigation > ul > li.select.expanded");
if(!select.is(event.target) && select.has(event.target).length === 0) {
closeAll();
}
});
$(document).on("focus", "#navigation > ul > li > a", function () {
closeAll();
if($(this).parent().hasClass("select")) {
toggle($(this).parent());
}
});
});
HTML Code
<div id="navigation">
<ul>
<li><i class="fa fa-home"></i> Home</li>
<li class="select">
<i class="fa fa-users"></i> Find a Society
<ul>
<li>Scotland</li>
<li>North West</li>
<li>North East</li>
<li>Midlands</li>
<li>Eastern Counties</li>
<li>Central Counties</li>
<li>Wales</li>
<li>South West Counties</li>
<li>Southern Counties</li>
<li>South East Counties</li>
<li>Greater London</li>
</ul>
</li>
</ul>
</div>
The current design
I recently had to create a similar dropdown with some complex features like typeahead list filtering and fixed this issue along the way.
The trick is to only have one entry point into your dropdown menu, every other method has to call this same event. In your case it's the tab focus, so you want to trigger this on click:
EDIT: Fix Open/Close as per OP comment
$("#navigation > ul > li.select > a").click(function(event) {
event.preventDefault();
if($(this).hasClass('expanded')){
closeAll()
}
else {
$(this).focus(); #Here the magic happens :)
}
});
Now the click event triggers a tab focus event which then toggles the visibility of your dropdown.
Closing the dropdown when clicking outside can be simplified with event delegation and the css :not() selector. This should also be slightly faster than your current implementation, though the length of the css selector probably means not by much.
$(document).on('mouseup',':not(#navigation > ul > li.select.expanded)',(function(event) {
closeAll();
});
By the way, your toggle function can be simplified using Jquery's toggleClass
function toggle(select) {
closeAll(select);
select.toggleClass('expanded');
}
I have a standard bootstrap 3 accordion panel with a dynamic number of panels. I need to display another div with information specific to the panel that is open. I have trapped the open event and tried to identify the calling panel with the following code:
$(document).on('click', "#accordion_a", function(){
$('#accordion_a').on('shown.bs.collapse', function (e) {
alert('Calling #' + e.currentTarget.id);
})
})
However it just returns the parent panel set "#accordion_a." (and for some reason fires multiple times) So how can I identify which panel is open?
there are some issue in your javascript, I would suggest to use the
$(function() {});
instead of
$(document).on('click', "#accordion_a", function(){});
And then the event shown.bs.collapse must be triggered on the "collapse" block not on a link.
Please check this demo : http://jsfiddle.net/V8h9a/
And let me know if it solves your issue.