I am trying to do some draggable coding with jQuery. What I want to do is this. I have an image, I want the user to be able to drag the image, but I also want the original image to stay in place. So there would now be 2 images, the original (static) and the draggable clone.
I have tried using the clone method (fired on mouseover, which seems wrong on hacky) to clone the image and then append the clone using css, the problem is that the appended clone is being flowed into the div every time (thus creating many copies, for subsequent mouseovers), I have tried using absolute positioning and z-index, but it's not working.
mouseover is not a good choice because, as you have discovered, you can end up with lots of clones. mousedown is probably more sensible, but you need to check that you only have one clone at any time:
Code:
var theImage = document.getElementById("imageID"); // jQuery: $('#imageID')
var theClone = theClone || theImage.cloneNode(true); // jQuery: theImage.clone()
Then use mouseup to either insert the clone (or not) and set theClone = null (jQuery: .remove() ..? if you must . No, I think this removes an existing element from the DOM: just set it to null.)
BTW
Code:
var theClone = theClone || theImage.cloneNode(true);
is my favourite JS statement; we cannot do this in most any other language - or, at least, not as simply as this.
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Last edited by AndrewGSW; 12-15-2012 at 05:33 PM..
If I create the clone on mousedown, append it to the dom on mouseup, the user is going to need to click again to drag it. And I'm still not sure how to place the clone directly on top of the static image, z-index isn't doing to the trick. the clone(s) is always placed next to the static original. Thanks.
If I create the clone on mousedown, append it to the dom on mouseup, the user is going to need to click again to drag it. And I'm still not sure how to place the clone directly on top of the static image, z-index isn't doing to the trick. the clone(s) is always placed next to the static original. Thanks.
In general terms.. mousedown can be used to initiate the clone, mousemove to make it visible and move it, then mouseup to append it permanently.
z-index on its own won't help. You should use a container element (maybe a DIV) with position:relative, and make the clone position: absolute (within this DIV or other container) so that it can be moved at the same time as the mouse.
But (I keep forgetting) you are using jQuery, so why don't you investigate the jQuery draggable UI?
The following code is vanilla JS but it indicates the principles involved in dragging elements:
Code:
function Draggable() { // Class : allow draggable elements
if (!(this instanceof Draggable)) return new Draggable(); // did they use "new"?
var _startX, _startY, _offsetX, _offsetY,
_dragElement, // needs to be passed from OnMouseDown to OnMouseMove
_oldZIndex; // we temporarily increase the z-index during drag
var InitDragDrop = function () {
_startX = _startY = _offsetX = _offsetY = 0;
document.onmousedown = OnMouseDown;
document.onmouseup = OnMouseUp;
};
var OnMouseDown = function (e) {
if (e == null) e = window.event; // IE doesn't pass the event object
var target = e.target != null ? e.target : e.srcElement;
// ..IE uses srcElement, others use target
// for IE, left click == 1; for Firefox, left click == 0
if ((e.button == 1 && window.event != null || e.button == 0) &&
target.className == 'dragIt') { // grab the mouse position
// grab the clicked element's position
_startX = e.clientX; _startY = e.clientY;
_offsetX = ExtractNumber(target.style.left);
_offsetY = ExtractNumber(target.style.top);
// bring the clicked element to the front while it is being dragged
_oldZIndex = target.style.zIndex;
target.style.zIndex = 100;
// we need to access the element in OnMouseMove
_dragElement = target;
// tell our code to start moving the element with the mouse
document.onmousemove = OnMouseMove;
// cancel out any text selections
document.body.focus();
// prevent text selection in IE
document.onselectstart = function () { return false; };
// prevent IE from trying to drag an image
target.ondragstart = function() { return false; };
// prevent text selection (except IE)
return false;
}
return true; // not used
};
var OnMouseMove = function (e) {
if (e == null) e = window.event;
// this is the actual "drag code"
_dragElement.style.left = (_offsetX + e.clientX - _startX) + 'px';
_dragElement.style.top = (_offsetY + e.clientY - _startY) + 'px';
};
var OnMouseUp = function (e) {
// When the mouse is released, we remove the event handlers
// and reset dragElement:
if (_dragElement != null) {
_dragElement.style.zIndex = _oldZIndex;
// we're done with these events until the next OnMouseDown
document.onmousemove = null;
document.onselectstart = null;
_dragElement.ondragstart = null;
// this is how we know we're not dragging
_dragElement = null;
}
};
var ExtractNumber = function (value) {
var n = parseInt(value,10);
return n == null || isNaN(n) ? 0 : n;
};
this.InitDragDrop = InitDragDrop; // only need to expose this method
return this;
}
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Last edited by AndrewGSW; 12-15-2012 at 06:29 PM..
Hmmm, I'm going to look further at the regular js code you posted, and I am using jQuery's ui draggable.
Let me hack on it some, and I'll come back with more questions. Thanks.
Update: Got it working (mostly) I wound up needing to position the class absolutely, where as before it was just flowing in it's container. Now I have a new problem which is how to do it with n images, without creating separate css entries for each one.
Last edited by javageek; 12-15-2012 at 07:02 PM..
Reason: appending
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Last edited by AndrewGSW; 12-15-2012 at 07:07 PM..