Решение проблемы с событиями dragleave и dragenter в HTML5
Быстрый ответ
Для предотвращения ложного активирования события dragleave
при переходе к дочерним элементам, используйте метод contains
. Он позволяет проверить, не находится ли event.relatedTarget
внутри перетаскиваемого элемента:
parentElement.addEventListener('dragleave', function(event) {
if (!parentElement.contains(event.relatedTarget)) {
// Теперь всё работает правильно! Здесь вы можете реализовать свои срабатывания на drag leave.
}
});
Так последний будет работать правильно, активируясь только при выходе курсора за пределы перетаскиваемого элемента.
Практическое пособие по учету событий с помощью счетчика
Освоим методику учета событий dragenter
и dragleave
с использованием счетчика:
// Включаем счетчик!
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. Пример:
.child {
// Корректно управляем событиями наведения.
pointer-events: none;
}
При отсутствии поддержки необходимого функционала, можно воспользоваться JS-решениями или создать дополнительный слой.
Визуализация
В качестве аналогии представьте событие dragleave
как утку-маму (🦆), следящую за своими утятами (🐥), где каждое утёнок — это дочерний элемент.
🦆<div> (Утка-мама)
🐥<span> (Утёнок №1)
🐥<div> (Утёнок №2)
</div>
Переход курсора с утки к утёнку не выбивается из общего контекста:
Курсор 🖱️: 🦆 -> 🐥 (Просто внутрисемейное взаимодействие!)
Но dragleave
ошибочно воспринимает это как:
🦆: "Утенок исчез из виду — наступает тревога!"
Хотя на самом деле курсор не выходит за пределы границ элемента:
🚧 Утята в безопасности, не переступайте границы семейных отношений! 🚧
Ключевые определения и методы для эффективного управления событиями
Значение relatedTarget
Уделите внимание event.relatedTarget
, обозначающему, куда "смотрит" курсор. Это словно указатель направления при путешествии:
- Если он направлен на дочерний элемент (член семьи), нет причин для беспокойства.
- Если же курсор уходит за пределы элемента, в этом случае активируется
dragleave
.
Использование "маски" как способ управления событиями
Создайте "маску" в области перетаскивания:
<div id="dropzone">
// Не все герои носят плащи
<div id="mask" class="overlay"></div>
<!-- Содержимое -->
</div>
Привяжите dragleave
и drop
к этой маске, и она сохранит вас от нежелательных срабатываний:
// Даже супергерои иногда в беде
mask.addEventListener('dragleave', handleDragLeave);
mask.addEventListener('drop', handleDrop);
Учитываем разные устройства: встречаем совместимость!
Если в браузере пользователя отсутствуют нужные вам функции, используйте условную логику, предлагая альтернативные варианты или запасные решения.
Полезные материалы
- Drag operations – Web APIs | MDN – Развернутое описание drag & drop событий на MDN.
- HTML5 dragleave fired when hovering a child element – Stack Overflow — Орудует сообщество в обсуждениях проблемы события
dragleave
при переходе на дочерние элементы. - The HTML5 drag and drop disaster – QuirksBlog — Исследование сложностей, возникающих при работе с HTML5 drag and drop.
- Drag and Drop File Uploading | CSS-Tricks — Практичное руководство по реализации функции drag and drop для загрузки файлов в HTML5.
- HTML Drag and Drop API — Описание событий для функции drag and drop в HTML на W3Schools.
- How To Use The HTML Drag-And-Drop API In React — Smashing Magazine — Руководство по использованию API drag and drop HTML в React для создания сложных интерфейсов.
- DISTINGUISH dragleave of parent from child elements — Обсуждение на Stack Overflow, посвященное отличию событий
dragleave
у родительских и дочерних элементов.