// e.g.: MainTableForm.asp?rsID=0&fcn=getDetails&id=3379&value=2
/* 
	These javascript routines come from years of compliling the 
	best of the best from various web scripts. Some are written from scratch
	others are modifications of snippets or ideas found around the world. 
	NOTE: Most of what I've learned and have written over the years comes from knowledge gained
	through Danny Goodman's JavaScript Bible! (several well worn Editions). Thanks Danny.
	-Geoff Inglis University of Rochester, Dept of Environmental Medicine
*/
// Test for the Global var targetPageWithArgs, it must be globaly defined in calling page.
   if(!window.targetPageWithArgs) { 
      targetPageWithArgs = "ERROR ** 'targetPageWithArgs' MUST be defined in main, Row ID="
	alert(targetPageWithArgs);
   };
// define the template&args to call on dbl Click Row (put in main page)
// e.g., var targetPageWithArgs="template.asp?nav=FRSEncExp&fldExpid=";



function getFormWithDetail(IDandCat) {
	if (IDandCat) {
/* use this with '-' seperator for more than one arg, value is ID of ROW e.g. <tr ID="123"> or <tr ID="123-456">
	  var parts = IDandCat.split("-");
	  var value = parts[1];
	  var id    = parts[0];
*/
	  var value = IDandCat;
	} else {
	  var value = "";
//	  var id    = "";
	}
	  // alert("GetRecordDetail.asp?fcn=getDetails&id="+id+"&value="+value);
	  // alert(targetPageWithArgs+value);
	     location = targetPageWithArgs+value;
	  // os("GetRecordDetail.asp?fcn=getDetails&id="+id+"&value="+value);
}


function e(E){
        return document.getElementById(E);
}

function initTableOnly(tableID){ //call once FOR EACH sortable table 
      T = new SortableTable(e(tableID));
}

function SortableTable(oTable, oSortTypes) {

	this.element = oTable;
	this.tHead = oTable.tHead;
	this.tBody = oTable.tBodies[0];
	this.document = oTable.ownerDocument || oTable.document;
	
	this.sortColumn = null;
	this.descending = null;
	
	this.selectedRow = null;
	this.selectedCol = null;
	
	var oThis = this;
	this._mOver = function (e) {
		oThis.onmouseover(e);
	};
	this._mOut = function (e) {
		oThis.onmouseout(e);
	};
	this._onClick = function (e) {
		oThis.onclick(e);
	};
	this._dblClick = function (e) {
		oThis.ondblclick(e);
	};
	
	// only IE needs this
	var win = this.document.defaultView || this.document.parentWindow;
	this._onunload = function () {
		oThis.destroy();
	};
	if (win && ("attachEvent" in win)) {
		win.attachEvent("onunload", this._onunload);
	}
	
	this.init(oSortTypes || []);
}

SortableTable.gecko = navigator.product == "Gecko";
SortableTable.msie = /msie/i.test(navigator.userAgent);
// Mozilla is faster when doing the DOM manipulations on
// an orphaned element. MSIE is not
SortableTable.removeBeforeSort = SortableTable.gecko;

SortableTable.prototype.onsort = function () {};

// adds arrow containers and events
// also binds sort type to the header cells so that reordering columns does
// not break the sort types
SortableTable.prototype.init = function (oSortTypes) {
	var a = document.createElement("SPAN");
	var tn = document.createTextNode("6");
	a.appendChild(tn);
	a.className = "arrow";
	this.tHead.arrow = a;

	var cells = this.tHead.rows[0].cells;
	var l = cells.length;
	var c;
	for (var i = 0; i < l; i++) {
		c = cells[i];
		if (oSortTypes[i] != null) {
			c._sortType = oSortTypes[i];
		}
	}

	var t = this.element;
	if ("addEventListener" in t){
		t.addEventListener("click", this._onClick, false);
		t.addEventListener("dblclick", this._dblClick, false);
		t.addEventListener("mouseover", this._mOver, false);	
		t.addEventListener("mouseout", this._mOut, false);
	}
	else if ("attachEvent" in t){
		t.attachEvent("onclick", this._onClick);
		t.attachEvent("ondblclick", this._dblClick);
		t.attachEvent("onmouseover", this._mOver);
		t.attachEvent("onmouseout", this._mOut);
	}
};

// remove arrows and events
SortableTable.prototype.unInit = function () {
	var t = this.element;
	if ("removeEventListener" in t){
		t.removeEventListener("click", this._onClick, false);
		t.removeEventListener("mouseover", this._mOver, false);	
		t.removeEventListener("mouseout", this._mOut, false);
	}
	else if ("detachEvent" in t){
		t.detachEvent("onclick", this._onClick);
		t.detachEvent("onmouseover", this._mOver);
		t.detachEvent("onmouseout", this._mOut);
	}

};

SortableTable.prototype.updateHeaderArrows = function () {
	var hCell = this.tHead.rows[0].cells[this.sortColumn];
	var p = this.tHead.arrow.parentNode;
	if (p != null){
		if (p != hCell) {
			p.removeChild(this.tHead.arrow);
		}
	}
	if (this.descending)
		this.tHead.arrow.firstChild.data = "6";
	else
		this.tHead.arrow.lastChild.data = "5";
	
	hCell.appendChild(this.tHead.arrow);

};

SortableTable.prototype.getSortType = function (nColumn) {
	var cell = this.tHead.rows[0].cells[nColumn];
	var val = cell._sortType;
	if (val != "")
		return val;
	return "String";
};

// only nColumn is required
// if bDescending is left out the old value is taken into account
// if sSortType is left out the sort type is found from the sortTypes array

SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) {
	window.status = "S O R T I N G ... . . .!";

	if (sSortType == null)
		sSortType = this.getSortType(nColumn);

	// exit if None	
	if (sSortType == "None")
		return;
	
	if (bDescending == null) {
		if (this.sortColumn != nColumn)
			this.descending = true;
		else
			this.descending = !this.descending;
	}	
	
	this.sortColumn = nColumn;
	
	if (typeof this.onbeforesort == "function")
		this.onbeforesort();
	
	var f = this.getSortFunction(sSortType, nColumn);
	var a = this.getCache(sSortType, nColumn);
	var tBody = this.tBody;
	
	a.sort(f);
	
	if (this.descending)
		a.reverse();
	
	if (SortableTable.removeBeforeSort) {
		// remove from doc
		var nextSibling = tBody.nextSibling;
		var p = tBody.parentNode;
		p.removeChild(tBody);
	}
	
	// insert in the new order
	var l = a.length;
	for (var i = 0; i < l; i++)
		tBody.appendChild(a[i].element);
	
	if (SortableTable.removeBeforeSort) {	
		// insert into doc
		p.insertBefore(tBody, nextSibling);
	}
	
	this.updateHeaderArrows();
	
	this.destroyCache(a);
	
	if (typeof this.onsort == "function")
		this.onsort();

	    //[if mesagewindow opens] sortWin.close();
		window.status = "S O R T I N G COMPLETE!";
};

SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) {
	var oThis = this;
	this._asyncsort = function () {
		oThis.sort(nColumn, bDescending, sSortType);
	};
	window.setTimeout(this._asyncsort, 1);	
};

SortableTable.prototype.getCache = function (sType, nColumn) {
	var rows = this.tBody.rows;
	var l = rows.length;
	var a = new Array(l);
	var r;
	for (var i = 0; i < l; i++) {
		r = rows[i];
		a[i] = {
			value:		this.getRowValue(r, sType, nColumn),
			element:	r
		};
	};
	return a;
};

SortableTable.prototype.destroyCache = function (oArray) {
	var l = oArray.length;
	for (var i = 0; i < l; i++) {
		oArray[i].value = null;
		oArray[i].element = null;
		oArray[i] = null;
	}
}

SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) {
	var s;
	var c = oRow.cells[nColumn];
	if ("innerText" in c)
		s = c.innerText;
	else
		s = SortableTable.getInnerText(c);
	return this.getValueFromString(s, sType);
};

SortableTable.getInnerText = function (oNode) {
	var s = "";	
	var cs = oNode.childNodes;
	var l = cs.length;
	for (var i = 0; i < l; i++) {
		switch (cs[i].nodeType) {
			case 1: //ELEMENT_NODE
				s += getInnerText(cs[i]);
				break;
			case 3:	//TEXT_NODE
				s += cs[i].nodeValue;
				break;
		}
	}
	return s;
}

SortableTable.prototype.getValueFromString = function (sText, sType) {
	switch (sType) {
		case "Number":
			return Number(sText);
		case "CaseInsensitiveString":
			return sText.toUpperCase();
		case "Date":
			var parts = sText.split("-");
			var d = new Date(0);
			d.setFullYear(parts[0]);
			d.setMonth(parts[1]);
			d.setDate(parts[2]);
			return d.valueOf();		
	}
	return sText;
};

SortableTable.prototype.getSortFunction = function (sType, nColumn) {
	return function compare(n1, n2) {
		if (n1.value < n2.value)
			return -1;
		if (n2.value < n1.value)
			return 1;
		return 0;
	};
};

SortableTable.prototype.destroy = function () {
	this.unInit();
	var win = this.document.parentWindow;
	if (win && ("detachEvent" in win)) {	// only IE needs this
		win.detachEvent("onunload", this._onunload);
	}	
	this._onunload = null;
	this.element = null;
	this.tHead = null;
	this.tBody = null;
	this.document = null;
	this._headerOnclick = null;
	this.sortTypes = null;
	this._asyncsort = null;
	this.onsort = null;
};

SortableTable.prototype.getElement = function (el, pTagName){
	if (el == null) return null;
	else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()){
		return el;
	}else{
		return this.getElement(el.parentNode, pTagName);
	}
}

SortableTable.prototype.getCellValue = function (oRow, nColumn) {
	var s;
	var c = this.element.rows[oRow].cells[nColumn];
	if ("innerText" in c)
		s = c.innerText;
	else
		s = SortableTable.getInnerText(c);
	//return this.getValueFromString(s, sType);
	return s;
};

SortableTable.prototype.onclick = function (e) {
	var v = e.target || e.srcElement;
	var c = this.getElement(v,"td");				// source cell
	var r = this.getElement(v,"tr");				// source row
	var h = this.getElement(v,"thead");				// source table's tHead
	
	if(h!=null)	this.sort(c.cellIndex);				// sort table by column: c

	if(h==null){									// if not clicked on tHead
		if(r!=null){								// if row not null
			if(this.selectedRow){
				this.selectedRow.style.backgroundColor = "";// clear previous selected Row
			}
				r.style.backgroundColor = "yellow";		// #99cccc set current selected Row; slcolor
			this.selectedRow = r;							// set current row to selected Row
		}
	}
	
//	alert(this.getCellValue(this.selectedRow,this.selectedCol));
//	alert(this.selectedRow + ',' + this.selectedCol);
//	this.sort(c.cellIndex);	
};

SortableTable.prototype.ondblclick = function (e) {
	var v = e.target || e.srcElement;
	var c = this.getElement(v,"td");				// source cell
	var r = this.getElement(v,"tr");				// source row
	var h = this.getElement(v,"thead");				// source table's tHead
	
	if(h==null){									// if not clicked on tHead
		if(r!=null){								// if row not null
			getFormWithDetail(r.id);
			//alert(r.id);				
		}
	}
};

SortableTable.prototype.onmouseover = function (e) {
	var v = e.target || e.srcElement;
	var c = this.getElement(v,"td");				// source cell
	var r = this.getElement(v,"tr");				// source row
	var h = this.getElement(v,"thead");				// source table's tHead

	if(h==null && r!=null){
		if(r!=this.selectedRow){
			r.style.backgroundColor = "#ddd"; //hlcolor #ddd
		}
	}		
};
SortableTable.prototype.onmouseout = function (e) {
	var v = e.target || e.srcElement;
	var c = this.getElement(v,"td");				// source cell
	var r = this.getElement(v,"tr");				// source row
	var h = this.getElement(v,"thead");				// source table's tHead

	if(h==null && r!=null){
		if(r!=this.selectedRow){
			r.style.backgroundColor = ""; //hlcolor
		}
	}		
};

function preSetRow(xx){
   //alert(xx);
   if(xx !== '') {
	var row = e(xx);
	row.style.backgroundColor = "lightgreen"; //hlcolor
   }
}

xoffSet = 7 //xy offset for opening multiple windows (in pixels)
yoffSet = 20
z=0 //offset multiplier

  // Function to open named window of size(h,w), and allow TARGET to put page there!
  // Any or all arguments may be ommited, use null as place holder.
  // Call examle: onClick="os(null,this.target,'500','500')" TARGET='anyname' 
  // OR: onClick="os()" TARGET='detail' OR: onClick="(null,this.target)" TARGET="microscope"
  // OR: <A HREF="..." onClick="os(null,null,null,'800','yes')" TARGET='info'>
  function os(r,n,h,w,s,t,l,m,x)  { 
  // HREF,name,height,width,scrollbars,location,menu,status -by Geoff Inglis
((r) ? r : r=""    );	  // Href   (default = ''  ) if no HREF open wait for target!
((n) ? n : n="detail");   // name   (default = 'detail')
((h) ? h : h="450"  );    // height (default = '100' ) 
((w) ? w : w="900"  );    // width  (default = '300' )
((s) ? s : s="yes" );     // scroll (default = 'yes' )
((t) ? t : t="yes"  );    // naviga (default = 'yes'  )
((l) ? l : l="yes"  );    // locati (default = 'yes'  )
((m) ? m : m="yes" );     // menu   (default = 'yes'  )
((x) ? x : x="yes"  );    // status (default = 'yes'  )

    window.name="report"; // name the stupid thing so opener will have name!

//  alert("1 name= "+n+" &nbsp; top= "+":"+z*yoffSet + " &nbsp; left= "+":"+z*xoffSet );
    newWin=window.open(r,n,"top="+(z*yoffSet)+",left="+(z*xoffSet)+",height="+h+",width="+w+",toolbar="+t+",location="+l+",menubar="+m+",directories=no,status="+x+",resizable=yes,scrollbars="+s);
//  alert("2 name= "+n+" &nbsp; top= "+":"+z*yoffSet + " &nbsp; left= "+":"+z*xoffSet );
 
//  alert("new Name Already made: " + newWin.opener.name )

   newWin.focus();
  }

    function sortDisplay(){
     sortWin=window.open("","sortTime","top=150,left=150,height=100,width=200,toolbar=no,location=no,menubar=no,directories=no,status=no,resizable=no,scrollbars=no");
     sortWin.document.write("<h2>Sorting.....</h2>");
     sortWin.focus();
    }
