Я много боролся с этим, даже после прочтения всех этих ответов, и подумал, что могу поделиться с вами своим решением, потому что я подумал, что это может быть один из более простых подходов, хотя и несколько другой. Я думал о том, чтобы просто dragleave
полностью исключить прослушиватель событий и кодировать поведение dragleave при каждом новом событии dragenter, в то же время следя за тем, чтобы события dragenter не запускались без необходимости.
В моем примере ниже у меня есть таблица, где я хочу иметь возможность обмениваться содержимым строк таблицы друг с другом с помощью 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;
}
}
В коде остались очень простые комментарии, так что этот код подходит и для начинающих. Надеюсь, это поможет вам! Обратите внимание, что вам, конечно, нужно добавить всех прослушивателей событий, о которых я упоминал выше, в каждую ячейку таблицы, чтобы это работало.