Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / XHTML

Expanding / Collapsing GridView Columns with Smooth Dynamic Effect

4.83/5 (16 votes)
3 Jul 2009CPOL3 min read 82.7K   722  
This article describes how to expand and collapse columns of a GridView using JavaScript
Demo.gif

Introduction

Last year I had posted an article: Expanding / Collapsing GridView Rows. In that article, I had described implementation details of Expanding / Collapsing rows of a GridView using JavaScript with smooth dynamic effect. Now through this article, I'm going to demonstrate how to expand and collapse columns of a GridView using JavaScript with smooth dynamic effect.

CSS Code

I've used the following CSS classes for this demo. Header and Footer CSS classes have been used for GridView’s header and footer rows respectively and Row and AlternateRow CSS classes for GridView’s normal and alternate rows respectively. Grid CSS class has been used for GridView’s background.

CSS
.Header
{
    background-color:#0053E1;
    color:White;
    font-weight:bold;
    text-align:right;
    vertical-align:middle;
    height:25px;
}
.Footer
{
    background-color:#0053E1;
    height:25px;
}
.Row
{
    background-color:#C1DAEB;
    text-align:right;
    vertical-align:middle;
    height:25px;
}
.AlternateRow
{
    background-color:#7FB4D3;
    text-align:right;
    vertical-align:middle;
    height:25px;
}
.Grid
{
    background-color:White;
}

I've put these CSS classes in a separate StyleSheet.css file and attached its reference in the Grid.aspx page as follows:

ASP.NET
<link href="CSS/StyleSheet.css" rel="stylesheet" type="text/css" />

HTML Code

Below is the HTML of the GridView that has been used for this demo. I've applied Header, Footer, Row & AlternateRow CSS classes in the GridView through HeaderStyle, FooterStyle, RowStyle and AlternatingRowStyle respectively. Grid CSS class is applied through the CssClass property of the GridView. I've taken TemplateField columns inside the GridView and put an Image control in HeaderTemplate of each TemplateField column.

ASP.NET
<asp:GridView ID="gvTab" CssClass="Grid" runat="server" AutoGenerateColumns="False"
                                   ShowFooter="True" GridLines="Vertical">
   <Columns>
      <asp:TemplateField>
         <HeaderTemplate>
            <asp:Image ID="imgN" onclick="javascript:Toggle(this,0);" 
			runat="server" ImageUrl="~/Images/minus.gif"
                           	ToolTip="Collapse" ImageAlign="AbsMiddle" />
            <asp:Label ID="lblHeaderN" runat="server" Text="n"></asp:Label>
         </HeaderTemplate>
         <ItemTemplate>
            <asp:Label ID="lblItemN" runat="server" Text='<%# Eval("n") %>'></asp:Label>
         </ItemTemplate>
         <HeaderStyle Width="50px" />
         <ItemStyle Width="50px" />
     </asp:TemplateField>
     <asp:TemplateField>
        <HeaderTemplate>
           <asp:Image ID="imgSqrt" onclick="javascript:Toggle(this,1);" 
		runat="server" ImageUrl="~/Images/minus.gif"
                  	ToolTip="Collapse" ImageAlign="AbsMiddle" />
           <asp:Label ID="lblHeaderSqrt" runat="server" Text="sqrt(n)"></asp:Label>
        </HeaderTemplate>
        <ItemTemplate>
           <asp:Label ID="lblItemSqrt" runat="server" Text='<%# Eval("sqrtn") %>'>
	  </asp:Label>
        </ItemTemplate>
        <HeaderStyle Width="150px" />
        <ItemStyle Width="150px" />
     </asp:TemplateField>
     <asp:TemplateField>
        <HeaderTemplate>
           <asp:Image ID="imgQbrt" onclick="javascript:Toggle(this,2);" 
		runat="server" ImageUrl="~/Images/minus.gif"
           	ToolTip="Collapse" ImageAlign="AbsMiddle" />
           <asp:Label ID="lblHeaderQbrt" runat="server" Text="qbrt(n)"></asp:Label>
        </HeaderTemplate>
        <ItemTemplate>
           <asp:Label ID="lblItemQbrt" runat="server" Text='<%# Eval("qbrtn") %>'>
	  </asp:Label>
        </ItemTemplate>
        <HeaderStyle Width="150px" />
        <ItemStyle Width="150px" />
     </asp:TemplateField>
  </Columns>
  <HeaderStyle CssClass="Header" />
  <RowStyle CssClass="Row" />
  <AlternatingRowStyle CssClass="AlternateRow" />
  <FooterStyle CssClass="Footer" />
</asp:GridView>

Attaching click Event

I've attached click event on header Image of each GridView column as:

ASP.NET
<asp:Image ID="imgSqrt" onclick="javascript:Toggle(this,1);" 
	runat="server" ImageUrl="~/Images/minus.gif"
         ToolTip="Collapse" ImageAlign="AbsMiddle" />

Page’s window.onload Event

I've used window.onload event to initialize global variables.

JavaScript
var Grid = null;
var UpperBound = 0;
var LowerBound = 1;
var CollapseImage = 'Images/minus.gif';
var ExpandImage = 'Images/plus.gif';
var Rows = null;
var n = 1;
var TimeSpan = 25;
        
window.onload = function()
{
    Grid = document.getElementById('<%= this.gvTab.ClientID %>');
    UpperBound = parseInt('<%= this.gvTab.Rows.Count %>');
    Rows = Grid.getElementsByTagName('tr');
}

GridView’s Header Image’s Click Event

This event gets invoked on successive clicks on any one header Image. This event first toggles the header Image and then toggles the requested column of the GridView by invoking the ToggleImage and ToggleColumns methods respectively.

JavaScript
function Toggle(Image, Index)
{
    ToggleImage(Image, Index);  
    ToggleColumns(Image, Index);
}

The first argument is the reference of the Image to be clicked while the second argument is the column index of the GridView that contains the particular Image.

ToggleImage Method

This method is invoked from the Toggle method. The basic function of this method is to toggle the source as well as tooltip of the selected header Image.

JavaScript
function ToggleImage(Image, Index)
{
    if(Image.IsExpanded == undefined || Image.IsExpanded)
    {
        Image.src = ExpandImage;
        Image.title = 'Expand';
        n = UpperBound;
                
        Image.IsExpanded = false;
    }
    else
    {
        Image.src = CollapseImage;
        Image.title = 'Collapse';
        n = LowerBound;
                
        Image.IsExpanded = true;
    }
}    

ToggleColumns Method

The first time this method is invoked from the Toggle method, after that it is invoked by itself recursively, using the setTimeout method. I've invoked it recursively here in order to create a smooth dynamic effect during the expanding/collapsing of the GridView columns.

In order to make a delay in each recursion, each call of the ToggleColumns method has been delayed for 25 milliseconds. You can set it by altering the TimeSpan value depending on your need.

I've used here JavaScript closure to invoke ToggleColumns method recursively with arguments through setTimeout method.

JavaScript
function ToggleColumns(Image, Index)
{
   if (n < LowerBound || n > UpperBound) return;

   var Condition = Rows[n].getElementsByTagName('td')[Index].style.visibility == '';
   Condition = Condition || Rows[n].getElementsByTagName('td')
				[Index].style.visibility = 'visible'; 
   
   Rows[n].getElementsByTagName('td')[Index].style.visibility = 
				Condition ? 'hidden' : 'visible';


   if(Image.IsExpanded) n++; else n--;

   setTimeout(function(){ToggleColumns(Image, Index);},TimeSpan);
}

Winding Up

I have toggled visibility of all TD elements of a GridView column in order to create an illusion of smooth dynamic effect with the help of setTimeout method through recursion. Different browsers have different effects of Expanding / Collapsing GridView Columns. In Internet Explorer 7/8, Safari, Google Chrome and Opera, it seems that columns are Expanding / Collapsing while in case of Mozilla, Firefox and Netscape Navigator, it seems that column’s text are Expanding / Collapsing.

Supporting Browsers

I have tested this code on the following browsers:

Browsers_New.gif

History

  • 4th July, 2009 -- Original version posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)