// 1/3/8 Tim with Tom's much appreciated help!: Changed getElementsByTagName to Mochikit's getElementsByTagAndClassName so that
// we could manipulate which pieces of the table are being sorted (class="sortable"). This was needed since "everything" is in a table...
// Also added function stripNumber so columns with formatted numbers could be sorted.

/*
On page load, the SortableManager:

- Finds the table by its id (sortable_table).
- Parses its thead for columns with a "mochi:format" attribute.
- Parses the data out of the tbody based upon information given in the
  "mochi:format" attribute, and clones the tr elements for later re-use.
- Clones the column header th elements for use as a template when drawing
  sort arrow columns.
- Stores away a reference to the tbody, as it will be replaced on each sort.
- Performs the first sort.


On sort request:

- Sorts the data based on the given key and direction
- Creates a new tbody from the rows in the new ordering
- Replaces the column header th elements with clickable versions, adding an
   indicator (&uarr; or &darr;) to the most recently sorted column.

*/

SortableManager = function () {
    this.thead = null;
    this.tbody = null;
    this.columns = [];
    this.rows = [];
    this.sortState = {};
    this.sortkey = 0;
};

mouseOverFunc = function () {
    addElementClass(this, "over");
};

mouseOutFunc = function () {
    removeElementClass(this, "over");
};

ignoreEvent = function (ev) {
    if (ev && ev.preventDefault) {
        ev.preventDefault();
        ev.stopPropagation();
    } else if (typeof(event) != 'undefined') {
        event.cancelBubble = false;
        event.returnValue = false;
    }
};


update(SortableManager.prototype, {

    "initWithTable": function (table) {
        log('initWithTable', 0, true);
        /***

            Initialize the SortableManager with a table object

        ***/
        // Ensure that it's a DOM element
        table = getElement(table);
        // Find the thead
        this.thead = getElementsByTagAndClassName('thead','sortable',table)[0];
        // get the mochi:format key and contents for each column header
        var cols = getElementsByTagAndClassName('th','sortable',this.thead);
		for (var i = 0; i < cols.length; i++) {
            var node = cols[i];
            var attr = null;
            try {
                attr = node.getAttribute("mochi:format");
            } catch (err) {
                // pass
            }
            var o = node.childNodes;
            this.columns.push({
                "format": attr,
                "element": node,
                "proto": node.cloneNode(true)
            });
            //Save the original width for later disappearing
            colWidth[i] = node.clientWidth;
        }
        // scrape the tbody for data
        this.tbody = getElementsByTagAndClassName('tbody','sortable',table)[0];
        // every row
        var rows = getElementsByTagAndClassName('tr','sortable',this.tbody);
        for (var i = 0; i < rows.length; i++) {
            // every cell
            var row = rows[i];
            var cols = getElementsByTagAndClassName('td','sortable',row);
            var rowData = [];
            for (var j = 0; j < cols.length; j++) {
                // scrape the text and build the appropriate object out of it
//log('Scrape', j, true);
                var cell = cols[j];
                var obj = scrapeText(cell);
                switch (this.columns[j].format) {
                    case 'isodate':
                        obj = isoDate(obj);
                        break;
                    case 'americandate':  // added 11/4/7 Tim to format American date format
                        obj = americanDate(obj);
                        break;
                    case 'str':
                        break;
                    case 'istr':
                        obj = obj.toLowerCase();
                        break;
                    // cases for numbers, etc. could be here
                    case 'number':  // added 1/3/8 Tim from
                    // http://groups.google.com/group/mochikit/browse_thread/thread/d431c8265d72c981/4eb5853625a310ed?#4eb5853625a310ed
                        obj = parseFloat(stripNumber(obj));  // 1/3/8 added stripNumber to delete extra formatting of numbers in sort
                        break;
                    case 'urcnumber':  // added 1/8/8 Tim Modified above to hanle N/A
                        //log(obj, stripNumber(obj), parseFloat(stripNumber(obj)));
                        if (isNaN(parseFloat(stripNumber(obj)))) {
                          obj = -1000;  // sort lower than zero or -99%
                          }
                        else {
                          obj = parseFloat(stripNumber(obj));  // 1/3/8 added stripNumber to delete extra formatting of numbers in sort
                          }
                        break;
                    default:
                        break;
                }
                rowData.push(obj);
            }
            // stow away a reference to the TR and save it
            rowData.row = row.cloneNode(true);
            this.rows.push(rowData);

        }

        // do initial sort on first column
        this.drawSortedRows(this.sortkey, true, false);

    },

    "onSortClick": function (name) {
//        log('onSortClick', 1, true);
        /***

            Return a sort function for click events

        ***/
        return method(this, function () {
            //log('onSortClick', name);
            var order = this.sortState[name];
            if (order == null) {
                order = true;
            } else if (name == this.sortkey) {
                order = !order;
            }
            this.drawSortedRows(name, order, true);
        });
    },

    "drawSortedRows": function (key, forward, clicked) {
        /***

            Draw the new sorted table body, and modify the column headers
            if appropriate

        ***/
        log('drawSortedRows', key, forward);
        this.sortkey = key;
        // sort based on the state given (forward or reverse)
        var cmp = (forward ? keyComparator : reverseKeyComparator);
        this.rows.sort(cmp(key));
        // save it so we can flip next time
        this.sortState[key] = forward;
        // get every "row" element from this.rows and make a new tbody
        var newBody = TBODY(null, map(itemgetter("row"), this.rows));
        // swap in the new tbody
        this.tbody = swapDOM(this.tbody, newBody);
        for (var i = 0; i < this.columns.length; i++) {
            var col = this.columns[i];
            var node = col.proto.cloneNode(true);
            // remove the existing events to minimize IE leaks
            col.element.onclick = null;
            col.element.onmousedown = null;
            col.element.onmouseover = null;
            col.element.onmouseout = null;
            // set new events for the new node
            node.onclick = this.onSortClick(i);
            node.onmousedown = ignoreEvent;
            node.onmouseover = mouseOverFunc;
            node.onmouseout = mouseOutFunc;
            // if this is the sorted column
            if (key == i) {
                // \u2193 is down arrow, \u2191 is up arrow
                // forward sorts mean the rows get bigger going down
                var arrow = (forward ? "\u2193" : "\u2191");
				//var arrow = (forward ? "\u21E7" : "\u21E9");  // http://unicode.org/charts/symbols.html
                // add the character to the column header
                node.appendChild(SPAN(null, arrow));
                if (clicked) {
                    node.onmouseover();
                }
            }

            // swap in the new th 
						
//            if (col.element.style.display!="none" && // Tim 8/11/8 if visible 
//                !hasElementClass(col.element, 'hidden')
//						   )  
                col.element = swapDOM(col.element, node);
        }
				
			if($('tabs'))
			{
				var tabs = getElementsByTagAndClassName('*', 'tab', 'tabs');
				
				var tabCount = tabs.length;
				for(var t=0; t<tabCount; t++)
				{
					if(hasElementClass(tabs[t], 'selected'))
					{
						tabs[t].onclick();
					}
				}
					
			}
    }
});

function stripNumber(string) {  // Strip off everthing that is not part of number: digits, Negative sign, and decimal
    for (var i=0, output='', valid="1234567890-."; i<string.length; i++)
       if (valid.indexOf(string.charAt(i)) != -1)
          output += string.charAt(i)
    return output;
}


  var sortableManager = new SortableManager();

/*
switch(selfName)
{
case 'index.php':
  var sortableManager = new SortableManager();
  break;    
case 'school.php':
  var sortableManager = new SortableManager();
  break;
case 'chart.php':
  var sortableManager = new SortableManager();
  break;
case 'meter.php':
  break;
default:
  var sortableManager1 = new SortableManager();
  var sortableManager2 = new SortableManager();
  var sortableManager3 = new SortableManager();
}
*/
/*
  var sortableManager1 = new SortableManager();
  var sortableManager2 = new SortableManager();
  var sortableManager3 = new SortableManager();
*/
//alert('Help');

var colWidth = [];  // Keep track of column widths for disappearing magic

addLoadEvent(function () {
/*
  switch(selfName)
  {
  case 'index.php':
    sortableManager.initWithTable('sortable_table');
    break;    
  case 'school.php':
    sortableManager.initWithTable('sortable_table');
    break;
  case 'chart.php':
    sortableManager.initWithTable('sortable_table');
    break;
  case 'meter.php':
    break;
  default:
    sortableManager1.initWithTable('sortable_table1');
    sortableManager2.initWithTable('sortable_table2');
    sortableManager3.initWithTable('sortable_table3');
  }
*/

    if(getElement('sortable_table')) sortableManager.initWithTable('sortable_table');
		for(var i=0;i<20;i++)
		{
			if(getElement('sortable_table'+i)) sortableManager.initWithTable('sortable_table'+i);
		}
		
		
//alert("sortableManager1");
/*
    sortableManager1.initWithTable('sortable_table1');
    sortableManager2.initWithTable('sortable_table2');
    sortableManager3.initWithTable('sortable_table3');
*/
});

function submitForm(element)
{
	//log("SELECT:", element.name);
	//log("SELECT.VALUE:", element.value);
	//log("FORM:", element.form);
	//log("    ACTION:", element.form.action);
	var regx = RegExp('('+element.name+'=)(.+?)(&|$)');  //match everything till next '&' or end of string '$'
	window.location.href = element.form.action.replace(regx, '$1'+element.value+'$3');
	//log("NEW ACTION:", element.form.action);
	//logDebug("regexp:", regx);
	//element.form.submit();
}

