addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;
var sortUp;
var headerRowCount=0;
var tmpcnt=0;

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];        
        if (((' '+thisTbl.className+' ').indexOf("sort") != -1) && (thisTbl.id)) {
            //initTable(thisTbl.id);
            ts_makeSortable(thisTbl);                                    
        }
    }
}

function ts_makeSortable(table) {
    if (table.rows && table.rows.length > 0) {
        // do thead
        if (table.tHead && table.tHead.rows.length > 0){
            ts_makeHeaderRow(table.tHead.rows[table.tHead.rows.length-1]);                   
        }
        
        // do any tbodies with class thead
        for (var idx=0; idx<table.tBodies.length; idx++) {        
            if ((' '+table.tBodies[idx].className+' ').indexOf("thead") != -1) {
                ts_makeHeaderRow(table.tBodies[idx].rows[table.tBodies[idx].rows.length-1]);                       
            }
        }            
          
    }        
}

function ts_makeHeaderRow(row) {
    for (var i=0;i<row.cells.length;i++) {
        var cell = row.cells[i];
        if ((' '+cell.className+' ').indexOf("nosort") == -1) {
			var txt = cell.innerHTML; //ts_getInnerText(cell);
			cell.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this,' + i + ');return false;">'+txt+'<span class="sortarrow"></span></a>';
		}
    }
}

function ts_getInnerText(el) {
	//alert(typeof el);
	if (typeof el == "string") return el;
	if (typeof el == "undefined") {return '';}
	if (el.innerText) return el.innerText;	//Not needed but it is faster
	var str = "";
	var done = false;
	
	var cs = el.childNodes;
	var l = cs.length;
	
	for (var i = 0; i < l; i++) {
	    if (done==true) break;
	    
	    //if (tmpcnt==0) alert(cs[i].nodeType);
	    switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE				
				if (cs[i].nodeName=="SELECT") {
				    str +=cs[i].options[cs[i].selectedIndex].value;
				    done=true;				    
				}
				else {
				    str += ts_getInnerText(cs[i]);				
				}
				break;
			case 3:	//TEXT_NODE
				str += cs[i].nodeValue;				
				break;
		}
		
		//if (tmpcnt==1) alert(i + ": $" + str + "$");
		
		//if (tmpcnt==1) alert(i + ": $" + str + "$");		
	}
	str=str.replace(/\n/g, ""); // remove newlines
	str=str.replace(/\t/g, ""); // remove tabs
	str=str.replace(/\s /g, "");   // remove spaces
	return str;
}

function ts_resortTable(lnk, cellIndex) {
    // get the span
    var span;
    var cellClass;
    var highlightIndex;
    
    for (var ci=0;ci<lnk.childNodes.length;ci++) {		
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    //var column = td.cellIndex;
    
    var column = cellIndex || td.cellIndex;
    var table = getParent(td,'TABLE');
    
    // Set default sort direction
    if (span.getAttribute("sortdir")==null) {
		if ((' '+td.className+' ').indexOf("sortasc") != -1) {
			span.setAttribute('sortdir','up');
		}
		else
			span.setAttribute('sortdir','down');
    }
    
    // Work out a type for the column
    if (table.rows.length <= 1) return;
    
    if ((' '+td.className+' ').indexOf("sortpos") != -1) {
		sortfn = ts_sort_position;
	}
	else if ((' '+td.className+' ').indexOf("sortgrade") != -1) {
		sortfn = ts_sort_grade;
	}
	else if ((' '+td.className+' ').indexOf("sortheight") != -1) 
    {
		sortfn = ts_sort_height;
	}
	else if ((' '+td.className+' ').indexOf("sortrecord") != -1) 
    {
		sortfn = ts_sort_record;
	}
	else if ((' '+td.className+' ').indexOf("sortclass") != -1) 
    {
		sortfn = ts_sort_class;
	}
	else if ((' '+td.className+' ').indexOf("sortsmalldate") != -1) 
    {
		sortfn = ts_sort_smalldate;
	}
	else if ((' '+td.className+' ').indexOf("sortdatetime") != -1) 
    {
		sortfn = ts_sort_datetime;
	}	
	else if ((' '+td.className+' ').indexOf("sortmoney") != -1) 
    {
		sortfn = ts_sort_currency;
	}
	else if ((' '+td.className+' ').indexOf("sortrank") != -1) 
    {
		sortfn = ts_sort_rank;
	}
	else if ((' '+td.className+' ').indexOf("sortWithText") != -1) 
	{
		sortfn = ts_sort_numWithText;
	}
    else {
        var itm;        
        var iIdx = 0;
        
        for (idx=0; idx<table.tBodies.length; idx++) {
            if (((' '+table.tBodies[idx].className+' ').indexOf("thead") == -1) && ((' '+table.tBodies[idx].className+' ').indexOf("tfoot") == -1)) {
		        itm = ts_getInnerText(table.tBodies[idx].rows[0].cells[column]);    
		        if (escape(itm)=='%A0' || escape(itm)=='%20') itm=="";
		    }
		    if (itm && itm.length > 0) break;
        }
        
        //alert(itm);
		sortfn = ts_sort_caseinsensitive;
		
		if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
		if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
		if (itm.match(/^[£$]/)) sortfn = ts_sort_currency;
		if (itm.match(/^[+-]?[\d\.]+$/)) sortfn = ts_sort_numeric;
    }
    
    //alert(sortfn);
    SORT_COLUMN_INDEX = column;
    
    var newRows = new Array();    
    var oldRows;
    var footerRows = new Array();
    var sortDirection;
    
    sortDirection = span.getAttribute("sortdir");
    
    if (sortDirection == 'down') {
        sortUp = 0;
    } else {
        sortUp = 1;
    }
    
    // loop through tbodies
    for (idx=0; idx<table.tBodies.length; idx++) {
        //alert(table.tBodies[idx].className);
        if (((' '+table.tBodies[idx].className+' ').indexOf("thead") == -1) && ((' '+table.tBodies[idx].className+' ').indexOf("tfoot") == -1)) {
            // clear arrays
            newRows.length = 0;
            footerRows.length = 0;
        
            // Get old rows collection
            oldRows = table.tBodies[idx].rows;
            
            // copy to array for sorting
            for (idx2=0; idx2<oldRows.length; idx2++) {
                if (oldRows[idx2].className.indexOf('tfoot') == -1) {
                    newRows[idx2] = oldRows[idx2];
                }
                else {
                    footerRows[footerRows.length] = oldRows[idx2];
                }
            }        
            
            // perform sort
            newRows.sort(sortfn);
            
            // Handle sort direction        
            if (sortDirection == 'down') {
                newRows.reverse();            
            } 
            
            // Set correct row class
            var rowCount=0;
            for (j=0;j<newRows.length;j++) { 		
		        newRows[j].className=newRows[j].className.replace("even","");
		        newRows[j].className=newRows[j].className.replace("odd","");
        		
		        if (rowCount % 2){newRows[j].className+=' even';}
		        else {newRows[j].className+=' odd';}
        		
		        // Set highlight on column
		        for (k=0;k<newRows[j].cells.length;k++) { 		
			        newRows[j].cells[k].className = newRows[j].cells[k].className.replace("highlight","");
        		
			        if (k==SORT_COLUMN_INDEX) {				
				        newRows[j].cells[k].className += ' highlight';
			        }			    
		        }
        		
		        rowCount++;
	        }
        	
            // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
            for (i=0; i<newRows.length; i++) { 
		        table.tBodies[idx].appendChild(newRows[i]);    		
	        }	 
    	    
	        // do footer rows     
            for (i=0; i<footerRows.length; i++) { 
		        table.tBodies[idx].appendChild(footerRows[i]);		
	        }	   
        }
    }
        
    // Handle sort direction
    if (sortDirection == 'down') {        
        sortDirection = 'up';
    } 
    else {
        sortDirection = 'down';
    }
    
    // set sort direction for all header row links
    // do thead
    if (table.tHead && table.tHead.rows.length > 0){
        setSortDir(table.tHead.rows[table.tHead.rows.length-1], sortDirection);
    }
    
    
    // do any tbodies with class thead
    for (var idx=0; idx<table.tBodies.length; idx++) {        
        if ((' '+table.tBodies[idx].className+' ').indexOf("thead") != -1) {            
            setSortDir(table.tBodies[idx].rows[table.tBodies[idx].rows.length-1], sortDirection);
        }
    }  
   	
    tmpcnt=0;

}

function setSortDir(row, direction){
    var headerSpan;
    var headerLink;
    
    headerLink = row.cells[SORT_COLUMN_INDEX].childNodes[0];
    for (var i=0; i<headerLink.childNodes.length; i++) {		
        if (headerLink.childNodes[i].tagName && headerLink.childNodes[i].tagName.toLowerCase() == 'span') headerSpan = headerLink.childNodes[i];
    }        
    headerSpan.setAttribute('sortdir', direction);
}

function getParent(el, pTagName) {
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
		return el;
	else
		return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
    } else {
        yr = aa.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
    } else {
        yr = bb.substr(6,2);
        if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
        dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
    }
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_datetime(a,b) {
    // format mm/dd/yyyy hh:mm [am/pm]
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    
    dt1 = new Date(aa);
    dt2 = new Date(bb);
    
    if (!dt1.getMonth()) return -1;
    if (!dt2.getMonth()) return 1;
    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_smalldate(a,b) {
    // small dates are just mon/day (i.e. 2/15)
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    
    aa = aa + '/2000';
    bb = bb + '/2000';
    dt1 = new Date(aa);
    dt2 = new Date(bb);

    if (dt1==dt2) return 0;
    if (dt1<dt2) return -1;
    return 1;
}

function ts_sort_currency(a,b) { 
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,''));
    if (isNaN(aa)) aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,''));
	if (isNaN(bb)) bb = 0;
	return aa-bb;
}

function ts_sort_numeric(a,b) { 
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) aa = -1;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX])); 
    if (isNaN(bb)) bb = -1;
    return aa-bb;
}

function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    
    if (aa==bb) return 0;
    if (aa==" " || aa<bb) return -1;
    return 1;
}

function ts_sort_position(a,b) {
    var a_adj, b_adj;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    
    switch (aa){
		case 'qb': a_adj=11; break;
		case 'rb': a_adj=10; break;
		case 'wr': a_adj=9; break;
		case 'te': a_adj=8; break;
		case 'ol': a_adj=7; break;
		case 'dl': a_adj=6; break;
		case 'lb': a_adj=5; break;
		case 'db': a_adj=4; break;
		case 'k': a_adj=3; break;
		case 'p': a_adj=2; break;
		default: a_adj=1;
	}
	switch (bb){
		case 'qb': b_adj=11; break;
		case 'rb': b_adj=10; break;
		case 'wr': b_adj=9; break;
		case 'te': b_adj=8; break;
		case 'ol': b_adj=7; break;
		case 'dl': b_adj=6; break;
		case 'lb': b_adj=5; break;
		case 'db': b_adj=4; break;
		case 'k': b_adj=3; break;
		case 'p': b_adj=2; break;
		default: b_adj=1;
	}
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
}

function ts_sort_class(a,b) {
    var a_adj, b_adj;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    
    aa = aa.replace('*', '');
    bb = bb.replace('*', '');
    
    switch (aa){
		case 'fr.': 
		case 'freshman': 
		    a_adj=1; break;		
		case 'so.': 
		case 'sophomore': 
		    a_adj=2; break;
		case 'jr.': 
		case 'junior': 
		    a_adj=3; break;
		case 'sr.': 
		case 'senior': 
		    a_adj=4; break;		
		default: a_adj=5;
	}
	switch (bb){
		case 'fr.': 
		case 'freshman': 
		    b_adj=1; break;		
		case 'so.': 
		case 'sophomore': 
		    b_adj=2; break;
		case 'jr.': 
		case 'junior': 
		    b_adj=3; break;
		case 'sr.': 
		case 'senior': 
		    b_adj=4; break;		
		default: b_adj=5;
	}
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
}

function ts_sort_rank(a,b) { 
    var a_adj, b_adj;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    
    // &nbsp is char code 160
    if (isNaN(aa) || aa.charCodeAt(0)==160) a_adj = 99999;
    else a_adj = parseFloat(aa);    
    
    if (isNaN(bb) || bb.charCodeAt(0)==160) b_adj = 99999;
    else b_adj = parseFloat(bb);
    
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
    
}

function ts_sort_grade(a,b) {
    var a_adj, b_adj;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    
    switch (aa){
		case 'a+': a_adj=1; break;
		case 'a':  a_adj=2; break;
		case 'a-': a_adj=3; break;
		case 'b+': a_adj=4; break;
		case 'b':  a_adj=5; break;
		case 'b-': a_adj=6; break;
		case 'c+': a_adj=7; break;
		case 'c':  a_adj=8; break;
		case 'c-': a_adj=9; break;
		case 'd+': a_adj=10; break;
		case 'd':  a_adj=11; break;
		case 'd-': a_adj=12; break;		
		default: a_adj=13;
	}
	switch (bb){
		case 'a+': b_adj=1; break;
		case 'a':  b_adj=2; break;
		case 'a-': b_adj=3; break;
		case 'b+': b_adj=4; break;
		case 'b':  b_adj=5; break;
		case 'b-': b_adj=6; break;
		case 'c+': b_adj=7; break;
		case 'c':  b_adj=8; break;
		case 'c-': b_adj=9; break;
		case 'd+': b_adj=10; break;
		case 'd':  b_adj=11; break;
		case 'd-': b_adj=12; break;		
		default: b_adj=13;
	}
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
}

function ts_sort_height(a,b) {
    var a_adj, b_adj, i;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX], false).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX], false).toLowerCase();
    
    a_adj = Number(aa.charAt(0) * 12) + Number(aa.substring(2, aa.length-1));
        
    b_adj = Number(bb.charAt(0) * 12) + Number(bb.substring(2, bb.length-1));
    
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
}

function ts_sort_record(a,b) {
    var a_adj, b_adj, i;
    var a_wins, a_losses, b_wins, b_losses;
    
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX], false).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX], false).toLowerCase();
   
    i = aa.indexOf('-');
    if (i == -1)
		a_adj = Number(-1);		
	else {
		a_wins = Number(aa.substring(0,i));
		a_losses = Number(aa.substring(i+1));
		//a_adj = wins; //wins / (wins+losses);
	}
		
    i = bb.indexOf('-');
    if (i == -1)
		b_adj = Number(-1);
	else {
		b_wins = Number(bb.substring(0,i));
		b_losses = Number(bb.substring(i+1));
		//b_adj = wins; //wins / (wins+losses);
	}
	
	if (a_wins==b_wins) {
		a_adj = -a_losses;
		b_adj = -b_losses;    
    }
    else {
        a_adj = a_wins;
        b_adj = b_wins;
    }
    	    
    if (a_adj==b_adj) return 0;
    if (a_adj<b_adj) return -1;
    return 1;
}

function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) return 0;
    if (aa<bb) return -1;
    return 1;
}
function ts_sort_numWithText(a,b) { 
	var naValue = 0;
	
	if (sortUp == 1) {
		naValue = 1000000;
	}
	if (ts_getInnerText(a.cells[SORT_COLUMN_INDEX], false) == "N/A" || ts_getInnerText(a.cells[SORT_COLUMN_INDEX], false) == "NA")
		aa = naValue;
	else
		aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX], false));
		
    if (isNaN(aa)) aa = -1;
    
    if (ts_getInnerText(b.cells[SORT_COLUMN_INDEX], false) == "N/A" || ts_getInnerText(b.cells[SORT_COLUMN_INDEX], false) == "NA")
		bb = naValue;
	else
		bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX], false)); 
		
    if (isNaN(bb)) bb = -1;
    return aa-bb;
}

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
    elm.addEventListener(evType, fn, useCapture);
    return true;
  } else if (elm.attachEvent){
    var r = elm.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
  }
} 
