Eu lutei muito com isso, mesmo depois de ler todas essas respostas, e pensei em compartilhar minha solução com você, porque achei que poderia ser uma das abordagens mais simples, embora um pouco diferente. Meu pensamento era simplesmente omitir dragleave
completamente o ouvinte de evento e codificar o comportamento da saída de arrastar com cada novo evento dragenter acionado, enquanto certificava-me de que os eventos dragenter não fossem acionados desnecessariamente.
No meu exemplo abaixo, eu tenho uma tabela na qual desejo trocar o conteúdo da linha da tabela por meio da API de arrastar e soltar. Em dragenter
, uma classe CSS deve ser adicionada ao elemento de linha no qual você está arrastando o elemento para destacá-lo e dragleave
, em seguida , essa classe deve ser removida.
Exemplo:
Tabela HTML muito básica:
<table>
<tr>
<td draggable="true" class="table-cell">Hello</td>
</tr>
<tr>
<td draggable="true" clas="table-cell">There</td>
</tr>
</table>
E a função dragenter manipulador de eventos, adicionado para cada célula da tabela (com exceção dragstart
, dragover
, drop
, e dragend
manipuladores, que não são específicos para esta questão, por isso não copiadas aqui):
/*##############################################################################
## 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;
}
}
Comentários muito básicos deixados no código, de modo que este código seja adequado também para iniciantes. Espero que isso ajude você! Observe que é claro que você precisará adicionar todos os ouvintes de eventos mencionados acima em cada célula da tabela para que isso funcione.