javascript - working - dropdown traduzione




Evita menu a tendina chiudi al clic all'interno (16)

Ho un menu a tendina Bootstrap su Twitter. Come tutti gli utenti di Twitter Bootstrap sanno, il menu a tendina si chiude sul clic (facendo clic anche all'interno di esso).

Per evitare ciò, posso facilmente collegare un gestore di eventi click nel menu a discesa e aggiungere semplicemente il famoso 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>

Questo sembra facile e un comportamento molto comune, tuttavia, e poiché i gestori di eventi di carousel indicators (così come gli carousel indicators ) sono delegati all'oggetto del document , l'evento click su questi elementi (controlli prev / next , ...) sarà “ignorato”.

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

Affidarsi a Twitter Bootstrap dropdown hide / hidden events non è una soluzione per i seguenti motivi:

  • L'evento fornito per entrambi i gestori di eventi non fornisce alcun riferimento all'elemento selezionato
  • Il contenuto del menu a discesa viene generato dinamicamente, quindi non è possibile aggiungere una classe flag

Questo violino è il comportamento normale e questo violino è con event.stopPropagation() aggiunto.

Aggiornare

Grazie a Roman per la sua risposta . Ho anche trovato una risposta che puoi trovare qui sotto .


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

l'ho aggiornato ancora una volta per essere il più intelligente e funzionale possibile. ora si chiude quando si passa il mouse fuori dal nav, rimanendo aperti mentre ci si trova all'interno. semplicemente perfetto.


Ad esempio, Bootstrap 4 Alpha ha questo Evento di menu. Perché non usare?

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

Ho anche trovato una soluzione.

Supponendo che i gestori di eventi relativi ai Twitter Bootstrap Components siano delegati all'oggetto document , eseguo il loop dei gestori collegati e verifica se l'elemento su cui si fa clic (o uno dei suoi genitori) è interessato da un evento delegato.

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

Spero che aiuti chiunque cerchi una soluzione simile.

Grazie a tutti per il vostro aiuto.


Invece di scrivere un codice javascript o jquery (reinventando la ruota). Lo scenario sopra può essere gestito dall'opzione di chiusura automatica del bootstrap. Puoi fornire uno dei valori alla chiusura automatica :

  1. sempre - (Predefinito) chiude automaticamente il menu a discesa quando viene fatto clic su uno qualsiasi degli elementi.

  2. outsideClick - chiude automaticamente il menu a discesa solo quando l'utente fa clic su un elemento esterno al menu a discesa.

  3. disabilitato - disabilita la chiusura automatica

Dai un'occhiata al seguente plunkr:

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

Impostato

uib-dropdown auto-close="disabled" 

Spero che questo ti aiuti :)


La soluzione di lavoro più semplice per me è:

  • aggiungere la classe keep-open agli elementi che non dovrebbero causare la chiusura del menu a discesa
  • e questo pezzo di codice fa il resto:
$('.dropdown').on('click', function(e) {
    var target = $(e.target);
    var dropdown = target.closest('.dropdown');
    return !dropdown.hasClass('open') || !target.hasClass('keep-open');
});

Nel contenuto .dropdown metti la classe .keep-open su qualsiasi etichetta in questo modo:

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

I casi precedenti evitavano gli eventi relativi agli oggetti container, ora il contenitore eredita la classe keep-open e controlla prima di essere chiusa.


Non ho trovato nessuna delle soluzioni ha funzionato come vorrei utilizzare il bootstrap di default. Ecco la mia soluzione a questo problema:

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

Per chiudere il menu a discesa solo se un evento click è stato attivato al di fuori del menu a discesa di avvio, questo è ciò che ha funzionato per me:

File JS:

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

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

Questo dovrebbe aiutare pure

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

Questo potrebbe aiutare:

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

Rimozione dei dati di attributo data-toggle="dropdown" e l'implementazione dell'apertura / chiusura del menu a discesa può essere una soluzione.

Innanzitutto gestendo il clic sul link per aprire / chiudere il menu a discesa in questo modo:

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

e quindi ascoltando i clic all'esterno del menu a discesa per chiuderlo in questo modo:

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

Ecco la demo: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/


So che c'è già una risposta precedente che suggerisce di usare un modulo ma il markup fornito non è corretto / ideale. Ecco la soluzione più semplice, non è necessario alcun javascript e non interrompe il menu a discesa. Funziona con Bootstrap 4.

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


[Bootstrap 4 Alpha 6] [Rails] Per lo sviluppatore di rails, e.stopPropagation() porterà a comportamenti indesiderati per link_to con data-method diverso da get dato che per impostazione predefinita restituirà tutte le richieste come get .

Per ovviare a questo problema, suggerisco questa soluzione, che è universale

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

$('.dropdown .dropdown-menu').on('click.bs.dropdown', function() {
  return $('.dropdown').one('hide.bs.dropdown', function() {
    return false;
  });
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

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


Bootstrap fornisce la seguente funzione:

                 | This event is fired immediately when the hide instance method 
hide.bs.dropdown | has been called. The toggling anchor element is available as the 
                 | relatedTarget property of the event.

Pertanto, l'implementazione di questa funzione dovrebbe essere in grado di disabilitare il menu a discesa dalla chiusura.

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

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

Questo può funzionare per qualsiasi condizione.


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






drop-down-menu