Bootstrap - dropdown menu close on click in Datepicker - javascript

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>

Related

Close dropdown menu when clicking outside of it

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');
}
});

Bootstrap dropdown-menu doesn't get close when clicking an element

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

Making a drop-down menu keyboard and mouse browsable

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');
}

Bootstrap dropdown checkbox select

I'm trying to customize a bootstrap dropdown with checkboxes and if I select a checkbox from dropdown the label name I want to be written on input dropdown delimited with ';' like in uploaded picture when dropdown is closed.
Here is a fiddle example.
Not the most elegant solution - you will probably want to refine this somewhat, but this might get you started:
$(document).ready(function() {
$("ul.dropdown-menu input[type=checkbox]").each(function() {
$(this).change(function() {
var line = "";
$("ul.dropdown-menu input[type=checkbox]").each(function() {
if($(this).is(":checked")) {
line += $("+ span", this).text() + ";";
}
});
$("input.form-control").val(line);
});
});
});
I know it's a old question but still, you can use this library to do almost (except the exact design you asked) what you want http://davidstutz.github.io/bootstrap-multiselect/#getting-started
The following code works in Bootstrap 4.1 if you add a function to show the menu on hover, but when you click the < li > then your checkboxes becomes unclickable. Anybody having a better solution please provide.
<ul class="dropdown-menu dropdown-menu-form">
<li><label class="checkbox"><input type="checkbox">One</label></li>
<li><label class="checkbox"><input type="checkbox">Two</label></li>
</ul>
And add these JS codes:
// Allow Bootstrap dropdown menus to have forms/checkboxes inside,
// and when clicking on a dropdown item, the menu doesn't disappear.
$(document).on('click', '.dropdown-menu.dropdown-menu-form', function(e) {
e.stopPropagation();
});
UPDATE
The below code is working good but checkboxes events are fired twice so had to choose the onchange event instead of onclick
<ul class="dropdown-menu dropdown-menu-form">
<li><label class="checkbox"><input type="checkbox" onchange="some()">One</label></li>
<li><label class="checkbox"><input type="checkbox" onchange="some()">Two</label></li>
</ul>
and the jquery code as follows:
$(document).on('click', '.dropdown-menu', function (e) {
e.stopPropagation();
});

Prevent default function using only child pseudo selectors

I am using jQuery to dynamically add elements every time a user clicks a link (".add-event"). Also included in this element is a icon to remove the entire element if the user chooses. I want to hide or disable this remove icon if the element is the last left on the page. This is what I have tried so far:
$(document).on('click','.close_box2:only-child',function(){
event.preventDefault();
});
AND
if( $('.event').length===1) {
$('.close_box2').hide()
}
HTML:
<div class="event">
<span class="close_box2"><i class="icon-remove"></i></span>
<span class="add-event">Add Event</span>
</div>
What am I doing wrong!? Thanks
JSFiddle: http://jsfiddle.net/TrueBlueAussie/KPY9r/6/
You just want to check for the "last one" inside the delete handler:
// initial hide of sole close button
$('.close_box2').hide();
// On add, clone the template and show all close buttons
$(document).on('click', '.add-event', function () {
// Create a new event based on the template
$('#events').append($('#template').html());
// Show all close buttons (as we must now have > 1 event)
$('.close_box2').show();
});
$(document).on('click', '.close_box2', function (e) {
$(this).closest('.event').remove();
// Is there only one left?
if ($('.event').length === 1) {
// Hide the close box on the last event
$('.close_box2').hide()
}
});
Notes:
I use a dummy <script> element to hold you HTML template. This is better than cloning an element on the page and much better than inline HTML strings in your code.
The following looks better regarding performance:
$('.close_box2:only-child').on('click', function(event){
event.preventDefault();
});

Categories