Ever been on a website 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.

Introduction:

Ever been on a website 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, MS AJAX Library is not developer friendly meaning it is darn complicated to use. So, if you are looking for some head banging sure dive into MS AJAX but if you are interested in a simple 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 also is a very complicated and time consuming approach. If you are interested in using only JavaScript then check out the article below:

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, the 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 animation shown below:


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:

 

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 and fill it up with the data from the 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 straight forward. Check out the code below:

<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 screen shot:

 

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

<%# 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 “block”. Let’s take a look at all the styles in the next section.

CSS Styles:

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

.block {
   border: 2px solid #0090DF;
   background-color: #68BFEF;
   width: 200px;
   height: 200px;
   margin: 10px;
   overflow:auto;
   padding:1em 1em 1em 1em;
   z-index:9999;
   cursor:move;
}

The block style is used for all the draggable items.

.roomItem {
   border: 2px solid #0090DF;
   background-color: yellow;  
}

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

.drop {
 background-color: #e9b96e;
 border: 3px double #c17d11;
   width: 300px;
   height: 300px;
   margin: 10px;
   overflow:auto;
   position:absolute;
  top: 5px;
  right: 10%;
  padding: 1em 0 0 0; 
}

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.

$(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 to 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 action on the draggable item. We are using the ‘clone’ helper which will create a clone for our draggable item.

$(".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 “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.

// 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 which is used to remove the items from the drop zone (Basically remove link is used to remove the users from the room).

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 which in this case is the username of the user.

$(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 screen shot below which shows the item added to the drop zone.


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

Ajax Methods:

I have used MS ASP.NET AJAX to create asynchronous calls to the web service methods. Let’s take a look at these methods:

[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 which is used to create data access operations on objects. You can use DataSets, Entity classes, Managers, Repositories and Mappers to perform the data access operations. If you are interested in the MethodInvoker class then take a look at the following 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 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.

 <Triggers>
     <asp:AsyncPostBackTrigger ControlID="timer1" EventName="Tick" />
     </Triggers>

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

<asp:Timer ID="timer1" runat="server" Interval="5000" ontick="timer1_Tick" />

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

  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 the you won't be able to drag and drop your objects.

The reason is that when you updated the screen using the UpdatePanel it resetted 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:

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 loose 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 JQuery UI API. I hope you liked this article, happy coding!

[Download]