Решение проблемы с событиями dragleave и dragenter в HTML5

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для предотвращения ложного активирования события dragleave при переходе к дочерним элементам, используйте метод contains. Он позволяет проверить, не находится ли event.relatedTarget внутри перетаскиваемого элемента:

JS
Скопировать код
parentElement.addEventListener('dragleave', function(event) {
    if (!parentElement.contains(event.relatedTarget)) {
        // Теперь всё работает правильно! Здесь вы можете реализовать свои срабатывания на drag leave.
    }
});

Так последний будет работать правильно, активируясь только при выходе курсора за пределы перетаскиваемого элемента.

Кинга Идем в IT: пошаговый план для смены профессии

Практическое пособие по учету событий с помощью счетчика

Освоим методику учета событий dragenter и dragleave с использованием счетчика:

JS
Скопировать код
// Включаем счетчик!
var dragCounter = 0;

parentElement.addEventListener('dragenter', function(event) {
  // Учитываем каждый приход.
  dragCounter++;

  // Создаем визуальный эффект.
  this.classList.add('red');

  // Используем для совместимости в IE.
  event.preventDefault(); 
});

parentElement.addEventListener('dragleave', function(event) {
  // Засчитываем уход.
  dragCounter--;

  // Если все ушли, то возвращаем первоначальное состояние.
  if (dragCounter === 0) {
    this.classList.remove('red');
  }
});

parentElement.addEventListener('drop', function(event) {
  // Сбрасываем счетчик при завершении перетаскивания.
  dragCounter = 0; 

  // Возвращаем первоначальный вид.
  this.classList.remove('red');

  event.preventDefault();
});

Обеспечиваем совместимость с браузерами

Важно учесть совместимость с различными браузерами. Следите в частности за свойством pointer-events, оно особенно важно при работе с Firefox. Пример:

CSS
Скопировать код
.child {
  // Корректно управляем событиями наведения.
  pointer-events: none;
}

При отсутствии поддержки необходимого функционала, можно воспользоваться JS-решениями или создать дополнительный слой.

Визуализация

В качестве аналогии представьте событие dragleave как утку-маму (🦆), следящую за своими утятами (🐥), где каждое утёнок — это дочерний элемент.

Markdown
Скопировать код
🦆<div> (Утка-мама)
  🐥<span> (Утёнок №1)
  🐥<div> (Утёнок №2)
</div>

Переход курсора с утки к утёнку не выбивается из общего контекста:

Markdown
Скопировать код
Курсор 🖱️: 🦆 -> 🐥 (Просто внутрисемейное взаимодействие!)

Но dragleave ошибочно воспринимает это как:

Markdown
Скопировать код
🦆: "Утенок исчез из виду — наступает тревога!"

Хотя на самом деле курсор не выходит за пределы границ элемента:

Markdown
Скопировать код
🚧 Утята в безопасности, не переступайте границы семейных отношений! 🚧

Ключевые определения и методы для эффективного управления событиями

Уделите внимание event.relatedTarget, обозначающему, куда "смотрит" курсор. Это словно указатель направления при путешествии:

  • Если он направлен на дочерний элемент (член семьи), нет причин для беспокойства.
  • Если же курсор уходит за пределы элемента, в этом случае активируется dragleave.

Использование "маски" как способ управления событиями

Создайте "маску" в области перетаскивания:

HTML
Скопировать код
<div id="dropzone">
  // Не все герои носят плащи 
  <div id="mask" class="overlay"></div>
  <!-- Содержимое -->
</div>

Привяжите dragleave и drop к этой маске, и она сохранит вас от нежелательных срабатываний:

JS
Скопировать код
// Даже супергерои иногда в беде
mask.addEventListener('dragleave', handleDragLeave);
mask.addEventListener('drop', handleDrop);

Учитываем разные устройства: встречаем совместимость!

Если в браузере пользователя отсутствуют нужные вам функции, используйте условную логику, предлагая альтернативные варианты или запасные решения.

Полезные материалы

  1. Drag operations – Web APIs | MDN – Развернутое описание drag & drop событий на MDN.
  2. HTML5 dragleave fired when hovering a child element – Stack Overflow — Орудует сообщество в обсуждениях проблемы события dragleave при переходе на дочерние элементы.
  3. The HTML5 drag and drop disaster – QuirksBlog — Исследование сложностей, возникающих при работе с HTML5 drag and drop.
  4. Drag and Drop File Uploading | CSS-Tricks — Практичное руководство по реализации функции drag and drop для загрузки файлов в HTML5.
  5. HTML Drag and Drop APIОписание событий для функции drag and drop в HTML на W3Schools.
  6. How To Use The HTML Drag-And-Drop API In React — Smashing Magazine — Руководство по использованию API drag and drop HTML в React для создания сложных интерфейсов.
  7. DISTINGUISH dragleave of parent from child elements — Обсуждение на Stack Overflow, посвященное отличию событий dragleave у родительских и дочерних элементов.