/*
jsTableSort.js
Include this file to be able to sort a table by clicking on the table column header.
Code modified from http://www.brainjar.com/dhtml/tablesort/demo.html to remove style and
assumption of an already sorted column.

For best results, table should have header row(s) in <thead> and table body in <tbody> with
an id for <tbody> being passed in.
*/

/*
Original copyright of code owner
<!--************************************************************************-->
<!--* Table Sort Demo                                                      *-->
<!--*                                                                      *-->
<!--* Copyright 2002 by Mike Hall                                          *-->
<!--* Please see http://www.brainjar.com for terms of use.                 *-->
<!--************************************************************************-->
*/

//-----------------------------------------------------------------------------
// sortTable(id, col, rev)
//
//  id  - ID of the TABLE, TBODY, THEAD or TFOOT element to be sorted.
//  col - Index of the column to sort, 0 = first column, 1 = second column,
//        etc.
//  rev - If true, the column is sorted in reverse (descending) order
//        initially.
//
//-----------------------------------------------------------------------------

function sortTable(id, col, rev) 
   {
        
   window.status = 'Sorting the data . . . . .'; 

   // Get the table or table section to sort.
   var tblEl = document.getElementById(id);

   // The first time this function is called for a given table, set up an
   // array of reverse sort flags.
   if (tblEl.reverseSort == null) 
	   {
      tblEl.reverseSort = new Array();
      // set lastColumn to -1 to initialize.
      tblEl.lastColumn = -1;
      }

   // If this column has not been sorted before, set the initial sort direction.
   if (tblEl.reverseSort[col] == null)
      tblEl.reverseSort[col] = rev;

   // If this column was the last one sorted, reverse its sort direction.
   if (col == tblEl.lastColumn)
      tblEl.reverseSort[col] = !tblEl.reverseSort[col];

   // Remember this column as the last one sorted.
   tblEl.lastColumn = col;

   // Set the table display style to "none" - necessary for Netscape 6 
   // browsers.
   var oldDsply = tblEl.style.display;
   tblEl.style.display = "none";

   // Sort the rows based on the content of the specified column using a
   // selection sort.
   var tmpEl;
   var i, j;
   var minVal, minIdx;
   var testVal;
   var cmp;

   for (i = 0; i < tblEl.rows.length - 1; i++) 
	   {
      // Assume the current row has the minimum value.
      minIdx = i;
      minVal = getTextValue(tblEl.rows[i].cells[col]);

      // Search the rows that follow the current one for a smaller value.
      for (j = i + 1; j < tblEl.rows.length; j++) 
		   {
         testVal = getTextValue(tblEl.rows[j].cells[col]);
         cmp = compareValues(minVal, testVal);

         // Negate the comparison result if the reverse sort flag is set.
         if (tblEl.reverseSort[col])
         cmp = -cmp;
         // If this row has a smaller value than the current minimum, remember its
         // position and update the current minimum value.
         if (cmp > 0) 
			   {
            minIdx = j;
            minVal = testVal;
            }
         }

      // By now, we have the row with the smallest value. Remove it from the
      // table and insert it before the current row.
      if (minIdx > i) 
		   {
         tmpEl = tblEl.removeChild(tblEl.rows[minIdx]);
         tblEl.insertBefore(tmpEl, tblEl.rows[i]);
         }
      }

   // Restore the table's display style.
   tblEl.style.display = oldDsply;

   window.status = ''; 

   return false;
   }

//-----------------------------------------------------------------------------
// Functions to get and compare values during a sort.
//-----------------------------------------------------------------------------

// This code is necessary for browsers that don't reflect the DOM constants
// (like IE).
if (document.ELEMENT_NODE == null) 
   {
   document.ELEMENT_NODE = 1;
   document.TEXT_NODE = 3;
   }

function getTextValue(el) 
   {
   var i;
   var s;

   // Find and concatenate the values of all text nodes contained within the
   // element.
   s = "";
   for (i = 0; i < el.childNodes.length; i++)
	   {
      if (el.childNodes[i].nodeType == document.TEXT_NODE)
         s += el.childNodes[i].nodeValue;
      else if (el.childNodes[i].nodeType == document.ELEMENT_NODE &&
               el.childNodes[i].tagName == "BR")
         s += " ";
      else
         // Use recursion to get text within sub-elements.
         s += getTextValue(el.childNodes[i]);
		}

   return normalizeString(s);
   }

function compareValues(v1, v2) 
   {
   var f1, f2; 

   // handle money fields, which have comma formatting
   if (v1.indexOf(',') > 0) {
     v1 = v1.replace(/,/g, "");
     v2 = v2.replace(/,/g, "");
   }

   // handle dates (look for two slashes) and laps (one slash)
   if (v1.indexOf('/') > 0) { 
     if (v1.lastIndexOf('/') != v1.indexOf('/')) {
       // two slashes - must be a date
       v1 = (v1.substr(6,1) < "4" ? "20" : "19") + v1.slice(6) + v1.substr(0,2) + v1.substr(3,2);
       v2 = (v2.substr(6,1) < "4" ? "20" : "19") + v2.slice(6) + v2.substr(0,2) + v2.substr(3,2);
     }
     else {           
       // one slash - must be laps; sort by laps completed (the numbers before the slash)
       v1 = v1.substr(0,v1.indexOf('/'));
       v2 = v2.substr(0,v2.indexOf('/'));
     }
   } 

   // If the values are numeric, convert them to floats.

   f1 = parseFloat(v1);
   f2 = parseFloat(v2);
   if (!isDate(v1) && !isNaN(f1))
      v1 = f1;	  
   if (!isDate(v2)&& !isNaN(f2)) 
      v2 = f2;

   // Compare the two values.
   if (v1 == v2)
      return 0;
   if (v1 > v2)
      return 1
   return -1;
   }

function isDate(str)
   {
   /* Returns true if the field is mm/dd/yyyy because for some reason, the browser is not giving
	   the expected NaN for these fields */ 
	var re = /^[01]?[0-9]\/[0-9]?[0-9]\/[12][0-9][0-9][0-9]$/;
	
	if (!str || str.length<1) return false;	
	if (!re.test(str)) return false;
	else return true;	
   }      

// Regular expressions for normalizing white space.
var whtSpEnds = new RegExp("^\\s*|\\s*$", "g");
var whtSpMult = new RegExp("\\s\\s+", "g");

function normalizeString(s) 
   {
   s = s.replace(whtSpMult, " ");  // Collapse any multiple whites space.
   s = s.replace(whtSpEnds, "");   // Remove leading or trailing white space.

   return s;
   }

