.: How to Create a Draggable Div :.

Intro

Ever wanted to be able to create a draggable item on a webpage? That's why I created this page. I wanted to create a draggable div, and I also wanted to learn CSS at the same time, so I created this page as a guide to any of you out there who may need some help creating one yourself. I will run through all of the steps and the thought process I went through while I was creating my draggable div so maybe you can get a better understanding of how to do it. The understanding you need here is the following.

It's ok if you don't fully understand these. I will do my best to explain them as we go along, and of course always feel free to email me with any questions.

Step 1: The div

The idea here is to first create a div. This will be your element that you with to drag around. We give it an id of "dragger" which will be how we refer to it using our javascript. We give it a class of monkey which will define it's attributes. The HTML inbetween the <div></div> tags can be whatever you want to be inside of this div.

<div id="dragger" class="monkey">
Div with class <b>monkey</b>
<p>replace this text!</p>
</div>

Now that we have our div created, we still need to create our class. Our class name we will be using is called monkey. This can be whatever you like, just remember to refer to it in your div. Using CSS you can define attributes for an object once and have them reusable as a class. So you could make 20 div's and they would all look the same if you just do class="monkey". This isn't a tutorial on CSS, so i won't go into the details of CSS, but here we create a simple red box with a width and height of 200 pixels. Make sure this CSS goes in the head portion of your code.

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

.monkey {
background: #FF0000; /* red background */
width: 200px;
height: 200px;
position: absolute; /* we want to set an absolute position so the div can be moved in reference to the screen */
top: 50px; /* this sets the positioning of the element in reference to the top left of your window. it will space it 50 pixels from the top */
left: 50px; /* this will set the position of the element 50 pixels to right of the top left of your window. */
z-index: 5; /* this will position it above anything with a lower z-index, sort of like layers. So you could layer these divs using z-index and have them stack on each other. */
}

</style>
</head>

Div with class monkey

replace this text!

This will be a sample div like the one on the right. I just set some default properties for it, such as a red background and a width and height of 200 pixels. You can of course customize this any way you want. Yours would however appear in the top left of the window. You can put whatever relevant content you would like to display in the div, be it an image, text, or a form. Anything you want!

Ok.

Now we've got an ugly red box in the top left of our screen.

It's not moving.

Or anything.

Well, let's think about what we are going to need to make it move.

We are going to need to know how our div is positioned. The way I like to identify a div position is using the top left coordinate as the start point. This can be specified using CSS, using the top: and left: attributes. Then from that top left, a width and height is added to draw our box.

X:

Y:

Ok, our div is positioned using the top left coordinate. Got it. Now we need to find out where the mouse is. Using javascript we will use the mouse move event to track the mouse position. If you move your mouse, the box to the right will tell you the position of the mouse in realtime. I will explain this soon.

We also need to know some more things. A drag event works like this. You click on an item and hold down the mouse button. Then you move the mouse and after you are done, you release the mouse button. Now the item's position will be where you released the mouse button. So we have to know if the mouse was pressed on the item, if it moved while it was pressed down, and if it was released. This will be accomplished using javascript event handlers as well.

Step 2: The Javascript

I am by no means an expert on javascript, and there may be much better ways to handle what I'm doing. While I was trying to create this draggable div, I looked at the DOM listing at w3schools. From there I pulled what I thought was necessary to create this draggable div. They have a nice listing of all the events and some sample code.

::OnClick()

Click in me!

Now we will take a look at the basic onClick event. Try clicking in the div to the right. You should see an alert box pop up. The code for this is extremely simple. You don't even have to declare any javascript in the head part of your page. It embeds right into the div tag. Here's what it looks like.

<div id="click_me" onClick="alert('I got clicked!')">
<center>Click in me!</center>
</div>

That was it. You could put that on any div, and it would popup the alert.
The onClick makes an event handler to handle any clicks on the div. When something is clicked, it will do whatever is withing the quotes.
Within the quotes I used an existing javascript function called alert(); It takes a parameter, which could be a string or variable and will create the popup box for me. I suggest not using javascript alerts() if you can avoid them. For testing they are fine, but on real websites, they are annoying. If i see a javascript alert on a page, I probably won't stick around too long. Maybe if it was for field validation or something, but I find popping them up and having to click OK a waste of clicks. So what do I suggest to do?

::innerHTML

Click in me!
No Click Yet :(

Create a span and change the message there. A span is much like a div, except I only use it for text. I find it easier to think of divs as my boxes and spans as my html or text I want to change. Using spans for debugging were extremely useful for me while I was creating this draggable div. Click in the box to the right, and you can see an example of what I'm talking about. The code isn't too difficult either.

<div onClick="document.getElementById('help_text').innerHTML = '<b>I got clicked! :) </b>'">
<center> <b>Click in me!</b> <br>
<span id="help_text">No click yet :( </span>
</div>

Let's take a look at what's going on here. I created a div, and i added an onClick event. I put some weird code in it, which I will explain soon. Next I put some default text, Click in me! Then a line break, then I created my span with an id="help_text". You must give any element you wish to refer to using javascript an id. Now back to the weird code. Whenever we click on the div, we want the span's text to change.

onClick="document.getElementById('help_text').innerHTML = '<b>I got clicked! :) </b>'"

Now what is all this mess. Simple. This is how javascript finds the span within our page or document. So document means page, then getElementById() is a function of the document class which javascript uses to find an element. It finds the element by id (hence the name), and the reason why I gave my span an id. The final part is innerHTML which is an attribute of the span. It is the actual HTML between the <span></span> tags. So you could change the whole text, formatting, even put a whole table within the span. Then finally you set what you want the new HTML to be inside your span. So now let's put it together.This is what we want to do in a pseudo-language...

myPage.myElement.Message = myMessage;

which we can translate to javascript by doing...

document.getElementById('help_text').innerHTML = 'your message here';

Simple right? ( I hope so, because we are going to be using this functionality quite a bit soon. )

::Cursor Position

X:

Y:

Moving along, now we start getting to some coolstuff. When dragging on object, we need to know our position on the screen. So if I click an object, I need the coordinates of the mouse when I start dragging the object. This is done fairly easy, but a little more work than before. You must first establish the scope of the object you wish to drag. The scope of the draggable object means, do you want to be able to drag the object all over the screen? OR should it be confined to only drag in a certain box? For the scope of this tutorial, I will assume the scope we want is the whole screen, so I should be able to drag my div anywhere on screen. So to track the coordinates of the cursor we will need a couple pieces of code. First let's create our display box like the one to the right.

<div>
X: <span id="X-coord"></span><br><br>
Y: <span id="Y-coord"></span>
</div>

By now all of this should make sense. It's a basic div with two spans which we will put the X and Y coordinates.

<body onMouseMove="mouser(event)">

Can you guess what that does?

If you said track the mouse when it moves by calling a user-defined function which parses the event info to readable output, you are correct.

If you did not say that. Then I'll say it again. We call upon the onMouseMove event handler. We put it in the <body> tag, because it is the scope we desired. We want to be able to move anywhere over the page and drag our object. So whenever the mouse moves on the screen, our function mouser() is called. mouser() takes an argument, event. Once again event is where the mouse action is going down, like the clicks from before.

Now lets define our mouser(event) function's code.

Place somewhere in your <head></head> tags the following code. Place is either below or above your CSS <script></script> tags, just not inside or it will not work correctly.

<head>

<script language="javascript">
var x;
var y;

function mouser(event){
x=event.clientX;
y=event.clientY;
document.getElementById('X-coord').innerHTML = x +'px';
document.getElementById('Y-coord').innerHTML = y +'px';
}
</script>

</head>

It not that much code, let's break it down.
First of course <script language="javascript"> sets our language. Enough said. Then I declare some global variables, x and y to hold the value of the coordinates. Now i define my function mouser with the event it would be taking in. The next two lines just set the values of our variables to the mouse position.

event.clientX; //event is the where the MouseMove is happening, and clientX is the just the X position relative to the screen of the cursor. Y is the same.
Then all we do is set the innerHTML of the spans to be the variable and append the letters px by doing +'px'

Step 3: Putting it all together

Click in me!
No Click Yet :(

We are getting close now. We have established our div, and we can track the cursor's position. Now we just need to click and drag it. So what event handler(s) should we be using for this? onDrag()? If it were that easy, I wouldn't have written this tutorial. What about onClick()? Sounds good right? Makes sense. I click then drag. This is wrong though. A click event is treated as a full push and pull, click and release. If you click an item and hold it, not until you release will the event trigger. Try this on the box we previously created. Click and hold, and you will notice no change until you release the button. We need to be able to press down, move, then release. That is how a drag works. So how do we set that up? Enter the heroes.

We got our handlers now, let's wrap this thing up. There are two states associated with our div. One while is it being dragged and one where it is not being dragged. So we will have to track state of our object in a variable. I also like to keep the name of the div I'm dragging in a variable, so if I wanted I could drag multiple divs and only have to write one function. Easy enough, add this to your javascript.

var being_dragged = false;
var element;

Now let's create our final div we are going to work with, adding all the necessary event handlers.

<div id="dragger" class="monkey" onMouseDown="mouse_down(event, 'dragger')" onMouseUp="mouse_up()">
MONKEY!
</div>

We create our div and assign it a class and id. We setup our event handlers for onMouseDown and onMouseUp. The functions we will define next (remember these go in the <head></head> tags). Let's first take a look at the mouse_down() function.

function mouse_down(event, ele_name) {
being_dragged = true;
element = ele_name;
document.getElementById(element).style.cursor = 'move';
}

All this function does, is after pressing down on the div, it sets our state to true. So we are now being_dragged. It also sets the element to the ele_name passed in which was 'dragger'. So element = dragger, which is our current div. The last line is just a little flavor on the end, to give us the "move" cursor when moving an item. Now lets take a look at the mouse_up() function.

function mouse_up() {
being_dragged = false;
document.getElementById(element).style.cursor = 'auto';
document.getElementById(element).style.top = y +'px';
document.getElementById(element).style.left = x +'px';
}

This function takes no arguments, because all it does is reset our state, cursor, and freeze our position. The first line resets the state. The 2nd line resets the cursor. Then the 3rd and 4th line set our position. Because the top and left attributes are defined in the style tag, you must specify .style.top to set the top of the element. So this does the following...

myPage.myElement.Y-coordinate = y;

translating to javascript it is

document.getElementById(element).style.top = y +'px';

So we set it to our Y coordinate and we must append +'px' to specify our unit of measure is pixels. The X element works the exact same way. Now one last piece of code must be changed. You need to modify the mouser(event) function from earlier. It should look like the following.

function mouser(event) {

 if(event.offsetX || event.offsetY) { //For Internet Explorer
  x=event.offsetX;
  y=event.offsetY;
 }
 else { //For FireFox
  x=event.pageX;
  y=event.pageY;
 }

  document.getElementById('X-coord').innerHTML = x +'px';
  document.getElementById('Y-coord').innerHTML = y +'px';
 if(being_dragged == true) { //
  document.getElementById(element).style.top = y +'px'; //
  document.getElementById(element).style.left = x +'px';
//
 } //

}

I have put in bold the new lines added and also put some trailing //'s so you can see what the difference is. The code being replaced is
x=event.clientX;
y=event.clientY;

with

 if(event.offsetX || event.offsetY) { //For Internet Explorer
  x=event.offsetX;
  y=event.offsetY;
 }
 else { //For FireFox
  x=event.pageX;
  y=event.pageY;
 }

event.clientX; will work fine if your page will stay in the confines of the current Resolution/Screen. So if you only want to deal with one screen, no scrolling, clienX/clientY will work fine. However, that is not always the case. Such as this page, it's pretty huge. It extends well below your resolution. So we have to keep track of where it is from the Top Left of the page, before scrolling, than after scrolling. Unfortunately Internet Explorer and FireFox handle this differently. Therefore, inorder for this to work between multiple browsers, this is the code you should use. And for the other piece of code. All it does is check to see if the state is true,

if(being_dragged == true)

then execute the move code, else it will do nothing. The other lines just set the top left corner of the object to the cursor position. This simple check works, because when you mouse down, the state is true, and when you mouse up the state is false. That's all there is to it. You should have a working draggable box now. Drag the Red Box below, so you can see all the code.

demo

Monkey! I AM IN THE WAY! YOU CAN'T SEE WHAT'S UNDER ME

Here is all the code below.

{the code}

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

.monkey {
background: #FF0000; /* red background */
width: 200px;
height: 200px;
position: absolute; /* we want to set an absolute position so the div can be moved in reference to the screen */
top: 50px; /* this sets the positioning of the element in reference to the top left of your window. it will space it 50 pixels from the top */
left: 50px; /* this will set the position of the element 50 pixels to right of the top left of your window. */
z-index: 5; /* this will position it above anything with a lower z-index, sort of like layers. So you could layer these divs using z-index and have them stack on each other. */
}

</style>
<script language="javascript">
//Draggable Div by surren @ http://www.diffusedreality.com
var x;
var y;
var element;
var being_dragged = false;
function mouser(event){
if(event.offsetX || event.offsetY) {
x=event.offsetX;
y=event.offsetY;
}
else {
x=event.pageX;
y=event.pageY;
}
document.getElementById('X').innerHTML = x +'px';
document.getElementById('Y').innerHTML = y +'px';
document.getElementById('X-coord').innerHTML = x +'px';
document.getElementById('Y-coord').innerHTML = y +'px';
if(being_dragged == true) {
document.getElementById(element).style.left = x +'px';
document.getElementById(element).style.top = y +'px';
}
}
function mouse_down(ele_name) {
being_dragged = true;
element = ele_name;
document.getElementById(element).style.cursor = 'move';
}
function mouse_up() {
being_dragged = false;
document.getElementById(element).style.top = y +'px';
document.getElementById(element).style.left = x +'px';
document.getElementById(element).style.cursor = 'auto';
}
</script>
</head>
<body class="main" onMouseMove="mouser(event);">
<div id="dragger" class="real_monkey" onMouseDown="mouse_down('dragger')" onMouseUp="mouse_up()">Monkey!</div>
</body>

Step 4: A more realistic application

Title Bar
Content Panel
Put more content here.

Now that we've gotten our basic draggable div down, you can take it, run with it and start using it. Or you can stick around and improve it a little more. Now what do I mean by improve it? Well how about adding a title bar and a content panel, and making it only draggable by the title bar. It will mimic normal window functionality like your Operating System. By now I am going to make the assumption you have a basic understand of what was done before, so we'll be moving a bit faster than before.

The building blocks.

To set this up think about the object. It is a title bar and a content panel. So it's 2 div's right? Close. 3 divs. You need one div to hold them, one div for the title, and one div for the content.

Div::Holder
Div::Title Bar

Div::Content Panel

So you need 3 div's each with a different Id. I usually use a naming convention like monkey_title, monkey_content, monkey_holder.

....work in progress. Here is my current test page.

{ Tutorial by Surren @ diffused Reality }