How to style dragged element
Asked Answered
T

6

22

There are some events that I can use for handling drag & drop:

https://developer.mozilla.org/en/DragDrop/Drag_and_Drop

there is a drag event, which is fired during the time the element is being dragged. I can control the source element styling or the target droppable container, but how can I style the "ghost" element that's being created by the browser?

I want to remove the "disabled" icon from it when the element is over a non-draggable area and replace it with a "cursor-move" icon

Here's what I have so far:

http://jsfiddle.net/YkaCM/

enter image description here

Tobit answered 23/6, 2012 at 12:36 Comment(0)
A
3

Not too sure about other browsers however the dataTransfer object contains a property called mozCursor. This allows you to change the cursor in the drag state, however this is a Mozilla property.

https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/mozCursor

An example of using this can be found at the following location, the setting is changed on dragstart (set to use default 'arrow' cursor), dragover (set to use auto drag cursor (arrow with copy)) and dragleave (reset to use default 'arrow' cursor):

http://jsfiddle.net/YkaCM/4/


Try the answers to:
Javascript: How can I set the cursor during a drag & drop operation on a website?


Updated your dragover with the following:

$('#droppable').bind('dragover', function (e) {
  $(this).addClass('over'); // new

  ...

http://jsfiddle.net/YkaCM/1/

Acrylic answered 23/6, 2012 at 12:40 Comment(2)
thanks, that fixes what I thought was a browser glitch, but it doesn't solve my question :PTobit
I don't think you can style the 'ghost' element. With Firebug opened when testing it doesn't appear to show any change to the HTML. Do you have any examples of what you'd like to achieve?Acrylic
C
28

You can't style this directly as it is a bitmap/copy of what the element looked like when the drag started:

http://jsfiddle.net/2EvGP/

EDIT:

You can actually cheat to achieve this by briefly changing the style of the element when the drag starts: http://jsfiddle.net/LULbV/

$('#draggable').bind('dragstart', function (e){

  [Set style here]

  setTimeout(function(){
    [Reset style here]
  }, 1);

  ...

});

This works flawlessly in Chrome 19, and shows the style change depending on how you drag in Firefox 13. You would need to reset the dragged element's style on drop.

(Note I have a pretty fast computer, so I'm not sure if this hack would still work on slow machines)

Camelliacamelopard answered 23/6, 2012 at 12:52 Comment(1)
Worked great, thanks... tried using the setDataImage method (and other dataTransfer methods) before using this solution with mixed results. It seems there are some odd behaviors in the DnD/Data Transfer API.Touber
L
8

An alternative, using only CSS, is to style the :active pseudo-class of the element to the desired drag style. The dragged copy will be created based on this state.

However, the original element will be kept with this style, as the browser seems to keep it :active until drop. To avoid this we can assign the style in an animation that runs for a very short period of time. Enough for the browser to copy the style but not too short. 0.1s seems enough for Chrome, Safari and Firefox.

https://jsfiddle.net/mLsw5ajr/

$('#draggable').bind('dragstart', function(e) {

  // https://mcmap.net/q/53766/-get-selected-element-39-s-outer-html
  var stuff = $(this).clone().wrap('<div></div>').parent().html();

  e.originalEvent.dataTransfer.effectAllowed = 'copy';
  e.originalEvent.dataTransfer.setData('stuff', stuff);
});

$('#draggable').bind('drag', function(e) {
  // here I want to style the ghost element, not the source...    
});

$('#droppable').bind('dragover', function(e) {

  if (e.originalEvent.preventDefault)
    e.preventDefault();

  e.originalEvent.dataTransfer.dropEffect = 'copy';
  return false;
});


$('#droppable').bind('dragenter', function(e) {
  $(this).addClass('over');
});

$('#droppable').bind('dragleave', function(e) {
  $(this).removeClass('over');
});


$('#droppable').bind('drop', function(e) {

  if (e.originalEvent.stopPropagation)
    e.originalEvent.stopPropagation();

  var stuff = $(e.originalEvent.dataTransfer.getData('stuff'));
  stuff.appendTo(this);
  return false;
});
#draggable,
#droppable {
  background: #ccc;
  color: #fff;
  padding: 10px;
  margin: 10px 0 100px;
}

#draggable:active {
  animation: drag_style .1s;
}

#droppable.over {
  background: #000;
}

@keyframes drag_style {
  0% {
    background-color: #fc0;
    color: #000;
  }
  99% {
    background-color: #fc0;
    color: #000;
  }
  100% {
    background-color: #ccc;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="draggable" draggable="true">
  <p>Drag me to my target</p>
</div>

<div id="droppable">
  <p>Drop me</p>
</div>

A problem I found in Firefox is that the element is kept :active if there is no event triggering by another element (like a drop). To fix this we could trigger a click outside the element.

Loeffler answered 24/10, 2018 at 18:12 Comment(0)
A
3

Not too sure about other browsers however the dataTransfer object contains a property called mozCursor. This allows you to change the cursor in the drag state, however this is a Mozilla property.

https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/mozCursor

An example of using this can be found at the following location, the setting is changed on dragstart (set to use default 'arrow' cursor), dragover (set to use auto drag cursor (arrow with copy)) and dragleave (reset to use default 'arrow' cursor):

http://jsfiddle.net/YkaCM/4/


Try the answers to:
Javascript: How can I set the cursor during a drag & drop operation on a website?


Updated your dragover with the following:

$('#droppable').bind('dragover', function (e) {
  $(this).addClass('over'); // new

  ...

http://jsfiddle.net/YkaCM/1/

Acrylic answered 23/6, 2012 at 12:40 Comment(2)
thanks, that fixes what I thought was a browser glitch, but it doesn't solve my question :PTobit
I don't think you can style the 'ghost' element. With Firebug opened when testing it doesn't appear to show any change to the HTML. Do you have any examples of what you'd like to achieve?Acrylic
H
2

You can add a class to the element being dragged, therefore allowing you to style it however you want. Like so:

element.addEventListener("dragstart", (event) => {
  event.currentTarget.classList.add("dragging");
});

Checkout https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setData

Hermitage answered 17/11, 2022 at 18:20 Comment(0)
B
1

basically you want to apply a specific style to newly created element that are son of #droppable?

#droppable div { here your code }
Benfield answered 23/6, 2012 at 12:41 Comment(0)
G
0

Add a setTimeout to remove the class do the trick ! As the browser do a bitmap copy, when we set the class at dragstart, the copy contains the class. The timeout remove the class on the orginial element, not the ghost.

element.addEventListener("dragstart", (event) => {
  event.currentTarget.classList.add("dragging");
  setTimeout(() => {
    event.currentTarget.classList.remove('dragging')
  }, 10)
});

10 ms is arbitrary. I've no idea of the best delay.

Greece answered 2/4, 2024 at 6:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.