JavaScript DHTML/GUI Components/Table Grid

Материал из Web эксперт
Перейти к: навигация, поиск

Содержание

Adding a table row

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD>

 <TITLe>Demo of DHTML Grid V 0.92</title>
 <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <META http-equiv="Author" content="Charles Dickens">
       <STYLE type="text/css"> 
   A:link {color:#FFFFFF;   font-weight: normal; text-decoration: none;}
   A:visited {color:#FFFFFF; font-weight: normal; text-decoration: none;}
   A:active {color:#FFFFFF; font-weight: normal; text-decoration: none;}
   A:hover {color:#FFFFFF; font-weight: normal; text-decoration:underline;}
   BODY {bottom-Margin:0px; background-color:#003399; left-Margin:20px;
     top-Margin:0px; right-Margin:0px; color:#FFFFFF}
   TD {font-family: "Verdana, Arial"; font-size: 12px;}
   .bigheader {font-family: "Verdana, Arial"; font-size: 28px; font-weight: bold}
   .mnuheader {font-family: "Verdana, Arial"; font-size: 16px;}
   .inputBox { border-style: solid; border-width: 1px; font-family: verdana, arial,
       sans-serif; font-size: 9px; padding: 0px; color:black; backgroundcolor: #FFFFEE}
 </STYLE>

</HEAD> <BODY>

     THE 
     <DHTML> 
     Grid
                     
¤ This is the test area for ver 0.92 which will be released soon. For the latest stable release click on the download link above. ¤
                     <IFRAME id="frmGrid1" name="frmGrid1" scrolling="auto" frameborder="0" src="4colGrid.htm" width="601" height="150"></IFRAME>
                     Col 1                   Col 2                   Col 3                   Col 4
<FORM> <INPUT id="Col1" style="FONT-SIZE: 8pt; LEFT: 0px; WIDTH: 102px; BORDER-TOP-STYLE: none; FONT-FAMILY: Verdana, Arial; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none" type="text" maxLength="6" name="Col1"> <INPUT id="Col2" style="FONT-SIZE: 8pt; LEFT: 0px; WIDTH: 102px; BORDER-TOP-STYLE: none; FONT-FAMILY: Verdana, Arial; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none" type="text" maxLength="6" name="Col2"> <INPUT id="Col3" style="FONT-SIZE: 8pt; LEFT: 0px; WIDTH: 102px; BORDER-TOP-STYLE: none; FONT-FAMILY: Verdana, Arial; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none" type="text" maxLength="6" name="Col3"> <INPUT id="Col4" style="FONT-SIZE: 8pt; LEFT: 0px; WIDTH: 102px; BORDER-TOP-STYLE: none; FONT-FAMILY: Verdana, Arial; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none" type="text" maxLength="6" name="Col4">
<INPUT value="ADD" name="cmdAddRow" id="cmdAddRow" title="Add Row" style="FONT-WEIGHT: bold; FONT-SIZE: 8pt; LEFT: 0px; WIDTH: 102px; FONT-FAMILY: Verdana, Arial;" type="button" onclick="javascript: top.frames["frmGrid1"].addRow(Col1.value, Col2.value , Col3.value, Col4.value), Col1.value="", Col2.value="", Col3.value="", Col4.value="";" > <INPUT value="Delete" name="cmdDeleteRow" id="cmdDeleteRow" title="Delete Last Row" style="FONT-SIZE: 8pt; LEFT: 93px; WIDTH: 102px; FONT-FAMILY: Verdana, Arial; " type="button" onclick="javascript: return top.frames["frmGrid1"].deleteLastRow()"> </FORM>

¤ The biggest feature of ver 0.92 is that it works both IE 5+ and in Netscape 6+
¤ Mouseover to select a row.
¤ Select any row and hit Delete key to delete it
¤ Click to edit.... and everything else
 </BODY>

</HTML>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/AddTableRow.zip">AddTableRow.zip( 9 k)</a>


Ajax Table

<A href="http://www.wbex.ru/Code/JavaScriptDownload/MochiKit-1.3.1.zip">MochiKit-1.3.1.zip( 302 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Basic Grid (Table)

   <source lang="html4strict">

<html>

<head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedlightshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>
 
 <script>
   var myData = [
     ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
     ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"],
     ["SAP", "SAP AG (ADR)", "40,986.328", "8,296.420", "28961"],
     ["CA", "Computer Associates Inter", "15,606.335", "3,164.000", "16000"],
     ["ERTS", "Electronic Arts Inc.", "14,490.895", "2,503.727", "4000"],
     ["SFTBF", "Softbank Corp. (ADR)", "14,485.840", ".000", "6865"],
     ["VRTS", "Veritas Software Corp.", "14,444.272", "1,578.658", "5647"],
     ["SYMC", "Symantec Corporation", "9,932.483", "1,482.029", "4300"],
     ["INFY", "Infosys Technologies Ltd.", "9,763.851", "830.748", "15400"],
     ["INTU", "Intuit Inc.", "9,702.477", "1,650.743", "6700"],
     ["ADBE", "Adobe Systems Incorporate", "9,533.050", "1,230.817", "3341"],
     ["PSFT", "PeopleSoft, Inc.", "8,246.467", "1,941.167", "8180"],
     ["SEBL", "Siebel Systems, Inc.", "5,434.649", "1,417.952", "5909"],
     ["BEAS", "BEA Systems, Inc.", "5,111.813", "965.694", "3063"],
     ["SNPS", "Synopsys, Inc.", "4,482.535", "1,169.786", "4254"],
     ["CHKP", "Check Point Software Tech", "4,396.853", "424.769", "1203"],
     ["MERQ", "Mercury Interactive Corp.", "4,325.488", "444.063", "1822"],
     ["DOX", "Amdocs Limited", "4,288.017", "1,427.088", "9400"],
     ["CTXS", "Citrix Systems, Inc.", "3,946.485", "554.222", "1670"],
     ["KNM", "Konami Corporation (ADR)", "3,710.784", ".000", "4313"]
   ];
   var myColumns = [
     "Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"
   ];
 </script>

</head> <body>

 <script>
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  set number of rows/columns
 obj.setRowProperty("count", 20);
 obj.setColumnProperty("count", 5);
 //  provide cells and headers text
 obj.setDataProperty("text", function(i, j){return myData[i][j]});
 obj.setColumnProperty("text", function(i){return myColumns[i]});
 //  set headers width/height
 obj.setRowHeaderWidth("28px");
 obj.setColumnHeaderHeight("20px");
 //  set click action handler
 obj.setAction("click", function(src){window.status = src.getItemProperty("text")});
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Build a Grid (Table) from CSV data file

   <source lang="html4strict">


<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create ActiveWidgets data model - text-based table
 var table = new Active.Text.Table;
 //  provide data URL - plain text comma-separated file
 table.setURL("gridExamples/data/companies.csv");
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Build a Grid (Table) from yahoo quotes (IE only)

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width: 80px;}
   .active-column-1 {width: 80px; text-align: right; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-column-5 {text-align: right;}
   .active-column-6 {text-align: right;}
   .active-column-7 {text-align: right;}
   .active-column-8 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create ActiveWidgets data model - text-based table
 var table = new Active.Text.Table;
 //  Yahoo provides 15min delayed stock quotes in CSV format
 var url = "http://finance.yahoo.ru/d/quotes.csv?s=" +
       "MSFT,ORCL,SAP,CA,ERTS,SFTBF,VRTS,SYMC,INFY,INTU,ADBE,PSFT,SEBL,BEAS,SNPS,CHKP,MERQ,DOX,CTXS,KNM" +
       "&f=sl1d1t1c1ohgv&e=.csv";
 //  set data URL
 table.setURL(url);
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columnNames = ["Ticker", "Last", "Date", "Time", "Change", "Close", "Open", "High", "Volume"];
 var columnOrder = [0, 1, 4, 8, 3, 2, 5, 6, 7];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columnNames);
 obj.setColumnProperty("values", columnOrder);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Build a Grid (Tree) from a tab separated file

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create ActiveWidgets data model - text-based table
 var table = new Active.Text.Table;
 //  provide data URL - plain text tabs-separated file
 table.setURL("gridExamples/data/companies.txt");
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Call back action in Grid Table

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 5</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Example 5 - Custom Callbacks

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   how to refine actions when the user clicks on column titles.
   we"ll show an "Hello World!" message box when the user clicks on "Lastname".
        // Column 1 will print "hello world" on click
        g.set_click_cb ( 1, "alert ( "hello world!" )" );
        // Column "Lastname" does not produce any event on click
        g.set_click_cb ( 2, -1 );
    
   how to call a function each time the grid is rendered. 
   To set a callback each time the grid is rendered on screen, 
   simply refine the "onrender" attribute:
        // A callback for each render event
        g.onrender = rendered;
    
   Callback function should get one argument (the grid instance) like this one:
        function rendered ( grid )
        {
          alert ( "Grid: " + grid.id + " rendered" );
        }
    
     <script type="text/javascript">
       function rendered ( grid )
       {
         alert ( "Grid: " + grid.id + " rendered" );
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "Age" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", 33 );
       g.add_row ( "john", "John", "Bustone", 31 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       // Enable sortable rows
       g.set_sortable ( true );
       // "Age" column is an integer number
       g.set_col_type ( 3, "int" );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       // Column 1 will print "hello world" on click
       g.set_click_cb ( 1, "alert ( "hello world!" )" );
       // The second column is not clickable
       g.set_click_cb ( 2, -1 );
       // A callback for each render event
       g.onrender = rendered;
       
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Create 100 random rows and do the column sorting

   <source lang="html4strict">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html>

 <head>
   <title>Table Sorter Proof of Concept</title>
   <style type="text/css">

table {

 width: 80%;
 margin: 1em auto;
 border-collapse: collapse;

} thead th, tfoot th {

 padding: 0.5em;
 text-align: left;
 border: 1px solid black;
 background-color: #AAF;

} tfoot td {

 border-top: 1px solid black;

} tbody td {

 padding: 0.5em;
 border-left: 1px solid black;
 border-right: 1px solid black;

} tbody tr.odd {

 background-color: #DDF;

} td.numeric, th.numeric {

 text-align: right;

}

   </style>
       
   <script type="text/javascript">
   /**
* addEvent written by Dean Edwards, 2005
* with input from Tino Zijdel
*
* http://dean.edwards.name/weblog/2005/10/add-event/
**/

function addEvent(element, type, handler) {

 // assign each event handler a unique ID
 if (!handler.$$guid) handler.$$guid = addEvent.guid++;
 // create a hash table of event types for the element
 if (!element.events) element.events = {};
 // create a hash table of event handlers for each element/event pair
 var handlers = element.events[type];
 if (!handlers) {
   handlers = element.events[type] = {};
   // store the existing event handler (if there is one)
   if (element["on" + type]) {
     handlers[0] = element["on" + type];
   }
 }
 // store the event handler in the hash table
 handlers[handler.$$guid] = handler;
 // assign a global event handler to do all the work
 element["on" + type] = handleEvent;

}; // a counter used to create unique IDs addEvent.guid = 1; function removeEvent(element, type, handler) {

 // delete the event handler from the hash table
 if (element.events && element.events[type]) {
   delete element.events[type][handler.$$guid];
 }

}; function handleEvent(event) {

 var returnValue = true;
 // grab the event object (IE uses a global event object)
 event = event || fixEvent(window.event);
 // get a reference to the hash table of event handlers
 var handlers = this.events[event.type];
 // execute each event handler
 for (var i in handlers) {
   this.$$handleEvent = handlers[i];
   if (this.$$handleEvent(event) === false) {
     returnValue = false;
   }
 }
 return returnValue;

}; function fixEvent(event) {

 // add W3C standard event methods
 event.preventDefault = fixEvent.preventDefault;
 event.stopPropagation = fixEvent.stopPropagation;
 return event;

}; fixEvent.preventDefault = function() {

 this.returnValue = false;

}; fixEvent.stopPropagation = function() {

 this.cancelBubble = true;

}; // end from Dean Edwards

/**

* Creates an Element for insertion into the DOM tree.
* From http://simon.incutio.ru/archive/2003/06/15/javascriptWithXML
*
* @param element the element type to be created.
*        e.g. ul (no angle brackets)
**/

function createElement(element) {

 if (typeof document.createElementNS != "undefined") {
   return document.createElementNS("http://www.w3.org/1999/xhtml", element);
 }
 if (typeof document.createElement != "undefined") {
   return document.createElement(element);
 }
 return false;

} /**

* "targ" is the element which caused this function to be called
* from http://www.quirksmode.org/js/events_properties.html
**/

function getEventTarget(e) {

 var targ;
 if (!e) {
   e = window.event;
 }
 if (e.target) {
   targ = e.target;
 } else if (e.srcElement) {
   targ = e.srcElement;
 }
 if (targ.nodeType == 3) { // defeat Safari bug
   targ = targ.parentNode;
 }
 return targ;

}

   </script>
   
   <script type="text/javascript">

/**

* Written by Neil Crosby. 
* http://www.workingwith.me.uk/
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
* SOFTWARE.
**/

var css = {

 /**
  * Returns an array containing references to all elements
  * of a given tag type within a certain node which have a given class
  *
  * @param node    the node to start from 
  *          (e.g. document, 
  *              getElementById("whateverStartpointYouWant")
  *          )
  * @param searchClass the class we"re wanting
  *          (e.g. "some_class")
  * @param tag     the tag that the found elements are allowed to be
  *          (e.g. "*", "div", "li")
  **/
 getElementsByClass : function(node, searchClass, tag) {
   var classElements = new Array();
   var els = node.getElementsByTagName(tag);
   var elsLen = els.length;
   var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
   
   
   for (var i = 0, j = 0; i < elsLen; i++) {
     if (this.elementHasClass(els[i], searchClass) ) {
       classElements[j] = els[i];
       j++;
     }
   }
   return classElements;
 },
 /**
  * PRIVATE.  Returns an array containing all the classes applied to this
  * element.
  *
  * Used internally by elementHasClass(), addClassToElement() and 
  * removeClassFromElement().
  **/
 privateGetClassArray: function(el) {
   return el.className.split(" "); 
 },
 /**
  * PRIVATE.  Creates a string from an array of class names which can be used 
  * by the className function.
  *
  * Used internally by addClassToElement().
  **/
 privateCreateClassString: function(classArray) {
   return classArray.join(" ");
 },
 /**
  * Returns true if the given element has been assigned the given class.
  **/
 elementHasClass: function(el, classString) {
   if (!el) {
     return false;
   }
   
   var regex = new RegExp("\\b"+classString+"\\b");
   if (el.className.match(regex)) {
     return true;
   }
   return false;
 },
 /**
  * Adds classString to the classes assigned to the element with id equal to
  * idString.
  **/
 addClassToId: function(idString, classString) {
   this.addClassToElement(document.getElementById(idString), classString);
 },
 /**
  * Adds classString to the classes assigned to the given element.
  * If the element already has the class which was to be added, then
  * it is not added again.
  **/
 addClassToElement: function(el, classString) {
   var classArray = this.privateGetClassArray(el);
   if (this.elementHasClass(el, classString)) {
     return; // already has element so don"t need to add it
   }
   classArray.push(classString);
   el.className = this.privateCreateClassString(classArray);
 },
 /**
  * Removes the given classString from the list of classes assigned to the
  * element with id equal to idString
  **/
 removeClassFromId: function(idString, classString) {
   this.removeClassFromElement(document.getElementById(idString), classString);
 },
 /**
  * Removes the given classString from the list of classes assigned to the
  * given element.  If the element has the same class assigned to it twice, 
  * then only the first instance of that class is removed.
  **/
 removeClassFromElement: function(el, classString) {
   var classArray = this.privateGetClassArray(el);
   for (x in classArray) {
     if (classString == classArray[x]) {
       classArray[x] = "";
       break;
     }
   }
   el.className = this.privateCreateClassString(classArray);
 }

}

   </script>
   
   <script type="text/javascript">

/**

* Written by Neil Crosby. 
* http://www.workingwith.me.uk/articles/scripting/standardista_table_sorting
*
* This module is based on Stuart Langridge"s "sorttable" code.  Specifically, 
* the determineSortFunction, sortCaseInsensitive, sortDate, sortNumeric, and
* sortCurrency functions are heavily based on his code.  This module would not
* have been possible without Stuart"s earlier outstanding work.
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
* SOFTWARE.
**/

var standardistaTableSorting = {

 that: false,
 isOdd: false,
 sortColumnIndex : -1,
 lastAssignedId : 0,
 newRows: -1,
 lastSortedTable: -1,
 /**
  * Initialises the Standardista Table Sorting module
  **/
 init : function() {
   // first, check whether this web browser is capable of running this script
   if (!document.getElementsByTagName) {
     return;
   }
   
   this.that = this;
   
   this.run();
   
 },
 
 /**
  * Runs over each table in the document, making it sortable if it has a class
  * assigned named "sortable" and an id assigned.
  **/
 run : function() {
   var tables = document.getElementsByTagName("table");
   
   for (var i=0; i < tables.length; i++) {
     var thisTable = tables[i];
     
     if (css.elementHasClass(thisTable, "sortable")) {
       this.makeSortable(thisTable);
     }
   }
 },
 
 /**
  * Makes the given table sortable.
  **/
 makeSortable : function(table) {
 
   // first, check if the table has an id.  if it doesn"t, give it one
   if (!table.id) {
     table.id = "sortableTable"+this.lastAssignedId++;
   }
   
   // if this table does not have a thead, we don"t want to know about it
   if (!table.tHead || !table.tHead.rows || 0 == table.tHead.rows.length) {
     return;
   }
   
   // we"ll assume that the last row of headings in the thead is the row that 
   // wants to become clickable
   var row = table.tHead.rows[table.tHead.rows.length - 1];
   
   for (var i=0; i < row.cells.length; i++) {
   
     // create a link with an onClick event which will 
     // control the sorting of the table
     var linkEl = createElement("a");
     linkEl.href = "#";
     linkEl.onclick = this.headingClicked;
     linkEl.setAttribute("columnId", i);
     linkEl.title = "Click to sort";
     
     // move the current contents of the cell that we"re 
     // hyperlinking into the hyperlink
     var innerEls = row.cells[i].childNodes;
     for (var j = 0; j < innerEls.length; j++) {
       linkEl.appendChild(innerEls[j]);
     }
     
     // and finally add the new link back into the cell
     row.cells[i].appendChild(linkEl);
     var spanEl = createElement("span");
     spanEl.className = "tableSortArrow";
     spanEl.appendChild(document.createTextNode("\u00A0\u00A0"));
     row.cells[i].appendChild(spanEl);
   }
 
   if (css.elementHasClass(table, "autostripe")) {
     this.isOdd = false;
     var rows = table.tBodies[0].rows;
   
     // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
     for (var i=0;i<rows.length;i++) { 
       this.doStripe(rows[i]);
     }
   }
 },
 
 headingClicked: function(e) {
   
   var that = standardistaTableSorting.that;
   
   // linkEl is the hyperlink that was clicked on which caused
   // this method to be called
   var linkEl = getEventTarget(e);
   
   // directly outside it is a td, tr, thead and table
   var td     = linkEl.parentNode;
   var tr     = td.parentNode;
   var thead  = tr.parentNode;
   var table  = thead.parentNode;
   
   // if the table we"re looking at doesn"t have any rows
   // (or only has one) then there"s no point trying to sort it
   if (!table.tBodies || table.tBodies[0].rows.length <= 1) {
     return false;
   }
   // the column we want is indicated by td.cellIndex
   var column = linkEl.getAttribute("columnId") || td.cellIndex;
   //var column = td.cellIndex;
   
   // find out what the current sort order of this column is
   var arrows = css.getElementsByClass(td, "tableSortArrow", "span");
   var previousSortOrder = "";
   if (arrows.length > 0) {
     previousSortOrder = arrows[0].getAttribute("sortOrder");
   }
   
   // work out how we want to sort this column using the data in the first cell
   // but just getting the first cell is no good if it contains no data
   // so if the first cell just contains white space then we need to track
   // down until we find a cell which does contain some actual data
   var itm = ""
   var rowNum = 0;
   while ("" == itm && rowNum < table.tBodies[0].rows.length) {
     itm = that.getInnerText(table.tBodies[0].rows[rowNum].cells[column]);
     rowNum++;
   }
   var sortfn = that.determineSortFunction(itm);
   // if the last column that was sorted was this one, then all we need to 
   // do is reverse the sorting on this column
   if (table.id == that.lastSortedTable && column == that.sortColumnIndex) {
     newRows = that.newRows;
     newRows.reverse();
   // otherwise, we have to do the full sort
   } else {
     that.sortColumnIndex = column;
     var newRows = new Array();
     for (var j = 0; j < table.tBodies[0].rows.length; j++) { 
       newRows[j] = table.tBodies[0].rows[j]; 
     }
     newRows.sort(sortfn);
   }
   that.moveRows(table, newRows);
   that.newRows = newRows;
   that.lastSortedTable = table.id;
   
   // now, give the user some feedback about which way the column is sorted
   
   // first, get rid of any arrows in any heading cells
   var arrows = css.getElementsByClass(tr, "tableSortArrow", "span");
   for (var j = 0; j < arrows.length; j++) {
     var arrowParent = arrows[j].parentNode;
     arrowParent.removeChild(arrows[j]);
     if (arrowParent != td) {
       spanEl = createElement("span");
       spanEl.className = "tableSortArrow";
       spanEl.appendChild(document.createTextNode("\u00A0\u00A0"));
       arrowParent.appendChild(spanEl);
     }
   }
   
   // now, add back in some feedback 
   var spanEl = createElement("span");
   spanEl.className = "tableSortArrow";
   if (null == previousSortOrder || "" == previousSortOrder || "DESC" == previousSortOrder) {
     spanEl.appendChild(document.createTextNode(" \u2191"));
     spanEl.setAttribute("sortOrder", "ASC");
   } else {
     spanEl.appendChild(document.createTextNode(" \u2193"));
     spanEl.setAttribute("sortOrder", "DESC");
   }
   
   td.appendChild(spanEl);
   
   return false;
 },
 getInnerText : function(el) {
   
   if ("string" == typeof el || "undefined" == typeof el) {
     return el;
   }
   
   if (el.innerText) {
     return el.innerText;  // Not needed but it is faster
   }
   var str = el.getAttribute("standardistaTableSortingInnerText");
   if (null != str && "" != str) {
     return str;
   }
   str = "";
   var cs = el.childNodes;
   var l = cs.length;
   for (var i = 0; i < l; i++) {
     // "if" is considerably quicker than a "switch" statement, 
     // in Internet Explorer which translates up to a good time 
     // reduction since this is a very often called recursive function
     if (1 == cs[i].nodeType) { // ELEMENT NODE
       str += this.getInnerText(cs[i]);
       break;
     } else if (3 == cs[i].nodeType) { //TEXT_NODE
       str += cs[i].nodeValue;
       break;
     }
   }
   
   // set the innertext for this element directly on the element
   // so that it can be retrieved early next time the innertext
   // is requested
   el.setAttribute("standardistaTableSortingInnerText", str);
   
   return str;
 },
 determineSortFunction : function(itm) {
   
   var sortfn = this.sortCaseInsensitive;
   
   if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) {
     sortfn = this.sortDate;
   }
   if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) {
     sortfn = this.sortDate;
   }
   if (itm.match(/^[£$]/)) {
     sortfn = this.sortCurrency;
   }
   if (itm.match(/^\d?\.?\d+$/)) {
     sortfn = this.sortNumeric;
   }
   if (itm.match(/^[+-]?\d*\.?\d+([eE]-?\d+)?$/)) {
     sortfn = this.sortNumeric;
   }
       if (itm.match(/^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$/)) {
           sortfn = this.sortIP;
      }
   return sortfn;
 },
 
 sortCaseInsensitive : function(a, b) {
   var that = standardistaTableSorting.that;
   
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase();
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase();
   if (aa==bb) {
     return 0;
   } else if (aa<bb) {
     return -1;
   } else {
     return 1;
   }
 },
 
 sortDate : function(a,b) {
   var that = standardistaTableSorting.that;
   // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]);
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]);
   
   var dt1, dt2, yr = -1;
   
   if (aa.length == 10) {
     dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
   } else {
     yr = aa.substr(6,2);
     if (parseInt(yr) < 50) { 
       yr = "20"+yr; 
     } else { 
       yr = "19"+yr; 
     }
     dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
   }
   
   if (bb.length == 10) {
     dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
   } else {
     yr = bb.substr(6,2);
     if (parseInt(yr) < 50) { 
       yr = "20"+yr; 
     } else { 
       yr = "19"+yr; 
     }
     dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
   }
   
   if (dt1==dt2) {
     return 0;
   } else if (dt1<dt2) {
     return -1;
   }
   return 1;
 },
 sortCurrency : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,"");
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,"");
   return parseFloat(aa) - parseFloat(bb);
 },
 sortNumeric : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = parseFloat(that.getInnerText(a.cells[that.sortColumnIndex]));
   if (isNaN(aa)) { 
     aa = 0;
   }
   var bb = parseFloat(that.getInnerText(b.cells[that.sortColumnIndex])); 
   if (isNaN(bb)) { 
     bb = 0;
   }
   return aa-bb;
 },
 makeStandardIPAddress : function(val) {
   var vals = val.split(".");
   for (x in vals) {
     val = vals[x];
     while (3 > val.length) {
       val = "0"+val;
     }
     vals[x] = val;
   }
   val = vals.join(".");
   return val;
 },
 sortIP : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = that.makeStandardIPAddress(that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase());
   var bb = that.makeStandardIPAddress(that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase());
   if (aa==bb) {
     return 0;
   } else if (aa<bb) {
     return -1;
   } else {
     return 1;
   }
 },
 moveRows : function(table, newRows) {
   this.isOdd = false;
   // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
   for (var i=0;i<newRows.length;i++) { 
     var rowItem = newRows[i];
     this.doStripe(rowItem);
     table.tBodies[0].appendChild(rowItem); 
   }
 },
 
 doStripe : function(rowItem) {
   if (this.isOdd) {
     css.addClassToElement(rowItem, "odd");
   } else {
     css.removeClassFromElement(rowItem, "odd");
   }
   
   this.isOdd = !this.isOdd;
 }

} function standardistaTableSortingInit() {

 standardistaTableSorting.init();

} addEvent(window, "load", standardistaTableSortingInit)

   </script>
 </head>
 <body>
<thead> </thead> <tbody> <script> for (var i=0; i < 100; i++) { var number = Math.round(Math.random()*1000); var day = (1 + Math.round(Math.random()*30)); if (day < 10) { day = "0" + day; } var month = (1 + Math.round(Math.random()*11)); if (month < 10) { month = "0" + month; } var year = (1990 + Math.round(Math.random()*16)); var pennies = (1 + Math.round(Math.random()*99)); if (pennies < 10) { pennies = "0" + pennies; } var pounds = (1 + Math.round(Math.random()*1500)); var date = day + "/" + month + "/" + year; document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); document.write(""); } </script> </tbody>
Heading Heading Heading Heading Heading Heading Heading Heading
"+number+""+date+"$"+pounds+"."+pennies+""+number+""+date+"$"+pounds+"."+pennies+""+number+""+date+"
 </body>

</html>


 </source>
   
  


Data in Grid (Table) from XML file

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-column-5 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create data formats
 var string = new Active.Formats.String;
 var number1 = new Active.Formats.Number;
 var number2 = new Active.Formats.Number;
 var date = new Active.Formats.Date;
 //  define formatting rule for text output
 number1.setTextFormat("#,###.##");
 number2.setTextFormat("");
 date.setTextFormat("dd mmm yy");
 date.setDataFormat("ISO8061");
 //  create ActiveWidgets data model - XML-based table
 var table = new Active.XML.Table;
 //  provide data URL
 table.setURL("gridExamples/data/companies-array.xml");
 //  define namespace for selecting column data
 table.setNamespace("co", "http://tempuri.org/");
 //  set column XPath
 table.setColumns(["co:ticker", "co:name", "co:marketcap", "co:sales", "co:employees", "co:timestamp"]);
 //  set column formatting
 table.setFormats([string, string, number1, number1, number2, date]);
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees", "Date"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Drag and drop table columns

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ddi.1.5.2.all-in-one.zip">ddi.1.5.2.all-in-one.zip( 47 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Dynamic data grid: add a row, remove a row and sort column

<A href="http://www.wbex.ru/Code/JavaScriptDownload/LWcomponents_0_4.zip">LWcomponents_0_4.zip( 29 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Editable Grid Table cell

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 4 - Editable Grid</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Example 4 - Editable Grid

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   how to edit the grid.
First to set the editable columns:
        g.set_col_editable ( 1, "txt" );
        g.set_col_editable ( 2, "txt" );
        g.set_col_editable ( 3, "txt" );
    
   force the user to insert a valid e-mail by
   filtering his/her typing against the given string and by adding a field validator:
        g.set_col_valid_chars ( 3, "abcdefghijklmnopqrstuvwxyz@.-0123456789_" );
        g.set_col_validation ( 3, check_email );
    
   The check_email is a form validation function defined inside form_validators.js.
      <script src="form_validators.js" type="text/javascript"></script>
    
   grid rows to be automatically resorted when the user changes grid contents, simply
   set this flag to true:  
 
        g.sort_on_edit = true;
    
     <script type="text/javascript">
       function val_changed ( grid, x, y, new_val )
       {
         alert ( "On grid: " + grid.id + " x: " + x + " y: " + y + " - value changed to: " + new_val );
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "E-Mail Address" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", "fsoft (@) sourceforge (dot) net" );
       g.add_row ( "john", "John", "Bustone", "jbust (@) somewhere (dot) net" );
       g.add_row ( "mkey", "Mark", "Key", "mkey (@) okay (dot) net" );
       g.add_row ( "jdoe", "John", "Doe", "redbull (@) batman (dot) net" );
       // Enable sortable rows
       g.set_sortable ( true );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       g.set_col_editable ( 1, "txt" );
       g.set_col_editable ( 2, "txt" );
       g.set_col_editable ( 3, "txt" );
       g.onchange = val_changed;
       g.set_col_valid_chars ( 3, "abcdefghijklmnopqrstuvwxyz@.-0123456789_" );
       g.set_col_validation ( 3, check_email );
       g.set_row_select ( true );
       g.sort_on_edit = true;
       
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Editable table cell

   <source lang="html4strict">

<HTML> <HEAD>

 <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 <META http-equiv="Author" content="Charles Dickens" />
 <TITLE> HTML Grid Demo Ver 0.1.1</title>
 <STYLE type="text/css">
   input { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 9px; padding: 0px; color:black; backgroundcolor: #FFFFEE}
   td { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 10px; padding: 0px;}
 
 </STYLE>
 <SCRIPT type="text/javascript">

/*\ |*| Version : 0.92 |*| Author  : Chaitanya Yinti |*| Contact : yinti@users.sourceforge.net |*| WebSite : http://dhtmlgrid.sourceforge.net/ |*| |*| Feel free to use this script under the terms of the GNU General Public |*| License, as long as you do not remove or alter this notice. \*/

 /*************************************\
 |       Start of Config Param         |
 \*************************************/
 // Color used for hilighting a selected row
 var clrHilight = "blue";
 // Set this to false if you want "click to select" and
 // "doubleclick to Edit" mode
 var blnPointToSelect = true;
 // Full path of the blank image used to hide the sort images 
 var strBlankImage = "blank.gif";
 // Full path of the up image used on sort asc
 var strUpImage = "up.gif";  
 // Full path of the up image used on sort des
 var strDownImage = "down.gif";
 // The width of the images used to indicate the asc/des sort
 var intImgWidth = 12;
 // The height of the images used to indicate the asc/des sort
 var intImgHeight = 13;  
 /*************************************\
 |           End of Config Param       |
 \*************************************/
 /*************************************\
 |           Globals start             |
 \*************************************/
 // Stores the last used object during sort
 var objLastClick = -1;
 // Stores the text being edited
 var txtOld = "";
 // Stores the total table width
 var intTotalWidth = 0;
 // Stores the flag used by capturemouse
 var blnMouseOver = false;  
 // Stores the div being moved
 var objDivToMove = null;
 // Stores the number of coloumns; initialized in init ()
 var intColCount = 0;
 // Stores the row element currently selected
 var objRowSelected = null;
 //THE element which holds the table... 
 var element = null;
 /*************************************\
 |           Globals end               |
 \*************************************/
 /*********************TODO*****************************\
  prototype setCapture/releaseCapture PROPERLY
  Get rid of isIE, isNS4 completely ...
  Extend keycapture to navigate the table on up/down arrow
  Fix escape/unescape on text change
 \******************************************************/
   
 /*\
 |*| The entry point. This will 
 |*|    Attache all the appropriate functions to the table
 |*|    Call function to create the IMG elems used during the sorting
 |*|    call function to init the DIV elems that are used for moving
 |*|    call function to init the DIV elems used for about box
 \*/
 function init (tableName)
 {
   //Handle all javascript errors 
   window.onerror = handleError;
   isIE = (navigator.appVersion.indexOf ("MSIE") != -1);
   isNS4 = (document.layers) ? true : false;
   isNS6 = (!document.layers) && (navigator.userAgent.indexOf ("Netscape")!=-1);
   if ((isNS4) && (!isNS6)) alert ("Currently only supports NN 6 and above");
   if (document.getElementById)
     element = document.getElementById (tableName);
   else  //TODO: Need to test this piece of code still. Happens only in NN4 so far 
     eval (element = "document." + tableName);
   if (element == null)
     return alert ("Error: Not able to get table element ");
   if (element.tagName != "TABLE")
     return alert ("Error: Not able to control element " + element.tagName);
   initNNFunctions ();
   if (blnPointToSelect)
   {
     element.attachEvent ("onmouseover", selectRow);
     element.attachEvent ("onclick", onClickCell);
   }
   else
   {
     element.attachEvent ("onclick", selectRow);
     element.attachEvent ("ondblclick", onClickCell);
   }
   document.attachEvent ("onkeydown" , captureDelKey);
   //Need this fix for IE only .. so element.focus is stubbed in NN
   element.focus ();
 
   initSortImages ();
   initDiv ();
   initAbout ();
 }
 /*\
 |*| This function removes the textnodes from the table rows.
 |*| This cleanup work is needed to get rid of the EXTRA textnodes that NN gives
 \*/
 function removeTextNodes (t)
 {
   for (var i = 0; t.childNodes[i] ; i++)
   {
     if (!t.childNodes[i].tagName)
     {
        t.childNodes[i].parentNode.removeChild (t.childNodes[i]);
     }
     else
     {
       for (var j = 0; t.childNodes[i].childNodes[j] ; j++)
       {
         if (!t.childNodes[i].childNodes[j].tagName) 
           t.childNodes[i].childNodes[j].parentNode.removeChild (t.childNodes[i].childNodes[j]);
       }
     }
   }
 }
 /*\
 |*| This function adds the blank images to the head row of the table
 \*/
 function initSortImages ()
 {
   if (!element.tHead) return;
   removeTextNodes (element.tHead);
   var theadrow = element.tHead.childNodes[0]; //Assume just one Head row
   if (isIE) theadrow.style.cursor = "hand";
   else theadrow.style.cursor = "pointer";
   removeTextNodes (theadrow.parentNode);
   intColCount = theadrow.childNodes.length;
   for (var i = 0; i < intColCount; i++) 
   {
     objImg = document.createElement ("IMG");
     objImg.setAttribute ("src", strBlankImage);
     objImg.setAttribute ("id", "srtImg" + i);
     objImg.setAttribute ("width", intImgWidth);
     objImg.setAttribute ("height", intImgHeight);
     objImg.setAttribute ("align", "right");
     objImg.setAttribute ("valign", "middle");
     objImg.setAttribute ("border", 0);
     clickCell = theadrow.childNodes[i];
     clickCell.selectIndex = i;
     clickCell.insertAdjacentElement ("afterBegin", objImg);
     clickCell.style.width = clickCell.width;
   }
 }
 /*\
 |*| This will only be called once during initIALIZATION
 |*| This will create the DIV elems at the end of each col and
 |*| attach all the functions needed to resize the coloumns
 \*/
 function initDiv ()
 {
   var objLast = element, objDiv;
   removeTextNodes (element.tBodies[0]);
   for (var i = 1; i <= intColCount; i++)
   {  
     objDiv = document.createElement ("DIV");
     objDiv.setAttribute ("id", "DragMark" + (i - 1));
     objDiv.setAttribute ("name",  i);    //Used to track the TDs that have to be moved
     objDiv.style.position = "absolute";
     objDiv.style.top = 0; 
     var objTD = element.tHead.childNodes[0].childNodes[i - 1];
     if (!objTD || objTD.tagName != "TD") return;
     var intColWidth = (getRealPos (objTD) - 0) + (objTD.width - 0);
     objDiv.style.left = intColWidth - 3 ;
     objDiv.style.width = 6 + parseInt(element.border);
     objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * objTD.offsetHeight;
     // for debugging only
     //objDiv.style.backgroundColor = clrHilight;
     
     //To make it more beautiful in IE 6  
     if (navigator.appVersion.indexOf ("MSIE 6.0") != -1)
       objDiv.style.cursor = "col-resize";
     else
       objDiv.style.cursor = "crosshair";
     objDiv.attachEvent ("onmouseover", flagTrue);
     objDiv.attachEvent ("onmousedown", captureMouse);
     objDiv.attachEvent ("onmousemove", resizeColoumn);
     objDiv.attachEvent ("onmouseup", releaseMouse);
     objDiv.attachEvent ("onmouseout", flagFalse);
     objLast.insertAdjacentElement ("afterEnd", objDiv);
     objLast = objDiv;
   }
 }
 /*\
 |*| This function will be fired onmouseover of the DIVs
 |*| Set the flag to true indicating that the mouse is over the DIV
 \*/
 function flagTrue ()
 {
   blnMouseOver = true;
 }
 /*\
 |*| This function will be fired onmousedown on the DIVs
 |*| Capture all the mosue events if mousedown is fired inside the DIV
 \*/
 function captureMouse ()
 {
   if (blnMouseOver)
   {
     objDivToMove = window.event.srcElement;
     objDivToMove.setCapture ();
   }
 }
 /*\
 |*| This function will be fired onmousemove of the DIVs
 |*| This will be used as a ondrag function... thanks to IE 5
 \*/
 function resizeColoumn ()
 {
   //If mouse button is down, objDivToMove will be valid... we can move/resize
   if (!objDivToMove) return;
   var intTDNum = objDivToMove.name - 1;
   var thead = element.tHead;
   if (!thead) return;
   var objTD = thead.childNodes[0].childNodes[intTDNum];
   if (!objTD || objTD.tagName != "TD") return;
   var intCurWidth = objTD.offsetWidth;
   var newX = window.event.clientX;
   //var newX = window.event.x;
   var intNewWidth = newX - objTD.offsetLeft;
   //TODO: who decided that the minimum col widhth is 50px?
   if (intNewWidth < 50) return;
   //Check to see if the table widht is more than the width of the window
   //Need that 20px buffer in IE to prevent scroll bars from appearing
   if (element.document.body.offsetWidth - 20 < element.offsetWidth - intCurWidth + intNewWidth) return;
   objTD.style.width = intNewWidth;
   var objDiv = objDivToMove;
   //Will be � 1 depending on which side the mouse moved
   //will be used to move all the DIVs remaining on the right
   var intDivMove = newX - objDiv.offsetLeft;
   objDiv.style.left = newX;
   //Move all the remaining DIVs on the right
   for (var i = 1; i < intColCount - intTDNum; i++)
   {        
     objDiv = objDiv.nextSibling;
     objDiv.style.left = objDiv.offsetLeft + intDivMove ;
   }
 }
 /*\
 |*| This function will be fired onmouseup
 |*| Release all the mouse events of the DIV
 \*/
 function releaseMouse ()
 {
   objDivToMove.releaseCapture ();
   objDivToMove = null;
 }
 /*\
 |*| This function will be fired onmouseout of the DIV
 |*| Set the flag indicating that the mouse is NOT over the DIV
 \*/
 function flagFalse ()
 {
   blnMouseOver = false;
 }
 /*\
 |*| This function will be called once during initIALIZATION
 |*| This will create DIV elm after the table to display the ABOUT informationA
 \*/
 function initAbout ()
 {
   objDiv = window.document.createElement ("DIV");
   objDiv.id = "About";
   objDiv.style.position = "absolute";
   objDiv.style.top = 0; 
   objDiv.style.left = 0 ;
   objDiv.align = "center";
   //element.document.body.offsetWidth ==> width of the IFRAME in IE
   objDiv.style.width = element.document.body.offsetWidth;
   objDiv.style.height = element.document.body.offsetHeight;
   objDiv.style.backgroundColor = "#0000FF";
   objDiv.style.color = "#FFFF00";
   objDiv.style.visibility = "hidden";
   objDiv.insertAdjacentText ("afterBegin", "DHTML Grid ver 0.92\n\n" + "");
   var objInput = document.createElement ("INPUT");
   objInput.id = "cmdAbout";
   objInput.title = "Ok";
   objInput.value = "Ok";
   objInput.align = "center";
   objInput.valign = "middle";
   objInput.style.height = "20px";
   objInput.style.width = "102px";
   objInput.type = "button";
   objInput.attachEvent ("onclick", about);
   objDiv.insertAdjacentElement ("beforeEnd", objInput);
   element.insertAdjacentElement ("afterEnd", objDiv);
 }
 /*\
 |*| Hilights the row on mouseover. This also sets the "previous row selected" to normal
 \*/
 function selectRow ()
 {
   var srcElem = getEventRow ();
   if (srcElem.tagName != "TR") return;
   if (objRowSelected)
   {
     objRowSelected.style.backgroundColor = "";
     objRowSelected = null;
   }
   if (srcElem.rowIndex > 0)
   {
     srcElem.style.backgroundColor = clrHilight;
     objRowSelected = srcElem;
   }
   element.focus ();
 }
 /*\
 |*| Entry point for all the click events on the table
 \*/
 function onClickCell ()
 {
   var srcElem = getEventRow ();
   if (srcElem.tagName != "TR") return;
   if (srcElem.rowIndex == 0) sort ();
   else onEdit ();
 }
 /*\
 |*| Capture the key press event, on del key see if a row is selected and delete
 \*/
 function captureDelKey ()
 {
   var keyPressed = event.keyCode;
   
   var srcElem = window.event.srcElement;
   if ((keyPressed == 46) && (srcElem.tagName != "INPUT") && (objRowSelected))
   {
     deleteRow (objRowSelected.rowIndex - 1);
     objRowSelected = null;
   }
 }
 /*\
 |*| detach all the events attached to the element and call other cleanup functions
 \*/
 function cleanup ()
 {
   element.detachEvent ("onmouseover", selectRow);
   element.detachEvent ("onclick", onClickCell);
   cleanupDiv ();
   cleanupAbout ();
 }
 /*\
 |*| Used by cleanup to clean the DIVs created for moving the Cols
 |*| detach all the events and delete the elements here
 \*/
 function cleanupDiv ()
 {
   var objDiv;
   for (var i = 1; i <= intColCount; i++)
   {  
     objDiv = element.document.getElementById ("DragMark" + (i - 1));
     objDiv.detachEvent ("onmouseover", flagTrue);
     objDiv.detachEvent ("onmousedown", captureMouse);
     objDiv.detachEvent ("onmousemove", resizeColoumn);
     objDiv.detachEvent ("onmouseup", releaseMouse);
     objDiv.detachEvent ("onmouseout", flagFalse);
     objDiv.removeNode (true);
   }
 }
 /*\
 |*| Detach all the events and Delete the elms related to the about box here
 \*/
 function cleanupAbout ()
 {
   element.document.getElementById ("About").removeNode (true);
 }
 /*\
 |*| This is THE function which does all the real sorting of the rows
 |*| First get rid of all the text-node elements that NN returns for spaces in the tables
 |*| then sort the contents based on which coloumn is clicked
 \*/
 function insertionSort (t, iRowEnd, fReverse, iColumn)
 {
   var textRowInsert, textRowCurrent, eRowInsert, eRowWalk;
   removeTextNodes (t);
   for (var iRowInsert = 1 ; iRowInsert <= iRowEnd ; iRowInsert++)
   {
     if (iColumn)
     {
       if (typeof (t.childNodes[iRowInsert].childNodes[iColumn]) != "undefined")
          textRowInsert = t.childNodes[iRowInsert].childNodes[iColumn].innerText;
       else
         textRowInsert = "";
     }
     else
     {
       textRowInsert = t.childNodes[iRowInsert].innerText;
     }
     for (var iRowWalk = 0 ; iRowWalk < iRowInsert ; iRowWalk++)
     {
       if (iColumn)
       {
         if (typeof (t.childNodes[iRowWalk].childNodes[iColumn]) != "undefined")
           textRowCurrent = t.childNodes[iRowWalk].childNodes[iColumn].innerText;
         else
           textRowCurrent = "";
       }
       else
       {
         textRowCurrent = t.childNodes[iRowWalk].innerText;
       }
       if ((!fReverse && textRowInsert < textRowCurrent) || (fReverse && textRowInsert > textRowCurrent))
       {
         eRowInsert = t.childNodes[iRowInsert];
         eRowWalk = t.childNodes[iRowWalk];
         t.insertBefore (eRowInsert, eRowWalk);
         iRowWalk = iRowInsert; // done
       }
     }
   }
 }
 /*\
 |*|  This function is called when there is a click event on the top
 |*|  row
 \*/
 function sort ()
 {
   var srcElem = getEventCell ();
   if (srcElem.tagName != "TD") return;
   var thead = element.tHead;  
   // clear the sort images in the head
   var imgcol = thead.getElementsByTagName ("IMG");
   for (var x = 0; x < imgcol.length; x++) 
   {
     imgcol[x].setAttribute("src", strBlankImage);
   }
   if (objLastClick == srcElem.selectIndex)
   {
     if (reverse == false)
     {
       srcElem.childNodes[0].setAttribute ("src", strDownImage);
       reverse = true;
     }
     else 
     {
       srcElem.childNodes[0].setAttribute ("src", strUpImage);
       reverse = false;
     }
   }
   else
   {
     reverse = false;
     objLastClick = srcElem.selectIndex;
     srcElem.childNodes[0].setAttribute ("arc", strUpImage);
   }
   tbody = element.tBodies [0];
   insertionSort (tbody, tbody.rows.length-1, reverse, srcElem.selectIndex);
 }
 /*\
 |*| This function is called when focus is lost on the text box
 |*| that is used to read user input. Validate the contents of the
 |*| input box and write them back to the table cell
 \*/
 function focusLost ()
 {
   var objSrcElm = window.event.srcElement; 
   objSrcElm.parentNode.innerHTML = unescape (objSrcElm.value);
 }
 /*\
 |*| This function is called when user clicks on a cell other than
 |*| the top row.
 |*| Show the content of the cell in an input box
 \*/
 function onEdit ()
 {
   var srcElem = getEventCell ();
   
   if (srcElem.tagName != "TD") return;
   if (srcElem.firstChild && srcElem.firstChild.tagName == "INPUT") return;
   
   txtOld = srcElem.innerHTML;
   srcElem.innerHTML = ""; 
   var objInput = document.createElement ("INPUT");
   objInput.style.width = "100%";//srcElem.clientWidth;
   objInput.type = "text";
   objInput.value = "" + escape (txtOld);
   //objInput.attachEvent ("onfocusout", focusLost);
   //the above onfocusout works fine in IE 6 but not in IE 5 so...
   objInput.attachEvent ("onblur", focusLost);
   objInput.attachEvent ("onkeypress", checkForEnter);
   srcElem.insertAdjacentElement ("beforeEnd", objInput);
   objInput.select ();
 }
 /*\
 |*| This function is used to add a row at the end of the tabl
 |*| Once the rows are added it calls the function to change the height
 |*|  of the DIVs that are used for resizing the table.
 \*/
 function addRow ()
 {
   var objTR = document.createElement ("TR");
   var objTD = document.createElement ("TD");
   for (var i = 0; i < addRow.arguments.length; i++) 
   {
     objTD = document.createElement ("TD");
     objTD.appendChild (document.createTextNode ((arguments[i]=="")?"null":arguments[i]));
     objTR.insertAdjacentElement ("beforeEnd", objTD);
   }
   objTBody = element.tBodies [0];
   objTBody.insertAdjacentElement ("beforeEnd", objTR);
   resizeDivs ();
 }
 
 /*\
 |*| The function deletes the last row by calling the deleteRow function 
 |*|  with the table row count
 \*/
 function deleteLastRow ()
 {
   removeTextNodes (element.tBodies[0]);
   this.deleteRow (element.tBodies[0].childNodes.length - 1);
 }
 /*\
 |*| The function checks if the rownum passed is a valid row 
 |*|  and deletes it 
 |*| This also calls the resizeDivs function to reduce the height
 |*|  of the DIVs that are used in resizing the table
 \*/
 function deleteRow (rowNum)
 {
   var tbody = element.tBodies [0];
   if (!tbody || rowNum < 0) return;
   removeTextNodes (tbody);
   tbody.childNodes[rowNum].removeNode (true);
   resizeDivs ();
 }
 /*\
 |*| This will be called on everkeypress event of the input box
 |*| This raises the focuslost event if the user hits enter
 \*/
 function checkForEnter ()
 {
   if (event.keyCode == 13) focusLost ();
 }
 /*\
 |*| Toggle the About div section
 \*/
 function about ()
 {
   if (element.document.getElementById ("About").style.visibility == "hidden")
     element.document.getElementById ("About").style.visibility = "visible";
   else
     element.document.getElementById ("About").style.visibility = "hidden";
 }
 /*\
 |*| Need this as IE 5 doesnt give the offsetLeft property properly
 \*/
 function getRealPos (elm)
 {
   intPos = 0;
   elm = elm.previousSibling;
   while ((elm!= null) && (elm.tagName!="BODY"))
   {
      intPos += elm.width - 0;
     elm = elm.previousSibling;
   }
   return intPos;
 }
 /*\
 |*| Return the TR elem on which an event has fireed
 \*/
 function getEventRow ()
 {
   var srcElem = window.event.srcElement;
   //crawl up to find the row
   while (srcElem.tagName != "TR" && srcElem.tagName != "TABLE")
   {
     srcElem = srcElem.parentNode;
   }
   return srcElem;
 }
 /*\
 |*| Return the TD elem on which an event has fireed
 \*/
 function getEventCell ()
 {
   var srcElem = window.event.srcElement;
   //crawl up the tree to find the table col
   while (srcElem.tagName != "TD" && srcElem.tagName != "TABLE")
   {
     srcElem = srcElem.parentNode;
   }
   return srcElem;
 }
 /*\
 |*| This funtion is used to change the height of the DIVs that are used to drag the cols
 |*| Used when a row is added or deleted.
 \*/
 function resizeDivs ()
 {
   for (var i = 0; i < intColCount; i++)
   {  
     var objDiv = element.document.getElementById ("DragMark" + (i));
     var objTD = element.tHead.childNodes[0].childNodes[i];
     if ((!objDiv) || (!objTD) || (objTD.tagName != "TD")) return;
     objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * (objTD.offsetHeight - 1);
   }
 }
 /*\
 |*| Function to handle erros. Displayes a request to contact along with the error messagei, filename and line
 \*/
 function handleError (err, url, line)
 {
   alert ("Oops, something went wrong.\n" +
      "Please contact yinti AT users DOT sourceforge DOT net with the following text\n" + 
      "Error text: " + err + "\n" + 
      "Location  : " + url + "\n" +
      "Line no   : " + line + "\n");
    return true; // let the browser handle the error */
 }
 /*\
 |*| Function to prototype all the functions needed by NN to emulate the functionality of IE
 \*/
 function initNNFunctions ()
 {
   if ((self.Node) && (self.Node.prototype))
   {
     Node.prototype.removeNode = NNRemoveNode;
     Element.prototype.insertAdjacentText = NNInsertAdjacentText;
     Element.prototype.insertAdjacentElement = NNInsertAdjacentElement;
     Element.prototype.insert__Adj = NNInsertAdj;
     Element.prototype.attachEvent = NNAttachEvent;
     Element.prototype.detachEvent = NNDetachEvent;
     Element.prototype.setCapture = NNSetCapture;
     Element.prototype.releaseCapture = NNReleaseCapture;
     Element.prototype.__defineGetter__("document", NNDocumentGetter);
     HTMLElement.prototype.focus = NNNullFunction;
     HTMLElement.prototype.attachEvent = NNAttachEvent;
     HTMLElement.prototype.detachEvent = NNDetachEvent;
     HTMLElement.prototype.__defineGetter__("innerText", NNInnerTextGetter);
     HTMLElement.prototype.__defineSetter__("innerText", NNInnerTextSetter);
     HTMLDocument.prototype.attachEvent = NNAttachEvent;
     HTMLDocument.prototype.detachEvent = NNDetachEvent;
     Event.prototype.__defineGetter__("keyCode", NNKeyCodeGetter);
   }
 }
 /*\
 |*|
 \*/
 function NNRemoveNode (a1)
 {
   var p = this.parentNode;
   if (p&&!a1)
   {
     var df = document.createDocumentFragment ();
     for (var a = 0; a < this.childNodes.length; a++)
     {
       df.appendChild (this.childNodes[a])
     }
     p.insertBefore (df , this)
   }
   return p?p.removeChild (this):this;
 }
 /*\
 |*|
 \*/
 function NNInsertAdjacentText (a1 , a2)
 {
   var t = document.createTextNode (a2||"")
   this.insert__Adj (a1 , t);
 }
 /*\
 |*|
 \*/
 function NNInsertAdjacentElement (a1 , a2)
 {
   this.insert__Adj (a1 , a2);
   return a2;
 }
 /*\
 |*|
 \*/
 function NNInsertAdj (a1 , a2)
 {
   var p = this.parentNode;
   var s = a1.toLowerCase ();
   if (s == "beforebegin"){p.insertBefore (a2 , this)}
   if (s == "afterend"){p.insertBefore (a2 , this.nextSibling)}
   if (s == "afterbegin"){this.insertBefore (a2 , this.childNodes[0])}
   if (s == "beforeend"){this.appendChild (a2)}
 }
 /*\
 |*| Fuction to simulate attachEvent
 \*/
 function NNAttachEvent (strEvent, funcHandle)
 {
   var shortTypeName = strEvent.replace (/on/, "");
   funcHandle._ieEmuEventHandler = function (e)
   {
     window.event = e;
     window.event.srcElement = e.target;
     return funcHandle ();
   };
   this.addEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);
 }
 /*\
 |*| Fuction to simulate detachEvent
 \*/
 function NNDetachEvent (strEvent, funcHandle)
 {
   var shortTypeName = strEvent.replace (/on/, "");
   if (typeof funcHandle._ieEmuEventHandler == "function")
     this.removeEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);
   else 
     this.removeEventListener (shortTypeName, funcHandle, true);
 }
 /*\
 |*| A HUGE HACK to getaway with the lack of setcapture in NN
 \*/
 function NNSetCapture ()
 {
   //TODO: FIX THIS FIRST BEFORE ANYTHING ELSE!! MAJOR HACK FOR NOW
   document.attachEvent ("onmousemove", resizeColoumn);
   document.attachEvent ("onmouseup", releaseMouse);
 }
 /*\
 |*| A HUGE HACK to getaway with the lack of releasecapture in NN
 \*/
 function NNReleaseCapture ()
 {
   //TODO: FIX THIS SECOND THEN GO TO EVERYTHING ELSE! 
   document.detachEvent ("onmousemove", resizeColoumn);
   document.detachEvent ("onmouseup", releaseMouse);
 }
 /*\
 |*| Empty function used to remove any functions not needed in NN
 \*/
 function NNNullFunction () { /*Nothing here*/ }
 /*\
 |*| return the innerhtml by replacing all the <TAGNAME> from the string
 \*/
 function NNInnerTextGetter ()
 {
   return this.innerHTML.replace (/<[^>]+>/g,"");
 }
 /*\
 |*| Add the text as a textnode to the element
 \*/
 function NNInnerTextSetter (txtStr)
 {
   var parsedText = document.createTextNode (txtStr);
   this.innerHTML = "";
   this.appendChild (parsedText);
 }
 /*\
 |*| Function to simulate event.keyCode
 \*/
 function NNKeyCodeGetter ()
 {
   return this.which;
 }
 /*\
 |*| Function to simulate element.document
 \*/
 function NNDocumentGetter ()
 {
   return this.ownerDocument;
 }
 
 </SCRIPT>

</HEAD> <BODY leftmargin="0" topmargin="0" onload="init("tblGrid")">

<THEAD> </THEAD> <TBODY> </TBODY>
Col 1 Col 2 Col 3 Col 4
200 dcdcdc 400 aaaaaa
300 c9e6ff 600 cccccc
301 e6e6ff 601 eeeeee

</BODY> </HTML>


 </source>
   
  


Grid Table Columns Resize

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 7 - Columns Resize</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Example 7 - Columns Resize

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   column resization: set the resize_cols attribute
   to true before rendering the grid.
        // Enable column resize <br />
        g.resize_cols = true;
    
     <script type="text/javascript">
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "Age" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", 33 );
       g.set_row_style ( "error" );
       g.add_row ( "john", "John", "Bustone", 31 );
       g.set_row_style ( "normal" );
       g.set_style ( "note" );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.set_style ( "normal" );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       // Enable sortable rows
       g.set_sortable ( true );
       g.set_col_type ( 3, "int" );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       // Enable column resize
       g.resize_cols = true;
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Grid (Table) data from RSS (IE only)

   <source lang="html4strict">

<html> <head>

 <style> body, html {margin:0px; padding: 0px; overflow: hidden; font: menu;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 <style>
   .active-column-0 {width: 400px}
   .active-column-1 {text-align: right}
 </style>

</head> <body>

 <script>
 var string = new Active.Formats.String;
 var date   = new Active.Formats.Date;
 date.setTextFormat("d mmm");
 date.setDataFormat("RFC822");
 var data = new Active.XML.Table;
 data.setURL("http://msdn.microsoft.ru/rss.xml");
 data.setRows("//item");
 data.setFormats([string, date]);
 data.request();
 var obj = new Active.Controls.Grid;
 obj.setDataModel(data);
 obj.setColumnProperty("texts", ["Title", "Date"]);
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) data from xml file 2

   <source lang="html4strict">

<html>

<head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create ActiveWidgets data model - XML-based table
 var table = new Active.XML.Table;
 //  provide data URL
 table.setURL("girdExamples/data/companies-simple.xml");
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) in Unix style

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 1</title>
 
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>

</head> <body>

OS3Grid Example 1 - Simple Grid

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   how to setup the basic grid and populate it with data.

include the OS3Grid files inside your page:
      <link type="text/css" rel="stylesheet" href="os3grid.css" />
      <script src="os3grid.js" type="text/javascript"></script>
    
   set the right paths of os3grid.css and os3grid.js.
      <div id="grid" ></div>
    
   here the code:
      <script type="text/javascript">
        // Create an OS3Grid instance
        var g = new OS3Grid ();
        // Grid Headers are the grid column names
        g.set_headers ( "nick", "Name", "Surname", "E-Mail Address" );
        // If contents is bigger than container, Grid will automatically show scrollbars
        g.set_scrollbars ( true );
        // The grid will have a solid border (these are CSS attributes)
        g.set_border ( 1, "solid", "#cccccc" );
        // Now, we add some rows to the grid
        g.add_row ( "fsoft", "Fabio", "Rotondo", "fsoft (@) sourceforge (dot) net" );
        g.add_row ( "john", "John", "Bustone", "jbust (@) somewhere (dot) net" );
        g.add_row ( "mkey", "Mark", "Key", "mkey (@) okay (dot) net" );
        g.add_row ( "jdoe", "John", "Doe", "redbull (@) batman (dot) net" );
        // Show the grid replacing the original HTML object with the "grid" ID.
        g.render ( "grid" );
      </script>
    
   The result:
     <script type="text/javascript">
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "E-Mail Address" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", "fsoft (@) sourceforge (dot) net" );
       g.add_row ( "john", "John", "Bustone", "jbust (@) somewhere (dot) net" );
       g.add_row ( "mkey", "Mark", "Key", "mkey (@) okay (dot) net" );
       g.add_row ( "jdoe", "John", "Doe", "redbull (@) batman (dot) net" );
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Grid (Table) with cell format and XML data set

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-column-5 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <script>
 //  create data formats
 var string = new Active.Formats.String;
 var number1 = new Active.Formats.Number;
 var number2 = new Active.Formats.Number;
 var date = new Active.Formats.Date;
 //  define formatting rule for text output
 number1.setTextFormat("#,###.##");
 number2.setTextFormat("");
 date.setTextFormat("dd mmm yy");
 date.setDataFormat("ISO8061");
 //  create ActiveWidgets data model - XML-based table
 var table = new Active.XML.Table;
 //  provide data URL
 table.setURL("gridExamples/data/companies-dataset.xml");
 //  set rows XPath
 table.setRows("//NewDataSet/*");
 //  set columns XPath
 table.setColumns(["ticker", "name", "mktcap", "sales", "employees", "timestamp"]);
 //  set column formatting
 table.setFormats([string, string, number1, number1, number2, date]);
 //  start asyncronous data retrieval
 table.request();
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees", "Date"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with colored cells

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>
 
 <script>
   var myData = [
     ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
     ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"],
     ["SAP", "SAP AG (ADR)", "40,986.328", "8,296.420", "28961"],
     ["CA", "Computer Associates Inter", "15,606.335", "3,164.000", "16000"],
     ["ERTS", "Electronic Arts Inc.", "14,490.895", "2,503.727", "4000"],
     ["SFTBF", "Softbank Corp. (ADR)", "14,485.840", ".000", "6865"],
     ["VRTS", "Veritas Software Corp.", "14,444.272", "1,578.658", "5647"],
     ["SYMC", "Symantec Corporation", "9,932.483", "1,482.029", "4300"],
     ["INFY", "Infosys Technologies Ltd.", "9,763.851", "830.748", "15400"],
     ["INTU", "Intuit Inc.", "9,702.477", "1,650.743", "6700"],
     ["ADBE", "Adobe Systems Incorporate", "9,533.050", "1,230.817", "3341"],
     ["PSFT", "PeopleSoft, Inc.", "8,246.467", "1,941.167", "8180"],
     ["SEBL", "Siebel Systems, Inc.", "5,434.649", "1,417.952", "5909"],
     ["BEAS", "BEA Systems, Inc.", "5,111.813", "965.694", "3063"],
     ["SNPS", "Synopsys, Inc.", "4,482.535", "1,169.786", "4254"],
     ["CHKP", "Check Point Software Tech", "4,396.853", "424.769", "1203"],
     ["MERQ", "Mercury Interactive Corp.", "4,325.488", "444.063", "1822"],
     ["DOX", "Amdocs Limited", "4,288.017", "1,427.088", "9400"],
     ["CTXS", "Citrix Systems, Inc.", "3,946.485", "554.222", "1670"],
     ["KNM", "Konami Corporation (ADR)", "3,710.784", ".000", "4313"]
   ];
   var myColumns = [
     "Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"
   ];
 </script>

</head> <body>

 <script>
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  set number of rows/columns
 obj.setRowProperty("count", 20);
 obj.setColumnProperty("count", 5);
 //  provide cells and headers text
 obj.setDataProperty("text", function(i, j){return myData[i][j]});
 obj.setColumnProperty("text", function(i){return myColumns[i]});
 //  set headers width/height
 obj.setRowHeaderWidth("28px");
 obj.setColumnHeaderHeight("20px");
 //  set click action handler
 obj.setAction("click", function(src){window.status = src.getItemProperty("text")});
 function myColor(){
   var value = this.getItemProperty("value");
   return value > 10000 ? "red" : "blue";
 }
 obj.getColumnTemplate(4).setStyle("color", myColor);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with Data Island and Column highlight

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>

</head> <body>

 <xml id="xmlDataIsland">
   <companies>
     <company>
       <ticker>MSFT</ticker>
       <name>Microsoft Corporation</name>
       <mktcap>314,571.156</mktcap>
       <sales>32,187.000</sales>
       <employees>55000</employees>
     </company>
     <company>
       <ticker>ORCL</ticker>
       <name>Oracle Corporation</name>
       <mktcap>62,615.266</mktcap>
       <sales>9,519.000</sales>
       <employees>40650</employees>
     </company>
     <company>
       <ticker>SAP</ticker>
       <name>SAP AG (ADR)</name>
       <mktcap>40,986.328</mktcap>
       <sales>8,296.420</sales>
       <employees>28961</employees>
     </company>
     <company>
       <ticker>CA</ticker>
       <name>Computer Associates Inter</name>
       <mktcap>15,606.335</mktcap>
       <sales>3,164.000</sales>
       <employees>16000</employees>
     </company>
     <company>
       <ticker>ERTS</ticker>
       <name>Electronic Arts Inc.</name>
       <mktcap>14,490.895</mktcap>
       <sales>2,503.727</sales>
       <employees>4000</employees>
     </company>
     <company>
       <ticker>SFTBF</ticker>
       <name>Softbank Corp. (ADR)</name>
       <mktcap>14,485.840</mktcap>
       <sales>.000</sales>
       <employees>6865</employees>
     </company>
     <company>
       <ticker>VRTS</ticker>
       <name>Veritas Software Corp.</name>
       <mktcap>14,444.272</mktcap>
       <sales>1,578.658</sales>
       <employees>5647</employees>
     </company>
     <company>
       <ticker>SYMC</ticker>
       <name>Symantec Corporation</name>
       <mktcap>9,932.483</mktcap>
       <sales>1,482.029</sales>
       <employees>4300</employees>
     </company>
     <company>
       <ticker>INFY</ticker>
       <name>Infosys Technologies Ltd.</name>
       <mktcap>9,763.851</mktcap>
       <sales>830.748</sales>
       <employees>15400</employees>
     </company>
     <company>
       <ticker>INTU</ticker>
       <name>Intuit Inc.</name>
       <mktcap>9,702.477</mktcap>
       <sales>1,650.743</sales>
       <employees>6700</employees>
     </company>
     <company>
       <ticker>ADBE</ticker>
       <name>Adobe Systems Incorporate</name>
       <mktcap>9,533.050</mktcap>
       <sales>1,230.817</sales>
       <employees>3341</employees>
     </company>
     <company>
       <ticker>PSFT</ticker>
       <name>PeopleSoft, Inc.</name>
       <mktcap>8,246.467</mktcap>
       <sales>1,941.167</sales>
       <employees>8180</employees>
     </company>
     <company>
       <ticker>SEBL</ticker>
       <name>Siebel Systems, Inc.</name>
       <mktcap>5,434.649</mktcap>
       <sales>1,417.952</sales>
       <employees>5909</employees>
     </company>
     <company>
       <ticker>BEAS</ticker>
       <name>BEA Systems, Inc.</name>
       <mktcap>5,111.813</mktcap>
       <sales>965.694</sales>
       <employees>3063</employees>
     </company>
     <company>
       <ticker>SNPS</ticker>
       <name>Synopsys, Inc.</name>
       <mktcap>4,482.535</mktcap>
       <sales>1,169.786</sales>
       <employees>4254</employees>
     </company>
     <company>
       <ticker>CHKP</ticker>
       <name>Check Point Software Tech</name>
       <mktcap>4,396.853</mktcap>
       <sales>424.769</sales>
       <employees>1203</employees>
     </company>
     <company>
       <ticker>MERQ</ticker>
       <name>Mercury Interactive Corp.</name>
       <mktcap>4,325.488</mktcap>
       <sales>444.063</sales>
       <employees>1822</employees>
     </company>
     <company>
       <ticker>DOX</ticker>
       <name>Amdocs Limited</name>
       <mktcap>4,288.017</mktcap>
       <sales>1,427.088</sales>
       <employees>9400</employees>
     </company>
     <company>
       <ticker>CTXS</ticker>
       <name>Citrix Systems, Inc.</name>
       <mktcap>3,946.485</mktcap>
       <sales>554.222</sales>
       <employees>1670</employees>
     </company>
     <company>
       <ticker>KNM</ticker>
       <name>Konami Corporation (ADR)</name>
       <mktcap>3,710.784</mktcap>
       <sales>.000</sales>
       <employees>4313</employees>
     </company>
   </companies>
 </xml>
 <script>
 //  create ActiveWidgets data model - XML-based table
 var table = new Active.XML.Table;
 //  get reference to the xml data island node
 var xml, node = document.getElementById("xmlDataIsland");
 //  IE
 if (window.ActiveXObject) {
   xml = node;
 }
 //  Mozilla
 else {
   xml = document.implementation.createDocument("","", null);
   xml.appendChild(node.selectSingleNode("*"));
 }
 //  provide data XML
 table.setXML(xml);
 //  define column labels
 var columns = ["Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"];
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  provide column labels
 obj.setColumnProperty("texts", columns);
 //  provide external model as a grid data source
 obj.setDataModel(table);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with image in cells

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width: 200px;}
   .active-column-1 {width: 80px; text-align: right;}
   .active-column-2 {width: 150px;}
   .active-column-3 {width: 120px;}
   .active-box-image {height: 16px;} /* for firefox 0.8 */
 </style>
 
 <script src="gridExamples/data/files.js"></script>

</head> <body>

 <script>
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  set the first column template to image+text
 obj.setColumnTemplate(new Active.Templates.Image, 0);
 //  set number of rows/columns
 obj.setRowProperty("count", 9);
 obj.setColumnProperty("count", 4);
 //  provide cells and headers text
 obj.setDataProperty("text", function(i, j){return myData[i][j]});
 obj.setDataProperty("image", function(i, j){return myData[i][4]});
 //  provide column headers
 obj.setColumnProperty("texts" , ["Name", "Size", "Type", "Date Modified"]);
 //  set column/row headers width/height
 obj.setColumnHeaderHeight("20px");
 obj.setRowHeaderWidth("0px");
 //  add tooltips to the first column template and data model
 obj.getColumnTemplate(0).setAttribute("title", function(){return this.getItemProperty("tooltip")});
 obj.defineDataProperty("tooltip", function(i, j){return "Type: " + myData[i][2] + "\nDate Modified: " + myData[i][3]  + "\nSize: " + myData[i][1]});
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with multiple selection

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   .active-controls-grid {height: 100%; font: menu;}
   .active-column-0 {width:  80px;}
   .active-column-1 {width: 200px; background-color: threedlightshadow;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-column {border-right: 1px solid threedshadow;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
 </style>
 
 <script>
   var myData = [
     ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
     ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"],
     ["SAP", "SAP AG (ADR)", "40,986.328", "8,296.420", "28961"],
     ["CA", "Computer Associates Inter", "15,606.335", "3,164.000", "16000"],
     ["ERTS", "Electronic Arts Inc.", "14,490.895", "2,503.727", "4000"],
     ["SFTBF", "Softbank Corp. (ADR)", "14,485.840", ".000", "6865"],
     ["VRTS", "Veritas Software Corp.", "14,444.272", "1,578.658", "5647"],
     ["SYMC", "Symantec Corporation", "9,932.483", "1,482.029", "4300"],
     ["INFY", "Infosys Technologies Ltd.", "9,763.851", "830.748", "15400"],
     ["INTU", "Intuit Inc.", "9,702.477", "1,650.743", "6700"],
     ["ADBE", "Adobe Systems Incorporate", "9,533.050", "1,230.817", "3341"],
     ["PSFT", "PeopleSoft, Inc.", "8,246.467", "1,941.167", "8180"],
     ["SEBL", "Siebel Systems, Inc.", "5,434.649", "1,417.952", "5909"],
     ["BEAS", "BEA Systems, Inc.", "5,111.813", "965.694", "3063"],
     ["SNPS", "Synopsys, Inc.", "4,482.535", "1,169.786", "4254"],
     ["CHKP", "Check Point Software Tech", "4,396.853", "424.769", "1203"],
     ["MERQ", "Mercury Interactive Corp.", "4,325.488", "444.063", "1822"],
     ["DOX", "Amdocs Limited", "4,288.017", "1,427.088", "9400"],
     ["CTXS", "Citrix Systems, Inc.", "3,946.485", "554.222", "1670"],
     ["KNM", "Konami Corporation (ADR)", "3,710.784", ".000", "4313"]
   ];
   var myColumns = [
     "Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"
   ];
 </script>

</head> <body>

 <script>
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  set number of rows/columns
 obj.setRowProperty("count", 20);
 obj.setColumnProperty("count", 5);
 //  provide cells and headers text
 obj.setDataProperty("text", function(i, j){return myData[i][j]});
 obj.setColumnProperty("text", function(i){return myColumns[i]});
 //  set headers width/height
 obj.setRowHeaderWidth("28px");
 obj.setColumnHeaderHeight("20px");
 // allow multiple selection
 obj.setSelectionProperty("multiple", true);
 // define action handler
 var message = function(){
   window.status = "Grid selection:" +
   " latest=" + this.getSelectionProperty("index") +
   " full list=" + this.getSelectionProperty("values") +
   " (press Ctrl- to select multiple rows)."
 }
 // assign action handler to grid
 obj.setAction("selectionChanged", message);
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with news feeder (IE only)

   <source lang="html4strict">

<html> <head>

 <style> body, html {margin:0px; padding: 0px; overflow: hidden; font: menu;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 <style>
   .active-column-0 {width: 400px}
 </style>

</head> <body>

 <script>
 var date = new Active.Formats.Date;
 date.setTextFormat("[ddd, d mmm]");
 var data = new Active.XML.Table;
 data.setURL("http://www.xignite.ru/xWorldNews.asmx/GetTopStories");
 data.setParameter("CriteriaType", "Region");
 data.setParameter("CategoryName", "West Europe");
 data.setParameter("StoryCount", 20);
 data.setNamespace("xi", "http://www.xignite.ru/services/");
 data.setRows("//xi:Abstract");
 data.setColumns(["xi:Title", "xi:Source", "xi:City", "xi:Language", "xi:InsertDate"]);
 data.setFormat(date, 4);
 data.request();
 var obj = new Active.Controls.Grid;
 obj.setDataModel(data);
 obj.setColumnProperty("texts", ["Title", "Source", "City", "Language", "Date"]);
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with quotes feeder (IE only)

   <source lang="html4strict">

<html> <head>

 <style> body, html {margin:0px; padding: 0px; overflow: hidden; font: menu;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>

</head> <body>

 <script>
 var symbols = [  "MSFT","ORCL","SAP","CA","ERTS","TIBX","VRTS","SYMC","INFY","INTU",
         "ADBE","PSFT","SEBL","BEAS","SNPS","CHKP","MERQ","DOX","CTXS","KNM"];
 var data = new Active.XML.Table;
 data.setURL("http://www.xignite.ru/xQuotes.asmx/GetQuotes");
 data.setParameter("Symbol", symbols);
 data.setNamespace("xi", "http://www.xignite.ru/services/");
 data.setColumns(["xi:Symbol", "xi:Name", "xi:Last", "xi:Change", "xi:Volume"]);
 data.request();
 var obj = new Active.Controls.Grid;
 obj.setDataModel(data);
 obj.setColumnProperty("texts", ["Ticker", "Company", "Last", "Change", "Volume"]);
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Grid (Table) with row header and tooltips

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {margin:0px; padding: 0px; overflow: hidden; font:menu} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>

</head> <body>

 <script>
 //  create ActiveWidgets Grid javascript object
 var obj = new Active.Controls.Grid;
 //  set data
 obj.setRowProperty("count", 5);
 obj.setColumnProperty("count", 5);
 obj.setDataProperty("text", function(i, j){return i + "." + j});
 //  set column header tooltip
 obj.setColumnProperty("tooltip", function(i){return "Tooltip for column " + i});
 //  write grid html to the page
 document.write(obj);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


GUI for table creation

<A href="http://www.wbex.ru/Code/JavaScriptDownload/oat-1.0.zip">oat-1.0.zip( 996 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

List box ( Grid Table )

   <source lang="html4strict">

<html> <script language="JavaScript" src="widgets/jsobjects.js"></script> <script>

 //Definindo linguagem - pt = portugues. Mensagens de erro serao apresentadas nesta lingua
 lang = "pt";
 //criando o documento base para adicionar os objetos
 docbody      = new JsDocument("docbody");
 //Funcoes extras para mostrar a adicao de eventos aos objetos:
 //Esta funcaum eh adicionada ao evento change do combobox
 function testeChange(e)
 {
   alert("mudou");
 }
 //funcao utilizada pelos botoes para transferir itens de um listbox para outro
 function transfer1_2()
 {
   transferListItens(listbox1, listbox2);
 }
 //funcao utilizada pelos botoes para transferir itens de um listbox para outro
 function transfer2_1()
 {
   transferListItens(listbox2, listbox1);
 }
 //funcao so para retornar o valor atual do calendario
 function teste(e)
 {
   alert(cal.getValue());
 }
 
 //funcao para ver se o treeview esta retornando ok
 function toolbarClick()
 {
   alert("Clicou no toolbar");
 }
 //funcaum para adicionar itens no listview
 function lstvaddItems()
 {
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", lstvaddItems);
   menu.addItem(menu_adicionar);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", lstvdelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   list_teste.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 //funcaum para remover itens do listview
 function lstvdelItems(e)
 {  
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   var lsitem = eval(obj.lstparent);
   list_teste.delItem(lsitem);
   temMudanca = true;
 }
 
 function treeaddItems()
 {
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", treeaddItems);
   menu.addItem(menu_adicionar);
   menu_adicionarsub = eval(itemname + "_menu_adicionarsub = new JsMenuItem("" + itemname + "_menu_adicionarsub")");
   menu_adicionarsub.setValue("Adicionar SubItem");
   menu_adicionarsub.setIcon("images/new.gif");
   menu_adicionarsub.setEvent("click", treeaddSubItems);
   menu_adicionarsub.setAttribute("lstparent",itemname);
   menu.addItem(menu_adicionarsub);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", treedelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   tree_teste.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 
 function treeaddSubItems(e)
 {
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   var lsitem = eval(obj.lstparent);
   
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", treeaddItems);
   menu.addItem(menu_adicionar);
   menu_adicionarsub = eval(itemname + "_menu_adicionarsub = new JsMenuItem("" + itemname + "_menu_adicionarsub")");
   menu_adicionarsub.setValue("Adicionar SubItem");
   menu_adicionarsub.setIcon("images/new.gif");
   menu_adicionarsub.setEvent("click", treeaddSubItems);
   menu_adicionarsub.setAttribute("lstparent",itemname);
   menu.addItem(menu_adicionarsub);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", treedelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   lsitem.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 
 function treedelItems(e)
 {
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   
   var lsitem = eval(obj.lstparent);
   lsitem.parent.delItem(lsitem);
   temMudanca = true;
 }
 //MenuBar
 menubar = new JsMenuBar("menubar");
 menubaritem1 = new JsMenu("menubaritem1");
 menubaritem2 = new JsMenu("menubaritem2");
 submenubaritem2 = new JsMenu("submenubaritem2");
 menubaritemsubitem1_1 = new JsMenuItem("menubaritemsubitem1_1");
 menubaritemsubitem1_2 = new JsMenuItem("menubaritemsubitem1_2");
 menubaritemsubitem1_3 = new JsMenuItem("menubaritemsubitem1_3");
 menubaritemsubitem1_4 = new JsMenuItem("menubaritemsubitem1_4");
 menubaritemsubitem2_1 = new JsMenuItem("menubaritemsubitem2_1");
 menubaritemsubitem2_2 = new JsMenuItem("menubaritemsubitem2_2");
 menubaritemsubitem2_3 = new JsMenuItem("menubaritemsubitem2_3");
 menubaritemsubitem2_4 = new JsMenuItem("menubaritemsubitem2_4");
 submenubaritemsubitem2_1 = new JsMenuItem("submenubaritemsubitem2_1");
 submenubaritemsubitem2_2 = new JsMenuItem("submenubaritemsubitem2_2");
 submenubaritemsubitem2_3 = new JsMenuItem("submenubaritemsubitem2_3");
 submenubaritemsubitem2_4 = new JsMenuItem("submenubaritemsubitem2_4");
 menubaritem1.setValue("Menu 1");
 menubaritemsubitem1_1.setValue("Item 1");
 menubaritemsubitem1_2.setValue("Item 2");
 menubaritemsubitem1_3.setValue("Item 3");
 menubaritemsubitem1_4.setValue("Item 4");
 menubaritem2.setValue("Menu 2");
 menubaritemsubitem2_1.setValue("Item 1");
 menubaritemsubitem2_2.setValue("Item 2");
 menubaritemsubitem2_3.setValue("Item 3");
 menubaritemsubitem2_4.setValue("Item 4");
 submenubaritem2.setValue("SubMenu 2");
 submenubaritemsubitem2_1.setValue("SubItem 1");
 submenubaritemsubitem2_2.setValue("SubItem 2");
 submenubaritemsubitem2_3.setValue("SubItem 3");
 submenubaritemsubitem2_4.setValue("SubItem 4");
 menubar.addItem(menubaritem1);
 menubar.addItem(menubaritem2);
 menubaritem1.addItem(menubaritemsubitem1_1);
 menubaritem1.addItem(menubaritemsubitem1_2);
 menubaritem1.addItem(menubaritemsubitem1_3);
 menubaritem1.addItem(menubaritemsubitem1_4);
 menubaritem2.addItem(menubaritemsubitem2_1);
 menubaritem2.addItem(menubaritemsubitem2_2);
 menubaritem2.addItem(menubaritemsubitem2_3);
 menubaritem2.addItem(menubaritemsubitem2_4);
 menubaritem2.addItem(submenubaritem2);
 submenubaritem2.addItem(submenubaritemsubitem2_1);
 submenubaritem2.addItem(submenubaritemsubitem2_2);
 submenubaritem2.addItem(submenubaritemsubitem2_3);
 submenubaritem2.addItem(submenubaritemsubitem2_4);
 docbody.addItem(menubar);
 //Toolbar
 toolbar = new JsToolBar("toolbar");
 toolbarbt1 = new JsToolBarButton("toolbarbt1");
 toolbarbt2 = new JsToolBarButton("toolbarbt2");
 toolbarbt3 = new JsToolBarButton("toolbarbt3");
 toolbarbt1.setSource("images/filenew.gif");
 toolbarbt2.setSource("images/fileopen.gif");
 toolbarbt3.setSource("images/trash.gif");
 
 toolbarbt1.setEvent("click",toolbarClick);
 toolbar.addItem(toolbarbt1);
 toolbar.addItem(toolbarbt2);
 toolbar.addDiv();
 toolbar.addItem(toolbarbt3);
 docbody.addItem(toolbar);
 //Grid principal, e de conteudo, que contera o tab
 //Serve pricipalmente para fazer o alinhamento dos elementos na tela
 maingrid = new JsWidgetGrid("grid");
 maingrid.setHeight(300);
 maingrid.addRow();
 maingrid.addCell("100%","10","center","top");
 maingrid.addRow();
 maingrid.addCell("100%","","center","top");
 docbody.addItem(maingrid);
 contentgrid = new JsWidgetGrid("grid");
 contentgrid.setWidth("95%");
 contentgrid.addRow();
 contentgrid.addCell("100%","","","top");
 maingrid.addItem(contentgrid);
 //Exemplo de tab
 tab_teste = new JsTab("tab_teste");
 tab_teste.addTab("Listview e TreeView (menu de contexto)");
 tab_teste.addTab("Combobox e Lineedit");
 tab_teste.addTab("Listbox e botao");
 tab_teste.addTab("Calendario e dateedit");
 tab_teste.setWidth("100%");
 tab_teste.setHeight("450");
 contentgrid.addItem(tab_teste);
 //Exemplo de listview com menu de contexto
 adigenmenu      = new JsMenu("adigenmenu");
 adigenmenuitem    = new JsMenuItem("adigenmenuitem");
 adigenmenuitem.setValue("Adicionar");
 adigenmenuitem.setIcon("images/new.gif");
 adigenmenuitem.setEvent("click", lstvaddItems);
 adigenmenu.addItem(adigenmenuitem);
 list_teste = new JsListView("list_teste");
 list_teste.setHeight(190)
 list_teste.addColumn("Coluna 1",200);
 list_teste.addColumn("Coluna 2",300);
 list_teste.addColumn("Coluna 3",400);
 
 list_label = new JsLabel("list_label");
 list_label.setValue("ListView");
 list_label.setHeight(30);
 list_teste.setMenu(adigenmenu);
 tab_teste.addItemToTab(list_label,0);
 tab_teste.addItemToTab(list_teste,0);
 
 //Exemplo de TreeView com menu de contexto
 adigentreemenu      = new JsMenu("adigentreemenu");
 adigentreemenuitem    = new JsMenuItem("adigentreemenuitem");
 adigentreemenuitem.setValue("Adicionar");
 adigentreemenuitem.setIcon("images/new.gif");
 adigentreemenuitem.setEvent("click", treeaddItems);
 adigentreemenu.addItem(adigentreemenuitem);
 
 tree_teste = new JsListView("tree_teste");
 tree_teste.setTreeView();
 tree_teste.setHeight(190)
 tree_teste.addColumn("Coluna 1",200);
 tree_teste.addColumn("Coluna 2",300);
 tree_teste.addColumn("Coluna 3",400);
 
 tree_label = new JsLabel("tree_label");
 tree_label.setValue("TreeView");
 tree_label.setHeight(30);
 
 tree_teste.setMenu(adigentreemenu);
 
 tab_teste.addItemToTab(tree_label,0);
 tab_teste.addItemToTab(tree_teste,0);
 //Exemplo de lineedit
 //criamos um grid para distribuir melhor os elementos na tela
 lineeditgrid = new JsWidgetGrid("lineeditgrid");
 lineeditgrid.setHeight(60);
 //label 1
 label1 = new JsLabel("label1");
 label2 = new JsLabel("label2");
 lineedit1 = new JsLineEdit("lineedit1");
 lineedit2 = new JsLineEdit("lineedit2");
 label1.setValue("Label 1");
 label2.setValue("Label 2");
 lineeditgrid.addRow();
 lineeditgrid.addCell("60");
 lineeditgrid.addItem(label1);
 lineeditgrid.addCell();
 lineeditgrid.addItem(lineedit1);
 lineeditgrid.addRow();
 lineeditgrid.addCell("60");
 lineeditgrid.addItem(label2);
 lineeditgrid.addCell();
 lineeditgrid.addItem(lineedit2);
 tab_teste.addItemToTab(lineeditgrid,1);
 //Exemplo de combobox
 combobox_teste = new JsComboBox("combobox_teste");
 for (var i=1; i < 20; i++)
   combobox_teste.addItem(i, "test - " + i, "images/user_small.gif");
 combobox_teste.setEvent("change", testeChange);
 tab_teste.addItemToTab(combobox_teste,1);
 //listbox example
 lsitboxgrid = new JsWidgetGrid("lsitboxgrid");
 listbox_bt1 = new JsPushButton("listbox_bt1");
 listbox_bt1.setValue(">>");
 listbox_bt1.setEvent("click", transfer1_2);
 listbox_bt1.setWidth("50");
 listbox_bt2 = new JsPushButton("listbox_bt2");
 listbox_bt2.setValue("<<");
 listbox_bt2.setEvent("click", transfer2_1);
 listbox_bt2.setWidth("50");
 listbox1 = new JsListBox("listbox1");
 listbox1.setHeight("300");
 listbox1.setWidth("100%");
 listbox2 = new JsListBox("listbox2");
 listbox2.setHeight("300");
 listbox2.setWidth("100%");
 for (var i=0; i < 20; i++)
   listbox1.addItem("test - " + i, "","");
 lsitboxgrid.addRow();
 lsitboxgrid.addCell("45%");
 lsitboxgrid.addItem(listbox1);
 lsitboxgrid.addCell(10);
 lsitboxgrid.addCell(50,null,"center");
 lsitboxgrid.addItem(listbox_bt1);
 lsitboxgrid.addItem(listbox_bt2);
 lsitboxgrid.addCell(10);
 lsitboxgrid.addCell("45%");
 lsitboxgrid.addItem(listbox2);
 tab_teste.addItemToTab(lsitboxgrid,2);
 //Calendario
 cal    = new JsCalendar("cal");
 data  = new JsDateEdit("data");
 cal.setEvent("click", teste);
 tab_teste.addItemToTab(data,3);
 tab_teste.addItemToTab(cal,3);
 
 //for (i=0;i<50;i++)
   //lstvaddItems();

</script> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jsobjects.zip">jsobjects.zip( 366 k)</a>


List view (Selection between two list)

   <source lang="html4strict">

<html> <script language="JavaScript" src="widgets/jsobjects.js"></script> <script>

 //Definindo linguagem - pt = portugues. Mensagens de erro serao apresentadas nesta lingua
 lang = "pt";
 //criando o documento base para adicionar os objetos
 docbody      = new JsDocument("docbody");
 //Funcoes extras para mostrar a adicao de eventos aos objetos:
 //Esta funcaum eh adicionada ao evento change do combobox
 function testeChange(e)
 {
   alert("mudou");
 }
 //funcao utilizada pelos botoes para transferir itens de um listbox para outro
 function transfer1_2()
 {
   transferListItens(listbox1, listbox2);
 }
 //funcao utilizada pelos botoes para transferir itens de um listbox para outro
 function transfer2_1()
 {
   transferListItens(listbox2, listbox1);
 }
 //funcao so para retornar o valor atual do calendario
 function teste(e)
 {
   alert(cal.getValue());
 }
 
 //funcao para ver se o treeview esta retornando ok
 function toolbarClick()
 {
   alert("Clicou no toolbar");
 }
 //funcaum para adicionar itens no listview
 function lstvaddItems()
 {
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", lstvaddItems);
   menu.addItem(menu_adicionar);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", lstvdelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   list_teste.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 //funcaum para remover itens do listview
 function lstvdelItems(e)
 {  
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   var lsitem = eval(obj.lstparent);
   list_teste.delItem(lsitem);
   temMudanca = true;
 }
 
 function treeaddItems()
 {
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", treeaddItems);
   menu.addItem(menu_adicionar);
   menu_adicionarsub = eval(itemname + "_menu_adicionarsub = new JsMenuItem("" + itemname + "_menu_adicionarsub")");
   menu_adicionarsub.setValue("Adicionar SubItem");
   menu_adicionarsub.setIcon("images/new.gif");
   menu_adicionarsub.setEvent("click", treeaddSubItems);
   menu_adicionarsub.setAttribute("lstparent",itemname);
   menu.addItem(menu_adicionarsub);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", treedelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   tree_teste.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 
 function treeaddSubItems(e)
 {
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   var lsitem = eval(obj.lstparent);
   
   //gerador de valor randomico para o nome dos objetos criados
   itemname = randomizer();
   //Menu do Item
   menu = eval(itemname + "_menu = new JsMenu(""+itemname+"_menu");");
   menu_adicionar = eval(itemname + "_menu_adicionar = new JsMenuItem("" + itemname + "_menu_adicionar")");
   menu_adicionar.setValue("Adicionar");
   menu_adicionar.setIcon("images/new.gif");
   menu_adicionar.setEvent("click", treeaddItems);
   menu.addItem(menu_adicionar);
   menu_adicionarsub = eval(itemname + "_menu_adicionarsub = new JsMenuItem("" + itemname + "_menu_adicionarsub")");
   menu_adicionarsub.setValue("Adicionar SubItem");
   menu_adicionarsub.setIcon("images/new.gif");
   menu_adicionarsub.setEvent("click", treeaddSubItems);
   menu_adicionarsub.setAttribute("lstparent",itemname);
   menu.addItem(menu_adicionarsub);
   menu_remover = eval(itemname + "_menu_remover = new JsMenuItem("" + itemname + "_menu_remover")");
   menu_remover.setValue("Remover");
   menu_remover.setIcon("images/delete.gif");
   menu_remover.setEvent("click", treedelItems);
   menu_remover.setAttribute("lstparent",itemname);
   menu.addItem(menu_remover);
   listviewitem = eval (itemname + " = new JsListViewItem(""+itemname+"");");
   lsitem.addItem(listviewitem);
   check = eval ("check_test"+itemname+" = new JsCheckBox("check_test"+itemname+"")");
   check.setLabel("Teste");
   check.setValue("true");
   listviewitem.addItem(randomizer(),"",true);
   listviewitem.addItem(check);
   listviewitem.addItem("Vai!!! Da um duplo clique logo!","",true);
   listviewitem.setMenu(menu);
 }
 
 function treedelItems(e)
 {
   if (browserType == "ie")
   {
     e = window.event;
     obj = e.srcElement;
   }
   else
   {
     obj = e.target;
   }
   
   var lsitem = eval(obj.lstparent);
   lsitem.parent.delItem(lsitem);
   temMudanca = true;
 }
 //MenuBar
 menubar = new JsMenuBar("menubar");
 menubaritem1 = new JsMenu("menubaritem1");
 menubaritem2 = new JsMenu("menubaritem2");
 submenubaritem2 = new JsMenu("submenubaritem2");
 menubaritemsubitem1_1 = new JsMenuItem("menubaritemsubitem1_1");
 menubaritemsubitem1_2 = new JsMenuItem("menubaritemsubitem1_2");
 menubaritemsubitem1_3 = new JsMenuItem("menubaritemsubitem1_3");
 menubaritemsubitem1_4 = new JsMenuItem("menubaritemsubitem1_4");
 menubaritemsubitem2_1 = new JsMenuItem("menubaritemsubitem2_1");
 menubaritemsubitem2_2 = new JsMenuItem("menubaritemsubitem2_2");
 menubaritemsubitem2_3 = new JsMenuItem("menubaritemsubitem2_3");
 menubaritemsubitem2_4 = new JsMenuItem("menubaritemsubitem2_4");
 submenubaritemsubitem2_1 = new JsMenuItem("submenubaritemsubitem2_1");
 submenubaritemsubitem2_2 = new JsMenuItem("submenubaritemsubitem2_2");
 submenubaritemsubitem2_3 = new JsMenuItem("submenubaritemsubitem2_3");
 submenubaritemsubitem2_4 = new JsMenuItem("submenubaritemsubitem2_4");
 menubaritem1.setValue("Menu 1");
 menubaritemsubitem1_1.setValue("Item 1");
 menubaritemsubitem1_2.setValue("Item 2");
 menubaritemsubitem1_3.setValue("Item 3");
 menubaritemsubitem1_4.setValue("Item 4");
 menubaritem2.setValue("Menu 2");
 menubaritemsubitem2_1.setValue("Item 1");
 menubaritemsubitem2_2.setValue("Item 2");
 menubaritemsubitem2_3.setValue("Item 3");
 menubaritemsubitem2_4.setValue("Item 4");
 submenubaritem2.setValue("SubMenu 2");
 submenubaritemsubitem2_1.setValue("SubItem 1");
 submenubaritemsubitem2_2.setValue("SubItem 2");
 submenubaritemsubitem2_3.setValue("SubItem 3");
 submenubaritemsubitem2_4.setValue("SubItem 4");
 menubar.addItem(menubaritem1);
 menubar.addItem(menubaritem2);
 menubaritem1.addItem(menubaritemsubitem1_1);
 menubaritem1.addItem(menubaritemsubitem1_2);
 menubaritem1.addItem(menubaritemsubitem1_3);
 menubaritem1.addItem(menubaritemsubitem1_4);
 menubaritem2.addItem(menubaritemsubitem2_1);
 menubaritem2.addItem(menubaritemsubitem2_2);
 menubaritem2.addItem(menubaritemsubitem2_3);
 menubaritem2.addItem(menubaritemsubitem2_4);
 menubaritem2.addItem(submenubaritem2);
 submenubaritem2.addItem(submenubaritemsubitem2_1);
 submenubaritem2.addItem(submenubaritemsubitem2_2);
 submenubaritem2.addItem(submenubaritemsubitem2_3);
 submenubaritem2.addItem(submenubaritemsubitem2_4);
 docbody.addItem(menubar);
 //Toolbar
 toolbar = new JsToolBar("toolbar");
 toolbarbt1 = new JsToolBarButton("toolbarbt1");
 toolbarbt2 = new JsToolBarButton("toolbarbt2");
 toolbarbt3 = new JsToolBarButton("toolbarbt3");
 toolbarbt1.setSource("images/filenew.gif");
 toolbarbt2.setSource("images/fileopen.gif");
 toolbarbt3.setSource("images/trash.gif");
 
 toolbarbt1.setEvent("click",toolbarClick);
 toolbar.addItem(toolbarbt1);
 toolbar.addItem(toolbarbt2);
 toolbar.addDiv();
 toolbar.addItem(toolbarbt3);
 docbody.addItem(toolbar);
 //Grid principal, e de conteudo, que contera o tab
 //Serve pricipalmente para fazer o alinhamento dos elementos na tela
 maingrid = new JsWidgetGrid("grid");
 maingrid.setHeight(300);
 maingrid.addRow();
 maingrid.addCell("100%","10","center","top");
 maingrid.addRow();
 maingrid.addCell("100%","","center","top");
 docbody.addItem(maingrid);
 contentgrid = new JsWidgetGrid("grid");
 contentgrid.setWidth("95%");
 contentgrid.addRow();
 contentgrid.addCell("100%","","","top");
 maingrid.addItem(contentgrid);
 //Exemplo de tab
 tab_teste = new JsTab("tab_teste");
 tab_teste.addTab("Listview e TreeView (menu de contexto)");
 tab_teste.addTab("Combobox e Lineedit");
 tab_teste.addTab("Listbox e botao");
 tab_teste.addTab("Calendario e dateedit");
 tab_teste.setWidth("100%");
 tab_teste.setHeight("450");
 contentgrid.addItem(tab_teste);
 //Exemplo de listview com menu de contexto
 adigenmenu      = new JsMenu("adigenmenu");
 adigenmenuitem    = new JsMenuItem("adigenmenuitem");
 adigenmenuitem.setValue("Adicionar");
 adigenmenuitem.setIcon("images/new.gif");
 adigenmenuitem.setEvent("click", lstvaddItems);
 adigenmenu.addItem(adigenmenuitem);
 list_teste = new JsListView("list_teste");
 list_teste.setHeight(190)
 list_teste.addColumn("Coluna 1",200);
 list_teste.addColumn("Coluna 2",300);
 list_teste.addColumn("Coluna 3",400);
 
 list_label = new JsLabel("list_label");
 list_label.setValue("ListView");
 list_label.setHeight(30);
 list_teste.setMenu(adigenmenu);
 tab_teste.addItemToTab(list_label,0);
 tab_teste.addItemToTab(list_teste,0);
 
 //Exemplo de TreeView com menu de contexto
 adigentreemenu      = new JsMenu("adigentreemenu");
 adigentreemenuitem    = new JsMenuItem("adigentreemenuitem");
 adigentreemenuitem.setValue("Adicionar");
 adigentreemenuitem.setIcon("images/new.gif");
 adigentreemenuitem.setEvent("click", treeaddItems);
 adigentreemenu.addItem(adigentreemenuitem);
 
 tree_teste = new JsListView("tree_teste");
 tree_teste.setTreeView();
 tree_teste.setHeight(190)
 tree_teste.addColumn("Coluna 1",200);
 tree_teste.addColumn("Coluna 2",300);
 tree_teste.addColumn("Coluna 3",400);
 
 tree_label = new JsLabel("tree_label");
 tree_label.setValue("TreeView");
 tree_label.setHeight(30);
 
 tree_teste.setMenu(adigentreemenu);
 
 tab_teste.addItemToTab(tree_label,0);
 tab_teste.addItemToTab(tree_teste,0);
 //Exemplo de lineedit
 //criamos um grid para distribuir melhor os elementos na tela
 lineeditgrid = new JsWidgetGrid("lineeditgrid");
 lineeditgrid.setHeight(60);
 //label 1
 label1 = new JsLabel("label1");
 label2 = new JsLabel("label2");
 lineedit1 = new JsLineEdit("lineedit1");
 lineedit2 = new JsLineEdit("lineedit2");
 label1.setValue("Label 1");
 label2.setValue("Label 2");
 lineeditgrid.addRow();
 lineeditgrid.addCell("60");
 lineeditgrid.addItem(label1);
 lineeditgrid.addCell();
 lineeditgrid.addItem(lineedit1);
 lineeditgrid.addRow();
 lineeditgrid.addCell("60");
 lineeditgrid.addItem(label2);
 lineeditgrid.addCell();
 lineeditgrid.addItem(lineedit2);
 tab_teste.addItemToTab(lineeditgrid,1);
 //Exemplo de combobox
 combobox_teste = new JsComboBox("combobox_teste");
 for (var i=1; i < 20; i++)
   combobox_teste.addItem(i, "test - " + i, "images/user_small.gif");
 combobox_teste.setEvent("change", testeChange);
 tab_teste.addItemToTab(combobox_teste,1);
 //listbox example
 lsitboxgrid = new JsWidgetGrid("lsitboxgrid");
 listbox_bt1 = new JsPushButton("listbox_bt1");
 listbox_bt1.setValue(">>");
 listbox_bt1.setEvent("click", transfer1_2);
 listbox_bt1.setWidth("50");
 listbox_bt2 = new JsPushButton("listbox_bt2");
 listbox_bt2.setValue("<<");
 listbox_bt2.setEvent("click", transfer2_1);
 listbox_bt2.setWidth("50");
 listbox1 = new JsListBox("listbox1");
 listbox1.setHeight("300");
 listbox1.setWidth("100%");
 listbox2 = new JsListBox("listbox2");
 listbox2.setHeight("300");
 listbox2.setWidth("100%");
 for (var i=0; i < 20; i++)
   listbox1.addItem("test - " + i, "","");
 lsitboxgrid.addRow();
 lsitboxgrid.addCell("45%");
 lsitboxgrid.addItem(listbox1);
 lsitboxgrid.addCell(10);
 lsitboxgrid.addCell(50,null,"center");
 lsitboxgrid.addItem(listbox_bt1);
 lsitboxgrid.addItem(listbox_bt2);
 lsitboxgrid.addCell(10);
 lsitboxgrid.addCell("45%");
 lsitboxgrid.addItem(listbox2);
 tab_teste.addItemToTab(lsitboxgrid,2);
 //Calendario
 cal    = new JsCalendar("cal");
 data  = new JsDateEdit("data");
 cal.setEvent("click", teste);
 tab_teste.addItemToTab(data,3);
 tab_teste.addItemToTab(cal,3);
 
 
 //for (i=0;i<50;i++)
   //lstvaddItems();

</script> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/jsobjects.zip">jsobjects.zip( 366 k)</a>


One page two grid (Table)

   <source lang="html4strict">

<html> <head>

 <title>ActiveWidgets Grid :: Examples</title>
 <style> body, html {font: menu; background: threedface;} </style>
 
 <link href="gridRuntime/styles/classic/grid.css" rel="stylesheet" type="text/css" ></link>
 <script src="gridRuntime/lib/grid.js"></script>
 
 <style>
   #grid1 {height: 200px; border: 2px inset; background: white}
   #grid2 {height: 100px; border: 2px inset; background: white}
   #grid1 .active-column-1 {width: 200px; background-color: threedlightshadow;}
   #grid2 .active-column-1 {width: 150px; background-color: infobackground;}
   .active-column-2 {text-align: right;}
   .active-column-3 {text-align: right;}
   .active-column-4 {text-align: right;}
   .active-grid-row {border-bottom: 1px solid threedlightshadow;}
   .active-grid-column {border-right: 1px solid threedlightshadow;}
 </style>
 
 <script>
   var data1 = [
     ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
     ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"],
     ["SAP", "SAP AG (ADR)", "40,986.328", "8,296.420", "28961"],
     ["CA", "Computer Associates Inter", "15,606.335", "3,164.000", "16000"],
     ["ERTS", "Electronic Arts Inc.", "14,490.895", "2,503.727", "4000"],
     ["SFTBF", "Softbank Corp. (ADR)", "14,485.840", ".000", "6865"],
     ["VRTS", "Veritas Software Corp.", "14,444.272", "1,578.658", "5647"],
     ["SYMC", "Symantec Corporation", "9,932.483", "1,482.029", "4300"],
     ["INFY", "Infosys Technologies Ltd.", "9,763.851", "830.748", "15400"],
     ["INTU", "Intuit Inc.", "9,702.477", "1,650.743", "6700"],
     ["ADBE", "Adobe Systems Incorporate", "9,533.050", "1,230.817", "3341"],
     ["PSFT", "PeopleSoft, Inc.", "8,246.467", "1,941.167", "8180"],
     ["SEBL", "Siebel Systems, Inc.", "5,434.649", "1,417.952", "5909"],
     ["BEAS", "BEA Systems, Inc.", "5,111.813", "965.694", "3063"],
     ["SNPS", "Synopsys, Inc.", "4,482.535", "1,169.786", "4254"],
   ];
   var data2 = [
     ["CHKP", "Check Point Software Tech", "4,396.853", "424.769", "1203"],
     ["MERQ", "Mercury Interactive Corp.", "4,325.488", "444.063", "1822"],
     ["DOX", "Amdocs Limited", "4,288.017", "1,427.088", "9400"],
     ["CTXS", "Citrix Systems, Inc.", "3,946.485", "554.222", "1670"],
     ["KNM", "Konami Corporation (ADR)", "3,710.784", ".000", "4313"],
   ];
   var columns1 = [
     "Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"
   ];
   var columns2 = [
     "Ticker(2)", "Company Name(2)", "Market Cap.(2)", "$ Sales(2)", "Employees(2)"
   ];
 </script>

</head> <body>

Here is the first grid:

 <script>
   var obj1 = new Active.Controls.Grid;
   obj1.setId("grid1");
   obj1.setRowProperty("count", 15);
   obj1.setColumnProperty("count", 5);
   obj1.setDataProperty("text", function(i, j){return data1[i][j]});
   obj1.setColumnProperty("text", function(i){return columns1[i]});
   document.write(obj1);
 </script>

And another one...

 <script>
   var obj2 = new Active.Controls.Grid;
   obj2.setId("grid2");
   obj2.setRowProperty("count", 5);
   obj2.setColumnProperty("count", 5);
   obj2.setDataProperty("text", function(i, j){return data2[i][j]});
   obj2.setColumnProperty("text", function(i){return columns2[i]});
   document.write(obj2);
 </script>

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/ActiveWidgets.zip">ActiveWidgets.zip( 344 k)</a>


Pagable Table

   <source lang="html4strict">

<html> <head> <title>nrsTable Examples</title> <style type="text/css"> body { background-color: #ffff99; } .code_display { background-color: #b9b9ac;

         border: 1px solid #9d9d94;

}

  1. example4 td.dataTD0 { letter-spacing: 2; }
  2. example4 td.dataTD1 { text-decoration: underline; }
  3. example4 td.dataTD2 { background-color: grey; }

</style> <script language="JavaScript"> /* natcompare.js -- Perform "natural order" comparisons of strings in JavaScript. Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre) Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be> Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion. Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.ru> The Java version was based on the C version by Martin Pool. Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

  • /

function isWhitespaceChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode <= 32 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function isDigitChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode >= 48  && charCode <= 57 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function compareRight(a,b) {

   var bias = 0;
   var ia = 0;
   var ib = 0;
   var ca;
   var cb;
   // The longest run of digits wins.  That aside, the greatest
   // value wins, but we can"t know that it will until we"ve scanned
   // both numbers to know that they have the same magnitude, so we
   // remember it in BIAS.
   for (;; ia++, ib++) {
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       if (!isDigitChar(ca)
               && !isDigitChar(cb)) {
           return bias;
       } else if (!isDigitChar(ca)) {
           return -1;
       } else if (!isDigitChar(cb)) {
           return +1;
       } else if (ca < cb) {
           if (bias == 0) {
               bias = -1;
           }
       } else if (ca > cb) {
           if (bias == 0)
               bias = +1;
       } else if (ca == 0 && cb == 0) {
           return bias;
       }
   }

} function natcompare(a,b) {

   var ia = 0, ib = 0;
 var nza = 0, nzb = 0;
 var ca, cb;
 var result;
   while (true)
   {
       // only count the number of zeroes leading the last number compared
       nza = nzb = 0;
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       // skip over leading spaces or zeros
       while ( isWhitespaceChar( ca ) || ca =="0" ) {
           if (ca == "0") {
               nza++;
           } else {
               // only count consecutive zeroes
               nza = 0;
           }
           ca = a.charAt(++ia);
       }
       while ( isWhitespaceChar( cb ) || cb == "0") {
           if (cb == "0") {
               nzb++;
           } else {
               // only count consecutive zeroes
               nzb = 0;
           }
           cb = b.charAt(++ib);
       }
       // process run of digits
       if (isDigitChar(ca) && isDigitChar(cb)) {
           if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
               return result;
           }
       }
       if (ca == 0 && cb == 0) {
           // The strings compare the same.  Perhaps the caller
           // will want to call strcmp to break the tie.
           return nza - nzb;
       }
       if (ca < cb) {
           return -1;
       } else if (ca > cb) {
           return +1;
       }
       ++ia; ++ib;
   }

} </script> <script language="JavaScript"> /**

* Copyright 2005 New Roads School
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**

* \class nrsTable
* This describes the nrsTable, which is a table created in JavaScript that is
* able to be sorted and displayed in different ways based on teh configuration
* parameters passed to it. 
* to create a new table one only needs to call the setup function like so:
*
 * nrsTable.setup(
 * {
 *   table_name: "table_container",
 *   table_data: d,
 *   table_header: h
 * }
 * );
 * 
* Where table_name is the name of the table to build.  THis must be defined in
* your HTML by putting a table declaration, such as *
. This will declare where your table will be shown.
* All sorts of parameters can be customized here.  For details look at the
* function setup.
* \see setup
*/

/**

* Debug function.  Set debug to tru to view messages.
* \param msg Message to display in an alert.
*/

debug = false; function DEBUG(msg) {

 if(debug)
   alert(msg);

} /**

* There is a memory leak problem that I can"t seem to fix.  I"m attching 
* something that I found from Aaron Boodman, which will clean up all the
* memory leaks in the page (this can be found at http://youngpup.net/2005/0221010713
* ). This is a little clunky, but it will do till I track this problem.
* Oh, and this problem only occurrs is IE.
*/

if (window.attachEvent) {

   var clearElementProps = [
   "data",
       "onmouseover",
       "onmouseout",
       "onmousedown",
       "onmouseup",
       "ondblclick",
       "onclick",
       "onselectstart",
       "oncontextmenu"
   ];
   window.attachEvent("onunload", function() {
       var el;
       for(var d = document.all.length;d--;){
           el = document.all[d];
           for(var c = clearElementProps.length;c--;){
               el[clearElementProps[c]] = null;
           }
       }
   });

}

/**

* This is the constructor.
* It only needs the name of the table.  This should never be called directly, 
* instead use setup function.
* \param table The name of the table to create.
* \see setup
*/

function nrsTable(table) {

 this.my_table = table;
 this.field_to_sort = 0;
 this.field_asc = true;

} new nrsTable(""); /**

* This function is responsible for setting up an nrsTable.  All the parameters
* can be configured directly from this function.  The params array of this 
* function is a class (or a associative array, depending on how you want to
* look at it) with the following possible parameters:
*   - table_name: required.  The id of the table tag.
*  - table_header: required.  An array containing the header names.
*   - table_data: optional.  A 2D array of strings containing the cell contents.
*  - caption: optional.  A caption to include on the table.
*  - row_links: optional.  An array with hyperlinks per row.  Must be a javascript function.
*  - cell_links: optional.  A 2D array with links on every cell.  Must be a javascript function
*  - up_icon: optional.  A path to the ascending sort arrow.
*  - down_icon: optional.  A path to the descending sort arrow.
*  - prev_icon: optional.  A path to the previous page icon in the navigation.
*  - next_icon: optional.  A path to the next page icon in the navigation.
*  - rew_icon: optional.  A path to the first page icon in the navigation.
*  - fwd_icon: optional.  A path to the last page icon in the navigation.
*  - rows_per_page: optional.  The number of rows per page to display at any one time.
*  - display_nav: optional.  Displays navigation (prev, next, first, last)
*  - foot_headers: optional.  Whether to display th eheaders at the foot of the table.
*  - header_color: optional.  The color of the header cells.  Will default to whatever is defined in CSS.
*  - even_cell_color: optional.  The color of the even data cells.  Will default to whatever is defined in CSS.
*  - odd_cell_color: optional.  The color of the odd data cells.  Will default to whatever is defined in CSS.
*  - footer_color: optional.  The color of the footer cells.  Will default to whatever is defined in CSS.
*  - hover_color: optional.  The color tha a row should turn when the mouse is over it.
*  - padding: optional.  Individual cell padding, in pixels.
*  - natural_compare: optional.  Uses the natural compare algorithm (separate from this program) to sort.
*  - disable_sorting: optional.  An array specifying the columns top disable sorting on (0 is the first column).
*
* \params params An array as described above.
*/

nrsTable.setup = function(params) {

 //here we assign all the veriables that we are passed, or the defaults if 
 //they are not defined.
 //Note that the only requirements are a table name and a header.
 if(typeof params["table_name"] == "undefined")
 {
   alert("Error! You must supply a table name!");
   return null;
 }
 if(typeof params["table_header"] == "undefined")
 {
   alert("Error! You must supply a table header!");
   return null;
 }
 
 //check if the global array exists, else create it.
 if(typeof(nrsTables) == "undefined")
 {
   eval("nrsTables = new Array();");
 }
 nrsTables[params["table_name"]] = new nrsTable(params["table_name"]);
 nrsTables[params["table_name"]].heading = params["table_header"].concat();
 
 //now the non-required elements.  Data elements first
 nrsTables[params["table_name"]].data = (typeof params["table_data"] == "undefined" || !params["table_data"])? null: params["table_data"].concat();
 nrsTables[params["table_name"]].caption = (typeof params["caption"] == "undefined")? null: params["caption"];
 nrsTables[params["table_name"]].row_links = (typeof params["row_links"] == "undefined" || !params["row_links"])? null: params["row_links"].concat();
 nrsTables[params["table_name"]].cell_links = (typeof params["cell_links"] == "undefined" || !params["row_links"])? null: params["cell_links"].concat();
 
 //these are the icons.
 nrsTables[params["table_name"]].up_icon = (typeof params["up_icon"] == "undefined")? "up.gif": params["up_icon"];
 nrsTables[params["table_name"]].down_icon = (typeof params["down_icon"] == "undefined")? "down.gif": params["down_icon"];
 nrsTables[params["table_name"]].prev_icon = (typeof params["prev_icon"] == "undefined")? "left.gif": params["prev_icon"];
 nrsTables[params["table_name"]].next_icon = (typeof params["next_icon"] == "undefined")? "right.gif": params["next_icon"];
 nrsTables[params["table_name"]].rew_icon = (typeof params["rew_icon"] == "undefined")? "first.gif": params["rew_icon"];
 nrsTables[params["table_name"]].fwd_icon = (typeof params["fwd_icon"] == "undefined")? "last.gif": params["fwd_icon"];
 
 //now the look and feel options.
 nrsTables[params["table_name"]].rows_per_page = (typeof params["rows_per_page"] == "undefined")? -1: params["rows_per_page"];
 nrsTables[params["table_name"]].page_nav = (typeof params["page_nav"] == "undefined")? false: params["page_nav"];
 nrsTables[params["table_name"]].foot_headers = (typeof params["foot_headers"] == "undefined")? false: params["foot_headers"];
 nrsTables[params["table_name"]].header_color = (typeof params["header_color"] == "undefined")? null: params["header_color"];
 nrsTables[params["table_name"]].even_cell_color = (typeof params["even_cell_color"] == "undefined")? null: params["even_cell_color"];
 nrsTables[params["table_name"]].odd_cell_color = (typeof params["odd_cell_color"] == "undefined")? null: params["odd_cell_color"];
 nrsTables[params["table_name"]].footer_color = (typeof params["footer_color"] == "undefined")? null: params["footer_color"];
 nrsTables[params["table_name"]].hover_color = (typeof params["hover_color"] == "undefined")? null: params["hover_color"];
 nrsTables[params["table_name"]].padding = (typeof params["padding"] == "undefined")? null: params["padding"];
 nrsTables[params["table_name"]].natural_compare = (typeof params["natural_compare"] == "undefined")? false: true;
 nrsTables[params["table_name"]].disable_sorting = 
   (typeof params["disable_sorting"] == "undefined")? false: "." + params["disable_sorting"].join(".") + ".";
 //finally, build the table
 nrsTables[params["table_name"]].buildTable();

};

/**

* This is the Javascript quicksort implementation.  This will sort the 
* this.data and the this.data_nodes based on the this.field_to_sort parameter.
* \param left The left index of the array.
* \param right The right index of the array
*/

nrsTable.prototype.quickSort = function(left, right) {

 if(!this.data || this.data.length == 0)
   return;
 var i = left;
 var j = right;
 var k = this.data[Math.round((left + right) / 2)][this.field_to_sort];
 while(j > i)
 {
   if(this.field_asc)
   {
     while(this.data[i][this.field_to_sort].toLowerCase() < k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() > k.toLowerCase())
       j--;
   }
   else
   {
     while(this.data[i][this.field_to_sort].toLowerCase() > k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() < k.toLowerCase())
       j--;
   }
   if(i <= j )
   {
     //swap both values
     //sort data
     var temp = this.data[i];
     this.data[i] = this.data[j];
     this.data[j] = temp;
     
     //sort contents
     var temp = this.data_nodes[i];
     this.data_nodes[i] = this.data_nodes[j];
     this.data_nodes[j] = temp;
     i++;
     j--;
   }
 }
 if(left < j)
   this.quickSort(left, j);
 if(right > i)
   this.quickSort(i, right);

} /**

* This is the Javascript natural sort function.  Because of some obscure JavaScript
* quirck, we could not do quicsort while calling natcompare to compare, so this
* function will so a simple bubble sort using the natural compare algorithm.
*/

nrsTable.prototype.natSort = function() {

 if(!this.data || this.data.length == 0)
   return;
 var swap;
 for(i = 0; i < this.data.length - 1; i++)
 {
   for(j = i; j < this.data.length; j++)
   {
     if(!this.field_asc)
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == -1)
         swap = true;
       else
         swap = false;
     }
     else
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == 1)
         swap = true;
       else
         swap = false;
     }
     if(swap)
     {
       //swap both values
       //sort data
       var temp = this.data[i];
       this.data[i] = this.data[j];
       this.data[j] = temp;
       
       //sort contents
       var temp = this.data_nodes[i];
       this.data_nodes[i] = this.data_nodes[j];
       this.data_nodes[j] = temp;
     }
   }
 }

} /**

* This function will recolor all the the nodes to conform to the alternating 
* row colors.
*/

nrsTable.prototype.recolorRows = function() {

 if(this.even_cell_color || this.odd_cell_color)
 {
   DEBUG("Recoloring Rows. length = " + this.data_nodes.length);
   for(var i = 0; i < this.data_nodes.length; i++)
   {
     if(i % 2 == 0)
     {
       if(this.even_cell_color)
         this.data_nodes[i].style.backgroundColor = this.even_cell_color;
       this.data_nodes[i].setAttribute("id", "even_row");
     }
     else
     {
       if(this.odd_cell_color)
         this.data_nodes[i].style.backgroundColor = this.odd_cell_color;
       this.data_nodes[i].setAttribute("id", "odd_row");
     }
   }
 }

} /**

* This function will create the Data Nodes, which are a reference to the table
* rows in the HTML.
*/

nrsTable.prototype.createDataNodes = function() {

 if(this.data_nodes)
   delete this.data_nodes;
 this.data_nodes = new Array();
 if(!this.data)
   return;
 for(var i = 0; i < this.data.length; i++)
 {
   var curr_row = document.createElement("TR");
   
   for(var j = 0; j < this.data[i].length; j++)
   {
     var curr_cell = document.createElement("TD");
     //do we need to create links on every cell?
     if(this.cell_links)
     {
       var fn = new Function("", this.cell_links[i][j]);
       curr_cell.onclick = fn;
       curr_cell.style.cursor = "pointer";
     }
     //workaround for IE
     curr_cell.setAttribute("className", "dataTD" + j);
     //assign the padding
     if(this.padding)
     {
       curr_cell.style.paddingLeft = this.padding + "px";
       curr_cell.style.paddingRight = this.padding + "px";
     }
     curr_cell.appendChild(document.createTextNode(this.data[i][j]));
     curr_row.appendChild(curr_cell);
   }
   //do we need to create links on every row?
   if(!this.cell_links && this.row_links)
   {
     var fn = new Function("", this.row_links[i]);
     curr_row.onclick = fn;
     curr_row.style.cursor = "pointer";
   }
   //sets the id for odd and even rows.
   if(i % 2 == 0)
   {
     curr_row.setAttribute("id", "even_row");
     if(this.even_cell_color)
       curr_row.style.backgroundColor = this.even_cell_color;
   }
   else
   {
     curr_row.setAttribute("id", "odd_row");
     if(this.odd_cell_color)
       curr_row.style.backgroundColor = this.odd_cell_color;
   }
   if(this.hover_color)
   {
     curr_row.onmouseover = new Function("", "this.style.backgroundColor="" + this.hover_color + "";");
     curr_row.onmouseout = new Function("", "this.style.backgroundColor=(this.id=="even_row")?"" + 
               this.even_cell_color + "":"" + this.odd_cell_color + "";");
   }
   this.data_nodes[i] = curr_row;
 }

} /**

* This function will update the nav page display.
*/

nrsTable.prototype.updateNav = function() {

 if(this.page_nav)
 {
   var p = 0;
   if(this.foot_headers)
     p++;
   var t = document.getElementById(this.my_table);
   var nav = t.tFoot.childNodes[p];
   if(nav)
   {
     var caption = t.tFoot.childNodes[p].childNodes[0].childNodes[2];
     caption.innerHTML = "Page " + (this.current_page + 1) + " of " + this.num_pages;
   }
   else
   {
     if(this.num_pages > 1)
     {
       this.insertNav();
       nav = t.tFoot.childNodes[p];
     }
   }
   if(nav)
   {
     if(this.current_page == 0)
       this.hideLeftArrows();
     else
       this.showLeftArrows();
     
     if(this.current_page + 1 == this.num_pages)
       this.hideRightArrows();
     else
       this.showRightArrows();
   }
 }

} /**

* This function will flip the sort arrow in place.  If a heading is used in the
* footer, then it will flip that one too.
*/

nrsTable.prototype.flipSortArrow = function() {

 this.field_asc = !this.field_asc;
 //flip the arrow on the heading.
 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 if(this.field_asc)
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
 else
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 //is there a heading in the footer?
 if(this.foot_headers)
 {
   //yes, so flip that arrow too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   if(this.field_asc)
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
   else
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 }

} /**

* This function will move the sorting arrow from the place specified in 
* this.field_to_sort to the passed parameter.  It will also set 
* this.field_to_sort to the new value.  It will also do it in the footers, 
* if they exists.
* \param field The new field to move it to.
*/

nrsTable.prototype.moveSortArrow = function(field) {

 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 var img = heading.removeChild(heading.getElementsByTagName("IMG")[0]);
 heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[field];
 heading.appendChild(img);
 //are there headers in the footers.
 if(this.foot_headers)
 {
   //yes, so switch them too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   var img = footer.removeChild(footer.getElementsByTagName("IMG")[0]);
   footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[field];
   footer.appendChild(img);
 }
 //finally, set the field to sort by.
 this.field_to_sort = field;

} /**

* This function completely destroys a table.  Should be used only when building
* a brand new table (ie, new headers).  Else you should use a function like
* buildNewData which only deletes the TBody section.
*/

nrsTable.prototype.emptyTable = function() {

 var t = document.getElementById(this.my_table);
 while(t.childNodes.length != 0)
   t.removeChild(t.childNodes[0]);

}; /**

* This function builds a brand new table from scratch.  This function should
* only be called when a brand new table (with headers, footers, etc) needs
* to be created.  NOT when refreshing data or changing data.
*/

nrsTable.prototype.buildTable = function() {

 //reset the sorting information.
 this.field_to_sort = 0;
 this.field_asc = true;
 
 //remove the nodes links.
 delete this.data_nodes;
 
 //do we have to calculate the number of pages?
 if(this.data && this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.current_page = 0;
 }
 
 //blank out the table.
 this.emptyTable();
 
 //this is the table that we will be using.
 var table = document.getElementById(this.my_table);
 
 //is there a caption?
 if(this.caption)
 {
   var caption = document.createElement("CAPTION");
   caption.setAttribute("align", "top");
   caption.appendChild(document.createTextNode(this.caption));
   table.appendChild(caption);
 }
 
 //do the heading first
 var table_header = document.createElement("THEAD");
 var table_heading = document.createElement("TR");
 //since this is a new table the first field is what"s being sorted.
 var curr_cell = document.createElement("TH");
 var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + 0 + ");");
 if(!this.disable_sorting || this.disable_sorting.indexOf(".0.") == -1)
   curr_cell.onclick = fn;
 if(this.header_color)
   curr_cell.style.backgroundColor = this.header_color;
 curr_cell.style.cursor = "pointer";
 var img = document.createElement("IMG");
 img.setAttribute("src", this.up_icon);
 img.setAttribute("border", "0");
 img.setAttribute("height", "8");
 img.setAttribute("width", "8");
 curr_cell.appendChild(document.createTextNode(this.heading[0]));
 curr_cell.appendChild(img);
 table_heading.appendChild(curr_cell);
 //now do the rest of the heading.
 for(var i = 1; i < this.heading.length; i++)
 {
   curr_cell = document.createElement("TH");
   var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + i + ");");
   if(!this.disable_sorting || this.disable_sorting.indexOf("." + i + ".") == -1)
     curr_cell.onclick = fn;
   if(this.header_color)
     curr_cell.style.backgroundColor = this.header_color;
   curr_cell.style.cursor = "pointer";
   //build the sorter
   curr_cell.appendChild(document.createTextNode(this.heading[i]));
   table_heading.appendChild(curr_cell);
 }
 table_header.appendChild(table_heading);
 
 //now the content
 var table_body = document.createElement("TBODY");
 this.createDataNodes();
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
   this.recolorRows();
 }
 //finally, the footer
 var table_footer = document.createElement("TFOOT");
 if(this.foot_headers)
 {
   table_footer.appendChild(table_heading.cloneNode(true));
 }
 
 if(this.page_nav && this.num_pages > 1)
 {
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table_footer.appendChild(nav);
 }
 
 if(this.footer_color)
 {
   for(var i = 0; i < table_footer.childNodes.length; i++)
     table_footer.childNodes[i].style.backgroundColor = this.footer_color;
 }
 
 //append the data
 table.appendChild(table_header);
 table.appendChild(table_body);
 table.appendChild(table_footer);
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
 }
 this.refreshTable();

}; /**

* This function will remove the elements in teh TBody section of the table and
* return an array of references of those elements.  This array can then be 
* sorted and re-inserted into the table.
* \return An array to references of the TBody contents.
*/

nrsTable.prototype.extractElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var nodes = new Array();
 var i = 0;
 while(tbody.childNodes.length > 0)
 {
   nodes[i] = tbody.removeChild(tbody.childNodes[0]);
   i++;
 }
 return nodes;

} /**

* This function will re-insert an array of elements into the TBody of a table.
* Note that the array elements are stored in the this.data_nodes reference.
*/

nrsTable.prototype.insertElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var start = 0;
 var num_elements = this.data_nodes.length;
 if(this.rows_per_page != -1)
 {
   start = this.current_page * this.rows_per_page;
   num_elements = (this.data_nodes.length - start) > this.rows_per_page?
             this.rows_per_page + start:
             this.data_nodes.length;
 }
 DEBUG("start is " + start + " and num_elements is " + num_elements);
 for(var i = start; i < num_elements; i++)
 {
   tbody.appendChild(this.data_nodes[i]);
 }

} /**

* This function will sort the table"s data by a specific field.  The field 
* parameter referes to which field index should be sorted.
* \param field The field index which to sort on.
*/

nrsTable.prototype.fieldSort = function(field) {

 if(this.field_to_sort == field)
 {
   //only need to reverse the array.
   if(this.data)
   {
     this.data.reverse();
     this.data_nodes.reverse();
   }
   //flip the arrow on the heading.
   this.flipSortArrow();
 }
 else
 {
   //In this case, we need to sort the array.  We"ll sort it last, first 
   //make sure that the arrow images are set correctly.
   this.moveSortArrow(field);
   //finally, set the field to sort by.
   this.field_to_sort = field;
   if(this.data)
   {
     //we"ll be using our implementation of quicksort
     if(this.natural_compare)
       this.natSort(0, this.data.length - 1);
     else
       this.quickSort(0, this.data.length - 1);
   }
 }
 //finally, we refresh the table.
 this.refreshTable();

}; /**

* This function will refresh the data in the table.  This function should be
* used whenever the nodes have changed, or when chanign pages.  Note that 
* this will NOT re-sort.
*/

nrsTable.prototype.refreshTable = function() {

 this.extractElements();
 this.recolorRows();
 this.insertElements();
 //finally, if there is a nav, upate it.
 this.updateNav();

} /**

* This function will advance a page.  If we are already at the last page, then 
* it will remain there.
*/

nrsTable.prototype.nextPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page + 1 != this.num_pages)
 {
   this.current_page++;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go back a page.  If we are already at the first page, then 
* it will remain there.
*/

nrsTable.prototype.prevPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page != 0)
 {
   this.current_page--;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go to the first page.
*/

nrsTable.prototype.firstPage = function() {

 if(this.current_page != 0)
 {
   this.current_page = 0;
   this.refreshTable();
 }

} /**

* This function will go to the last page.
*/

nrsTable.prototype.lastPage = function() {

 DEBUG("lastPage(), current_page: " + this.current_page + " and num_pages: " + this.num_pages);
 if(this.current_page != (this.num_pages - 1))
 {
   this.current_page = this.num_pages - 1;
   this.refreshTable();
 }

} /**

* This function will go to a specific page.  valid values are pages 1 to 
* however many number of pages there are.
* \param page The page number to go to.
*/

nrsTable.prototype.gotoPage = function(page) {

 page--;
 if(page >=0 && page < this.num_pages)
 {
   this.current_page = page;
   this.refreshTable();
 }

} /**

* This function can be used to change the number of entries per row displayed
* on the fly.
* \param entries The number of entries per page.
*/

nrsTable.prototype.changeNumRows = function(entries) {

 if(entries > 0)
 {
   this.rows_per_page = entries;
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.refreshTable();
 }

} /**

* This function will take in a new data array and , optionally, a new cell_link
* array OR a new row_link array.  Only one will be used, with the cell_link
* array taking precedence.  It will then re-build the table with the new data
* array.
* \param new_data This is the new data array.  This is required.
* \param cell_links This is the new cell links array, a 2D array for each cell.
* \param row_links This is the new row links array, a 1D array for each row.
*/

nrsTable.prototype.newData = function(new_data, cell_links, row_links) {

 //extract the elements from teh table to clear the table.
 this.extractElements();
 //now delete all the data related to this table.  I do this so that 
 //(hopefully) the memory will be freed.  This is realy needed for IE, whose
 //memory handling is almost non-existant
 delete this.data;
 delete this.data_nodes;
 delete this.cell_links;
 delete this.row_links
 //now re-assign.
 this.data = new_data;
 this.cell_links = cell_links;
 this.row_links = row_links;
 if(this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   if(this.num_pages <= 1 && this.page_nav)
     this.removeNav();
   else if(this.page_nav)
     this.insertNav();
   this.current_page = 0;
 }
 this.createDataNodes();
 if(this.field_to_sort != 0)
   this.moveSortArrow(0);
 if(!this.field_asc)
   this.flipSortArrow();
 this.insertElements();
 this.updateNav();

} /**

* This function will remove the NAV bar (if one exists) from the table.
*/

nrsTable.prototype.removeNav = function() {

 if(this.page_nav)
 {
   //in this case, remove the nav from the existing structure.
   var table = document.getElementById(this.my_table);
   var p = 0;
   if(this.foot_headers)
     p++;
   var nav = table.tFoot.childNodes[p];
   if(nav)
   {
     table.tFoot.removeChild(nav);
     delete nav;
   }
 }

} /**

* This function wil re-insert the nav into the table.
*/

nrsTable.prototype.insertNav = function() {

 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 if(this.page_nav && !table.tFoot.childNodes[p])
 {
   //this means there should be a nav and there isn"t one.
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table.tFoot.appendChild(nav);
 }

} /**

* This function will hide the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.hideLeftArrows = function() {

 if(!this.page_nav)
   return;
 var myTable = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = myTable.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "none";

} /**

* This function will show the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.showLeftArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "block";

} /**

* This function will hide the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.hideRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "none";

} /**

* This function will show the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.showRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "block";

} </script> </head> <body>

nrsTable Examples

</td> </table>
<script language="JavaScript"> var header = new Array("First Name", "Last Name", "Income", "Date Hired"); var data = new Array( new Array ( "Joseph", "Smith", "$35,000", "2000"), new Array ( "Aaron", "Zelzet", "$45,000", "1997"), new Array ( "Michael", "Doe", "$55,000", "1965"), new Array ( "Cindy", "Perez", "$44,345", "2004"), new Array ( "Robert", "Williams", "$48,234", "1990"), new Array ( "William", "Cohen", "$12,234", "2005"), new Array ( "David", "Gross", "$34,563", "1998"), new Array ( "Linda", "Mendez", "$46,975", "1988"), new Array ( "Karen", "Anderson", "$124,345", "1978"), new Array ( "Veronica", "O\"Reiley", "$89,034", "1968") ); var links = new Array( "alert("Row1");", "alert("Row2");", "alert("Row3");", "alert("Row4");", "alert("Row5");", "alert("Row6");", "alert("Row7");", "alert("Row8");", "alert("Row9");", "alert("Row10");" ); nrsTable.setup( { table_name: "example3", table_header: header, table_data: data, up_icon: "nrstableimg/up.gif", down_icon: "nrstableimg/down.gif", prev_icon: "nrstableimg/left.gif", next_icon: "nrstableimg/right.gif", rew_icon: "nrstableimg/first.gif", fwd_icon: "nrstableimg/last.gif", header_color: "#53c2f4", footer_color: "#53c2f4", even_cell_color: "#b9b9ac", odd_cell_color: "#d4fbf6", hover_color: "#ccff99", natural_compare: true, caption: "Example 3 table: a caption", page_nav: true, rows_per_page: 5 } ); </script> </body> </html> </source> <A href="http://www.wbex.ru/Code/JavaScriptDownload/nrsTable-0.3.3.zip">nrsTable-0.3.3.zip( 31 k)</a>

Repeat table column at the table bottom

   <source lang="html4strict">

<html> <head> <title>nrsTable Examples</title> <style type="text/css"> body { background-color: #ffff99; } .code_display { background-color: #b9b9ac;

         border: 1px solid #9d9d94;

}

  1. example4 td.dataTD0 { letter-spacing: 2; }
  2. example4 td.dataTD1 { text-decoration: underline; }
  3. example4 td.dataTD2 { background-color: grey; }

</style> <script language="JavaScript"> /* natcompare.js -- Perform "natural order" comparisons of strings in JavaScript. Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre) Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be> Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion. Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.ru> The Java version was based on the C version by Martin Pool. Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

  • /

function isWhitespaceChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode <= 32 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function isDigitChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode >= 48  && charCode <= 57 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function compareRight(a,b) {

   var bias = 0;
   var ia = 0;
   var ib = 0;
   var ca;
   var cb;
   // The longest run of digits wins.  That aside, the greatest
   // value wins, but we can"t know that it will until we"ve scanned
   // both numbers to know that they have the same magnitude, so we
   // remember it in BIAS.
   for (;; ia++, ib++) {
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       if (!isDigitChar(ca)
               && !isDigitChar(cb)) {
           return bias;
       } else if (!isDigitChar(ca)) {
           return -1;
       } else if (!isDigitChar(cb)) {
           return +1;
       } else if (ca < cb) {
           if (bias == 0) {
               bias = -1;
           }
       } else if (ca > cb) {
           if (bias == 0)
               bias = +1;
       } else if (ca == 0 && cb == 0) {
           return bias;
       }
   }

} function natcompare(a,b) {

   var ia = 0, ib = 0;
 var nza = 0, nzb = 0;
 var ca, cb;
 var result;
   while (true)
   {
       // only count the number of zeroes leading the last number compared
       nza = nzb = 0;
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       // skip over leading spaces or zeros
       while ( isWhitespaceChar( ca ) || ca =="0" ) {
           if (ca == "0") {
               nza++;
           } else {
               // only count consecutive zeroes
               nza = 0;
           }
           ca = a.charAt(++ia);
       }
       while ( isWhitespaceChar( cb ) || cb == "0") {
           if (cb == "0") {
               nzb++;
           } else {
               // only count consecutive zeroes
               nzb = 0;
           }
           cb = b.charAt(++ib);
       }
       // process run of digits
       if (isDigitChar(ca) && isDigitChar(cb)) {
           if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
               return result;
           }
       }
       if (ca == 0 && cb == 0) {
           // The strings compare the same.  Perhaps the caller
           // will want to call strcmp to break the tie.
           return nza - nzb;
       }
       if (ca < cb) {
           return -1;
       } else if (ca > cb) {
           return +1;
       }
       ++ia; ++ib;
   }

} </script> <script language="JavaScript"> /**

* Copyright 2005 New Roads School
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**

* \class nrsTable
* This describes the nrsTable, which is a table created in JavaScript that is
* able to be sorted and displayed in different ways based on teh configuration
* parameters passed to it. 
* to create a new table one only needs to call the setup function like so:
*
 * nrsTable.setup(
 * {
 *   table_name: "table_container",
 *   table_data: d,
 *   table_header: h
 * }
 * );
 * 
* Where table_name is the name of the table to build.  THis must be defined in
* your HTML by putting a table declaration, such as
*
. This will declare where your table will be shown.
* All sorts of parameters can be customized here.  For details look at the
* function setup.
* \see setup
*/

/**

* Debug function.  Set debug to tru to view messages.
* \param msg Message to display in an alert.
*/

debug = false; function DEBUG(msg) {

 if(debug)
   alert(msg);

} /**

* There is a memory leak problem that I can"t seem to fix.  I"m attching 
* something that I found from Aaron Boodman, which will clean up all the
* memory leaks in the page (this can be found at http://youngpup.net/2005/0221010713
* ). This is a little clunky, but it will do till I track this problem.
* Oh, and this problem only occurrs is IE.
*/

if (window.attachEvent) {

   var clearElementProps = [
   "data",
       "onmouseover",
       "onmouseout",
       "onmousedown",
       "onmouseup",
       "ondblclick",
       "onclick",
       "onselectstart",
       "oncontextmenu"
   ];
   window.attachEvent("onunload", function() {
       var el;
       for(var d = document.all.length;d--;){
           el = document.all[d];
           for(var c = clearElementProps.length;c--;){
               el[clearElementProps[c]] = null;
           }
       }
   });

}

/**

* This is the constructor.
* It only needs the name of the table.  This should never be called directly, 
* instead use setup function.
* \param table The name of the table to create.
* \see setup
*/

function nrsTable(table) {

 this.my_table = table;
 this.field_to_sort = 0;
 this.field_asc = true;

} new nrsTable(""); /**

* This function is responsible for setting up an nrsTable.  All the parameters
* can be configured directly from this function.  The params array of this 
* function is a class (or a associative array, depending on how you want to
* look at it) with the following possible parameters:
*   - table_name: required.  The id of the table tag.
*  - table_header: required.  An array containing the header names.
*   - table_data: optional.  A 2D array of strings containing the cell contents.
*  - caption: optional.  A caption to include on the table.
*  - row_links: optional.  An array with hyperlinks per row.  Must be a javascript function.
*  - cell_links: optional.  A 2D array with links on every cell.  Must be a javascript function
*  - up_icon: optional.  A path to the ascending sort arrow.
*  - down_icon: optional.  A path to the descending sort arrow.
*  - prev_icon: optional.  A path to the previous page icon in the navigation.
*  - next_icon: optional.  A path to the next page icon in the navigation.
*  - rew_icon: optional.  A path to the first page icon in the navigation.
*  - fwd_icon: optional.  A path to the last page icon in the navigation.
*  - rows_per_page: optional.  The number of rows per page to display at any one time.
*  - display_nav: optional.  Displays navigation (prev, next, first, last)
*  - foot_headers: optional.  Whether to display th eheaders at the foot of the table.
*  - header_color: optional.  The color of the header cells.  Will default to whatever is defined in CSS.
*  - even_cell_color: optional.  The color of the even data cells.  Will default to whatever is defined in CSS.
*  - odd_cell_color: optional.  The color of the odd data cells.  Will default to whatever is defined in CSS.
*  - footer_color: optional.  The color of the footer cells.  Will default to whatever is defined in CSS.
*  - hover_color: optional.  The color tha a row should turn when the mouse is over it.
*  - padding: optional.  Individual cell padding, in pixels.
*  - natural_compare: optional.  Uses the natural compare algorithm (separate from this program) to sort.
*  - disable_sorting: optional.  An array specifying the columns top disable sorting on (0 is the first column).
*
* \params params An array as described above.
*/

nrsTable.setup = function(params) {

 //here we assign all the veriables that we are passed, or the defaults if 
 //they are not defined.
 //Note that the only requirements are a table name and a header.
 if(typeof params["table_name"] == "undefined")
 {
   alert("Error! You must supply a table name!");
   return null;
 }
 if(typeof params["table_header"] == "undefined")
 {
   alert("Error! You must supply a table header!");
   return null;
 }
 
 //check if the global array exists, else create it.
 if(typeof(nrsTables) == "undefined")
 {
   eval("nrsTables = new Array();");
 }
 nrsTables[params["table_name"]] = new nrsTable(params["table_name"]);
 nrsTables[params["table_name"]].heading = params["table_header"].concat();
 
 //now the non-required elements.  Data elements first
 nrsTables[params["table_name"]].data = (typeof params["table_data"] == "undefined" || !params["table_data"])? null: params["table_data"].concat();
 nrsTables[params["table_name"]].caption = (typeof params["caption"] == "undefined")? null: params["caption"];
 nrsTables[params["table_name"]].row_links = (typeof params["row_links"] == "undefined" || !params["row_links"])? null: params["row_links"].concat();
 nrsTables[params["table_name"]].cell_links = (typeof params["cell_links"] == "undefined" || !params["row_links"])? null: params["cell_links"].concat();
 
 //these are the icons.
 nrsTables[params["table_name"]].up_icon = (typeof params["up_icon"] == "undefined")? "up.gif": params["up_icon"];
 nrsTables[params["table_name"]].down_icon = (typeof params["down_icon"] == "undefined")? "down.gif": params["down_icon"];
 nrsTables[params["table_name"]].prev_icon = (typeof params["prev_icon"] == "undefined")? "left.gif": params["prev_icon"];
 nrsTables[params["table_name"]].next_icon = (typeof params["next_icon"] == "undefined")? "right.gif": params["next_icon"];
 nrsTables[params["table_name"]].rew_icon = (typeof params["rew_icon"] == "undefined")? "first.gif": params["rew_icon"];
 nrsTables[params["table_name"]].fwd_icon = (typeof params["fwd_icon"] == "undefined")? "last.gif": params["fwd_icon"];
 
 //now the look and feel options.
 nrsTables[params["table_name"]].rows_per_page = (typeof params["rows_per_page"] == "undefined")? -1: params["rows_per_page"];
 nrsTables[params["table_name"]].page_nav = (typeof params["page_nav"] == "undefined")? false: params["page_nav"];
 nrsTables[params["table_name"]].foot_headers = (typeof params["foot_headers"] == "undefined")? false: params["foot_headers"];
 nrsTables[params["table_name"]].header_color = (typeof params["header_color"] == "undefined")? null: params["header_color"];
 nrsTables[params["table_name"]].even_cell_color = (typeof params["even_cell_color"] == "undefined")? null: params["even_cell_color"];
 nrsTables[params["table_name"]].odd_cell_color = (typeof params["odd_cell_color"] == "undefined")? null: params["odd_cell_color"];
 nrsTables[params["table_name"]].footer_color = (typeof params["footer_color"] == "undefined")? null: params["footer_color"];
 nrsTables[params["table_name"]].hover_color = (typeof params["hover_color"] == "undefined")? null: params["hover_color"];
 nrsTables[params["table_name"]].padding = (typeof params["padding"] == "undefined")? null: params["padding"];
 nrsTables[params["table_name"]].natural_compare = (typeof params["natural_compare"] == "undefined")? false: true;
 nrsTables[params["table_name"]].disable_sorting = 
   (typeof params["disable_sorting"] == "undefined")? false: "." + params["disable_sorting"].join(".") + ".";
 //finally, build the table
 nrsTables[params["table_name"]].buildTable();

};

/**

* This is the Javascript quicksort implementation.  This will sort the 
* this.data and the this.data_nodes based on the this.field_to_sort parameter.
* \param left The left index of the array.
* \param right The right index of the array
*/

nrsTable.prototype.quickSort = function(left, right) {

 if(!this.data || this.data.length == 0)
   return;
 var i = left;
 var j = right;
 var k = this.data[Math.round((left + right) / 2)][this.field_to_sort];
 while(j > i)
 {
   if(this.field_asc)
   {
     while(this.data[i][this.field_to_sort].toLowerCase() < k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() > k.toLowerCase())
       j--;
   }
   else
   {
     while(this.data[i][this.field_to_sort].toLowerCase() > k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() < k.toLowerCase())
       j--;
   }
   if(i <= j )
   {
     //swap both values
     //sort data
     var temp = this.data[i];
     this.data[i] = this.data[j];
     this.data[j] = temp;
     
     //sort contents
     var temp = this.data_nodes[i];
     this.data_nodes[i] = this.data_nodes[j];
     this.data_nodes[j] = temp;
     i++;
     j--;
   }
 }
 if(left < j)
   this.quickSort(left, j);
 if(right > i)
   this.quickSort(i, right);

} /**

* This is the Javascript natural sort function.  Because of some obscure JavaScript
* quirck, we could not do quicsort while calling natcompare to compare, so this
* function will so a simple bubble sort using the natural compare algorithm.
*/

nrsTable.prototype.natSort = function() {

 if(!this.data || this.data.length == 0)
   return;
 var swap;
 for(i = 0; i < this.data.length - 1; i++)
 {
   for(j = i; j < this.data.length; j++)
   {
     if(!this.field_asc)
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == -1)
         swap = true;
       else
         swap = false;
     }
     else
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == 1)
         swap = true;
       else
         swap = false;
     }
     if(swap)
     {
       //swap both values
       //sort data
       var temp = this.data[i];
       this.data[i] = this.data[j];
       this.data[j] = temp;
       
       //sort contents
       var temp = this.data_nodes[i];
       this.data_nodes[i] = this.data_nodes[j];
       this.data_nodes[j] = temp;
     }
   }
 }

} /**

* This function will recolor all the the nodes to conform to the alternating 
* row colors.
*/

nrsTable.prototype.recolorRows = function() {

 if(this.even_cell_color || this.odd_cell_color)
 {
   DEBUG("Recoloring Rows. length = " + this.data_nodes.length);
   for(var i = 0; i < this.data_nodes.length; i++)
   {
     if(i % 2 == 0)
     {
       if(this.even_cell_color)
         this.data_nodes[i].style.backgroundColor = this.even_cell_color;
       this.data_nodes[i].setAttribute("id", "even_row");
     }
     else
     {
       if(this.odd_cell_color)
         this.data_nodes[i].style.backgroundColor = this.odd_cell_color;
       this.data_nodes[i].setAttribute("id", "odd_row");
     }
   }
 }

} /**

* This function will create the Data Nodes, which are a reference to the table
* rows in the HTML.
*/

nrsTable.prototype.createDataNodes = function() {

 if(this.data_nodes)
   delete this.data_nodes;
 this.data_nodes = new Array();
 if(!this.data)
   return;
 for(var i = 0; i < this.data.length; i++)
 {
   var curr_row = document.createElement("TR");
   
   for(var j = 0; j < this.data[i].length; j++)
   {
     var curr_cell = document.createElement("TD");
     //do we need to create links on every cell?
     if(this.cell_links)
     {
       var fn = new Function("", this.cell_links[i][j]);
       curr_cell.onclick = fn;
       curr_cell.style.cursor = "pointer";
     }
     //workaround for IE
     curr_cell.setAttribute("className", "dataTD" + j);
     //assign the padding
     if(this.padding)
     {
       curr_cell.style.paddingLeft = this.padding + "px";
       curr_cell.style.paddingRight = this.padding + "px";
     }
     curr_cell.appendChild(document.createTextNode(this.data[i][j]));
     curr_row.appendChild(curr_cell);
   }
   //do we need to create links on every row?
   if(!this.cell_links && this.row_links)
   {
     var fn = new Function("", this.row_links[i]);
     curr_row.onclick = fn;
     curr_row.style.cursor = "pointer";
   }
   //sets the id for odd and even rows.
   if(i % 2 == 0)
   {
     curr_row.setAttribute("id", "even_row");
     if(this.even_cell_color)
       curr_row.style.backgroundColor = this.even_cell_color;
   }
   else
   {
     curr_row.setAttribute("id", "odd_row");
     if(this.odd_cell_color)
       curr_row.style.backgroundColor = this.odd_cell_color;
   }
   if(this.hover_color)
   {
     curr_row.onmouseover = new Function("", "this.style.backgroundColor="" + this.hover_color + "";");
     curr_row.onmouseout = new Function("", "this.style.backgroundColor=(this.id=="even_row")?"" + 
               this.even_cell_color + "":"" + this.odd_cell_color + "";");
   }
   this.data_nodes[i] = curr_row;
 }

} /**

* This function will update the nav page display.
*/

nrsTable.prototype.updateNav = function() {

 if(this.page_nav)
 {
   var p = 0;
   if(this.foot_headers)
     p++;
   var t = document.getElementById(this.my_table);
   var nav = t.tFoot.childNodes[p];
   if(nav)
   {
     var caption = t.tFoot.childNodes[p].childNodes[0].childNodes[2];
     caption.innerHTML = "Page " + (this.current_page + 1) + " of " + this.num_pages;
   }
   else
   {
     if(this.num_pages > 1)
     {
       this.insertNav();
       nav = t.tFoot.childNodes[p];
     }
   }
   if(nav)
   {
     if(this.current_page == 0)
       this.hideLeftArrows();
     else
       this.showLeftArrows();
     
     if(this.current_page + 1 == this.num_pages)
       this.hideRightArrows();
     else
       this.showRightArrows();
   }
 }

} /**

* This function will flip the sort arrow in place.  If a heading is used in the
* footer, then it will flip that one too.
*/

nrsTable.prototype.flipSortArrow = function() {

 this.field_asc = !this.field_asc;
 //flip the arrow on the heading.
 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 if(this.field_asc)
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
 else
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 //is there a heading in the footer?
 if(this.foot_headers)
 {
   //yes, so flip that arrow too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   if(this.field_asc)
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
   else
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 }

} /**

* This function will move the sorting arrow from the place specified in 
* this.field_to_sort to the passed parameter.  It will also set 
* this.field_to_sort to the new value.  It will also do it in the footers, 
* if they exists.
* \param field The new field to move it to.
*/

nrsTable.prototype.moveSortArrow = function(field) {

 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 var img = heading.removeChild(heading.getElementsByTagName("IMG")[0]);
 heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[field];
 heading.appendChild(img);
 //are there headers in the footers.
 if(this.foot_headers)
 {
   //yes, so switch them too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   var img = footer.removeChild(footer.getElementsByTagName("IMG")[0]);
   footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[field];
   footer.appendChild(img);
 }
 //finally, set the field to sort by.
 this.field_to_sort = field;

} /**

* This function completely destroys a table.  Should be used only when building
* a brand new table (ie, new headers).  Else you should use a function like
* buildNewData which only deletes the TBody section.
*/

nrsTable.prototype.emptyTable = function() {

 var t = document.getElementById(this.my_table);
 while(t.childNodes.length != 0)
   t.removeChild(t.childNodes[0]);

}; /**

* This function builds a brand new table from scratch.  This function should
* only be called when a brand new table (with headers, footers, etc) needs
* to be created.  NOT when refreshing data or changing data.
*/

nrsTable.prototype.buildTable = function() {

 //reset the sorting information.
 this.field_to_sort = 0;
 this.field_asc = true;
 
 //remove the nodes links.
 delete this.data_nodes;
 
 //do we have to calculate the number of pages?
 if(this.data && this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.current_page = 0;
 }
 
 //blank out the table.
 this.emptyTable();
 
 //this is the table that we will be using.
 var table = document.getElementById(this.my_table);
 
 //is there a caption?
 if(this.caption)
 {
   var caption = document.createElement("CAPTION");
   caption.setAttribute("align", "top");
   caption.appendChild(document.createTextNode(this.caption));
   table.appendChild(caption);
 }
 
 //do the heading first
 var table_header = document.createElement("THEAD");
 var table_heading = document.createElement("TR");
 //since this is a new table the first field is what"s being sorted.
 var curr_cell = document.createElement("TH");
 var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + 0 + ");");
 if(!this.disable_sorting || this.disable_sorting.indexOf(".0.") == -1)
   curr_cell.onclick = fn;
 if(this.header_color)
   curr_cell.style.backgroundColor = this.header_color;
 curr_cell.style.cursor = "pointer";
 var img = document.createElement("IMG");
 img.setAttribute("src", this.up_icon);
 img.setAttribute("border", "0");
 img.setAttribute("height", "8");
 img.setAttribute("width", "8");
 curr_cell.appendChild(document.createTextNode(this.heading[0]));
 curr_cell.appendChild(img);
 table_heading.appendChild(curr_cell);
 //now do the rest of the heading.
 for(var i = 1; i < this.heading.length; i++)
 {
   curr_cell = document.createElement("TH");
   var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + i + ");");
   if(!this.disable_sorting || this.disable_sorting.indexOf("." + i + ".") == -1)
     curr_cell.onclick = fn;
   if(this.header_color)
     curr_cell.style.backgroundColor = this.header_color;
   curr_cell.style.cursor = "pointer";
   //build the sorter
   curr_cell.appendChild(document.createTextNode(this.heading[i]));
   table_heading.appendChild(curr_cell);
 }
 table_header.appendChild(table_heading);
 
 //now the content
 var table_body = document.createElement("TBODY");
 this.createDataNodes();
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
   this.recolorRows();
 }
 //finally, the footer
 var table_footer = document.createElement("TFOOT");
 if(this.foot_headers)
 {
   table_footer.appendChild(table_heading.cloneNode(true));
 }
 
 if(this.page_nav && this.num_pages > 1)
 {
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table_footer.appendChild(nav);
 }
 
 if(this.footer_color)
 {
   for(var i = 0; i < table_footer.childNodes.length; i++)
     table_footer.childNodes[i].style.backgroundColor = this.footer_color;
 }
 
 //append the data
 table.appendChild(table_header);
 table.appendChild(table_body);
 table.appendChild(table_footer);
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
 }
 this.refreshTable();

}; /**

* This function will remove the elements in teh TBody section of the table and
* return an array of references of those elements.  This array can then be 
* sorted and re-inserted into the table.
* \return An array to references of the TBody contents.
*/

nrsTable.prototype.extractElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var nodes = new Array();
 var i = 0;
 while(tbody.childNodes.length > 0)
 {
   nodes[i] = tbody.removeChild(tbody.childNodes[0]);
   i++;
 }
 return nodes;

} /**

* This function will re-insert an array of elements into the TBody of a table.
* Note that the array elements are stored in the this.data_nodes reference.
*/

nrsTable.prototype.insertElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var start = 0;
 var num_elements = this.data_nodes.length;
 if(this.rows_per_page != -1)
 {
   start = this.current_page * this.rows_per_page;
   num_elements = (this.data_nodes.length - start) > this.rows_per_page?
             this.rows_per_page + start:
             this.data_nodes.length;
 }
 DEBUG("start is " + start + " and num_elements is " + num_elements);
 for(var i = start; i < num_elements; i++)
 {
   tbody.appendChild(this.data_nodes[i]);
 }

} /**

* This function will sort the table"s data by a specific field.  The field 
* parameter referes to which field index should be sorted.
* \param field The field index which to sort on.
*/

nrsTable.prototype.fieldSort = function(field) {

 if(this.field_to_sort == field)
 {
   //only need to reverse the array.
   if(this.data)
   {
     this.data.reverse();
     this.data_nodes.reverse();
   }
   //flip the arrow on the heading.
   this.flipSortArrow();
 }
 else
 {
   //In this case, we need to sort the array.  We"ll sort it last, first 
   //make sure that the arrow images are set correctly.
   this.moveSortArrow(field);
   //finally, set the field to sort by.
   this.field_to_sort = field;
   if(this.data)
   {
     //we"ll be using our implementation of quicksort
     if(this.natural_compare)
       this.natSort(0, this.data.length - 1);
     else
       this.quickSort(0, this.data.length - 1);
   }
 }
 //finally, we refresh the table.
 this.refreshTable();

}; /**

* This function will refresh the data in the table.  This function should be
* used whenever the nodes have changed, or when chanign pages.  Note that 
* this will NOT re-sort.
*/

nrsTable.prototype.refreshTable = function() {

 this.extractElements();
 this.recolorRows();
 this.insertElements();
 //finally, if there is a nav, upate it.
 this.updateNav();

} /**

* This function will advance a page.  If we are already at the last page, then 
* it will remain there.
*/

nrsTable.prototype.nextPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page + 1 != this.num_pages)
 {
   this.current_page++;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go back a page.  If we are already at the first page, then 
* it will remain there.
*/

nrsTable.prototype.prevPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page != 0)
 {
   this.current_page--;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go to the first page.
*/

nrsTable.prototype.firstPage = function() {

 if(this.current_page != 0)
 {
   this.current_page = 0;
   this.refreshTable();
 }

} /**

* This function will go to the last page.
*/

nrsTable.prototype.lastPage = function() {

 DEBUG("lastPage(), current_page: " + this.current_page + " and num_pages: " + this.num_pages);
 if(this.current_page != (this.num_pages - 1))
 {
   this.current_page = this.num_pages - 1;
   this.refreshTable();
 }

} /**

* This function will go to a specific page.  valid values are pages 1 to 
* however many number of pages there are.
* \param page The page number to go to.
*/

nrsTable.prototype.gotoPage = function(page) {

 page--;
 if(page >=0 && page < this.num_pages)
 {
   this.current_page = page;
   this.refreshTable();
 }

} /**

* This function can be used to change the number of entries per row displayed
* on the fly.
* \param entries The number of entries per page.
*/

nrsTable.prototype.changeNumRows = function(entries) {

 if(entries > 0)
 {
   this.rows_per_page = entries;
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.refreshTable();
 }

} /**

* This function will take in a new data array and , optionally, a new cell_link
* array OR a new row_link array.  Only one will be used, with the cell_link
* array taking precedence.  It will then re-build the table with the new data
* array.
* \param new_data This is the new data array.  This is required.
* \param cell_links This is the new cell links array, a 2D array for each cell.
* \param row_links This is the new row links array, a 1D array for each row.
*/

nrsTable.prototype.newData = function(new_data, cell_links, row_links) {

 //extract the elements from teh table to clear the table.
 this.extractElements();
 //now delete all the data related to this table.  I do this so that 
 //(hopefully) the memory will be freed.  This is realy needed for IE, whose
 //memory handling is almost non-existant
 delete this.data;
 delete this.data_nodes;
 delete this.cell_links;
 delete this.row_links
 //now re-assign.
 this.data = new_data;
 this.cell_links = cell_links;
 this.row_links = row_links;
 if(this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   if(this.num_pages <= 1 && this.page_nav)
     this.removeNav();
   else if(this.page_nav)
     this.insertNav();
   this.current_page = 0;
 }
 this.createDataNodes();
 if(this.field_to_sort != 0)
   this.moveSortArrow(0);
 if(!this.field_asc)
   this.flipSortArrow();
 this.insertElements();
 this.updateNav();

} /**

* This function will remove the NAV bar (if one exists) from the table.
*/

nrsTable.prototype.removeNav = function() {

 if(this.page_nav)
 {
   //in this case, remove the nav from the existing structure.
   var table = document.getElementById(this.my_table);
   var p = 0;
   if(this.foot_headers)
     p++;
   var nav = table.tFoot.childNodes[p];
   if(nav)
   {
     table.tFoot.removeChild(nav);
     delete nav;
   }
 }

} /**

* This function wil re-insert the nav into the table.
*/

nrsTable.prototype.insertNav = function() {

 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 if(this.page_nav && !table.tFoot.childNodes[p])
 {
   //this means there should be a nav and there isn"t one.
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table.tFoot.appendChild(nav);
 }

} /**

* This function will hide the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.hideLeftArrows = function() {

 if(!this.page_nav)
   return;
 var myTable = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = myTable.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "none";

} /**

* This function will show the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.showLeftArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "block";

} /**

* This function will hide the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.hideRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "none";

} /**

* This function will show the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.showRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "block";

} </script> </head> <body>

nrsTable Examples

</td> </table>
<script language="JavaScript"> var header = new Array("First Name", "Last Name", "Income", "Date Hired"); var data = new Array( new Array ( "Joseph", "Smith", "$35,000", "2000"), new Array ( "Aaron", "Zelzet", "$45,000", "1997"), new Array ( "Michael", "Doe", "$55,000", "1965"), new Array ( "Cindy", "Perez", "$44,345", "2004"), new Array ( "Robert", "Williams", "$48,234", "1990"), new Array ( "William", "Cohen", "$12,234", "2005"), new Array ( "David", "Gross", "$34,563", "1998"), new Array ( "Linda", "Mendez", "$46,975", "1988"), new Array ( "Karen", "Anderson", "$124,345", "1978"), new Array ( "Veronica", "O\"Reiley", "$89,034", "1968") ); var links = new Array( "alert("Row1");", "alert("Row2");", "alert("Row3");", "alert("Row4");", "alert("Row5");", "alert("Row6");", "alert("Row7");", "alert("Row8");", "alert("Row9");", "alert("Row10");" ); nrsTable.setup( { table_name: "example4", table_header: header, table_data: data, row_links: links, foot_headers: true, up_icon: "img/up.gif", down_icon: "img/down.gif", prev_icon: "img/left.gif", next_icon: "img/right.gif", rew_icon: "img/first.gif", fwd_icon: "img/last.gif", header_color: "#53c2f4", footer_color: "#53c2f4", even_cell_color: "#b9b9ac", odd_cell_color: "#d4fbf6", hover_color: "#ccff99", natural_compare: true, caption: "Example 3 table: a caption", page_nav: true, rows_per_page: 5, padding: 3, natural_compare: true, disable_sorting: new Array(1,3) } ); </script> </body> </html> </source> <A href="http://www.wbex.ru/Code/JavaScriptDownload/nrsTable-0.3.3.zip">nrsTable-0.3.3.zip( 31 k)</a>

Selectable Cells Grid Table

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 3 - Selectable Cells Grid</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = "
"; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 

</head> <body>

OS3Grid Example 3 - Selectable Cells Grid

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

     <script type="text/javascript">
       function cell_clicked ( grid, cell, row_num, col_num, val )
       {
         alert ( "Grid: " + grid.id + " cell: " + cell + " - rown: " + row_num + " - col: " + col_num + " - val: " + val );
         return ( true );
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "E-Mail Address" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", "fsoft (@) sourceforge (dot) net" );
       g.add_row ( "john", "John", "Bustone", "jbust (@) somewhere (dot) net" );
       g.add_row ( "mkey", "Mark", "Key", "mkey (@) okay (dot) net" );
       g.add_row ( "jdoe", "John", "Doe", "redbull (@) batman (dot) net" );
       // Enable sortable rows
       g.set_sortable ( true );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       g.set_cell_click ( cell_clicked );
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Sortable Grids (table)

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 2 - Sortable Grids</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 

</head> <body>

OS3Grid Example 2 - Sortable Grids

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   sort the rows by clicking
   on the column names: add the following line of code before the g.render()
   instruction:
      g.set_sortable ( true );
    
   a single line of code and you have sortable rows!
a single row highlighted when I move the mouse,
      g.set_highlight ( true );
    
     <script type="text/javascript">
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "E-Mail Address" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", "fsoft (@) sourceforge (dot) net" );
       g.add_row ( "john", "John", "Bustone", "jbust (@) somewhere (dot) net" );
       g.add_row ( "mkey", "Mark", "Key", "mkey (@) okay (dot) net" );
       g.add_row ( "jdoe", "John", "Doe", "redbull (@) batman (dot) net" );
       // Enable sortable rows
       g.set_sortable ( true );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Sortable Table

<A href="http://www.wbex.ru/Code/JavaScriptDownload/sortableTable.zip">sortableTable.zip( 19 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a>

Sortable table column

   <source lang="html4strict">

<html> <head> <title>nrsTable Examples</title> <style type="text/css"> body { background-color: #ffff99; } .code_display { background-color: #b9b9ac;

         border: 1px solid #9d9d94;

}

  1. example4 td.dataTD0 { letter-spacing: 2; }
  2. example4 td.dataTD1 { text-decoration: underline; }
  3. example4 td.dataTD2 { background-color: grey; }

</style> <script language="JavaScript"> /* natcompare.js -- Perform "natural order" comparisons of strings in JavaScript. Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre) Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be> Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion. Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.ru> The Java version was based on the C version by Martin Pool. Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

  • /

function isWhitespaceChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode <= 32 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function isDigitChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode >= 48  && charCode <= 57 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function compareRight(a,b) {

   var bias = 0;
   var ia = 0;
   var ib = 0;
   var ca;
   var cb;
   // The longest run of digits wins.  That aside, the greatest
   // value wins, but we can"t know that it will until we"ve scanned
   // both numbers to know that they have the same magnitude, so we
   // remember it in BIAS.
   for (;; ia++, ib++) {
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       if (!isDigitChar(ca)
               && !isDigitChar(cb)) {
           return bias;
       } else if (!isDigitChar(ca)) {
           return -1;
       } else if (!isDigitChar(cb)) {
           return +1;
       } else if (ca < cb) {
           if (bias == 0) {
               bias = -1;
           }
       } else if (ca > cb) {
           if (bias == 0)
               bias = +1;
       } else if (ca == 0 && cb == 0) {
           return bias;
       }
   }

} function natcompare(a,b) {

   var ia = 0, ib = 0;
 var nza = 0, nzb = 0;
 var ca, cb;
 var result;
   while (true)
   {
       // only count the number of zeroes leading the last number compared
       nza = nzb = 0;
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       // skip over leading spaces or zeros
       while ( isWhitespaceChar( ca ) || ca =="0" ) {
           if (ca == "0") {
               nza++;
           } else {
               // only count consecutive zeroes
               nza = 0;
           }
           ca = a.charAt(++ia);
       }
       while ( isWhitespaceChar( cb ) || cb == "0") {
           if (cb == "0") {
               nzb++;
           } else {
               // only count consecutive zeroes
               nzb = 0;
           }
           cb = b.charAt(++ib);
       }
       // process run of digits
       if (isDigitChar(ca) && isDigitChar(cb)) {
           if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
               return result;
           }
       }
       if (ca == 0 && cb == 0) {
           // The strings compare the same.  Perhaps the caller
           // will want to call strcmp to break the tie.
           return nza - nzb;
       }
       if (ca < cb) {
           return -1;
       } else if (ca > cb) {
           return +1;
       }
       ++ia; ++ib;
   }

} </script> <script language="JavaScript"> /**

* Copyright 2005 New Roads School
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**

* \class nrsTable
* This describes the nrsTable, which is a table created in JavaScript that is
* able to be sorted and displayed in different ways based on teh configuration
* parameters passed to it. 
* to create a new table one only needs to call the setup function like so:
*
 * nrsTable.setup(
 * {
 *   table_name: "table_container",
 *   table_data: d,
 *   table_header: h
 * }
 * );
 * 
* Where table_name is the name of the table to build.  THis must be defined in
* your HTML by putting a table declaration, such as *
. This will declare where your table will be shown.
* All sorts of parameters can be customized here.  For details look at the
* function setup.
* \see setup
*/

/**

* Debug function.  Set debug to tru to view messages.
* \param msg Message to display in an alert.
*/

debug = false; function DEBUG(msg) {

 if(debug)
   alert(msg);

} /**

* There is a memory leak problem that I can"t seem to fix.  I"m attching 
* something that I found from Aaron Boodman, which will clean up all the
* memory leaks in the page (this can be found at http://youngpup.net/2005/0221010713
* ). This is a little clunky, but it will do till I track this problem.
* Oh, and this problem only occurrs is IE.
*/

if (window.attachEvent) {

   var clearElementProps = [
   "data",
       "onmouseover",
       "onmouseout",
       "onmousedown",
       "onmouseup",
       "ondblclick",
       "onclick",
       "onselectstart",
       "oncontextmenu"
   ];
   window.attachEvent("onunload", function() {
       var el;
       for(var d = document.all.length;d--;){
           el = document.all[d];
           for(var c = clearElementProps.length;c--;){
               el[clearElementProps[c]] = null;
           }
       }
   });

}

/**

* This is the constructor.
* It only needs the name of the table.  This should never be called directly, 
* instead use setup function.
* \param table The name of the table to create.
* \see setup
*/

function nrsTable(table) {

 this.my_table = table;
 this.field_to_sort = 0;
 this.field_asc = true;

} new nrsTable(""); /**

* This function is responsible for setting up an nrsTable.  All the parameters
* can be configured directly from this function.  The params array of this 
* function is a class (or a associative array, depending on how you want to
* look at it) with the following possible parameters:
*   - table_name: required.  The id of the table tag.
*  - table_header: required.  An array containing the header names.
*   - table_data: optional.  A 2D array of strings containing the cell contents.
*  - caption: optional.  A caption to include on the table.
*  - row_links: optional.  An array with hyperlinks per row.  Must be a javascript function.
*  - cell_links: optional.  A 2D array with links on every cell.  Must be a javascript function
*  - up_icon: optional.  A path to the ascending sort arrow.
*  - down_icon: optional.  A path to the descending sort arrow.
*  - prev_icon: optional.  A path to the previous page icon in the navigation.
*  - next_icon: optional.  A path to the next page icon in the navigation.
*  - rew_icon: optional.  A path to the first page icon in the navigation.
*  - fwd_icon: optional.  A path to the last page icon in the navigation.
*  - rows_per_page: optional.  The number of rows per page to display at any one time.
*  - display_nav: optional.  Displays navigation (prev, next, first, last)
*  - foot_headers: optional.  Whether to display th eheaders at the foot of the table.
*  - header_color: optional.  The color of the header cells.  Will default to whatever is defined in CSS.
*  - even_cell_color: optional.  The color of the even data cells.  Will default to whatever is defined in CSS.
*  - odd_cell_color: optional.  The color of the odd data cells.  Will default to whatever is defined in CSS.
*  - footer_color: optional.  The color of the footer cells.  Will default to whatever is defined in CSS.
*  - hover_color: optional.  The color tha a row should turn when the mouse is over it.
*  - padding: optional.  Individual cell padding, in pixels.
*  - natural_compare: optional.  Uses the natural compare algorithm (separate from this program) to sort.
*  - disable_sorting: optional.  An array specifying the columns top disable sorting on (0 is the first column).
*
* \params params An array as described above.
*/

nrsTable.setup = function(params) {

 //here we assign all the veriables that we are passed, or the defaults if 
 //they are not defined.
 //Note that the only requirements are a table name and a header.
 if(typeof params["table_name"] == "undefined")
 {
   alert("Error! You must supply a table name!");
   return null;
 }
 if(typeof params["table_header"] == "undefined")
 {
   alert("Error! You must supply a table header!");
   return null;
 }
 
 //check if the global array exists, else create it.
 if(typeof(nrsTables) == "undefined")
 {
   eval("nrsTables = new Array();");
 }
 nrsTables[params["table_name"]] = new nrsTable(params["table_name"]);
 nrsTables[params["table_name"]].heading = params["table_header"].concat();
 
 //now the non-required elements.  Data elements first
 nrsTables[params["table_name"]].data = (typeof params["table_data"] == "undefined" || !params["table_data"])? null: params["table_data"].concat();
 nrsTables[params["table_name"]].caption = (typeof params["caption"] == "undefined")? null: params["caption"];
 nrsTables[params["table_name"]].row_links = (typeof params["row_links"] == "undefined" || !params["row_links"])? null: params["row_links"].concat();
 nrsTables[params["table_name"]].cell_links = (typeof params["cell_links"] == "undefined" || !params["row_links"])? null: params["cell_links"].concat();
 
 //these are the icons.
 nrsTables[params["table_name"]].up_icon = (typeof params["up_icon"] == "undefined")? "up.gif": params["up_icon"];
 nrsTables[params["table_name"]].down_icon = (typeof params["down_icon"] == "undefined")? "down.gif": params["down_icon"];
 nrsTables[params["table_name"]].prev_icon = (typeof params["prev_icon"] == "undefined")? "left.gif": params["prev_icon"];
 nrsTables[params["table_name"]].next_icon = (typeof params["next_icon"] == "undefined")? "right.gif": params["next_icon"];
 nrsTables[params["table_name"]].rew_icon = (typeof params["rew_icon"] == "undefined")? "first.gif": params["rew_icon"];
 nrsTables[params["table_name"]].fwd_icon = (typeof params["fwd_icon"] == "undefined")? "last.gif": params["fwd_icon"];
 
 //now the look and feel options.
 nrsTables[params["table_name"]].rows_per_page = (typeof params["rows_per_page"] == "undefined")? -1: params["rows_per_page"];
 nrsTables[params["table_name"]].page_nav = (typeof params["page_nav"] == "undefined")? false: params["page_nav"];
 nrsTables[params["table_name"]].foot_headers = (typeof params["foot_headers"] == "undefined")? false: params["foot_headers"];
 nrsTables[params["table_name"]].header_color = (typeof params["header_color"] == "undefined")? null: params["header_color"];
 nrsTables[params["table_name"]].even_cell_color = (typeof params["even_cell_color"] == "undefined")? null: params["even_cell_color"];
 nrsTables[params["table_name"]].odd_cell_color = (typeof params["odd_cell_color"] == "undefined")? null: params["odd_cell_color"];
 nrsTables[params["table_name"]].footer_color = (typeof params["footer_color"] == "undefined")? null: params["footer_color"];
 nrsTables[params["table_name"]].hover_color = (typeof params["hover_color"] == "undefined")? null: params["hover_color"];
 nrsTables[params["table_name"]].padding = (typeof params["padding"] == "undefined")? null: params["padding"];
 nrsTables[params["table_name"]].natural_compare = (typeof params["natural_compare"] == "undefined")? false: true;
 nrsTables[params["table_name"]].disable_sorting = 
   (typeof params["disable_sorting"] == "undefined")? false: "." + params["disable_sorting"].join(".") + ".";
 //finally, build the table
 nrsTables[params["table_name"]].buildTable();

};

/**

* This is the Javascript quicksort implementation.  This will sort the 
* this.data and the this.data_nodes based on the this.field_to_sort parameter.
* \param left The left index of the array.
* \param right The right index of the array
*/

nrsTable.prototype.quickSort = function(left, right) {

 if(!this.data || this.data.length == 0)
   return;
 var i = left;
 var j = right;
 var k = this.data[Math.round((left + right) / 2)][this.field_to_sort];
 while(j > i)
 {
   if(this.field_asc)
   {
     while(this.data[i][this.field_to_sort].toLowerCase() < k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() > k.toLowerCase())
       j--;
   }
   else
   {
     while(this.data[i][this.field_to_sort].toLowerCase() > k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() < k.toLowerCase())
       j--;
   }
   if(i <= j )
   {
     //swap both values
     //sort data
     var temp = this.data[i];
     this.data[i] = this.data[j];
     this.data[j] = temp;
     
     //sort contents
     var temp = this.data_nodes[i];
     this.data_nodes[i] = this.data_nodes[j];
     this.data_nodes[j] = temp;
     i++;
     j--;
   }
 }
 if(left < j)
   this.quickSort(left, j);
 if(right > i)
   this.quickSort(i, right);

} /**

* This is the Javascript natural sort function.  Because of some obscure JavaScript
* quirck, we could not do quicsort while calling natcompare to compare, so this
* function will so a simple bubble sort using the natural compare algorithm.
*/

nrsTable.prototype.natSort = function() {

 if(!this.data || this.data.length == 0)
   return;
 var swap;
 for(i = 0; i < this.data.length - 1; i++)
 {
   for(j = i; j < this.data.length; j++)
   {
     if(!this.field_asc)
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == -1)
         swap = true;
       else
         swap = false;
     }
     else
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == 1)
         swap = true;
       else
         swap = false;
     }
     if(swap)
     {
       //swap both values
       //sort data
       var temp = this.data[i];
       this.data[i] = this.data[j];
       this.data[j] = temp;
       
       //sort contents
       var temp = this.data_nodes[i];
       this.data_nodes[i] = this.data_nodes[j];
       this.data_nodes[j] = temp;
     }
   }
 }

} /**

* This function will recolor all the the nodes to conform to the alternating 
* row colors.
*/

nrsTable.prototype.recolorRows = function() {

 if(this.even_cell_color || this.odd_cell_color)
 {
   DEBUG("Recoloring Rows. length = " + this.data_nodes.length);
   for(var i = 0; i < this.data_nodes.length; i++)
   {
     if(i % 2 == 0)
     {
       if(this.even_cell_color)
         this.data_nodes[i].style.backgroundColor = this.even_cell_color;
       this.data_nodes[i].setAttribute("id", "even_row");
     }
     else
     {
       if(this.odd_cell_color)
         this.data_nodes[i].style.backgroundColor = this.odd_cell_color;
       this.data_nodes[i].setAttribute("id", "odd_row");
     }
   }
 }

} /**

* This function will create the Data Nodes, which are a reference to the table
* rows in the HTML.
*/

nrsTable.prototype.createDataNodes = function() {

 if(this.data_nodes)
   delete this.data_nodes;
 this.data_nodes = new Array();
 if(!this.data)
   return;
 for(var i = 0; i < this.data.length; i++)
 {
   var curr_row = document.createElement("TR");
   
   for(var j = 0; j < this.data[i].length; j++)
   {
     var curr_cell = document.createElement("TD");
     //do we need to create links on every cell?
     if(this.cell_links)
     {
       var fn = new Function("", this.cell_links[i][j]);
       curr_cell.onclick = fn;
       curr_cell.style.cursor = "pointer";
     }
     //workaround for IE
     curr_cell.setAttribute("className", "dataTD" + j);
     //assign the padding
     if(this.padding)
     {
       curr_cell.style.paddingLeft = this.padding + "px";
       curr_cell.style.paddingRight = this.padding + "px";
     }
     curr_cell.appendChild(document.createTextNode(this.data[i][j]));
     curr_row.appendChild(curr_cell);
   }
   //do we need to create links on every row?
   if(!this.cell_links && this.row_links)
   {
     var fn = new Function("", this.row_links[i]);
     curr_row.onclick = fn;
     curr_row.style.cursor = "pointer";
   }
   //sets the id for odd and even rows.
   if(i % 2 == 0)
   {
     curr_row.setAttribute("id", "even_row");
     if(this.even_cell_color)
       curr_row.style.backgroundColor = this.even_cell_color;
   }
   else
   {
     curr_row.setAttribute("id", "odd_row");
     if(this.odd_cell_color)
       curr_row.style.backgroundColor = this.odd_cell_color;
   }
   if(this.hover_color)
   {
     curr_row.onmouseover = new Function("", "this.style.backgroundColor="" + this.hover_color + "";");
     curr_row.onmouseout = new Function("", "this.style.backgroundColor=(this.id=="even_row")?"" + 
               this.even_cell_color + "":"" + this.odd_cell_color + "";");
   }
   this.data_nodes[i] = curr_row;
 }

} /**

* This function will update the nav page display.
*/

nrsTable.prototype.updateNav = function() {

 if(this.page_nav)
 {
   var p = 0;
   if(this.foot_headers)
     p++;
   var t = document.getElementById(this.my_table);
   var nav = t.tFoot.childNodes[p];
   if(nav)
   {
     var caption = t.tFoot.childNodes[p].childNodes[0].childNodes[2];
     caption.innerHTML = "Page " + (this.current_page + 1) + " of " + this.num_pages;
   }
   else
   {
     if(this.num_pages > 1)
     {
       this.insertNav();
       nav = t.tFoot.childNodes[p];
     }
   }
   if(nav)
   {
     if(this.current_page == 0)
       this.hideLeftArrows();
     else
       this.showLeftArrows();
     
     if(this.current_page + 1 == this.num_pages)
       this.hideRightArrows();
     else
       this.showRightArrows();
   }
 }

} /**

* This function will flip the sort arrow in place.  If a heading is used in the
* footer, then it will flip that one too.
*/

nrsTable.prototype.flipSortArrow = function() {

 this.field_asc = !this.field_asc;
 //flip the arrow on the heading.
 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 if(this.field_asc)
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
 else
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 //is there a heading in the footer?
 if(this.foot_headers)
 {
   //yes, so flip that arrow too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   if(this.field_asc)
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
   else
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 }

} /**

* This function will move the sorting arrow from the place specified in 
* this.field_to_sort to the passed parameter.  It will also set 
* this.field_to_sort to the new value.  It will also do it in the footers, 
* if they exists.
* \param field The new field to move it to.
*/

nrsTable.prototype.moveSortArrow = function(field) {

 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 var img = heading.removeChild(heading.getElementsByTagName("IMG")[0]);
 heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[field];
 heading.appendChild(img);
 //are there headers in the footers.
 if(this.foot_headers)
 {
   //yes, so switch them too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   var img = footer.removeChild(footer.getElementsByTagName("IMG")[0]);
   footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[field];
   footer.appendChild(img);
 }
 //finally, set the field to sort by.
 this.field_to_sort = field;

} /**

* This function completely destroys a table.  Should be used only when building
* a brand new table (ie, new headers).  Else you should use a function like
* buildNewData which only deletes the TBody section.
*/

nrsTable.prototype.emptyTable = function() {

 var t = document.getElementById(this.my_table);
 while(t.childNodes.length != 0)
   t.removeChild(t.childNodes[0]);

}; /**

* This function builds a brand new table from scratch.  This function should
* only be called when a brand new table (with headers, footers, etc) needs
* to be created.  NOT when refreshing data or changing data.
*/

nrsTable.prototype.buildTable = function() {

 //reset the sorting information.
 this.field_to_sort = 0;
 this.field_asc = true;
 
 //remove the nodes links.
 delete this.data_nodes;
 
 //do we have to calculate the number of pages?
 if(this.data && this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.current_page = 0;
 }
 
 //blank out the table.
 this.emptyTable();
 
 //this is the table that we will be using.
 var table = document.getElementById(this.my_table);
 
 //is there a caption?
 if(this.caption)
 {
   var caption = document.createElement("CAPTION");
   caption.setAttribute("align", "top");
   caption.appendChild(document.createTextNode(this.caption));
   table.appendChild(caption);
 }
 
 //do the heading first
 var table_header = document.createElement("THEAD");
 var table_heading = document.createElement("TR");
 //since this is a new table the first field is what"s being sorted.
 var curr_cell = document.createElement("TH");
 var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + 0 + ");");
 if(!this.disable_sorting || this.disable_sorting.indexOf(".0.") == -1)
   curr_cell.onclick = fn;
 if(this.header_color)
   curr_cell.style.backgroundColor = this.header_color;
 curr_cell.style.cursor = "pointer";
 var img = document.createElement("IMG");
 img.setAttribute("src", this.up_icon);
 img.setAttribute("border", "0");
 img.setAttribute("height", "8");
 img.setAttribute("width", "8");
 curr_cell.appendChild(document.createTextNode(this.heading[0]));
 curr_cell.appendChild(img);
 table_heading.appendChild(curr_cell);
 //now do the rest of the heading.
 for(var i = 1; i < this.heading.length; i++)
 {
   curr_cell = document.createElement("TH");
   var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + i + ");");
   if(!this.disable_sorting || this.disable_sorting.indexOf("." + i + ".") == -1)
     curr_cell.onclick = fn;
   if(this.header_color)
     curr_cell.style.backgroundColor = this.header_color;
   curr_cell.style.cursor = "pointer";
   //build the sorter
   curr_cell.appendChild(document.createTextNode(this.heading[i]));
   table_heading.appendChild(curr_cell);
 }
 table_header.appendChild(table_heading);
 
 //now the content
 var table_body = document.createElement("TBODY");
 this.createDataNodes();
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
   this.recolorRows();
 }
 //finally, the footer
 var table_footer = document.createElement("TFOOT");
 if(this.foot_headers)
 {
   table_footer.appendChild(table_heading.cloneNode(true));
 }
 
 if(this.page_nav && this.num_pages > 1)
 {
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table_footer.appendChild(nav);
 }
 
 if(this.footer_color)
 {
   for(var i = 0; i < table_footer.childNodes.length; i++)
     table_footer.childNodes[i].style.backgroundColor = this.footer_color;
 }
 
 //append the data
 table.appendChild(table_header);
 table.appendChild(table_body);
 table.appendChild(table_footer);
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
 }
 this.refreshTable();

}; /**

* This function will remove the elements in teh TBody section of the table and
* return an array of references of those elements.  This array can then be 
* sorted and re-inserted into the table.
* \return An array to references of the TBody contents.
*/

nrsTable.prototype.extractElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var nodes = new Array();
 var i = 0;
 while(tbody.childNodes.length > 0)
 {
   nodes[i] = tbody.removeChild(tbody.childNodes[0]);
   i++;
 }
 return nodes;

} /**

* This function will re-insert an array of elements into the TBody of a table.
* Note that the array elements are stored in the this.data_nodes reference.
*/

nrsTable.prototype.insertElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var start = 0;
 var num_elements = this.data_nodes.length;
 if(this.rows_per_page != -1)
 {
   start = this.current_page * this.rows_per_page;
   num_elements = (this.data_nodes.length - start) > this.rows_per_page?
             this.rows_per_page + start:
             this.data_nodes.length;
 }
 DEBUG("start is " + start + " and num_elements is " + num_elements);
 for(var i = start; i < num_elements; i++)
 {
   tbody.appendChild(this.data_nodes[i]);
 }

} /**

* This function will sort the table"s data by a specific field.  The field 
* parameter referes to which field index should be sorted.
* \param field The field index which to sort on.
*/

nrsTable.prototype.fieldSort = function(field) {

 if(this.field_to_sort == field)
 {
   //only need to reverse the array.
   if(this.data)
   {
     this.data.reverse();
     this.data_nodes.reverse();
   }
   //flip the arrow on the heading.
   this.flipSortArrow();
 }
 else
 {
   //In this case, we need to sort the array.  We"ll sort it last, first 
   //make sure that the arrow images are set correctly.
   this.moveSortArrow(field);
   //finally, set the field to sort by.
   this.field_to_sort = field;
   if(this.data)
   {
     //we"ll be using our implementation of quicksort
     if(this.natural_compare)
       this.natSort(0, this.data.length - 1);
     else
       this.quickSort(0, this.data.length - 1);
   }
 }
 //finally, we refresh the table.
 this.refreshTable();

}; /**

* This function will refresh the data in the table.  This function should be
* used whenever the nodes have changed, or when chanign pages.  Note that 
* this will NOT re-sort.
*/

nrsTable.prototype.refreshTable = function() {

 this.extractElements();
 this.recolorRows();
 this.insertElements();
 //finally, if there is a nav, upate it.
 this.updateNav();

} /**

* This function will advance a page.  If we are already at the last page, then 
* it will remain there.
*/

nrsTable.prototype.nextPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page + 1 != this.num_pages)
 {
   this.current_page++;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go back a page.  If we are already at the first page, then 
* it will remain there.
*/

nrsTable.prototype.prevPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page != 0)
 {
   this.current_page--;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go to the first page.
*/

nrsTable.prototype.firstPage = function() {

 if(this.current_page != 0)
 {
   this.current_page = 0;
   this.refreshTable();
 }

} /**

* This function will go to the last page.
*/

nrsTable.prototype.lastPage = function() {

 DEBUG("lastPage(), current_page: " + this.current_page + " and num_pages: " + this.num_pages);
 if(this.current_page != (this.num_pages - 1))
 {
   this.current_page = this.num_pages - 1;
   this.refreshTable();
 }

} /**

* This function will go to a specific page.  valid values are pages 1 to 
* however many number of pages there are.
* \param page The page number to go to.
*/

nrsTable.prototype.gotoPage = function(page) {

 page--;
 if(page >=0 && page < this.num_pages)
 {
   this.current_page = page;
   this.refreshTable();
 }

} /**

* This function can be used to change the number of entries per row displayed
* on the fly.
* \param entries The number of entries per page.
*/

nrsTable.prototype.changeNumRows = function(entries) {

 if(entries > 0)
 {
   this.rows_per_page = entries;
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.refreshTable();
 }

} /**

* This function will take in a new data array and , optionally, a new cell_link
* array OR a new row_link array.  Only one will be used, with the cell_link
* array taking precedence.  It will then re-build the table with the new data
* array.
* \param new_data This is the new data array.  This is required.
* \param cell_links This is the new cell links array, a 2D array for each cell.
* \param row_links This is the new row links array, a 1D array for each row.
*/

nrsTable.prototype.newData = function(new_data, cell_links, row_links) {

 //extract the elements from teh table to clear the table.
 this.extractElements();
 //now delete all the data related to this table.  I do this so that 
 //(hopefully) the memory will be freed.  This is realy needed for IE, whose
 //memory handling is almost non-existant
 delete this.data;
 delete this.data_nodes;
 delete this.cell_links;
 delete this.row_links
 //now re-assign.
 this.data = new_data;
 this.cell_links = cell_links;
 this.row_links = row_links;
 if(this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   if(this.num_pages <= 1 && this.page_nav)
     this.removeNav();
   else if(this.page_nav)
     this.insertNav();
   this.current_page = 0;
 }
 this.createDataNodes();
 if(this.field_to_sort != 0)
   this.moveSortArrow(0);
 if(!this.field_asc)
   this.flipSortArrow();
 this.insertElements();
 this.updateNav();

} /**

* This function will remove the NAV bar (if one exists) from the table.
*/

nrsTable.prototype.removeNav = function() {

 if(this.page_nav)
 {
   //in this case, remove the nav from the existing structure.
   var table = document.getElementById(this.my_table);
   var p = 0;
   if(this.foot_headers)
     p++;
   var nav = table.tFoot.childNodes[p];
   if(nav)
   {
     table.tFoot.removeChild(nav);
     delete nav;
   }
 }

} /**

* This function wil re-insert the nav into the table.
*/

nrsTable.prototype.insertNav = function() {

 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 if(this.page_nav && !table.tFoot.childNodes[p])
 {
   //this means there should be a nav and there isn"t one.
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table.tFoot.appendChild(nav);
 }

} /**

* This function will hide the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.hideLeftArrows = function() {

 if(!this.page_nav)
   return;
 var myTable = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = myTable.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "none";

} /**

* This function will show the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.showLeftArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "block";

} /**

* This function will hide the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.hideRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "none";

} /**

* This function will show the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.showRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "block";

} </script> </head> <body>

nrsTable Examples


<script language="JavaScript"> var header = new Array("First Name", "Last Name", "Income", "Date Hired"); var data = new Array( new Array ( "Joseph", "Smith", "$35,000", "2000"), new Array ( "Aaron", "Zelzet", "$45,000", "1997"), new Array ( "Michael", "Doe", "$55,000", "1965"), new Array ( "Cindy", "Perez", "$44,345", "2004"), new Array ( "Robert", "Williams", "$48,234", "1990"), new Array ( "William", "Cohen", "$12,234", "2005"), new Array ( "David", "Gross", "$34,563", "1998"), new Array ( "Linda", "Mendez", "$46,975", "1988"), new Array ( "Karen", "Anderson", "$124,345", "1978"), new Array ( "Veronica", "O\"Reiley", "$89,034", "1968") ); var links = new Array( "alert("Row1");",

           "alert("Row2");",
           "alert("Row3");",
           "alert("Row4");",
           "alert("Row5");",
           "alert("Row6");",
           "alert("Row7");",
           "alert("Row8");",
           "alert("Row9");",
           "alert("Row10");"
         );

nrsTable.setup( { table_name: "example1", table_header: header, table_data: data, up_icon: "nrstableimg/up.gif", down_icon: "nrstableimg/down.gif" } ); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/nrsTable-0.3.3.zip">nrsTable-0.3.3.zip( 31 k)</a>


Sortable Tables from Scratch with MochiKit

<A href="http://www.wbex.ru/Code/JavaScriptDownload/MochiKit-1.3.1.zip">MochiKit-1.3.1.zip( 302 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Sorting for each column or double click to edit its contents.

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3Grid - Grid for Web Sites</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid - Grid for Web Sites

Current version: 0.5 - release date: Jun, 6 2005

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

OS3Grid example

   try sorting reasons for 
   each column or to double click on a cell edit its contents.
     <script type="text/javascript">
       function val_changed ( grid, x, y, new_val )
       {
         alert ( "On grid: " + grid.id + " x: " + x + " y: " + y + " - value changed to: " + new_val );
       }
       function bold_render ( txt )
       {
         return "" + txt + "<\/span>";
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "feat.no", "Name", "Descr", "Importance" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( 1, "Layout", "OS3Grid looks like a standard spreadsheet grid", 10 );
       g.add_row ( 2, "Row Colors", "You can change the colors of every singular row in the grid", 5 );
       g.add_row ( 3, "Sorting", "Rows can be sorted ascending or descending by clicking on column names", 15 );
       g.add_row ( 4, "Highlight", "Rows can be highlighted by onmouseover<\/em> events", 5 );
       g.add_row ( 5, "HTML Embedding", "Rows can contain any kind of HTML in it", 5 );
       g.add_row ( 6, "Value Editing", "Users can edit cell contents on the fly", 20 );
       g.add_row ( 7, "Input filtering", "User input can be filtered for special chars only", 15 );
       g.add_row ( 8, "Input Validation", "User input can validated with functions", 15 );
       g.add_row ( 9, "Input callback", "A JS function can be called as a callback on user input", 10 );
       g.add_row ( 10, "Free (LGPL)", "OS3Grid is Free as in freedom<\/em> released under LGPL license.", 20 );
       g.add_row ( 11, "Column Resize", "Columns can be resized by positioning the mouse between to headers", 30 );
       g.add_row ( 12, "Column Renderers", "Column data can be manipulated before displaying it", 15 );
       // Enable sortable rows
       g.set_sortable ( true );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       g.set_col_align ( 0, "center" );
       g.set_col_align ( 3, "right" );
       g.set_col_editable ( 1, "txt" );
       g.set_col_editable ( 2, "txt" );
       g.set_col_editable ( 3, "txt" );
       g.set_col_render ( 1, bold_render );
       g.onchange = val_changed;
       g.set_col_valid_chars ( 3, "0123456789" );
       g.set_col_validation ( 3, check_integer );
       g.resize_cols = true;
       g.sort_on_edit = true;
       
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>
   </div>
 </div>

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


 </source>
   
  


super table

<A href="http://www.wbex.ru/Code/JavaScriptDownload/supertable.zip">supertable.zip( 73 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Table Grid Column Renderers

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 8 - Column Renderers</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Example 8 - Column Renderers

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   Column Renderers. 
A column renderer allows you to define a custom visualization function to each column. In the next example, you"ll see how to:
  • Bold text inside a cell
  • Create a link based upon data contained in a cell
   To add a column renderer, you have to define it with the set_col_renderer()
   method before rendering the OS3Grid.
First of all, we"ll bold user nick name, creating this renderer:
      function bold_render ( txt ) 
      {
        return "<strong>" + txt + "<\/strong>"; 
      } 
      g.set_col_renderer ( 1, bold_render );
    
   Then, we have to create the render that will show up a link in the id column, this way:
      // Create link rendered
      function link_render ( id )
      {  
        return "<a href="#" + id + ">" + id + "</a>";
      }
      g.set_col_renderer ( 0, link_render );
    
   That"s all! The final result is shown below.
     <script type="text/javascript">
       function bold_render ( txt )
       {
         return "" + txt + "<\/span>";
       }
       function link_render ( id )
       {
         return "<a href="#">" + id + "<\/a>";
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "id", "nick", "Name", "Surname", "Age" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( 1, "fsoft", "Fabio", "Rotondo", 33 );
       g.add_row ( 2, "john", "John", "Bustone", 31 );
       g.add_row ( 3, "mkey", "Mark", "Key", 28 );
       g.add_row ( 4, "jdoe", "John", "Doe", 35 );
       // Enable sortable rows
       g.set_sortable ( true );
       g.set_col_type ( 0, "int" );
       g.set_col_type ( 4, "int" );
       g.set_col_render ( 0, link_render );
       g.set_col_render ( 1, bold_render );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       // Enable column resize
       g.resize_cols = true;
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>
   </div>
 </div>

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


 </source>
   
  


Table Grid Rows Selection

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>OS3 Grid Example 6 - Rows Selection</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Example 6 - Rows selection

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   select / deselect rows by simply 
   clicking on a row number:
        // Enable row selection
        g.set_row_select ( true );
    
   set a callback:
        function rowsel ( grid, row, selected )
        {
          alert ( "Row sel on grid: " + grid + " - row num: " + row + " - sel: " + selected );
        }
    
   and set the callback to the grid:
        g.onrowselect = rowsel;
    
     <script type="text/javascript">
       function rowsel ( grid, row, selected )
       {
         alert ( "Row sel on grid: " + grid + " - row num: " + row + " - sel: " + selected );
       }
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // Grid Headers are the grid column names
       g.set_headers ( "nick", "Name", "Surname", "Age" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows to the grid
       g.add_row ( "fsoft", "Fabio", "Rotondo", 33 );
       g.set_row_style ( "error" );
       g.add_row ( "john", "John", "Bustone", 31 );
       g.set_row_style ( "normal" );
       g.set_style ( "note" );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.set_style ( "normal" );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       g.add_row ( "mkey", "Mark", "Key", 28 );
       g.add_row ( "jdoe", "John", "Doe", 35 );
       // Enable sortable rows
       g.set_sortable ( true );
       g.set_col_type ( 3, "int" );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       g.set_col_editable ( 1, "txt" );
       g.set_col_editable ( 2, "txt" );
       g.set_col_editable ( 3, "txt" );
       g.set_row_select ( true );
       g.sort_on_edit = true;
       g.onrowselect = rowsel;
       g.start_counter = 1;
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Table Grid style and sort the style

   <source lang="html4strict">

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head>

 <title>Adv. Example: Setting and Using Styles</title>
 
 <style type="text/css" rel="stylesheet">

html, body {

 height: 100%;
 width:  100%;
 font-family: Arial, Verdana, sans-serif;
 color: #cccc99;
 font-size: 1em;
 /* overflow: auto; */
 margin-left: 0px;
 margin-top:  0px;
 margin-bottom: 0px;
 margin-right: 0px;

}

  1. block_top {
 margin: 5px;
 background-color: #d0d0d0;
 border: 1px solid #000;

}

  1. block_left {
 margin-left: 5px;
 left: 0px;
 background-color: #76808b;
 border: 1px solid #000;
 float: left;
 width: 15%;

}

  1. block_middle {
 margin-left: 18%;
 margin-right: 5%;
 padding: 5px;
 background-color: #959595;
 border: 1px solid #000;

} .block {

 margin: 5px;
 border: 1px solid #000;

} a {

 text-decoration: none;
 margin-left: 5px;
 }

a:hover {

   text-decoration: underline overline ;
   
 }
 

h1,h2,h3,h4,h5,h6.center { text-align: center; }

body {

 color: #000000;
 background: #666666;

} /* Menu */ .menu_title {

 margin:  4px;
 padding: 5px;
 border: 1px solid #000;
 background-color: #454545;
 color: white;
 font-weight: bold;

} /* Description Menu */ .descr_menu { border: 1px solid black; background-color: #353535; } .descr_menu th { width:150px; background:#8080ff; } .descr_menu th a { text-decoration:none; color:#000000; } .descr_menu td {

     font-weight: bold; 
     background:  #add8e6; 
     padding: 5px;
   }

/* Form 1 */ .form1 {

   border: 1px solid black; 
   padding: 5px;
   margin: 5px;
   background-color: #a5a5cc;
   display: none;
 }

.field_descr {

     text-align: right;
     font-weight: bold;
     margin-right: 5px;
   }

.code {

   padding: 5px;
   margin: 5px;
   font-family: courier;
   background: #ccccff;
   white-space: pre;
 }

.result {

   padding: 3px;
   margin: 2px;
   background: #eee;
 }

.note {

   padding: 5px;
   margin: 2px;
   background: #ffaaaa;
   border: solid;
   border-width: 1px;
 }
 
 </style>
 
 <style type="text/css" rel="stylesheet">

.g_table {

   margin: 0;
   padding: 0;
   border: 0;
   border-collapse: separate;
   border-spacing: 0px;
  }

.g_header {

   border: 2px solid;
   border-color: #fff #333 #333 #fff;
   background-color: #eeeeee; 
   padding-right: 9px;
   padding-left: 9px;
   padding-bottom: 2px;
   cursor: pointer; 
   text-align: center;
   color: black; 
   font-size: 12px;
      }

.g_resize {

   cursor: e-resize;
 }

.g_header_down {

     border: solid;
     border-color: #333 #555 #555 #333;
     border-width: 2px;
     background-color: #eeeeee; 
     padding-top: 2px;
     padding-left: 10px;
     padding-right: 8px;
     text-align: center;
     color: black; 
     cursor: pointer;
     font-size: 12px;
     }

.g_cell {

   border: solid;
   border-width: 1px 1px 1px 1px;
   border-color: #ccc;
   padding: 4px;
   font-size: 10px;
 }

.g_cell_hl {

     border: dashed;
     border-width: 1px;
     border-color: #f00;
     background-color: #ddd;
    }

.g_edit_box {

     border: solid;
     border-width: 1px;
     border-color: #999;
     padding: 3px;
     background: white;
     }
 
 </style>
 
 
 <script type="text/javascript">

/*

 OS3Grid v0.5
 by Fabio Rotondo - fsoft ( at ) sourceforge.net
 0.5:   - ATTR: start_counter
   - resize_cols
   - set_col_render ()
  • /

// =================================================================== // GLOBAL STUFF - Init global data class // =================================================================== function os3_grid_global_data () {

 this.grid_arr = new Array ();
 this.sort_field = 0;
 this.sort_inverted = 0;

} var _os3_grid_global_data = new os3_grid_global_data (); var _os3g_resize_cell; var _os3g_resize_start_x = -1; // Flag T/F to know if the current browser is the almighty bugged Internet Exploder. var _os3g_is_ie = ( document.all != null ); // =================================================================== // Grid Resize Functions // =================================================================== function grid_resize_cell_down ( id ) {

 _os3g_resize_cell = document.getElementById ( id );
 document.onmousemove = grid_resize_callback;
 if ( ! _os3g_is_ie ) 
 {
   document.captureEvents(Event.MOUSEMOVE);
 } else {
   while ( ! _os3g_resize_cell )
   {
     _os3g_resize_cell = document.getElementById ( id );
     if ( confirm ( "The buggy Internet Explorer cannot get the ID: " + id + ". Try again?\nBTW: You should really consider to switch to Mozilla Firefox (www.getfirefox.ru)" ) == false ) break;
   }
 }

} function grid_resize_cell_up () {

 if ( ! _os3g_resize_cell ) return;
 document.onmousemove = null;
 // later
 if ( ! _os3g_is_ie )
 {
   document.releaseEvents(Event.MOUSEMOVE);
 }
 if ( _os3g_resize_cell.old_className ) _os3g_resize_cell.className = _os3g_resize_cell.old_className;
 _os3g_resize_start_x = -1;
 // Save the new column width inside _column_width array;
 var res = _os3g_resize_cell.id.split ( "_th" );
 var name = res [ 0 ];
 var num  = res [ 1 ];
 var grid = _os3_grid_global_data.grid_arr [ name ];
 grid._column_width [ num ] = _os3g_resize_cell.width;
 _os3g_resize_cell = null;

} function grid_resize_callback ( e ) {

 var cur_x, cur_y;
 if ( ( ! _os3g_is_ie ) && ( e.pageX ) )
   cur_x = e.pageX;
 else 
   cur_x = event.x;
 if ( _os3g_resize_start_x == -1 ) 
 {
   _os3g_resize_start_x = 1;
   _os3g_resize_start_x = cur_x - _os3g_resize_cell.offsetWidth;
 }
 if ( cur_x <= _os3g_resize_start_x ) cur_x = _os3g_resize_start_x +1;
 _os3g_resize_cell.width = ( cur_x - _os3g_resize_start_x );

} // =================================================================== // Grid Edit Functions // =================================================================== function grid_edit_abort_or_blur ( input, cell_id, evt ) {

       evt = (evt) ? evt : event;
 var ccode = ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
       var ch = String.fromCharCode ( ccode );
 // User confirmed input by pressing "enter key"
 if ( ccode == 13 ) return input.blur ();
 // User aborted input
 if ( ccode == 27 )
 {
   var v = cell_id.split ( ":" );
   var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
   input.value = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
   input.blur ();
 }
 return true;

} function grid_edit_end ( input, cell_id ) {

 var v = cell_id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var oldv = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 if ( oldv != input.value )
 {
   if ( grid._column_validator [ v [ 1 ] ] )
     if ( grid._column_validator [ v [ 1 ] ] ( input.value ) == false )
     {
       alert ( "Invalid input: " + input.value );
       return input.focus ();
     }
   grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] = input.value;
   if ( grid.onchange ) grid.onchange ( grid, v [ 1 ], v [ 2 ], input.value );
   if ( grid.sort_on_edit ) grid.sort ();
 }
 return grid.render ();

} function grid_cell_txt_edit ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 var s, el, size;
 var type = grid._column_type [ v [ 2 ] ];
 if ( ! type ) type = "str";
 val = String ( grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ] );
 s  = "<input type="text" id="grid_edit_cell" value="" + val + "" ";
 s += " onblur="grid_edit_end ( this, \"" + cell.id + "\" )" ";
 s += " onfocus="this.select()" ";
 if ( grid._column_chars [ v [ 1 ] ] ) 
   s += "onkeypress="return grid_edit_filter_chars ( event, \"" + grid._column_chars [ v [ 1 ] ] + "\" )" ";
 s += " onkeydown="grid_edit_abort_or_blur(this, \"" + cell.id + "\", event)" ";
 s += " size=""+ val.length + "" ";
 s += " class="g_edit_box" ";
 if ( type == "int" ) s += " style="text-align: right;" ";
 s += "/>";
 cell.innerHTML = s;
 el = document.getElementById ( "grid_edit_cell" );
 el.focus ();

} function grid_edit_filter_chars ( evt, valids ) {

       evt = (evt) ? evt : event;
       if ( evt.charCode < 32 ) return true;
                                                                                                                                                  
       var ccode = ( evt.charcode ) ? evt.charcode : ( ( evt.which ) ? evt.which : evt.keycode );
       var ch = String.fromCharCode ( ccode ).toLowerCase ();
 valids = valids.toLowerCase ();
       if ( valids.indexOf ( ch ) == -1 ) return false;
       return true;

}

function grid_header_mdown ( header ) {

 if ( header.className == "g_header_down" ) return;
 header.old_className = header.className;
 header.className = "g_header_down";
 

} function grid_header_mup ( header ) {

 if ( header.old_className ) header.className = header.old_className;

} function grid_header_click ( header ) {

 var name, num, res, grid;
 
 res = header.id.split ( "_gh" );
 name = res [ 0 ];
 num  = res [ 1 ];
 grid = _os3_grid_global_data.grid_arr [ name ];
 grid.set_sort_field ( num );
 grid.sort ()

} function grid_row_over ( row ) {

 var old_col = row.style.backgroundColor;
 var hover_col = _os3_grid_global_data.grid_arr [ row.firstChild.id.split ( ":" ) [ 0 ] ].cols [ "hover" ];
 if ( _os3g_resize_cell ) grid_resize_cell_up ();
 if ( ( row.selected ) || ( old_col == hover_col ) ) return;
 row.old_color = old_col;
 row.style.backgroundColor = hover_col;

} function grid_row_out ( row ) {

 if ( ! row.selected ) row.style.backgroundColor = row.old_color;

} function grid_cell_click ( cell ) {

 var v = cell.id.split ( ":" );
 var grid = _os3_grid_global_data.grid_arr [ v [ 0 ] ];
 var val;
 val = grid.rows [ v [ 2 ] ] [ "data" ] [ v [ 1 ] ];
 sel = grid._cell_click ( grid, cell, v [ 2 ], v [ 1 ], val );
 
 if ( sel )
 {
   cell.old_border = cell.style.borderColor;
   cell.style.borderColor = grid.cols [ "rowsel" + ( v [ 2 ] % 2 ) ];
 } else
   cell.style.borderColor = cell.old_border;
 cell.selected = sel;

} // =================================================================== // Row selection function // =================================================================== function grid_row_click ( cell, grid_id, row_num ) {

 var grid = _os3_grid_global_data.grid_arr [ grid_id ];
 var row = cell.parentNode;
 if ( row.selected )
 {
   row.selected = false;
   grid_row_out ( row );
 } else {
   row.selected = true;
   row.style.backgroundColor = grid.cols [ "rowsel" + ( row_num % 2 ) ];
 }
 grid.rows_selected [ row_num ] = row.selected;
 if ( grid.onrowselect ) grid.onrowselect ( grid, row_num, row.selected );

} // =================================================================== // Internal Functions // =================================================================== function os3_grid_int_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = parseInt ( a [ "data" ][ _os3_grid_global_data.sort_field ] );
 v2 = parseInt ( b [ "data" ][ _os3_grid_global_data.sort_field ] );
 if  ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function os3_grid_str_sort ( a, b ) {

 var res = 0;
 var v1, v2;
 v1 = a [ "data" ][ _os3_grid_global_data.sort_field ];
 v2 = b [ "data" ][ _os3_grid_global_data.sort_field ];
 if ( v1 < v2 ) res = -1;
 else if ( v1 > v2 ) res = 1;
 if ( _os3_grid_global_data.sort_inverted ) res *= -1;
 return res;

} function _os3g_set_headers () {

 this.headers = arguments;

} function _os3g_set_sort_field ( num ) {

 if ( num == this.sort_field ) 
   this.sort_inverted = ! this.sort_inverted;
 else
 {
   this.sort_field = num;
   this.sort_inverted = false;
 }

} function _os3g_set_cell_click ( fname ) {

 this._cell_click = fname;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_size ( w, h ) {

 this._width = w;
 this._height = h;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_scrollbars ( sbars ) {

 this._scrollbars = sbars;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_border ( bsize, style, color ) {

 this._border = bsize;
 if ( style ) this._border_style = style;
 if ( color ) this._border_color = color;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_sortable ( sortable ) {

 this._sortable = sortable ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_highlight ( hl ) {

 this._row_hl = hl ;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_sort () {

 if ( this.sort_field == -1 ) return;
 var ctype = this._column_type [ this.sort_field ];
 var sfunc;
 if ( ! ctype ) ctype = "str";
 sfunc = { "str" : os3_grid_str_sort,
       "int" : os3_grid_int_sort,
       "date": os3_grid_str_sort } [ ctype ];
 _os3_grid_global_data.sort_field = this.sort_field;
 _os3_grid_global_data.sort_inverted = this.sort_inverted;
 this.rows.sort ( sfunc );
 this.render ( this.id );

} function _os3g_add_row () {

 var arr;
 arr = { "data" : arguments, "style" : this.current_style };
 this.rows.push ( arr );

} function _os3g_get_str () {

 var t, len;
var s = ""; var id, td_id; // Row selections are discarted on rendering this.rows_selected = new Array (); if ( this.headers ) { s += ""; if ( this._show_row_num ) s+= "";
   len = this.headers.length;
   for ( t = 0; t < len; t ++ )
   {
   
     td_id = this.id + "_th" + t;
     id = this.id + "_gh" + t;
s += "";
     if ( this.resize_cols )
s += "";
   }
s += ""; } var r, i, rlen, bgc, align, hl, style, rowcol, fullrow, v; len = this.rows.length; rlen = this.rows[0]["data"].length; // All rows must be equal size for ( t = 0; t < len; t ++ ) { fullrow = this.rows [ t ]; r = fullrow [ "data" ]; style = fullrow [ "style" ]; rowcol = fullrow [ "color" ]; if ( rowcol ) bgc = " bgcolor="" + rowcol + """; else bgc = " bgcolor="" + this.cols [ style + ( t % 2 ) ] + """; if ( this._row_hl ) hl = " onmouseover="grid_row_over(this)" onmouseout="grid_row_out(this)" "; else hl = ""; s += ""; if ( this._show_row_num ) { s+= "";
   }
   for ( i = 0; i < rlen; i ++ )
   {
     if ( this._column_align [ i ] )
       align = "align="" + this._column_align [ i ] + """;
     else if ( ( this._column_type [ i ] ) && ( this._column_type [ i ] != "str" ) )
       align = "align="right"";
     else
       align = "";
     
s += ""; } s += ""; } s += "
&nbsp
"+ this.headers [ t ] + "
" + ( this.start_counter + t ) + "";
     if ( this._column_render [ i ] )
       v = this._column_render [ i ] ( r [ i ] );
     else
       v = r [ i ];
     s += v;
s += "
";
 return s;

} function _os3g_render ( objId ) {

 if ( objId == undefined ) objId = this.id;
 this.id = objId;
 var obj = document.getElementById ( objId );
 obj.innerHTML = this.get_str ();
 if ( this._scrollbars )
   obj.style.overflow = "auto";
 else
   obj.style.overflow = "visible";  // was "none"
 if ( this._width )  obj.style.width = this._width;
 if ( this._height ) obj.style.height = this._height;
 if ( this._border ) 
 {
   if ( this._border_style ) obj.style.border = this._border_style;
   if ( this._border_color ) obj.style.borderColor = this._border_color;
   obj.style.borderWidth = this._border + "px";
 }
 
 // Bind element to the os3_grid_array
 _os3_grid_global_data.grid_arr [ objId ] = this;
 if ( this.onrender ) this.onrender ( this );

} function _os3g_set_row_color ( col, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 this.rows [ row_num ] [ "color" ] = col;

} function _os3g_set_row_style ( style, row_num ) {

 if ( ( row_num == undefined ) || ( row_num == -1 )  ) row_num = this.rows.length -1;
 
 this.rows [ row_num ] [ "style" ] = style;

} function _os3g_set_col_align ( col, align ) {

 this._column_align [ col ] = align;

} function _os3g_set_col_editable ( col, edit ) {

 this._column_edit [ col ] = edit;

}

function _os3g_get_value ( x, y ) {

 return this.rows [ y ] [ x ];

} function _os3g_set_col_valid_chars ( col, chars ) {

 this._column_chars [ col ] = chars;

} function _os3g_set_col_validation ( col, func ) {

 this._column_validator [ col ] = func;

} function _os3g_set_row_select ( rsel ) {

 this._row_sel = rsel;
 if ( this._row_sel ) this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_show_row_num ( show ) {

 this._show_row_num = true;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_col_type ( col, type ) {

 this._column_type [ col ] = type;

} function _os3g_set_col_render ( col, render ) {

 this._column_render [ col ] = render;

}

function _os3g_get_row ( row ) {

 return this.rows [ row ] [ "data" ];

} function _os3g_set_click_cb ( col, callback ) {

 this._click_cb [ col ] = callback;
 if ( this.id && this.autorender ) this.render ();

} function _os3g_set_style ( style ) {

 this.current_style = style;
 if ( this.id && this.autorender ) this.render ();

}

function OS3Grid ( auto_render ) {

 // ===========================================
 // Public attribs
 // ===========================================
 this.id = 0;
 this.start_counter = 0;
 // ===========================================
 // PUBLIC FLAGS
 // ===========================================
 // Flag T/F. If True, any modification (done with set_* funcs) will immediately renderd on grid
 this.autorender = auto_render;  
 // Flag T/F. If True, grid will be re-sorted on value changes
 this.sort_on_edit = false;
 // ===========================================
 // PUBLIC CALLBACKS
 // ===========================================
 // Function to be called when data in grid changes
 this.onchange = false;
 // Function to be called after the grid redraws
 this.onrender = false;
 // Callback to be called when the user selects / deselects a row
 this.onrowselect = false;
 // Flag T/F. If True, user can resize column at runtime
 this.resize_cols = false;
 
 // ===========================================
 // PUBLIC ATTRIBUTES
 // ===========================================
 // Array rows_selected
 this.rows_selected = false;  // This array keeps track of selected rows
 // Colors
 this.cols = { "hover"   : "#8ec4cf",
        "rowsel0"  : "#ffa07f",
        "rowsel1"  : "#df8c6f",
        "normal0"  : "#ffffff",
        "normal1"  : "#dfdfdf",
        "error0"  : "#ff0033",
        "error1"  : "#cc0033",
        "warn0"  : "#ffff99",
        "warn1"  : "#ffff66",
        "note0"  : "#9aff9a",
        "note1"  : "#4eee94"
       };
 // Default style
 this.current_style = "normal";
 // =============================================================================================
 // Private Stuff - Do not directly modify these values!
 // =============================================================================================
 this.headers = 0;
 this.rows = new Array ();
 this.sort_field = -1;
 this.sort_inverted = false;
   
 this._row_style = new Array ();
 this._column_align = new Array ();
 this._column_edit  = new Array ();
 this._column_chars  = new Array ();
 this._column_validator = new Array ();
 this._column_width = new Array ();
 this._column_render = new Array ();
 // This array stores the custom click callbacks
 this._click_cb = new Array ();
 
 // This array contains the column type. By default it is "str"
 // Valid values are: "str", "int", "date"
 this._column_type = new Array ();
 // Flag T/F. If True, the grid is sortable (by clicking on the headers)
 this._sortable = false;
 // Flag T/F. If True, scrollbars are used.
 this._scrollbars = false;
 // Force grid container width
 this._width = 0;
 // Force grid container height
 this._height = 0;
 // Grid container border size (in pixels)
 this._border = 0;
 // Grid container border style (solid, dashed, dotted...)
 this._border_style = 0;
 // Grid container block color
 this._border_color = 0;
 // Function callback for every cell click
 this._cell_click = 0;
 // Function callback for every row click
 this._row_click = 0;
 // Flag T/F. If True rows will be highlighted when the mouse scrolls over them.
 this._row_hl = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._show_row_num = false;
 // Flag T/F. If True rows number are shown and rows are selectable by clicking on them.
 this._row_sel = false;
 // Public methods
 this.add_row     = _os3g_add_row;
 this.get_row     = _os3g_get_row;
 this.get_str     = _os3g_get_str;
 this.getv    = _os3g_get_value;
 this.render     = _os3g_render;
 this.set_border   = _os3g_set_border;
 this.set_cell_click   = _os3g_set_cell_click;
 this.set_click_cb  = _os3g_set_click_cb;
 this.set_col_align  = _os3g_set_col_align;
 this.set_col_editable  = _os3g_set_col_editable;
 this.set_col_render  = _os3g_set_col_render;
 this.set_col_type  = _os3g_set_col_type;
 this.set_col_valid_chars = _os3g_set_col_valid_chars;
 this.set_col_validation = _os3g_set_col_validation;
 this.set_headers      = _os3g_set_headers;
 this.set_highlight  = _os3g_set_highlight;
 this.set_row_color  = _os3g_set_row_color;
 this.set_row_select  = _os3g_set_row_select;
 this.set_row_style  = _os3g_set_row_style;
 this.set_scrollbars   = _os3g_set_scrollbars;
 this.set_size     = _os3g_set_size;
 this.set_sort_field   = _os3g_set_sort_field;
 this.set_sortable  = _os3g_set_sortable;
 this.set_style    = _os3g_set_style;
 this.show_row_num  = _os3g_show_row_num;
 this.sort     = _os3g_sort;

}

 </script>
 
 
 <script type="text/javascript">

function check_integer ( n ) { return RegExp ( "^[-+]?[0-9]+$" ).test( n ); } function check_string ( s ) { return RegExp ( "^[a-zA-Z]+$" ).test( s ); } function check_alfanum_string ( s ) { return RegExp ( "^[a-zA-Z0-9]+$" ).test( s ); } function check_date ( s ) { return RegExp ( "^[0-9]{4,4}.[0-9]{2,2}.[0-9]{2,2}$" ).test( s ); } function check_time ( s ) { return RegExp ( "^[012][0-9]:[0-5][0-9]$" ).test( s ); } function check_email ( s ) { return RegExp ( "^[a-zA-Z0-9-_.]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" ).test( s ); } function check_float ( n ) {

 if (n.length == 0) return false;
 var first_char = n.charAt(0);
 if (first_char != "-" && first_char != "." &&
     (first_char < "0" || first_char > "9")) return false;
 var dot = false;
 var digit_expected = false;
 if (first_char == ".") {
   dot = true;
   digit_expected = true;
 } else if (first_char == "-")
   digit_expected = true;
 if (digit_expected && n.length < 2) return false;
 for (var count = 1; count < n.length; count++) {
   var c = n.charAt(count);
   if (c == ".") {
     if (dot) return false;
     dot = true;
   } else if (c < "0" || c > "9")
     return false;
 }
 return true;

}

 </script>

</head> <body>

OS3Grid Advanced Example: Setting and Using Styles

By Fabio Rotondo - fsoft (@) sourceforge ( dot ) net

   define and use styles, a graphical
   layout of rows that can be defined by the code. Each row in the table can have its own style and
   settings are saved even when the user sorts grid rows.
Styles are a better solution than set_row_color(), because the latter requires a row number to be set, while styles are dynamically linked to rows.
By default, OS3Grid provide these styles:
  • normal
    This is the normal style used to display a row. In OS3Grid, this usually equals to grey rows.
  • note
    This style should be used to highlight rows of special importance.
  • warn
    This style should be used for rows containing data that should be highlighted in a special way to the user.
  • error
    If you are using OS3Grid to display a report and there are errors (for example in a log file), use this style to show errors.
   These style are predefined, but this does not limit you with these: you can define your own.
   To define a new style, follow the example below, in which we are setting a new style yellow.
       // To set the new style, you have to define "stylename" + 0 and "stylename" + 1
       g.cols [ "yellow0" ] = "#f0dc04";
       g.cols [ "yellow1" ] = "#fcfc68";
   To use a defined (or pre-defined) style inside your grid, you have two choices:
  • g.set_style ( style_name )
    From this line of code, all rows added will use the defined style.
  • g.set_row_style ( style, [ row_num ] )
    You can change the style of a specific row, if [row_num] is omitted, the last row inserted will be affected by this call.
     <script type="text/javascript">
       // Create an OS3Grid instance
       var g = new OS3Grid ();
       // To set the new style, you have to define "stylename" + 0 and "stylename" + 1
       g.cols [ "yellow0" ] = "#f0dc04";
       g.cols [ "yellow1" ] = "#fcfc68";
       g.set_size ( "300px", "200px" );
       
       // Grid Headers are the grid column names
       g.set_headers ( "style", "descr" );
       // If contents is bigger than container, Grid will automatically show scrollbars
       g.set_scrollbars ( true );
       // The grid will have a solid border (these are CSS attributes)
       g.set_border ( 1, "solid", "#cccccc" );
       // Now, we add some rows with styles
       g.set_style ( "yellow" );
       g.add_row ( "yellow - 1", "this is the first yellow line" );
       g.add_row ( "yellow - 2", "this is the second yellow line" );
       g.add_row ( "yellow - 3", "this is the third yellow line" );
       g.add_row ( "yellow - 4", "this is the fourth yellow line" );
       g.set_style ( "normal" );
       g.add_row ( "normal - 1", "this is the first normal line" );
       g.add_row ( "normal - 2", "this is the second normal line" );
       g.add_row ( "normal - 3", "this is the third normal line" );
       g.add_row ( "normal - 4", "this is the fourth normal line" );
       g.set_style ( "note" );
       g.add_row ( "note - 1", "this is the first note line" );
       g.add_row ( "note - 2", "this is the second note line" );
       g.add_row ( "note - 3", "this is the third note line" );
       g.add_row ( "note - 4", "this is the fourth note line" );
       g.set_style ( "warn" );
       g.add_row ( "warn - 1", "this is the first warn line" );
       g.add_row ( "warn - 2", "this is the second warn line" );
       g.add_row ( "warn - 3", "this is the third warn line" );
       g.add_row ( "warn - 4", "this is the fourth warn line" );
       g.set_style ( "error" );
       g.add_row ( "error - 1", "this is the first error line" );
       g.add_row ( "error - 2", "this is the second error line" );
       g.add_row ( "error - 3", "this is the third error line" );
       g.add_row ( "error - 4", "this is the fourth error line" );
       // Enable sortable rows
       g.set_sortable ( true );
       // Enable highlight of rows with the mouse
       g.set_highlight ( true );
       // Show the grid replacing the original HTML object with the "grid" ID.
       g.render ( "grid" );
     </script>

</body> </html>


 </source>
   
  


Table in JavaScript

   <source lang="html4strict">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN"> <html> <head>

<script language=JavaScript> /****

   JsTable v0.4.5 (20050725) written by AT Mulyana (atmulyana@yahoo.ru)
 This libary is to create DHTML widget of Table on web page which is
 editable, cell navigatable and its content is submittable to web server.
 The target browser for this widget are :
   - Netscape 7.1+ / Mozilla 1.4+ or other Gecko browser whose the same
     or the newer version of Gecko engine.
   - Internet Explorer 6+
   - Opera 7.5+
   I hope you get the best version so that this script can run correctly
 You should get the documentaion to see how to use this script
   
 Copyright (C) 2005 AT Mulyana (atmulyana@yahoo.ru)
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License or (at your option) any later version.
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Send the bug report to "atmulyana@yahoo.ru" (Tell the exact version of your browser and under which Operating System you run the script) Currently, this script is personal work of myself, not involving other people or company including the company where I work.

          • /

/****** Checks the browser family ******/ function JsTableCheckBrowser() {

 var navFamily = navigator.userAgent.toLowerCase();
 if (navFamily.indexOf("opera")!=-1) { 
   var ver = parseFloat( navFamily.substring(navFamily.indexOf("opera")+6,
     navFamily.length) );
   if (ver >= 7.5) navFamily = "Opera7";
   else navFamily = "";
 } else if (navFamily.indexOf("msie")!=-1) {
   var ver = parseFloat( navFamily.substring(navFamily.indexOf("msie")+5,
     navFamily.length) );
   if (ver >= 6.0) navFamily = "IE6";
   else navFamily = "";
 } else if (navFamily.indexOf("gecko")!=-1) {
   var ver = parseFloat( navFamily.substring(navFamily.indexOf("gecko")+6,
     navFamily.length) );
   if (ver >= 20030624) navFamily = "Gecko"; //Good Gecko; Netscape 7.1+/Mozilla 1.4+
   else navFamily = "";
 } else {
   navFamily = "";
 }
 
 return navFamily;

} var JsTableNavFamily = JsTableCheckBrowser();

/********** Adds additional useful methods to the standart objects **********/ String.prototype.strip = function() { //Removes leading and trailing white space(s)

  return this.toString().replace(/^\s+/,"").replace(/\s+$/,"");

}; String.prototype.isNumeric = function() { //Does the string evaluate to a numeric value?

 var re = /-?\s*\d*\.?\d+/;
 var val = this.toString();
 val = val.strip();
 var valid = true;
 var found = re.exec(val);
 if (!found) valid=false;
 else valid = (found[0].length==val.length);
 return valid;

}; //Can the string be used as variabel name? String.prototype.isQualifiedVarName = function() {

 var re = /[a-zA-Z_]\w*/;
 var val = this.toString();
 var valid = true;
 var found = re.exec(val);
 if (!found) valid=false;
 else valid = (found[0].length==val.length);
 return valid;

}; //Does the string evaluate to a date value? (format: "dd-mm-yyyy" or "mm-dd-yyyy") //If true then returns a normalized date value String.prototype.isDate = function(sFormat) {

 var sFormat = (sFormat+"").toLowerCase();
  //Only "d-m-y" or "m-d-y" is accepted (It implies the paramater may
  //be omitted ==> "d-m-y" will be used)
 if (sFormat!="m-d-y") sFormat = "d-m-y";
 var idxDay = 0;
 var idxMonth = 1;
 if (sFormat=="m-d-y") {
   idxDay = 1;
   idxMonth = 0;
 }
 
 var sDate = this.toString().strip();
 var bValid = true;
 var arMonthlong = [0,31,28,31,30,31,30,31,31,30,31,30,31];
 var regDate = /(\d{1,2}\s*-\s*\d{1,2}\s*-\s*\d{4,4})/;
 
 var ar = regDate.exec(sDate);
 if (ar) {
   bValid = (sDate.length==ar[0].length);
   if (!bValid) return false;
 } else
   return false;
 
 sDate = sDate.replace(/\s+/g,""); //Removes all white spaces
 var arDate = sDate.split("-");
 var iYear = parseInt(arDate[2],10);
 var iMonth = parseInt(arDate[idxMonth],10);
 var iDay = parseInt(arDate[idxDay],10);
 bValid = (iMonth > 0) && (iMonth <= 12);
 if (bValid) {
   bValid = (iDay > 0);
   if (iMonth==2) {
     if (iYear%4) bValid = bValid && (iDay <= 28);
     else bValid = bValid && (iDay <= 29);
   } else {
     bValid = bValid && (iDay <= arMonthlong[iMonth]);
   }
 }
 
 if (bValid) {
   if (iDay < 10) iDay = "0" + iDay;
   if (iMonth < 10) iMonth = "0" + iMonth;
   iYear = "0000".substring(0, 4 - (iYear+"").length) + iYear;
   if (sFormat=="m-d-y") return (iMonth+"-"+iDay+"-"+iYear);
   return (iDay+"-"+iMonth+"-"+iYear);
 }
 return bValid;

}; //Does the string evaluate to a date-time value? (format: "dd-mm-yyyy hh:nn:ss" //or "mm-dd-yyyy hh:nn:ss") //If true then returns a normalized date-time value String.prototype.isDateTime = function(sFormat) {

 var sDt = this.toString().strip();
 var re = /((\d{1,2}\s*-\s*\d{1,2}\s*-\s*\d\d\d\d)\s+(\d{1,2}\s*:\s*\d{1,2}:\s*\d{1,2}))/;
 var ar = sDt.match(re);
 var bValid = true;
 if (ar) {
   bValid = (sDt.length==ar[0].length);
   if (!bValid) return bValid;
 } else
   return false;
 
 //Checks the date part
 var sDate = ar[2].isDate(sFormat);
 if (!sDate) return false;
 
 //Checks the time part
 ar[3] = ar[3].replace(/\s+/g,""); //Removes all white spaces
 var arTime = ar[3].split(":");
 var iHour = parseInt(arTime[0],10);
 var iMinute = parseInt(arTime[1],10);
 var iSecond = parseInt(arTime[2],10);
 bValid = (iHour >= 0) && (iHour < 24);
 if (bValid) bValid = (iMinute >= 0) && (iMinute < 60);
 if (bValid) bValid = (iSecond >= 0) && (iSecond < 60);
 
 if (bValid) {
   if (iHour < 10) iHour = "0" + iHour;
   if (iMinute < 10) iMinute = "0" + iMinute;
   if (iSecond < 10) iSecond = "0" + iSecond;
   return (sDate+" "+iHour+":"+iMinute+":"+iSecond);
 }
 return bValid;

}; //Gives denomination to the string if it evaluates to a numeric value String.prototype.giveDenomination = function(denominator,fracDigits) {

 var pointDec;
 if (denominator!=".") { //Ignores denominator except "," and "."
   denominator = ",";
   var pointDec = ".";
 } else pointDec = ",";
 var sNumber = this.toString();
 if (!sNumber.isNumeric()) return sNumber;
 sNumber = sNumber.replace(/\s/g,"");
 var sSign = "";
 if (sNumber.charAt(0)=="-") {
   sSign = "-";
   sNumber = sNumber.substring(1,sNumber.length);
   if (parseFloat(sNumber)==0.0) sSign = "";
 }
 var sDec = "";
 var i = sNumber.indexOf(".");
 if (i!=-1) {
   sDec = sNumber.substring(i+1,sNumber.length); sDec = sDec.replace(/0+$/,"");
   sNumber = sNumber.substring(0,i);
   if (!sNumber) sNumber = "0";
 }
 if (fracDigits) {
   fracDigits = parseInt(fracDigits);
   fracDigits = (isNaN(fracDigits)? 0 : fracDigits);
   if (!sDec) sDec = "0";
   sDec = Math.round( parseFloat("0."+sDec)* Math.pow(10,fracDigits) ) + "";
   while (sDec.length < fracDigits) sDec = "0" + sDec;
   if (sDec.length > fracDigits) {
     i = parseInt(sDec.substring(0,1));
     sDec = sDec.substring(1,sDec.length);
     sNumber = (parseInt(sNumber)+i) + "";
   }
 }
 var arNum = new Array();
 while (sNumber.length > 3) {
   arNum[arNum.length] = sNumber.substring(sNumber.length-3,sNumber.length);
   sNumber = sNumber.substring(0,sNumber.length-3);
 }
 if (sNumber.length > 0) arNum[arNum.length] = sNumber;
 arNum.reverse();
 if (sDec) sDec = pointDec + sDec;
 return (sSign+arNum.join(denominator)+sDec);

}; //Gives denomination to the string if it evaluates to a numeric value String.prototype.removeDenomination = function(denominator,alterPointDecToPeriod,ignoreNumeric) {

 var pointDec = ",";
 if (denominator!=".") { //Ignores denominator except "," and "."
   denominator = ",";
   pointDec = ".";
 }
 var sNumber = this.toString();
 sNumber = sNumber.replace(new RegExp("\\"+denominator,"g"),"");
 var sNumber1 = sNumber.replace(new RegExp("\\"+pointDec,"g"),".");
 if (sNumber1.isNumeric() || ignoreNumeric) {
   if (alterPointDecToPeriod) return sNumber1;
   else return sNumber;
 }
 return this.toString();

}; //To search if the "elm" is inside the array; //The "elm" is not an object Array.prototype.isThere = function(elm) {

 var s = this.join("|~&*&~|");
 return (s.indexOf(elm+"")!=-1);

}; //Returns the date value with format "dd-mm-yyyy" Date.prototype.ddmmyyyy = function() {

 day = this.getDate();
 month = this.getMonth()+1;
 year = this.getFullYear();
 if (day<10) day="0"+day;
 if (month<10) month="0"+month;
 return (day+"-"+month+"-"+year);

}; //Returns the date value with format "mm-dd-yyyy" Date.prototype.mmddyyyy = function() {

 day = this.getDate();
 month = this.getMonth()+1;
 year = this.getFullYear();
 if (day<10) day="0"+day;
 if (month<10) month="0"+month;
 return (month+"-"+day+"-"+year);

}; //Returns the date value with format "yyyy-mm-dd" Date.prototype.sqldate = function() {

 day = this.getDate();
 month = this.getMonth()+1;
 year = this.getFullYear();
 if (day<10) day="0"+day;
 if (month<10) month="0"+month;
 if (year<10) year="0"+year;
 return (year+"-"+month+"-"+day);

}; //Returns the time-stamp with format according to parameter "format" //Possible values (incasesensitive) for parameter format: // "d-m-y" ==> "dd-mm-yyyy hh:nn:ss" // "m-d-y" ==> "mm-dd-yyyy hh:nn:ss" // "sql" ==> "yyyy-mm-dd hh:nn:ss" Date.prototype.timeStamp = function(format) {

 format = (format+"").toLowerCase();
  //Only "d-m-y" or "m-d-y" or "sql" is accepted (It implies the paramater may
  //be omitted ==> "d-m-y" will be used)
 if (format!="m-d-y" && format!="sql") format = "d-m-y";
 
 hour = this.getHours();
 minute = this.getMinutes();
 second = this.getSeconds();
 if (hour<10) hour="0"+hour;
 if (minute<10) minute="0"+minute;
 if (second<10) second="0"+second;
 if (format=="m-d-y") return (this.mmddyyyy()+" "+hour+":"+minute+":"+second);
 if (format=="sql") return (this.sqldate()+" "+hour+":"+minute+":"+second);
 return (this.ddmmyyyy()+" "+hour+":"+minute+":"+second);

}; //Changes the date value according to parameter "ddmmyyyy" //"ddmmyyyy" is the date value with format "dd-mm-yyyy" Date.prototype.setFrom_ddmmyyyy = function(ddmmyyyy) {

 ddmmyyyy = ddmmyyyy+"";
 ddmmyyyy = ddmmyyyy.isDate();
 if (!ddmmyyyy) return;
 var dates = ddmmyyyy.split("-");
 this.setFullYear( parseInt(dates[2],10), parseInt(dates[1],10)-1, parseInt(dates[0],10) );

} //Changes the date value according to parameter "mmddyyyy" //"mmddyyyy" is the date value with format "mm-dd-yyyy" Date.prototype.setFrom_mmddyyyy = function(mmddyyyy) {

 mmddyyyy = mmddyyyy+"";
 mmddyyyy = mmddyyyy.isDate("m-d-y");
 if (!mmddyyyy) return;
 var dates = mmddyyyy.split("-");
 this.setFullYear( parseInt(dates[2],10), parseInt(dates[0],10)-1, parseInt(dates[1],10) );

} //Changes the date value according to parameter "sqldate" //"sqldate" is the date value with format "yyyy-mm-dd" Date.prototype.setFrom_sqldate = function(sqldate) {

 sqldate = sqldate+"";
 var dates = sqldate.split("-"); //No Checking
 this.setFullYear( parseInt(dates[0],10), parseInt(dates[1],10)-1, parseInt(dates[2],10) );

}

if (JsTableNavFamily) { /************ The browser fulfils the requirement ***************/ function JsTableRemoveAllText(oParent) {

 var sText = "";
 var oChild, sNodeName;
 var idx = 0;
 while (idx < oParent.childNodes.length) {
   oChild = oParent.childNodes[idx];
   sNodeName = oChild.nodeName;
   if (sNodeName!="INPUT") oParent.removeChild(oChild);
   if (sNodeName=="#text") {
     sText += oChild.nodeValue;
   } else if (sNodeName=="BR") {
     sText += "\n";
   } else {
     idx++;
     continue;
   }
 }
 return sText;

} /********** All about column models to set the colums behavior in the JsTable *******/ var JsTableCellEditorSelect = null; function JsTableSetCellEditorSelect() {

 if (!JsTableCellEditorSelect) return;
 JsTableCellEditorSelect.select();
 JsTableCellEditorSelect.readOnly = false;
 JsTableCellEditorSelect = null;

} var JsTableColumnIndex = 0; function JsTableColumnClass(columnName,inputName,width,align) {

 this.columnName = columnName || String.fromCharCode(160);
 this.inputName = inputName || ("col"+JsTableColumnIndex);
 JsTableColumnIndex++;
 align = (align+"").toLowerCase();
 this.align = ( ("left|center|right".indexOf(align)!=-1)? align : "left");
 this.width = ( isNaN(parseInt(width))? 20 : parseInt(width) );
 
 this.getInputElm = function(oCell) {
   var arElms = oCell.getElementsByTagName("INPUT");
   for (var i=0; i<arElms.length; i++) {
     if (arElms[i].getAttribute("name") == this.inputName) return arElms[i];
   }
 };
 
 this.getCellEditor = function(oCell,oJsTable) {
   return null;
 };
 this.isValid = function(val,oJsTable) {
   return true;
 };
 this.fixedValue = function(val,oJsTable) {
   if (typeof val == "undefined") return "";
   return val.toString();
 };
 this.getValue = function(oCell,oJsTable) {
   return this.getInputElm(oCell).value;
 };
 this._getShownValue = function(val,oJsTable) {
   return val;
 };
 this.getShownValue = function(oCell,oJsTable) {
   return this._getShownValue(this.getInputElm(oCell).value,oJsTable);
 };
 this.getShownValueOnEdit = function(oCell,oJsTable) {
   return this.getShownValue(oCell,oJsTable);
 };
 this._setShownValue = function(val,oCell,oJsTable) {
   JsTableRemoveAllText(oCell);
   var arText = (val+"").split("\n");
   var oText, oBR;
   for (var i=0; i<arText.length; i++) {
     oText = document.createTextNode(arText[i]);
     oCell.appendChild(oText);
     if (i<arText.length-1) {
       oBR = document.createElement("BR");
       oCell.appendChild(oBR);
     }
   }
 };
 this.setValue = function(val,oCell,oJsTable,oCellEditor) {
   val = this.fixedValue(val,oJsTable);
   this.getInputElm(oCell).value = val;
   if (oCellEditor) oCellEditor.value = this.getShownValue(oCell,oJsTable);
   else this._setShownValue( this._getShownValue(val,oJsTable), oCell, oJsTable);
 };
 this._setCellEditorSelect = function(oCellEditor) {
   JsTableCellEditorSelect = oCellEditor;
   setTimeout("JsTableSetCellEditorSelect()",0);
 };
 this.setEditorOnEdit = function(oCellEditor,oCell,oJsTable) {
   var val = this.getShownValueOnEdit(oCell,oJsTable);
   oCellEditor.value = val;
   oCellEditor.readOnly = false;
   this._setCellEditorSelect(oCellEditor);
 };
 this.setEditorOnCommit = function(oCellEditor,oCell,oJsTable) {
   var val = oCellEditor.value;
   oCellEditor.readOnly = true;
   oCellEditor.select(); //IE6, to hide text cursor
   if (JsTableNavFamily=="IE6") oJsTable._onclickIE6 = [oJsTable.row, oJsTable.col];
   oCellEditor.value = ""; //clear highlight selected text if any
   if (!this.isValid(val,oJsTable)) {
     if (oJsTable.tableModel.oldValIfInvalid) val = this.getShownValue(oCell,oJsTable);
   }
   this.setValue(val,oCell,oJsTable,oCellEditor);
 };
 this.setEditorOnArrive = function(oCellEditor,oCell,oJsTable) {
   var sText = JsTableRemoveAllText(oCell);
   //var oSbl = (oCell.nextSibling ? oCell.nextSibling : oCell.previousSibling);
   if (JsTableNavFamily=="Opera7") {
     oCellEditor.style.height = (oCell.offsetHeight-2) + "px";
   } else if (document.rupatMode=="CSS1Compat") {
     oCellEditor.style.width = (oCell.offsetWidth-3) + "px";
     oCellEditor.style.height = (oCell.offsetHeight-4) + "px";
   } else {
     oCellEditor.style.width = oCell.offsetWidth + "px";
     oCellEditor.style.height = (oCell.offsetHeight-2) + "px";
   }
   oCell.style.padding = "0px";
   oCellEditor.value = sText;
   oCellEditor.style.textAlign = this.align;
   oCellEditor = oCell.appendChild(oCellEditor);
 };
 this.setEditorOnRearrive = function(oCellEditor,oCell,oJsTable) {
    //Invoked when the currently active cell is the same as before
 };
 this.setEditorOnLeave = function(oCellEditor,oCell,oJsTable) {
   oCell.removeChild(oCellEditor);
   oCell.style.padding = "";
   if (oCell.style.removeProperty) {
     oCell.style.removeProperty("padding");
     //oCell.style.removeProperty("height");
   } else {
     oCell.style.padding = "";
     //oCell.style.height = "";
   }
   this._setShownValue(this.getShownValue(oCell,oJsTable),oCell,oJsTable);
 };
 this.containsEditor = function(oCell,oCellEditor) {
   //It returns integer because some consideration (See method oJsTable.setFocus
   //and JsTableColumnBoolean.containsEditor)
   if (oCell.contains(oCellEditor)) return -1;
   return 0;
 };
 this.addCell = function(oRow,oJsTable,val,primaryKey) {
   val = this.fixedValue(val);
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oInput = document.createElement("INPUT");
   oInput.type = "hidden";
   oInput.setAttribute("name",this.inputName);
   oInput.setAttribute("id",this.inputName); //IE6
   oInput.value = val;
   oCell.appendChild(oInput);
   this._setShownValue( this._getShownValue(val,oJsTable), oCell,oJsTable);
   return oCell;
 };

} function JsTableColumnString(columnName,inputName,width,align) {

 this.base = JsTableColumnClass;
 this.base(columnName,inputName,width,align);
 
 this._addCell_ = this.addCell;
 this.addCell = function(oRow,oJsTable,val,primaryKey) {
   var oCell = this._addCell_(oRow,oJsTable,val,primaryKey);
   oCell.onkeypress = JsTableOnStringKeyPress;
   return oCell;
 }

} function JsTableColumnNumber(columnName,inputName,width,align,denomination,fracDigits) {

 this.base = JsTableColumnClass;
 align = align || "right";
 this.base(columnName,inputName,width,align);
 this.denomination = (denomination?true:false);
 this.fracDigits = parseInt(fracDigits); if (isNaN(fracDigits)) fracDigits = 0;
 
 this.isValid = function (val,oJsTable) {
   val = (val+"").removeDenomination(oJsTable.tableModel.numberDenominator,true);
   return val.isNumeric();
 };
 this.fixedValue = function (val,oJsTable) {
   var denominator = oJsTable.tableModel.numberDenominator;
   if (typeof val != "number") val = (val+"").removeDenomination(denominator,true,true);
   val = parseFloat(val+"");
   if (isNaN(val)) return 0;
   val = (val+"").giveDenomination(denominator,this.fracDigits);
   val = parseFloat(val.removeDenomination(denominator,true));
   return val;
 };
 this.getValue = function(oCell,oJsTable) {
   return parseFloat(this.getInputElm(oCell).value);
 };
 this._getShownValue = function(val,oJsTable) {
   val = val+"";
   var denominator = oJsTable.tableModel.numberDenominator;
   val = val.giveDenomination(denominator,this.fracDigits);
   if (this.denomination) return val;
   return val.replace(new RegExp("\\"+denominator,"g"),"");
 };
 this.getShownValueOnEdit = function(oCell,oJsTable) {
   var val = this.getInputElm(oCell).value;
   var denominator = oJsTable.tableModel.numberDenominator;
   var pointDec = ",";
   if (denominator==",") pointDec = ".";
   return val.replace(/\./,pointDec);
 };
 this.addCell = function(oRow,oJsTable,val,primaryKey) {
   val = this.fixedValue(val,oJsTable);
   var denominator = oJsTable.tableModel.numberDenominator;
   var shownVal = (val+"").giveDenomination(denominator,this.fracDigits);
   if (!this.denomination) shownVal = shownVal.removeDenomination(denominator,false,true);
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oInput = document.createElement("INPUT");
   oInput.type = "hidden";
   oInput.setAttribute("name",this.inputName);
   oInput.setAttribute("id",this.inputName); //IE6
   oInput.value = val;
   oCell.appendChild(oInput);
   oCell.appendChild(document.createTextNode(shownVal));
   oCell.style.whiteSpace = "nowrap";
   oCell.onkeypress = JsTableOnNumberKeyPress;
   return oCell;
 };

} function JsTableColumnBoolean(columnName,inputName,width,align) {

 this.base = JsTableColumnClass;
 align = align || "center";
 this.base(columnName,inputName,width,align);
 
 this.setPrimaryKey = function(oCell,primaryKey) {
   this.getInputElm(oCell).value = primaryKey+"";
 };
 this.getCellEditor = function(oCell,oJsTable) {
   return this.getInputElm(oCell);
 };
 this.isValid = function (val) {
   return true; //Always true as usual evaluation in JavaScript, all values of all types
         //can be evaluated as boolean
 };
 this.fixedValue = function (val) {
      if (val) return true;
   return false;
 };
 this.getValue = function(oCell,oJsTable) {
   return this.getInputElm(oCell).checked;
 };
 this.getShownValue = function(oCell,oJsTable) {
   return this.getInputElm(oCell).checked;
 };
 this._setShownValue = function(val,oCell,oJsTable) {
 };
 this.setValue = function(val,oCell,oJsTable,oCellEditor) {
   this.getInputElm(oCell).checked = this.fixedValue(val);
 };
 this.setEditorOnEdit = function(oCellEditor,oCell,oJsTable) {
   oCellEditor.checked = !oCellEditor.checked;
   oCell._checked = oCellEditor.checked;
   oJsTable.onEdit = false;
 };
 this.setEditorOnCommit = function(oCellEditor,oCell,oJsTable) {
 };
 this.setEditorOnArrive = function(oCellEditor,oCell,oJsTable) {
   oCell.className = "cell-focus";
   if (oCell._onclick) //oCellEditor.checked = !oCellEditor.checked;
     oJsTable.setOnEdit(); //Also checks if the cell is editable, at once
 };
 this.setEditorOnRearrive = function(oCellEditor,oCell,oJsTable) {
   this.setEditorOnArrive(oCellEditor,oCell,oJsTable);
 };
 this.setEditorOnLeave = function(oCellEditor,oCell,oJsTable) {
   oCell.className = "";
 };
 this.containsEditor = function(oCell,oCellEditor) {
   return 1;
 };
 this.addCell = function(oRow,oJsTable,bChecked,val) {
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oEditor = document.createElement("INPUT");
   oEditor.type = "checkbox";
   oEditor.className = "checkbox";
   oEditor.setAttribute("name",this.inputName);
   oEditor.setAttribute("id",this.inputName); //IE6
   oEditor.value = val+"";
   oEditor.checked = this.fixedValue(bChecked);
   oEditor.defaultChecked = oEditor.checked;
   oCell.appendChild(oEditor);
   oEditor.onblur = JsTableOnBlur;
   oEditor.onclick = JsTableOnCheckboxClick;
   oEditor.onkeydown = JsTableOnCheckboxKeyDown;
   oEditor.onkeypress = JsTableOnCheckboxKeyPress;
   return oCell;
 };

} //This constructor is used to create object for option values in //column whose type of JsTableColumnOptions function JsTableOptionValues(arValuesSent,arValuesShown) {

 if (!arValuesSent) arValuesSent = [];
 if (!arValuesShown) arValuesShown = [];
 for (var i=0; i<arValuesSent.length; i++) {
   if (typeof arValuesShown[i] == "undefined") arValuesShown[i] = arValuesSent[i];
   this[arValuesSent[i]] = arValuesShown[i];
 }

} function JsTableColumnOptions(columnName,inputName,width,align,options) {

 this.base = JsTableColumnClass;
 this.base(columnName,inputName,width,align);
 this.options = options || (new JsTableOptionValues());
 
 var o = document.createElement("SELECT");
 o.style.overflow = "hidden";
 o.style.margin = "0px";
 o.style.padding = "0px";
 o.style.borderStyle = "none";
 o.style.width = "100%";
 for (var optVal in this.options) {
   opt = document.createElement("OPTION");
   opt.style.margin = "0px";
   opt.appendChild(document.createTextNode(this.options[optVal]));
   opt.setAttribute("value",optVal);
   o.appendChild(opt);
   //o.add(opt,null);
 }
 this.cellEditor = o;
 this.cellEditor._selectedIndex = -1;
 this.cellEditor.onblur = JsTableOnBlur;
 //this.cellEditor.onkeydown = JsTableOnKeyDown;
 //this.cellEditor.onkeypress = JsTableOnKeyPress;
 this.cellEditor.onkeyup = function (e) {
   if (this._selectedIndex >= 0) {
     this.selectedIndex = this._selectedIndex;
     this._selectedIndex1 = this._selectedIndex;
     this._selectedIndex = -1;
   }
 }
 /*if (JsTableNavFamily=="Opera7") { //For Linux
   this.cellEditor.onkeypress = function (e) {
     if (this._selectedIndex < 0 || (typeof this._selectedIndex=="undefined")) {
       this._repeatedKeypress = true;;
     }
   }
   this.cellEditor.onchange = function (e) {
     if (this._repeatedKeypress) {
       this.selectedIndex = this._selectedIndex1;
       this._repeatedKeypress = false;
     }
   }
 }*/
 
 this.getCellEditor = function(oCell,oJsTable) {
   if ( oJsTable.tableModel.isCellEditable(oCell.parentNode.rowIndex,oCell.cellIndex) )
     return this.cellEditor;
   return oJsTable.cellEditor;
 };
 this.isValid = function (val) {
   return (typeof this.options[val] != "undefined");
 };
 this.fixedValue = function (val) {
      if (typeof val != "undefined")
     if (typeof this.options[val] != "undefined") return val;
   for (var optVal in this.options) return optVal;//the first option
 };
 this._getShownValue = function(val,oJsTable) {
   return this.options[val];
 };
 this.setEditorOnEdit = function(oCellEditor,oCell,oJsTable) {
 };
 this.setEditorOnCommit = function(oCellEditor,oCell,oJsTable) {
 };
 this.setEditorOnArrive = function(oCellEditor,oCell,oJsTable) {
   oCell.style.padding = "0px";
   JsTableRemoveAllText(oCell);
   var val = this.getValue(oCell,oJsTable);
   if (oCellEditor.options) { //Combo box
     for (var i=0; i<oCellEditor.length; i++)
       if (oCellEditor.options[i].value==val) break;
     oCellEditor = oCell.appendChild(oCellEditor);
     oCellEditor.selectedIndex = i;
     if (oCell._keydown) oCellEditor._selectedIndex = i;
   } else { //Text box
     if (JsTableNavFamily=="Opera7") {
       oCellEditor.style.height = (oCell.offsetHeight-2) + "px";
     } else if (document.rupatMode=="CSS1Compat") {
       oCellEditor.style.width = (oCell.offsetWidth-3) + "px";
       oCellEditor.style.height = (oCell.offsetHeight-4) + "px";
     } else {
       oCellEditor.style.width = oCell.offsetWidth + "px";
       oCellEditor.style.height = (oCell.offsetHeight-2) + "px";
     }
     oCellEditor.value = this._getShownValue(val,oJsTable);
     oCellEditor.style.textAlign = "left";
     oCell.appendChild(oCellEditor);
   }
 };
 this.setEditorOnRearrive = function(oCellEditor,oCell,oJsTable) {
   if (oCell._keydown) oCellEditor._selectedIndex = oCellEditor.selectedIndex;
 };
 this.setEditorOnLeave = function(oCellEditor,oCell,oJsTable) {
   if (oCell.style.removeProperty) {
     oCell.style.removeProperty("padding");
   } else {
     oCell.style.padding = "";
   }
   if (oCellEditor._selectedIndex >= 0) {
     oCellEditor.selectedIndex = oCellEditor._selectedIndex;
     oCellEditor._selectedIndex = -1;
   }
   var val = oCellEditor.value;
   if (!oCellEditor.options) val = this.getInputElm(oCell).value; //Text box
   oCell.removeChild(oCellEditor);
   this.getInputElm(oCell).value = val;
   this._setShownValue( this._getShownValue(val,oJsTable), oCell,oJsTable);
 };

} function JsTableColumnDate(columnName,inputName,width,align,saveAsSQLformat) {

 this.base = JsTableColumnClass;
 align = align || "center";
 this.base(columnName,inputName,width,align);
 this.saveAsSQLformat = (saveAsSQLformat?true:false);
 
 this.isValid = function (val,oJsTable) {
   val = val+"";
   return val.isDate(oJsTable.tableModel.dateFormat);
 };
 this.fixedValue = function (val,oJsTable) {
      var valid = this.isValid(val,oJsTable);
   if (valid) return valid;
   return "00-00-0000";
 };
 this.getValue = function(oCell,oJsTable) {
   return this.getShownValue(oCell,oJsTable);
 };
 this._getShownDate = function(val,dateFormat) {
   if (this.saveAsSQLformat) {
     if (val=="0000-00-00") return "00-00-0000";
     var dt = new Date();
     dt.setFrom_sqldate(val);
     if (dateFormat=="m-d-y") return dt.mmddyyyy();
     return dt.ddmmyyyy();
   }
   return val;
 };
 this.getShownValue = function(oCell,oJsTable) {
   var val = this.getInputElm(oCell).value;
   return this._getShownDate(val,oJsTable.tableModel.dateFormat);
 };
 this._getSavedDate = function(val,dateFormat) {
   if (this.saveAsSQLformat) {
     dt = new Date();
     if (val=="00-00-0000") return "0000-00-00";
     else if (dateFormat=="m-d-y") dt.setFrom_mmddyyyy(val);
     else dt.setFrom_ddmmyyyy(val);
     return dt.sqldate();
   }
   return val;
 };
 this.setValue = function(val,oCell,oJsTable,oCellEditor) {
   val = this.fixedValue(val,oJsTable);
   this.getInputElm(oCell).value = this._getSavedDate(val, oJsTable.tableModel.dateFormat);
   if (oCellEditor) oCellEditor.value = this.getShownValue(oCell,oJsTable);
   else this._setShownValue(val,oCell,oJsTable);
 };
 this.addCell = function(oRow,oJsTable,val) {
   val = this.fixedValue(val,oJsTable);
   var savedval = this._getSavedDate(val,oJsTable.tableModel.dateFormat);;
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oInput = document.createElement("INPUT");
   oInput.type = "hidden";
   oInput.setAttribute("name",this.inputName);
   oInput.setAttribute("id",this.inputName); //IE6
   oInput.value = savedval;
   oCell.appendChild(oInput);
   oCell.appendChild(document.createTextNode(val));
   oCell.style.whiteSpace = "nowrap";
   oCell.onkeypress = JsTableOnNumberKeyPress;
   oCell.dateCol = true;
   return oCell;
 };

} function JsTableColumnDateTime(columnName,inputName,width,align,saveAsSQLformat) {

 this.base = JsTableColumnDate;
 this.base(columnName,inputName,width,align,saveAsSQLformat);
 
 this.isValid = function (val,oJsTable) {
   val = val+"";
   return val.isDateTime(oJsTable.tableModel.dateFormat);
 }
 this.fixedValue = function (val,oJsTable) {
      var valid = this.isValid(val,oJsTable);
   if (valid) return valid;
   return "00-00-0000 00:00:00";
 }
 this.getShownValue = function(oCell,oJsTable) {
   var val = this.getInputElm(oCell).value;
   var dt = val.split(/\s+/);
   var showndate = this._getShownDate(dt[0],oJsTable.tableModel.dateFormat);
   return (showndate+" "+dt[1]);
 };
 this.setValue = function(val,oCell,oJsTable,oCellEditor) {
   val = this.fixedValue(val,oJsTable);
   var dt = val.split(/\s+/);
   var saveddate = this._getSavedDate(dt[0],oJsTable.tableModel.dateFormat);
   this.getInputElm(oCell).value = saveddate + " " + dt[1];
   if (oCellEditor) oCellEditor.value = this.getShownValue(oCell,oJsTable);
   else this._setShownValue(val,oCell,oJsTable);
 };
 this.addCell = function(oRow,oJsTable,val) {
   val = this.fixedValue(val,oJsTable);
   var dt = val.split(/\s+/);
   var saveddate = this._getSavedDate(dt[0],oJsTable.tableModel.dateFormat);;
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oInput = document.createElement("INPUT");
   oInput.type = "hidden";
   oInput.setAttribute("name",this.inputName);
   oInput.setAttribute("id",this.inputName); //IE6
   oInput.value = saveddate + " " + dt[1];
   oCell.appendChild(oInput);
   oCell.appendChild(document.createTextNode(val));
   oCell.style.whiteSpace = "nowrap";
   oCell.onkeypress = JsTableOnNumberKeyPress;
   oCell.datetimeCol = true;
   return oCell;
 };

} function JsTableColumnLink(columnName,inputName,width,align,identifier,href) {

 this.base = JsTableColumnClass;
 align = align || "center";
 this.base(columnName,inputName,width,align);
 this.identifier = identifier;
 this.href = href+"";
 
 this.setPrimaryKey = function(oCell,primaryKey) {
   var oLink = this.getInputElm(oCell);
   var sHref = oLink.getAttribute("orgHref");
   sHref = sHref.replace(/__ROW__/g, oCell.parentNode.rowIndex);
   oLink.href = sHref.replace(/__PRIMARY_KEY__/g, primaryKey);
   oLink.setAttribute("primaryKey",primaryKey);
 };
 this.setRowIndex = function(oCell) {
   var oLink = this.getInputElm(oCell);
   var sHref = oLink.getAttribute("orgHref");
   sHref = sHref.replace(/__ROW__/g, oCell.parentNode.rowIndex);
   oLink.href = sHref.replace(/__PRIMARY_KEY__/g, oLink.getAttribute("primaryKey"));
 };
 this.getInputElm = function(oCell) {
   var arElms = oCell.getElementsByTagName("A");
   for (var i=0; i<arElms.length; i++) {
     if (arElms[i].getAttribute("name") == this.inputName) return arElms[i];
   }
 };
 this.getCellEditor = function(oCell,oJsTable) {
   return this.getInputElm(oCell);
 };
 this.getValue = function(oCell,oJsTable) {
   return this.getInputElm(oCell).href;
 };
 this.getShownValue = function(oCell,oJsTable) {
   return this.getInputElm(oCell).firstChild;
 };
 this.getShownValueOnEdit = function(oCell,oJsTable) {
 };
 this._setShownValue = function(val,oCell,oJsTable) {
   if (typeof val != "object") val = document.createTextNode(val+"");
   var oLink = this.getInputElm(oCell);
   if (oLink.firstChild) oLink.replaceChild(val,oLink.firstChild);
   else oLink.appendChild(val);
 };
 this.setIdentifier = function(identifier,oCell,oJsTable) {
   this._setShownValue(identifier,oCell,oJsTable);
   this.identifier = identifier;
 };
 this.setValue = function(sHref,oCell,oJsTable,oCellEditor) {
   var oLink = this.getInputElm(oCell);
   oLink.href = sHref.replace(/__PRIMARY_KEY__/g,primaryKey);
   oLink.setAttribute("orgHref",sHref);
 };
 this.setEditorOnEdit = function(oCellEditor,oCell,oJsTable) {
   oJsTable.onEdit = false;
 };
 this.setEditorOnCommit = function(oCellEditor,oCell,oJsTable) {
 };
 this.setEditorOnArrive = function(oCellEditor,oCell,oJsTable) {
   oCell.className = "cell-focus";
 };
 this.setEditorOnRearrive = function(oCellEditor,oCell,oJsTable) {
   this.setEditorOnArrive(oCellEditor,oCell,oJsTable);
 };
 this.setEditorOnLeave = function(oCellEditor,oCell,oJsTable) {
   oCell.className = "";
 };
 this.containsEditor = function(oCell,oCellEditor) {
   return 1;
 };
 this.addCell = function(oRow,oJsTable,sHref,primaryKey,iRow) {
   var oCell = oRow.insertCell(oRow.cells.length);
   oCell.style.textAlign = this.align;
   var oLink = document.createElement("A");
   oLink.setAttribute("name",this.inputName);
   if (!sHref) sHref = this.href;
   sHref = sHref + "";
   oLink.setAttribute("orgHref",sHref);
   oLink.setAttribute("primaryKey",primaryKey);
   sHref = sHref.replace(/__PRIMARY_KEY__/g,primaryKey);
   if (typeof oRow.rowIndex != "undefined") iRow = oRow.rowIndex; //undefined for Opera7
   oLink.href = sHref.replace(/__ROW__/g,iRow);
   oCell.appendChild(oLink);
   var identifier = this.identifier;
   if (typeof this.identifier == "object") {
     if (this.identifier.cloneNode) identifier = this.identifier.cloneNode(true);
     else identifier = this.identifier.toString();
   }
   this._setShownValue(identifier,oCell,oJsTable);
   if (JsTableNavFamily=="Opera7") {
     oLink.onclick = JsTableOnLinkClickOpera7;
     oLink.onmouseup = JsTableOnLinkMouseUpOpera7;
     //oLink.onkeypress = JsTableOnLinkKeyPress;
     oLink.onkeydown = JsTableOnLinkKeyDownOpera7;
   }
   oLink.onblur = JsTableOnBlur;
   return oCell;
 };

}

/***** Sets needed CSS *********************************/ function JsTableSetCSS() {

 var noJsTableStyle = true;
 var o, hasMethodInsert = true;
 if (document.styleSheets) {
   if (!document.styleSheets.length) {
     o = document.getElementsByTagName("HEAD");
     if (o) {
       o = o[0];
       o.appendChild(document.createElement("STYLE"));
     }
   }
   var cssRules = "cssRules";
   if (JsTableNavFamily=="IE6") cssRules = "rules";
   var selectorText;
   for (i=0; i<document.styleSheets.length; i++) {
     o = document.styleSheets[i][cssRules];
     for (j=0; j<o.length; j++) {
       selectorText = o[j].selectorText.toLowerCase();
       if (selectorText==".jstable" || selectorText=="table.jstable") {
         noJsTableStyle = false;
         break;
       }
     }
     if (!noJsTableStyle) break;
   }
   if (!document.styleSheets.length) hasMethodInsert = false; //We cannot insert new rules via DOM method
 } else {//if (document.styleSheets)
   hasMethodInsert = false;
 }
 
 var addRule = function(selector,sRule,o,iPhase) {
 }
 if (noJsTableStyle && hasMethodInsert) {
   o = document.styleSheets[0];
   if (JsTableNavFamily=="IE6") {
     addRule = function(selector,sRule,oStyle,iPhase) {
       oStyle.addRule(selector,sRule);
     }
   } else {
     addRule = function(selector,sRule,oStyle,iPhase) {
       oStyle.insertRule(selector + "{" + sRule + "}", o.cssRules.length);
     }
   }
 } else if (noJsTableStyle && !hasMethodInsert) {
   o = null;
     addRule = function(selector,sRule,oStyle,iPhase) {
       if (iPhase==1) document.write("<"+"style>\n");
       document.write(selector + "{" + sRule + "}\n");
       if (iPhase==2) document.write("<"+"/style>\n");
     }
 }
 var sCellStyle = "font-family:arial,sans-serif; font-size:12px; ";
 var sCellEditorStyle = "background-color:#cccccc; margin:0px; padding:0px; " + sCellStyle;
 sCellStyle = "background-color:white; height:18px; " + sCellStyle;
 addRule(".JsTable", "background-color:black", o, 1);
 addRule(".JsTable TH", sCellStyle, o, 0);
 addRule(".JsTable TD", sCellStyle, o, 0);
 addRule(".JsTable TEXTAREA", sCellEditorStyle, o, 0);
 addRule(".JsTable INPUT", sCellEditorStyle, o, 0);
 addRule(".JsTable INPUT.checkbox", "background-color:transparent", o, 0);
 addRule(".JsTable .cell-focus", "background-color:#cccccc", o, 0);
 addRule(".JsTable SELECT", "height:16px; " + sCellEditorStyle, o, 2);

} JsTableSetCSS(); var JsTableGetKeyCode = function(e) {}; if (JsTableNavFamily=="Gecko") { //Makes the event object in Gecko like the one in IE

 function JsTableGeckoEventButton() {
   switch (this.which) {
     case 1: return 1;
     case 2: return 4;
     case 3: return 2;
   }
 }
 function JsTableGeckoEventSrcElement() {
   return this.target;
 }
 function JsTableGeckoEventFromElement() {
   return this.relatedTarget;
 }
 function JsTableGeckoEventToElement() {
   return this.relatedTarget;
 }
 function JsTableGeckoEventReturnValue(bVal) {
   if (!bVal) this.preventDefault();
 }
 function JsTableGeckoEventCancelBubble(bVal) {
   if (bVal) this.stopPropagation();
 }
 function JsTableGeckoEventOffsetX() {
   return this.layerX;
 }
 function JsTableGeckoEventOffsetY() {
   return this.layerY;
 }
 //Other than Gecko, which doesn"t support getter and setter statement, will not fail here
 eval("Event.prototype.button getter= JsTableGeckoEventButton");
 eval("Event.prototype.srcElement getter= JsTableGeckoEventSrcElement");
 eval("Event.prototype.fromElement getter= JsTableGeckoEventFromElement");
 eval("Event.prototype.toElement getter= JsTableGeckoEventToElement");
 eval("Event.prototype.returnValue setter= JsTableGeckoEventReturnValue");
 eval("Event.prototype.cancelBubble setter= JsTableGeckoEventCancelBubble");
 eval("Event.prototype.offsetX getter= JsTableGeckoEventOffsetX");
 eval("Event.prototype.offsetY getter= JsTableGeckoEventOffsetY");
 

//Emulates method contains in IE

 Element.prototype.contains = function(oNode) {
   while (oNode) {
     if (this == oNode) return true;
     oNode = oNode.parentNode;
   }
   return false;
 }
 JsTableGetKeyCode = function(e) {
   if (e.type=="keypress") {
     if (e.charCode) return e.charCode;
     else switch (e.keyCode) {
       case 8:  //Backspace
       case 9:  //Tab
       case 13: //Enter
         return e.keyCode;
       default:
         return e.keyCode*1000; //Multiply by 1000 to avoid overlapping with printable keyCode 
     }
   }
   return e.keyCode;
 };

} else if (JsTableNavFamily=="Opera7") {

 //Opera7 has different value for middle button from IE has, but we forgive it
 /*Event.prototype.button getter= function() {
   switch (this.button) {
     case 1: return 1;
     case 2: return 2;
     case 3: return 4;
   }
 }*/
 
 JsTableKeyCodeOnKeyDown = 0;
 JsTableGetKeyCode = function(e) {
   //Opera 7.1 has different keyCode for extended keys (thousands value)
   if (e.type=="keypress") {
     switch (e.keyCode) {
       case 113: if (JsTableKeyCodeOnKeyDown==81) return 81; // q
       case 57346:
         return 113000; //F2
       case 37:
       case 57387:
         return 37000;  //Left Arrow
       case 38:
       case 57385:
         return 38000;  //Up Arrow
       case 39: //Right arrow or single quote ( " ) on Opera 7.2+
       case 57388:
         if (JsTableKeyCodeOnKeyDown==222) return 39; //single quote ( " )
         return 39000;  //Right Arrow
       case 40:
       case 57386: return 40000;  //Down Arrow
       case 57395: return 46000;  //Delete
       case 57381: return 36000;  //Home
       case 57382: return 35000;  //End
       default   : return e.keyCode;
     }
   } else {
     JsTableKeyCodeOnKeyDown = e.keyCode;
     switch (e.keyCode) {
       case 57346: return 113; //F2
       case 57387: return 37;  //Left Arrow
       case 57385: return 38;  //Up Arrow
       case 57388: return 39;  //Right Arrow
       case 57386: return 40;  //Down Arrow
       case 57395: return 46;  //Delete
       case 57381: return 36;  //Home
       case 57382: return 35;  //End
       default   : return e.keyCode;
     }
   }
 };

} else { //IE 6

 JsTableGetKeyCode = function(e) {
   return e.keyCode;
 };

} /************** Event Handler ********************/ function JsTableGetObjectsOnEvent(sTagName,e) {

 if (!e) e = window.event;
 var oTarget = e.srcElement;
 var objs = {target: oTarget};
 while (sTagName.indexOf("|"+oTarget.nodeName+"|")==-1) {
   if (oTarget.nodeName=="TABLE") return null;
   if (oTarget.nodeName=="HTML") return null;
   oTarget = oTarget.parentNode;
   if (!oTarget) return null;
 }
 if (oTarget.nodeName=="TD" || oTarget.nodeName=="TH") {
   objs.cellEditor = null;
   objs.cell = oTarget;
 } else {
   objs.cellEditor = oTarget;
   objs.cell = oTarget.parentNode;
 }
 if (!objs.cell) return null;
 objs.row = objs.cell.parentNode;
 if (!objs.row) return null;
 objs.tbl = (objs.row.parentNode ? objs.row.parentNode.parentNode : null);
 if (!objs.tbl) return null;
 objs.jsTable = window["_"+objs.tbl.id];
 objs.event = e;
 objs.keyCode = JsTableGetKeyCode(e);
 return objs;

} var JsTableColToResize = -1; var JsTableOffsetXstartToResize = -1; var JsTableObjectTblOnResize = null; function JsTableHeaderOnMouseMove(e) {

 if (!e) e = window.event;
 var oTarget = e.srcElement;
 var oTbl = oTarget;
 while (oTbl.nodeName!="TABLE") {
   oTbl = oTbl.parentNode;
   if (!oTbl) return;
 }
 var oRow = oTbl.rows[0];
 var bOnEdge = false;
 if (oTarget.tagName=="TH") {
   if (e.offsetX==0 && oTarget.cellIndex!=0) {
     JsTableColToResize = oTarget.cellIndex - 1; //Resize the left side column
     bOnEdge = true;
   }
   if (e.offsetX==oTarget.offsetWidth-1) {
     JsTableColToResize = oTarget.cellIndex; //Resize the left side column
     bOnEdge = true;
   }
 }
 
 if (bOnEdge) {
   oTbl.style.cursor = "w-resize";
 } else {
   oTbl.style.cursor = "default";
   JsTableColToResize = -1;
 }

} function JsTableHeaderOnMouseOver(e) {

 if (!e) e = window.event;
 var oTbl = e.srcElement;
 if (oTbl.tagName!="TABLE") return;
 if (!e.fromElement) return;
 if (e.fromElement.tagName!="TH") return;
 var oRow = oTbl.rows[0];
 var bOnEdge = (e.offsetY < oRow.offsetHeight && e.offsetX > 1); //On the edge precisely
 if (bOnEdge) {
   var iLeft = oRow.cells[0].offsetWidth + 1 + oRow.cells[1].offsetWidth;
   var iCol = 1;
   while (e.offsetX > iLeft) {
     iCol++;
     if (iCol==oRow.cells.length) break;
     iLeft += oRow.cells[iCol].offsetWidth + 1;
   }
   JsTableColToResize = iCol - 1; //Resize the left side column
   oTbl.style.cursor = "w-resize";
 } else {
   oTbl.style.cursor = "default";
   JsTableColToResize = -1;
 }

} function JsTableHeaderOnMouseOut(e) {

 if (!e) e = window.event;
 var oTarget = e.toElement;
 var oTbl = oTarget;
 while (oTbl) {
   if (oTbl.nodeName=="TABLE") break;
   oTbl = oTbl.parentNode;
 }
 if (!oTbl) {
   JsTableColToResize = -1;
   if (this.style) this.style.cursor = "default";
 }

} function JsTableStopDragOnResize(oJsTable,bHasFocus) {

 oTbl = oJsTable.table;
 oTbl.style.cursor = "default";
 oTbl.onmousemove = JsTableHeaderOnMouseMove;
 oTbl.onmouseover = JsTableHeaderOnMouseOver;
 oTbl.onmouseout = JsTableHeaderOnMouseOut;
 oTbl.onmouseup = null;
 if (document.releaseCapture) document.releaseCapture();
 else {
   document.removeEventListener("mouseup",JsTableOnResizeOnMouseUp,true);
   document.removeEventListener("mouseout",JsTableOnResizeOnMouseOut,true);
 }
 JsTableColToResize = -1;
 JsTableOffsetXstartToResize = -1;
 JsTableObjectTblOnResize = null;
 if (bHasFocus) oJsTable.setFocus(true);

} function JsTableOnResizeOnMouseUp(e) {

 if (!JsTableObjectTblOnResize) return;
 if (!e) e = window.event;
 var dx = e.screenX - JsTableOffsetXstartToResize;
 var oJsTable = window["_"+JsTableObjectTblOnResize.id];
 var bHasFocus = oJsTable.hasFocus;
 if (bHasFocus) oJsTable.setFocus(false);
 var oCol = oJsTable.tableModel.columns[JsTableColToResize];
 oCol.width += dx;
 if (oCol.width < 20) oCol.width = 20;
 var oTbl = oJsTable.table;
 for (var i=0; i<oTbl.rows.length; i++) {
   oTbl.rows[i].cells[JsTableColToResize].style.width = oCol.width + "px";
   oTbl.rows[i].cells[JsTableColToResize].width = oCol.width;
 }
 JsTableStopDragOnResize(oJsTable,bHasFocus);

} function JsTableOnResizeOnMouseOut(e) {

 if (!JsTableObjectTblOnResize) return;
 if (!e) e = window.event;
 if (!e.toElement) {
   var oJsTable = window["_"+JsTableObjectTblOnResize.id];
   var bHasFocus = oJsTable.hasFocus;
   JsTableStopDragOnResize(oJsTable,bHasFocus);
 }

} function JsTableOnMouseDown(e) {

 if (JsTableColToResize >= 0) {
   if (!e) e = window.event;
   JsTableOffsetXstartToResize = e.screenX;
   JsTableObjectTblOnResize = this;
   this.onmousemove = null;
   this.onmouseover = null;
   this.onmouseout = null;
   if (JsTableNavFamily=="IE6") {
     this.setCapture();
     this.onmouseup = JsTableOnResizeOnMouseUp;
     this.onmouseout = JsTableOnResizeOnMouseOut;
   } else {
     document.addEventListener("mouseup",JsTableOnResizeOnMouseUp,true);
     document.addEventListener("mouseout",JsTableOnResizeOnMouseOut,true);
   }
 }
 var o = JsTableGetObjectsOnEvent("|TD|TH|",e);
 if (!o) return;
 var iRow = o.row.rowIndex;
 var iCol = o.cell.cellIndex;
 if (iRow < 1) {
   if (o.tbl.rows.length <= 1) return;
   iRow = 1;
 }
 if ("|TEXTAREA|INPUT|SELECT|A|".indexOf("|"+o.target.nodeName+"|")!=-1) o.cellEditor = o.target;
 o.cell._onclick = true;
 if (JsTableNavFamily=="IE6" && o.jsTable.hasFocus && o.jsTable.row==iRow && o.jsTable.col==iCol) {
   if (o.target!=o.cellEditor) o.jsTable._onclickIE6 = [-1,-1];
   else if (o.target.nodeName=="TEXTAREA" ||
     (o.target.nodeName=="INPUT" && o.target.type=="text")) o.jsTable._onclickIE6 = [iRow,iCol];
 }
 o.jsTable.setActiveCell(iRow,iCol);
 if (o.cellEditor!=o.target) {
   o.event.returnValue = false;
   return false;
 }

} function JsTableOnDblClick(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|",e);
 if (!o) return;
 o.jsTable.setOnEdit();

} function JsTableOnBlur(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|SELECT|A|",e);
 if (!o) return;
 if (o.jsTable._onclickIE6)
   o.jsTable._onclickIE6 = (o.jsTable._onclickIE6[0]!=o.row.rowIndex
     || o.jsTable._onclickIE6[1]!=o.cell.cellIndex);
 if (o.jsTable._onmove) o.jsTable._onmove = false;
 else if (o.jsTable._onclickIE6) //IE 6
   //When JsTable has focus and then the active cell is clicked but not on the CellEditor,
   //such as checkbox or link, the blur event will occur but we want the JsTable still has focus
   o.cellEditor.focus();
 else if (o.jsTable.row==o.row.rowIndex && o.jsTable.col==o.cell.cellIndex)//used especially for Opera 7
   //must be the active cell which experiences the blur event. The event can happen on the previous
   //active cell whose different cell editor from the one owned the current active cell.
   //o.jsTable._onmove is useful when the cell editor remains the same
   { o.jsTable._onblur=true; o.jsTable.setFocus(false); }
 
 o.jsTable._onclickIE6 = false;

} function JsTableOnKeyPress(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|SELECT|",e);
 if (!o) return;
 var bRetVal = true;
 switch (o.keyCode) {
   case 37000: //Left Arrow
   case 38000: //Up Arrow
   case 39000: //Right Arrow
   case 40000: //Down Arrow
     if (o.jsTable.onEdit) break;
   case 13: //Enter
     if (o.cellEditor.nodeName=="A") break;
   case 113000: //F2
   case 27: //Esc
     o.event.returnValue = false;
     o.event.cancelBubble = true;
     bRetVal = false;
   default:
     
 }
 
 if (typeof o.jsTable.onkeypress == "function") o.jsTable.onkeypress(o.event);
 if (!bRetVal) return false;

} function JsTableGetNewCoordOnArrow(iArrowKey,iRow,iCol,oTbl,oRow) {

 switch (iArrowKey) {
   case 37: //Left
   case 37000:
     return {row: iRow, col: ( (iCol>0)?(iCol-1):iCol )};
   case 38: //Up
   case 38000:
     return {row: ( (iRow>1)?(iRow-1):iRow ), col: iCol};
   case 39: //Right
   case 39000:
     return {row: iRow, col: ( (iCol<oRow.cells.length-1)?(iCol+1):iCol )};
   case 40: //Down
   case 40000:
     return {row: ( (iRow<oTbl.rows.length-1)?(iRow+1):iRow ), col: iCol};
 }

} function JsTableOnKeyDown(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|SELECT|A|",e);
 if (!o) return;
 var iRow = o.row.rowIndex;
 var iCol = o.cell.cellIndex;
 var bRetVal = true;
 //Arrow keys
 if (o.keyCode >= 37 && o.keyCode <= 40) {
   if (!o.jsTable.onEdit) {
     var oCoord = JsTableGetNewCoordOnArrow(o.keyCode,iRow,iCol,o.tbl,o.row);
     o.cell._keydown = true;
     o.jsTable.setActiveCell(oCoord.row, oCoord.col);
     bRetVal = false;
   }
 } else {
   switch (o.keyCode) {
   case 13: //Enter
     if (o.cellEditor.nodeName=="A") break;
     if (!o.jsTable.onEdit) o.jsTable.setOnEdit();
     else {
       o.jsTable.setOnCommit();
       var keyCode = 0;
       if (o.jsTable.tableModel.enterAfterEdit == JsTable.ENTER_MOVE_DOWN) keyCode = 40;
       if (o.jsTable.tableModel.enterAfterEdit == JsTable.ENTER_MOVE_RIGHT) keyCode = 39;
       if (keyCode) {
         var oCoord = JsTableGetNewCoordOnArrow(keyCode,iRow,iCol,o.tbl,o.row);
         o.cell._keydown = true;
         o.jsTable.setActiveCell(oCoord.row, oCoord.col);
       }
     }
     bRetVal = false; break;
   case 113: //F2
     o.jsTable.setOnEdit();
     bRetVal = false; break;
   case 27: // Escape
     o.jsTable.setOnCommit();
     bRetVal = false; break;
   }
 }
 
 if (typeof o.jsTable.onkeydown == "function") o.jsTable.onkeydown(o.event);
 if (!bRetVal) {
   o.event.returnValue = false;
   o.event.cancelBubble = true;
   return false;
 }

} function JsTableOnCheckboxClick(e) {

 var o = JsTableGetObjectsOnEvent("|INPUT|",e);
 if (!o) return;
 o.event.returnValue = false;
 o.cellEditor.checked = o.cell._checked;

} function JsTableOnCheckboxKeyDown(e) {

 var o = JsTableGetObjectsOnEvent("|INPUT|",e);
 if (!o) return;
 switch (o.keyCode) {
   case 32: //Space
     o.jsTable.setOnEdit();
   case 113: //F2
   case 27: // Escape
     o.event.returnValue = false;
     o.event.cancelBubble = true;
     return false;
   case 13: //Enter
     o.jsTable.setOnEdit();
     o.jsTable.onEdit = true;
 }

} function JsTableOnCheckboxKeyPress(e) {

 var o = JsTableGetObjectsOnEvent("|INPUT|",e);
 if (!o) return;
 if (o.keyCode==32) { //space
   o.event.returnValue = false;
   o.event.cancelBubble = true;
   return false;
 }

} function JsTableOnStringKeyPress(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|",e);
 if (!o) return;
 if (!o.jsTable.onEdit && (o.keyCode >= 32 && o.keyCode <= 126)) { //typeable character
   o.cellEditor.readOnly = false;
   o.cellEditor.select(); //IE6
   o.jsTable.onEdit = true;
   o.cellEditor.value = "";//String.fromCharCode(o.keyCode);
 }

} function JsTableOnNumberKeyPress(e) {

 var o = JsTableGetObjectsOnEvent("|TEXTAREA|INPUT|",e);
 if (!o) return;
 
 var keyCode = o.keyCode;
 var val = o.cellEditor.value;
 var bTrueChar = ((keyCode >= 48 && keyCode <= 57)   //numeric keys
   || keyCode == 45);   //hyphen (-)
 var bDecOk = true;
 if (o.cell.dateCol || o.cell.datetimeCol) {
   //if (keyCode==45) return;//hyphen
   if (o.cell.datetimeCol)
     bTrueChar = bTrueChar || keyCode==32 || keyCode==58; //space, : (colon)
 } else {
   var pointDec = ",";
   if (o.jsTable.tableModel.numberDenominator==",") pointDec = ".";
   if (pointDec=="," && keyCode==44) {
     bTrueChar = true;
     bDecOk = (val.indexOf(",")==-1);//ok if decimal point not yet exist
   } else if (pointDec=="." && keyCode==46) {
     bTrueChar = true;
     bDecOk = (val.indexOf(".")==-1);//ok if decimal point not yet exist
   }
   //if (keyCode==45 && val.indexOf("-")!=0) return; //hyphen
 }
 if (!o.jsTable.onEdit) {
   if (bTrueChar) {
     o.cellEditor.readOnly = false;
     o.cellEditor.select(); //IE6
     o.jsTable.onEdit = true;
     o.cellEditor.value = "";//String.fromCharCode(keyCode);
     return;
   }
 } else if ((bTrueChar && bDecOk)
 //  || keyCode == 13 || keyCode == 27  //Enter, Escape
   || keyCode == 46000 || keyCode == 8 || keyCode == 9 //Delete, Backspace, Tab
   || (keyCode >= 37000 && keyCode <= 40000)   //Arrow
   || keyCode == 0   //Some extended keys on Opera
   || keyCode == 36000 || keyCode == 35000  //Home, end
 ) {
   return;
 }
 o.event.returnValue = false;
 o.event.cancelBubble = true;
 return false;

} function JsTableOnLinkClickOpera7(e) {

 if (this._nocancelclick) this._nocancelclick = false;
 else return false;

} var JsTableOnLinkMouseUpJsTableObject = null; var JsTableOnLinkMouseUpLinkObject = null; function JsTableOnLinkMouseUpOpera7(e) {

 var o = JsTableGetObjectsOnEvent("|A|",e);
 if (!o) return;
 JsTableOnLinkMouseUpLinkObject = o.cellEditor;
 JsTableOnLinkMouseUpJsTableObject = o.jsTable;
 setTimeout(
 "if (JsTableOnLinkMouseUpJsTableObject) { "
   + "JsTableOnLinkMouseUpJsTableObject.setFocus(true); "
   + "JsTableOnLinkMouseUpJsTableObject=null; } "
 + "if (JsTableOnLinkMouseUpLinkObject) { "
   + "JsTableOnLinkMouseUpLinkObject._nocancelclick=true; "
   + "JsTableOnLinkMouseUpLinkObject.click(); "
   + "JsTableOnLinkMouseUpLinkObject=null; }",0);

} function JsTableOnLinkKeyDownOpera7(e) {

 if (!e) e = window.event;
 if (e.keyCode==13) this._nocancelclick = true;

} /************ End: Event Handler ****************************/

function JsTableModel(columns,phpStyle,numberDenominator,dateFormat,oldValIfInvalid,

 withPrimaryKey)

{

 //columns is a collection of instance of JsTableColumnClass
 if (typeof columns != "object") columns = [];
 else if (!columns.length) columns = [];
 this.columns = columns;
 
 //Only "," or "." accepted
 if (numberDenominator != ",") numberDenominator = ".";
 this.numberDenominator = numberDenominator;
 
 //Only "d-m-y" or "m-d-y" accepted
 dateFormat = (dateFormat+"").toLowerCase();
 if (dateFormat != "m-d-y") dateFormat = "d-m-y";
 this.dateFormat = dateFormat;
 
 if (oldValIfInvalid) this.oldValIfInvalid = true;
 else this.oldValIfInvalid = false;
 
 if (phpStyle) {
   for (var i=0;i<columns.length;i++) columns[i].inputName += "[]";
 }
 
 this.withPrimaryKey = (withPrimaryKey ? true : false);
 this.enterAfterEdit = JsTable.ENTER_STAY;
 
 this.isCellEditable = function(iRow,iCol) {
   return true;
 };

}

function JsTable(sId,oTableModel,oParent,oNextSibling) {

 function errorId() {
   alert("The table Id is invalid or has been existed");
   return null;
 }
 if (typeof sId != "string" || !sId) return errorId();
 if (!sId.isQualifiedVarName()) return errorId();
 if ( (typeof window[sId]!="undefined") || (typeof window["_"+sId]!="undefined")
   || document.getElementById(sId)) return errorId();
 
 if (!oParent && !oParent.insertBefore) {
   if (document.forms.length) {
     oParent = document.forms[document.forms.length];
   } else {
     oParent = document.body.appendChild(document.createElement("FORM"));
   }
 }
 
 var oTbl = document.createElement("TABLE");
 //oTbl.onmousemove = JsTableHeaderOnMouseMove;
 oTbl.id = sId;
 oTbl.className = "JsTable";
 oTbl.cellSpacing = 1;
 oTbl.cellPadding = 0;
 
 /* Creates Column Headers */
 var o = oTbl.createTHead();
 o = o.insertRow(0);
 var columns = oTableModel.columns;
 var oText, oCell;
 for (var i=0; i<columns.length; i++) {
   oText = document.createTextNode(columns[i].columnName);
   oCell = o.appendChild(document.createElement("TH"));
   oCell.style.width = columns[i].width + "px";
   oCell.appendChild(oText);
 }
 if (JsTableNavFamily == "IE6") { //if (JsTableNavFamily != "Gecko")
   oTbl.onmousemove = JsTableHeaderOnMouseMove;
   oTbl.onmouseover = JsTableHeaderOnMouseOver;
   oTbl.onmouseout = JsTableHeaderOnMouseOut;
 }
 
 if (!oNextSibling) oNextSibling = null;
 oTbl = oParent.insertBefore(oTbl,oNextSibling);
 window[sId] = oTbl;
 window["_"+sId] = this;
 this.table = oTbl;
 this.id = sId;
 this.tableModel = oTableModel;
 
 if (true) { //(JsTableNavFamily=="Opera7") {
   o = document.createElement("INPUT");
   o.type = "text";
 } else {
   o = document.createElement("TEXTAREA");
   if (JsTableNavFamily=="IE6") o.style.overflow = "hidden";
   else o.style.overflow = "auto";
 }
 o.readOnly = true;
 o.style.width = "100%";
 o.style.height = "100%";
 o.style.margin = "0px";
 o.style.borderStyle = "solid";
 o.style.borderWidth = "1px";
 //o.style.padding = "1px 1px 1px 0px";
 o.style.paddingRight = "1px";
 o.style.borderColor = "#cccccc";
 this.cellEditor = o;
 
 this.row = -1;
 this.col = -1;
 this.onEdit = false;
 this.hasFocus = false;
 
 oTbl.onmousedown = JsTableOnMouseDown;
 oTbl.onkeydown = JsTableOnKeyDown;
 oTbl.onkeypress = JsTableOnKeyPress;
 //oTbl.onblur = JsTableOnBlur;
 this.cellEditor.ondblclick = JsTableOnDblClick;
 //this.cellEditor.onkeydown = JsTableOnKeyDown;
 //this.cellEditor.onkeypress = JsTableOnKeyPress;
 this.cellEditor.onblur = JsTableOnBlur;
 
 this.onkeydown = function(e) {};
 this.onkeypress = function(e) {};
 this.oncellchange = function() {};
 this.oncommit = function() {};
 
 this._keys = [];

} JsTable.prototype.getObjectsOnCell = function(iRow,iCol) {

 var oColumn = this.tableModel.columns[iCol];
 var oCell = this.table.rows[iRow];
 if (oCell) oCell = oCell.cells[iCol];
 var oCellEditor = oColumn.getCellEditor(oCell,this);
 if (!oCellEditor) oCellEditor = this.cellEditor;
 return {column: oColumn, cellEditor: oCellEditor, cell: oCell};

}; JsTable.prototype.getColumn = function(iCol) {

 return this.tableModel.columns[iCol];

}; JsTable.prototype.setHeader = function(sHeader, iCol) {

 var oCell = this.table.rows[0].cells[iCol];
 if (!oCell) return;
 JsTableRemoveAllText(oCell);
 oCell.appendChild(document.createTextNode(sHeader+""));

}; JsTable.prototype.setValue = function(val, iRow, iCol) {

 if (iRow < 1 || iCol < 0) return;
 var o = this.getObjectsOnCell(iRow,iCol);
 if (!o.cell) return;
 var oCellEditor = null;
 if (o.cellEditor) if (o.cell.contains(o.cellEditor)) oCellEditor = o.cellEditor;
 o.column.setValue(val,o.cell,this,oCellEditor);

}; JsTable.prototype.getValue = function(iRow, iCol) {

 var oTbl = this.table;
 if (iRow < 1) return;
 var oRow = oTbl.rows[iRow];
 if (!oRow) return;
 var oCell = oRow.cells[iCol];
 if (!oCell) return;
 var oColumn = this.tableModel.columns[iCol];
 oColumn.getValue(oCell,this);

}; //arguments list the values for each cell JsTable.prototype.insertRow = function(args,primaryKey,iRow) {

 var oTbl = this.table;
 var arColumn = this.tableModel.columns;
 
 if (!iRow) iRow = oTbl.rows.length;
 iRow = parseInt(iRow);
 if (isNaN(iRow)) return;
 if (iRow > oTbl.rows.length || iRow < 1) iRow = oTbl.rows.length;
 if (!this.tableModel.withPrimaryKey) primaryKey = iRow;
 
 var arColKey = [];
 var i, j = 0;
 var oRow = oTbl.insertRow(iRow);
 for (i=0; i<arColumn.length; i++) {
   arColumn[i].addCell(oRow, this, args[i], primaryKey, iRow);
   oRow.cells[i].style.width = arColumn[i].width + "px";
   if (arColumn[i].setPrimaryKey) {
     arColKey[j] = i;
     j++;
   }
 }
 
 if (!this.tableModel.withPrimaryKey) {
   for (var i=iRow+1; i<oTbl.rows.length; i++) {
     for (j=0; j<arColKey.length; j++) {
       var oCell = oTbl.rows[i].cells[arColKey[j]];
       arColumn[arColKey[j]].setPrimaryKey(oCell,i);
     }
   }
 }
 
 var oInput, oCell = oRow.cells[0];
 //The new row must have all keys
 for (i=0; i<this._keys.length; i++) {
   oInput = document.createElement("INPUT");
   oInput.type = "hidden";
   oInput.setAttribute("name",this._keys[i]);
   oCell.appendChild(oInput);
 }

}; JsTable.prototype.addMatrix = function(args2,primaryKeys) {

 for (var i=0; i<args2.length; i++) {
   this.insertRow(args2[i],primaryKeys[i]);
 }

}; JsTable.prototype.deleteRow = function(iRow) {

 var oTbl = this.table;
 iRow = parseInt(iRow);
 if (isNaN(iRow)) return;
 if (iRow < 1 || iRow >= oTbl.rows.length) return;
 var bHasFocus = this.hasFocus;
 if (iRow == this.row && bHasFocus) this.setFocus(false);
 oTbl.deleteRow(iRow);
 var arColumn = this.tableModel.columns;
 if (!this.tableModel.withPrimaryKey) {
   for (var j=0; j<arColumn.length; j++) {
     if (typeof arColumn[j].setPrimaryKey!="function") continue;
     for (var i=iRow; i<oTbl.rows.length; i++) {
       var oCell = oTbl.rows[i].cells[j];
       arColumn[j].setPrimaryKey(oCell,i);
     }
   }
 }
 for (var j=0; j<arColumn.length; j++) {
   if (typeof arColumn[j].setRowIndex!="function") continue;
   for (var i=iRow; i<oTbl.rows.length; i++) {
     var oCell = oTbl.rows[i].cells[j];
     arColumn[j].setRowIndex(oCell);
   }
 }
 
 if (iRow >= oTbl.rows.length) iRow = oTbl.rows.length-1;
 if (iRow > 0) this.setActiveCell(iRow,this.col);
 else this.row = -1;

}; JsTable.prototype.insertKey = function(sKeyName,val,iRow) {

 var arColumn = this.tableModel.columns;
 for (var i=0; i<arColumn.length; i++)
   if (arColumn[i].inputName==sKeyName) {
     alert("JsTable.insertKey : this key name has been owned by the input of a column");
     return;
   }
 var oTbl = this.table;
 if (!iRow) iRow = 1;
 iRow = parseInt(iRow);
 if (isNaN(iRow)) return;
 if (iRow < 1 || iRow >= oTbl.rows.length) return;
 
 var iLength = 0;
 if ((typeof val != "object") || (typeof val.length != "number")) {
   val = [val];
   iLength = 1;
 } else 
   iLength = val.length;
 if (iRow+iLength > oTbl.rows.length) iLength = oTbl.rows.length - iRow;
 
 var oCell = oTbl.rows[iRow].cells[0];
 var bKeyExist = false;
 var arInputs = oCell.getElementsByTagName("INPUT");
 for (var i=0; i<arInputs.length; i++)
   if (arInputs[i].getAttribute("name")==sKeyName) {
     bKeyExist = true;
     break;
   }
 if (bKeyExist) {
   for (var i=0; i<iLength; i++) {
     oCell = oTbl.rows[iRow+i].cells[0];
     arInputs = oCell.getElementsByTagName("INPUT");
     for (var j=0; j<arInputs.length; j++)
       if (arInputs[j].getAttribute("name")==sKeyName) {
         arInputs[j].value = val[i];
         break;
       }
   }
 } else {
   var j = iRow + iLength;
   //All rows must have this key
   for (var i=0; i<oTbl.rows.length; i++) {
     oCell = oTbl.rows[i].cells[0];
     var oInput = document.createElement("INPUT");
     oInput.type = "hidden";
     oInput.setAttribute("name",sKeyName);
     if (i >= iRow && i < j) oInput.value = val[i-iRow];
     oCell.appendChild(oInput);
   }
 }

}; JsTable.prototype.setActiveCell = function(iRow, iCol) {

 if (iRow < 1 || iRow >= this.table.rows.length
    || iCol < 0 || iCol >= this.tableModel.columns.length) return;
 if (!this.hasFocus) {
   this._oncellchange = (iRow != this.row || iCol != this.col);
   this.row = iRow;
   this.col = iCol;
   this.setFocus(true);
   return;
 }
 
 var o = this.getObjectsOnCell(iRow,iCol);
 if (this.row == iRow && this.col == iCol) {
   o.column.setEditorOnRearrive(o.cellEditor,o.cell,this);
   o.cell._onclick = false;
   o.cell._keydown = false;
   return;
 } else {
   if (this.row > 0 && this.col >= 0) {
     var oldCell = this.getObjectsOnCell(this.row,this.col);
     o.cell._keydown = oldCell.cell._keydown;
     oldCell.cell._keydown = false;
     //oldCell.cellEditor.blur();
     this._onmove = true;
     this.setFocus(false);
   }
 }
 
 this._oncellchange = true;
 this.row = iRow;
 this.col = iCol;
 this.setFocus(true);

};

JsTable.prototype.setOnEdit = function() {

 if (!this.tableModel.isCellEditable(this.row,this.col)) return;
 if (this.onEdit) return;
 if (this.row < 1 || this.col < 0) return;
 var o = this.getObjectsOnCell(this.row,this.col);
 this.onEdit = true;
 o.column.setEditorOnEdit(o.cellEditor,o.cell,this);
 //Enter cannot be canceled on Opera
 //if (o.cellEditor.value) o.cellEditor.value = o.cellEditor.value.replace(/\n/g,"").replace(/\r/g,"");

}; JsTable.prototype.setOnCommit = function() {

 if (!this.onEdit) return;
 if (this.row < 1 || this.col < 0) return;
 var o = this.getObjectsOnCell(this.row,this.col);
 this.onEdit = false;
 //Enter cannot be canceled on Opera
 //if (o.cellEditor.value) o.cellEditor.value = o.cellEditor.value.replace(/\n/g,"").replace(/\r/g,"");
 o.column.setEditorOnCommit(o.cellEditor,o.cell,this);
 this.oncommit();

}; JsTableActiveCellEditor = null; JsTableSetCellEditorFocus = function() {

 if (!JsTableActiveCellEditor) return;
 JsTableActiveCellEditor.focus();
 var oTbl = JsTableActiveCellEditor;
 for (var i=0; i<4; i++) {
   oTbl = oTbl.parentNode;
   if (!oTbl) return;
 }
 //.parentNode.parentNode.parentNode.parentNode;
 var oJsTable = window["_"+oTbl.id];
 oJsTable._onmove = false;
 JsTableActiveCellEditor = null;

}; JsTable.prototype._setCellEditorFocus = function(oCellEditor) {

 JsTableActiveCellEditor = oCellEditor;
 setTimeout("JsTableSetCellEditorFocus()",0);

}; JsTable.prototype.setFocus = function(bGetFocus) {

 if (this.hasFocus == bGetFocus) return;
 if (this.row < 1 || this.col < 0) return;
 var o = this.getObjectsOnCell(this.row,this.col);
 if (bGetFocus) {
   this.hasFocus = true;
   var iCont = o.column.containsEditor(o.cell,o.cellEditor);
   if (iCont ^ -1) //o.column.constructor==JsTableColumnBoolean || !o.cell.contains(o.cellEditor)
     o.column.setEditorOnArrive(o.cellEditor,o.cell,this);
   o.cell._onclick = false;
   o.cell._keydown = false;
   if (this._oncellchange) this.oncellchange();
   this._oncellchange = false;
   this._setCellEditorFocus(o.cellEditor);
 } else {
   this.hasFocus = false;
   if (o.column.containsEditor(o.cell,o.cellEditor)) {
     if (this.onEdit) this.setOnCommit();
     o.column.setEditorOnLeave(o.cellEditor,o.cell,this);
     if (o.column.containsEditor(o.cell,o.cellEditor)) //such as checkbox, Link
       if (!this._onblur) {
          if (o.cellEditor.blur)  o.cellEditor.blur;
       } else {
         this._onblur = false;
       }
   }
 }

}; JsTable.ENTER_STAY = 0; JsTable.ENTER_MOVE_DOWN = 1; JsTable.ENTER_MOVE_RIGHT = 2; } /**************** if (JsTableNavFamily) *****************************/ </script> <style></style> <script language=JavaScript>

</script> </head> <body onload="showTable()" style="width:90%">

Hello this is editable, navigatable and submitable table. Click on the table to give it the focus.
The decimal point of numbers in the table is represented by comma ( , ) not period ( . ). The date time format is "dd-mm-yyyy hh:nn:ss"

<noscript>

Turn on your JavaScript!!

</noscript>

<form method=post action="JsTable.php" target="submittedValues">

   <input type=submit value=Submit>
   <input type=button value="Add Row" onclick="addRow()">
Button "Submit" is to submit the content of table to web server. Button "Add Row" is to add row in the table

</form>

 

How To Edit and Navigate :

To give focus to table, click on the table. The cell on which we click, automatically become the active cell. The active cell is the cell in which we can edit its content. If usually its cell editor is hidden for that cell, when the cell is active, it reveals its cell editor, so we can edit it.

Navigation:
    We can move the active cell by pressing the arrow keys on keyboard by intuitive direction. We can also click on a cell, if we want that cell become active.

Editing:
    To edit the cell"s content needs some steps which is different for different cell editor. I will explain for each cell editor.

  • Textbox (element <TEXTAREA> or <INPUT type=text>)
    To edit, press Enter. Then we will go into the state, we call it editing state. In editing state, the text cursor will appear and thus we can edit the cell"s content. When editing state, the arrow keys cannot be used to navigate but used to move text cursor instead. To end the editing state, press Enter again. Another way to go into editing state is by pressing F2 (on Opera, F2 has the meaning for the browser itself). To end the editing state, press Esc. Pressing any valid character will also set the JsTable into editing state automatically (as of version 0.4.5). We can also double click on a cell (may be triple click) if we want to edit the cell. But to end the editing state, still use the keyboard. Clicking on another cell, when the active cell is edited, will end the editing state of current active cell and move the active cell to the cell has just been clicked. When on the number column, you may only press the valid character for a number. So do the date column and datetime column.
  • Checkbox (element <INPUT type=checkbox>)
    To change the state of the checkbox, press Enter or Space. Clicking on the cell will also change the checkbox" state.
  • Combobox (element <SELECT>)
    To edit, press Enter and then going into editing state. Use up arrow and down arrow, to change the option. Press enter again, to end the editing state. Key F2 can also be used but key Esc may not be useful in all browsers. Esc may reset the option. Another way to change the option, when in editing state, press Alt+down_arrow, the the combobox will reveal its option, choose option by pressing down arrow or up arrow and then press Enter to end the editing state. This way doesn"t run perfectly in all browsers.
    If you want to use mouse, do with usual steps: click on the combobox and choose the option.
  • Link
    The Link cannot be edited but only execute its link"s target. To execute its target, press Enter or click the Link.

This software is licensed under GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License or (at your option) any later version.
See the JsTable"s <a href="./JsTable.js" target="_blank">source</a> and the <a href="./JsTable_Documentation.html" target="_blank">documentation</a>.
Send the bugs report to <a href="mailto:almulyana@yahoo.ru">almulyana@yahoo.ru</a>.

Copyright © 2005 AT Mulyana

</body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/JsTable20050725.zip">JsTable20050725.zip( 34 k)</a>


Table row style with "mouse roll over" effect

   <source lang="html4strict">

<html> <head> <title>nrsTable Examples</title> <style type="text/css"> body { background-color: #ffff99; } .code_display { background-color: #b9b9ac;

         border: 1px solid #9d9d94;

}

  1. example4 td.dataTD0 { letter-spacing: 2; }
  2. example4 td.dataTD1 { text-decoration: underline; }
  3. example4 td.dataTD2 { background-color: grey; }

</style> <script language="JavaScript"> /* natcompare.js -- Perform "natural order" comparisons of strings in JavaScript. Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre) Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be> Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion. Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.ru> The Java version was based on the C version by Martin Pool. Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.

  • /

function isWhitespaceChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode <= 32 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function isDigitChar(a) {

   var charCode;
   charCode = a.charCodeAt(0);
   if ( charCode >= 48  && charCode <= 57 )
   {
       return true;
   }
   else
   {
       return false;
   }

} function compareRight(a,b) {

   var bias = 0;
   var ia = 0;
   var ib = 0;
   var ca;
   var cb;
   // The longest run of digits wins.  That aside, the greatest
   // value wins, but we can"t know that it will until we"ve scanned
   // both numbers to know that they have the same magnitude, so we
   // remember it in BIAS.
   for (;; ia++, ib++) {
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       if (!isDigitChar(ca)
               && !isDigitChar(cb)) {
           return bias;
       } else if (!isDigitChar(ca)) {
           return -1;
       } else if (!isDigitChar(cb)) {
           return +1;
       } else if (ca < cb) {
           if (bias == 0) {
               bias = -1;
           }
       } else if (ca > cb) {
           if (bias == 0)
               bias = +1;
       } else if (ca == 0 && cb == 0) {
           return bias;
       }
   }

} function natcompare(a,b) {

   var ia = 0, ib = 0;
 var nza = 0, nzb = 0;
 var ca, cb;
 var result;
   while (true)
   {
       // only count the number of zeroes leading the last number compared
       nza = nzb = 0;
       ca = a.charAt(ia);
       cb = b.charAt(ib);
       // skip over leading spaces or zeros
       while ( isWhitespaceChar( ca ) || ca =="0" ) {
           if (ca == "0") {
               nza++;
           } else {
               // only count consecutive zeroes
               nza = 0;
           }
           ca = a.charAt(++ia);
       }
       while ( isWhitespaceChar( cb ) || cb == "0") {
           if (cb == "0") {
               nzb++;
           } else {
               // only count consecutive zeroes
               nzb = 0;
           }
           cb = b.charAt(++ib);
       }
       // process run of digits
       if (isDigitChar(ca) && isDigitChar(cb)) {
           if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) {
               return result;
           }
       }
       if (ca == 0 && cb == 0) {
           // The strings compare the same.  Perhaps the caller
           // will want to call strcmp to break the tie.
           return nza - nzb;
       }
       if (ca < cb) {
           return -1;
       } else if (ca > cb) {
           return +1;
       }
       ++ia; ++ib;
   }

} </script> <script language="JavaScript"> /**

* Copyright 2005 New Roads School
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**

* \class nrsTable
* This describes the nrsTable, which is a table created in JavaScript that is
* able to be sorted and displayed in different ways based on teh configuration
* parameters passed to it. 
* to create a new table one only needs to call the setup function like so:
*
 * nrsTable.setup(
 * {
 *   table_name: "table_container",
 *   table_data: d,
 *   table_header: h
 * }
 * );
 * 
* Where table_name is the name of the table to build.  THis must be defined in
* your HTML by putting a table declaration, such as *
. This will declare where your table will be shown.
* All sorts of parameters can be customized here.  For details look at the
* function setup.
* \see setup
*/

/**

* Debug function.  Set debug to tru to view messages.
* \param msg Message to display in an alert.
*/

debug = false; function DEBUG(msg) {

 if(debug)
   alert(msg);

} /**

* There is a memory leak problem that I can"t seem to fix.  I"m attching 
* something that I found from Aaron Boodman, which will clean up all the
* memory leaks in the page (this can be found at http://youngpup.net/2005/0221010713
* ). This is a little clunky, but it will do till I track this problem.
* Oh, and this problem only occurrs is IE.
*/

if (window.attachEvent) {

   var clearElementProps = [
   "data",
       "onmouseover",
       "onmouseout",
       "onmousedown",
       "onmouseup",
       "ondblclick",
       "onclick",
       "onselectstart",
       "oncontextmenu"
   ];
   window.attachEvent("onunload", function() {
       var el;
       for(var d = document.all.length;d--;){
           el = document.all[d];
           for(var c = clearElementProps.length;c--;){
               el[clearElementProps[c]] = null;
           }
       }
   });

}

/**

* This is the constructor.
* It only needs the name of the table.  This should never be called directly, 
* instead use setup function.
* \param table The name of the table to create.
* \see setup
*/

function nrsTable(table) {

 this.my_table = table;
 this.field_to_sort = 0;
 this.field_asc = true;

} new nrsTable(""); /**

* This function is responsible for setting up an nrsTable.  All the parameters
* can be configured directly from this function.  The params array of this 
* function is a class (or a associative array, depending on how you want to
* look at it) with the following possible parameters:
*   - table_name: required.  The id of the table tag.
*  - table_header: required.  An array containing the header names.
*   - table_data: optional.  A 2D array of strings containing the cell contents.
*  - caption: optional.  A caption to include on the table.
*  - row_links: optional.  An array with hyperlinks per row.  Must be a javascript function.
*  - cell_links: optional.  A 2D array with links on every cell.  Must be a javascript function
*  - up_icon: optional.  A path to the ascending sort arrow.
*  - down_icon: optional.  A path to the descending sort arrow.
*  - prev_icon: optional.  A path to the previous page icon in the navigation.
*  - next_icon: optional.  A path to the next page icon in the navigation.
*  - rew_icon: optional.  A path to the first page icon in the navigation.
*  - fwd_icon: optional.  A path to the last page icon in the navigation.
*  - rows_per_page: optional.  The number of rows per page to display at any one time.
*  - display_nav: optional.  Displays navigation (prev, next, first, last)
*  - foot_headers: optional.  Whether to display th eheaders at the foot of the table.
*  - header_color: optional.  The color of the header cells.  Will default to whatever is defined in CSS.
*  - even_cell_color: optional.  The color of the even data cells.  Will default to whatever is defined in CSS.
*  - odd_cell_color: optional.  The color of the odd data cells.  Will default to whatever is defined in CSS.
*  - footer_color: optional.  The color of the footer cells.  Will default to whatever is defined in CSS.
*  - hover_color: optional.  The color tha a row should turn when the mouse is over it.
*  - padding: optional.  Individual cell padding, in pixels.
*  - natural_compare: optional.  Uses the natural compare algorithm (separate from this program) to sort.
*  - disable_sorting: optional.  An array specifying the columns top disable sorting on (0 is the first column).
*
* \params params An array as described above.
*/

nrsTable.setup = function(params) {

 //here we assign all the veriables that we are passed, or the defaults if 
 //they are not defined.
 //Note that the only requirements are a table name and a header.
 if(typeof params["table_name"] == "undefined")
 {
   alert("Error! You must supply a table name!");
   return null;
 }
 if(typeof params["table_header"] == "undefined")
 {
   alert("Error! You must supply a table header!");
   return null;
 }
 
 //check if the global array exists, else create it.
 if(typeof(nrsTables) == "undefined")
 {
   eval("nrsTables = new Array();");
 }
 nrsTables[params["table_name"]] = new nrsTable(params["table_name"]);
 nrsTables[params["table_name"]].heading = params["table_header"].concat();
 
 //now the non-required elements.  Data elements first
 nrsTables[params["table_name"]].data = (typeof params["table_data"] == "undefined" || !params["table_data"])? null: params["table_data"].concat();
 nrsTables[params["table_name"]].caption = (typeof params["caption"] == "undefined")? null: params["caption"];
 nrsTables[params["table_name"]].row_links = (typeof params["row_links"] == "undefined" || !params["row_links"])? null: params["row_links"].concat();
 nrsTables[params["table_name"]].cell_links = (typeof params["cell_links"] == "undefined" || !params["row_links"])? null: params["cell_links"].concat();
 
 //these are the icons.
 nrsTables[params["table_name"]].up_icon = (typeof params["up_icon"] == "undefined")? "up.gif": params["up_icon"];
 nrsTables[params["table_name"]].down_icon = (typeof params["down_icon"] == "undefined")? "down.gif": params["down_icon"];
 nrsTables[params["table_name"]].prev_icon = (typeof params["prev_icon"] == "undefined")? "left.gif": params["prev_icon"];
 nrsTables[params["table_name"]].next_icon = (typeof params["next_icon"] == "undefined")? "right.gif": params["next_icon"];
 nrsTables[params["table_name"]].rew_icon = (typeof params["rew_icon"] == "undefined")? "first.gif": params["rew_icon"];
 nrsTables[params["table_name"]].fwd_icon = (typeof params["fwd_icon"] == "undefined")? "last.gif": params["fwd_icon"];
 
 //now the look and feel options.
 nrsTables[params["table_name"]].rows_per_page = (typeof params["rows_per_page"] == "undefined")? -1: params["rows_per_page"];
 nrsTables[params["table_name"]].page_nav = (typeof params["page_nav"] == "undefined")? false: params["page_nav"];
 nrsTables[params["table_name"]].foot_headers = (typeof params["foot_headers"] == "undefined")? false: params["foot_headers"];
 nrsTables[params["table_name"]].header_color = (typeof params["header_color"] == "undefined")? null: params["header_color"];
 nrsTables[params["table_name"]].even_cell_color = (typeof params["even_cell_color"] == "undefined")? null: params["even_cell_color"];
 nrsTables[params["table_name"]].odd_cell_color = (typeof params["odd_cell_color"] == "undefined")? null: params["odd_cell_color"];
 nrsTables[params["table_name"]].footer_color = (typeof params["footer_color"] == "undefined")? null: params["footer_color"];
 nrsTables[params["table_name"]].hover_color = (typeof params["hover_color"] == "undefined")? null: params["hover_color"];
 nrsTables[params["table_name"]].padding = (typeof params["padding"] == "undefined")? null: params["padding"];
 nrsTables[params["table_name"]].natural_compare = (typeof params["natural_compare"] == "undefined")? false: true;
 nrsTables[params["table_name"]].disable_sorting = 
   (typeof params["disable_sorting"] == "undefined")? false: "." + params["disable_sorting"].join(".") + ".";
 //finally, build the table
 nrsTables[params["table_name"]].buildTable();

};

/**

* This is the Javascript quicksort implementation.  This will sort the 
* this.data and the this.data_nodes based on the this.field_to_sort parameter.
* \param left The left index of the array.
* \param right The right index of the array
*/

nrsTable.prototype.quickSort = function(left, right) {

 if(!this.data || this.data.length == 0)
   return;
 var i = left;
 var j = right;
 var k = this.data[Math.round((left + right) / 2)][this.field_to_sort];
 while(j > i)
 {
   if(this.field_asc)
   {
     while(this.data[i][this.field_to_sort].toLowerCase() < k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() > k.toLowerCase())
       j--;
   }
   else
   {
     while(this.data[i][this.field_to_sort].toLowerCase() > k.toLowerCase())
       i++;
     while(this.data[j][this.field_to_sort].toLowerCase() < k.toLowerCase())
       j--;
   }
   if(i <= j )
   {
     //swap both values
     //sort data
     var temp = this.data[i];
     this.data[i] = this.data[j];
     this.data[j] = temp;
     
     //sort contents
     var temp = this.data_nodes[i];
     this.data_nodes[i] = this.data_nodes[j];
     this.data_nodes[j] = temp;
     i++;
     j--;
   }
 }
 if(left < j)
   this.quickSort(left, j);
 if(right > i)
   this.quickSort(i, right);

} /**

* This is the Javascript natural sort function.  Because of some obscure JavaScript
* quirck, we could not do quicsort while calling natcompare to compare, so this
* function will so a simple bubble sort using the natural compare algorithm.
*/

nrsTable.prototype.natSort = function() {

 if(!this.data || this.data.length == 0)
   return;
 var swap;
 for(i = 0; i < this.data.length - 1; i++)
 {
   for(j = i; j < this.data.length; j++)
   {
     if(!this.field_asc)
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == -1)
         swap = true;
       else
         swap = false;
     }
     else
     {
       if(natcompare(this.data[i][this.field_to_sort].toLowerCase(), 
         this.data[j][this.field_to_sort].toLowerCase()) == 1)
         swap = true;
       else
         swap = false;
     }
     if(swap)
     {
       //swap both values
       //sort data
       var temp = this.data[i];
       this.data[i] = this.data[j];
       this.data[j] = temp;
       
       //sort contents
       var temp = this.data_nodes[i];
       this.data_nodes[i] = this.data_nodes[j];
       this.data_nodes[j] = temp;
     }
   }
 }

} /**

* This function will recolor all the the nodes to conform to the alternating 
* row colors.
*/

nrsTable.prototype.recolorRows = function() {

 if(this.even_cell_color || this.odd_cell_color)
 {
   DEBUG("Recoloring Rows. length = " + this.data_nodes.length);
   for(var i = 0; i < this.data_nodes.length; i++)
   {
     if(i % 2 == 0)
     {
       if(this.even_cell_color)
         this.data_nodes[i].style.backgroundColor = this.even_cell_color;
       this.data_nodes[i].setAttribute("id", "even_row");
     }
     else
     {
       if(this.odd_cell_color)
         this.data_nodes[i].style.backgroundColor = this.odd_cell_color;
       this.data_nodes[i].setAttribute("id", "odd_row");
     }
   }
 }

} /**

* This function will create the Data Nodes, which are a reference to the table
* rows in the HTML.
*/

nrsTable.prototype.createDataNodes = function() {

 if(this.data_nodes)
   delete this.data_nodes;
 this.data_nodes = new Array();
 if(!this.data)
   return;
 for(var i = 0; i < this.data.length; i++)
 {
   var curr_row = document.createElement("TR");
   
   for(var j = 0; j < this.data[i].length; j++)
   {
     var curr_cell = document.createElement("TD");
     //do we need to create links on every cell?
     if(this.cell_links)
     {
       var fn = new Function("", this.cell_links[i][j]);
       curr_cell.onclick = fn;
       curr_cell.style.cursor = "pointer";
     }
     //workaround for IE
     curr_cell.setAttribute("className", "dataTD" + j);
     //assign the padding
     if(this.padding)
     {
       curr_cell.style.paddingLeft = this.padding + "px";
       curr_cell.style.paddingRight = this.padding + "px";
     }
     curr_cell.appendChild(document.createTextNode(this.data[i][j]));
     curr_row.appendChild(curr_cell);
   }
   //do we need to create links on every row?
   if(!this.cell_links && this.row_links)
   {
     var fn = new Function("", this.row_links[i]);
     curr_row.onclick = fn;
     curr_row.style.cursor = "pointer";
   }
   //sets the id for odd and even rows.
   if(i % 2 == 0)
   {
     curr_row.setAttribute("id", "even_row");
     if(this.even_cell_color)
       curr_row.style.backgroundColor = this.even_cell_color;
   }
   else
   {
     curr_row.setAttribute("id", "odd_row");
     if(this.odd_cell_color)
       curr_row.style.backgroundColor = this.odd_cell_color;
   }
   if(this.hover_color)
   {
     curr_row.onmouseover = new Function("", "this.style.backgroundColor="" + this.hover_color + "";");
     curr_row.onmouseout = new Function("", "this.style.backgroundColor=(this.id=="even_row")?"" + 
               this.even_cell_color + "":"" + this.odd_cell_color + "";");
   }
   this.data_nodes[i] = curr_row;
 }

} /**

* This function will update the nav page display.
*/

nrsTable.prototype.updateNav = function() {

 if(this.page_nav)
 {
   var p = 0;
   if(this.foot_headers)
     p++;
   var t = document.getElementById(this.my_table);
   var nav = t.tFoot.childNodes[p];
   if(nav)
   {
     var caption = t.tFoot.childNodes[p].childNodes[0].childNodes[2];
     caption.innerHTML = "Page " + (this.current_page + 1) + " of " + this.num_pages;
   }
   else
   {
     if(this.num_pages > 1)
     {
       this.insertNav();
       nav = t.tFoot.childNodes[p];
     }
   }
   if(nav)
   {
     if(this.current_page == 0)
       this.hideLeftArrows();
     else
       this.showLeftArrows();
     
     if(this.current_page + 1 == this.num_pages)
       this.hideRightArrows();
     else
       this.showRightArrows();
   }
 }

} /**

* This function will flip the sort arrow in place.  If a heading is used in the
* footer, then it will flip that one too.
*/

nrsTable.prototype.flipSortArrow = function() {

 this.field_asc = !this.field_asc;
 //flip the arrow on the heading.
 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 if(this.field_asc)
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
 else
   heading.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 //is there a heading in the footer?
 if(this.foot_headers)
 {
   //yes, so flip that arrow too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   if(this.field_asc)
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.up_icon);
   else
     footer.getElementsByTagName("IMG")[0].setAttribute("src", this.down_icon);
 }

} /**

* This function will move the sorting arrow from the place specified in 
* this.field_to_sort to the passed parameter.  It will also set 
* this.field_to_sort to the new value.  It will also do it in the footers, 
* if they exists.
* \param field The new field to move it to.
*/

nrsTable.prototype.moveSortArrow = function(field) {

 var heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[this.field_to_sort];
 var img = heading.removeChild(heading.getElementsByTagName("IMG")[0]);
 heading = document.getElementById(this.my_table).tHead.childNodes[0].childNodes[field];
 heading.appendChild(img);
 //are there headers in the footers.
 if(this.foot_headers)
 {
   //yes, so switch them too.
   var footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[this.field_to_sort];
   var img = footer.removeChild(footer.getElementsByTagName("IMG")[0]);
   footer = document.getElementById(this.my_table).tFoot.childNodes[0].childNodes[field];
   footer.appendChild(img);
 }
 //finally, set the field to sort by.
 this.field_to_sort = field;

} /**

* This function completely destroys a table.  Should be used only when building
* a brand new table (ie, new headers).  Else you should use a function like
* buildNewData which only deletes the TBody section.
*/

nrsTable.prototype.emptyTable = function() {

 var t = document.getElementById(this.my_table);
 while(t.childNodes.length != 0)
   t.removeChild(t.childNodes[0]);

}; /**

* This function builds a brand new table from scratch.  This function should
* only be called when a brand new table (with headers, footers, etc) needs
* to be created.  NOT when refreshing data or changing data.
*/

nrsTable.prototype.buildTable = function() {

 //reset the sorting information.
 this.field_to_sort = 0;
 this.field_asc = true;
 
 //remove the nodes links.
 delete this.data_nodes;
 
 //do we have to calculate the number of pages?
 if(this.data && this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.current_page = 0;
 }
 
 //blank out the table.
 this.emptyTable();
 
 //this is the table that we will be using.
 var table = document.getElementById(this.my_table);
 
 //is there a caption?
 if(this.caption)
 {
   var caption = document.createElement("CAPTION");
   caption.setAttribute("align", "top");
   caption.appendChild(document.createTextNode(this.caption));
   table.appendChild(caption);
 }
 
 //do the heading first
 var table_header = document.createElement("THEAD");
 var table_heading = document.createElement("TR");
 //since this is a new table the first field is what"s being sorted.
 var curr_cell = document.createElement("TH");
 var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + 0 + ");");
 if(!this.disable_sorting || this.disable_sorting.indexOf(".0.") == -1)
   curr_cell.onclick = fn;
 if(this.header_color)
   curr_cell.style.backgroundColor = this.header_color;
 curr_cell.style.cursor = "pointer";
 var img = document.createElement("IMG");
 img.setAttribute("src", this.up_icon);
 img.setAttribute("border", "0");
 img.setAttribute("height", "8");
 img.setAttribute("width", "8");
 curr_cell.appendChild(document.createTextNode(this.heading[0]));
 curr_cell.appendChild(img);
 table_heading.appendChild(curr_cell);
 //now do the rest of the heading.
 for(var i = 1; i < this.heading.length; i++)
 {
   curr_cell = document.createElement("TH");
   var fn = new Function("", "nrsTables["" + this.my_table + ""].fieldSort(" + i + ");");
   if(!this.disable_sorting || this.disable_sorting.indexOf("." + i + ".") == -1)
     curr_cell.onclick = fn;
   if(this.header_color)
     curr_cell.style.backgroundColor = this.header_color;
   curr_cell.style.cursor = "pointer";
   //build the sorter
   curr_cell.appendChild(document.createTextNode(this.heading[i]));
   table_heading.appendChild(curr_cell);
 }
 table_header.appendChild(table_heading);
 
 //now the content
 var table_body = document.createElement("TBODY");
 this.createDataNodes();
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
   this.recolorRows();
 }
 //finally, the footer
 var table_footer = document.createElement("TFOOT");
 if(this.foot_headers)
 {
   table_footer.appendChild(table_heading.cloneNode(true));
 }
 
 if(this.page_nav && this.num_pages > 1)
 {
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table_footer.appendChild(nav);
 }
 
 if(this.footer_color)
 {
   for(var i = 0; i < table_footer.childNodes.length; i++)
     table_footer.childNodes[i].style.backgroundColor = this.footer_color;
 }
 
 //append the data
 table.appendChild(table_header);
 table.appendChild(table_body);
 table.appendChild(table_footer);
 if(this.data)
 {
   if(this.natural_compare)
     this.natSort(0, this.data.length - 1);
   else
     this.quickSort(0, this.data.length - 1);
 }
 this.refreshTable();

}; /**

* This function will remove the elements in teh TBody section of the table and
* return an array of references of those elements.  This array can then be 
* sorted and re-inserted into the table.
* \return An array to references of the TBody contents.
*/

nrsTable.prototype.extractElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var nodes = new Array();
 var i = 0;
 while(tbody.childNodes.length > 0)
 {
   nodes[i] = tbody.removeChild(tbody.childNodes[0]);
   i++;
 }
 return nodes;

} /**

* This function will re-insert an array of elements into the TBody of a table.
* Note that the array elements are stored in the this.data_nodes reference.
*/

nrsTable.prototype.insertElements = function() {

 var tbody = document.getElementById(this.my_table).tBodies[0];
 var start = 0;
 var num_elements = this.data_nodes.length;
 if(this.rows_per_page != -1)
 {
   start = this.current_page * this.rows_per_page;
   num_elements = (this.data_nodes.length - start) > this.rows_per_page?
             this.rows_per_page + start:
             this.data_nodes.length;
 }
 DEBUG("start is " + start + " and num_elements is " + num_elements);
 for(var i = start; i < num_elements; i++)
 {
   tbody.appendChild(this.data_nodes[i]);
 }

} /**

* This function will sort the table"s data by a specific field.  The field 
* parameter referes to which field index should be sorted.
* \param field The field index which to sort on.
*/

nrsTable.prototype.fieldSort = function(field) {

 if(this.field_to_sort == field)
 {
   //only need to reverse the array.
   if(this.data)
   {
     this.data.reverse();
     this.data_nodes.reverse();
   }
   //flip the arrow on the heading.
   this.flipSortArrow();
 }
 else
 {
   //In this case, we need to sort the array.  We"ll sort it last, first 
   //make sure that the arrow images are set correctly.
   this.moveSortArrow(field);
   //finally, set the field to sort by.
   this.field_to_sort = field;
   if(this.data)
   {
     //we"ll be using our implementation of quicksort
     if(this.natural_compare)
       this.natSort(0, this.data.length - 1);
     else
       this.quickSort(0, this.data.length - 1);
   }
 }
 //finally, we refresh the table.
 this.refreshTable();

}; /**

* This function will refresh the data in the table.  This function should be
* used whenever the nodes have changed, or when chanign pages.  Note that 
* this will NOT re-sort.
*/

nrsTable.prototype.refreshTable = function() {

 this.extractElements();
 this.recolorRows();
 this.insertElements();
 //finally, if there is a nav, upate it.
 this.updateNav();

} /**

* This function will advance a page.  If we are already at the last page, then 
* it will remain there.
*/

nrsTable.prototype.nextPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page + 1 != this.num_pages)
 {
   this.current_page++;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go back a page.  If we are already at the first page, then 
* it will remain there.
*/

nrsTable.prototype.prevPage = function() {

 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);
 if(this.current_page != 0)
 {
   this.current_page--;
   this.refreshTable();
 }
 DEBUG("current page is " + this.current_page + " and num_pages is " + this.num_pages);

} /**

* This function will go to the first page.
*/

nrsTable.prototype.firstPage = function() {

 if(this.current_page != 0)
 {
   this.current_page = 0;
   this.refreshTable();
 }

} /**

* This function will go to the last page.
*/

nrsTable.prototype.lastPage = function() {

 DEBUG("lastPage(), current_page: " + this.current_page + " and num_pages: " + this.num_pages);
 if(this.current_page != (this.num_pages - 1))
 {
   this.current_page = this.num_pages - 1;
   this.refreshTable();
 }

} /**

* This function will go to a specific page.  valid values are pages 1 to 
* however many number of pages there are.
* \param page The page number to go to.
*/

nrsTable.prototype.gotoPage = function(page) {

 page--;
 if(page >=0 && page < this.num_pages)
 {
   this.current_page = page;
   this.refreshTable();
 }

} /**

* This function can be used to change the number of entries per row displayed
* on the fly.
* \param entries The number of entries per page.
*/

nrsTable.prototype.changeNumRows = function(entries) {

 if(entries > 0)
 {
   this.rows_per_page = entries;
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   this.refreshTable();
 }

} /**

* This function will take in a new data array and , optionally, a new cell_link
* array OR a new row_link array.  Only one will be used, with the cell_link
* array taking precedence.  It will then re-build the table with the new data
* array.
* \param new_data This is the new data array.  This is required.
* \param cell_links This is the new cell links array, a 2D array for each cell.
* \param row_links This is the new row links array, a 1D array for each row.
*/

nrsTable.prototype.newData = function(new_data, cell_links, row_links) {

 //extract the elements from teh table to clear the table.
 this.extractElements();
 //now delete all the data related to this table.  I do this so that 
 //(hopefully) the memory will be freed.  This is realy needed for IE, whose
 //memory handling is almost non-existant
 delete this.data;
 delete this.data_nodes;
 delete this.cell_links;
 delete this.row_links
 //now re-assign.
 this.data = new_data;
 this.cell_links = cell_links;
 this.row_links = row_links;
 if(this.rows_per_page != -1)
 {
   //we do.
   this.num_pages = Math.ceil(this.data.length / this.rows_per_page);
   if(this.num_pages <= 1 && this.page_nav)
     this.removeNav();
   else if(this.page_nav)
     this.insertNav();
   this.current_page = 0;
 }
 this.createDataNodes();
 if(this.field_to_sort != 0)
   this.moveSortArrow(0);
 if(!this.field_asc)
   this.flipSortArrow();
 this.insertElements();
 this.updateNav();

} /**

* This function will remove the NAV bar (if one exists) from the table.
*/

nrsTable.prototype.removeNav = function() {

 if(this.page_nav)
 {
   //in this case, remove the nav from the existing structure.
   var table = document.getElementById(this.my_table);
   var p = 0;
   if(this.foot_headers)
     p++;
   var nav = table.tFoot.childNodes[p];
   if(nav)
   {
     table.tFoot.removeChild(nav);
     delete nav;
   }
 }

} /**

* This function wil re-insert the nav into the table.
*/

nrsTable.prototype.insertNav = function() {

 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 if(this.page_nav && !table.tFoot.childNodes[p])
 {
   //this means there should be a nav and there isn"t one.
   //print out the page navigation
   //first and previous page
   var nav = document.createElement("TR");
   var nav_cell = document.createElement("TH");
   nav_cell.colSpan = this.heading.length;
   
   var left = document.createElement("DIV");
   if(document.attachEvent)
     left.style.styleFloat = "left";
   else
     left.style.cssFloat = "left";
   var img = document.createElement("IMG");
   img.setAttribute("src", this.rew_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].firstPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   left.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.prev_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].prevPage();");
   img.style.cursor = "pointer";
   left.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(left);
   
   //next and last pages
   var right = document.createElement("DIV");
   if(document.attachEvent)
     right.style.styleFloat = "right";
   else
     right.style.cssFloat = "right";
   img = document.createElement("IMG");
   img.setAttribute("src", this.next_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "nrsTables["" + this.my_table + ""].nextPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //hack to space the arrows, cause IE is absolute crap
   right.appendChild(document.createTextNode(" "));
   img = document.createElement("IMG");
   img.setAttribute("src", this.fwd_icon);
   img.setAttribute("border", "0");
   img.setAttribute("height", "10");
   img.setAttribute("width", "10");
   img.onclick = new Function("", "JavaScript:nrsTables["" + this.my_table + ""].lastPage();");
   img.style.cursor = "pointer";
   right.appendChild(img);
   //apend it to the cell
   nav_cell.appendChild(right);
   
   //page position
   var pos = document.createElement("SPAN");
   pos.setAttribute("id", "nav_pos");
   pos.appendChild(document.createTextNode("Page " + 
           (this.current_page + 1) + " of " + this.num_pages));
   //append it to the cell.
   nav_cell.appendChild(pos);
   
   nav.appendChild(nav_cell);
   //append it to the footer
   table.tFoot.appendChild(nav);
 }

} /**

* This function will hide the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.hideLeftArrows = function() {

 if(!this.page_nav)
   return;
 var myTable = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = myTable.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "none";

} /**

* This function will show the previous arrow and the rewind arrows from the
* nav field.
*/

nrsTable.prototype.showLeftArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[0].style.display = "block";

} /**

* This function will hide the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.hideRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "none";

} /**

* This function will show the next arrow and the fast foward arrows from the
* nav field.
*/

nrsTable.prototype.showRightArrows = function() {

 if(!this.page_nav)
   return;
 table = document.getElementById(this.my_table);
 var p = 0;
 if(this.foot_headers)
   p++;
 var nav = table.tFoot.childNodes[p];
 nav.childNodes[0].childNodes[1].style.display = "block";

} </script> </head> <body>

nrsTable Examples


<script language="JavaScript"> var header = new Array("First Name", "Last Name", "Income", "Date Hired"); var data = new Array( new Array ( "Joseph", "Smith", "$35,000", "2000"), new Array ( "Aaron", "Zelzet", "$45,000", "1997"), new Array ( "Michael", "Doe", "$55,000", "1965"), new Array ( "Cindy", "Perez", "$44,345", "2004"), new Array ( "Robert", "Williams", "$48,234", "1990"), new Array ( "William", "Cohen", "$12,234", "2005"), new Array ( "David", "Gross", "$34,563", "1998"), new Array ( "Linda", "Mendez", "$46,975", "1988"), new Array ( "Karen", "Anderson", "$124,345", "1978"), new Array ( "Veronica", "O\"Reiley", "$89,034", "1968") ); var links = new Array( "alert("Row1");",

           "alert("Row2");",
           "alert("Row3");",
           "alert("Row4");",
           "alert("Row5");",
           "alert("Row6");",
           "alert("Row7");",
           "alert("Row8");",
           "alert("Row9");",
           "alert("Row10");"
         );

nrsTable.setup( { table_name: "example2", table_header: header, table_data: data, up_icon: "nrstableimg/up.gif", down_icon: "nrstableimg/down.gif", header_color: "#53c2f4", even_cell_color: "#b9b9ac", odd_cell_color: "#d4fbf6", hover_color: "#ccff99", natural_compare: true } ); </script> </body> </html>


 </source>
   
  

<A href="http://www.wbex.ru/Code/JavaScriptDownload/nrsTable-0.3.3.zip">nrsTable-0.3.3.zip( 31 k)</a>


Table row with mouse roll over

   <source lang="html4strict">

<HTML> <HEAD>

 <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 <META http-equiv="Author" content="Charles Dickens" />
 <TITLE> HTML Grid Demo Ver 0.1.1</title>
 <STYLE type="text/css">
   input { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 9px; padding: 0px; color:black; backgroundcolor: #FFFFEE}
   td { border-style: solid; border-width: 1px; font-family: verdana, arial, sans-serif; font-size: 10px; padding: 0px;}
 
 </STYLE>
 <SCRIPT type="text/javascript">

/*\ |*| Version : 0.92 |*| Author  : Chaitanya Yinti |*| Contact : yinti@users.sourceforge.net |*| WebSite : http://dhtmlgrid.sourceforge.net/ |*| |*| Feel free to use this script under the terms of the GNU General Public |*| License, as long as you do not remove or alter this notice. \*/

 /*************************************\
 |       Start of Config Param         |
 \*************************************/
 // Color used for hilighting a selected row
 var clrHilight = "blue";
 // Set this to false if you want "click to select" and
 // "doubleclick to Edit" mode
 var blnPointToSelect = true;
 // Full path of the blank image used to hide the sort images 
 var strBlankImage = "blank.gif";
 // Full path of the up image used on sort asc
 var strUpImage = "up.gif";  
 // Full path of the up image used on sort des
 var strDownImage = "down.gif";
 // The width of the images used to indicate the asc/des sort
 var intImgWidth = 12;
 // The height of the images used to indicate the asc/des sort
 var intImgHeight = 13;  
 /*************************************\
 |           End of Config Param       |
 \*************************************/
 /*************************************\
 |           Globals start             |
 \*************************************/
 // Stores the last used object during sort
 var objLastClick = -1;
 // Stores the text being edited
 var txtOld = "";
 // Stores the total table width
 var intTotalWidth = 0;
 // Stores the flag used by capturemouse
 var blnMouseOver = false;  
 // Stores the div being moved
 var objDivToMove = null;
 // Stores the number of coloumns; initialized in init ()
 var intColCount = 0;
 // Stores the row element currently selected
 var objRowSelected = null;
 //THE element which holds the table... 
 var element = null;
 /*************************************\
 |           Globals end               |
 \*************************************/
 /*********************TODO*****************************\
  prototype setCapture/releaseCapture PROPERLY
  Get rid of isIE, isNS4 completely ...
  Extend keycapture to navigate the table on up/down arrow
  Fix escape/unescape on text change
 \******************************************************/
   
 /*\
 |*| The entry point. This will 
 |*|    Attache all the appropriate functions to the table
 |*|    Call function to create the IMG elems used during the sorting
 |*|    call function to init the DIV elems that are used for moving
 |*|    call function to init the DIV elems used for about box
 \*/
 function init (tableName)
 {
   //Handle all javascript errors 
   window.onerror = handleError;
   isIE = (navigator.appVersion.indexOf ("MSIE") != -1);
   isNS4 = (document.layers) ? true : false;
   isNS6 = (!document.layers) && (navigator.userAgent.indexOf ("Netscape")!=-1);
   if ((isNS4) && (!isNS6)) alert ("Currently only supports NN 6 and above");
   if (document.getElementById)
     element = document.getElementById (tableName);
   else  //TODO: Need to test this piece of code still. Happens only in NN4 so far 
     eval (element = "document." + tableName);
   if (element == null)
     return alert ("Error: Not able to get table element ");
   if (element.tagName != "TABLE")
     return alert ("Error: Not able to control element " + element.tagName);
   initNNFunctions ();
   if (blnPointToSelect)
   {
     element.attachEvent ("onmouseover", selectRow);
     element.attachEvent ("onclick", onClickCell);
   }
   else
   {
     element.attachEvent ("onclick", selectRow);
     element.attachEvent ("ondblclick", onClickCell);
   }
   document.attachEvent ("onkeydown" , captureDelKey);
   //Need this fix for IE only .. so element.focus is stubbed in NN
   element.focus ();
 
   initSortImages ();
   initDiv ();
   initAbout ();
 }
 /*\
 |*| This function removes the textnodes from the table rows.
 |*| This cleanup work is needed to get rid of the EXTRA textnodes that NN gives
 \*/
 function removeTextNodes (t)
 {
   for (var i = 0; t.childNodes[i] ; i++)
   {
     if (!t.childNodes[i].tagName)
     {
        t.childNodes[i].parentNode.removeChild (t.childNodes[i]);
     }
     else
     {
       for (var j = 0; t.childNodes[i].childNodes[j] ; j++)
       {
         if (!t.childNodes[i].childNodes[j].tagName) 
           t.childNodes[i].childNodes[j].parentNode.removeChild (t.childNodes[i].childNodes[j]);
       }
     }
   }
 }
 /*\
 |*| This function adds the blank images to the head row of the table
 \*/
 function initSortImages ()
 {
   if (!element.tHead) return;
   removeTextNodes (element.tHead);
   var theadrow = element.tHead.childNodes[0]; //Assume just one Head row
   if (isIE) theadrow.style.cursor = "hand";
   else theadrow.style.cursor = "pointer";
   removeTextNodes (theadrow.parentNode);
   intColCount = theadrow.childNodes.length;
   for (var i = 0; i < intColCount; i++) 
   {
     objImg = document.createElement ("IMG");
     objImg.setAttribute ("src", strBlankImage);
     objImg.setAttribute ("id", "srtImg" + i);
     objImg.setAttribute ("width", intImgWidth);
     objImg.setAttribute ("height", intImgHeight);
     objImg.setAttribute ("align", "right");
     objImg.setAttribute ("valign", "middle");
     objImg.setAttribute ("border", 0);
     clickCell = theadrow.childNodes[i];
     clickCell.selectIndex = i;
     clickCell.insertAdjacentElement ("afterBegin", objImg);
     clickCell.style.width = clickCell.width;
   }
 }
 /*\
 |*| This will only be called once during initIALIZATION
 |*| This will create the DIV elems at the end of each col and
 |*| attach all the functions needed to resize the coloumns
 \*/
 function initDiv ()
 {
   var objLast = element, objDiv;
   removeTextNodes (element.tBodies[0]);
   for (var i = 1; i <= intColCount; i++)
   {  
     objDiv = document.createElement ("DIV");
     objDiv.setAttribute ("id", "DragMark" + (i - 1));
     objDiv.setAttribute ("name",  i);    //Used to track the TDs that have to be moved
     objDiv.style.position = "absolute";
     objDiv.style.top = 0; 
     var objTD = element.tHead.childNodes[0].childNodes[i - 1];
     if (!objTD || objTD.tagName != "TD") return;
     var intColWidth = (getRealPos (objTD) - 0) + (objTD.width - 0);
     objDiv.style.left = intColWidth - 3 ;
     objDiv.style.width = 6 + parseInt(element.border);
     objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * objTD.offsetHeight;
     // for debugging only
     //objDiv.style.backgroundColor = clrHilight;
     
     //To make it more beautiful in IE 6  
     if (navigator.appVersion.indexOf ("MSIE 6.0") != -1)
       objDiv.style.cursor = "col-resize";
     else
       objDiv.style.cursor = "crosshair";
     objDiv.attachEvent ("onmouseover", flagTrue);
     objDiv.attachEvent ("onmousedown", captureMouse);
     objDiv.attachEvent ("onmousemove", resizeColoumn);
     objDiv.attachEvent ("onmouseup", releaseMouse);
     objDiv.attachEvent ("onmouseout", flagFalse);
     objLast.insertAdjacentElement ("afterEnd", objDiv);
     objLast = objDiv;
   }
 }
 /*\
 |*| This function will be fired onmouseover of the DIVs
 |*| Set the flag to true indicating that the mouse is over the DIV
 \*/
 function flagTrue ()
 {
   blnMouseOver = true;
 }
 /*\
 |*| This function will be fired onmousedown on the DIVs
 |*| Capture all the mosue events if mousedown is fired inside the DIV
 \*/
 function captureMouse ()
 {
   if (blnMouseOver)
   {
     objDivToMove = window.event.srcElement;
     objDivToMove.setCapture ();
   }
 }
 /*\
 |*| This function will be fired onmousemove of the DIVs
 |*| This will be used as a ondrag function... thanks to IE 5
 \*/
 function resizeColoumn ()
 {
   //If mouse button is down, objDivToMove will be valid... we can move/resize
   if (!objDivToMove) return;
   var intTDNum = objDivToMove.name - 1;
   var thead = element.tHead;
   if (!thead) return;
   var objTD = thead.childNodes[0].childNodes[intTDNum];
   if (!objTD || objTD.tagName != "TD") return;
   var intCurWidth = objTD.offsetWidth;
   var newX = window.event.clientX;
   //var newX = window.event.x;
   var intNewWidth = newX - objTD.offsetLeft;
   //TODO: who decided that the minimum col widhth is 50px?
   if (intNewWidth < 50) return;
   //Check to see if the table widht is more than the width of the window
   //Need that 20px buffer in IE to prevent scroll bars from appearing
   if (element.document.body.offsetWidth - 20 < element.offsetWidth - intCurWidth + intNewWidth) return;
   objTD.style.width = intNewWidth;
   var objDiv = objDivToMove;
   //Will be � 1 depending on which side the mouse moved
   //will be used to move all the DIVs remaining on the right
   var intDivMove = newX - objDiv.offsetLeft;
   objDiv.style.left = newX;
   //Move all the remaining DIVs on the right
   for (var i = 1; i < intColCount - intTDNum; i++)
   {        
     objDiv = objDiv.nextSibling;
     objDiv.style.left = objDiv.offsetLeft + intDivMove ;
   }
 }
 /*\
 |*| This function will be fired onmouseup
 |*| Release all the mouse events of the DIV
 \*/
 function releaseMouse ()
 {
   objDivToMove.releaseCapture ();
   objDivToMove = null;
 }
 /*\
 |*| This function will be fired onmouseout of the DIV
 |*| Set the flag indicating that the mouse is NOT over the DIV
 \*/
 function flagFalse ()
 {
   blnMouseOver = false;
 }
 /*\
 |*| This function will be called once during initIALIZATION
 |*| This will create DIV elm after the table to display the ABOUT informationA
 \*/
 function initAbout ()
 {
   objDiv = window.document.createElement ("DIV");
   objDiv.id = "About";
   objDiv.style.position = "absolute";
   objDiv.style.top = 0; 
   objDiv.style.left = 0 ;
   objDiv.align = "center";
   //element.document.body.offsetWidth ==> width of the IFRAME in IE
   objDiv.style.width = element.document.body.offsetWidth;
   objDiv.style.height = element.document.body.offsetHeight;
   objDiv.style.backgroundColor = "#0000FF";
   objDiv.style.color = "#FFFF00";
   objDiv.style.visibility = "hidden";
   objDiv.insertAdjacentText ("afterBegin", "DHTML Grid ver 0.92\n\n" + "");
   var objInput = document.createElement ("INPUT");
   objInput.id = "cmdAbout";
   objInput.title = "Ok";
   objInput.value = "Ok";
   objInput.align = "center";
   objInput.valign = "middle";
   objInput.style.height = "20px";
   objInput.style.width = "102px";
   objInput.type = "button";
   objInput.attachEvent ("onclick", about);
   objDiv.insertAdjacentElement ("beforeEnd", objInput);
   element.insertAdjacentElement ("afterEnd", objDiv);
 }
 /*\
 |*| Hilights the row on mouseover. This also sets the "previous row selected" to normal
 \*/
 function selectRow ()
 {
   var srcElem = getEventRow ();
   if (srcElem.tagName != "TR") return;
   if (objRowSelected)
   {
     objRowSelected.style.backgroundColor = "";
     objRowSelected = null;
   }
   if (srcElem.rowIndex > 0)
   {
     srcElem.style.backgroundColor = clrHilight;
     objRowSelected = srcElem;
   }
   element.focus ();
 }
 /*\
 |*| Entry point for all the click events on the table
 \*/
 function onClickCell ()
 {
   var srcElem = getEventRow ();
   if (srcElem.tagName != "TR") return;
   if (srcElem.rowIndex == 0) sort ();
   else onEdit ();
 }
 /*\
 |*| Capture the key press event, on del key see if a row is selected and delete
 \*/
 function captureDelKey ()
 {
   var keyPressed = event.keyCode;
   
   var srcElem = window.event.srcElement;
   if ((keyPressed == 46) && (srcElem.tagName != "INPUT") && (objRowSelected))
   {
     deleteRow (objRowSelected.rowIndex - 1);
     objRowSelected = null;
   }
 }
 /*\
 |*| detach all the events attached to the element and call other cleanup functions
 \*/
 function cleanup ()
 {
   element.detachEvent ("onmouseover", selectRow);
   element.detachEvent ("onclick", onClickCell);
   cleanupDiv ();
   cleanupAbout ();
 }
 /*\
 |*| Used by cleanup to clean the DIVs created for moving the Cols
 |*| detach all the events and delete the elements here
 \*/
 function cleanupDiv ()
 {
   var objDiv;
   for (var i = 1; i <= intColCount; i++)
   {  
     objDiv = element.document.getElementById ("DragMark" + (i - 1));
     objDiv.detachEvent ("onmouseover", flagTrue);
     objDiv.detachEvent ("onmousedown", captureMouse);
     objDiv.detachEvent ("onmousemove", resizeColoumn);
     objDiv.detachEvent ("onmouseup", releaseMouse);
     objDiv.detachEvent ("onmouseout", flagFalse);
     objDiv.removeNode (true);
   }
 }
 /*\
 |*| Detach all the events and Delete the elms related to the about box here
 \*/
 function cleanupAbout ()
 {
   element.document.getElementById ("About").removeNode (true);
 }
 /*\
 |*| This is THE function which does all the real sorting of the rows
 |*| First get rid of all the text-node elements that NN returns for spaces in the tables
 |*| then sort the contents based on which coloumn is clicked
 \*/
 function insertionSort (t, iRowEnd, fReverse, iColumn)
 {
   var textRowInsert, textRowCurrent, eRowInsert, eRowWalk;
   removeTextNodes (t);
   for (var iRowInsert = 1 ; iRowInsert <= iRowEnd ; iRowInsert++)
   {
     if (iColumn)
     {
       if (typeof (t.childNodes[iRowInsert].childNodes[iColumn]) != "undefined")
          textRowInsert = t.childNodes[iRowInsert].childNodes[iColumn].innerText;
       else
         textRowInsert = "";
     }
     else
     {
       textRowInsert = t.childNodes[iRowInsert].innerText;
     }
     for (var iRowWalk = 0 ; iRowWalk < iRowInsert ; iRowWalk++)
     {
       if (iColumn)
       {
         if (typeof (t.childNodes[iRowWalk].childNodes[iColumn]) != "undefined")
           textRowCurrent = t.childNodes[iRowWalk].childNodes[iColumn].innerText;
         else
           textRowCurrent = "";
       }
       else
       {
         textRowCurrent = t.childNodes[iRowWalk].innerText;
       }
       if ((!fReverse && textRowInsert < textRowCurrent) || (fReverse && textRowInsert > textRowCurrent))
       {
         eRowInsert = t.childNodes[iRowInsert];
         eRowWalk = t.childNodes[iRowWalk];
         t.insertBefore (eRowInsert, eRowWalk);
         iRowWalk = iRowInsert; // done
       }
     }
   }
 }
 /*\
 |*|  This function is called when there is a click event on the top
 |*|  row
 \*/
 function sort ()
 {
   var srcElem = getEventCell ();
   if (srcElem.tagName != "TD") return;
   var thead = element.tHead;  
   // clear the sort images in the head
   var imgcol = thead.getElementsByTagName ("IMG");
   for (var x = 0; x < imgcol.length; x++) 
   {
     imgcol[x].setAttribute("src", strBlankImage);
   }
   if (objLastClick == srcElem.selectIndex)
   {
     if (reverse == false)
     {
       srcElem.childNodes[0].setAttribute ("src", strDownImage);
       reverse = true;
     }
     else 
     {
       srcElem.childNodes[0].setAttribute ("src", strUpImage);
       reverse = false;
     }
   }
   else
   {
     reverse = false;
     objLastClick = srcElem.selectIndex;
     srcElem.childNodes[0].setAttribute ("arc", strUpImage);
   }
   tbody = element.tBodies [0];
   insertionSort (tbody, tbody.rows.length-1, reverse, srcElem.selectIndex);
 }
 /*\
 |*| This function is called when focus is lost on the text box
 |*| that is used to read user input. Validate the contents of the
 |*| input box and write them back to the table cell
 \*/
 function focusLost ()
 {
   var objSrcElm = window.event.srcElement; 
   objSrcElm.parentNode.innerHTML = unescape (objSrcElm.value);
 }
 /*\
 |*| This function is called when user clicks on a cell other than
 |*| the top row.
 |*| Show the content of the cell in an input box
 \*/
 function onEdit ()
 {
   var srcElem = getEventCell ();
   
   if (srcElem.tagName != "TD") return;
   if (srcElem.firstChild && srcElem.firstChild.tagName == "INPUT") return;
   
   txtOld = srcElem.innerHTML;
   srcElem.innerHTML = ""; 
   var objInput = document.createElement ("INPUT");
   objInput.style.width = "100%";//srcElem.clientWidth;
   objInput.type = "text";
   objInput.value = "" + escape (txtOld);
   //objInput.attachEvent ("onfocusout", focusLost);
   //the above onfocusout works fine in IE 6 but not in IE 5 so...
   objInput.attachEvent ("onblur", focusLost);
   objInput.attachEvent ("onkeypress", checkForEnter);
   srcElem.insertAdjacentElement ("beforeEnd", objInput);
   objInput.select ();
 }
 /*\
 |*| This function is used to add a row at the end of the tabl
 |*| Once the rows are added it calls the function to change the height
 |*|  of the DIVs that are used for resizing the table.
 \*/
 function addRow ()
 {
   var objTR = document.createElement ("TR");
   var objTD = document.createElement ("TD");
   for (var i = 0; i < addRow.arguments.length; i++) 
   {
     objTD = document.createElement ("TD");
     objTD.appendChild (document.createTextNode ((arguments[i]=="")?"null":arguments[i]));
     objTR.insertAdjacentElement ("beforeEnd", objTD);
   }
   objTBody = element.tBodies [0];
   objTBody.insertAdjacentElement ("beforeEnd", objTR);
   resizeDivs ();
 }
 
 /*\
 |*| The function deletes the last row by calling the deleteRow function 
 |*|  with the table row count
 \*/
 function deleteLastRow ()
 {
   removeTextNodes (element.tBodies[0]);
   this.deleteRow (element.tBodies[0].childNodes.length - 1);
 }
 /*\
 |*| The function checks if the rownum passed is a valid row 
 |*|  and deletes it 
 |*| This also calls the resizeDivs function to reduce the height
 |*|  of the DIVs that are used in resizing the table
 \*/
 function deleteRow (rowNum)
 {
   var tbody = element.tBodies [0];
   if (!tbody || rowNum < 0) return;
   removeTextNodes (tbody);
   tbody.childNodes[rowNum].removeNode (true);
   resizeDivs ();
 }
 /*\
 |*| This will be called on everkeypress event of the input box
 |*| This raises the focuslost event if the user hits enter
 \*/
 function checkForEnter ()
 {
   if (event.keyCode == 13) focusLost ();
 }
 /*\
 |*| Toggle the About div section
 \*/
 function about ()
 {
   if (element.document.getElementById ("About").style.visibility == "hidden")
     element.document.getElementById ("About").style.visibility = "visible";
   else
     element.document.getElementById ("About").style.visibility = "hidden";
 }
 /*\
 |*| Need this as IE 5 doesnt give the offsetLeft property properly
 \*/
 function getRealPos (elm)
 {
   intPos = 0;
   elm = elm.previousSibling;
   while ((elm!= null) && (elm.tagName!="BODY"))
   {
      intPos += elm.width - 0;
     elm = elm.previousSibling;
   }
   return intPos;
 }
 /*\
 |*| Return the TR elem on which an event has fireed
 \*/
 function getEventRow ()
 {
   var srcElem = window.event.srcElement;
   //crawl up to find the row
   while (srcElem.tagName != "TR" && srcElem.tagName != "TABLE")
   {
     srcElem = srcElem.parentNode;
   }
   return srcElem;
 }
 /*\
 |*| Return the TD elem on which an event has fireed
 \*/
 function getEventCell ()
 {
   var srcElem = window.event.srcElement;
   //crawl up the tree to find the table col
   while (srcElem.tagName != "TD" && srcElem.tagName != "TABLE")
   {
     srcElem = srcElem.parentNode;
   }
   return srcElem;
 }
 /*\
 |*| This funtion is used to change the height of the DIVs that are used to drag the cols
 |*| Used when a row is added or deleted.
 \*/
 function resizeDivs ()
 {
   for (var i = 0; i < intColCount; i++)
   {  
     var objDiv = element.document.getElementById ("DragMark" + (i));
     var objTD = element.tHead.childNodes[0].childNodes[i];
     if ((!objDiv) || (!objTD) || (objTD.tagName != "TD")) return;
     objDiv.style.height = (element.tBodies[0].childNodes.length + 1) * (objTD.offsetHeight - 1);
   }
 }
 /*\
 |*| Function to handle erros. Displayes a request to contact along with the error messagei, filename and line
 \*/
 function handleError (err, url, line)
 {
   alert ("Oops, something went wrong.\n" +
      "Please contact yinti AT users DOT sourceforge DOT net with the following text\n" + 
      "Error text: " + err + "\n" + 
      "Location  : " + url + "\n" +
      "Line no   : " + line + "\n");
    return true; // let the browser handle the error */
 }
 /*\
 |*| Function to prototype all the functions needed by NN to emulate the functionality of IE
 \*/
 function initNNFunctions ()
 {
   if ((self.Node) && (self.Node.prototype))
   {
     Node.prototype.removeNode = NNRemoveNode;
     Element.prototype.insertAdjacentText = NNInsertAdjacentText;
     Element.prototype.insertAdjacentElement = NNInsertAdjacentElement;
     Element.prototype.insert__Adj = NNInsertAdj;
     Element.prototype.attachEvent = NNAttachEvent;
     Element.prototype.detachEvent = NNDetachEvent;
     Element.prototype.setCapture = NNSetCapture;
     Element.prototype.releaseCapture = NNReleaseCapture;
     Element.prototype.__defineGetter__("document", NNDocumentGetter);
     HTMLElement.prototype.focus = NNNullFunction;
     HTMLElement.prototype.attachEvent = NNAttachEvent;
     HTMLElement.prototype.detachEvent = NNDetachEvent;
     HTMLElement.prototype.__defineGetter__("innerText", NNInnerTextGetter);
     HTMLElement.prototype.__defineSetter__("innerText", NNInnerTextSetter);
     HTMLDocument.prototype.attachEvent = NNAttachEvent;
     HTMLDocument.prototype.detachEvent = NNDetachEvent;
     Event.prototype.__defineGetter__("keyCode", NNKeyCodeGetter);
   }
 }
 /*\
 |*|
 \*/
 function NNRemoveNode (a1)
 {
   var p = this.parentNode;
   if (p&&!a1)
   {
     var df = document.createDocumentFragment ();
     for (var a = 0; a < this.childNodes.length; a++)
     {
       df.appendChild (this.childNodes[a])
     }
     p.insertBefore (df , this)
   }
   return p?p.removeChild (this):this;
 }
 /*\
 |*|
 \*/
 function NNInsertAdjacentText (a1 , a2)
 {
   var t = document.createTextNode (a2||"")
   this.insert__Adj (a1 , t);
 }
 /*\
 |*|
 \*/
 function NNInsertAdjacentElement (a1 , a2)
 {
   this.insert__Adj (a1 , a2);
   return a2;
 }
 /*\
 |*|
 \*/
 function NNInsertAdj (a1 , a2)
 {
   var p = this.parentNode;
   var s = a1.toLowerCase ();
   if (s == "beforebegin"){p.insertBefore (a2 , this)}
   if (s == "afterend"){p.insertBefore (a2 , this.nextSibling)}
   if (s == "afterbegin"){this.insertBefore (a2 , this.childNodes[0])}
   if (s == "beforeend"){this.appendChild (a2)}
 }
 /*\
 |*| Fuction to simulate attachEvent
 \*/
 function NNAttachEvent (strEvent, funcHandle)
 {
   var shortTypeName = strEvent.replace (/on/, "");
   funcHandle._ieEmuEventHandler = function (e)
   {
     window.event = e;
     window.event.srcElement = e.target;
     return funcHandle ();
   };
   this.addEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);
 }
 /*\
 |*| Fuction to simulate detachEvent
 \*/
 function NNDetachEvent (strEvent, funcHandle)
 {
   var shortTypeName = strEvent.replace (/on/, "");
   if (typeof funcHandle._ieEmuEventHandler == "function")
     this.removeEventListener (shortTypeName, funcHandle._ieEmuEventHandler, false);
   else 
     this.removeEventListener (shortTypeName, funcHandle, true);
 }
 /*\
 |*| A HUGE HACK to getaway with the lack of setcapture in NN
 \*/
 function NNSetCapture ()
 {
   //TODO: FIX THIS FIRST BEFORE ANYTHING ELSE!! MAJOR HACK FOR NOW
   document.attachEvent ("onmousemove", resizeColoumn);
   document.attachEvent ("onmouseup", releaseMouse);
 }
 /*\
 |*| A HUGE HACK to getaway with the lack of releasecapture in NN
 \*/
 function NNReleaseCapture ()
 {
   //TODO: FIX THIS SECOND THEN GO TO EVERYTHING ELSE! 
   document.detachEvent ("onmousemove", resizeColoumn);
   document.detachEvent ("onmouseup", releaseMouse);
 }
 /*\
 |*| Empty function used to remove any functions not needed in NN
 \*/
 function NNNullFunction () { /*Nothing here*/ }
 /*\
 |*| return the innerhtml by replacing all the <TAGNAME> from the string
 \*/
 function NNInnerTextGetter ()
 {
   return this.innerHTML.replace (/<[^>]+>/g,"");
 }
 /*\
 |*| Add the text as a textnode to the element
 \*/
 function NNInnerTextSetter (txtStr)
 {
   var parsedText = document.createTextNode (txtStr);
   this.innerHTML = "";
   this.appendChild (parsedText);
 }
 /*\
 |*| Function to simulate event.keyCode
 \*/
 function NNKeyCodeGetter ()
 {
   return this.which;
 }
 /*\
 |*| Function to simulate element.document
 \*/
 function NNDocumentGetter ()
 {
   return this.ownerDocument;
 }
 
 </SCRIPT>

</HEAD> <BODY leftmargin="0" topmargin="0" onload="init("tblGrid")">

<THEAD> </THEAD> <TBODY> </TBODY>
Col 1 Col 2 Col 3 Col 4
200 dcdcdc 400 aaaaaa
300 c9e6ff 600 cccccc
301 e6e6ff 601 eeeeee

</BODY> </HTML>


 </source>
   
  


Table sorter

<A href="http://www.wbex.ru/Code/JavaScriptDownload/tablesorter.zip">tablesorter.zip( 26 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm">Web Data Grid Table</a> <A href="/Code/JavaScript/GUI-Components/WebDataGridTable.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>

Table Sorter Proof of Concept

   <source lang="html4strict">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html>

 <head>
   <title>Table Sorter Proof of Concept</title>
   <style type="text/css">

table {

 width: 80%;
 margin: 1em auto;
 border-collapse: collapse;

} thead th, tfoot th {

 padding: 0.5em;
 text-align: left;
 border: 1px solid black;
 background-color: #AAF;

} tfoot td {

 border-top: 1px solid black;

} tbody td {

 padding: 0.5em;
 border-left: 1px solid black;
 border-right: 1px solid black;

} tbody tr.odd {

 background-color: #DDF;

} td.numeric, th.numeric {

 text-align: right;

}

   </style>
       
   <script type="text/javascript">
   /**
* addEvent written by Dean Edwards, 2005
* with input from Tino Zijdel
*
* http://dean.edwards.name/weblog/2005/10/add-event/
**/

function addEvent(element, type, handler) {

 // assign each event handler a unique ID
 if (!handler.$$guid) handler.$$guid = addEvent.guid++;
 // create a hash table of event types for the element
 if (!element.events) element.events = {};
 // create a hash table of event handlers for each element/event pair
 var handlers = element.events[type];
 if (!handlers) {
   handlers = element.events[type] = {};
   // store the existing event handler (if there is one)
   if (element["on" + type]) {
     handlers[0] = element["on" + type];
   }
 }
 // store the event handler in the hash table
 handlers[handler.$$guid] = handler;
 // assign a global event handler to do all the work
 element["on" + type] = handleEvent;

}; // a counter used to create unique IDs addEvent.guid = 1; function removeEvent(element, type, handler) {

 // delete the event handler from the hash table
 if (element.events && element.events[type]) {
   delete element.events[type][handler.$$guid];
 }

}; function handleEvent(event) {

 var returnValue = true;
 // grab the event object (IE uses a global event object)
 event = event || fixEvent(window.event);
 // get a reference to the hash table of event handlers
 var handlers = this.events[event.type];
 // execute each event handler
 for (var i in handlers) {
   this.$$handleEvent = handlers[i];
   if (this.$$handleEvent(event) === false) {
     returnValue = false;
   }
 }
 return returnValue;

}; function fixEvent(event) {

 // add W3C standard event methods
 event.preventDefault = fixEvent.preventDefault;
 event.stopPropagation = fixEvent.stopPropagation;
 return event;

}; fixEvent.preventDefault = function() {

 this.returnValue = false;

}; fixEvent.stopPropagation = function() {

 this.cancelBubble = true;

}; // end from Dean Edwards

/**

* Creates an Element for insertion into the DOM tree.
* From http://simon.incutio.ru/archive/2003/06/15/javascriptWithXML
*
* @param element the element type to be created.
*        e.g. ul (no angle brackets)
**/

function createElement(element) {

 if (typeof document.createElementNS != "undefined") {
   return document.createElementNS("http://www.w3.org/1999/xhtml", element);
 }
 if (typeof document.createElement != "undefined") {
   return document.createElement(element);
 }
 return false;

} /**

* "targ" is the element which caused this function to be called
* from http://www.quirksmode.org/js/events_properties.html
**/

function getEventTarget(e) {

 var targ;
 if (!e) {
   e = window.event;
 }
 if (e.target) {
   targ = e.target;
 } else if (e.srcElement) {
   targ = e.srcElement;
 }
 if (targ.nodeType == 3) { // defeat Safari bug
   targ = targ.parentNode;
 }
 return targ;

}

   </script>
   
   <script type="text/javascript">

/**

* Written by Neil Crosby. 
* http://www.workingwith.me.uk/
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
* SOFTWARE.
**/

var css = {

 /**
  * Returns an array containing references to all elements
  * of a given tag type within a certain node which have a given class
  *
  * @param node    the node to start from 
  *          (e.g. document, 
  *              getElementById("whateverStartpointYouWant")
  *          )
  * @param searchClass the class we"re wanting
  *          (e.g. "some_class")
  * @param tag     the tag that the found elements are allowed to be
  *          (e.g. "*", "div", "li")
  **/
 getElementsByClass : function(node, searchClass, tag) {
   var classElements = new Array();
   var els = node.getElementsByTagName(tag);
   var elsLen = els.length;
   var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
   
   
   for (var i = 0, j = 0; i < elsLen; i++) {
     if (this.elementHasClass(els[i], searchClass) ) {
       classElements[j] = els[i];
       j++;
     }
   }
   return classElements;
 },
 /**
  * PRIVATE.  Returns an array containing all the classes applied to this
  * element.
  *
  * Used internally by elementHasClass(), addClassToElement() and 
  * removeClassFromElement().
  **/
 privateGetClassArray: function(el) {
   return el.className.split(" "); 
 },
 /**
  * PRIVATE.  Creates a string from an array of class names which can be used 
  * by the className function.
  *
  * Used internally by addClassToElement().
  **/
 privateCreateClassString: function(classArray) {
   return classArray.join(" ");
 },
 /**
  * Returns true if the given element has been assigned the given class.
  **/
 elementHasClass: function(el, classString) {
   if (!el) {
     return false;
   }
   
   var regex = new RegExp("\\b"+classString+"\\b");
   if (el.className.match(regex)) {
     return true;
   }
   return false;
 },
 /**
  * Adds classString to the classes assigned to the element with id equal to
  * idString.
  **/
 addClassToId: function(idString, classString) {
   this.addClassToElement(document.getElementById(idString), classString);
 },
 /**
  * Adds classString to the classes assigned to the given element.
  * If the element already has the class which was to be added, then
  * it is not added again.
  **/
 addClassToElement: function(el, classString) {
   var classArray = this.privateGetClassArray(el);
   if (this.elementHasClass(el, classString)) {
     return; // already has element so don"t need to add it
   }
   classArray.push(classString);
   el.className = this.privateCreateClassString(classArray);
 },
 /**
  * Removes the given classString from the list of classes assigned to the
  * element with id equal to idString
  **/
 removeClassFromId: function(idString, classString) {
   this.removeClassFromElement(document.getElementById(idString), classString);
 },
 /**
  * Removes the given classString from the list of classes assigned to the
  * given element.  If the element has the same class assigned to it twice, 
  * then only the first instance of that class is removed.
  **/
 removeClassFromElement: function(el, classString) {
   var classArray = this.privateGetClassArray(el);
   for (x in classArray) {
     if (classString == classArray[x]) {
       classArray[x] = "";
       break;
     }
   }
   el.className = this.privateCreateClassString(classArray);
 }

}

   </script>
   
   <script type="text/javascript">

/**

* Written by Neil Crosby. 
* http://www.workingwith.me.uk/articles/scripting/standardista_table_sorting
*
* This module is based on Stuart Langridge"s "sorttable" code.  Specifically, 
* the determineSortFunction, sortCaseInsensitive, sortDate, sortNumeric, and
* sortCurrency functions are heavily based on his code.  This module would not
* have been possible without Stuart"s earlier outstanding work.
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy 
* of this software and associated documentation files (the "Software"), to deal 
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in 
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
* SOFTWARE.
**/

var standardistaTableSorting = {

 that: false,
 isOdd: false,
 sortColumnIndex : -1,
 lastAssignedId : 0,
 newRows: -1,
 lastSortedTable: -1,
 /**
  * Initialises the Standardista Table Sorting module
  **/
 init : function() {
   // first, check whether this web browser is capable of running this script
   if (!document.getElementsByTagName) {
     return;
   }
   
   this.that = this;
   
   this.run();
   
 },
 
 /**
  * Runs over each table in the document, making it sortable if it has a class
  * assigned named "sortable" and an id assigned.
  **/
 run : function() {
   var tables = document.getElementsByTagName("table");
   
   for (var i=0; i < tables.length; i++) {
     var thisTable = tables[i];
     
     if (css.elementHasClass(thisTable, "sortable")) {
       this.makeSortable(thisTable);
     }
   }
 },
 
 /**
  * Makes the given table sortable.
  **/
 makeSortable : function(table) {
 
   // first, check if the table has an id.  if it doesn"t, give it one
   if (!table.id) {
     table.id = "sortableTable"+this.lastAssignedId++;
   }
   
   // if this table does not have a thead, we don"t want to know about it
   if (!table.tHead || !table.tHead.rows || 0 == table.tHead.rows.length) {
     return;
   }
   
   // we"ll assume that the last row of headings in the thead is the row that 
   // wants to become clickable
   var row = table.tHead.rows[table.tHead.rows.length - 1];
   
   for (var i=0; i < row.cells.length; i++) {
   
     // create a link with an onClick event which will 
     // control the sorting of the table
     var linkEl = createElement("a");
     linkEl.href = "#";
     linkEl.onclick = this.headingClicked;
     linkEl.setAttribute("columnId", i);
     linkEl.title = "Click to sort";
     
     // move the current contents of the cell that we"re 
     // hyperlinking into the hyperlink
     var innerEls = row.cells[i].childNodes;
     for (var j = 0; j < innerEls.length; j++) {
       linkEl.appendChild(innerEls[j]);
     }
     
     // and finally add the new link back into the cell
     row.cells[i].appendChild(linkEl);
     var spanEl = createElement("span");
     spanEl.className = "tableSortArrow";
     spanEl.appendChild(document.createTextNode("\u00A0\u00A0"));
     row.cells[i].appendChild(spanEl);
   }
 
   if (css.elementHasClass(table, "autostripe")) {
     this.isOdd = false;
     var rows = table.tBodies[0].rows;
   
     // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
     for (var i=0;i<rows.length;i++) { 
       this.doStripe(rows[i]);
     }
   }
 },
 
 headingClicked: function(e) {
   
   var that = standardistaTableSorting.that;
   
   // linkEl is the hyperlink that was clicked on which caused
   // this method to be called
   var linkEl = getEventTarget(e);
   
   // directly outside it is a td, tr, thead and table
   var td     = linkEl.parentNode;
   var tr     = td.parentNode;
   var thead  = tr.parentNode;
   var table  = thead.parentNode;
   
   // if the table we"re looking at doesn"t have any rows
   // (or only has one) then there"s no point trying to sort it
   if (!table.tBodies || table.tBodies[0].rows.length <= 1) {
     return false;
   }
   // the column we want is indicated by td.cellIndex
   var column = linkEl.getAttribute("columnId") || td.cellIndex;
   //var column = td.cellIndex;
   
   // find out what the current sort order of this column is
   var arrows = css.getElementsByClass(td, "tableSortArrow", "span");
   var previousSortOrder = "";
   if (arrows.length > 0) {
     previousSortOrder = arrows[0].getAttribute("sortOrder");
   }
   
   // work out how we want to sort this column using the data in the first cell
   // but just getting the first cell is no good if it contains no data
   // so if the first cell just contains white space then we need to track
   // down until we find a cell which does contain some actual data
   var itm = ""
   var rowNum = 0;
   while ("" == itm && rowNum < table.tBodies[0].rows.length) {
     itm = that.getInnerText(table.tBodies[0].rows[rowNum].cells[column]);
     rowNum++;
   }
   var sortfn = that.determineSortFunction(itm);
   // if the last column that was sorted was this one, then all we need to 
   // do is reverse the sorting on this column
   if (table.id == that.lastSortedTable && column == that.sortColumnIndex) {
     newRows = that.newRows;
     newRows.reverse();
   // otherwise, we have to do the full sort
   } else {
     that.sortColumnIndex = column;
     var newRows = new Array();
     for (var j = 0; j < table.tBodies[0].rows.length; j++) { 
       newRows[j] = table.tBodies[0].rows[j]; 
     }
     newRows.sort(sortfn);
   }
   that.moveRows(table, newRows);
   that.newRows = newRows;
   that.lastSortedTable = table.id;
   
   // now, give the user some feedback about which way the column is sorted
   
   // first, get rid of any arrows in any heading cells
   var arrows = css.getElementsByClass(tr, "tableSortArrow", "span");
   for (var j = 0; j < arrows.length; j++) {
     var arrowParent = arrows[j].parentNode;
     arrowParent.removeChild(arrows[j]);
     if (arrowParent != td) {
       spanEl = createElement("span");
       spanEl.className = "tableSortArrow";
       spanEl.appendChild(document.createTextNode("\u00A0\u00A0"));
       arrowParent.appendChild(spanEl);
     }
   }
   
   // now, add back in some feedback 
   var spanEl = createElement("span");
   spanEl.className = "tableSortArrow";
   if (null == previousSortOrder || "" == previousSortOrder || "DESC" == previousSortOrder) {
     spanEl.appendChild(document.createTextNode(" \u2191"));
     spanEl.setAttribute("sortOrder", "ASC");
   } else {
     spanEl.appendChild(document.createTextNode(" \u2193"));
     spanEl.setAttribute("sortOrder", "DESC");
   }
   
   td.appendChild(spanEl);
   
   return false;
 },
 getInnerText : function(el) {
   
   if ("string" == typeof el || "undefined" == typeof el) {
     return el;
   }
   
   if (el.innerText) {
     return el.innerText;  // Not needed but it is faster
   }
   var str = el.getAttribute("standardistaTableSortingInnerText");
   if (null != str && "" != str) {
     return str;
   }
   str = "";
   var cs = el.childNodes;
   var l = cs.length;
   for (var i = 0; i < l; i++) {
     // "if" is considerably quicker than a "switch" statement, 
     // in Internet Explorer which translates up to a good time 
     // reduction since this is a very often called recursive function
     if (1 == cs[i].nodeType) { // ELEMENT NODE
       str += this.getInnerText(cs[i]);
       break;
     } else if (3 == cs[i].nodeType) { //TEXT_NODE
       str += cs[i].nodeValue;
       break;
     }
   }
   
   // set the innertext for this element directly on the element
   // so that it can be retrieved early next time the innertext
   // is requested
   el.setAttribute("standardistaTableSortingInnerText", str);
   
   return str;
 },
 determineSortFunction : function(itm) {
   
   var sortfn = this.sortCaseInsensitive;
   
   if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) {
     sortfn = this.sortDate;
   }
   if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) {
     sortfn = this.sortDate;
   }
   if (itm.match(/^[£$]/)) {
     sortfn = this.sortCurrency;
   }
   if (itm.match(/^\d?\.?\d+$/)) {
     sortfn = this.sortNumeric;
   }
   if (itm.match(/^[+-]?\d*\.?\d+([eE]-?\d+)?$/)) {
     sortfn = this.sortNumeric;
   }
       if (itm.match(/^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$/)) {
           sortfn = this.sortIP;
      }
   return sortfn;
 },
 
 sortCaseInsensitive : function(a, b) {
   var that = standardistaTableSorting.that;
   
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase();
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase();
   if (aa==bb) {
     return 0;
   } else if (aa<bb) {
     return -1;
   } else {
     return 1;
   }
 },
 
 sortDate : function(a,b) {
   var that = standardistaTableSorting.that;
   // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]);
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]);
   
   var dt1, dt2, yr = -1;
   
   if (aa.length == 10) {
     dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
   } else {
     yr = aa.substr(6,2);
     if (parseInt(yr) < 50) { 
       yr = "20"+yr; 
     } else { 
       yr = "19"+yr; 
     }
     dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
   }
   
   if (bb.length == 10) {
     dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
   } else {
     yr = bb.substr(6,2);
     if (parseInt(yr) < 50) { 
       yr = "20"+yr; 
     } else { 
       yr = "19"+yr; 
     }
     dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
   }
   
   if (dt1==dt2) {
     return 0;
   } else if (dt1<dt2) {
     return -1;
   }
   return 1;
 },
 sortCurrency : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = that.getInnerText(a.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,"");
   var bb = that.getInnerText(b.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,"");
   return parseFloat(aa) - parseFloat(bb);
 },
 sortNumeric : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = parseFloat(that.getInnerText(a.cells[that.sortColumnIndex]));
   if (isNaN(aa)) { 
     aa = 0;
   }
   var bb = parseFloat(that.getInnerText(b.cells[that.sortColumnIndex])); 
   if (isNaN(bb)) { 
     bb = 0;
   }
   return aa-bb;
 },
 makeStandardIPAddress : function(val) {
   var vals = val.split(".");
   for (x in vals) {
     val = vals[x];
     while (3 > val.length) {
       val = "0"+val;
     }
     vals[x] = val;
   }
   val = vals.join(".");
   return val;
 },
 sortIP : function(a,b) { 
   var that = standardistaTableSorting.that;
   var aa = that.makeStandardIPAddress(that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase());
   var bb = that.makeStandardIPAddress(that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase());
   if (aa==bb) {
     return 0;
   } else if (aa<bb) {
     return -1;
   } else {
     return 1;
   }
 },
 moveRows : function(table, newRows) {
   this.isOdd = false;
   // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
   for (var i=0;i<newRows.length;i++) { 
     var rowItem = newRows[i];
     this.doStripe(rowItem);
     table.tBodies[0].appendChild(rowItem); 
   }
 },
 
 doStripe : function(rowItem) {
   if (this.isOdd) {
     css.addClassToElement(rowItem, "odd");
   } else {
     css.removeClassFromElement(rowItem, "odd");
   }
   
   this.isOdd = !this.isOdd;
 }

} function standardistaTableSortingInit() {

 standardistaTableSorting.init();

} addEvent(window, "load", standardistaTableSortingInit)

   </script>
 </head>
 <body>
<thead> </thead> <tfoot> </tfoot> <tbody> </tbody>
Name
Date Forename Surname Number Price IP Address Scientific
385 $160.91
21/01/2006 Neil Crosby 123 $1.96 192.168.1.1 -12E2
01/02/2006 Becca Courtley 122 $23.95 192.167.2.1 12E2
17/11/2004 David Freidman 048 $14.00 192.168.2.1 13e-2
17/10/2004 Sylvia Tyler 43 $104.00 192.168.2.17 12.1e2
17/11/2005 Carl Conway 49 $17.00 192.168.02.13 12e3
 </body>

</html>


 </source>
   
  


Web Data Grid Table

<A href="http://www.wbex.ru/Code/JavaScriptDownload/Webdatagrid.zip">Webdatagrid.zip( 89 k)</a>

1. <A href="/Code/JavaScript/GUI-Components/TableSorterProofofConcept.htm">Table Sorter Proof of Concept</a> 2. <A href="/Code/JavaScript/GUI-Components/Create100randomrowsanddothecolumnsorting.htm">Create 100 random rows and do the column sorting</a> 3. <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm">Sortable table column</a> <A href="/Code/JavaScript/GUI-Components/Sortabletablecolumn.htm"></a> 4. <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm">Table row style with "mouse roll over" effect</a> <A href="/Code/JavaScript/GUI-Components/Tablerowstylewithmouserollovereffect.htm"></a> 5. <A href="/Code/JavaScript/GUI-Components/PagableTable.htm">Pagable Table</a> <A href="/Code/JavaScript/GUI-Components/PagableTable.htm"></a> 6. <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm">Repeat table column at the table bottom</a> <A href="/Code/JavaScript/GUI-Components/Repeattablecolumnatthetablebottom.htm"></a> 7. <A href="/Code/JavaScript/GUI-Components/Editabletablecell.htm">Editable table cell</a> 8. <A href="/Code/JavaScript/GUI-Components/Tablerowwithmouserollover.htm">Table row with mouse roll over</a> 9. <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm">Adding a table row</a> <A href="/Code/JavaScript/GUI-Components/Addingatablerow.htm"></a> 10. <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm">List box ( Grid Table )</a> <A href="/Code/JavaScript/GUI-Components/ListboxGridTable.htm"></a> 11. <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm">List view (Selection between two list)</a> <A href="/Code/JavaScript/GUI-Components/ListviewSelectionbetweentwolist.htm"></a> 12. <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm">Basic Grid (Table) </a> <A href="/Code/JavaScript/GUI-Components/BasicGridTable.htm"></a> 13. <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm">Grid (Table) with colored cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcoloredcells.htm"></a> 14. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm">Build a Grid (Table) from CSV data file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromCSVdatafile.htm"></a> 15. <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm">Build a Grid (Tree) from a tab separated file</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTreefromatabseparatedfile.htm"></a> 16. <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm">Build a Grid (Table) from yahoo quotes (IE only)</a> <A href="/Code/JavaScript/GUI-Components/BuildaGridTablefromyahooquotesIEonly.htm"></a> 17. <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm">Grid (Table) with image in cells</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithimageincells.htm"></a> 18. <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm">Grid (Table) with multiple selection</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithmultipleselection.htm"></a> 19. <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm">Grid (Table) with row header and tooltips</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithrowheaderandtooltips.htm"></a> 20. <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm">One page two grid (Table)</a> <A href="/Code/JavaScript/GUI-Components/OnepagetwogridTable.htm"></a> 21. <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm">Data in Grid (Table) from XML file</a> <A href="/Code/JavaScript/GUI-Components/DatainGridTablefromXMLfile.htm"></a> 22. <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm">Grid (Table) with Data Island and Column highlight</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithDataIslandandColumnhighlight.htm"></a> 23. <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm">Grid (Table) with cell format and XML data set</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithcellformatandXMLdataset.htm"></a> 24. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm">Grid (Table) data from RSS (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromRSSIEonly.htm"></a> 25. <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm">Grid (Table) data from xml file 2</a> <A href="/Code/JavaScript/GUI-Components/GridTabledatafromxmlfile2.htm"></a> 26. <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm">Grid (Table) with news feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithnewsfeederIEonly.htm"></a> 27. <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm">Grid (Table) with quotes feeder (IE only)</a> <A href="/Code/JavaScript/GUI-Components/GridTablewithquotesfeederIEonly.htm"></a> 28. <A href="/Code/JavaScript/GUI-Components/GridTableinUnixstyle.htm">Grid (Table) in Unix style</a> 29. <A href="/Code/JavaScript/GUI-Components/SortableGridstable.htm">Sortable Grids (table)</a> 30. <A href="/Code/JavaScript/GUI-Components/SelectableCellsGridTable.htm">Selectable Cells Grid Table</a> 31. <A href="/Code/JavaScript/GUI-Components/EditableGridTablecell.htm">Editable Grid Table cell</a> 32. <A href="/Code/JavaScript/GUI-Components/CallbackactioninGridTable.htm">Call back action in Grid Table</a> 33. <A href="/Code/JavaScript/GUI-Components/TableGridRowsSelection.htm">Table Grid Rows Selection</a> 34. <A href="/Code/JavaScript/GUI-Components/GridTableColumnsResize.htm">Grid Table Columns Resize</a> 35. <A href="/Code/JavaScript/GUI-Components/TableGridColumnRenderers.htm">Table Grid Column Renderers</a> 36. <A href="/Code/JavaScript/GUI-Components/Sortingforeachcolumnordoubleclicktoedititscontents.htm">Sorting for each column or double click to edit its contents.</a> 37. <A href="/Code/JavaScript/GUI-Components/TableGridstyleandsortthestyle.htm">Table Grid style and sort the style</a> 38. <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm">Table in JavaScript</a> <A href="/Code/JavaScript/GUI-Components/TableinJavaScript.htm"></a> 39. <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm">Sortable Tables from Scratch with MochiKit</a> <A href="/Code/JavaScript/GUI-Components/SortableTablesfromScratchwithMochiKit.htm"></a> 40. <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm">Ajax Table</a> <A href="/Code/JavaScript/GUI-Components/AjaxTable.htm"></a> 41. <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm">Drag and drop table columns</a> <A href="/Code/JavaScript/GUI-Components/Draganddroptablecolumns.htm"></a> 42. <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm">Dynamic data grid: add a row, remove a row and sort column</a> <A href="/Code/JavaScript/GUI-Components/Dynamicdatagridaddarowremovearowandsortcolumn.htm"></a> 43. <A href="/Code/JavaScript/GUI-Components/supertable.htm">super table </a> <A href="/Code/JavaScript/GUI-Components/supertable.htm"></a> 44. <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm">GUI for table creation</a> <A href="/Code/JavaScript/GUI-Components/GUIfortablecreation.htm"></a> 45. <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm">Table sorter</a> <A href="/Code/JavaScript/GUI-Components/Tablesorter.htm"></a> 46. <A href="/Code/JavaScript/GUI-Components/SortableTable.htm">Sortable Table</a> <A href="/Code/JavaScript/GUI-Components/SortableTable.htm"></a>