Joerg
Joerg

Reputation: 3813

HTML5 dragend event firing immediately

I have several draggable elements

<div Class="question-item" draggable="true">Box 1: Milk was a bad choice.</div>
<div class="question-item" draggable="true">Box 2: I'm Ron Burgundy?</div>
<div class="question-item" draggable="true">Box 3: You ate the entire wheel of cheese?     </div>
<div class="question-item" draggable="true">Box 4: Scotch scotch scotch</div>

And I have the following event handlers:

var $questionItems = $('.question-item');

$questionItems
  .on('dragstart', startDrag)
  .on('dragend', removeDropSpaces)
  .on('dragenter', toggleDropStyles)
  .on('dragleave', toggleDropStyles);


function startDrag(e){
  console.log('dragging...');
  addDropSpaces();
  e.stopPropagation();
}

function toggleDropStyles(){
  $(this).toggleClass('drag-over');
  console.log(this);
}


function addDropSpaces(){
  $questionItems.after('<div class="empty-drop-target"></div>');
}

function removeDropSpaces(){
  console.log("dragend");
  $('.empty-drop-target').remove()
}

Why does it only work for the first draggable. If I drag say the last draggable - the dragend event is fired immediately. (I don't want to use jQuery UI btw)

It makes no sense to me - it looks like a bug.

I am on Chrome v 30 on OSX.

Here is a link to the JSFiddle: http://jsfiddle.net/joergd/zGSpP/17/

(Edit: this is repeat of the following question: dragend, dragenter, and dragleave firing off immediately when I drag - but I think the original poster was fine to go with jQuery UI, whereas I want it to be HTML5 native)

Upvotes: 26

Views: 9643

Answers (4)

user1351905
user1351905

Reputation: 161

This is a known chrome issue. Problem is, as Joerg mentions that you manipulates the dom on dragstart.

You can do so, but you need to do it in a timeout.


For example

const dragstart = (event: DragEvent) => {
    event.dataTransfer!.setDragImage(image, 0, 0);

    setTimeout(() => {
        // mutate dom here
    }, 0);
};

Upvotes: 11

Cody Rowley
Cody Rowley

Reputation: 11

Just had the same problem. I was manipulating the DOM by changing an elements position to fixed in dragStart. I fixed my issues using Ivan's answer like this:

/* This function produced the issue */
function dragStart(ev) {
    /* some code */
    myElement.style.position="fixed";
}

/* This function corrected issue */
function dragStart(ev) {
    /*some code */
    setTimeout(function changePos() {
        myElement.style.position="fixed";
        }, 10);
}

It seems like the answer to your problem would be

function startDrag(e){
  console.log('dragging...');
  setTimeout(addDropSpaces(),10);
  e.stopPropagation();
}

Upvotes: 1

Ivan Koshelev
Ivan Koshelev

Reputation: 4260

As i mentioned in the topic dragend, dragenter, and dragleave firing off immediately when I drag , what solved the problem (which looks to be a Chrome bug) for me was to add a setTimeout of 10 milliseconds into the handler and manipulate the DOM in that timeout.

Upvotes: 24

Joerg
Joerg

Reputation: 3813

I don't have a direct solution, but changing the DOM in the dragStart event handler is causing this problem, and any code that changes the DOM should really go in the dragEnter event handler - doing so, drag&drop events are fired more reliably.

Not sure whether this is by design - it feels a bit like a bug though.

Upvotes: 15

Related Questions