If you are creating a web application and you need to have the ability to schedule resources (people, machines, Precious Moments figurines, etc) it can sometimes be a cumbersome task. With this drag and drop schedule you won’t have to worry about the end user making typos in an html form and causing more trouble for you later.
Let’s start off by putting the obvious header information along with some javascript variables that we will use later:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html>
<head>
<title>Test Schedule</title>
<script>
var moving_object = “”;
var mX, mY, devX, devY;
var set_to_grid = true;
var lock_x_axis = false;
var lock_y_axis = false;
var gridX = 10;
var gridY = 10;
Next, while still in the script tag we need a function that will keep track of our mouse movements so that we know when the user is dragging an object.
This function will also be responsible for moving the floating schedule objects and should be able to restrict the movement of the floating objects so that they only move horizontally or vertically (depending on your schedule type).
Another nice feature would be to lock the floater to an invisible grid so that placing your object in the correct spot is easier.
function setCoords( e )
{
if( document.all )
{
mX = event.clientX;
mY = event.clientY;
}
else
{
mX = e.pageX;
mY = e.pageY;
}
if( moving_object )
{
if( moving_object != “” )
{
if( set_to_grid )
{
useY = parseInt( (mY – devY) / gridY) * gridY;
useX = parseInt( (mX – devX) / gridX) * gridX;
}
else
{
useY = mY – devY;
useX = mX – devX;
}
if( lock_y_axis == false )
{
document.getElementById(moving_object).style.top = useY + “px”;
}if( lock_x_axis == false )
{
document.getElementById(moving_object).style.left = useX + “px”;
}
}
}
}
We also need a function that is called when we click on the floating object that tells the setCoords() function some basic information, like which object is moving and if it should lock the movement in any way.
This function should also bring the floating object above the rest of the objects on the page.
function setMover( object_id , lock_y, lock_x, use_grid )
{
moving_object = object_id;
set_to_grid = use_grid;
lock_x_axis = lock_x;
lock_y_axis = lock_y;if( object_id != “” )
{
devY = mY – parseInt( document.getElementById( moving_object ).style.top );
devX = mX – parseInt( document.getElementById( moving_object ).style.left );
document.getElementById( moving_object ).style.zIndex=99;
}
}
Lastly, we need a function that is called when the user “let’s go” of the floating (i.e. they dropped it). This function basically undoes everything that setMover() does and moves the floating object back down with the rest of the objects.
If you want to get really fancy you can update a database from this function, which comes in handy if you want to automatically save the new position of your floater. To do this just create an invisible iframe document with a form in it. Update the form from within this function and use the form’s submit() function to send the new coordinates to the database.
function unSetMover( object_id )
{
moving_object = “”;
lock_x_axis = false;
lock_y_axis = false;
if( object_id != “” )
{
document.getElementById( object_id ).style.zIndex=10;
}
//Something like this might help you update the database:
//frames['hidden_iframe'].document.editform.x_coord.value = mX;
//frames['hidden_iframe'].document.editform.y_coord.value = mY;
//frames['hidden_iframe'].document.editform.submit();
}
</script>
</head>
The next thing our page needs is some style. We need a class for our floater objects, for consistancy. Most of this is just fluff, the ‘position’ is the only essential part.
<style>
.floater
{
z-index: 10;
text-align: center;
position: absolute;
border: thin solid black;
}

It would be nice if our ‘floater’ class did something to highlight itself when the mouse was floating over it. It would also be nice if it became semi-transparent while it was moving over the other objects so we could see what was underneath it. (This is all fluff…you can leave this out if you want to)
.floater:hover
{
opacity: .75;
filter: alpha( opacity = 75 );
border: thin dashed blue;
}
The last part of the style is just to setup the background and x/y axis so that it resembles a schedule.
body
{
background-image: url(‘images/background_time_grid.gif’);
}.axis-background, .row-background
{
opacity: .35;
filter: alpha(opacity=35);
position: absolute;
}
.axis-background
{
background-color: #aaaadd;
}
.row-background
{
background-color: #ddddaa;
}
.axis-label
{
background-color: #ffffee;
position: absolute;
text-align: center;
font-size: 90%;
border: thin solid black;
}
</style>
When declaring the ‘body’ element we need to make sure that it runs the setCoords() function each time the mouse moves, so we will know where the pointer is if we are moving an floating object.
<body onMouseMove=”setCoords(event);”>
Next, we are going to create a nice background for our x and y axis.
<div class=”axis-background” style=”top: 0px; left: 0px; height: 50px; width: 100%;”> </div>
<div class=”axis-background” style=”top: 50px; left: 0px; height: 100%; width: 100px;”> </div>
Now let’s put some times along the top of the page on the x-axis. You’ll probably want generate these out of a database, but to show you how it is done we will just use static html.
<div class=”axis-label” style=”top: 5px; left: 70px; width: 60px;”>8:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 170px; width: 60px;”>9:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 270px; width: 60px;”>10:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 370px; width: 60px;”>11:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 470px; width: 60px;”>12:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 570px; width: 60px;”>1:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 670px; width: 60px;”>2:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 770px; width: 60px;”>3:00AM</div>
<div class=”axis-label” style=”top: 5px; left: 870px; width: 60px;”>4:00AM</div>
We need to create the y-axis labels now. Again, you’ll probably generate these values from a database but for our example we’ll just use assume we are scheduling “work stations”.
<div class=”axis-label” style=”top: 60px; left: 5px; width: 90px;”>Work Station 1</div>
<div class=”row-background” style=”top: 160px; left: 100px; height: 100px; width: 100%;”> </div>
<div class=”axis-label” style=”top: 160px; left: 5px; width: 90px;”>Work Station 2</div>
<div class=”axis-label” style=”top: 260px; left: 5px; width: 90px;”>Work Station 3</div>
<div class=”row-background” style=”top: 360px; left: 100px; height: 100px; width: 100%;”> </div>
<div class=”axis-label” style=”top: 360px; left: 5px; width: 90px;”>Work Station 4</div>
Finally (at last!) we can create the actual floating objects. We are going to make these all a different color (and all pastel at that). These you would definitely want to generate from a database…else the purpose of this article is probably lost on you. Our object needs to run the setMover() function when it is clicked and it needs to run the unSetMover() function when that click is released (when it is ‘dropped’). If you are scheduling people you can even put a thumbnail image in these floaters so that the end user will really feel at home–pushing around his/her co-workers.
You’ll notice that the third floater does not restrict the movement at all, the user can move it up, down, left and right. This should give you an idea of how movements can be done.
<div id=”floater1″ class=”floater” style=”background-color:#cccccc; top: 50px; left: 100px; width: 100px” onmousedown=” setMover( ‘floater1′, true, false, true );” onmouseup=” unSetMover( ‘floater1′ );” >Order 1991-01A<br /><hr><small>Shearer, Grant</small></div>
<div id=”floater2″ class=”floater” style=”background-color:#ffccff; top: 50px; left: 200px; width: 80px” onmousedown=” setMover( ‘floater2′, true, false, true );” onmouseup=” unSetMover( ‘floater2′ );” >Order 2491-01A<br /><hr><small>Dummy, Test</small></div>
<div id=”floater3″ class=”floater” style=”background-color:#ccccff; top: 50px; left: 280px; width: 120px” onmousedown=” setMover( ‘floater3′, false, false, false );” onmouseup=” unSetMover( ‘floater3′ );” >Order 1431-01A<br /><hr><small>Smith, Bob</small></div>
<div id=”floater4″ class=”floater” style=”background-color:#ccffcc; top: 50px; left: 400px; width: 70px” onmousedown=” setMover( ‘floater4′, true, false, true );” onmouseup=” unSetMover( ‘floater4′ );” >Order 2236-09A<br /><hr><small>Springer, Jerry</small></div>
<div id=”floater5″ class=”floater” style=”background-color:#ffcccc; top: 50px; left: 470px; width: 110px” onmousedown=” setMover( ‘floater5′, true, false, true );” onmouseup=” unSetMover( ‘floater5′ );” >Order 3507-00<br /><hr><small>Simpleton Sr, Gary</small></div>
<div id=”floater6″ class=”floater” style=”background-color:#ffffcc; top: 50px; left: 580px; width: 170px” onmousedown=” setMover( ‘floater6′, true, false, true );” onmouseup=” unSetMover( ‘floater6′ );” >Order 3567-00<br /><hr><small>Simpleton Jr, Gary</small></div>
<div id=”floater7″ class=”floater” style=”background-color:#ccffff; top: 50px; left: 750px; width: 90px” onmousedown=” setMover( ‘floater7′, true, false, true );” onmouseup=” unSetMover( ‘floater7′ );” >Order 3337-00<br /><hr><small>Jingleheimer, Jerry</small></div>
<div id=”floater8″ class=”floater” style=”background-color:#ffcccc; top: 150px; left: 100px; width: 110px” onmousedown=” setMover( ‘floater8′, true, false, true );” onmouseup=” unSetMover( ‘floater8′ );” >Order 5507-00<br /><hr><small>Simpleton Sr, Gary</small></div>
<div id=”floater9″ class=”floater” style=”background-color:#ffffcc; top: 150px; left: 210px; width: 170px” onmousedown=” setMover( ‘floater9′, true, false, true );” onmouseup=” unSetMover( ‘floater9′ );” >Order 8456-00<br /><hr><small>Simpleton Jr, Gary</small></div>
<div id=”floater10″ class=”floater” style=”background-color:#ccffff; top: 150px; left: 380px; width: 90px” onmousedown=” setMover( ‘floater10′, true, false, true );” onmouseup=” unSetMover( ‘floater10′ );” >Order 4321-00<br /><hr><small>Jingleheimer, Jerry</small></div>
The ending. The iframe and it’s contents are only needed if you plan on updating your database every time the user “drops” one of the floating objects.
<iframe name=”hidden_iframe” style=”visibility: hidden;”>
<form name=”editform” method=”post” action=”myupdatepage.php”>
<input type=”hidden” name=”x_coord” />
<input type=”hidden” name=”y_coord” />
</form>
</iframe>
</body>
</html>
(To use the code, just click on “See it in action” and save the page from there)
Some of the css used in the code above does not work in all browsers. The opacity property, for instance, does not appear to work in Internet Explorer. YMMV.


9 responses so far ↓
1 techrageo.us links » Blog Archive » Drag and Drop Schedule For Web Apps // Sep 8, 2005 at 2:21 am
[...] http://techrageo.us/2005/08/09/creating-a-drag-and-drop-schedule-for-your-web-application/ creating a drag and drop schedule for web applications [...]
2 Kate // Jan 14, 2008 at 4:08 pm
In IE7 and Firefox, I cannot move the boxes along the vertical axis. I have looked at the code and I don’t see that either axis is locked. Help!
3 Grant // Jan 14, 2008 at 11:12 pm
Kate,
The application was designed to be “locked” along the Y-axis…so you shouldn’t be able to move the boxes up and down. The exception to this is the “Order 1431-01A” box, which you can move all over the place. This one has the “lock_y” argument set to “false” when “setMover” is called in it’s onmousedown.
Hopefully that helps a little bit,
Grant
4 Rick // Mar 13, 2009 at 2:11 pm
Not a javascript programmer (php) – I would love to know how to get the iframe javascript working – as it is above nothing happens – maybe I’m missing something?
Can you give a working example showing an alert box or some such thing?
Thanks for the nice example -
-Rick Mills
5 Jason Roberts // Mar 20, 2009 at 6:00 pm
Rick, the iframe portion allows you to save the data to a DB. In this example the fom action file is myupdatepage.php Create a php file with name myupdatepage.php The data to be saved are object_id, x_coord and y_coord. Since you claim to be a php programmer you should be familiar with and should be able to process data from a form
6 Rick // Apr 28, 2009 at 9:51 am
Thanks, Jason – The problem I was encountering was getting the data back and forth from js to php – finally figured out the proper way to do that.
Very nice example, again, and will be used in a sheet-metal scheduling applet where I work.
-Rick
7 Adam // May 7, 2009 at 9:02 am
“finally figured out the proper way to do that”
Please do tell!
8 Maheep // Jul 26, 2009 at 2:43 am
Could you please let me know what should i do to make the form working.
9 Maheep // Jul 31, 2009 at 9:18 am
Any one who can help me to save the updated to database.
Leave a Comment