Here is the first version of the TFRPortal, it is still in beta but I figured I'd upload it anyways.
What I have done is create css friendly web parts with drag and drop support. The task of creating drag and drop support with divs took longer that I had anticipated, I had the bulk of it done in a few hours just the last like 5% took a day in itself. I think in the long run having css friendly web parts will save me time when I get to themes.
References I used while developing this project. I also debugged the .net framework to view how the Microsoft web parts worked.
The code download contains one main dll called TFR.Web.dll. This component consits of the following custom controls and components.
Using the components are strait forward and as of right now they are drop in replacements for the Microsoft web parts
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<%@ Register assembly="TFR.Web" namespace="TFR.Web.UI.WebControls.WebParts" tagprefix="tfr" %>
<%@ Register src="Controls/stuff1.ascx" mce_src="Controls/stuff1.ascx" tagname="stuff1" tagprefix="tfr" %>
<%@ Register src="Controls/stuff2.ascx" mce_src="Controls/stuff2.ascx" tagname="stuff2" tagprefix="tfr" %>
<%@ Register src="Controls/stuff3.ascx" mce_src="Controls/stuff3.ascx" tagname="stuff3" tagprefix="tfr" %>
<%@ Register src="DisplayManager.ascx" mce_src="DisplayManager.ascx" tagname="DisplayManager" tagprefix="tfr" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>TFRPortal</title>
<link href="layout.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="MainForm" runat="server">
<asp:ScriptManager ID="scm" runat="server" />
<tfr:WebPartManager ID="WebPartManager" runat="server" Personalization-Enabled="true" Personalization-InitialScope="Shared" />
<tfr:WebPartManagerExtender ID="WebPartManagerExtender" runat="server" TargetControlID="WebPartManager" />
<div class="header">
<tfr:DisplayManager ID="DisplayManager" runat="server" />
<asp:LoginName ID="LoginName1" runat="server" />
<asp:LoginView ID="LoginView" runat="server">
<LoggedInTemplate>
<asp:LinkButton ID="LogoffLinkButton" runat="server" onclick="LogoffLinkButton_Click">Logoff</asp:LinkButton>
</LoggedInTemplate>
<AnonymousTemplate>
<asp:Login ID="Login" runat="server" />
</AnonymousTemplate>
</asp:LoginView>
</div>
<div class="wrapper">
<asp:CatalogZone ID="CatalogZone" runat="server">
<ZoneTemplate>
<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart" runat="server">
<WebPartsTemplate>
<tfr:stuff1 ID="stuff1" runat="server" />
<tfr:stuff2 ID="stuff2" runat="server" />
<tfr:stuff3 ID="stuff3" runat="server" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
<asp:PageCatalogPart ID="PageCatalogPart" runat="server" />
</ZoneTemplate>
</asp:CatalogZone>
<tfr:WebPartZone ID="WebPartZone1" runat="server" CssClass="left1" WebPartVerbRenderMode="TitleBar">
<MinimizeVerb ImageUrl="~/Images/MinimizeVerb.gif" />
<RestoreVerb ImageUrl="~/Images/RestoreVerb.gif" />
<EditVerb ImageUrl="~/Images/EditVerb.gif" />
<CloseVerb ImageUrl="~/Images/CloseVerb.gif" />
<ZoneTemplate>
<tfr:stuff1 ID="stuff1" runat="server" />
</ZoneTemplate>
<DeleteVerb ImageUrl="~/Images/DeleteVerb.gif" />
</tfr:WebPartZone>
<tfr:WebPartZone ID="WebPartZone2" runat="server" CssClass="left2" WebPartVerbRenderMode="TitleBar">
<MinimizeVerb ImageUrl="~/Images/MinimizeVerb.gif" />
<RestoreVerb ImageUrl="~/Images/RestoreVerb.gif" />
<EditVerb ImageUrl="~/Images/EditVerb.gif" />
<CloseVerb ImageUrl="~/Images/CloseVerb.gif" />
<ZoneTemplate>
<tfr:stuff2 ID="stuff2" runat="server" />
</ZoneTemplate>
<DeleteVerb ImageUrl="~/Images/DeleteVerb.gif" />
</tfr:WebPartZone>
<tfr:WebPartZone ID="WebPartZone3" runat="server" CssClass="right" WebPartVerbRenderMode="TitleBar">
<MinimizeVerb ImageUrl="~/Images/MinimizeVerb.gif" />
<RestoreVerb ImageUrl="~/Images/RestoreVerb.gif" />
<EditVerb ImageUrl="~/Images/EditVerb.gif" />
<CloseVerb ImageUrl="~/Images/CloseVerb.gif" />
<ZoneTemplate>
<tfr:stuff3 ID="stuff3" runat="server" />
</ZoneTemplate>
<DeleteVerb ImageUrl="~/Images/DeleteVerb.gif" />
</tfr:WebPartZone>
</div>
<div class="footer">
layout generated by <a href="http://www.pagecolumn.com/3_column_div_generator.htm" target="_blank">www.pagecolumn.com</a>
</div>
</form>
</body>
</html>
/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("TFR.Web");
TFR.Web.WebPartBehavior = function ( element )
{
if ( element == null ) throw Error.argumentNull("element");
TFR.Web.WebPartBehavior.initializeBase(this, [element]);
this._titleBar$delegates =
{
mousedown : Function.createDelegate(this, this._titleBar_onMouseDown)
};
this._zone = null;
this._titleBarElement = null;
};
TFR.Web.WebPartBehavior.prototype =
{
initialize: function ()
{
TFR.Web.WebPartBehavior.callBaseMethod(this, 'initialize');
// <div id="wp1560555101" class="webpart">
// <div class="webpart_chrome">
// <div id="WebPartManager_wp1560555101_titlebar" class="webpart_title">
// <span>Untitled</span>
// <a title="Minimizes 'Untitled [3]'" href="javascript:__doPostBack('WebPartZone2','minimize:wp1560555101')" mce_href="javascript:__doPostBack('WebPartZone2','minimize:wp1560555101')">
// <img title="Minimizes 'Untitled [3]'" src="Images/MinimizeVerb.gif" mce_src="Images/MinimizeVerb.gif" alt="Minimize" style="border-width:0px;" />
// </a>
// <a title="Closes 'Untitled [3]'" href="javascript:__doPostBack('WebPartZone2','close:wp1560555101')" mce_href="javascript:__doPostBack('WebPartZone2','close:wp1560555101')">
// <img title="Closes 'Untitled [3]'" src="Images/CloseVerb.gif" mce_src="Images/CloseVerb.gif" alt="Close" style="border-width:0px;" />
// </a>
// </div><div class="webpart_body">
// <div class="webpart_data">
// Hello
// </div>
// </div>
// </div>
// </div>
this._titleBarElement = this.get_element().firstChild.firstChild.firstChild;
this._titleBarElement.style.cursor = "move";
$addHandlers(this._titleBarElement, this._titleBar$delegates);
},
dispose: function ()
{
$common.removeHandlers(this._titleBarElement, this._titleBar$delegates);
this._zone = null;
TFR.Web.WebPartBehavior.callBaseMethod(this, 'dispose');
},
get_zone: function ()
{
return this._zone;
},
set_zone: function ( value )
{
this._zone = value;
},
_titleBar_onMouseDown: function ( e )
{
window._event = e; // Needed internally by _DragDropManager
var element = this.get_element();
this._webParSize = $common.getSize(element); // used later to create an empty div in the drop target where the mouse is
// this cloneNode isn't needed but for some reason it's not playing nice when i remove it and replace it with element
this._visual = element.cloneNode(true);
this._visual.className = "movingWebPart";
document.body.appendChild(this._visual);
$common.setElementOpacity(this._visual, 0.6);
$common.setSize(this._visual, this._webParSize);
$common.setLocation(this._visual, $common.getLocation(this.get_element()));
AjaxControlToolkit.DragDropManager.startDragDrop(this, this._visual, null);
var zone = this.get_zone();
var tempWebPartElement = zone._createTempElement(this._webParSize);
var zoneElement = zone.get_element();
zone._attachElementToZone(zoneElement, tempWebPartElement);
zone._tempWebPartElement = tempWebPartElement;
element.style.display = "none";
},
// AjaxControlToolkit.IDragSource section start
get_dragDataType: function()
{
return "WebPart";
},
getDragData: function ()
{
return this.get_element();
},
get_dragMode: function ()
{
return AjaxControlToolkit.DragMode.Move;
},
onDragStart: function ()
{
// do nothing
},
onDrag: function ()
{
// do nothing
},
onDragEnd: function ( canceled )
{
document.body.removeChild(this._visual);
this.get_element().style.display = "";
}
};
TFR.Web.WebPartBehavior.registerClass('TFR.Web.WebPartBehavior', AjaxControlToolkit.BehaviorBase, AjaxControlToolkit.IDragSource);
TFR.Web.WebPartZoneBehavior = function(element)
{
if ( element == null ) throw Error.argumentNull("element");
TFR.Web.WebPartZoneBehavior.initializeBase(this, [element]);
this._manager = null;
this._webParts = new Array();
};
TFR.Web.WebPartZoneBehavior.prototype =
{
initialize: function()
{
TFR.Web.WebPartZoneBehavior.callBaseMethod(this, 'initialize');
AjaxControlToolkit.DragDropManager.registerDropTarget(this);
// all child elements are web parts, so here we wire up the web part dom elements with WebPartBehavior's
var zoneElement = this.get_element();
var childElement = zoneElement.firstChild;
while( childElement != null )
{
var webPart = $create(TFR.Web.WebPartBehavior, null, null, null, childElement);
webPart.set_zone(this);
Array.add(this._webParts, webPart);
childElement = childElement.nextSibling;
};
},
dispose: function()
{
AjaxControlToolkit.DragDropManager.unregisterDropTarget(this);
TFR.Web.WebPartZoneBehavior.callBaseMethod(this, 'dispose');
},
get_manager: function ()
{
return this._manager;
},
set_manager: function ( value )
{
this._manager = value;
},
_getMouseLocation : function ()
{
var e = window._event;
var x = e.clientX + ( document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft );
var y = e.clientY + ( document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop );
return new Sys.UI.Point(x, y);
},
_getSiblingByPosition : function ( position )
{
var zoneElement = this.get_element();
var child = zoneElement.firstChild;
while ( child != null )
{
var childBounds = $common.getBounds(child);
// Sys.Debug.trace(" positino.y = " + position.y + ", childBounds.y = " + childBounds.y);
if ( position.y >= childBounds.y && position.y <= (childBounds.y + childBounds.height)) return child;
child = child.nextSibling;
};
return null;
},
_attachElementToZone : function ( zoneElement, element )
{
if ( this._tempWebPartElement != null )
{
zoneElement.removeChild(this._tempWebPartElement);
this._tempWebPartElement = null;
};
var position = this._getMouseLocation();
var sibling = this._getSiblingByPosition(position);
if ( sibling != null )
{
zoneElement.insertBefore(element, sibling);
}
else
{
zoneElement.appendChild(element);
};
},
_createTempElement: function ( size )
{
var tempWebPartElement = document.createElement("div");
tempWebPartElement.className = "targetWebPartBox";
tempWebPartElement.style.height = size.height + "px";
return tempWebPartElement;
},
_getWebPartIndex : function ( webPartElement )
{
var zoneElement = webPartElement.parentNode;
var webParts = zoneElement.childNodes;
for ( var webPartIndex = 0; webPartIndex < webParts.length; webPartIndex++ )
{
if ( webPartElement.id == webParts[webPartIndex].id )
{
return webPartIndex + 1;
};
};
return 0;
},
// AjaxControlToolkit.IDropTarget
get_dropTargetElement: function()
{
return this.get_element();
},
canDrop: function(dragMode, dataType, data)
{
return (dataType == 'WebPart' && data);
},
drop: function(dragMode, dataType, data)
{
var dragDropManager = AjaxControlToolkit.DragDropManager._getInstance();
var webPart = dragDropManager._activeDragSource;
webPart.set_zone(this);
var zoneElement = this.get_element();
var startingZoneElement = webPart.get_element().parentNode;
var webPartElement = webPart.get_element();
var oldWebPartIndex = this._getWebPartIndex(webPartElement);
this._attachElementToZone(zoneElement, webPartElement);
var newWebPartIndex = this._getWebPartIndex(webPartElement);
if ( startingZoneElement == zoneElement && newWebPartIndex == oldWebPartIndex ) return; // no change
if ( oldWebPartIndex > newWebPartIndex ) newWebPartIndex -= 1;
var eventTarget = zoneElement.id;
var eventArgument = "Drag:" + webPart.get_element().id + ":" + newWebPartIndex;
Sys.Debug.trace("eventTarget = " + eventTarget + ", eventArgument = " + eventArgument);
__doPostBack(eventTarget, eventArgument);
},
onDragEnterTarget: function(dragMode, dataType, data)
{
// do nothing
},
onDragLeaveTarget: function(dragMode, dataType, data)
{
if ( this._tempWebPartElement != null )
{
var zoneElement = this.get_element();
zoneElement.removeChild(this._tempWebPartElement);
this._tempWebPartElement = null;
};
},
onDragInTarget: function(dragMode, dataType, data)
{
var dragDropManager = AjaxControlToolkit.DragDropManager._getInstance();
var webPart = dragDropManager._activeDragSource;
var size = webPart._webParSize
var tempWebPartElement = this._createTempElement(size);
var zoneElement = this.get_element();
this._attachElementToZone(zoneElement, tempWebPartElement);
this._tempWebPartElement = tempWebPartElement;
}
};
TFR.Web.WebPartZoneBehavior.registerClass('TFR.Web.WebPartZoneBehavior', AjaxControlToolkit.BehaviorBase, AjaxControlToolkit.IDropTarget);
TFR.Web.WebPartManagerBehavior = function(element)
{
TFR.Web.WebPartManagerBehavior.initializeBase(this, [element]);
this._zones = new Array();
this._enableDragDrop = false;
this._dragDropEnabled = false;
};
TFR.Web.WebPartManagerBehavior.prototype =
{
initialize: function()
{
TFR.Web.WebPartManagerBehavior.callBaseMethod(this, 'initialize');
if ( !this.get_enableDragDrop() )
{
return;
};
for ( var zoneIndex = 0; zoneIndex < this._zonesIds.length; zoneIndex++ )
{
var id = this._zonesIds[zoneIndex];
var zone = $create(TFR.Web.WebPartZoneBehavior, null, null, null, $get(id));
zone.set_manager(this);
Array.add(this._zones, zone);
};
this._dragDropEnabled = true;
},
dispose: function()
{
TFR.Web.WebPartManagerBehavior.callBaseMethod(this, 'dispose');
},
get_zonesIds: function ()
{
return this._zonesIds;
},
set_zonesIds: function ( value )
{
this._zonesIds = value;
},
get_enableDragDrop: function ()
{
return this._enableDragDrop;
},
set_enableDragDrop: function ( value )
{
this._enableDragDrop = value;
}
};
TFR.Web.WebPartManagerBehavior.registerClass('TFR.Web.WebPartManagerBehavior', AjaxControlToolkit.BehaviorBase);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();