
var grids = Array();
var cur_grid = null;

function grid_date(str) {
   var month = "";
   var day = "";
   var year = "";
   var date_array = Array();

   str = str.replace(/[^\d\/-]/g, ''); // leave only digits, slashes and dashes

   // m/d/yyyy || mm/dd/yyyy || mm/dd/yy || m-d-yyyy || mm-dd-yyyy || mm-dd-yy
   if(date_array = str.match(/^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2,4})$/)) {
		month = date_array[1];
		day = date_array[3];
		year = date_array[4];
   }

   if(year && month && day && year.length && month.length && day.length) {
      if(day.length === 1) {
         day = '0' + day;
      }
      if(month.length === 1) {
         month = '0' + month;
      }
      return year + month + day;
   }
   else {
      return str;
   }
}

function grid_num(str) {
   if((str.charAt(0) == '(') && (str.charAt(str.length-1) == ')')) {
      str = str.replace(/[^\d.]/g, ''); // leave only digits and decimal
      str = "-" + str;
   }
   else {
      str = str.replace(/[^\d.-]/g, ''); // leave only digits, decimal and minus
   }

   if(str.length) {
      return str;
   }
   else {
      return '0';
   }
}

function grid_remove_html(str) {
   if(str && str.length) {
      str = str.replace(/<[^>]+>/g, '');
      return str;
   }
   else {
      return '';
   }
}

function grid_stopPropagation(evt) {
   if(evt && evt.stopPropagation) {
      evt.stopPropagation();
   }
   else if(window.event) {
      window.event.cancelBubble = true;
   }
}

function grid_row_onmouseover() {
   if(this.className == 'odd') {
      this.className = 'odd_over';
   }
   else if(this.className == 'even') {
      this.className = 'even_over';
   }
}

function grid_row_onmouseout() {
   if(this.className == 'odd_over') {
      this.className = 'odd';
   }
   else if(this.className == 'even_over') {
      this.className = 'even';
   }
}

function header_cell_onmouseover() {
   cur_grid = this.offsetParent.id;
   grids[cur_grid].sort_col = this.cellIndex;
   this.className = 'over';
}

function header_cell_onmouseout() {
   this.className = '';
}

function num_compare(a, b) {
   if(isNaN(a)) {
      a = a.replace(/\|.*$/, '');
      a = parseFloat(a);
   }
   if(isNaN(b)) {
      b = b.replace(/\|.*$/, '');
      b = parseFloat(b);
   }
   if(!isNaN(a) && !isNaN(b)) {
      return(a - b);
   }
   return 0;
}

function get_sortable_data(my_data, data_type, row_index) {
   my_data = grid_remove_html(my_data);
   switch(data_type) {
      case 'date':
         my_data = grid_date(my_data);
         break;
      case 'str':
         my_data = my_data.toLowerCase();
         break;
      case 'istr':
         my_data = my_data.toLowerCase();
         break;
      case 'num':
         my_data = grid_num(my_data);
         break;
      default:
         break;
   }
   my_data += '|' + row_index;

   return my_data;
}

// table_id:         ID of the table (required)
// sort_col:         Zero based column number for initial sort. Default is 0 (optional)
// sort_direction:   1 for descending. 0 for ascending. Default is 0 (optional)
// selectable:       If 0, the onmouseover events will be disabled for TR elements. Default is enabled (optional)
//
function grid_init(table_id, sort_col, sort_direction, selectable) {
   if(!document.getElementById(table_id))
      return;

   if (typeof sort_col == "undefined") {
      sort_col = 0;
   }
   if (typeof sort_direction == "undefined") {
      sort_direction = 0;
   }
   if (typeof selectable == "undefined") {
      selectable = 1;
   }

   cur_grid = table_id;

   grids[cur_grid] = new Object();
   grids[cur_grid].table = document.getElementById(cur_grid);
   grids[cur_grid].table_id = cur_grid;
   grids[cur_grid].rows = Array();
   grids[cur_grid].column_count = 0;
   grids[cur_grid].column_types = Array();
   grids[cur_grid].column_labels = Array();
   grids[cur_grid].sorter = Array();
   grids[cur_grid].sort_col=sort_col;
   grids[cur_grid].last_sort_col=sort_col;
   grids[cur_grid].ascending=sort_direction;
   grids[cur_grid].selectable=selectable;

   grid_load();
}

function grid_load() {
   var i;
   var j;
   var grid = grids[cur_grid];
   var rows = grid.table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');

   // Header
   var header_cells = grid.table.getElementsByTagName('th');
   var data_type;
   grid.column_count = header_cells.length;
   for(i=0; i < grid.column_count; i++) {
      data_type = header_cells[i].id;
      grid.column_types.push(data_type);
      grid.column_labels.push(header_cells[i].innerHTML);

      if(data_type != "nosort") {
         header_cells[i].id = grid.table_id + '_col_' + i;
         header_cells[i].onmouseover = header_cell_onmouseover;
         header_cells[i].onmouseout = header_cell_onmouseout;
         header_cells[i].onclick = grid_sort;
      }
      grid.sorter.push(Array(rows.length));
   }

   // Data
   var cells = Array(grid.column_count);
   var cell_data;
   for(i=0; i < rows.length; i++) {
      cells = rows[i].getElementsByTagName('td');
      for(j=0; j < cells.length; j++) {
         cell_data = cells[j].innerHTML;
         if(grid.column_types[j] != 'nosort') {
            cell_data = get_sortable_data(cell_data, grid.column_types[j], i);
         }
         grid.sorter[j][i] = cell_data;
      }
      grid.rows[i] = rows[i].cloneNode(true);
   }
   grid_sort();
}

function grid_sort() {
   var i;
   var j;

   if(!cur_grid || !grids[cur_grid])
      return;

   var grid = grids[cur_grid];

   if(grid.sort_col == grid.last_sort_col) {
      grid.ascending = (grid.ascending ? 0 : 1);
   }
   else {
      grid.ascending = 1;
   }

   grid.last_sort_col = grid.sort_col;

   if(grid.column_types[grid.sort_col] == 'num') {
      grid.sorter[grid.sort_col].sort(num_compare);
   }
   else {
      grid.sorter[grid.sort_col].sort();
   }

   if(!grid.ascending) {
      grid.sorter[grid.sort_col].reverse();
   }

   // Header
   var column;
   for(i=0; i < grid.column_count; i++) {
      if(grid.column_types[i] != 'nosort') {
         column = document.getElementById(grid.table_id + '_col_' + i);

         if(grid.sort_col == i) {
            if(grid.ascending) {
               column.innerHTML = grid.column_labels[i] + "\u2193";
            }
            else {
               column.innerHTML = grid.column_labels[i] + "\u2191";
            }
         }
         else {
            column.innerHTML = grid.column_labels[i];
         }
      }
   }

   // Data
   var tbody_new = document.createElement("tbody");
   var tbody_old = grid.table.getElementsByTagName('tbody')[0];
   var idx;
   var node;
   var odd=0;

   for(i=0; i < grid.rows.length; i++) {
      idx = grid.sorter[grid.sort_col][i].replace(/^.*\|/, '');
      node = grid.rows[idx].cloneNode(true);
      if(odd) {
         node.className = 'odd';
         odd = 0;
      }
      else {
         node.className = 'even';
         odd = 1;
      }
      if(grid.selectable) {
         node.onmouseover = grid_row_onmouseover;
         node.onmouseout = grid_row_onmouseout;
      }
      tbody_new.appendChild(node);
   }
   grid.table.removeChild(tbody_old);
   grid.table.appendChild(tbody_new);
}
