December 20, 2014
Hot Topics:

A Better Fixed GridView Header for ASP.NET

  • August 29, 2007
  • By Paul Kimmel
  • Send Email »
  • More Articles »

In the listing, the function Foo is treated like a class and the statement alert... basically plays the role of initialization (or construct) code. The statement var foo = new Foo(); ultimately creates an instance of Foo (upper case) and runs the initialization code.

You could move the alert statement to a function within Foo and invoke that function. This will give you a better sense of the object-oriented nature of JavaScript when used in this manner (see Listing 4).

Listing 4: Adding a member function to Foo.

<%@ Page Language="VB" AutoEventWireup="false"
         CodeFile="Default2.aspx.vb" Inherits="Default2" %>

<!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>Untitled Page</title>
<script language="javascript">

function Foo()
{
   this.MemberFunc = memberFunc;
   function memberFunc()
   {
      alert("This is a simple JavaScript class");
   }
}

var foo = new Foo();
foo.MemberFunc();


</script>
</head>
<body>
   <form id="form1" runat="server">
   <div>

   </div>
   </form>
</body>
</html>

In the revision, Foo has a member function called memberFunc (notice the case) and makes it accessible externally by assigning it to this.MemberFunc. Without the this.member statement, the member is treated as inaccessible externally.

Cloning the Grid Header

To begin wrapping things up, you now can implement what I refer to as the PositionClass. The PositionClass will figure out where the grid is, where the header is, and keep track of where the header should be depending on the scroll position and the size of the window containing the grid. Listing 5 is a couple of hundred lines long, but a complete explanation is offered after the listing. To get started, add a new JavaScript file to your solution and put the code in Listing 5 in that file.

Listing 5: JavaScript code to manage and position a row containing header information.

// JScript File - by PTK
// Implements a fixed header for HTML tables (like a GridView,
// which renders and HTML table)
function PositionClass()
{
   this.Top          = top;
   this.Left         = left;
   this.Width        = width;
   this.Height       = height;
   this.ClientID     = clientID;
   this.SavePosition = savePosition;
   this.Reposition   = reposition;
   this.SetClientID  = setClientID;
   var top, left, width, height, clientID;
   var head, caption;

   // the client ID of the table/gridview
   function setClientID(id)
   {
      clientID = id;
   }

   // determines the absolute position of X or Y--determined by
   // the getOffset function to handle control nesting
   function getAbsolutePosition(control, getOffset, adjustCaption)
   {
      var result = 0;
      while(control)
      {
         if(control.tagName)
            if((control.tagName == "TBODY") ||
               (control.tagName == "TR"))
            {
               if(control.parentElement)
                  control = control.parentElement;
               else
                  break;
               continue;
            }

         if(control.style.position == "absolute")
            return result;

         result += getOffset(control);

         if(control.parentElement)
            control = control.parentElement;
         else
            break;
      }

      if(adjustCaption && caption && isAlignedTop(caption))
         result -= caption.clientHeight;
      return result;
   }

   // returns the x offset
   function getXOffset(control)
   {
      if(control.offsetLeft)
         return control.offsetLeft;
      else
         return 0;
   }

   // returns the y offset
   function getYOffset(control)
   {
      if(control.offsetTop)
         return control.offsetTop;
      else
         return 0;
   }

   // get the grid header row. It may not exist or there may be a
   // caption above it
   function getHeaderNode(grid)
   {
      if(!grid) return null;
      for(var i=0; i<grid.rows.length; i++)
      {
         var s = new String();
         if(grid.rows[i].childNodes.length > 0)
         {
            s = grid.rows[i].childNodes[0].tagName;
            if(s.toLowerCase() == "th")
               return grid.rows[i];
         }
      }
      return null;
   }

   // everything but "bottom" is top=aligned
   function isAlignedTop(theCaption)
   {
      if(!theCaption) return false;
      var tag = theCaption.align.toLowerCase();
      return (tag == "top") || (tag == "left") || (tag == "right")
         || (tag == "");
   }

   // find the caption; we have to allow for a caption above the
   // header
   function getCaptionNode(grid)
   {
      if(!grid) return null;
      return grid.caption;
   }

   // stores the current position of the control
   function savePosition()
   {
      // debugger;
      // get the grid
      var grid = document.all[clientID];
      if(!grid) return;
      header.cellPadding = grid.cellPadding;
      header.cellSpacing = grid.cellSpacing;
      header.border      = grid.border;
      header.bgColor     = grid.bgColor;
      header.className   = grid.className;
      caption = getCaptionNode(grid);
      if(caption && (caption.style.backgroundColor == ""))
      {
         // debugger;
         caption.style.backgroundColor = "white";
      }
      head = getHeaderNode(grid);
      if(head == null) return;
      head.style.visibility = "hidden";
      // get the header position
      top      = getAbsolutePosition(head, getYOffset, true);
      left     = getAbsolutePosition(head, getXOffset, false);
      width    = head.clientWidth;
      height   = head.clientHeight;
      var temp = head.cloneNode(true);
      // store sizes in style attributes
      for(var i=0; i<head.childNodes.length; i++)
      {
         temp.childNodes[i].style.width =
            head.childNodes[i].clientWidth;
         temp.childNodes[i].style.height =
            head.childNodes[i].clientHeight;
      }
      head = temp;
      // clone the header
      head.style.visibility = "visible";
      // insert the header (and caption) into our copy table
      if(caption && isAlignedTop(caption))
      {
         var newCaption = caption.cloneNode(true);
         if(header.caption)
            header.replaceChild(newCaption, header.caption);
         else
            header.appendChild(newCaption);
         caption.style.visibility = "hidden";
      }

      // place the new table header in the table-playing header
      var th = getHeaderNode(header);
      if(th)
         header.childNodes[0].replaceChild(head, th);
      else
         header.childNodes[0].appendChild(head);

      // fix the position of the div to overlap the gridview's header
      fixedHeader.style.posLeft    = left;
      fixedHeader.style.left       = left + "px";
      fixedHeader.style.posTop     = top;
      fixedHeader.style.top        = top + "px";
      fixedHeader.style.width      = width + "px";
      fixedHeader.style.height     = height + "px";
      fixedHeader.style.visibility = "visible";
      fixedHeader.style.zIndex     = 0;
   }

   // repositions the control if necessary
   function reposition()
   {
      if(!document.all[clientID]) return;
      // added silent try..catch because masterpages can have other
      // things that scroll;
      // for instance we scroll the treeview that fires this event
      try
      {
         if(document.body.parentNode.scrollLeft > 0)
         {
            fixedHeader.style.posLeft =
               document.body.parentNode.scrollLeft;
            fixedHeader.style.left =
               document.body.parentNode.scrollLeft + "px";
         }
         else
         {
            fixedHeader.style.posLeft =
               document.body.parentNode.scrollLeft + left;
            fixedHeader.style.left =
               document.body.parentNode.scrollLeft + left + "px";
         }
         if(document.body.parentNode.scrollTop > 0)
         {
            fixedHeader.style.top =
               document.body.parentNode.scrollTop + "px";
            fixedHeader.style.posTop =
               document.body.parentNode.scrollTop;
         }
         else
         {
            fixedHeader.style.top =
               document.body.parentNode.scrollTop + top + "px";
            fixedHeader.style.posTop =
               document.body.parentNode.scrollTop + top;
         }
         fixedHeader.style.width      = width + "px";
         fixedHeader.style.height     = height + "px";
         fixedHeader.style.visibility = "visible";
      }
      catch(oException)
      {
      }
   }
}




Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel