Keep Bootstrap Dropdown Open When Clicked Off

85,489

Solution 1

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>

Solution 2

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>

Solution 3

$('.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='http://stackoverflow.com/q/19740121/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>

Solution 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>

Solution 5

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.

Share:
85,489
kleban
Author by

kleban

Updated on May 21, 2020

Comments

  • kleban
    kleban almost 4 years

    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?

  • Andresch Serj
    Andresch Serj about 10 years
    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! +1
  • VarunC
    VarunC almost 10 years
    Can you also port this solution for Bootstrap 2.x please? :-) .. I tried but not able to make it work.
  • KyleMit
    KyleMit almost 10 years
    @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.
  • VarunC
    VarunC almost 10 years
    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?
  • onetwopunch
    onetwopunch over 9 years
    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?
  • KyleMit
    KyleMit over 9 years
    @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.
  • Shaiju T
    Shaiju T about 8 years
    here is another solution to check, hope helps someone.
  • KyleMit
    KyleMit about 8 years
    @stom, that's pretty much the same solution.
  • Ben
    Ben about 8 years
    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); }
  • Tisha
    Tisha almost 8 years
    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.
  • KyleMit
    KyleMit almost 8 years
    @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 jsFiddle
  • Shaiju T
    Shaiju T over 7 years
    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.
  • KyleMit
    KyleMit about 7 years
    @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.
  • user1735921
    user1735921 about 7 years
    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.
  • MONTS_MIND_Hacker
    MONTS_MIND_Hacker over 6 years
    Thanks Its really Helped me a lot !!
  • justinw
    justinw about 6 years
    this works but it has a slight lag in displaying the dropdown menu (bootstrap 4).
  • HunterTheGatherer
    HunterTheGatherer over 5 years
    Just implemented this solution, works on the original jsfiddle and in my own code.
  • synkro
    synkro over 3 years
    Exactly what I needed. Btw you're missing a closing </div>