Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Drag and Drop with Persistence using JQuery

4.41/5 (28 votes)
8 Mar 2008CPOL7 min read 1   6.3K  
How to create a drag and drop functionality to add users to a room

Introduction

Ever been on a Web site that shows off the drag and drop operation? Maybe it allows you to drag and drop the product into a shopping cart. Most of us have been there and were really impressed with the feature. In this article, we will focus on how to create a similar drag and drop functionality to add users to a room.

Why JQuery?

Why indeed? There are several drag and drop libraries available for free. Take Microsoft ASP.NET Ajax, for example. Unfortunately, the Microsoft Ajax Library is not developer friendly, meaning it is darn complicated to use. So, if you are looking for some head-banging, be sure to dive into Microsoft Ajax. However, if you are interested in a simple and powerful approach, then JQuery is your friend.

Some of you might be thinking, "Why not simply write plain old vanilla JavaScript?" Well, off course you can, but that is also a very complicated and time-consuming approach. If you are interested in using only JavaScript, then check out the article, "Browser Compatible Drag and Drop Shopping Cart".

Downloading JQuery and UI API

Before we implement anything, we need to download the JQuery library and the JQuery drag and drop UI API. Check out the following links for download:

  1. JQuery Library
  2. JQuery Drag and Drop UI API

Scenario

The scenario is a little different from the shopping cart basket. In this application, we are going to drag and drop the users to a room. Once a user is inserted into the room, an entry is written to the database. We can also delete the user from the room. In that case, the entry is deleted from the database. Check out the GIF using the link, "Drag and Drop With Persistence Using JQuery".

Database

There is one table, tblRoomSessions, that will hold the information about the user and the room. The diagram of the tblRoomSessions table is shown below:

gridviewguy_jquerydd1.JPG

The table script is included with the download.

Populating the Students List

There are multiple ways of populating the student DataList control. You can use a simple DataSet container, fill it up with the data from tblRoomSession and assign it to the DataList control. I have used a different approach, but it really does not matter how you populate the DataList.

Student DataList Control ASPX Code

The ASPX code for the DataList control is pretty straightforward. Check out the code below:

ASP.NET
<asp:DataList ID="dlRooms" EnableViewState="false" runat="server" RepeatColumns="3"
            RepeatDirection="Horizontal">
    <ItemTemplate>

    <div id="div1" class="block">

    <div style="text-align:center; font-size:18px; border:solid 1px">

        <%# Container.ItemIndex + 1 %></div><li id="username" runat="server">
    <%# Eval("UserName") %></li><li id="roomId" runat="server" style="visibility:hidden">

    <%# Eval("RoomID") %></li><li>
    <%# Eval("Subject") %></li><li>
    <%# Eval("Description") %></li></div></ItemTemplate></asp:DataList>

When the DataList is populated, it will look something like the following screenshot:

gridviewguy_jqimage1.JPG

The numbers indicate the order in which students requested the room. This means that the student with number 1 requested the room before the student with number 2. The numbers are generated using the following statement:

ASP.NET
<%# Container.ItemIndex + 1 %>

You will also notice that the <LI> with an ID equal to roomId is marked as hidden. You don't need to embed the roomId with every <LI>, as you will know the roomId before you will reach this page. The <DIV> element, which contains all the <LI>, has a class called block. Let's take a look at all the styles in the next section.

CSS Styles

There are several CSS styles used in this application. Let’s take a look at a few of them.

CSS
.block {
   border<span class="code-none">: 2px solid #0090DF<span class="code-none">;
   background-color<span class="code-none">: #68BFEF<span class="code-none">;
   width<span class="code-none">: 200px<span class="code-none">;
   height<span class="code-none">: 200px<span class="code-none">;
   margin<span class="code-none">: 10px<span class="code-none">;
   overflow<span class="code-none">:auto<span class="code-none">;
   padding<span class="code-none">:1em 1em 1em 1em<span class="code-none">;
   z-index<span class="code-none">:9999<span class="code-none">;
   cursor<span class="code-none">:move<span class="code-none">;
<span class="code-none">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>

The block style is used for all of the draggable items.

CSS
.roomItem {
   border<span class="code-none">: 2px solid #0090DF<span class="code-none">;
   background-color<span class="code-none">: yellow<span class="code-none">;
<span class="code-none">}</span></span></span></span></span>

The roomItem style is used for the items that are inserted into the room.

CSS
.drop {
 background-color<span class="code-none">: #e9b96e<span class="code-none">;
 border<span class="code-none">: 3px double #c17d11<span class="code-none">;
   width<span class="code-none">: 300px<span class="code-none">;
   height<span class="code-none">: 300px<span class="code-none">;
   margin<span class="code-none">: 10px<span class="code-none">;
   overflow<span class="code-none">:auto<span class="code-none">;
   position<span class="code-none">:absolute<span class="code-none">;
  top<span class="code-none">: 5px<span class="code-none">;
  right<span class="code-none">: 10%<span class="code-none">;
  padding<span class="code-none">: 1em 0 0 0<span class="code-none">;
<span class="code-none">}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>

The drop style is used for the drop zone <DIV> element which, in this case, is a room.

Making Items Draggable and Droppable using JQuery

Let me first post the complete code and then I will explain the code in segments.

JavaScript
$(document).ready(function(){

    $(".block").draggable({helper:'clone'});

    $(".drop").droppable({
 accept: ".block",
 activeClass: 'droppable-active',
 hoverClass: 'droppable-hover',
 drop: function(ev, ui) {

 $(ui.draggable).addClass("roomItem");

 var lid = ($(ui.draggable).children("li:first"));

 // gets the username
 var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
 var roomId = $(ui.draggable).children("li:eq(1)").text();

 var removeLink = document.createElement("a");
 removeLink.innerHTML = "remove";
 removeLink.href = "#";
 removeLink.onclick = function()
 {
      $("#drop1").children().remove("#"+lid[0].id);
      $(this).remove();
      // removes the class
      $(ui.draggable).removeClass("roomItem");
      // adds the new class
      $(ui.draggable).addClass("block");

      // remove the user session from the database
      VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
          username,Number(roomId));
 }

 $(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
 $(this).append(removeLink);

 // add user to the room
 VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));

 }
});

  });

Seems complicated! Don't worry; it is not that hard to understand. Let's start with the document.ready function, which is fired when the DOM (Document Object Model) is ready and loaded.

To make the element draggable, all you need to do is use the draggable function provided in the JQuery UI API. The function can take different arguments, but we used the name of the class, which in this case is .block. This means, "Make all the elements draggable whose class is .block." The draggable function also takes in the helper. Helpers are used to perform actions on the draggable item. We are using the clone helper, which will create a clone for our draggable item.

JavaScript
$(".block").draggable({helper:'clone'});

The same technique is used for creating the drop zone. When the item is dropped inside the drop zone, a class called roomItem is attached to the item. This applies the yellow background to the item, which indicates that the item has been dropped into the drop zone. Then we use the following code to extract the username and the roomId from the <LI> items contained inside the draggable <DIV> element.

JavaScript
// gets the username
 var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
 var roomId = $(ui.draggable).children("li:eq(1)").text();

A new hyperlink element is created that is used to remove the items from the drop zone. Basically, the remove link is used to remove the users from the room.

JavaScript
var removeLink = document.createElement("a");
 removeLink.innerHTML = "remove";
 removeLink.href = "#";
 removeLink.onclick = function()
 {
      $("#drop1").children().remove("#"+lid[0].id);
      $(this).remove();
      // removes the class
      $(ui.draggable).removeClass("roomItem");
      // adds the new class
      $(ui.draggable).addClass("block");

      // remove the user session from the database
      VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
          username,Number(roomId));
 }

When the item is removed from the drop zone, it is returned back to its original class, which is block. The server-side removeUserFromRoom method is fired, which removes the item from the database. We will take a look at this method later in this article. When we drag and drop the item into the drop zone, we append the first <LI> element into the drop zone. In this case, that is the username of the user.

JavaScript
$(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
 $(this).append(removeLink);

 // add user to the room
 VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));

Check out the screenshot below, which shows the item added to the drop zone.

gridviewguy_jqimage2.JPG

Finally, the addUserToRoom method is fired and adds the user to the room.

Ajax Methods

I have used Microsoft ASP.NET Ajax to create asynchronous calls to the Web service methods. Let's take a look at these methods:

C#
[WebMethod]
        public bool removeUserFromRoom(string username, int roomId)
        {
            MethodInvoker.Invoke<SQLDataAccess>("RemoveUserFromRoom", new object[]
            {
                username.Trim(), roomId
            });

            return false;
        }

        [WebMethod]
        public bool addUserToRoom(string username, int roomId)
        {
            try
            {
                MethodInvoker.Invoke<SQLDataAccess>(
                    typeof(tblRoomSession), "AddAndPersistAll",
                    new object[]
                    {
                        new tblRoomSession()
                        {
                            Guid = Guid.NewGuid().ToString(), RoomID = roomId,
                            StudentUserName = username.Trim(),
                            TutorUserName = User.Identity.Name, IsSessionStarted = true,
                            SessionStartDate = DateTime.Now
                        }
                    });
            }
            catch (Exception ex)
            {
                string exception = ex.Message;
            }

            return false;
        }

Don't pay that much attention to the MethodInvoker class. This is a custom class that is used to create data access operations on objects. You can use DataSets, Entity classes, Managers, Repositorys and Mappers to perform the data access operations. If you are interested in the MethodInvoker class, then take a look at the blog post, "MethodInvoker".

Additional Features

There are several additional features that need to be implemented for this application. Some of them are listed below:

  1. A timer that will asynchronously fetch the users waiting for the room without refreshing the page.
  2. Not allowing duplicate users to be added to the same room.

Update

When this was published, we talked about few additional features that might be useful. Some of them are shown above under the "Additional Features" section. Here is the implementation of both the features.

First, let's see how we can update the interface when a new user enters the waiting list. This process should be done asynchronously which means that the screen should not refresh on the server side but on the client side. As it turns out, this can easily be accomplished by using the ASP.NET Timer control. The Timer control will fire an event which will fire a method on the server side. First you will need to add the Triggers section inside the UpdatePanel control.

C#
<triggers>
    <asyncpostbacktrigger eventname="Tick" controlid="timer1">
    </triggers>

Now, let's see the Timer control which is also contained inside the UpdatePanel control.

C#
<timer id="timer1" ontick="timer1_Tick" interval="5000" runat="server" />

The Timer control will fire the timer1_Tick event every 5 seconds. Now, let's take a look at the timer1_Tick event:

C#
protected void timer1_Tick(object sender, EventArgs e)
      {
          BindData();
          up1.Update();        }

That was simple! The timer1_Tick event simply fetches the data from the database using the BindData method and then refreshes the UpdatePanel to update the user interface. Everything works great..... for 5 seconds. After 5 seconds, you won't be able to drag and drop your objects.

The reason is that when you updated the screen using the UpdatePanel, it reset all the controls inside it. Now, you can see the controls but they don't have any functionality. There is an easy way to fix this problem. All you need to do is to make the elements draggable once again. Check out the implementation below:

C#
protected void timer1_Tick(object sender, EventArgs e)
        {
            BindData();
            up1.Update();

            RegisterDragAndDropScript();
        }

        // this method is fired to register the scripts again 
        // since the timer will refresh the contents of the
        // update panel and hence the HTML controls will lose 
        // the drag and drop capability
        private void RegisterDragAndDropScript()
        {
            string script = "makeElementsDraggableAndDroppable();";

            ScriptManager.RegisterClientScriptBlock(this,this.GetType(),
                "DragAndDropScript", script, true);

        }

Now, when the UpdatePanel is refreshed, the controls are again made draggable.

Conclusion

In this article, we learned how to create a drag and drop UI using JQuery and the JQuery UI API. I hope you liked this article; happy coding!

History

  • 5 March, 2008 -- Original version posted
  • 7 March, 2008 -- Article updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)