Luché MUCHO con esto, incluso después de leer todas estas respuestas, y pensé que podría compartir mi solución con ustedes, porque pensé que podría ser uno de los enfoques más simples, aunque algo diferente. Mi pensamiento era simplemente omitir eldragleave
completo el detector de eventos y codificar el comportamiento de dragleave con cada nuevo evento dragenter activado, mientras me aseguraba de que los eventos dragenter no se activaran innecesariamente.
En mi ejemplo a continuación, tengo una tabla, donde quiero poder intercambiar el contenido de las filas de la tabla entre sí a través de la API de arrastrar y soltar. Activado dragenter
, se agregará una clase CSS al elemento de fila al que está arrastrando actualmente su elemento, para resaltarlo, y activado , dragleave
se eliminará esta clase.
Ejemplo:
Tabla HTML muy básica:
<table>
<tr>
<td draggable="true" class="table-cell">Hello</td>
</tr>
<tr>
<td draggable="true" clas="table-cell">There</td>
</tr>
</table>
Y la función de controlador de eventos dragenter, añadido en cada celda de la tabla (a un lado dragstart
, dragover
, drop
, y dragend
los manipuladores, los cuales no son específicos de esta cuestión, por lo que no copiados aquí):
/*##############################################################################
## 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;
}
}
Se dejaron comentarios muy básicos en el código, de modo que este código también es adecuado para principiantes. ¡Espero que esto te ayude! Tenga en cuenta que, por supuesto, deberá agregar todos los oyentes de eventos que mencioné anteriormente en cada celda de la tabla para que esto funcione.