Keep Bootstrap Dropdown Open When Clicked Off
Asked Answered
A

9

39

If the dropdown is visible, and I click outside the dropdown it closes. I need it to not close.

From the documentation:

When opened, the plugin also adds .dropdown-backdrop as a click area for closing dropdown menus when clicking outside the menu.

What JavaScript can I add to prevent the drop down from closing?

Abhorrence answered 2/11, 2013 at 8:9 Comment(0)
G
104

From the events section of the Bootstrap dropdown documentation:

hide.bs.dropdown: This event is fired immediately when the hide instance method has been called.

For starters, to prevent the dropdown from closing, we can just listen to this event and stop it from proceeding by returning false:

$('#myDropdown').on('hide.bs.dropdown', function () {
    return false;
});

For a complete solution, you probably want to allow it to close when the dropdown itself is clicked. So only some of the time we'll want to prevent the box from closing.

To do this we'll set .data() flags in two more events raised by the dropdown:

  • shown.bs.dropdown - When shown, we'll set .data('closable') to false
  • click - When clicked, we'll set .data('closable') to true

Thus, if the hide.bs.dropdown event was raised by a click on the dropdown, we'll allow a close.

Live Demo in jsFiddle

JavaScript

$('.dropdown.keep-open').on({
    "shown.bs.dropdown": function() { this.closable = false; },
    "click":             function() { this.closable = true; },
    "hide.bs.dropdown":  function() { return this.closable; }
});

HTML (note I've added the class keep-open to the dropdown)

<div class="dropdown keep-open">
    <!-- Dropdown Button -->
    <button id="dLabel" role="button" href="#" class="btn btn-primary"
            data-toggle="dropdown" data-target="#" >
        Dropdown <span class="caret"></span>
    </button>

    <!-- Dropdown Menu -->
    <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>
Gorlovka answered 5/11, 2013 at 19:48 Comment(15)
Found so many answers to that question but this one is by far the best and saved me quite some time. Thank you very much! +1Merwin
Can you also port this solution for Bootstrap 2.x please? :-) .. I tried but not able to make it work.Kiehl
@VarunChaddha, You should ask another question and tag it with 2.x and link back to this one so you can show your work so far.Gorlovka
thnx for your reply @KyleMit. Actually I am able to get this resolved using following code: $j('.cal-options-dropdown .dropdown-menu').on({ "click":function(e){ e.stopPropagation(); } }); ... I don't know if I should open new question and answer it myself on that with this answer?Kiehl
I tried your jsfiddle and it doesn't seem to work. I click any of the options in the dropdown and it closes. I've tried this fix and the stopPropogation fix and none seem to keep the dropdown from closing. Any suggestions?Ingressive
@jryancanty, that's precisely what it's supposed to do! If you want it to always stay open, then use the first solution in my post. I added to that saying that you probably want to allow it to close when the dropdown itself is clicked, so I implemented a more complicated solution to achieve that.Gorlovka
here is another solution to check, hope helps someone.Headreach
@stom, that's pretty much the same solution.Gorlovka
For fellow UX mavericks who have set the dropdown menu to be expanded on page load, and want it to remain open until user clicks the actual menu, this hack may be useful: "hide.bs.dropdown": function() { return (this.closable===true); }Steels
Great answer! What if you want to have the dropdown open the minute the page loads, without user having to click on it and then have it kept open.Racing
@Tisha, you'll want to look at How to open Bootstrap dropdown programmatically. You can chain .find('.dropdown-toggle').dropdown('toggle') after you initialize the listeners to trigger the dropdown from opening. All the other listeners can stay exactly as is. Demo in jsFiddleGorlovka
I am was using multilevel dropdown and I probably want to allow it to close when the dropdown itself is clicked but for some reason second option didnt work for me but this worked, hope helps someone.Headreach
@user1735921, how/when/why/where? That's not a sufficient bug report, even if support was guaranteed over many years. We're all programmers here. Put on your programmer hat and produce a sample, create an minimal reproducible example and explain where it's not working or doing what you think it should do. "it's not working" is hardly ever going to cut it, especially not here.Gorlovka
Hey, I am sorry, I didn't mean to offend, I am trying to find similar solution, but on react. Your code doesn't work on jquery too, you can see the corrections in Mike Kane's answer, that works.Dextrin
Just implemented this solution, works on the original jsfiddle and in my own code.Lupitalupo
C
18

Version changes in some dependency have caused KyleMit's, and most other solutions to no longer work. I dug into a bit further and for some reason a click() is sent when Bootstrap tries and fails hide.bs.dropdown, followed by another call to hide.bs.dropdown. I got around this issue by forcing the closing click() to occur on the button itself, not the entire dropdown menu.

Live Demo in Bootply

JavaScript

$('.keep-open').on({
    "shown.bs.dropdown": function() { $(this).attr('closable', false); },
    //"click":             function() { }, // For some reason a click() is sent when Bootstrap tries and fails hide.bs.dropdown
    "hide.bs.dropdown":  function() { return $(this).attr('closable') == 'true'; }
});

$('.keep-open').children().first().on({
  "click": function() {
    $(this).parent().attr('closable', true );
  }
})

HTML

<h2>Click the dropdown button </h2>
<p>It will stay open unless clicked again to close </p>

<div class="dropdown keep-open">
    <!-- Dropdown Button -->
    <button id="dLabel" role="button" href="#" data-toggle="dropdown" data-target="#" class="btn btn-primary">
        Dropdown <span class="caret"></span>
    </button>
    
    <!-- Dropdown Menu -->
    <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>
Crandale answered 1/8, 2016 at 5:22 Comment(0)
H
4

$('.dropdown.keep-open').on({
    "shown.bs.dropdown": function() { this.closable = true; },
    "click":             function(e) { 
        var target = $(e.target);
        if(target.hasClass("btn-primary")) 
            this.closable = true;
        else 
           this.closable = false; 
    },
    "hide.bs.dropdown":  function() { return this.closable; }
});
body {
    margin: 10px;
}
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<h2>Click the dropdown button </h2>
<p>It will stay open unless clicked again to close </p>

<div class="dropdown keep-open">
    <!-- Dropdown Button -->
    <button id="dLabel" role="button" href="#"
       data-toggle="dropdown" data-target="#" 
       class="btn btn-primary">
        Dropdown <span class="caret"></span>
    </button>
    
    <!-- Dropdown Menu -->
    <ul class="dropdown-menu" role="menu" 
        aria-labelledby="dLabel">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>




<!-- Post Info -->
<div style='position:fixed;bottom:0;left:0;    
            background:lightgray;width:100%;'>
    About this SO Question: <a href='https://mcmap.net/q/162663/-keep-bootstrap-dropdown-open-when-clicked-off/1366033'>Keep dropdown menu open</a><br/>
    Fork This Skeleton Here <a href='http://jsfiddle.net/KyleMit/kcpma/'>Bootrsap 3.0 Skeleton</a><br/>
    Bootstrap Documentation: <a href='http://getbootstrap.com/javascript/#dropdowns'>Dropdowns</a><br/>
<div>
Hanna answered 13/5, 2015 at 8:45 Comment(0)
A
4

I found a solution that requires no new js. Don't use a drop down and use bootstrap collapse instead. I still use some dropdown classes to style it like a dropdown.

<div class="dropdown">
    <button class="dropdown-toggle" type="button" data-toggle="collapse" data-target="#myList">Drop Down
    <span class="caret"></span></button>
    <div id="myList" class="dropdown-menu">
        <input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
        <input type="checkbox" name="vehicle" value="Car"> I have a car<br></div>
Amitosis answered 24/5, 2017 at 15:21 Comment(3)
Thanks Its really Helped me a lot !!Erewhile
this works but it has a slight lag in displaying the dropdown menu (bootstrap 4).Lounge
Exactly what I needed. Btw you're missing a closing </div>Wane
F
2

I managed to use a combination of KyleMitt's solution above and ran into issues when using this within a Footable object (I believe this is due to the dynamic creation of the table). I applied .keep-open to the .dropdown .div at the top level.

$('#contact_table').on("click", '.keep-open', function () {
    this.closable = false;
});

$('#contact_table').on("shown.bs.dropdown", '.keep-open', function () {
    this.closable = true;
});
$('#contact_table').on("hide.bs.dropdown", '.keep-open', function () {
    let ret = this.closable;
    this.closable = true;
    return ret;
});

The functionality of this code allows you to click outside to close the dropdown, but clicking on items within it would maintain it being open. Please let me know if you have any suggestions/comments on this and I will attempt to edit.

Fudge answered 4/2, 2018 at 18:55 Comment(0)
A
1

Mike Kane's solution worked most of the time, but there was a case where the hide.bs.dropdown event was firing before the click() event which caused the dropdown to not close when it should have.

I have come up with with another method that checks the clickEvent object in the event. My original plan was to go up the DOM and check that the clickEvent target was or was not a child of the dropdown, but found that if you click inside the dropdown clickEvent is undefined, and if you click outside of it the event is an object.

So it's just a simple check on whether the clickEvent exists as an object.

$('.dropdown.keep-open').on({
    "hide.bs.dropdown":  function(e) {
        return (typeof(e.clickEvent) != 'object');
    }
});
Adelladella answered 18/11, 2019 at 22:53 Comment(0)
H
0

Other solution for this. Keep dropdown open after clicking inside .dropdown-menu:

$('.heading .options .dropdown').on({
    "shown.bs.dropdown":function(){this.closable = true;},
    "click":            function(e){
        var target = $(e.target);
        var d = target.data();
        if(typeof d.toggle != 'undefined' && d.toggle == 'dropdown')
            this.closable = true;
        else {
            var p = target.parent();
            var dd = p.data();
            if(typeof dd.toggle != 'undefined' && dd.toggle == 'dropdown')
                this.closable = true;
            else {
                if(target.hasClass('dropdown-menu'))
                    this.closable = false;
                else {
                    var pp = target.parent('.dropdown-menu');
                    if(typeof pp != 'undefined')
                        this.closable = false;
                    else
                        this.closable = true;
                }
            }
        }
    },
    "hide.bs.dropdown": function(){return this.closable;}
});
Hitandmiss answered 23/9, 2015 at 10:54 Comment(0)
C
0

Keep dropdown open after clicking inside .dropdown-menu

  $(document.body).on({
    "shown.bs.dropdown": function(){ this.closable = true; },
    "hide.bs.dropdown": function(){ return this.closable; },
    "click": function(e){ this.closable = !$(e.target).closest(".dropdown-menu").length; },
  },".dropdown.keepopen");
Commissure answered 25/1, 2016 at 16:39 Comment(0)
O
0
$('.dropdown.keep-open').on({
    "shown.bs.dropdown": function(){ 
        this.closable = true; 
    },
    "hide.bs.dropdown": function(e){ 
        if(!this.closable){
            this.closable = true;
            return false;
        }
        return this.closable; 
    },
    "click": function(e){ 
        this.closable = false;
    }
});
Occasional answered 20/5, 2020 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.