Wie kann ein Klickereignis NUR auf Eltern-DIV ausgelöst werden, nicht auf Kinder?

211

Ich habe einen DIV mit einer Klasse foobarund ein paar DIVs in diesem DIV, die nicht klassifiziert sind, aber ich nehme an, sie erben die foobarKlasse:

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

Ich möchte, dass das nur ausgelöst wird, wenn irgendwo im DIV geklickt wird, nicht aber auf die untergeordneten DIVs.

CaptSaltyJack
quelle

Antworten:

439

Wenn das e.targetdas gleiche Element ist wie this, haben Sie keinen Nachkommen angeklickt.

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

Benutzer1106925
quelle
Diese Antwort erklärt diesen Kommentar
Gdoron unterstützt Monica
@gdoron: Adam ist zu nett. :)
1
Hallo @vicky. Nur zu Ihrer Information, JavaScript bietet zwei verschiedene Arten des Vergleichs von Wertgleichheiten. Das ===oder !==verwendet den "Strict Equality Comparison Algorithm" , während das ==und !=den "Abstract Equality Comparison Algorithm" verwendet , der vom Typ Zwang ist. Die allgemeine Weisheit ist, immer einen strengen Vergleich zu verwenden, es sei denn, es besteht ein spezifischer Bedarf für den Zwangstyp (da seine Regeln etwas komplex sind) . In diesem Fall macht es keinen Unterschied, da Objekte verglichen werden, aber Sie werden feststellen, dass die meisten Menschen sich immer noch an den strengen Vergleich halten.
1
@ Vicky: Das ist in Ordnung. Es ist immer noch richtig. Nur JS zu lassen, hat die verschiedenen Operatoren. ;-)
3
Dies ist eine gute Antwort, da es auch mit Vanilla JS addEventListener funktionieren kann und nicht jQuery-spezifisch ist.
Michael Giovanni Pumo
64

Es gibt eine andere Möglichkeit, die funktioniert, wenn es Ihnen nichts ausmacht, nur auf neuere Browser abzuzielen. Fügen Sie einfach das CSS hinzu

pointer-events: none;

an alle Kinder des Div, die Sie den Klick erfassen möchten. Hier sind die Support-Tabellen

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

hobberwickey
quelle
13
Wisse, dass ich es vermeiden sollte, 'Danke'-Kommentare zu schreiben, aber ich kann dich dafür küssen :-)
Simona Adriani
@ SimonaAdriani nicht wahr?
n3wb
Danke, ich habe es genauso gemacht, aber ich habe Mühe, einen Unit-Testfall darum herum zu schreiben. Wie kann ich sicherstellen, dass der clickAuslöser für programmgesteuerte Klickereignisse blockiert wird?
Pankaj Parkar
29

Sie können das Sprudeln zu Ihren Gunsten verwenden:

$('.foobar').on('click', function(e) {
    // do your thing.
}).on('click', 'div', function(e) {
    // clicked on descendant div
    e.stopPropagation();
});
ori
quelle
Dies scheint eine gute Lösung für mein spezielles Szenario zu sein, da ich nur Klicks auf untergeordnete <a>Elemente ausschließen möchte . Es gibt nur ein Problem: Wenn ich mit der mittleren Maustaste darauf klicke, wird das Ereignis immer noch ausgelöst (in Google Chrome getestet). Gibt es eine Variante davon, die dies auch verhindert?
Cgogolin
@cgogolin, werfen Sie einen Blick auf diese: stackoverflow.com/questions/12197122/…
Jessica
28

Ich habe nicht die akzeptierte Antwort auf die Arbeit bekommen, aber dies scheint den Trick zu tun, zumindest in Vanilla JS.

if(e.target !== e.currentTarget) return;
Jens Törnell
quelle
1
e.currentTarget ist genauer als das Referenzieren, thisda sich das Objekt, auf das thises zeigt, je nach Umfang und Kontext ändern kann, von dem aus es aufgerufen wird
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)
});

Dadurch wird die Ausbreitung (Blasenbildung) des clickEreignisses auf einem der untergeordneten Elemente des .foobarElements gestoppt, sodass das Ereignis die .foobarElemente nicht erreicht , um deren Ereignishandler auszulösen.

Hier ist eine Demo: http://jsfiddle.net/bQQJP/

Jaspis
quelle
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
})
Michalis
quelle
2

Ich hatte das gleiche Problem und fand diese Lösung (basierend auf den anderen Antworten)

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

Grundsätzlich heißt es, wenn das Ziel das Div ist, dann führen Sie den Code aus, sonst tun Sie nichts (verstecken Sie ihn nicht)

Wonx2150
quelle
1

Mein Fall ist ähnlich, aber dies ist eine Gelegenheit, wenn Sie nur wenige foobar-s haben und nur eine schließen möchten - pro einen Klick:

Suchen Sie den übergeordneten Fall

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

Finden Sie einen Kinderfall

$(".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'
});
Wukadin
quelle
1

Sie können event.currentTarget verwenden. Es wird nur ein Klickereignis angezeigt, das ein Ereignis erhalten hat.

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

Dejan Markovic
quelle
1

Wenn Sie pointer-events: none;moderne Browser nicht verwenden können und auf diese abzielen, können Sie composedPatheinen direkten Klick auf das Objekt wie folgt erkennen:

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

Weitere Informationen zu composPath finden Sie hier: https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath

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

Omar bakhsh
quelle