Blog Post

Drop it Like its Windows - Drag and Drop on the Web

Drag what on my Web Page?

Drag and drop has been prevalent in Windows Forms but not so much in ASP.NET. To bridge that disparity, Microsoft is working on a Drag and Drop framework built into ASP.NET AJAX Framework. Leveraging this evolving tool, I am going to show how you how we can incorporate drag and drop functionality into an ASP.NET page, specifically one that uses Infragistics controls.

Intro to Drag and Drop

To begin, we should familiarize ourselves with the basic usage of this framework. Jeff Prosise wrote a great article on MSDN that explains how to use this framework between several div elements. Going through this article should give you the basics on setting up your page for drag and drop.  Please make sure you understand the concepts, such as DragDropManager, IDragSource, and IDropTarget, illustrated in the above article as I do not go over them in this post.

Drag and Drop from UltraWebTree to WebDayView

So, just setting an UltraWebTree as a drag source and an WebDayView as a drop target should be all you would have to do. Not quite, due to the wealth of information stored in various elements in each of these controls, we have to set up each element that contains relevant information as a drag source and each specific region that can accept a drop as a drop target. The elements you are setting as sources and targets will always change depending on the control you are interfacing with, but the process by which you identify these elements should be relatively similar.  Essentially, if it matters where on the control you drag from or drop to, you have to set up each element in that control separately.

Note: We could just set the UltraWebTree as a single drag source and the WebDayView as a single drop target using logic built off the elementFromPoint method, but due to Firefox 2 not having such a method ( exists in Firefox 3), such an implementation would work only in IE and Safari. Based off the cursor position, this method would be used to figure out which specific element you are over inside of each control, removing the need to set up each applicable element as a source/target.

One way to obtain the element directly under the cursor if you were to register the entire controls as a target/source:

//obtains the element that the mouse is currently over   

var visual=document.elementFromPoint(window._event.clientX,window._event.clientY);

//when dragging, the visual will be directly under the cursor

//so we have to hide the visual first

visual.style.display='none';

//call the method again to obtain the element that was under the visual

var actual=document.elementFromPoint(window._event.clientX,window._event.clientY);

Drag Source Elements in an UltraWebTree

To set up certain elements as Drag Sources, we are going to use the Client Side Object Model to filter the nodes that can be dragged. For this example, we are only going to allow the first set of children under the root nodes to be a drag source. For each of these node objects, we call the getElement method to obtain the HTML element associated with that object. We then pass each of these elements into the constructor for the drag source with additional information to aid in obtaining this object later in the drop event of the target.

Code for setting each applicable child element of the UltraWebTree as a drag source:

//obtains the id rendered on the client for the UltraWebTree

var treeId='<%= UltraWebTree1.ClientID %>';

//gets the tree object using the tree utility function

var tree=igtree_getTreeById(treeId);

//gets the first level of nodes

var firstlevel=tree.getNodes();

var children;

var source;

//loops through all the first level nodes

for(var i=0;i<firstlevel.length;i++)

{

    //gets the children of each first level node

    children=firstlevel[ i].getChildNodes(); 

    //loops through all the children on the current first level node being examined 

    for(var j=0;j<children.length;j++)

    {

        //for each node, we obtain the equivalent html element then obtain the SPAN element that context the text

        var element=getElementsByAttribute(children[j].getElement(),'SPAN','igtxt','1')[0];

        //initializes the drag source with the constructor

        source=new IG.UI.AppointmentInfoDragSourceBehavior(element,children[j].Id);

        source.initialize();

    }

}

 

Drop Target Elements in a WebDayView

Getting each individual time slot in the WebDayView is not as simple as the previous implementation for the tree. By examining the elements that make up the control using the IE Developer Toolbar, you can see that there is an attribute applied to each of these time slots called ‘uie’ and has a value of SLOT before the identification number. The ‘uie’ attribute is actually used extensively through all the WebSchedule views and its various elements that make up the entire control.

IE Developer Toolbar being used to investigate elements of the WebDayView:

dayviewuie

Knowing this information, I found a "getElementsByAttribute" function online that would return these elements based on those criteria of an element that has an attribute of ‘uie’ and the value of that attribute starting with ‘SLOT’. Since the original version checked for an exact match and not a ‘starts with’ condition, I added an extra boolean parameter to modify the regular expression used.

Code for setting each applicable child element of the WebDayView as a drop target:

//obtains the id rendered on the client for the WebDayView

var dayId='<%= WebDayView1.ClientID %>';

//gets every TD element from the dayview tree that

//has an attribute of uie that has a value starting with 'SLOT'

var elemArray = getElementsByAttribute($get(dayId),'TD','uie','SLOT');

var target;

//loops through retrieved elements and initializes each as a drop target

for (var i=0; i<elemArray.length; i++)

{  

    target=new IG.UI.AppointmentInfoDropTargetBehavior(elemArray[ i],"Day",dayId);

    target.initialize();

}

Making the Two Play Nice with the Framework and Each Other

With the sources and targets set up, they now have to interact correctly in a drag drop operation. The first thing we should look at is the data being transferred. I could have passed the node’s text as the data in the drag drop operation, but what if I also wanted the node’s key data or text of the child nodes of the source node. To allow for such conditions I passed the actual id of the node so that the node object and its members would be available to me in the drop portion of the operation.

Using the UltraWebTree's utility function to obtain the node from the id passed through the data context in the drop event:

newact.setSubject(igtree_getNodeById(data).getText());

On the WebDayView side of things, the time slot elements do not have an id associated with them. With no id to use with our utility functions, you could not work with the information you obtain from these time slots. To remedy this, we passed in the id of the parent control in addition to another string which identifies what type of view the element belongs to.

Obtains the WebDayView and WebScheduleInfo objects in order to create an activity and configure it based on source and target information:

//gets the number after the string 'SLOT' on the uie attribute

var slotnum=parseInt(this.get_element().attributes['uie'].value.replace("SLOT",""));

//gets the dayview object from the id that was passed in through the constructor

var dayview=ig_getWebDayViewById(this._parentControlID) ;

//gets the info object

info=dayview.getWebScheduleInfo();

var interval=dayview.getTimeSlotInterval();

//gets the activities collection and creates an activity

var activities = info.getActivities();

newact=activities.createActivity();

//set the appropriate time information based on the slotnum and interval

var newDate=newact.getStartDateTime();               

newDate.setHours(slotnum*interval/60);

newDate.setMinutes(slotnum*interval%60);

newDate.setFullYear(currentDay.getFullYear());

newDate.setMonth(currentDay.getMonth());

newDate.setDate(currentDay.getDate());

newact.setDuration(interval);

Going Further

Once we have everything connected, we can write the code in the drop event to do whatever operation we wanted to speed up. This specific case was to create appointments faster based on nodes in a tree. To do this, we use the slot # of the WebDayView element, translate that to a time, and set that time on a new appointment. In addition, we pull information from the node and set it as the subject of the appointment as well. Finally, we show the appointment dialog with the information we just set. We now have a drag and drop operation that removes several steps in the creation of a new appointment.

Drag and Drop in action:

Drag Drop Operation

Appointment Dialog Popup after Drop Operation:

Appointment Dialog after Drop Operation

Note: In the sample that is available at the bottom, I also added logic for the WebWeekView and the WebMonthView as well.  I employed the same strategies to obtain the appropriate elements to set as drop targets.

What Now?

Use it of course. Before you stop reading and work on your own implementation, there are some things you want to take into consideration. This is a preview and not in the core framework. I did run into some long running script issues. It may have to do with my implementation or simply the amount of sources and targets that I have. I am not sure as of now since I did not have a chance to look at the underlying source. However, it is a powerful tool and adds an element of coolness to your application in addition to enhanced productivity. Also, this is not the only way to implement drag and drop. One other alternative is the Infragistics drag and drop framework which is available for sampling in the July 2008 Akido Community Tech Preview. I did some preliminary work with our framework and did not seem to have the long running script issues. Look for an article on that implementation in the future…

Sample uses the following:

-Infragistics NetAdvantage 2008 Volume 2 CLR 3.5

-Visual Studio 2008

Minimum requirements:

-Infragistics NetAdvantage 2007 Volume 1

-Visual Studio 2005 with ASP.NET AJAX 1.0 or Visual Studio 2008

Get Sample here.


Posted 08-08-2008 4:40 PM by [Infragistics] Sung Kim
Filed under:

Add a Comment


Sign in to post a comment.