I enjoy simplicity, in everything. Unnecessary complexity is evil. Have a look at my WordPress plugins.

jQuery drag and drop inventory [1/2]

Lately i’ve been playing around with some interactive systems for browser based games with the ultimate dream of once creating such a browser game myself. Don’t stop reading if you’re not into browser based games though, this tutorial could prove very useful for creating web applications too!

This time i’ve used jQuery UI to create a drag and drop inventory and thought it might be useful for some others. I’ve split this article in 2 sections, section 1 covers the creating of the drag and drop system and section 2 covers storing the position of the items into the database. Let’s get started, or have a look at the demo to see what we’re actually trying to achieve here!

Creating the item spots and the inventory..

Let’s start off with some basic HTML to set up the various item spots and the inventory that holds the items, together with some items to be dragged around later..

<div id="weapon_spot"></div>
<div id="helmet_spot"></div>
<div id="inventory">
	<img src="weapon.png" class="weapons" alt="A sword thus a weapon" />
	<img src="helmet.png" class="helmets" alt="Some fancy helmet" />
</div>

Pretty basic stuff so far, just three div elements with some images inside the #inventory. For this example i’m using two different types of items, weapons and helmets. Both of these items can be stored in their own spot or in the inventory. Notice that i’ve added classes to the image which set to whatever category the image/item belongs.

Make the items draggable

Everything is still static so far. You can try to drag whatever you want, the images won’t move. That’s why we’re going to use the jQuery UI draggable() function here to make the images draggable.

$(document).ready(function() {
	$(".weapons,.helmets").draggable({ revert: 'invalid' });
});

You might be wondering what the revert is for? Well, this makes the image revert to it’s original position every time it isn’t dropped on a valid droppable element that accepts the item.

Alright, so the item is draggable but can’t be dropped anywhere because it always reverts to it’s original position. We want the items to be dropped on their spot OR in the inventory, so let’s make all those elements droppable.

Make the spots droppable so that they only accept certain items..

To make the various spots only accept items of a certain kind we’re going to use the droppable accept option. Let’s extend the snippet used above..

$(document).ready(function() {
	$(".weapons,.helmets").draggable({ revert: 'invalid' });
	$('#inventory').droppable();
	$("#weapon_spot").droppable({ accept: '.weapons'})
	$('#helmet_spot').droppable({ accept: '.helmets'});
});

Above snippet makes the inventory accept every draggable item, the weapon spot only accepts elements from the weapons class and the helmet spot only accepts draggable items from the helmets class. Pretty easy right?

Actually we’re done now, we’ve got ourself a drag and drop system in which items can only be dragged to their own spot. BUT.. it’s ugly! The absolute positioning looks ugly. We want the items to be aligned in a pretty way right? Right! Let’s fix this..

Re-creating the dragged element.

To position the dragged element inside their spots we need to re-create the element and add it to the HTML of the spot-elements. This removes the absolute positioning of the dragged element, and makes it use the padding etc. of the parent (thus the spot) element. I’ve wrote a little function that takes care of this and gets fired everytime a draggable item is dropped onto a droppable element. Let’s take a look..

function itemInSpot(drag_item,spot)
{
	var item = $('<img />'); // create new img element
	item.attr({ // copy attributes
		src: drag_item.attr('src'),
	}).attr('class',drag_item.attr('class')).appendTo(spot).draggable({ revert: 'invalid' }); // add to spot + make draggable
	drag_item.remove(); // remove the old object
}

So. Create a new image element, copy the attributes of the dropped item, append to the spot element, make it draggable and remove the old dropped element. Note that we’ve copied the class attribute separately, this is because IE thinks we’re actually creating a class when not used as a string. Now all that’s left is to bind this function and get it fired with the right parameters. To do this we’re adding another line to our document ready function, that passed the dropped element and the spot in which to store the newly created element.

$('#weapon_spot,#helmet_spot,#inventory').bind('drop', function(ev,ui) { itemInSpot(ui.draggable,this); });

Alright, the items align pretty now (assuming you did some styling). Basically, we got everything covered. But what if you got multiple items and the spot an item is dragged to is already occupied? Let’s make some kind of swap functionality in the next chapter!

Swapping items whenever a slot is already occupied.

The first thing we need to do is add another weapon item cause if we don’t this situation would be impossible.. Just add another image element inside the inventory div.

<img src="dagger.png" class="weapons" alt="A dagger which is also a weapon" />

Now, whenever our itemInSpot function is activated let’s check if there is an item inside the spot. We’re going to use jQuery’s find function along with length to accomplish this. If an element is found, append this to the inventory.

var oldSpotItem = $(spot).find('img');
if(oldSpotItem.length>0) {
	oldSpotItem.appendTo('#inventory').draggable({ revert: 'invalid' });
}

Append this piece of code to our itemInSpot function (which is fired after a dragged element is dropped onto a valid droppable) and you should be fine!

Well, that’s all. Want to take a look at the whole source code or have a look at what we’ve just created? Take a look at the demo!

In the next part of this article I’ll extend this code so the position of the items get stored into the database. Like this tutorial so far or have a question? Leave a comment, I greatly appreciate!

Share this post: on Twitter on Facebook

7 Responses to “jQuery drag and drop inventory [1/2]”

  1. Thank, that’s what i was looking for! Although the first part was imho not so difficult and i was thinking about a attempt of doing it before reading your text (now i don’t need), I’m still wondering how and when should i refresh the database. I’m looking forward for the next phase of your text ;]

  2. Hi Santa,

    I’ll probably have the next article ready tomorrow, it’s pretty in-depth cause interacting with the database could be handled in a few different ways! Hope you can wait that long.. Anyway, thanks a lot! Glad you like it and hope you like the next part even better!

    Best, Danny

  3. I implemented draggable image using jQuery-ui Draggable and saved coordinates into database.

    Now I am getting coordinates and images url in xml format.

    I want to reset the image position. where it was saved. using jquery and javascript.

  4. Hi Gen,

    What coordinates are you using, just a simple left and top? You might find jQuery’s offset functions useful then.

  5. Hi Danny
    I am trying to use your tutorial to help me build a menu planner (for recipes). I’d like to be able to drag multiple items from my “inventory” of recipes to a menu div. I tried getting rid of the line drag_item.remove() but that messes things up. I just want a neat listing of dishes for a menu. I’m not sure how to get it working in a nice looking way. Help!

Leave a Reply