Tránh menu thả xuống đóng vào nhấp vào bên trong


310

Tôi có một menu thả xuống Bootstrap Twitter. Như tất cả người dùng Twitter Bootstrap đều biết, menu thả xuống đóng khi nhấp (thậm chí nhấp vào bên trong nó).

Để tránh điều này, tôi có thể dễ dàng đính kèm một trình xử lý sự kiện nhấp chuột trên menu thả xuống và chỉ cần thêm sự nổi tiếng event.stopPropagation().

<ul class="nav navbar-nav">
  <li class="dropdown mega-dropdown">
    <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown">
      <i class="fa fa-list-alt"></i> Menu item 1
      <span class="fa fa-chevron-down pull-right"></span>
    </a>
    <ul class="dropdown-menu mega-dropdown-menu">
      <li>
        <div id="carousel" class="carousel slide" data-ride="carousel">
          <ol class="carousel-indicators">
            <li data-slide-to="0" data-target="#carousel"></li>
            <li class="active" data-slide-to="1" data-target="#carousel"></li>
          </ol>
          <div class="carousel-inner">
            <div class="item">
              <img alt="" class="img-rounded" src="img1.jpg">
            </div>
            <div class="item active">
              <img alt="" class="img-rounded" src="img2.jpg">
            </div>
          </div>
          <a data-slide="prev" role="button" href="#carousel" 
             class="left carousel-control">
            <span class="glyphicon glyphicon-chevron-left"></span>
          </a>
          <a data-slide="next" role="button" href="#carousel" 
             class="right carousel-control">
            <span class="glyphicon glyphicon-chevron-right"></span>
          </a>
        </div>
      </li>
    </ul>
  </li>
</ul>

Điều này có vẻ dễ dàng và là một hành vi rất phổ biến, tuy nhiên, và vì carousel-controls(cũng như carousel indicators) các trình xử lý sự kiện được ủy quyền cho documentđối tượng, clicksự kiện trên các phần tử này ( điều khiển trước / tiếp theo , ...) sẽ bị bỏ qua.

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){
    // The event won't be propagated up to the document NODE and 
    // therefore delegated events won't be fired
    event.stopPropagation();
});

Dựa vào Twitter hide/ hiddensự kiện thả xuống Bootstrap không phải là một giải pháp cho các lý do sau:

  • Đối tượng sự kiện được cung cấp cho cả hai trình xử lý sự kiện không cung cấp tham chiếu đến phần tử được nhấp
  • Tôi không có quyền kiểm soát nội dung trình đơn thả xuống nên việc thêm một flaglớp hoặc thuộc tính là không thể

Fiddle này là hành vi bình thường và fiddle này được event.stopPropagation()thêm vào.

Cập nhật

Cảm ơn Roman cho câu trả lời của mình . Tôi cũng tìm thấy một câu trả lời mà bạn có thể tìm thấy dưới đây .


1. jsfiddle của bạn không hoạt động. 2. Chính xác những gì bạn muốn đạt được?
paulalexandru

1
@paulalexandru, Cập nhật, thêm hai fiddle. Một hành vi mặc định và một hành vi có sửa đổi. Hãy thử nhấp vào nút tiếp theo & trước đó hoặc trên các chỉ báo. Ví dụ đầu tiên, menu ẩn và các slide băng chuyền. hoặc ví dụ thứ hai: Menu vẫn mở, nhưng băng chuyền không trượt vì event propagationđã dừng.
php-dev

@paulalexandru Hiểu chưa?
php-dev

@ php-dev: Tôi đã cập nhật lại vì thách thức, bây giờ nó hoàn hảo ... xem bản demo.
Luca Filosofi

Câu trả lời:


373

Loại bỏ thuộc tính dữ liệu data-toggle="dropdown"và thực hiện mở / đóng của danh sách thả xuống có thể là một giải pháp.

Đầu tiên bằng cách xử lý nhấp vào liên kết để mở / đóng trình đơn thả xuống như thế này:

$('li.dropdown.mega-dropdown a').on('click', function (event) {
    $(this).parent().toggleClass('open');
});

và sau đó lắng nghe các nhấp chuột bên ngoài thả xuống để đóng nó như thế này:

$('body').on('click', function (e) {
    if (!$('li.dropdown.mega-dropdown').is(e.target) 
        && $('li.dropdown.mega-dropdown').has(e.target).length === 0 
        && $('.open').has(e.target).length === 0
    ) {
        $('li.dropdown.mega-dropdown').removeClass('open');
    }
});

Đây là bản demo: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/


2
Giải pháp này đang hoạt động tốt. Tiền thưởng nên được trao cho bạn nếu không có câu trả lời nào khác.
php-dev

1
Giải pháp của bạn đang hoạt động, chung chung và cũng "phổ biến". Tiền thưởng nên được trao cho câu trả lời của bạn. Tôi cũng tìm thấy một câu trả lời, nhìn vào nó bên dưới;)
php-dev

1
@Cichy ... chỉ cần sửa đổi trình xử lý đầu tiên như thế này ... $ ('li.dropdown.mega-dropdown a'). On ('click', function (event) {$ ('li.dropdown.mega-dropdown .open '). removeClass (' open '); $ (this) .parent (). toggleClass (' open ');});
DSaket

63
Câu trả lời ưa thích này là một hack. ồ !!! Dưới đây là câu trả lời BOOTSTRAP 4 ALPHA đơn giản hơn để ngăn chặn nhấp chuột bên trong trong một lần thả xuống lớn. // PREVENT INSIDE CLICK DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
Frank Thoeny

7
e.stopPropagation()là giải pháp tốt nhất.
nacholibre

332

Điều này cũng sẽ giúp

$(document).on('click', 'someyourContainer .dropdown-menu', function (e) {
  e.stopPropagation();
});

33
Tôi nghĩ đó là chắc chắn giải pháp đơn giản nhất cho vấn đề này. Thumbs up - chỉ cần thử nghiệm cái này và nó hoạt động!
Torsten Barthel

13
Đây là giải pháp tốt nhất.
im lặng

3
Đó là giải pháp phổ biến nhất, nhưng tôi có một yêu cầu khác. Vui lòng đọc kỹ câu hỏi của tôi :)
php-dev

4
Giải pháp tốt nhất cho việc giữ menu mở khi nhấp chuột.
Matt Pierce

2
Giải pháp tốt nhất thực sự. Cá nhân tôi đã sử dụng '.dropdown-menu :not(.dropdown-item)'để nhấp vào dropdown-itemkhông đóng cửa sổ bật lên, nhưng nhấp vào dropdown-headerkhông.
Benjamin

41

Bootstrap cung cấp chức năng sau:

                 | Sự kiện này được kích hoạt ngay lập tức khi phương thức ẩn
ẩn.bs.dropdown | đã được gọi. Phần tử neo bật tắt có sẵn như là
                 | tài sản mục tiêu có liên quan của sự kiện.

Do đó, việc thực hiện chức năng này sẽ có thể vô hiệu hóa việc thả xuống từ việc đóng.

$('#myDropdown').on('hide.bs.dropdown', function (e) {
    var target = $(e.target);
    if(target.hasClass("keepopen") || target.parents(".keepopen").length){
        return false; // returning false should stop the dropdown from hiding.
    }else{
        return true;
    }
});

2
@Vartan, Ngoài ra targettài sản sự kiện là li.dropdown, relatedTargeta.dropdown-toggle. Vì vậy, bạn không thể tham chiếu đến phần tử được nhấp trong hidetrình xử lý sự kiện.
php-dev

2
hasClass lấy một tên lớp, không phải là bộ chọn CSS. target.hasClass(".keepopen")nên target.hasClass("keepopen"). Nếu không thì mã sẽ không hoạt động.
Hugh Guiney

3
Tôi đã quét internet và đây là giải pháp thông minh nhất cho đến nay, vì lý do này ... msot các phương pháp khác gọi cho một phương pháp sử dụng dừng sự kiện mặc định hoặc dừng lan truyền. các cách tiếp cận này rất tệ vì chúng sẽ phá vỡ mọi sự kiện được kích hoạt khác bên trong trình đơn thả xuống (tức là các yếu tố hình thức di động kỳ quặc của tôi) bằng cách sử dụng phương pháp này cho phép bạn xác định cụ thể khi chính menu đóng và cho phép bạn thực hiện hành động đó một mình. Câu trả lời này cần rất nhiều sao ....
webfish

3
@webfish Bạn mất bao nhiêu thời gian để quét internet? (rofl)
php-dev

2
Có thể điều này được sử dụng để làm việc .. nhưng với bootstrap 4, e.target luôn là chính phần thả xuống. Không phải mục tiêu được nhấp. Ngay cả khi bạn nhấp vào bên ngoài danh sách thả xuống, e.target vẫn là danh sách thả xuống. Vì vậy, bạn không thể thực hiện loại kiểm tra này. Bất cứ ai cũng thấy một cách xung quanh này?
FredArters

36

Câu trả lời tuyệt đối tốt nhất là đặt thẻ biểu mẫu sau trình đơn thả xuống lớp

vậy mã của bạn là

<ul class="dropdown-menu">
  <form>
    <li>
      <div class="menu-item">bla bla bla</div>
    </li>
  </form>
</ul>

2
chức năng làm việc tuyệt vời cho tôi, nhưng đã phá vỡ phong cách
2778

2
đây là giải pháp nhanh nhất cho tôi
Jonathan Morales Vélez

15
Đây không phải là một câu trả lời hay nhất :) một <li>yếu tố không nên nằm trong một <form> yếu tố.
GETah

2
Đây không phải là một giải pháp đúng ngữ nghĩa - đứa con hợp lệ duy nhất của UL là một LI - nếu bất cứ điều gì các thẻ biểu mẫu phải nằm trong các thẻ li - nhưng điều đó có thể không liên quan đến hành động mong muốn - dù là một ul> form> li thì không đánh dấu đúng
gavgrif

2
Thnaks cho giải pháp nhanh chóng này
Herman Demsong

27

Tôi cũng tìm thấy một giải pháp.

Giả sử rằng các Twitter Bootstrap Componentstrình xử lý sự kiện liên quan được ủy quyền cho documentđối tượng, tôi lặp các trình xử lý đính kèm và kiểm tra xem phần tử được nhấp hiện tại (hoặc một trong các phần tử cha mẹ của nó) có liên quan đến sự kiện được ủy nhiệm không.

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){
    var events = $._data(document, 'events') || {};
    events = events.click || [];
    for(var i = 0; i < events.length; i++) {
        if(events[i].selector) {

            //Check if the clicked element matches the event selector
            if($(event.target).is(events[i].selector)) {
                events[i].handler.call(event.target, event);
            }

            // Check if any of the clicked element parents matches the 
            // delegated event selector (Emulating propagation)
            $(event.target).parents(events[i].selector).each(function(){
                events[i].handler.call(this, event);
            });
        }
    }
    event.stopPropagation(); //Always stop propagation
});

Hy vọng nó sẽ giúp bất cứ ai tìm kiếm một giải pháp tương tự.

Cảm ơn mọi sự giúp đỡ của bạn.


1
Chà !!! làm việc hoàn hảo Đã gặp rắc rối trong một tuần, tôi đang sử dụng mCustomeScrollbar và sau khi nhấp vào thanh cuộn để thả xuống, nó đã hoạt động và kịch bản của bạn đã hoạt động tốt! Cảm ơn rất nhiều.
eirenaios

làm việc tuyệt vời Làm thế nào để mở rộng điều này, để người dùng vẫn có thể nhấn "ESC" (hoặc thậm chí nhấp bên ngoài) trên bàn phím để đóng DD?
Chú Iroh

2
@MaggewDotCom Bấm phím ESC vẫn hoạt động. Tương tự cho việc nhấp bên ngoài ...
php-dev

Nhược điểm duy nhất của giải pháp này là nó không cho phép thả xuống lồng nhau (giả sử bạn có một sự mơ hồ trong một lần thả xuống). Có một cách giải quyết cho trường hợp này?
snksv

26

Điều này có thể giúp:

$("dropdownmenuname").click(function(e){
   e.stopPropagation();
})

Đây chắc chắn là câu trả lời đơn giản / tốt nhất nếu bạn muốn người dùng tương tác với thành phần UI có trong danh sách thả xuống (ví dụ: nút radio) và không muốn menu đóng khi họ chuyển đổi tùy chọn.
Cướp

22
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".open") && e.stopPropagation();
});

Điều này có thể làm việc cho bất kỳ điều kiện.


đây phải là câu trả lời đúng vì nó sử dụng ít dòng mã hơn là câu trả lời được chọn
Muhammad Omer Aslam

@MuhammadOmerAslam Nah! Vì nó không đáp ứng yêu cầu của tôi
php-dev

12

jQuery:

<script>
  $(document).on('click.bs.dropdown.data-api', '.dropdown.keep-inside-clicks-open', function (e) {
    e.stopPropagation();
  });
</script>

HTML:

<div class="dropdown keep-inside-clicks-open">
  <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
     Dropdown Example
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu">
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
  </ul>
</div>

Bản trình diễn :

Chung: https://jsfiddle.net/kerryjohnson/omefq68b/1/

Bản demo của bạn với giải pháp này: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/


9

Tôi đã thử điều đơn giản này và nó hoạt động như một lá bùa.

Tôi đã thay đổi thả xuống menu phần tử từ <div>đến <form>và nó làm việc tốt.

<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
     </li>
     <li class="list-group-item"   >
     </li>
  </ul>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>


<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>


<div class="nav-item dropdown" >
  <a href="javascript:;" class="nav-link dropdown-toggle" data-toggle="dropdown">
   Click to open dropdown
 </a>
 <form class="dropdown-menu   ">
  <ul class="list-group text-black">
     <li class="list-group-item"  >
      List Item 1
     </li>
     <li class="list-group-item"   >
         LI 2<input class="form-control" />
     </li>
     <li class="list-group-item"   >
        List Item 3
     </li>
  </ul>
</form>


6

Gần đây tôi đã gặp một vấn đề tương tự và đã thử nhiều cách khác nhau để giải quyết nó bằng cách loại bỏ thuộc tính dữ liệu data-toggle="dropdown"và lắng nghe clickbằng cách event.stopPropagation()gọi.

Cách thứ hai có vẻ thích hợp hơn. Các nhà phát triển Bootstrap cũng sử dụng cách này. Trong tệp nguồn tôi tìm thấy khởi tạo các phần tử thả xuống:

// APPLY TO STANDARD DROPDOWN ELEMENTS
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
}(jQuery);

Vì vậy, dòng này:

.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })

đề nghị bạn có thể đặt một formphần tử bên trong container với lớp .dropdownđể tránh đóng menu thả xuống.


6

Bootstrap đã tự giải quyết vấn đề này trong sự hỗ trợ của họ cho <form>các thẻ trong danh sách thả xuống. Giải pháp của họ khá dễ nắm bắt và bạn có thể đọc tại đây: https://github.com/twbs/bootstrap/blob/v4-dev/js/src/dropdown.js

Nó nắm rõ để ngăn chặn sự lan truyền ở phần tử tài liệu và chỉ làm như vậy đối với các sự kiện thuộc loại 'click.bs.dropdown.data-api'phù hợp với bộ chọn'.dropdown .your-custom-class-for-keep-open-on-click-elements' .

Hoặc trong mã

$(document).on('click.bs.dropdown.data-api', '.dropdown .keep-open-on-click', (event) => {
    event.stopPropagation();
});

1
Cảm ơn bạn cảm ơn bạn cảm ơn bạn đã liên kết đến nguồn. Đối với những người khác tự hỏi tại sao formcách tiếp cận từ các ví dụ không hiệu quả với bạn - Tôi đã sử dụng lớp dropleft, nhưng nó cũng cần dropdownđể bộ chọn biểu mẫu khớp.
Mark K Cowan

6

Tôi đã sửa đổi câu trả lời của @ Vartan để làm cho nó hoạt động với Bootstrap 4.3. Giải pháp của anh ấy không còn hoạt động nữa với phiên bản mới nhất vì targettài sản luôn trả về gốc của thả xuốngdiv bất kể vị trí nhấp chuột được đặt ở đâu.

Đây là mã:

$('.dropdown-keep-open').on('hide.bs.dropdown', function (e) {
  if (!e.clickEvent) {
    // There is no `clickEvent` property in the `e` object when the `button` (or any other trigger) is clicked. 
    // What we usually want to happen in such situations is to hide the dropdown so we let it hide. 
    return true;
  }

  var target = $(e.clickEvent.target);

  return !(target.hasClass('dropdown-keep-open') || target.parents('.dropdown-keep-open').length);
});
<div class="dropdown dropdown-keep-open">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Dropdown button
  </button>
  <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
    <a class="dropdown-item" href="#">Action</a>
    <a class="dropdown-item" href="#">Another action</a>
    <a class="dropdown-item" href="#">Something else here</a>
  </div>
</div>

trực tuyến:$('.dropdown-keep-open').on('hide.bs.dropdown', ev => !(ev.clickEvent && $(ev.target).has(ev.clickEvent.target).length))
Matveev Dmitriy

@MatveevDmitriy Tôi xin lỗi nhưng không ai, đơn giản là không ai có thể đọc được phần này. Viết mã theo cách này là một thực tế xấu.
ViRuSTriNiTy

Dòng cuối cùng có thể được đơn giản hóa bằng cách sử dụng return !target.closest('.dropdown-keep-open').length). Điều đó nói rằng, đây là một giải pháp tuyệt vời! Tìm thấy điều này cần thiết để giải quyết vấn đề này.
patrick3853

6
$('body').on("click", ".dropdown-menu", function (e) {
    $(this).parent().is(".show") && e.stopPropagation();
});

Đầu tiên, cảm ơn bạn đã trả lời. Câu hỏi đã được trả lời. Ngoài ra, tôi có một yêu cầu khác như được mô tả trong câu hỏi so với yêu cầu chung.
php-dev

4
$('ul.nav.navbar-nav').on('click.bs.dropdown', function(e){
    var $a  = $(e.target), is_a = $a.is('.is_a');
    if($a.hasClass('dropdown-toggle')){   
        $('ul.dropdown-menu', this).toggle(!is_a);
        $a.toggleClass('is_a', !is_a);
    }
}).on('mouseleave', function(){
    $('ul.dropdown-menu',this).hide();
    $('.is_a', this).removeClass('is_a');
});

tôi đã cập nhật nó một lần nữa để trở nên thông minh và hoạt động nhất có thể. Bây giờ nó đóng khi bạn di chuột ra ngoài điều hướng, vẫn mở trong khi bạn ở trong đó. Đơn giản là hoàn hảo.


Giải pháp của bạn rất thông minh do độ ngắn của nó, tuy nhiên, sau khi thêm lớp show, trình đơn thả xuống không đóng khi nhấp vào bên ngoài và chúng tôi cần nhấp vào nút thả xuống trước khi ... +1 dù sao
php-dev

tôi đã cập nhật nó, nhìn vào bản demo đó là lý do tốt nhất không kiểm tra sự kiện nhấp vào cơ thể mọi lúc. chỉ ảnh hưởng đến phần tử bên trong mỗi phần tử điều hướng duy nhất không nằm ngoài nó.
Luca Filosofi

Giải pháp của tôi cũng không dựa bodyvào sự kiện nhấp chuột ^^
php-dev

vâng, nó chuyển tiếp một phần vào sự kiện nhấp vào cơ thể, nó cố gắng kiểm tra xem phần tử nào đã được nhấp để xác định sự ủy nhiệm của cơ thể. $('body').on('click', function (e) {
Luca Filosofi

Không! Đó không phải là câu trả lời của tôi. Câu trả lời của tôi là bài cuối cùng được đăng.
php-dev

4

Ví dụ như Bootstrap 4 Alpha có Menu Event này. Tại sao không sử dụng?

// PREVENT INSIDE MEGA DROPDOWN
$('.dropdown-menu').on("click.bs.dropdown", function (e) {
    e.stopPropagation();
    e.preventDefault();                
});

1
e.preventDefault();chặn các liên kết, bạn có thể bỏ qua nó
dài

@czachor Bạn nói đúng! e.preventDefault (); Ngăn chặn một liên kết theo URL.
Frank Thoeny

3

Bạn có thể dừng nhấp vào thả xuống từ việc truyền bá và sau đó thực hiện lại thủ công các điều khiển băng chuyền bằng các phương pháp javascript băng chuyền .

$('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event) {
    event.stopPropagation();
});

$('a.left').click(function () {
    $('#carousel').carousel('prev');
});

$('a.right').click(function () {
    $('#carousel').carousel('next');
});

$('ol.carousel-indicators li').click(function (event) {
    var index = $(this).data("slide-to");
    $('#carousel').carousel(index);
});

Đây là jsfiddle .


Ví dụ của bạn hoạt động tốt nhưng vấn đề là trình đơn thả xuống có thể chứa bất kỳ nội dung nào và không chỉ hình ảnh băng chuyền ...
php-dev

3

Với Angular2 Bootstrap, bạn có thể sử dụng nonInput cho hầu hết các tình huống:

<div dropdown autoClose="nonInput">

nonInput - (mặc định) sẽ tự động đóng cửa sổ thả xuống khi bất kỳ phần tử nào của nó được nhấp - miễn là phần tử được nhấp không phải là một đầu vào hoặc một vùng văn bản.

https://valor-software.com/ng2-bootstrap/#/dropdowns


2

Tôi biết câu hỏi này dành riêng cho jQuery, nhưng với bất kỳ ai sử dụng AngularJS có vấn đề này, bạn có thể tạo một lệnh xử lý việc này:

angular.module('app').directive('dropdownPreventClose', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
          element.on('click', function(e) {
            e.stopPropagation(); //prevent the default behavior of closing the dropdown-menu
          });
        }
    };
});

Sau đó, chỉ cần thêm thuộc tính dropdown-prevent-closevào thành phần của bạn đang kích hoạt menu để đóng và nó sẽ ngăn chặn nó. Đối với tôi, đó là một selectyếu tố tự động đóng menu:

<div class="dropdown-menu">
  <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel">
    <option value="">Select Me</option>
  </select>
</div>

6
<div class="dropdown-menu" ng-click="$event.stopPropagation()">làm việc cho tôi trong 1.2.x
dr3w

2

[Bootstrap 4 Alpha 6] [Rails] Đối với nhà phát triển đường ray, e.stopPropagation()sẽ dẫn đến hành vi không mong muốn link_todata-methodkhông bằng getvì nó sẽ trả về tất cả yêu cầu của bạn theo mặc định get.

Để khắc phục vấn đề này, tôi đề xuất giải pháp này, đó là phổ quát

$('.dropdown .dropdown-menu').on('click.bs.dropdown', function() {
  return $('.dropdown').one('hide.bs.dropdown', function() {
    return false;
  });
});


2

Thay vì viết một số mã javascript hoặc jquery (phát minh lại bánh xe). Kịch bản trên có thể được quản lý bằng tùy chọn tự động đóng bootstrap. Bạn có thể cung cấp một trong các giá trị để tự động đóng :

  1. luôn luôn - (Mặc định) tự động đóng cửa sổ thả xuống khi bất kỳ yếu tố nào của nó được nhấp.

  2. bên ngoàiClick - chỉ đóng tự động thả xuống khi người dùng nhấp vào bất kỳ yếu tố nào bên ngoài danh sách thả xuống.

  3. bị vô hiệu hóa - vô hiệu hóa tự động đóng

Hãy xem plunkr sau đây:

http://plnkr.co/edit/gnU8M2fqlE0GscUQtCWa?p=preview

Bộ

uib-dropdown auto-close="disabled" 

Hi vọng điêu nay co ich :)


5
Cần lưu ý rõ ràng rằng điều này chỉ tốt cho những người sử dụng ui-bootstrap, có lẽ không phải là trường hợp cho rất nhiều người xem câu hỏi này.
kevlarr

Bạn mô tả tốt nhưng tôi nghĩ bạn nên viết giải pháp như uib-dropdown auto-close="outsideClick". Menu đóng khi nhấp vào bên trong chỉ là một chút không hài lòng nhưng menu không đóng khi nhấp vào bên ngoài thì khá khó chịu.
vusan

2

Tôi biết đã có một câu trả lời trước đó đề nghị sử dụng một biểu mẫu nhưng đánh dấu được cung cấp là không chính xác / lý tưởng. Đây là giải pháp đơn giản nhất, hoàn toàn không cần javascript và nó không phá vỡ danh sách thả xuống của bạn. Hoạt động với Bootstrap 4.

<form class="dropdown-item"> <!-- Your elements go here --> </form>


@RosdiKasim Tôi có nó hoạt động tốt trên một trang web với Bootstrap 4.0.0. Chưa được thử nghiệm với 4.1
Radu Ciobanu

Trên thực tế, nó phải giống như: <form class = "dropdown dropdown-item">
Nasser Sadraee

2

Điều này đã giúp tôi

$('.dropdown-menu').on('click', function (e) {
     if ($(this).parent().is(".open")) {
         var target = $(e.target);
         if (target.hasClass("keepopen") || target.parents(".keepopen").length){
                    return false; 
                }else{
                    return true;
                }
            }            
});

Phần tử trình đơn thả xuống của bạn cần phải như thế này, (ghi chú các lớp dropdown-menukeepopen.

<ul role="menu" class="dropdown-menu topmenu-menu eserv_top_notifications keepopen">

Đoạn mã trên ngăn chặn toàn bộ <body>, thay vào đó là phần tử specfic với lớpdropdown-menu .

Hy vọng điều này sẽ giúp được ai đó.

Cảm ơn.


Cảm ơn đã cập nhật theo Per Bootstrap 4 $ ('. Dropdown-menu [data-Xử lýropdownclose = "true"]'). On ('click', function (e) {if ($ (this) .parent (). Is (" .show ")) {var target = $ (e.target); return (target.hasClass (" CloseDropDown ") || target.parents (". CloseDropDown "). length);}});
Thicesiram

1

Giải pháp làm việc đơn giản nhất đối với tôi là:

  • thêm keep-openlớp vào các phần tử không nên đóng
  • và đoạn mã này làm phần còn lại:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});

bạn có thể vui lòng giúp tôi sửa lỗi stackoverflow.com/questions/51552712/ cấp @ Gee-Bee
Zhu

1

Tôi đã tìm thấy không có giải pháp nào hoạt động như tôi muốn bằng cách sử dụng điều hướng bootstrap mặc định. Đây là giải pháp của tôi cho vấn đề này:

       $(document).on('hide.bs.dropdown', function (e) {
        if ($(e.currentTarget.activeElement).hasClass('dropdown-toggle')) {
          $(e.relatedTarget).parent().removeClass('open');
          return true;
        }
        return false;
       });

1

Trong .dropdownnội dung, đặt .keep-openlớp trên bất kỳ nhãn nào như vậy:

$('.dropdown').on('click', function (e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    if (target.hasClass('keep-open')) {
        $(dropdown).addClass('keep-open');
    } else {
        $(dropdown).removeClass('keep-open');
    }
});

$(document).on('hide.bs.dropdown', function (e) {
    var target = $(e.target);
    if ($(target).is('.keep-open')) {
        return false
    }
});

Các trường hợp trước đã tránh các sự kiện liên quan đến các đối tượng container, bây giờ container kế thừa lớp giữ mở và kiểm tra trước khi đóng.


1

Tôi đã làm nó với điều này:

$(element).on({
    'mouseenter': function(event) {
        $(event.currentTarget).data('mouseover', true);
    },
    'mouseleave': function(event) {
        $(event.currentTarget).data('mouseover', false);
    },
    'hide.bs.dropdown': function (event) {
        return !$(event.currentTarget).data('mouseover');
    }
});

0
$(function() {
    $('.mega-dropdown').on('hide.bs.dropdown', function(e) {
        var $target = $(e.target);
        return !($target.hasClass("keep-open") || $target.parents(".keep-open").size() > 0);
    });

    $('.mega-dropdown > ul.dropdown-menu').on('mouseenter', function() {
        $(this).parent('li').addClass('keep-open')
    }).on('mouseleave', function() {
        $(this).parent('li').removeClass('keep-open')
    });
});

0

Để đóng cửa thả xuống chỉ khi một sự kiện nhấp được kích hoạt bên ngoài danh sách thả xuống bootstrap, đây là điều làm việc cho tôi:

Tệp tin:

    $('.createNewElement').on('click.bs.dropdown.data-api', '.tags-btn-group.keep-open-dropdown', function (e) {
        var target = $(e.target);
        if (target.hasClass("dropdown-menu") || target.parents(".dropdown-menu").length) {
            e.stopPropagation();
        }
    });

Tệp HTML:

<!-- button: -->
<div class="createNewElement">
                <div class="btn-group tags-btn-group keep-open-dropdown">

                    <div class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">OPEN DROPDOWN</div>

                    <ul class="dropdown-menu">
                        WHAT EVER YOU WANT HERE...
                    </ul>

                </div>
</div>

0

Bạn có thể gặp một số vấn đề nếu bạn sử dụng phương thức return false hoặc stopPropagation () vì các sự kiện của bạn sẽ bị gián đoạn. Hãy thử mã này, nó hoạt động tốt:

$(function() {
    $('.dropdown').on("click", function (e) {
            $('.keep-open').removeClass("show");
    });
    $('.dropdown-toggle').on("click", function () {
            $('.keep-open').addClass("show");
    });

    $( ".closeDropdown" ).click(function() {
        $('.dropdown').closeDropdown();
    });
});
jQuery.fn.extend({
    closeDropdown: function() {
        this.addClass('show')
            .removeClass("keep-open")
            .click()
            .addClass("keep-open");
    }
  });

Trong HTML:

<div class="dropdown keep-open" id="search-menu" >
    <button  class="btn dropdown-toggle btn  btn-primary" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    <i class="fa fa-filter fa-fw"></i> 
    </button>
    <div class="dropdown-menu">
        <button class="dropdown-item" id="opt1" type="button">Option 1</button>
        <button class="dropdown-item" id="opt2" type="button">Option 2</button>
        <button type="button" class="btn btn-primary closeDropdown">Close</button>
    </div>
</div>

Nếu bạn muốn đóng dropdrown:

`$('#search-menu').closeDropdown();`

0

Trong Bootstrap 4, bạn cũng có thể làm điều này:

$('#dd-link').on('hide.bs.dropdown', onListHide)

function onListHide(e)
{
  if(e.clickEvent && $.contains(e.relatedTarget.parentNode, e.clickEvent.target)) {
  e.preventDefault()
  }
}

trong đó #dd-linkphần tử neo hoặc nút có thuộc data-toggle="drowndown"tính.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.