Я боровся з цим багато, навіть прочитавши всі ці відповіді, і подумав, що можу поділитися своїм рішенням з вами, тому що я вважав, що це може бути один із найпростіших підходів, хоча дещо інший. Моя думка полягала в тому, щоб просто пропустити цеdragleave
слухача події повністю і кодувати поведінку драглейка при кожному новому запущеному події драгенера, одночасно переконуючись, що події драгенера не будуть запускатися без потреби.
У наведеному нижче прикладі у мене є таблиця, в якій я хочу мати можливість обмінюватися вмістом рядків таблиці один з одним за допомогою API перетягування. Увімкнено dragenter
, клас CSS буде доданий до елемента рядка, у який ви зараз перетягуєте ваш елемент, щоб виділити його, і dragleave
цей клас буде видалено.
Приклад:
Дуже основна таблиця HTML:
<table>
<tr>
<td draggable="true" class="table-cell">Hello</td>
</tr>
<tr>
<td draggable="true" clas="table-cell">There</td>
</tr>
</table>
А функція DragEnter обробник події додається на кожен елемент таблиці (крім dragstart
, dragover
, drop
і dragend
обробники, які не є специфічними для цього питання, тому не скопійовані тут):
/*##############################################################################
## Dragenter Handler ##
##############################################################################*/
// When dragging over the text node of a table cell (the text in a table cell),
// while previously being over the table cell element, the dragleave event gets
// fired, which stops the highlighting of the currently dragged cell. To avoid
// this problem and any coding around to fight it, everything has been
// programmed with the dragenter event handler only; no more dragleave needed
// For the dragenter event, e.target corresponds to the element into which the
// drag enters. This fact has been used to program the code as follows:
var previousRow = null;
function handleDragEnter(e) {
// Assure that dragenter code is only executed when entering an element (and
// for example not when entering a text node)
if (e.target.nodeType === 1) {
// Get the currently entered row
let currentRow = this.closest('tr');
// Check if the currently entered row is different from the row entered via
// the last drag
if (previousRow !== null) {
if (currentRow !== previousRow) {
// If so, remove the class responsible for highlighting it via CSS from
// it
previousRow.className = "";
}
}
// Each time an HTML element is entered, add the class responsible for
// highlighting it via CSS onto its containing row (or onto itself, if row)
currentRow.className = "ready-for-drop";
// To know which row has been the last one entered when this function will
// be called again, assign the previousRow variable of the global scope onto
// the currentRow from this function run
previousRow = currentRow;
}
}
У коді залишилися дуже основні коментарі, такі, що цей код підходить і для початківців. Сподіваюсь, це допоможе вам! Зауважте, що вам, звичайно, потрібно буде додати всіх слухачів подій, про яких я згадував вище, у кожну клітинку таблиці, щоб це працювало.