I'm working on a small jQuery plugin that mimics the jQuery UI draggable/droppable behavior with native HTML5 drag and drop events.
A feature I'd want to add is the ability to specify the node which will serve as the drag proxy.
I did a bit of research, and according to MDN, to do this requires the use of setDragImage()
, passing an image or an element.
What is the support for setDragImage
in different browsers?
I've noticed there's a plugin named jquery.event.drag which takes a different than I expected to this problem.
Would this feature require me to make some kind of workaround like the above plugin, or should this be possible out-of-the-box in most or all browsers using setDragImage
?
EDIT
After playing around a bit with this functionality, it would seem that this function is quite limited.
Besides having no support in quite a few browsers, using an arbitrary DOM element as the helper requires it to be in the DOM tree and visible, and so you have the element itself on the body, and a copy of it as the handler. This is mostly unwanted for this sort of plugin.
Further more, rendering is also problematic even when the right terms are met. When trying to create a helper from <span>TEST</span>
, the helper itself only showed a white rectangle with the dimensions of the span
.
Are these issues that were to be expected according to the specs? Could they be fixed in code or would they require a workaround?
I'm working on a small jQuery plugin that mimics the jQuery UI draggable/droppable behavior with native HTML5 drag and drop events.
A feature I'd want to add is the ability to specify the node which will serve as the drag proxy.
I did a bit of research, and according to MDN, to do this requires the use of setDragImage()
, passing an image or an element.
What is the support for setDragImage
in different browsers?
I've noticed there's a plugin named jquery.event.drag which takes a different than I expected to this problem.
Would this feature require me to make some kind of workaround like the above plugin, or should this be possible out-of-the-box in most or all browsers using setDragImage
?
EDIT
After playing around a bit with this functionality, it would seem that this function is quite limited.
Besides having no support in quite a few browsers, using an arbitrary DOM element as the helper requires it to be in the DOM tree and visible, and so you have the element itself on the body, and a copy of it as the handler. This is mostly unwanted for this sort of plugin.
Further more, rendering is also problematic even when the right terms are met. When trying to create a helper from <span>TEST</span>
, the helper itself only showed a white rectangle with the dimensions of the span
.
Are these issues that were to be expected according to the specs? Could they be fixed in code or would they require a workaround?
Share Improve this question edited Oct 16, 2012 at 21:47 GeReV asked Oct 7, 2012 at 4:23 GeReVGeReV 3,2657 gold badges34 silver badges45 bronze badges1 Answer
Reset to default 19setDragImage is IMO a vital feature for any non trivial drag and drop use case. e.g consider a multi select list where a drag needs to include all the selected items and not just the row that the drag gesture was made on. it's odd that the thing you want to set needs to be visible in the DOM but even worse is that this method is not implemented at all in IE as of version 11.
However, with a bit of effort I was able to get it working reasonably satisfactorily. The custom drag image node can be removed from the DOM in a timeout 0 function. so add it to the DOM in dragstart then use it in set drag image and then remove it. This works perfectly in FF but in chrome the drag image node will flicker before the timeout fires. One way to prevent this is to position it such that the actual browser generated drag image will appear in exactly the same place, this is not as bad as it sounds since you can control the position of the custom drag image relative to the cursor.
I was playing with this recently and was able to get it working on IE as well. the trick there is to get IE to drag the custom drag image node and not the node that dragstart fired on. you can do this with the IE specific dragDrop() method.
The final thing to be aware of is that on windows there is a 300px limit on the width of the custom drag image node this applies to all draggables not just the custom node actually. so the browser applies a heavy radial gradient if the drag image is too big.
http://jsfiddle.net/stevendwood/akScu/21/
$(function() {
(function($) {
var isIE = (typeof document.createElement("span").dragDrop === "function");
$.fn.customDragImage = function(options) {
var offsetX = options.offsetX || 0,
offsetY = options.offsetY || 0;
var createDragImage = function($node, x, y) {
var $img = $(options.createDragImage($node));
$img.css({
"top": Math.max(0, y-offsetY)+"px",
"left": Math.max(0, x-offsetX)+"px",
"position": "absolute",
"pointerEvents": "none"
}).appendTo(document.body);
setTimeout(function() {
$img.remove();
});
return $img[0];
};
if (isIE) {
$(this).on("mousedown", function(e) {
var originalEvent = e.originalEvent,
node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);
node.dragDrop();
});
}
$(this).on("dragstart", function(e) {
var originalEvent = e.originalEvent,
dt = originalEvent.dataTransfer;
if (typeof dt.setDragImage === "function") {
node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY);
dt.setDragImage(node, offsetX, offsetY);
}
});
return this;
};
}) (jQuery);
$("[draggable='true']").customDragImage({
offsetX: 50,
offsetY: 50,
createDragImage: function($node) {
return $node.clone().html("I'm a custom DOM node/drag image").css("backgroundColor", "orange");
}
}).on("dragstart", function(e) {
e.originalEvent.dataTransfer.setData("Text", "Foo");
});
});