/*
Library for creating a sortable table. Depends on there being thead/td and tbody in the table.

This needs to find any table which has a "sortable" class, and make the headers
clickable to sort the table. 

Martin Holmes September 2011. TO BE COMPLETED.
*/

//Add an event listener to the onload event.
if (window.addEventListener) window.addEventListener('load', makeTablesSortable, false)
else if (window.attachEvent) window.attachEvent('onload', makeTablesSortable);

//The array used to stash table rows before
//sorting them.
rows = new Array();

//A class for containing a row and associated sort key.
function RowObj(){
  this.row = null;
  this.sortKey = '';
}

//Up and down pointing triangles used for showing direction of sort.
//var upTriangle = '&#x25b2;';
//var downTriangle = '&#x25bc;';
var upTriangle = '\u25b2';
var downTriangle = '\u25bc';

//Utility function.
String.prototype.trim = function () {
    return this.replace(/^\s*/, "").replace(/\s*$/, "");
}

function makeTablesSortable(){
//Find each table with the correct class attribute and make them sortable.
  var tables = document.getElementsByTagName('table');
  for (var i=0; i<tables.length; i++){
    if (tables[i].className.search(/\bsortable\b/) != -1) {
        makeSortable(tables[i]);
    }
  }
}

function makeSortable(table){
  var headers = table.getElementsByTagName('th');
  if (headers.length < 1){
    var theads = table.getElementsByTagName('thead');
    if (theads.length > 0){
      headers = theads[0].getElementsByTagName('td');
    }
  }
  for (var i=0; i<headers.length; i++){
    headers[i].style.cursor = 'pointer';
    headers[i].setAttribute('onclick', 'sortByCol(this, ' + i + ')');
    headers[i].setAttribute('title', 'Click to sort the table by this column.');
  }
}

function sortByCol(sender, sortCol){
//Clear the existing array.
  rows = [];
  
//Get a pointer to the ancestor table element.
  var table = sender;
  while (table.tagName.toLowerCase() != 'table'){
    table = table.parentNode;
  }

//Find its tbody. Assume there's only one.
  var tbodies = table.getElementsByTagName('tbody')
  if (tbodies.length <1) return;
  
  tbody = tbodies[0];
  
//This is used to check what kind of data we're sorting on.
  var textSort = false;
  
//Detach all the rows.
  var tbodyRows = tbody.getElementsByTagName('tr');
  
  for (var i=tbodyRows.length-1; i>=0; i--){
    var rowCells = tbodyRows[i].getElementsByTagName('td');

    var sortKey = '';
    if (rowCells.length > sortCol){
      sortKey = rowCells[sortCol].textContent.toLowerCase().trim();
      
      if (sortKey.length > 0){
        textSort = (isNaN(sortKey) || textSort);
      }
    }
    rowObj = new RowObj();
    rowObj.row = tbodyRows[i].parentNode.removeChild(tbodyRows[i]); 
    rowObj.sortKey = sortKey;
    rows.push(rowObj);
  }

var sortAsc = true;

//Now figure out which direction to sort in.
var triangle = document.getElementById('sortTriangle');
if (triangle != null){
  if (triangle.parentNode == sender){
    if (triangle.textContent == downTriangle){
      sortAsc = false;
      triangle.textContent = upTriangle;
    }
    else{
      triangle.textContent = downTriangle;
    }
  }
  else{
    sender.appendChild(triangle.parentNode.removeChild(triangle));
    triangle.textContent = downTriangle;
  }
}
else{
  triangle = document.createElement('span');
  triangle.style.paddingLeft = '0.5em';
  triangle.setAttribute('id', 'sortTriangle');
  triangle.textContent = downTriangle;
  sender.appendChild(triangle);
}

//Sort them.
  if (textSort == true){
    sortAsc ? rows.sort(textSortAsc) : rows.sort(textSortDesc);
  }
  else{
    sortAsc ? rows.sort(numSortAsc) : rows.sort(numSortDesc);
  }

//Re-attach them to tbody.
  for (var i=0; i<rows.length; i++){
    tbody.appendChild(rows[i].row);
  }
}

//Comparator functions
function textSortAsc(a, b){
//alert(a.sortKey + ' : ' + b.sortKey + ' = ' + ((a.sortKey < b.sortKey) ? -1: ((a.sortKey > b.sortKey) ? 1 : 0)));
  return ((a.sortKey < b.sortKey) ? -1: ((a.sortKey > b.sortKey) ? 1 : 0));
}
function textSortDesc(a, b){
  return ((b.sortKey < a.sortKey) ? -1: ((b.sortKey > a.sortKey) ? 1 : 0));
}
function numSortAsc(a, b){
  return (parseFloat(a.sortKey) - parseFloat(b.sortKey));
}
function numSortDesc(a, b){
  return (parseFloat(b.sortKey) - parseFloat(a.sortKey)); 
}


