TFRPortal - CSS friendly web parts

by Jeff 14. March 2009 14:54

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.

  1. Tableless WebParts and WebPartZones
  2. Drag and Drop like iGoogle with ASP.Net Ajax Toolkit
  3. Build Google IG like Ajax Start Page in 7 days using ASP.NET Ajax and .NET 3.0

 

Download the code here (955.55 kb)

The code download contains one main dll called TFR.Web.dll. This component consits of the following custom controls and components.

  1. PartChrome.vb
  2. WebPartManager.vb
  3. WebPartManagerBehavior.js
  4. WebPartManagerExtender.vb
  5. WebPartZone.vb
  6. ZoneButton.vb
  7. ZoneLinkButton.vb

As of right now a WebPartZone in browser mode will generate the following code

Example html code

<div id="WebPartZone1" class="left1">
    <div id="WebPart_gwpstuff1" class="webpart">
        <div id="WebPart_gwpstuff1" class="webpart_chrome">
            <div class="webpart_title">
                <span>Untitled</span>
            </div><div class="webpart_body">
                <div class="webpart_data">
                    test
                </div>
            </div>
        </div>
    </div>
</div>

Using the components are strait forward and as of right now they are drop in replacements for the Microsoft web parts

Example asp.net code

<%@ 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>

here is the javascript that makes drag and drop posible

Example javascript code: Microsoft Asp.net AJAX

/// <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();
Bookmark and Share

Tags:

Asp.net | Asp.net AJAX | Asp.net AJAX Control Toolkit | TFRPortal | Web Parts

Comments

6/29/2009 12:49:58 PM #

pingback

Pingback from kiranpatils.wordpress.com

Tableless WebParts and WebPartZones « A Place for C Sharpers/.Netters

kiranpatils.wordpress.com

7/9/2009 9:11:56 PM #

club penguin cheats

I think your blog theme is not good.
There are many codes out of my screen.

club penguin cheats United States

7/17/2009 7:20:48 AM #

internet marketing

How to change theme in the whole application in asp.net?

internet marketing's last blog post.. A feed could not be found at http://www.webmarketingexperts.com.au

internet marketing United States

9/15/2009 7:06:24 AM #

sachin

awesome work... many many thanks...

sachin India

9/16/2009 11:33:28 AM #

constatntin

Download link doesn't work.
Do you think you can fix it?

Constantin

constatntin United States

9/18/2009 6:31:54 AM #

sachin

Again, thanks for such wonderful work...

Its working as expected, I have wrapped entire components in UpdatePanel.

But somwhow it doesnt work in Design and Connect mode, as I continue to get errors like "Id cannot be null" or "zoneElement not found".

It was working perfectly with regular ASP.Net WebParts

Any suggestion if I am doing it wrong?

Thanks

sachin India

12/14/2009 9:27:57 AM #

hip hop reviews

Resources like the one you mentioned here will be very useful to me! I will post a link to this page on my blog. I am sure my visitors will find that very useful.


Regards
Weeks

hip hop reviews United States

2/13/2010 3:54:54 PM #

total body cleanse

Let me bang if you are involved to transform as article illustrator for me? I can act $10/article.

Regards

jops

total body cleanse United States

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET

Code Research Center

©2009 CodeResearchCenter.com. All Rights Reserved

About Me

I'm a 30 year old browser based software developer who has just started to research the various ways to make money online. My current interests are software development, online marketing, social networking and blogging.

Disclaimer

These postings are provided "AS IS" with no warranties, use at your own risk

Page List

Poll

What blog platform do you use?



Show Results