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

4/15/2010 9:58:28 PM #

skin care advices

It is always valuable to distribute the innovative ideas with others on our demand.That is the main way for the people to know about the useful types of techniques to equip it. It will really gives the crucial moments for others to know about it. It is a beneficial passion for the people to select the conducive categories of the stories on the requirements of using it.

skin care advices United Kingdom

4/20/2010 12:06:53 PM #

Clasificados Gratis

Clasificados Online. Anuncios Clasificados Gratis en España.

Clasificados Gratis United States

4/21/2010 12:51:53 PM #

Bani pe internet

Bani pe internet - Online guide for making money

Bani pe internet United States

5/3/2010 2:16:10 AM #

voyage

Excellent article. Thanks for that, and keep doing great on your site. Regards

http://www.partir-en-voyage.net/">Partir en voyage

voyage United States

5/14/2010 2:35:32 PM #

Antwan Garratt

I was very pleased to locate this site.I wanted to thank you for this excellent read!! I certainly enjoyed every little bit of it and I have you bookmarked to check out new things you publish.

Antwan Garratt United States

6/12/2010 2:05:20 PM #

Premium Web Directory

Quite Nice Blogpost. Would you thoughts if I take a small snippets of your post and naturally link it for your blogposts??

Premium Web Directory United States

6/18/2010 1:30:08 AM #

Zen gardens

Zen changed my life and everyone who has anger or hurt in themself, go visit a zen garden and you will change your tune I am sure.

Zen gardens United States

6/18/2010 4:06:48 AM #

Victoria Brum

Really so nice post.I am always so interested about internet and web development related subjects and now found a new very informative source for this. Thanks

Victoria Brum United States

6/19/2010 10:08:13 AM #

RTA Kitchen Cabinets

Just now I discovered the web for exactly this kind of information. Thank to your post that search has to end right now. You wrote the post in a very understandable way. With that, I added your blogs as one of my favorites! Cheers!

RTA Kitchen Cabinets United States

6/24/2010 2:21:39 PM #

Isiah Dunzelman

I was searching for information about this on Google and came upon your piece. I found it to be nice and clear. Thanks

Isiah Dunzelman United States

7/4/2010 12:27:10 PM #

Delia Hubby

I just subscribed to your rss feed after reading this article! Would you post more about this subject in future posts?

Delia Hubby United States

7/4/2010 12:27:49 PM #

Abdul Petersheim

I found a similar post on a different site and didn't see the point, but your article explains it better. Appreciate it!

Abdul Petersheim United States

7/10/2010 5:56:04 PM #

godric

Trubloods.com can be a site specialized in bringing you almost all on the goodness and night in the hit show True Blood. True Blood will be known as as the actual artificial blood the western have created now vampires arise in the night to attempt because well as exist together together with humans. An individual follow Sookie Stackhouse because she offers applying the turmoil that exists in the particular globe. There is certainly romance, humor, motion, and many a great deal more although a person view vampires, human beings as well since supernaturals collide inside the town regarding Bon Temperatures, Louisiana. Watch free channels at trubloods.com!

godric Armenia

7/24/2010 3:29:19 AM #

Gore

Hi there! Very useful post! I am very happy that I was able to stumble upon your blog while searching Yahoo. Koodles for this great post!

Gore 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