Come fare in modo che l'evento click SOLO attivi il DIV principale, non i bambini?


211

Ho un DIV con un classificato foobare alcuni DIV all'interno di quel DIV che non sono classificati, ma suppongo che stiano ereditando la foobarclasse:

$('.foobar').on('click', function() { /*...do stuff...*/ });

Voglio che si spenga solo quando si fa clic in un punto del DIV ma non sui DIV dei suoi figli.

Risposte:


440

Se e.targetè lo stesso elemento di this, non hai fatto clic su un discendente.

$('.foobar').on('click', function(e) {
  if (e.target !== this)
    return;
  
  alert( 'clicked the foobar' );
});
.foobar {
  padding: 20px; background: yellow;
}
span {
  background: blue; color: white; padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='foobar'> .foobar (alert) 
  <span>child (no alert)</span>
</div>


Questa risposta spiega questo commento
gdoron sostiene Monica

@gdoron: Adam è troppo gentile. :)

1
Ciao @vicky. Solo FYI, JavaScript ha due diversi tipi di confronto di uguaglianza di valore. Il ===o !==usi la "uguaglianza Confronto Algoritmo Strict" , mentre l' ==e !=usi la "astratta uguaglianza Confronto Algorithm" , che è di tipo coercitivo. La saggezza generale è quella di usare sempre un confronto rigoroso a meno che non ci sia una necessità specifica per il tipo coercitivo (poiché le sue regole sono un po 'complesse) . In questo caso, poiché gli oggetti vengono confrontati, in realtà non fa differenza, ma scoprirai che la maggior parte delle persone continuerà a seguire il rigoroso confronto.

1
@vicky: va bene. È ancora corretto. Solo lasciarti JS ha i diversi operatori. ;-)

3
Questa è una buona risposta perché può funzionare anche con Vanilla JS addEventListener e non è specifica per jQuery.
Michael Giovanni Pumo,

64

C'è un altro modo che funziona se non ti dispiace solo indirizzare i browser più recenti. Aggiungi il CSS

pointer-events: none;

a tutti i figli del div che si desidera acquisire il clic. Ecco le tabelle di supporto

http://caniuse.com/#feat=pointer-events


13
Sappi che dovrei evitare di scrivere commenti di ringraziamento, ma posso baciarti il ​​piede per questo :-)
Simona Adriani,

@SimonaAdriani eh?
n3wb,

Grazie, ho fatto lo stesso, ma faccio fatica a scrivere un caso di test unitario. Come posso assicurarmi che il clicktrigger programmatico dell'evento clic debba essere bloccato?
Pankaj Parkar,

29

Puoi usare il gorgogliamento a tuo favore:

$('.foobar').on('click', function(e) {
    // do your thing.
}).on('click', 'div', function(e) {
    // clicked on descendant div
    e.stopPropagation();
});

Questa sembra una buona soluzione per il mio scenario specifico, poiché voglio solo escludere i clic sugli <a>elementi discendenti . C'è solo un problema: quando faccio clic centrale su di essi, l'evento si attiva (testato su Google Chrome). C'è una variante di questo che impedisce anche questo?
cgogolin,

@cgogolin, dai un'occhiata a questo: stackoverflow.com/questions/12197122/…
Jessica,

28

Non ho ottenuto la risposta accettata per funzionare, ma questo sembra fare il trucco, almeno nella vaniglia JS.

if(e.target !== e.currentTarget) return;

1
e.currentTarget è più preciso del riferimento thisperché l'oggetto a cui thispunta può cambiare a seconda dell'ambito e del contesto da cui viene chiamato
eballeste,

20
//bind `click` event handler to the `.foobar` element(s) to do work,
//then find the children of all the `.foobar` element(s)
//and bind a `click` event handler to them that stops the propagation of the event
$('.foobar').on('click', function () { ... }).children().on('click', function (event) {
    event.stopPropagation();
    //you can also use `return false;` which is the same as `event.preventDefault()` and `event.stopPropagation()` all in one (in a jQuery event handler)
});

Ciò interromperà la propagazione (bolle) clickdell'evento su uno qualsiasi degli elementi figlio .foobardell'elemento (s) in modo che l'evento non raggiunga il.foobar elemento (i) per attivare i gestori dell'evento.

Ecco una demo: http://jsfiddle.net/bQQJP/


3
$(".advanced ul li").live('click',function(e){
    if(e.target != this) return;
    //code
    // this code will execute only when you click to li and not to a child
})

2

Ho avuto lo stesso problema e ho trovato questa soluzione (sulla base delle altre risposte)

 $( ".newsletter_background" ).click(function(e) {
    if (e.target == this) {
        $(".newsletter_background").hide();
    } 
});

Fondamentalmente dice se il target è il div quindi eseguire il codice altrimenti non fare nulla (non nasconderlo)


1

Il mio caso è simile, ma questa è l'occasione in cui hai pochi foobarsecondi e vuoi chiuderne solo uno per ogni clic:

Trova il caso genitore

$(".foobar-close-button-class").on("click", function () {
    $(this).parents('.foobar').fadeOut( 100 );
    // 'this' - means that you finding some parent class from '.foobar-close-button-class'
    // '.parents' -means that you finding parent class with name '.foobar'
});

Trova un caso figlio

$(".foobar-close-button-class").on("click", function () {
    $(this).child('.foobar-close-button-child-class').fadeOut( 100 );
    // 'this' - means that you finding some child class from '.foobar-close-button-class'
    // '.child' -means that you finding child class with name '.foobar-close-button-child-class'
});

1

È possibile utilizzare event.currentTarget. Farà clic solo su elemnt che ha ottenuto l'evento.

target = e => {
    console.log(e.currentTarget);
  };
<ul onClick={target} className="folder">
      <li>
        <p>
          <i className="fas fa-folder" />
        </p>
      </li>
    </ul>


1

Se non riesci a utilizzare pointer-events: none;e stai prendendo di mira i browser moderni puoi utilizzare composedPathper rilevare un clic diretto sull'oggetto in questo modo:

element.addEventListener("click", function (ev) {
    if (ev.composedPath()[0] === this) {
        // your code here ...
    }
})

Puoi leggere di più su compoundPath qui: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath


0

// if its li get value 
document.getElementById('li').addEventListener("click", function(e) {
                if (e.target == this) {
                    UodateNote(e.target.id);
                }
                })
                
                
                function UodateNote(e) {

    let nt_id = document.createElement("div");
    // append container to duc.
    document.body.appendChild(nt_id);
    nt_id.id = "hi";
    // get conatiner value . 
    nt_id.innerHTML = e;
    // body...
    console.log(e);

}
li{
 cursor: pointer;
    font-weight: bold;
  font-size: 20px;
    position: relative;
    width: 380px;
    height: 80px;
    background-color: silver;
    justify-content: center;
    align-items: center;
    text-align: center;
    margin-top: 0.5cm;
    border: 2px solid purple;
    border-radius: 12%;}
    
    p{
     cursor: text;
  font-size: 16px;
   font-weight: normal;
    display: block;
    max-width: 370px;
    max-height: 40px;
    overflow-x: hidden;}
<li id="li"><p>hi</p></li>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.