79

I'm wondering how to change during dragging (dragover/dragenter) icon/cursor when I dragenter for example to deny or allow section. Of course, I can move with cursor a part of DOM positioned absolutely, but I'm interested in native HTML5 solution.

Thanks!

Alex Ivasyuv
  • 8,585
  • 17
  • 72
  • 90

7 Answers7

44

You are after dropEffect:

Initialize it in dragstart:

event.dataTransfer.effectAllowed = "copyMove";

Update it in dragenter:

event.dataTransfer.dropEffect = "copy";
akelec
  • 3,797
  • 3
  • 41
  • 39
zupa
  • 12,809
  • 5
  • 40
  • 39
  • 2
    I updated the above JSFiddle to http://jsfiddle.net/rvRhM/192/ to follow your recommendation. It works in Chrome, but Firefox doesn't change the cursor (versions current at time of writing...). Thanks for the tip anyway. – PhiLho Feb 19 '13 at 10:45
  • I had to use event.preventDefault() next to event.dataTransfer.dropEffect in order to make this work – HartWoom Sep 16 '22 at 12:43
16

I have a standalone crossbrowser HTML5 drag and drop example here: http://jsfiddle.net/rvRhM/1/

Have a look at the dragstart and dragend events. dm is the element being dragged.

EventUtil.addHandler(dm, 'dragstart', function(e) {
    e.dataTransfer.setData(format, 'Dragme');
    e.dataTransfer.effectAllowed = effect;
    var target = EventUtil.getCurrentTarget(e);
    target.style.backgroundColor = 'blue';
    target.style.cursor = 'move'; // You can do this or use a css class to change the cursor
    return true;
});

Be sure the reset the cursor when dragging ends:

EventUtil.addHandler(dm, 'dragend', function(e) {  
    var target = EventUtil.getCurrentTarget(e);
    target.style.backgroundColor = '';
    target.style.cursor = 'default'; // Reset cursor
    return true;
});
T. Junghans
  • 11,385
  • 7
  • 52
  • 75
  • 3
    Thanks for response! But I need to change during dragenter/dragover based on have I access to drag element into it or not. BTW, that example doesn't work in Chrome 18 (OS X). – Alex Ivasyuv Apr 12 '12 at 09:12
  • Yeah, not just chrome, also safari and I'm not quite sure why because it's plain old javascript. It works in Firefox. Regarding your other issue, you'll have to make some kind of a connection between the draggable element and the dropzone (with id, cssClass, etc), so that you can determine which draggable is allowed into which dropzone. Then you can style the draggable accordingly. – T. Junghans Apr 12 '12 at 09:56
  • dataTransfer is only supported in FF. – Tym Pollack Jan 23 '16 at 00:21
  • I tried on chrome 75, sometimes it show move cursor, but sometime it just default cursor icon. – Azriz Jun 28 '19 at 01:12
4

preventDefault() needs to go on the target element. This line attached to the document finally took care of it for me

document.addEventListener("dragover", (event) => {
    event.preventDefault();
});
Robb Hoff
  • 1,719
  • 2
  • 17
  • 32
3

Adding pure css solution, which may be useful for few folks. Use this class on the html element.

.grab {
        cursor: move;
        cursor: grab;
        cursor: -moz-grab;
        cursor: -webkit-grab;
        .thumbnails-list{
            cursor: pointer;
        }
    }

    .grab:active {
        cursor: grabbing;
        cursor: -moz-grabbing;
        cursor: -webkit-grabbing;
    }
Kurkula
  • 6,386
  • 27
  • 127
  • 202
2

I was trying to achieve the same and couldn't really find a nice solution. What I did in the end was setting an image to the dataTransfer and change its src with every action. That way the behavior is consistent across browsers at least. Here's a link to a page that I used as a reference:

https://kryogenix.org/code/browser/custom-drag-image.html

eduedu87
  • 54
  • 2
2

The accepted answer works if and only if ev.preventDefault() is called on all events changing the dropEffect (don't call it in dragstart) as described in MDN

ShaMan123
  • 99
  • 4
0

This worked for me:

<div class="container">
    <div draggable="true">
    <div draggable="true">
</div>
$('.container').bind('dragover', function() {
    $('body').addClass('dragging');
});
$('.container').bind('dragleave', function() {
    $('body').removeClass('dragging');
});
.container > div {
    cursor: grab;
}
body.dragging .container > div {
    cursor: grabbing;
}

https://jsfiddle.net/cLb3hxtf/1/

zyrup
  • 691
  • 2
  • 10
  • 18
  • @AMoore seems to have worked for me on Chrome 92.0.4515.107 https://jsfiddle.net/cLb3hxtf/1/ – zyrup Aug 02 '21 at 14:42
  • For me, on Chrome 92.0.4515.131 (windows 7, sry :( ) it's not even draggable in the jsfiddle provided. – A Moore Aug 04 '21 at 17:09