Simple Drag&Drop with JavaScript, JQuery



I am working on an application that requires Drag & Drop functionality in a web page with images. First I thought I would implement this using JQuery UI, because I had used it earlier and it makes DnD very easy. But then I thought it may not be too difficult to implement it myself. As it turned out, it is not really very difficult. Here is a simple demo of that implementation.

There are two Divs in this demo, one containing image thumbnails and the other is a drop target for images. Drag and drop image thumbnails on the target Div. The original image would be added to the Div.You can then move images within this Div. If you drag and drop it anywhere outside the div, the drop operation is cancelled and image is removed.

Drag & Drop above images below –

 

This is how it is implemented –

  • Add mousedown, mousemove and mouseup listeners to Document
  • In mousedown, check if the element that is clicked has ‘rk_draggable’ class
    • If yes, then clone that element and save reference to it. Save offset of mouse click location in the image
  • In mousemove, move the cloned element.
  • In mouseup, check the location of mouse up falls in any of the elements with ‘rk_droppable’ class, if not cancel drop
    • Else, get source element of the thumbnail, create a new image and add to target element.
    • Remove cloned thumbnail

Here is the complete source code :

<script language="JavaScript">
	var mouseDown = false;
	var clonedElm = null;
	var xOffset = 0, yOffset = 0;

	$().ready(function(){
		$(document).mousedown(onMouseDown);
		$(document).mousemove(onMouseMove);
		$(document).mouseup(onMouseUp);
	});

	function onMouseDown (event)
	{
		if (event.srcElement == undefined && event.target != undefined)
			event.srcElement = event.target;

		if (!$(event.srcElement).hasClass("rk_draggable"))
			return;

		mouseDown = true;

		if ($(event.srcElement).hasClass("rk_clonable"))
		{
			//clone the element
			clonedElm = $(event.srcElement).clone();
			$(clonedElm).removeClass("rk_clonable");
			$(clonedElm).addClass("rk_thumbnail");
			var offset = $(event.srcElement).offset();
			$(event.srcElement).parent().append($(clonedElm));
			$(clonedElm).offset(offset);
		}
		else
		{
			clonedElm = $(event.srcElement);
		}

		var tmpOffset = clonedElm.offset();
		xOffset = tmpOffset.left - event.pageX;
		yOffset = tmpOffset.top - event.pageY;

		$(clonedElm).css("position", "absolute");

		var width = $(event.srcElement).width();
		var height = $(event.srcElement).height();

		$(clonedElm).width(width);
		$(clonedElm).height(height);

		return false;
	}

	function onMouseMove (event)
	{
		if (clonedElm == null)
			return;

		$(clonedElm).offset({
        	left: event.pageX + xOffset,
        	top: event.pageY + yOffset
        });

        return false;
	}

	function onMouseUp (event)
	{
		//check if object is dropped on droppable element
		var droppableElements = $(".rk_droppable");
		if (droppableElements.length == 0)
		{
			cancelDrop(event);
		}
		else
		{
			var droppableElm = null;
			for (var i = droppableElements.length-1; i >= 0; i--)
			{
				if (isLocationInElement(droppableElements[i], event.pageX, event.pageY))
				{
					droppableElm = droppableElements[i];
					break;
				}
			}

			if (droppableElm == null)
				cancelDrop(event);
			else
				performDrop (event, droppableElm);
		}

		mouseDown = false;
		clonedElm = null;
		xOffset = 0;
		yOffset = 0;
    }

	function cancelDrop (event)
	{
		if (clonedElm == null)
			return;
		if (!$(clonedElm).hasClass("rk_clonable"))
		{
			$(clonedElm).remove();
		}
		clonedElm = null;
	}

	function performDrop (event, droppableElm)
	{
		//blow up images
		if (event.srcElement == undefined && event.target != undefined)
			event.srcElement = event.target;

		//check element has source attribute
		var src = $(event.srcElement).attr("src");

		if (src != undefined && $(event.srcElement).hasClass("rk_thumbnail"))
		{
			var newImage = "<img src='" + src + "' class='rk_draggable'>";
			var newImageElm = $(newImage).appendTo($(droppableElm));
			//remove thumb nail
			$(clonedElm).remove();
		}
		//$(clonedElm).remove();
		clonedElm = null;
	}

	function isLocationInElement (element, x, y)
	{
		var elmOffset = $(element).offset();
		if (x >= elmOffset.left && x <= (elmOffset.left + $(element).width()) &&
			y >= elmOffset.top && y <= (elmOffset.top + $(element).height()))
			return true;
		return false;
	}
</script>

-Ram Kulkarni

23 Replies to “Simple Drag&Drop with JavaScript, JQuery”

    1. You can do that in performDrop function. For example, if you want to set width to half, then after creating ‘newImageElm’, add following lines of code –

      var heightWidthRatio = newImageElm.height() / newImageElm.width();
      newImageElm.width(newImageElm.width()/2);
      newImageElm.height(newImageElm.width() * heightWidthRatio);
      
      1. Thank you so much Ram. I have one question here. The div with class ‘rk_droppable’ contains an image inside it and this image takes the whole width of the screen. Can you suggest me how to drop image with class ‘rk_draggable rk_clonable’ above this image instead of div.

        This is my div –

  1. Hi Ram,
    Thanks for your reply.
    Plz send me the complete code. I need it because its very excellent code. Code not available in given link.

  2. Is it possible to drop the image at anywhere inside the parent rather at coordinates(0,0) ?? If so how it could be done ??

    Thanks

Leave a Reply to Ganesh Cancel reply