// new-sortable.js
// My first go at a sortable table, starting with code from
//  http://www.builder.com/Programming/Scripter/080999/index.html
// Augmented it to provide sorting in either direction, and
//  changed <form> approach to <a href onClicks>
//  Use "#tables" anchor to keep from jerking to the top of the
//  page.  Should be failsafe if not present, but is a problem
//  if you need more than one anchor.
// Made NAN fields for numeric columns sort as big (positive)
//  numbers to make P/E work correctly
// Tom von Alten
// 2001-03-10
// 2002-12-30  Corrected "dnbtn" error
// 2003-09-30  Omit sort arrows for null-labeled column

function Sortable(id,rows,cols,border,width,align) {
 this.id = id;
 this.rows = rows;
 this.cols = cols;
 this.border = border;
 this.width = width;
 this.align = align;
 this.buttons = new Array(cols);
 this.numeric = new Array(cols);
 this.data = new Array(rows);
 for(var i=0;i<rows;++i) {
  this.data[i] = new Array(cols);
  for(var j=0;j<cols;++j)
   this.data[i][j] = " ";  // for format neatness?
   this.buttons[j] = " ";
   this.numeric[j]=false;
 }
 // point to functions
 this.display = Sortable_display;
 this.setButtons = Sortable_setButtons;
 this.buttonRow = Sortable_buttonRow;
 this.setData = Sortable_setData;
 this.setNumeric = Sortable_setNumeric;
 this.sort = Sortable_sort;
}

function Sortable_setData(data) {
 if(data == null) return;
 if(data.length > 0) {
  for(var i=0;i<this.rows;++i) {
   if(i>=data.length) break;
   if(data[i] != null) {
    var n = data[i].length;
    if(n > this.cols) n = this.cols;
    for(var j=0;j<n;++j)
     if(data[i][j]!=null) this.data[i][j] = data[i][j];
   }
  }
 }
}

function Sortable_setButtons(buttons) {
 if(buttons == null) return;
 var n = buttons.length;
 if(n > this.cols) n = this.cols;
 for(var i=0;i<n;++i)
  if(buttons[i]!=null) this.buttons[i] = buttons[i];
}

function Sortable_buttonRow() {
 // Table row of headers with sort links
 document.writeln('<tr>');
 // relative path has to be relative to the page that uses this, not
 // this script itself. :-/
 var dnbtn = '<img src="/images/widgets/dnarrow.gif" border="0" width="15"';
 dnbtn = dnbtn + ' height="9" alt="dn">';
 var upbtn = '<img src="/images/widgets/uparrow.gif" border="0" width="15"';
 upbtn = upbtn + ' height="9" alt="up">';
 var preamble = '<a href="#tables" onClick="Sort_cookie(\'';
 var asuffix = 'onMouseOver="window.status=\'Sort ascending by this column\'';
 var asuffix = asuffix + ';return true" onMouseOut="window.status=\'\'">';
 var dsuffix = 'onMouseOver="window.status=\'Sort descending by this column\'';
 var dsuffix = dsuffix + ';return true" onMouseOut="window.status=\'\'">';
 for(var i=0;i<this.cols;++i) {
  document.write('<th>');
  if(this.buttons[i].length == 0) {
   document.write('</th>');
  }else{
   document.write(preamble + this.id + '\',' + i + ')" ');
   document.write(asuffix + upbtn + '</a><br />');
   document.write(this.buttons[i]+'<br />');
   // Add 1000 to the column number to signal reverse sort
   document.write(preamble + this.id + '\',' + (1000+i) + ')" ');
   document.write(dsuffix + dnbtn + '</a></th>');
  }
 }
 document.writeln('</tr>');
}

function Sortable_display() {
 // Check for tableSortBy cookie
 if(document.cookie.length > 0) {
  var search = this.id + "=";
  var offset = document.cookie.indexOf(search) ;
  if(offset != -1) { 
   offset += search.length ;
   var end = document.cookie.indexOf(";", offset) ;
   if(end == -1) end = document.cookie.length;
   var sortcol = document.cookie.substring(offset, end);
   if (sortcol >= 1000) { // reverse sort
     this.sort(sortcol-1000,true);
   }else{
     this.sort(sortcol,false);
   }
  }   
 }
 document.write('<table border="'+this.border+'" width="');
 document.writeln(this.width+'" align="'+this.align+'">');
 document.writeln('<tr>');
 this.buttonRow();
 //
 // Display sorted/unsorted table
 for(var i=0;i<this.rows;++i) {
  document.writeln('<tr>');
  for(var j=0;j<this.cols;++j) {
   if(this.numeric[j]) {
    document.write('<td align="right">');
   }else{
    document.write('<td>');
   }
   document.write(this.data[i][j]);
   document.writeln('</td>');
  }
  document.writeln('</tr>');
 }
 this.buttonRow()
 document.writeln('</table>')
}

function Sort_cookie(id,n) { // Set cookie and reload
 document.cookie = id + "=" + n;
 window.location.reload();
}

function Sortable_setNumeric(n) { this.numeric[n] = true }

function Sortable_sort(n,reversedir) {
 // Sort rows ascending
 var changes=true;
 for(;changes;) {
  changes = false
  for(var i=0;i<this.rows-1;++i) {
   if(this.numeric[n]) {
    var v1 = parseFloat(this.data[i][n]);
    if(isNaN(v1)) v1 = 10000000;
    var v2 = parseFloat(this.data[i+1][n]);
    if(isNaN(v2)) v2 = 10000000;
    if(v1 > v2) {
     changes = true;
     var temp = this.data[i];
     this.data[i] = this.data[i+1];
     this.data[i+1] = temp;
    }   
   }else{
    if(this.data[i][n] > this.data[i+1][n]) {
     changes = true;
     var temp = this.data[i];
     this.data[i] = this.data[i+1];
     this.data[i+1] = temp;
    }
   }
  }
 } 
 // Reverse, if called for
 if (reversedir) this.data.reverse();
}
