In this series:
1. Introduction
2. Part 1 – Portal Core Functionality
3. Part 2 – Drag and Drop Widget Personalization
4. Part 3 – Building Widget Gallery
5. Part 4 – Introduce Tabs and Users
6. Part 5 – Enhancements and Conclusion
Note: Check out the working portal at http://aspspider.info/lakkakula/local.aspx.
In my previous post I have explained how to design and re-use a widget-client-template. Also I have shown you, how to load the widget-body through declarative way of using jQuery and Microsoft Ajax. The advantage of using jQuery load method (GET) and asp.net MVC call over updatepanel/web forms is that, jQuery load method by-default uses GET method and asp.net MVC does not have viewstate, page load lifecycle and server control reconstruction overheads.
Moreover we are returning only the required html to render the widget body through a partial view unlike asp.net page. In asp.net, when you use updatepanel, even though it makes an async call to web server, entire page is posted back and all the response is sent to client and finally only the portion inside the updatepanel is re-rendered.
So our approach through jQuery load and asp.net MVC would definitely be faster and cleaner.
In this post we will examine how to provide drag and drop functionality to widgets. Drag and drop gives web pages dynamic behavior. Drag and drop is basically achieved through mousedown, mousemove and mouseup JavaScript events. There are several articles and libraries available out there on the web. You can read detailed explanation about drag and drop using plain-old javascript by Mark Kahn. Or just bing-it for Javascript Drag and Drop. Here is a list of some fo the javascript libraries: jquery, prototypejs, dojotoolkit, mootools, qooxdoo, Yahoo! User Interface Library (YUI), extjs, UIZE JavaScript Framework, openrico,mochikit, SproutCore, My Library, javascriptian’s ajax library
jQuery’s sortable found in UI library makes our life easier. Through this UI plug-in we can attach drag and drop to selected HTML element just by calling
1 $("selector").sortable();
When attached, sortable can raise 12 events: start, sort, change, beforeStop, stop, update, receive, remove, over, out, activate, deactivate. Among these; we are interested only in two events: start and stop.
As we have arranged widgets (div tags) in 3 columns. We will be hooking sortable to each column and specify that items to drag are Widgets. Let us see how to do that just right here:
1 $('.col').each(function() { 2 attachDragDrop($(this)) 3 });
Above code calls attachDragDrop($(this)) for each column in our page
1 function attachDragDrop(col) { 2 var all-cols = $('.col'); 3 $('.col').sortable({ 4 connectWith: all-cols, 5 items: '.widget:not(.ad-holder)', 6 handle: 'h2', 7 helper: 'original', 8 placeholder: 'placeholder', 9 }); 10 }
Then each column being hooked-up to sortable; is connected with all other columns; in this line
4 connectWith: all-cols,
Then we specify “items to drag” are widgets in this line
5 items: '.widget:not(.ad-holder)'
One interesting thing to note here is :not(.ad-holder). This specifies that we want to enable dragging for all widgets but not for ad-holder div. Who calls it a web portal without an ad 😉 but the idea here is to demonstrate how to make some of the widgets non-dragable.
As you could guess “handle” specifies the handle for widget. i.e., the area where user can click and start dragging on a widget. Helper specifies the element to be used while dragging. Helper accepts two values, original and clone (by default it is original). We will go with original so that we can use this element in “start” event. Finally placeholder specifies a class name which defines how to display the place-holder area when user is moving the widget.
Time to talk about sortable events: event “start” is raised as soon as user click’s on the handle element and starts dragging. We will use this event to capture original element and re-set its width and also to set the height of placeholder element. As soon as user starts moving widget, sortable changes the position of the widget’s div element on screen thus by changing its width to fill out entire screen.
Start event code:
1 start: function(e, ui) { 2 ui.helper.css("width", ui.item.parent().outerWidth()); 3 ui.placeholder.height(ui.item.height()); 4 },
To avoid this we will capture helper element and re-set its width to original. First line in above code does exactly same. Second line specifies the height of the placeholder. Now we have nice moving widget
Now that we have width problem fixed, let us move to “stop” event. We will use “stop” event to calculate new widget position, get the column where the widget is dropped and widget’s id for database update.
Stop event code:
1 stop: function(e, ui) { 2 ui.item.css({ 'width': 'auto' }); // reset widget width 3 var position = ui.item.parent().children().index(ui.item); // get position of the widget 4 var col_id = ui.item.parents('.col:first').attr('id'); // get the column element where the widget is placed 5 var widget_id = ui.item.attr('id'); //get widget id 6 updateWidgetLocation(widget_id, col_id, position); //interface to update widget location on server 7 }, 1 function updateWidgetLocation (widgetId, colId, position) { 2 //call to widget controller -> post method to update widget location 3 };
Above code is executed as soon as the user drops the widget in to new location in a column. What we do here is to get widget position, column-id and widget-id. Finally we make an ajax post call to widget controller to update the new widget location in the server.
Other widget status change events are, widget minimize, widget maximize, widget removed. These events can be directly hooked to the controls on the widget header and call appropriate action method inside widget controller to update the status in the server.
1 function removeWidget (ctrl) { 2 if (!confirm('Are you sure, you really want to remove this widget?')) return; 3 var widget = $(ctrl).parents('.widget:first'); 4 widget.slideUp('fast'); //animation before removing widget from page. 5 var remove = function() { deleteWidget(widget) }; 6 setTimeout(remove, 500); 7 //call to widget controller -> post method to update widget status 8 }; 9 10 function deleteWidget(widget) { 11 $(widget).remove(); 12 }; 13 14 this.toggleWidget = function(ctrl) { 15 var widget = $(ctrl).parents('.widget:first'); 16 widget.children('.widget-body:first').slideTogle('fast'); 17 //call to widget controller -> post method to update widget status 18 };
In this post we have seen how to provide drag and drop functionality to widgets and interfaces to save widget status on server. In my next post we will examine how to build Widget Gallery. Trust me, its going to be interesting as I will cover some CSS stuff.

Developing Web 2.0 Portal using Asp.Net MVC, Microsoft Ajax Client Templates and jQuery with drag and drop widget personalization – Part 2 « Lakkakula’s Blog…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
Trackback by DotNetShoutout — June 26, 2009 @ 7:06 pm