Go Back   CodingForums.com > :: Client side development > JavaScript programming > JavaScript frameworks

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 12-15-2012, 04:29 PM   PM User | #1
javageek
New to the CF scene

 
Join Date: Dec 2012
Posts: 7
Thanks: 0
Thanked 1 Time in 1 Post
javageek is an unknown quantity at this point
Draggable clone of image, jQuery

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.

Hope this makes sense, any thoughts appreciated.
javageek is offline   Reply With Quote
Old 12-15-2012, 05:08 PM   PM User | #2
AndrewGSW
Senior Coder

 
Join Date: Apr 2011
Location: London, England
Posts: 2,120
Thanks: 15
Thanked 354 Times in 353 Posts
AndrewGSW will become famous soon enough
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..
AndrewGSW is offline   Reply With Quote
Old 12-15-2012, 06:10 PM   PM User | #3
javageek
New to the CF scene

 
Join Date: Dec 2012
Posts: 7
Thanks: 0
Thanked 1 Time in 1 Post
javageek is an unknown quantity at this point
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.
javageek is offline   Reply With Quote
Old 12-15-2012, 06:24 PM   PM User | #4
AndrewGSW
Senior Coder

 
Join Date: Apr 2011
Location: London, England
Posts: 2,120
Thanks: 15
Thanked 354 Times in 353 Posts
AndrewGSW will become famous soon enough
Quote:
Originally Posted by javageek View Post
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..
AndrewGSW is offline   Reply With Quote
Old 12-15-2012, 06:54 PM   PM User | #5
javageek
New to the CF scene

 
Join Date: Dec 2012
Posts: 7
Thanks: 0
Thanked 1 Time in 1 Post
javageek is an unknown quantity at this point
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
javageek is offline   Reply With Quote
Old 12-15-2012, 07:02 PM   PM User | #6
AndrewGSW
Senior Coder

 
Join Date: Apr 2011
Location: London, England
Posts: 2,120
Thanks: 15
Thanked 354 Times in 353 Posts
AndrewGSW will become famous soon enough
Quote:
Originally Posted by javageek View Post
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.
Here's a complete page if it helps. It is not mine - believe it's Vic's work
Code:
<!DOCTYPE html>
<html>
<head>
<title>Some Title</title>

<style type="text/css">
/* */
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
</script>
<script type="text/javascript">

$(document).ready(function() {

});

var dragobjekt = null;

var dragx = 0;
var dragy = 0;

var posx = 0;
var posy = 0;

function draginit() {
    document.onmousemove = drag;
    document.onmouseup = dragstop;
}

function dragstart(element,coords) {
    dragstart.coords=coords;
    dragobjekt = element;
    dragx = posx - dragobjekt.offsetLeft;
    dragy = posy - dragobjekt.offsetTop;
}

function dragstop() {
    var lft=dragobjekt.offsetLeft,top=dragobjekt.offsetTop,c=dragstart.coords;
    if (c&&lft>c[0]&&lft+dragobjekt.offsetWidth<c[1]&&top>c[2]&&top+dragobjekt.offsetHeight<c[3]){
        alert(c)
    }
    dragobjekt=null;
}

function drag(ereignis) {
    posx = document.all ? window.event.clientX : ereignis.pageX;
    posy = document.all ? window.event.clientY : ereignis.pageY;
    if(dragobjekt != null) {
        dragobjekt.style.left = (posx - dragx) + "px";
        dragobjekt.style.top = (posy - dragy) + "px";
    }
}
</script>

</head>

<body onload="draginit()">
<div  style="position:absolute;top:200px;left:500px;height:120px;width:120px;border:solid red 1px;"> </div>
<div onmousedown="dragstart(this,[500,620,200,320])"
     style="position:absolute;top:0px;left:0px;height:100px;width:100px;background:#ff0000"> </div>
<div onmousedown="dragstart(this,[500,620,200,320])"
     style="position:absolute;top:200px;left:0px;height:100px;width:100px;background:#00ff00"> </div>
</body>
</html>
Vic

God Loves You and will never love you less.

http://www.vicsjavascripts.org.uk/

If my post has been useful please donate to http://www.operationsmile.org.uk/
__________________
"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..
AndrewGSW is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 06:19 AM.


Advertisement
Log in to turn off these ads.