Як створити ТОЛЬКИ пожежу на натиск на батьківський DIV, а не на дітей?


211

У мене є DIV з класифікованим foobar, і кілька DIV всередині цього DIV, які не є класифікованими, але я припускаю, що вони успадковують foobarклас:

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

Я хочу, щоб він вистрілювався лише при натисканні десь у DIV, але не на його дітях DIV.

Відповіді:


439

Якщо e.targetелемент - це той самий елемент this, що ви не натискали нащадка.

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


Ця відповідь пояснює цей коментар
gdoron підтримує Моніку

@gdoron: Адам занадто добрий. :)

1
Привіт @vicky. Тільки FYI, JavaScript має два різні типи порівняння рівності значення. ===Або !==використання «суворе рівність Порівняння Алгоритм» , в той час як , ==і !=використовує «Abstract Рівність алгоритм порівняння» , який є типом коерцитивності. Загальна мудрість полягає у тому, щоб завжди використовувати суворе порівняння, якщо немає конкретної потреби в примусовому типі (оскільки його правила трохи складні) . У цьому випадку, оскільки об’єкти порівнюються, це насправді не має значення, але ви виявите, що більшість людей все одно буде дотримуватися суворого порівняння.

1
@vicky: Це добре. Це все-таки правильно. Просто дозволяючи JS має різних операторів. ;-)

3
Це хороша відповідь, оскільки він також може працювати з Vanilla JS addEventListener і не є специфічним для jQuery.
Майкл Джованні Пумо

64

Є ще один спосіб, який працює, якщо ви не заперечуєте лише націлювати на нові браузери. Просто додайте CSS

pointer-events: none;

будь-яким дітям, які ви хочете зафіксувати клацанням. Ось таблиці підтримки

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


13
Знайте, що мені слід уникати писати коментарі "спасибі", але я можу поцілувати вас за це :-)
Симона Адріані

@SimonaAdriani так?
n3wb

Дякую, я зробив так само, але я намагаюся написати тестовий випадок навколо нього. Як я можу переконатися, що clickтригер подій програмного натискання повинен бути заблокований?
Панкай Паркар

29

Ви можете використовувати барботаж на свою користь:

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

Це виглядає як приємне рішення для мого конкретного сценарію, оскільки я хочу виключити лише кліки на нащадкові <a>елементи. Є лише одна проблема: коли я клацну на них середнім клавішею, подія все ще спрацьовує (перевірено в Google Chrome). Чи є варіант цього, який також перешкоджає цьому?
cgogolin

@cgogolin, подивіться на це: stackoverflow.com/questions/12197122/…
Джессіка

28

Я не отримав прийнятої відповіді на роботу, але це, здається, робило трюк, принаймні у ванільному JS.

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

1
e.currentTarget є більш точним, ніж посилання, thisтому що об’єкт, на який thisвказує, може змінюватися залежно від сфери та контексту, звідки він викликаний
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)
});

Це зупинить розповсюдження (барботування) clickподії на будь-якому з дочірніх елементів (-ів) .foobarелемента (-ів), тому подія не дійде до .foobarелементів (-ів), щоб запустити обробник (-ів) подій.

Ось демонстрація: 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

У мене була така ж проблема і я придумав це рішення (виходячи з інших відповідей)

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

В основному це говорить, що якщо ціль є div, то запустіть код, інакше нічого не робити (не ховайте)


1

Мій випадок подібний, але це випадок, коли у вас є кілька foobar-ти, і ви хочете закрити лише один - за один клік:

Знайдіть батьківський випадок

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

Знайдіть випадок дитини

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

Ви можете використовувати event.currentTarget. Це зробить подія лише натисканням елементу, який отримав подію.

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


1

Якщо ви не можете використовувати pointer-events: none;та орієнтуєтесь на сучасні веб-переглядачі, ви можете використовувати composedPathдля виявлення прямого клацання на об’єкт так:

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

Ви можете прочитати більше про съставлений шлях тут: 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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.