Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve appearance of dragged A element when using html5 draggable attribute

How can i preserve appearance of the dragged A element when using 'draggable' html5 attribute. On some browsers (Safari & Chrome) when dragging anchor, dragged helper is replaced with browser native implementation of dragged element as seen on the screenshots:

When dragging DIV

When dragging DIV

When dragging A

When dragging A

HTML

<div class="draggable">Draggable DIV</div>
<a href="" class="draggable">Draggable A</a>

CSS

$('.draggable').attr('draggable', true);

Here is the quick JSBin i assembled to demonstrate this issue http://jsbin.com/pihayeceza/1/edit

Thanks

like image 354
Goran Radulovic Avatar asked Dec 26 '14 10:12

Goran Radulovic


2 Answers

I'm able to preserve the appearance of the dragged element by using DataTransfer.setDragImage. If I add the following code to the JavaScript in your jsbin instance, it work for me on Firefox, Chrome and Safari:

$('a.draggable').on('dragstart', function (ev) {
  var dt = ev.originalEvent.dataTransfer;
  // In IE browsers, setDragImage does not exist. However, the issue we are 
  // trying to fix does not happen in these broswers. So if setDragImage is not
  // available, then just don't do anything.
  if (dt.setDragImage) 
    dt.setDragImage(ev.target, 0, 0);

});

The dataTransfer field of the event has a DataTransfer object associated with the drag operation. You have to fetch it from the original DOM Event rather than from the jQuery Event wrapper, so ev.originalEvent.dataTransfer.

For IE browsers, setDragImage is not present but the problem reported in the question does not occur in the first place so if setDragImage is absent, we just don't call it.

A bin with the updated code.

like image 177
Louis Avatar answered Sep 21 '22 01:09

Louis


This problem happens because the default behavior of dragging a link with an href attribute is to create an image containing the url to be used as the drag placeholder. You can fix this by removing the href attribute, however, to get around that without having to remove the href attribute you can use mousedown/up event handlers to remove the attribute and then re-add it, leaving the anchors clickable*.

$('.draggable').attr('draggable', true).on('mousedown', function () {
  if ($(this).is('a')) {
    $(this).data('href', this.href);
    $(this).removeAttr('href');
  }
}).on('mouseup', function () {
  if ($(this).is('a')) {
    $(this).attr('href', $(this).data('href'));
  }
}).on('click', function () {
  console.log(this.href);
});
.draggable {
  margin: 10px;
  display: block;
  width: 200px;
  background: #fafafa;
  color: #333;
  text-decoration: none;
  height: 40px;
  border: 1px solid #eaeaea;
  line-height: 40px;
  text-align: center;
  cursor: move;
  border-radius: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="draggable">Draggable DIV</div>
  <a href="http://www.google.com" target="_blank" class="draggable">Draggable A</a>

*Note: stack snippets doesn't let you follow the link.

like image 41
Kevin B Avatar answered Sep 23 '22 01:09

Kevin B