Experimenting with jQuery Draggables and ASP.NET
Back in the day, I needed to create a web-based Flatplan application. For those that don't know, a Flatplan is used in magazine publishing and it consists of a grid representing the pages of a magazine. Someone in the production department used to write on this using a pencil (a hollow tube of wood filled with a stick of graphite that left marks on paper) to indicate where specific advertisements of various sizes and editorial items (articles and news stories) would appear in the final printed item. An eraser was used as items were constantly moved about from page to page to accommodate the demands of advertisers booking space right up to the final minute.
The final solution was (I thought) elegant and featured various sized divs stacked on top of eachother using incrementing z-indexes, which could be dragged around the web page and left wherever the user wanted. They used AJAX (xmlhttprequest) to report their position, which was stored in a database. When the user opened the application, each of the divs "remembered" their position and took it up at start-up. The Javascript file to manage all this was several hundreds of lines long, and was the heavily customised result of a snippet I found through Googling. jQuery's UI Library would probably have made this so much easier, but it wasn't available then. So I have recently been fiddling about with the Draggables to see what they are capable of.
To make use of Draggables, you need to download the UI library and then use the ui.core and ui.draggable files along with jquery:
<script src="script/jquery-1.3.1.min.js" type="text/javascript"></script>
<script src="script/ui.core.min.js" type="text/javascript"></script>
<script src="script/ui.draggable.min.js" type="text/javascript"></script>
Now I need something to drag around the page, so I add a div:
<body>
<form id="form1" runat="server">
<div id="d1">
<p>Move This Div</p>
</div>
</form>
</body>
To make the div draggable, very few lines of javascript are needed (along with a couple of lines of CSS to add a border etc). You just need to apply draggable() to the id of the element using dot notation:
<script type="text/javascript">
$(function() {
$("#d1").draggable();
});
</script>

Clicking and dragging will allow you to move this around the browser wherever you like. When you release the mouse, the div stays where it is positioned after dragging. Actually, clicking on any part of the div will allow you to drag in FireFox, Opera and Safari. IE7 is a little different. The first drag can be made by holding down the left mouse button anywhere on the div. Once released, second and subsequent drags require that the text is clicked on. IE7 seems to need a "drag handle" of some sort after the first move. Explictly setting the bacground-color property of the div corrects this.
As the div is moved around the browser, it's position is available to the drag callback, so I've added a <table> to record this:
<table id="console">
<tr>
<td>drag x: </td>
<td><input type="text" id="x" class="console" /></td>
<td>drag y: </td>
<td><input type="text" id="y" class="console" /></td>
</tr>
</table>
A little Javascript is needed to handle the callback, so the <script> block is altered and an option applied to draggable():
<script type="text/javascript">
$(function() {
$("#d1").draggable({
drag: function(event, ui) {
$("#x").val(ui.position.left);
$("#y").val(ui.position.top);
}
});
});
</script>
Now, as the div is dragged around, the text boxes are updated to display the current position of the div:

The absolutePosition is also available, so the table is amended to add a couple of rows and the Javascript is changed to record these values as well:
<script type="text/javascript">
$(function() {
$("#d1").draggable({
drag: function(event, ui) {
$("#x").val(ui.position.left);
$("#y").val(ui.position.top);
$("#x2").val(ui.absolutePosition.left);
$("#y2").val(ui.absolutePosition.top);
}
});
});
</script>

There's a discrepancy between the two measurements. The reason for this is that position gives the position of the div relative to its starting point. absolutePosition gives the positon of the div relative to the browser window. At the moment, in IE7, the default starting position of the div is 15px down and 10px into the page. This is because, by default, IE7 applies a margin to the <body> element of the document. If this is removed - body{margin:0;} - both position and absolutePosition will be the same.

You will also notice that the div occupies a starting position tucked right up into the top and left of the browser window. As an interesting diversion, if you remove the margin:0 from the body, and try running the page in FireFox, Safari and Opera, you will see that each browser applies a different default margin to the body. This is one of the sources of problems trying to get pages to look the same in all browsers, so for that reason, one of the first things I do with any new site is to remove the margin from the body element in the site's CSS file.
Now some more changes to the Javascript:
<script type="text/javascript">
$(function() {
$("input").val(''); // Reset console values
$("#d1").draggable({
drag: function(event, ui) {
$("d1").css("opacity", "0.6"); // Semi-transparent while being dragged
},
stop: function(event, ui) {
$("#x").val(ui.absolutePosition.left);
$("#y").val(ui.absolutePosition.top);
$("d1").css("opacity", "1.0"); // Revert to fully opaque when dragging stopped
},
cursor: "move"
});
});
</script>
These changes result in the text box values being reset when the page is refreshed. That stops FireFox from holding on to the values as it does by default. Secondly, I have set the opacity of the item being dragged to 0.6 while it is being dragged, and then added a reference to the stop callback. In this, I register the position of the item once the mouse has been released from the item and reset its opacity. I also change the cursor for the item that has draggable() applied to it to the cross arrows that are familiar to users when they move stuff around Windows. The result looks like this during a drag:

And this after the drag has stopped:

Any HTML element can have draggable() applied to it. For example, here it has been applied to an img tag:

We've seen three of the options that draggable() can have applied to it: start, stop and cursor. there are many others and the full documentation is available here. If I had used jQuery for my old Flatplan application, stop is the place where I would have used AJAX to send the absolutePosition to the database so that draggable elements' positions could be persisted.
Currently rated 3.50 by 6 people
Rate Now!
Date Posted:
01 February 2009 08:12
Last Updated:
31 March 2009 19:55
Posted by:
Mikesdotnetting
Total Views to date:
14022
Printer Friendly Version
Comments
04 February 2009 22:32 from Mikesdotnetting
@Jim: I've managed to put a short piece together that answers your question: http://www.mikesdotnetting.com/Article/101/Persisting-the-position-of-jQuery-Draggables-in-ASP.NET
24 March 2009 14:27 from Dan Sylvester
Mike another great example. Thanks.
Jquery is fun.
31 March 2009 11:02 from Brian
Really bugs me the blurring of ajax and non-ajax. Drag and drop is not ajax never mind a keystone.
31 March 2009 11:56 from Mikesdotnetting
@"Brian"
It bugs me a little too. As you allude to - DHTML is not AJAX. Now show me where in this article I have claimed that Drag and Drop is AJAX...
Really bugs me that people spout off without actually reading something carefully.
31 March 2009 12:37 from Andrew
Oh come on, your first line is....
"One of the keystones of modern AJAX-enabled web sites is
Drag and Drop"
I'd say Brian had read your article carefully!
31 March 2009 17:25 from Sam
Missing from this article seems to be any relevance to the ASP.Net platform. Nice script but no asp.net here... drop the "and ASP.NET" part from the article title. Casually mentioning that you once used drag and drop on an old asp.net application doesn't really qualify.
31 March 2009 19:46 from Mikesdotnetting
@Andrew
How does that equate to "Drag and Drop is AJAX"? All it says is that Drag and Drop often features on sites that are Ajax-enabled. The article even mentions specific instances where Ajax can be used with draggables - thus drawing an inherent distinction between them.
31 March 2009 19:58 from Mikesdotnetting
@Sam
Fair point. My intention was to show how easy it is to use jQuery for draggables in an ASP.NET web form. That wasn't clear at the time you commented. I have added a bit to the first part of the code to show this now. If you have any other suggestions for improvement, I'm all ears.
03 April 2009 12:58 from Doug
Great job on getting started with jQuery drag and drop. Its articles and blogs like these that I can send to co-workers to get them excited and using modern web development techniques.
31 August 2009 14:16 from Dam
Hi there !
Thanks for this article, it is very useful. As I can see, you manipulate the positions with the ui object provided by the drag, start and stop functions. But what if you want to know the position outside of these functions ?
Thanks,
Dam.
02 September 2009 07:26 from Mikesdotnetting
@Dam
There's nothing to stop you using the same mechanism to obtain the coordinates outside of the drag, start or stop events.



02 February 2009 21:29 from Jim
If I had users log in to their "home" page, and they could customize their page by dragging the divs wherever they wanted, what method would I use to track the position so they remain in the adjusted spot on the screen when they log in next time?
Thank you.