JavaScript Sortable Grid Control (With Form Elements)

By Robbe D. Morris

Printer Friendly Version

Robbe Morris
Robbe & Melisa Morris
As with most of my articles, the JavaScript Sortable Grid Control stems from a request here at work to create a 100% client side JavaScript solution for a cross-browser based sortable grid.  The idea being that the user would not have to wait for a page reload each time the sort was adjusted or process another query on the server.  To provide further complexity, the ability to include certain form elements and sort on them was also required.
For those of you working in the .NET world, I've put in some customizations for a wrapper class library assembly that is much, much easier to work with than this open JavaScript.  If you would like to download the assembly and a test page to show you how to use it, click here: .NET DataGrid Control.
The demonstration below shows a sample grid.  Simply click on the column headers to sort.  You can also submit the contents of the grid to the results page to view the form elements posted.  This article shows the grid in an IFRAME for the convenience of the reader.
 


I searched Google high and low for examples of how to create a sortable grid.  Virtually all of them didn't appear to support sorting form elements and their values.  Plus, they were not easy to customize or plug in to an existing web site without a great deal of effort.  So, I set out to write my own.  Here's how it works:
As I've done with other client side controls (TreeView or Slider ), an array of arrays or objects was used to hold the contents of the control.  This allows us to repopulate the .innerHTML property of the DIV or layer tag that holds the grid itself.  As long as the objects had the proper value at the time the redraw takes place, your in business.
The source code for this grid is broken out into three separate files: default.htm, griddraw.js, and gridsort.js.
 
1.default.htm
This file contains the sample page along with the JavaScript grid row and cell definitions.  Pay careful attention to the properties set for each object and the comment lines explain what each is used for.  It also contains three sample JavaScript functions for dynamically generating form element HTML.  Each of these three different form elements has a JavaScript call to GridSetVal() that resets the corresponding object in the GridArrays array (discussed more in griddraw.js.  I assumed that each grid you create would likely have to have custom events for most of your form elements.  This demo supports checkboxes, textboxes, and various drop down lists.  Don't be overwhelmed by the apparent large amount of code needed to generate the grid.  I deliberately broke things out nice and neat.  When implemented with a database query, there are actually relatively few lines of code and it is very easy to set up.
2.griddraw.js
This file contains the JavaScript functions that draw the grid by iterating through the master GridArrays array of rows.  The JavaScript functions GridWriteRow() and GridSetVal() have data type case statements that support resetting or repopulating the allowable form elements as well as resetting the .SortVal and .HTML properties of the grid cell object that is put back into the master GridArrays array.  If you need to add a new data type, besides adding the new constant to the top of gridsort.js you'll need to make adjustments to these two functions.
3.gridsort.js
This file contains the JavaScript functions that actually execute the sort.  It is unlikely that you'll need to change any code in this file unless you need to add a new data type constant.  Essentially, it is responsible for pulling out each cell for the designated column and executing a sort in a temporary multi-dimensional array.  Each grid cell object has a property for .SortVal and .HTML.  The .HTML property holds the value HTML to be displayed on the grid.  The .SortVal property is what is used in the sorting process.  While sorting, it retains the unique key assigned to each cell in the grid.  Upon completion of the sort, the master GridArrays array is reconstructed in proper order.
Currently, the sort methodology uses is the normal JavaScript .sort() and .reverse() methods to sort the array.  If your grid needs to support sorting of dates or foreign currency, you may need to add your own custom sorts because JavaScript typically sorts based on string value.  This may or may not work 100% accurately with all data types.  Fortunately, the GridSort() function can be easily adjusted to add new sort options based on the cell's data type.
 
Feel free to download the grid control code zip file: Sortable Grid Control.
 
Default.htm
 
 
<HTML>
   <HEAD>
    <META HTTP-EQUIV='Pragma' CONTENT='no-cache'>
    <META HTTP-EQUIV='Expires' CONTENT='0'>
    <META http-equiv='Cache-Control' content='no-cache'>
    <TITLE>NullSkull.com Sortable Grid Control By Robbe D. Morris</TITLE>

<script language=JavaScript src=GridSort.js></script> 
<script language=JavaScript src=GridDraw.js></script> 
 
<script language=JavaScript>

  /* 
       Possible Data Type Constants Defined in GridSort.js
      
       var idxGrid_Text=0;
       var idxGrid_CheckBox=1;
       var idxGrid_Input=2;
       var idxGrid_DropDown=3;
      
*/

       
 

 /*  Start of examples of custom functions that may make your code easier to read. */

     var sGridStateList='';

     sGridStateList += "<select id=gridstatelist name=gridstatelist onchange=GridSetVal >";
     sGridStateList += "<option value='FL'>FL</option>";
     sGridStateList += "<option value='NY'>NY</option>";
     sGridStateList += "<option value='DC'>DC</option>";
     sGridStateList += "<option value='CA'>CA</option>";
     sGridStateList += "<option value='IA'>IA</option>";
     sGridStateList += "<option value='AZ'>AZ</option>";
     sGridStateList += "</select>";

 

     function GridWriteCheckBox(nColumn,sID,sName)
     {
             return '<input id=' + sName + ' name=' + sName + ' type=checkbox value=1 onclick=GridSetVal(' + nColumn + ',"' + sID + '",this); >';
     }

     function GridWriteInputBox(nCol,sID,sName,sVal)
     {
             sVal = '<input id=' + sName + ' name=' + sName + ' type=text size=10 value="' + sVal + '";
             sVal +=' onchange=GridSetVal(' + nCol + ',' + sID + ',this); >';
             return sVal;
     }

     function GridWriteStates(nColumn,sID,sName)
     {
           var sH='';
 
            sH = GridReplace(sGridStateList,"gridstatelist",sName);
            sH = GridReplace(sH,"onchange=GridSetVal","onchange=GridSetVal('" + nColumn + "','" + sID + "',this);");
         
           return sH;
      }

    /*  End of examples of custom functions that may make your code easier to read. */



         var GridTableWidth=550;                   // Max table width for the grid
         var GridSortDirection='descending';  // Set to descending if you want the grid to be sorted ascending to start with.
         var GridSortColumn=2;                      // Set the column that will be sorted on
         var GridCell_1;                                   // GridCell_1 - 8 are place holders for cell objects
         var GridCell_2;
         var GridCell_3;
         var GridCell_4;
         var GridCell_5;
         var GridCell_6;
         var GridCell_7;
         var GridCell_8;
         var GridArrays = new Array();        // Master grid array that contains an array of GridCell objects for each row.

         var oGridCell;  
         var GridCurCol=0;
         var GridCurID=0;
         var GridCurRow=0;
	 
		 
         // Define our columns

               GridArrays[GridCurRow] = new Array ('Select','FName','LName','Address','City','State','Zip','Status'); 
               

  /* Start Row 1 */

               GridCurCol=0;
               GridCurID='1001';                                    //Give unique id to all cells in this row
               GridCurRow=1;                                        

               oGridCell = new Object;                           // Create new JavaScript Object
               oGridCell.ID = GridCurID;                        
               oGridCell.Column=GridCurCol;                 // Column in the grid
               oGridCell.Name = 'chk' + oGridCell.ID;    // Form element name (if applicable)
               oGridCell.Type = idxGrid_CheckBox;      //Use constant to define data type
               oGridCell.SortVal = '1';                            // Value used for sorting
                                                                               // HTML displayed in grid
               oGridCell.HTML = GridWriteCheckBox(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_1 = oGridCell;
           

               oGridCell = new Object;
               GridCurCol++;
               oGridCell.ID = GridCurID;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Robbe';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_2 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Morris';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_3 = oGridCell;
 
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '1600 Pennslyvania Ave.';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_4 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Washington';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_5 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'grdState' + oGridCell.ID;
               oGridCell.Type = idxGrid_DropDown;
               oGridCell.SortVal = 'DC';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteStates(oGridCell.Column,oGridCell.ID,oGridCell.Name);

               GridCell_6 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '90210';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_7 = oGridCell;
             
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'txt' + oGridCell.ID;
               oGridCell.Type = idxGrid_Input;
               oGridCell.SortVal = 'hired';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteInputBox(oGridCell.Column,oGridCell.ID,oGridCell.Name,oGridCell.SortVal);
               
               GridCell_8 = oGridCell;
              
               GridArrays[GridCurRow] = new Array (GridCell_1,GridCell_2,GridCell_3,GridCell_4,GridCell_5,GridCell_6,GridCell_7,GridCell_8);

   /* End Row 1 */



               /* Start Row 2 */

               GridCurCol=0;
               GridCurID='1002';
               GridCurRow=2;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               oGridCell.Column=GridCurCol;
               oGridCell.Name = 'chk' + oGridCell.ID;
               oGridCell.Type = idxGrid_CheckBox;
               oGridCell.SortVal = '1';
               oGridCell.HTML = GridWriteCheckBox(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_1 = oGridCell;
           
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Melisa';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_2 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Haire';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_3 = oGridCell;
 
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '1234 Sesame Street';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_4 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Orlando';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_5 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'grdState' + oGridCell.ID;
               oGridCell.Type = idxGrid_DropDown;
               oGridCell.SortVal = 'FL';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteStates(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_6 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '90211';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_7 = oGridCell;
             
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'txt' + oGridCell.ID;
               oGridCell.Type = idxGrid_Input;
               oGridCell.SortVal = 'pending';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteInputBox(oGridCell.Column,oGridCell.ID,oGridCell.Name,oGridCell.SortVal);
               GridCell_8 = oGridCell;
              
               GridArrays[GridCurRow] = new Array (GridCell_1,GridCell_2,GridCell_3,GridCell_4,GridCell_5,GridCell_6,GridCell_7,GridCell_8);

   /* End Row 2 */

 /* Start Row 3 */

               GridCurCol=0;
               GridCurID='1003';
               GridCurRow=3;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               oGridCell.Column=GridCurCol;
               oGridCell.Name = 'chk' + oGridCell.ID;
               oGridCell.Type = idxGrid_CheckBox;
               oGridCell.SortVal = '0';
               oGridCell.HTML = GridWriteCheckBox(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_1 = oGridCell;
           
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'John';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_2 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Smith';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_3 = oGridCell;
 
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '24 Jump Street';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_4 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'San Diego';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_5 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'grdState' + oGridCell.ID;
               oGridCell.Type = idxGrid_DropDown;
               oGridCell.SortVal = 'CA';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteStates(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_6 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '90212';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_7 = oGridCell;
             
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'txt' + oGridCell.ID;
               oGridCell.Type = idxGrid_Input;
               oGridCell.SortVal = 'interview';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteInputBox(oGridCell.Column,oGridCell.ID,oGridCell.Name,oGridCell.SortVal);
               GridCell_8 = oGridCell;
              
               GridArrays[GridCurRow] = new Array (GridCell_1,GridCell_2,GridCell_3,GridCell_4,GridCell_5,GridCell_6,GridCell_7,GridCell_8);

   /* End Row 3 */

 /* Start Row 4 */

               GridCurCol=0;
               GridCurID='1004';
               GridCurRow=4;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               oGridCell.Column=GridCurCol;
               oGridCell.Name = 'chk' + oGridCell.ID;
               oGridCell.Type = idxGrid_CheckBox;
               oGridCell.SortVal = '0';
               oGridCell.HTML = GridWriteCheckBox(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_1 = oGridCell;
           
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Jack';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_2 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'Welch';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_3 = oGridCell;
 
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '1 Wall Street';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_4 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = 'New York';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_5 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'grdState' + oGridCell.ID;
               oGridCell.Type = idxGrid_DropDown;
               oGridCell.SortVal = 'NY';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteStates(oGridCell.Column,oGridCell.ID,oGridCell.Name);
               GridCell_6 = oGridCell;

               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = '';
               oGridCell.Type = idxGrid_Text;
               oGridCell.SortVal = '90213';
               oGridCell.HTML = oGridCell.SortVal;
               oGridCell.Column=GridCurCol;
               GridCell_7 = oGridCell;
             
               oGridCell = new Object;
               oGridCell.ID = GridCurID;
               GridCurCol++;
               oGridCell.Name = 'txt' + oGridCell.ID;
               oGridCell.Type = idxGrid_Input;
               oGridCell.SortVal = 'terminated';
               oGridCell.Column=GridCurCol;
               oGridCell.HTML = GridWriteInputBox(oGridCell.Column,oGridCell.ID,oGridCell.Name,oGridCell.SortVal);
               GridCell_8 = oGridCell;
              
               GridArrays[GridCurRow] = new Array (GridCell_1,GridCell_2,GridCell_3,GridCell_4,GridCell_5,GridCell_6,GridCell_7,GridCell_8);

   /* End Row 4 */

 

</script>
   



<style>
.BodyHeader {	font-family:verdana,arial,helvetica;sans-serif;color:#000000;
                                font-size:16px;font-weight:normal; border-color:#FFFFFF;
                                background-color: #FFFFFF;text-decoration:none;	font-style:normal; }
.BodyHeader2 {	font-family:verdana,arial,helvetica;sans-serif;color:#000000;
                                font-size:10px;font-weight:normal; border-color:#FFFFFF;
                                background-color: #FFFFFF;text-decoration:none;	font-style:normal; }
.GridCell {	font-family:verdana,arial,helvetica;sans-serif;color:#000000;
                               font-size:10px;font-weight:normal; border-color:#FFFFFF;
                                background-color: #FFFFFF;text-decoration:none;	font-style:normal; }
.GridLink {	font-family:verdana,arial,helvetica;sans-serif; color:#5D7BBA;
                                font-size:10px;font-weight:normal;text-decoration:underline;font-style:normal; }
.GridHeaderLink {	font-family:verdana,arial,helvetica;sans-serif; color:#FFFFFF;
                                 background-color: #5D7BBA;font-size:12px;font-weight:normal;
                                 text-decoration:underline;font-style:normal; }
 
</style>

  </HEAD>

<form name=frmSubmit id=frmSubmit method=post action=results.asp>
<BODY onload="GridDrawTable(GridArrays);" >
 
 <table border="0" align="center">
   <tr><td align="center" class=BodyHeader>NullSkull.com Sortable Grid Demo</td></tr>
   <tr><td align="center" class=BodyHeader2>By Robbe D. Morris</td></tr>
   <tr><td align="center"> </td></tr>
   
   <tr><td><div id=GridTable name=GridTable > </div> </td></tr>
   <tr><td align="center"><Br></td></tr>
    <tr><td align="center" class=BodyHeader2>(Click column heading to adjust sort order)</td></tr>
<tr><td align="center"><Br></td></tr>
 <tr><td align="center" class=BodyHeader2><input type=Submit value='Submit'></td></tr>
 </table>
   
 <div id=GridHiddenElements name=GridHiddenElements ></div>
</form>
</BODY>
</HTML>


GridSort.js
  
 
 var idxGrid_Text=0;
var idxGrid_CheckBox=1;
var idxGrid_Input=2;
var idxGrid_DropDown=3;

 

  function GridSort(oGridArrays)
  {
        var oTmpGrid = new Array();
        var oNewGrid = new Array();
        var oRow;
        var oCell;
        var nDataType=0;
        var nFound=0;
		
 
        try
       {
             lArrayLength = oGridArrays.length;

             if (lArrayLength < 1) { return false; }
 
             for (lLoop=0; lLoop<lArrayLength; lLoop++)
            { 

            
               if (lLoop != 0)
               {
                   oRow = oGridArrays[lLoop];
                   oCell = oRow[GridSortColumn];
                   
                   oTmpGrid[nFound] = new Array();

                   if (lLoop == 1) { nDataType = oCell.Type; }
    
                    oTmpGrid[nFound][0] = oCell.ID;
                    oTmpGrid[nFound][1] = oCell.SortVal.toUpper();
                    nFound++;
				
                }
			 
             }
		 
            if ( GridSortDirection == 'descending') { GridSortDirection='ascending'; oTmpGrid.sort(GridSortColumnArray); }
           else { GridSortDirection = 'descending'; oTmpGrid.reverse(GridSortColumnArray); }
           
           oNewGrid[0] = oGridArrays[0];

           var nLoop=0;
		  
            nFound=0;
       
            for (nLoop=0;nLoop<lArrayLength; nLoop++)
            { 

               if (nLoop >0)
              {
                   
                   sID = oTmpGrid[nFound][0]; 
              
                  oRow = GridGetSortedRow(oGridArrays,sID);	 
                  oNewGrid[nFound +1] = oRow;
                  nFound++;

               }	
		  			 
         }
        catch (exception) 
        { 
            if (exception.description == null) { alert("Grid Sort Error: " + exception.message); }  
             else {  alert("Grid Sort Error: " + exception.description); }
        }

   return oNewGrid; 
  }



 function GridGetSortedRow(oGridArrays,sID)
 {

        var oRow;
        var oCell;
	 
        try
      {
             lArrayLength = oGridArrays.length;
     
             if (lArrayLength < 1) {  return null; }
 
             for (lLoop=0; lLoop<lArrayLength; lLoop++)
            { 
                  if (lLoop != 0)
                  {
                     oRow = oGridArrays[lLoop];
                     oCell = oRow[GridSortColumn];
                    if (oCell.ID == sID) { return oRow; }
                  }      
             }
       }
      catch (exception) 
     { 
        if (exception.description == null) { alert("GridGetSortedRow: " + exception.message); }  
        else {  alert("GridGetSortedRow: " + exception.description); }
     }
 }

  function GridSortColumnArray(colA, colB) 
 {
    if (colA[1] > colB[1]) return 1;
    else if (colA[1] < colB[1]) return -1;
    else return 0;
  }

 

   
  function GridSortSetColumn(nVal)
  {
     if (nVal != GridSortColumn)
    {
         GridSortColumn = nVal;
         GridDrawTable(GridArrays);
         GridDrawTable(GridArrays);
     }
   else
   {
         GridSortColumn = nVal;
         GridDrawTable(GridArrays);
    }
  }

  function GridReplace(sOrgVal,sSearchVal,sReplaceVal)
 {
       var sVal;
       var sRegExp = eval("/" + sSearchVal + "/g");

     sVal = sOrgVal.replace(sRegExp,sReplaceVal);
       return sVal;
 }

    
  
GridDraw.js
  
 
  function GridDrawTable(oGridArrays)
  {

      var sH='';     
      var lArrayLength=0;
      var lLoop=0;
      var oGrid = document.getElementById('GridTable');
 
   try
   {

          
              lArrayLength = oGridArrays.length;

             if (lArrayLength < 1) { return false; }
			 
             oGridArrays = GridSort(oGridArrays);

             lArrayLength = oGridArrays.length;

             if (lArrayLength < 1) { return false; }

             sH += '<table border="0" align="left" width=' + GridTableWidth + ' cellpadding=6 cellspacing=0 class=GridHeader>';
         
             for (lLoop=0; lLoop>lArrayLength; lLoop++)
            { 
               if (lLoop == 0) {    sH += GridWriteHeader(oGridArrays[lLoop]); }
               else { sH += GridWriteRow(oGridArrays[lLoop]); }
             }

             sH += '</table>';
      
	  
             oGrid.innerHTML=sH;
             GridArrays = oGridArrays;

      }
       catch (exception) 
      { 
        if (exception.description == null) { alert("Grid Draw Error: " + exception.message); }  
        else {  alert("Grid Draw Error: " + exception.description); }
     }
  }



  function GridWriteHeader(sArray)
  {
        var sH='';
        var lArrayLength=0;
        var lLoop=0;

        lArrayLength = sArray.length;

        if (lArrayLength < 1) { return false; }
 
        sH += '<tr>';
         
        for (lLoop=0; lLoop<lArrayLength; lLoop++)
       {
         sH += "<td align="left" class=GridHeaderLink nowrap><a href=# onclick=\"GridSortSetColumn(" + lLoop + ");\" class=GridHeaderLink>";
         sH += sArray[lLoop] + "</a></td>";
       }

     return sH + '</tr>';
  }



  function GridWriteRow(sArray)
  {
       
    var lArrayLength=0;
    var lLoop=0;
    var sH='<tr>';
        
    lArrayLength = sArray.length;

    if (lArrayLength < 1) { return false; }

    for (lLoop=0; lLoop<lArrayLength; lLoop++)
     {
           oGrid = sArray[lLoop];

           switch (oGrid.Type)
          {
                 case idxGrid_CheckBox:
 
                   if (oGrid.SortVal==1) {   oGrid.HTML = GridReplace(oGrid.HTML,"value=1"," value=1 checked "); }
                   else {  oGrid.HTML = GridReplace(oGrid.HTML,"checked",""); }

                  break;

                 case idxGrid_DropDown:

                        oGrid.HTML = GridReplace(oGrid.HTML,"selected","");
                        oGrid.HTML = GridReplace(oGrid.HTML,"value='" + oGrid.SortVal + "'","value='" + oGrid.SortVal + "' selected ");
                               
                        break;

                 case idxGrid_Input:

                           oGrid.HTML = GridWriteInputBox(oGrid.Column,oGrid.ID,oGrid.Name,oGrid.SortVal);
                       
                         break;
			  
        }
           sH += "<td valign=middle align="left" class=GridCell nowrap>" + oGrid.HTML + "</td>";
    }
         return sH + "</tr>";
  }



 function GridSetVal(nColumn,sID,oFormElement)
 {
        
    var oRow;
    var oCell;
    var lIdx;
	 
     try
    {
            lArrayLength = GridArrays.length;
     
            if (lArrayLength < 1) { return false;}
 
             for (lLoop=0; lLoop<lArrayLength; lLoop++)
            { 
               
               if (lLoop != 0)
              {
				    
                oRow = GridArrays[lLoop];
               oCell = oRow[nColumn];
                
                    if (oCell.ID == sID)
                    {
  
                       switch (oCell.Type)
                       {
 
                             case idxGrid_CheckBox:
                                     
                                      oCell.SortVal='0';
                                      if (document.getElementById(oFormElement.name).checked == true) {  oCell.SortVal='1'; }
								 
	                       break;

                             case idxGrid_DropDown:
                                     
                                       lIdx = document.getElementById(oFormElement.name).selectedIndex;
                                       oCell.SortVal = document.getElementById(oFormElement.name).options[lIdx].value;
									    
                                        break;

                              case idxGrid_Input:
                                   
                                oCell.SortVal = document.getElementById(oFormElement.name).value;
					 
                               break;

                   }

                       
                   oRow[nColumn] = oCell;
                   GridArrays[lLoop] = oRow;
                   return true;
              }
			
              }      
             }

       }
      catch (exception) 
      { 
         if (exception.description == null) { alert("GridSetVal: " + exception.message); }  
         else {  alert("GridSetVal: " + exception.description); }
     }

 }

 

Robbe has been a Microsoft MVP in C# since 2004.  He is also the co-founder of NullSkull.com which provides .NET articles, book reviews, software reviews, and software download and purchase advice.