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

  var _hNotifySortHandler = null; // this value should be overridden
  var _cHeaderRows = 0;           // this value should be overridden
  var _cFooterRows = 0;           // this value should be overridden

// do not show visitor any scripting errors
//  function WindowOnError() {return true;}
//  window.onerror = WindowOnError;

  function Init_SortTable( hNotifySortHandler, cHeaderRows, cFooterRows )
  {
    _hNotifySortHandler = hNotifySortHandler;
    _cHeaderRows = cHeaderRows;
    _cFooterRows = cFooterRows;
  }

  function AddClassName( oElement, strClassName )
  {
    if (arguments.length < 2) 
    {
      return alert("AddClassName: insufficient arguments.");
    }
    // if the class name isn't already set, add it
    if (-1 == oElement.className.indexOf(strClassName))
    {
      oElement.className += " " + strClassName;
    }
  }

  function DelClassName( oElement, strClassName )
  {
    if (arguments.length < 2) 
    {
      return alert("DelClassName: insufficient arguments.");
    }
    var strOld = oElement.className;
    var strNew = strOld.replace(strClassName, "");
    oElement.className = strNew;
  }

  function Trim( string )
  {
    if (arguments.length < 1) return alert("Trim: insufficient arguments.");

    while ((string.length > 0) && (string.indexOf(" ") == 0))
      string = string.substr(1);

    while ((string.length > 0) && (string.lastIndexOf(" ") == string.length-1))
      string = string.substr(0,string.length-1);

    return string;
  }

  function GetTableIDFromElement( oElement ) 
  {
    if (arguments.length < 1) return alert("GetTableIDFromElement: insufficient arguments.");

    // find the name of the table containing the given element
    var strResult = "";
    var strTagName = oElement.tagName;
    while ( (oElement != null) && (strTagName != "TABLE") )
    {
      oElement = oElement.parentNode;
      strTagName = oElement.tagName;
    }
    if (oElement == null) strResult = "";
    if (strTagName == "TABLE") strResult = oElement.id;
    return strResult;
  }

  function SortByColumn( strTableName, strColName, fAscending, fForce )
  {
    // default to not avoid toggling behavior
    if (arguments.length < 4) fForce = false;

    // default to sort in ascending order
    if (arguments.length < 3) fAscending = true;

    // find out which column to sort
    if ( (arguments.length < 2) || (strColName == null) )
    {
      var oElement = event.srcElement;
      strColName = Trim(oElement.innerText);
    }
    else
    {
      strColName = Trim(strColName);
    }

    // detect the correct table
    if (arguments.length < 1) 
    {
      strTableName = GetTableIDFromElement(event.srcElement);
      if (strTableName == "") 
      {
        return alert("Cannot identify which table [" + strTableName + "] is.");
      }
    }

    // find out which direction to sort
    // if fForce == true, ignore the smart toggling behavior
    if (!fForce)
    {
      if (GetSortField(strTableName) == strColName)
      {
        // if the column was the one most recently sorted
        // then sort the opposite way
        fAscending = !GetSortOrder(strTableName);
      }
      else
      {
        // if the column was not the one most recently sorted
        // then sort in ascending order first
        fAscending = true;
      }
    }

    // get the table object
    var oTable = document.all(strTableName);

    // count the rows
    var cRows = oTable.rows.length;

    // count the columns
    var cCols = oTable.rows(0).cells.length;

    // find out the number of the column to be sorted
    var iSortColumn = -1;
    for (var i = 0; i < cCols && iSortColumn == -1; i++)
    {
      var strCell = oTable.rows(0).cells(i).innerText;
      strCell = Trim(strCell);
      if (strCell == strColName)
      {
        iSortColumn = i;
      }
    }

    // avoid sorting if we can't identify the column number
    if (iSortColumn != -1)
    {
      SetSortOrder(strTableName, fAscending);
      SetSortField(strTableName, strColName);

       // avoid sorting the column headers
      var cNumberOfHeaderRows = _cHeaderRows;

      // find out what type of values are to be sorted
      var sType = GetSortType(strTableName);
      SortRows( oTable, 
                 cNumberOfHeaderRows, 
                 cRows-1-_cFooterRows, 
                 iSortColumn, 
                 fAscending, 
                 sType,
                 _hNotifySortHandler );
    }
    else
    {
      return alert("SortByColumn: Couldn't sort.");
    }
  }

  function SortRows( oTable, iFirstRow, iLastRow, iColumn, fAscending, sType, hNotifyHook )
  {
    if (arguments.length < 1) return alert("SortRows: insufficient arguments.");
    if (arguments.length < 2) iFirstRow = _cHeaderRows;
    if (arguments.length < 3) iLastRow = oTable.rows.length - _cFooterRows;
    if (arguments.length < 4) iColumn = 1;
    if (arguments.length < 5) fAscending = true;
    if (arguments.length < 6) sType = "string";
    if (arguments.length < 7) hNotifyHook = null;  

    var oRow = oTable.rows(iFirstRow);
    var oColumn = oRow.cells(iColumn);

    // yes, this is a Bubblesort
    for (var i = iFirstRow; i < iLastRow; i++)
    {
      // keep user informed of progress of sort
      if (hNotifyHook) hNotifyHook( Math.round(i / iLastRow * 100) );

      for (var j = i+1; j <= iLastRow; j++)
      {
        var strElementText = Trim(oTable.rows(i).cells(iColumn).innerText);
        var strElementText2 = Trim(oTable.rows(j).cells(iColumn).innerText);
        var fSwap = false;
        // determine whether or not to swap the rows based on the type of data
        switch (sType)
        {
          case "date":
            var dElementValue = parse(strElementText);
            var dElementValue2 = parse(strElementText2);
            fSwap = fAscending ? (dElementValue2 < dElementValue) : (dElementValue2 > dElementValue);
            break;
          case "number":
            var iElementValue = parseInt(strElementText);
            var iElementValue2 = parseInt(strElementText2);
            if (false == isNaN(iElementValue) && false == isNaN(iElementValue2))
            {
              // if both columns contain parseable numbers, sort as numbers
              fSwap = fAscending ? (iElementValue2 < iElementValue) : (iElementValue2 > iElementValue);
            }
            break;
          case "string":
          default:
            fSwap = fAscending ? (strElementText2 < strElementText) : (strElementText2 > strElementText);
            break;
        }
        if (fSwap) SwapRows(oTable, i, j);
      }
    }
  }

  function SwapRows( oTable, iRowA, iRowB ) 
  {
    if (arguments.length < 3) return alert("SwapRows: insufficient arguments.");
    oTable.rows(iRowA).swapNode(oTable.rows(iRowB));
  }

  function GetSortType( strTableName )
  {
    if (arguments.length < 1) return alert("GetSortType: insufficient arguments.");
    var sFieldName = GetSortField(strTableName);
    switch (sFieldName.toLowerCase())
    {
      case "subscribers":
        return "number";
        break;

      case "comments":
      case "date":
      default:
        return "string";
        break;
    }
  }

  function GetSortField( strTableName )
  {
    if (arguments.length < 1) return alert("GetSortField: insufficient arguments.");
    return Trim(document.all(strTableName + "-sortField").innerText);
  }

  function SetSortField( strTableName, strColName )
  {
    if (arguments.length < 2) return alert("SetSortField: insufficient arguments.");
    var strElementName = strTableName + "-sortField";
    document.all(strElementName).innerText = strColName;

    var iSortCol = GetColumnNumberFromColumnName(strTableName, strColName);

    // loop through the whole table and show which column is being sorted
    var oTable = document.all(strTableName);
    var cRows = oTable.rows.length;
    for (var i = _cHeaderRows; i < cRows-_cFooterRows; i++)
    {
      var cCols = oTable.rows(i).cells.length;
      for (var j = 0; j < cCols; j++)
      {
        if (j == iSortCol)
        {
          AddClassName(oTable.rows(i).cells(j), "sortCol");
        }
        else
        {
          DelClassName(oTable.rows(i).cells(j), "sortCol");
        }
      }
    }
  }

  function GetSortOrder( strTableName )
  {
    if (arguments.length < 1) return alert("GetSortOrder: insufficient arguments.");
    var strElement = strTableName + "-sortOrder";
    var strElementText = Trim(document.all(strElement).innerText);
    return (strElementText == "(ascending)") ? true : false;
  }

  function SetSortOrder( strTableName, fAscending )
  {
    if (arguments.length < 2) return alert("SetSortOrder: insufficient arguments.");
    if (arguments.length < 1) return alert("SetSortOrder: insufficient arguments.");

    var strElementName = strTableName + "-sortOrder";
    if (fAscending)
    {
      document.all(strElementName).innerText = "(ascending)";
    }
    else
    {
      document.all(strElementName).innerText = "(descending)";
    }
  }

/* </script> */

