Ho lottato molto con questo, anche dopo aver letto tutte queste risposte, e ho pensato che potrei condividere la mia soluzione con te, perché ho pensato che potesse essere uno degli approcci più semplici, anche se in qualche modo diverso. Il mio pensiero era semplicemente omettere dragleave
completamente l'ascoltatore di eventi e codificare il comportamento di dragleave con ogni nuovo evento dragenter attivato, assicurandomi al contempo che gli eventi dragenter non venissero generati inutilmente.
Nel mio esempio di seguito, ho una tabella, in cui desidero poter scambiare tra loro i contenuti delle righe della tabella tramite l'API di trascinamento della selezione. Su dragenter
, una classe CSS deve essere aggiunta all'elemento riga in cui si sta attualmente trascinando l'elemento, per evidenziarlo e su dragleave
, questa classe deve essere rimossa.
Esempio:
Tabella HTML molto semplice:
<table>
<tr>
<td draggable="true" class="table-cell">Hello</td>
</tr>
<tr>
<td draggable="true" clas="table-cell">There</td>
</tr>
</table>
E la funzione di gestore di eventi DragEnter, aggiunto su ogni cella di una tabella (a parte dragstart
, dragover
, drop
, e dragend
gestori, che non sono specifici a questa domanda, in modo da non copiate qui):
/*##############################################################################
## 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;
}
}
Commenti di base lasciati nel codice, in modo che questo codice sia adatto anche ai principianti. Spero che questo ti possa aiutare! Nota che dovrai ovviamente aggiungere tutti i listener di eventi che ho menzionato sopra in ogni cella della tabella affinché questo funzioni.