/*
 * --------------------------------------------------------------------
 * 6-12-08
 * Mark Brautigam
 * Idea from Wikipedia's sortable tables
 * I looked at their code and some others, but I wrote my own.
 * --------------------------------------------------------------------
 *
 * To do:
 * 1. add clickability to the top row cells and their contents
 *    a. make the text links so they appear as links
 * 2. add a class to the table that indicates the type of sort to be done
 *    a. alphanumeric - DONE
 *    b. numeric - DONE
 *    c. date (might be several different ones) - ATTEMPTING
 *    d. currency (not used yet)
 *    e. phase level for round dances - DONE maybe?
 *    f. dance level for square dancing
 * 3. add sort code for each of those sort types
 * 4. add init code that add the clickability, etc.
 */

init_table_sort();
var mu_counter;

var levels = new Array (
    "Basic", "ND", "Newer", "MS", "Mainstream", "Plus", "A1", "A2", 
    "C1", "C2", "C3A", "C3", "C4", "Rounds");
var days_of_week = new Array ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");

//---------------------------------------------------------------------
function muGetElementsByClassName(node,cn)
//---------------------------------------------------------------------
{
  if (document.getElementsByClassName)
    return (node.getElementsByClassName (cn));

  // if getElementsByClassName not defined,
  // look through the list of tables instead
  // var tt = document.getElementsByTagName ("table");
  var tt = node.getElementsByTagName ("*");
  var ntt = tt.length;
  var rv = new Array ();
  for (var i=0; i<ntt; i++)
    if (tt[i].className.indexOf (cn) > -1)
      rv.push (tt[i]);
  return (rv);
}

//---------------------------------------------------------------------
function is_ready ()
//---------------------------------------------------------------------
{ 
  /*
  if (document &&
      document.readyState &&
     ((document.readyState.indexOf ("loaded")) ||
      (document.readyState.indexOf ("complete"))))
    return true;
  if (! document.body)
    return false;
  if (! document.getElementsByTagName)
    return false;
  if (! document.getElementById)
    return false;
  if (! document.getElementsByClassName)
    return false;
  var tt = document.getElementsByClassName ("mu_sort");
  if (tt.length < 1)
    return false;
  */
 
  if (! document)
    return false;
  var tt = muGetElementsByClassName(document, "mu_sort");
  if (tt.length < 1)
    return false;

  return true;
}

//---------------------------------------------------------------------
function init_table_sort ()
//---------------------------------------------------------------------
{
  if (! is_ready())
  {
    window.setTimeout (init_table_sort, 100);
    return;
  }

  var tt = muGetElementsByClassName(document, "mu_sort");
  if (tt) {
    for (var i=0; i<tt.length; i++)
      table_make_clickable (tt[i]);
  }
}

//---------------------------------------------------------------------
function muSetInnerText (node, value)
//---------------------------------------------------------------------
{
  // Safari
  if (node.innerText)
     node.innerText = value;

  // Firefox
  else if (node.textContent)
    node.textContent = value;

  // ??
  else
    return ("error");
}

//---------------------------------------------------------------------
function muGetInnerText (node)
//---------------------------------------------------------------------
{
  // Safari
  if (node.innerText)
    return (node.innerText);

  // Firefox
  else if (node.textContent)
    return (node.textContent);

  // ??
  else
    return ("error");
}

//---------------------------------------------------------------------
function table_make_clickable (table)
//---------------------------------------------------------------------
{
  var firstRow = table.rows[0].cells;
  for (var i=0; i<firstRow.length; i++) {
    /*
    var newHTML = 
      "<a href=\"#\" onclick=\"table_sort(" +
      "this.parentNode.parentNode.parentNode.parentNode,"
      + i + ");\">" + firstRow[i].innerText + 
      "<span class=\"mu_sort_img\"></span></a>";
    */
    // note: the event is handled in the table cell
    var newHTML = 
      "<a href=\"#\" onclick=\"return false;\">" +
      // firstRow[i].innerText + "<span class=\"mu_sort_img\"></span></a>";
      muGetInnerText (firstRow[i]) + "<span class=\"mu_sort_img\"></span></a>";
    table.rows[0].cells[i].innerHTML = newHTML;
  }

  for (var i=0; i<firstRow.length; i++) {
    table.rows[0].cells[i].onclick = table_sort_you_know;
  }
}

//---------------------------------------------------------------------
function table_sort_you_know ()
//---------------------------------------------------------------------
{
  table = this.parentNode.parentNode.parentNode;
  for (var i=0; i<table.rows[0].cells.length; i++) {
    if (this == table.rows[0].cells[i]) {
      table_sort (table, i);
    }
  }
}

//---------------------------------------------------------------------
function table_sort (table, sortCol)
//---------------------------------------------------------------------
{
  mu_counter = 0;
  myclasses = table.className;
  var myclasses_a = myclasses.split (" ");
  var sortTypes;

  // get the class that tells us about the fields
  for (var i=0; i<myclasses_a.length; i++)
    if (myclasses_a[i].indexOf ("mu_fields_") != -1)
      sortTypes = myclasses_a[i];
  sortTypes = sortTypes.substr (10);

  // figure out whether the current sort, if any, is reversed
  var reverseit = false;
  /*
  var sort_img = table.rows[0].cells[sortCol].getElementsByClassName(
    "mu_sort_img")[0].innerHTML;
  */
  var sort_img = muGetElementsByClassName (
    table.rows[0].cells[sortCol], "mu_sort_img")[0].innerHTML;
  if (sort_img.length > 3)
    reverseit = true;

  // get the data from the rows
  var sortedRows = new Array ();
  for (var i=1; i<table.rows.length; i++) {
    if (table.rows[i].className && 
	(table.rows[i].className.indexOf ("mu_ignore") > -1))
      continue;
    var key = muGetInnerText (table.rows[i].cells[sortCol]);
    var contents = table.rows[i].innerHTML;
    var visible = table.rows[i].style.display;
    var cn = table.rows[i].className;
    sortedRows.push (new Array (key, contents, visible, cn));
  }

  // sort based on the specified type for this column
  switch (sortTypes[sortCol]) {
    case "n": sortedRows.sort (sort_num); break;
    case "a": sortedRows.sort (sort_alpha); break;
    case "b": sortedRows.sort (sort_alphanum); break;
    case "p": sortedRows.sort (sort_phase); break;
    case "d": sortedRows.sort (sort_date); break;
    case "m": sortedRows.sort (sort_money); break;
    case "g": sortedRows.sort (sort_grade); break;
    case "s": sortedRows.sort (sort_level); break;
    case "c": sortedRows.sort (sort_caller); break;
    case "w": sortedRows.sort (sort_dayofweek); break;
    case "z": sortedRows.sort (sort_filesize); break;
  }
  if (reverseit)
    sortedRows.reverse();

  // re-insert the sorted data back into the table
  for (var i=1; i<table.rows.length; i++) {
    if (table.rows[i].className && 
	(table.rows[i].className.indexOf ("mu_ignore") > -1))
      continue;
    var firstElt = sortedRows.shift();
    // table.rows[i].innerHTML = sortedRows[i-1][1];
    table.rows[i].innerHTML = firstElt[1];
    table.rows[i].style.display = firstElt[2];
    table.rows[i].className = firstElt[3];
  }

  // remove all the icons
  for (var i=0; i<table.rows[0].cells.length; i++)
    muSetInnerText (
      // table.rows[0].cells[i].getElementsByClassName("mu_sort_img")[0], "");
      muGetElementsByClassName (table.rows[0].cells[i], "mu_sort_img")[0], "");
  // add the icons back for the selected column
  if (reverseit)
    /*
    table.rows[0].cells[sortCol].getElementsByClassName
      ("mu_sort_img")[0].innerHTML = "&nbsp; &#x25BC;"
    */
    muGetElementsByClassName (table.rows[0].cells[sortCol],
      "mu_sort_img")[0].innerHTML = "&nbsp; &#x25BC;"
  else
    /*
    table.rows[0].cells[sortCol].getElementsByClassName
      ("mu_sort_img")[0].innerHTML = "&nbsp; &#x25B2; "
    */
    muGetElementsByClassName (table.rows[0].cells[sortCol],
      "mu_sort_img")[0].innerHTML = "&nbsp; &#x25B2; "

  // add row coloring
  if (table.className.indexOf ("mu_odd_even") > -1)
    do_odd_even_coloring (table);
}

//---------------------------------------------------------------------
function do_odd_even_coloring (t)
//---------------------------------------------------------------------
{
  var cur = 0;
  for (var i=0; i<t.rows.length; i++) {
    if (t.rows[i].className && 
	(t.rows[i].className.indexOf ("mu_ignore") > -1))
      continue;
    if (t.rows[i].style.display.indexOf ("none") > -1)
      continue;
    if (cur % 2 == 0)
      t.rows[i].className = odd_even_change (t.rows[i].className, "even");
    else
      t.rows[i].className = odd_even_change (t.rows[i].className, "odd");
    cur++;
  }  
}

//---------------------------------------------------------------------
function odd_even_change (s, oe)
//---------------------------------------------------------------------
{
  var classes = s.split (" ");
  for (var i=0; i<s.length; i++)
    if (classes[i] == "odd" || classes[i] == "even")
      classes[i] = oe;
  return (classes.join (" "));
}

//---------------------------------------------------------------------
function sort_alpha (a,b)
//---------------------------------------------------------------------
{
  return (a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0);
}

//---------------------------------------------------------------------
function sort_alphanum (a,b)
//---------------------------------------------------------------------
{
  /*
      48  0    49  1    50  2    51  3    52  4    53  5    54  6    55 7
      56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63 ?
      64  @    65  A    66  B    67  C    68  D    69  E    70  F    71 G
      72  H    73  I    74  J    75  K    76  L    77  M    78  N    79 O
      80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87 W
      88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95 _
      96  `    97  a    98  b    99  c   100  d   101  e   102  f   103 g
     104  h   105  i   106  j   107  k   108  l   109  m   110  n   111 o
     112  p   113  q   114  r   115  s   116  t   117  u   118  v   119 w
     120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del
  */
  var aa = a[0].charCodeAt (0);
  var bb = b[0].charCodeAt (0);
  if (aa < 48 || (aa > 57 && aa < 65) || (aa > 90 && aa < 97) || bb > 123)
    return 1;
  if (bb < 48 || (bb > 57 && bb < 65) || (bb > 90 && bb < 97) || bb > 123)
    return -1;
  return (sort_alpha (a,b));
}

//---------------------------------------------------------------------
function sort_num (a,b)
//---------------------------------------------------------------------
{
  if (!a[0]) return 1;
  if (!b[0]) return -1;
  aa = parseFloat (a[0].replace (/[^0-9\.-]/g, ""));
  if (isNaN (aa)) aa = 9999;
  if (!aa && aa != 0) return 1;
  // bb = b[0].replace (/&nbsp;/g, "");
  // bb = parseFloat (bb.replace (/,/g, ""));
  bb = parseFloat (b[0].replace (/[^0-9\.-]/g, ""));
  if (isNaN (bb)) bb = 9999;
  if (!bb && bb != 0) return -1;
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function phase_to_int (x)
//---------------------------------------------------------------------
{
  var phases = new Array ("I", "II", "III", "IV", "V", "VI");
  var xp = x.indexOf ("+");
  if (xp != -1)
    return (phases.indexOf (x.substr (0, xp)));
  else
    return (phases.indexOf (x));
}

//---------------------------------------------------------------------
function sort_phase (a,b)
//---------------------------------------------------------------------
{
  var aa = phase_to_int (a[0]);
  var bb = phase_to_int (b[0]);
  return (aa<bb ? -1 : aa>bb ? 1 : a[0]<b[0] ? -1 : a[0]>b[0] ? 1 : 0);
}

//---------------------------------------------------------------------
function sort_date (a,b)
//---------------------------------------------------------------------
{
  var aa = new Date (a[0]);
  var bb = new Date (b[0]);
  if (aa == "Invalid Date" || bb == "Invalid Date")
    return (sort_date_hand (a,b));
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function two_digit_year_to_four (year)
//---------------------------------------------------------------------
{
  var yeari = parseInt (year, 10);
  if (yeari < 33)
    yeari += 2000;
  else if (yeari < 100) 
    yeari += 1900;
  return (yeari);
}

//---------------------------------------------------------------------
function get_date_hand (x)
//---------------------------------------------------------------------
{
  // Attempt #1 - string "Today"
  if (x.indexOf ("Today") != -1)
    return (new Date());

  var months = new Array ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Any");

  // Attempt #2 - string 4-14-07 or 5/19/08
  var mdy = x.match (/([0-9][0-9]*)[/-]([0-9][0-9]*)[/-]([0-9][0-9])/);
  if (mdy != null) {
    var d = new Date (months[mdy[1]-1] + " " + mdy[2] + ", " + 
      two_digit_year_to_four (mdy[3]));
    return (d);
  }

  // Attempt #3 - string 4-07 or 5/08
  var moyr = x.match (/([0-9][0-9]*)[/-]([0-9][0-9])/);
  if (moyr != null) {
    var d = new Date (months[moyr[1]-1] + " 1, " + 
      two_digit_year_to_four (moyr[2]));
    return (d);
  }

  // Attempt #4 - string Mar 08 as used for ROMs
  var month;
  for (var i=0, nm=months.length; i<nm; i++) {
    if (x.indexOf (months[i]) > -1) {
      month = months[i];
      break;
    }
  }
  var year = x.match(/\b[0-9][0-9][0-9][0-9]\b/);
  if (year==null)
    year = x.match(/\b[0-9][0-9]\b/);
  var yeari = two_digit_year_to_four (year);
  if (month && yeari) {
    var d = new Date (month + " 1, " + yeari);
    return (d);
  }

  // Attempt #5 - string 1959 e.g. 4-year date
  else if (yeari) {
    var d = new Date ("Jan 1, " + yeari);
    return (d); 
  }

  // Attempt #6 - month only
  else if (month) {
    if (month == "Any")
      var d = new Date ("Jan 1, 2009");
    else
      var d = new Date (month + " 1, 2008");
    return (d); 
  }

  return (new Date ("Jan 31, 2030"));
}

//---------------------------------------------------------------------
function sort_date_hand (a,b)
//---------------------------------------------------------------------
{
  var aa = get_date_hand (a[0]);
  var bb = get_date_hand (b[0]);
  // alert (a[0] + "->" + aa + "\n" + b[0] + "->" + bb);
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function sort_money (a,b)
//---------------------------------------------------------------------
{
  if (a[0] == "-") return 1;
  if (b[0] == "-") return -1;
  if ((a[0].indexOf ("c") > -1) && (b[0].indexOf ("$") > -1))
    return -1;
  if ((a[0].indexOf ("$") > -1) && (b[0].indexOf ("c") > -1))
    return 1;
  aa = a[0].replace ("c", "");
  bb = b[0].replace ("c", "");
  aa = aa.replace ("$", "");
  bb = bb.replace ("$", "");
  if (aa == "1/2") return -1;
  if (bb == "1/2") return 1;
  aaa = parseFloat (aa);
  bbb = parseFloat (bb);
  if (aa.indexOf ("1/2") > -1)
    aaa += 0.5;
  if (bb.indexOf ("1/2") > -1)
    bbb += 0.5;
  return (aaa<bbb ? -1 : aaa>bbb ? 1 : 0);
}

//---------------------------------------------------------------------
function level_to_int (x)
//---------------------------------------------------------------------
{
  // levels array defined at the top of the file
  var nlevels = levels.length;
  for (i=0; i<nlevels; i++) {
    if (x.indexOf (levels[i]) > -1) {
      return i;
    }
  }
  return nlevels;
}

//---------------------------------------------------------------------
function sort_level (a,b)
//---------------------------------------------------------------------
{
  var aa = level_to_int (a[0]);
  var bb = level_to_int (b[0]);
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function caller_last_name (x)
//---------------------------------------------------------------------
{
  if (x.indexOf ("/") > -1)
    return (x);
  else {
    s = x.split (" ");
    return (s[1] + " " + s[0]);
  }
}

//---------------------------------------------------------------------
function sort_caller (a,b)
//---------------------------------------------------------------------
{
  var aa = caller_last_name (a[0]);
  var bb = caller_last_name (b[0]);
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function day_to_int (x)
//---------------------------------------------------------------------
{
  // days of week array defined at the top of the file
  var ndays = days_of_week.length;
  for (i=0; i<ndays; i++)
    if (x.indexOf (days_of_week[i]) > -1)
      return i;
  return ndays;
}

//---------------------------------------------------------------------
function sort_dayofweek (a,b)
//---------------------------------------------------------------------
{
  var aa = day_to_int (a[0]);
  var bb = day_to_int (b[0]);
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

//---------------------------------------------------------------------
function filesize_to_int (x)
//---------------------------------------------------------------------
{
  if (x == "" || x == null /*|| isNaN(x)*/) return 0;
  var xx = parseFloat (x);
  if (isNaN (xx)) return 0;
  if      (x.indexOf ("K") > -1) xx *= 1000;
  else if (x.indexOf ("k") > -1) xx *= 1000;
  else if (x.indexOf ("M") > -1) xx *= 1000000;
  else if (x.indexOf ("m") > -1) xx *= 1000000;
  else if (x.indexOf ("G") > -1) xx *= 1000000000;
  else if (x.indexOf ("g") > -1) xx *= 1000000000;
  return (xx);
}

//---------------------------------------------------------------------
function sort_filesize (a,b)
//---------------------------------------------------------------------
{
  var aa = filesize_to_int (a[0]);
  var bb = filesize_to_int (b[0]);
  return (aa<bb ? -1 : aa>bb ? 1 : 0);
}

