Использование: not () для фильтрации элементов в обработчике событий - PullRequest
0 голосов
/ 13 декабря 2018

Меня довольно смущает селектор :not() .В простом CSS это выглядит довольно просто:

section { /* Overriden as expected */
  color: red;
}
input {
  color: green; /* In effect as expected */
}
:not(input) {
  color: blue; /* In effect as expected */
}
<section>
  <p>Lorem ipsum</p>
  <input value="Lorem ipsum">
</section>

Однако при применении для фильтрации потомков выбранных элементов, запускающих событие, я не могу понять логику:

jQuery(function($){
  $(document).on("keydown", "input", function(event){
    // This fires only for <input> as expected
    console.log("Event handler #1 on", event.target);
  });  

  $(document).on("keydown", ":not(input)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", event.target);
    // ... even though these checks return the results that intuition suggests
    console.log('Is "input"? %s; Is ":not(input)"? %s',
      $(event.target).is("input"),
      $(event.target).is(":not(input)")
    );
  });

  $(document).on("keydown", "section :not(input)", function(event){
    // This *never* fires :-?
    console.log("Event handler #3 on", event.target);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <p>Click and type here</p>
  <input value="Click and type here">
</section>

Каково обоснование того, как :not() работает здесь?

Я действительно ищу объяснение, а неисправление.

1 Ответ

0 голосов
/ 13 декабря 2018

Проблема в том, что keydown событие пузырьков выше input.Если вы используете :not(input), обработчик не будет запускаться, когда событие было только что инициализировано в элементе input, но он будет запускаться, когда событие всплывает до элемента section.Вы можете проверить это, установив this внутри функции, которая будет ссылаться на элемент, к которому всплыло событие, когда срабатывает обработчик.(event.target будет всегда будет input при вводе в поле ввода)

jQuery(function($){
  $(document).on("keydown", ":not(input)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", this);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <p>Click and type here</p>
  <input value="Click and type here">
</section>

Если вы продолжите добавлять :not s, вы увидите, что он всплывает вплоть до HTML-тега:

jQuery(function($){
  $(document).on("keydown", ":not(input):not(section):not(body)", function(event){
    // This fires for *all* elements :-?
    console.log("Event handler #2 on", this);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <p>Click and type here</p>
  <input value="Click and type here">
</section>

Полагаю, вы могли бы использовать :not(input):not(section):not(body):not(html), но это немного глупо и трудно управлять.

Ваштретий обработчик правильно исключает input из события, но только только input (и подобные) элементы запускают keydown события - его нельзя запустить, например, из <section>,Возможно, будет понятнее, если есть дочерний элемент textarea для section, а также для ввода - вы увидите, что textarea запускает обработчик, но ввод не делает:

$(document).on("keydown", "section :not(input)", function(event) {
  console.log("Event handler #3 on", event.target);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
  <p>Click and type here</p>
  <input value="Click and type here">
  <textarea></textarea>
</section>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...