function addClass(el, cls, forceBefore) {
	if(forceBefore !== null && el.className.match(new RegExp('(^| )' + forceBefore))) {
		el.className = el.className.replace(new RegExp("( |^)" + forceBefore), '$1' + cls + ' ' + forceBefore);

	} else if(!el.className.match(new RegExp('(^| )' + cls + '($| )'))) {
		el.className += ' ' + cls;
		el.className = el.className.replace(/(^ +)|( +$)/g, '');
	}
}

function removeClass(el, cls) {
	var old = el.className;
	var newCls = ' ' + el.className + ' ';
	newCls = newCls.replace(new RegExp(' (' + cls + ' +)+','g'), ' ');
	el.className = newCls.replace(/(^ +)|( +$)/g, '');
} 

function replaceClass(el, cls, aCls) {
	var old = el.className;
	var newCls = ' ' + el.className + ' ';
	//alert("2:" + newCls);
	//newCls = newCls.replace(new RegExp(' (' + cls + '+)+','g'), ' ' + aCls);
	//newCls = newCls.replace(new RegExp(' (cls+)+,'g'), ' ' + aCls);
	newCls = newCls.replace(new RegExp(' (' + cls + ' +)+','g'),  ' ' + aCls + ' ');
	//alert("3:" + newCls);
	//newCls = newCls.replace('@',' ');
	
	//alert("4:" + newCls);
	el.className = newCls.replace(/(^ +)|( +$)/g, '');
	//alert("5:" + newCls.replace(/(^ +)|( +$)/g, ''));
} 

function findTextOwner(li) {
	//alert(li.childNodes.length);
	if ( li.childNodes.length == 0 )
	  return null;
	var child = li.childNodes[0];
	//alert(child.nodeName);
	if ( child.nodeName == "#text" )
	  return li;
	return findTextOwner(child);  
}

function replaceAll (streng, soeg, erstat)
{ var st = streng;
  if (soeg.length == 0)
     return st;
  var idx = st.indexOf(soeg);
  while (idx >= 0)        
  {  st = st.substring(0,idx) + erstat + st.substr(idx+soeg.length);
     idx = st.indexOf(soeg);
  }
  return st;
}

function trimString (str, chars) {
  str = replaceAll(str, '&nbsp;', '');
  str = replaceAll(str, ',', '');
  var neg = false;
  if ( str != null && str.length != 0)
    neg = str.charAt(0) == '(';
  
  var len = str.length;
  var sIndex = 0, fIndex = len;
  for (var i = 0; i < len; i++) {
    if (chars.indexOf(str.charAt(i)) == -1) break;
    sIndex++;
  }
  for (var i = len - 1; i >= 0; i--) {
    if (chars.indexOf(str.charAt(i)) == -1) break;
    fIndex--;
  }
  str = str.substring(sIndex, fIndex);
  if (neg && !isNaN(Number(str))) 
	  str = '-' + str ;
  return str;
}

function buildHeaderTable(oTable)
{
/*
  var parentObj = oTable.parentNode;
  var aTable = oTable.cloneNode(false);
  var cap = document.createElement('caption');
  cap.innerHTML = 'ABCDEFG';
  aTable.appendChild(cap);
  aTable.appendChild(oTable.tHead.cloneNode(true));
  parentObj.insertBefore(aTable, oTable);
*/
}

function SortableTable(oTable, oSortTypes) {
	var args = SortableTable.arguments;
	if ( args.length > 2 )
	  this.rowIgnored = args[2];
	else
	  this.rowIgnored = 0;
	this.sortTypes = oSortTypes || [];
	
	this.sortColumn = null;
	this.descending = null;
	var oThis = this;
	this._headerOnclick = function (e) {
		oThis.headerOnclick(e);
	};
	if (oTable) {
		this.setTable( oTable );
		this.document = oTable.ownerDocument || oTable.document;
	}
	else {
		this.document = document;
	}


	// only IE needs this
	var win = this.document.defaultView || this.document.parentWindow;
	this._onunload = function () {
		oThis.destroy();
	};
	if (win && typeof win.attachEvent != "undefined") {
		win.attachEvent("onunload", this._onunload);
	}
    buildHeaderTable(oTable);
}

SortableTable.IGNORE_CHARACTERS = "\n\r\t ()";
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 () {};

// default sort order. true -> descending, false -> ascending
SortableTable.prototype.defaultDescending = false;

// shared between all instances. This is intentional to allow external files
// to modify the prototype
SortableTable.prototype._sortTypeInfo = {};

function findChild(li, tagname, className) {
	if ( li == null )
	  return null;
	for(var i=0;i<li.childNodes.length;i=i+1)
	  if ( li.childNodes[i].tagName != null &&
		  li.childNodes[i].tagName.toLowerCase() == tagname &&
	      li.childNodes[i].className.indexOf(className) != -1 ) 
	    return li.childNodes[i];
	return null;
}


SortableTable.prototype.setTable = function (oTable) {
	//alert("3");
	if ( this.tHead )
		this.uninitHeader();
	this.element = oTable;
	var tb = oTable.tBodies[0];
	if ( oTable.tHead )
		this.setTHead( oTable.tHead );
	else {
		var tr = findChild(tb, 'tr', 'thead');
		//if ( tr == null ) { tr = findChild(tb, 'tr', 'tscroll');}
		if ( tr ) { 
		  this.headerIndex = tr.rowIndex;
		  var thead = document.createElement('thead');
		  oTable.appendChild(thead);
		  oTable.appendChild(tb);
		  var i =0;
		  for(i=0;i<this.headerIndex;i++)
		    thead.appendChild(tb.rows[i]); 
		  thead.appendChild(tr);
		  this.setTHead( thead);
		}
		/*
		var tr1 = findChild(tb, 'tr', 'dgfooter');
		if (tr1){
			oTable.removeChild(tr1);
		}
		*/
	}
	this.setTBody( tb );
};

SortableTable.prototype.setTHead = function (oTHead) {
	//alert("4");
	if (this.tHead && this.tHead != oTHead )
		this.uninitHeader();
	this.tHead = oTHead;
	this.initHeader( this.sortTypes );
};

SortableTable.prototype.setTBody = function (oTBody) {
	//alert("5");
	this.tBody = oTBody;
};

SortableTable.prototype.setSortTypes = function ( oSortTypes ) {
	//alert("6");
	if ( this.tHead )
		this.uninitHeader();
	this.sortTypes = oSortTypes || [];
	if ( this.tHead )
		this.initHeader( this.sortTypes );
};

// 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.initHeader = function (oSortTypes) {
	//alert("7");
	if (!this.tHead) return;
	////var cells = this.tHead.rows[0].cells;
	//if (!this.headerIndex) return;
	//alert(this.tHead.rows[1].cells);
	if (!this.tHead.rows[this.headerIndex].cells) return;
	
	var cells = this.tHead.rows[this.headerIndex].cells;
	var doc = this.tHead.ownerDocument || this.tHead.document;
	this.sortTypes = oSortTypes || [];
	var l = cells.length;
	var img, c;
	for (var i = 0; i < l; i++) {
		c = cells[i];
		if (/*this.sortTypes[i] != null && */ this.sortTypes[i] != "None") {
//			img = doc.createElement("IMG");
//			img.src = "images/blank.png";
//			c.appendChild(img);
			if (this.sortTypes[i] != null)
				c._sortType = this.sortTypes[i];
			if (typeof c.addEventListener != "undefined") {
				c.addEventListener("click", this._headerOnclick, false);
			}
			else if (typeof c.attachEvent != "undefined")
				c.attachEvent("onclick", this._headerOnclick);
			else 
				c.onclick = this._headerOnclick;
		}
		else
		{
			c.setAttribute( "_sortType", oSortTypes[i] );
			c._sortType = "None";

		}
	}
	this.updateHeaderArrows();
};

// remove arrows and events
SortableTable.prototype.uninitHeader = function () {
	//alert("8");
	if (!this.tHead || !this.tHead.rows) return;
	////var cells = this.tHead.rows[0].cells;
	//if (!this.headerIndex) return;
	
	if (! this.tHead.rows[this.headerIndex].cells) return;
	var cells = this.tHead.rows[this.headerIndex].cells;
	if ( !cells ) return;
	var l = cells.length;
	var c;
	for (var i = 0; i < l; i++) {
		c = cells[i];
		if (c._sortType != null && c._sortType != "None") {
			c.removeChild(c.lastChild);
			if (typeof c.removeEventListener != "undefined")
				c.removeEventListener("click", this._headerOnclick, false);
			else if (typeof c.detachEvent != "undefined")
				c.detachEvent("onclick", this._headerOnclick);
			c._sortType = null;
			c.removeAttribute( "_sortType" );
		}
	}
};

/*function replaceClass(el, cls, aCls) {
	//alert("9");
	var old = el.className;
	var newCls = ' ' + el.className + ' ';
	newCls = newCls.replace(new RegExp(' (' + cls + ' +)+','g'), ' ' + aCls);
	el.className = newCls.replace(/(^ +)|( +$)/g, '');
} */

function hasClass(el, cls) {
	//alert("10");
/*
	if ( cls != 'sortableColumn' )
	  return ;
*/
	var c = el.className;
	if ( c == null )
	  return false;
	if ( (c == cls) || startsWith(c, cls+' ') || endsWith(c, ' '+cls)
	|| (c.indexOf(' '+cls+' ') != -1) )
	  
	  return true;
	return false;
} 

SortableTable.prototype.updateRownum = function () {
  if (!this.tHead) return;

  ////var THs = this.tHead.rows[0].cells;
  //if (!this.headerIndex) return;
  if (!this.tHead.rows[this.headerIndex].cells) return;
  var THs = this.tHead.rows[this.headerIndex].cells;
  var l = THs.length;
  var rownumHeader = -1;
  for (var i = 0; i < l; i++) {
    var header = THs.item(i);
    if (hasClass(header, "rownumColumn"))
      rownumHeader = i;
  }
  if (rownumHeader != -1) {
	var rows = this.tBody.rows;
	var l = rows.length - this.rowIgnored;
	for (i = 0; i < l; i++) {
	  rows[i].cells[rownumHeader].innerHTML = i+1;
	}
  }
}
SortableTable.prototype.updateHeaderArrows = function () {
	//alert("11");
  if (!this.tHead) return;

  ////var THs = this.tHead.rows[0].cells;
  //if (!this.headerIndex) return;
  if (!this.tHead.rows[this.headerIndex].cells) return;
  var THs = this.tHead.rows[this.headerIndex].cells;
  //alert(this.headerIndex);
  var l = THs.length;
  //alert(l);
  for (var i = 0; i < l; i++) {
    var header = THs.item(i);
   
    if (i == this.sortColumn) {
      if (hasClass(header, "clickedColumnAsc"))
        replaceClass(header, "clickedColumnAsc", "clickedColumnDes");
      else if (hasClass(header, "clickedColumnDes"))
        replaceClass(header, "clickedColumnDes", "clickedColumnAsc");
      else
      {
		// alert(header.className);
        replaceClass(header, 'sortableColumn', 'clickedColumnAsc');
       // alert("->:" + header.className);
        }
	  }
/*
    else if (hasClass(header, "_clickedColumnAsc"))
      replaceClass(header, "_clickedColumnAsc", "clickedColumnAsc");
    else if (hasClass(header,"_clickedColumnDes")) 
      replaceClass(header, "_clickedColumnDes", "clickedColumnDes");
*/
    else if (hasClass(header, "clickedColumnAsc")) {
      replaceClass(header, "clickedColumnAsc", "sortableColumn");
    }
    else if (hasClass(header, "clickedColumnDes")) {
      replaceClass(header, "clickedColumnDes", "sortableColumn");
    }
  }
  
  document.body.style.cursor = "auto";
/*	var cells = this.tHead.rows[0].cells;
	var l = cells.length;
	var img;
	for (var i = 0; i < l; i++) {
		if (cells[i]._sortType != null && cells[i]._sortType != "None") {
			img = cells[i].lastChild;
			if (i == this.sortColumn)
				img.className = "sort-arrow " + (this.descending ? "descending" : "ascending");
			else
				img.className = "sort-arrow";
		}
	}*/
};

SortableTable.prototype.headerOnclick = function (e) {
	document.body.style.cursor = "wait";
	// find TH element
  var el = e.target || e.srcElement;
  ////alert(el.tagName.toLowerCase());
  //el.style.cursor = "wait";
  while (el.tagName.toLowerCase() != "td" && el.tagName.toLowerCase() != "th" )
    el = el.parentNode;
  //alert(el.parentNode);
  if (hasClass(el, "sortableColumn") || hasClass(el, "clickedColumnAsc")
      || hasClass(el, "clickedColumnDes")) {
    this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex);
   }
   //el.style.cursor = "auto";
};

// IE returns wrong cellIndex when columns are hidden
SortableTable.getCellIndex = function (oTd) {
	//alert("13");
	var cells = oTd.parentNode.childNodes
	var l = cells.length;
	var i;
	for (i = 0; cells[i] != oTd && i < l; i++)
		;
	return i;
};

SortableTable.prototype.getSortType = function (nColumn) {
	//alert("14");
	return this.sortTypes[nColumn] || "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) {
	//alert("15");
	if (!this.tBody) return;
	if (sSortType == null)
		sSortType = this.getSortType(nColumn);

	// exit if None
	if (sSortType == "None")
		return;

	if (bDescending == null) {
		if (this.sortColumn != nColumn)
			this.descending = this.defaultDescending;
		else
			this.descending = !this.descending;
	}
	else
		this.descending = bDescending;

	this.sortColumn = nColumn;

	if (typeof this.onbeforesort == "function")
		this.onbeforesort();
	//alert(nColumn);
	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++) {
		if ( this.rowIgnored == 0 ) {
		  tBody.appendChild(a[i].element);
		  }
		else {
		  //tBody.insertBefore(a[i].element, tBody.rows[this.headerIndex])
		  tBody.insertBefore(a[i].element, tBody.rows[0])
		  }
	}
	if (SortableTable.removeBeforeSort) {
		// insert into doc
		p.insertBefore(tBody, nextSibling);
	}

	this.updateHeaderArrows();
	this.updateRownum();
	this.destroyCache(a);

	rehighlight(tBody);

	if (typeof this.onsort == "function")
		this.onsort();
};

SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) {
	//alert("16");
	var oThis = this;
	this._asyncsort = function () {
		oThis.sort(nColumn, bDescending, sSortType);
	};
	window.setTimeout(this._asyncsort, 1);
};

SortableTable.prototype.getCache = function (sType, nColumn) {
	if (!this.tBody) return [];
	var rows = this.tBody.rows;
	var l = rows.length-this.rowIgnored;
	var r;
	var a = new Array(l);
	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) {
	//alert("18");
	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) {
	////alert("19");
  // if we have defined a custom getRowValue use that
  if (this._sortTypeInfo[sType] && this._sortTypeInfo[sType].getRowValue)
    return this._sortTypeInfo[sType].getRowValue(oRow, nColumn);

  var s;
  var c = oRow.cells[nColumn];
  //c = findTextOwner(c);
  
  if (typeof c.innerText != "undefined")
    s = trimString(c.innerText, SortableTable.IGNORE_CHARACTERS);
  else
    s = trimString(SortableTable.getInnerText(c), SortableTable.IGNORE_CHARACTERS);
  return this.getValueFromString(s, sType);
};

SortableTable.getInnerText = function (oNode) {
	//alert("20");
  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 += SortableTable.getInnerText(cs[i]);
      break;
    case 3:	//TEXT_NODE
      s += cs[i].nodeValue;
      break;
    }
  }
  return s;
};

SortableTable.prototype.getValueFromString = function (sText, sType) {
	////alert("21");
	if (this._sortTypeInfo[sType])
		return this._sortTypeInfo[sType].getValueFromString( sText );
	return sText;
	/*
	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.setDate(parts[2]);
			d.setMonth(parts[1] - 1);
			return d.valueOf();
	}
	return sText;
	*/
	};

SortableTable.prototype.getSortFunction = function (sType, nColumn) {
	//alert("22");
	if (this._sortTypeInfo[sType])
		return this._sortTypeInfo[sType].compare;
	return SortableTable.basicCompare;
};

SortableTable.prototype.destroy = function () {
	//alert("23");
	this.uninitHeader();
	var win = this.document.parentWindow;
	if (win && typeof win.detachEvent != "undefined") {	// 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;
	this.rowIgnored = null;
	this.headerIndex = 0;
	
};

// Adds a sort type to all instance of SortableTable
// sType : String - the identifier of the sort type
// fGetValueFromString : function ( s : string ) : T - A function that takes a
//    string and casts it to a desired format. If left out the string is just
//    returned
// fCompareFunction : function ( n1 : T, n2 : T ) : Number - A normal JS sort
//    compare function. Takes two values and compares them. If left out less than,
//    <, compare is used
// fGetRowValue : function( oRow : HTMLTRElement, nColumn : int ) : T - A function
//    that takes the row and the column index and returns the value used to compare.
//    If left out then the innerText is first taken for the cell and then the
//    fGetValueFromString is used to convert that string the desired value and type

SortableTable.prototype.addSortType = function (sType, fGetValueFromString, fCompareFunction, fGetRowValue) {
	//alert("24");
	this._sortTypeInfo[sType] = {
		type:				sType,
		getValueFromString:	fGetValueFromString || SortableTable.idFunction,
		compare:			fCompareFunction || SortableTable.basicCompare,
		getRowValue:		fGetRowValue
	};
};

// this removes the sort type from all instances of SortableTable
SortableTable.prototype.removeSortType = function (sType) {
	//alert("25");
	delete this._sortTypeInfo[sType];
};

SortableTable.prototype.cmp = function (ch1, ch2) {
	////alert("26");
  var ARABIC_BEH = 0x628;
  var ARABIC_JEEM = 0x62c;
  var ARABIC_ZAIN = 0x632;
  var ARABIC_KAF = 0x643;
  var ARABIC_VAV = 0x648;
  var ARABIC_HEH = 0x647;
  var ARABIC_YEH = 0x64a;

  var FARSI_PEH = 0x67e;
  var FARSI_TCHEH = 0x686;
  var FARSI_JEH = 0x698;
  var FARSI_KEHEH = 0x6a9;
  var FARSI_GAF = 0x6af;

  var i1 = ch1.charCodeAt(0)
  var i2 = ch2.charCodeAt(0)

  if (i1 == FARSI_PEH) i1 = ARABIC_BEH + 0.5;

  if (i1 == FARSI_TCHEH) i1 = ARABIC_JEEM + 0.5;
  else if (i1 == FARSI_JEH) i1 = ARABIC_ZAIN + 0.5;
  else if (i1 == FARSI_KEHEH) i1 = ARABIC_KAF + 0.5;
  else if (i1 == FARSI_GAF) i1 = ARABIC_KAF + 0.6;
  else if (i1 == ARABIC_HEH) i1 = ARABIC_YEH - 0.5;
  else if (i1 == ARABIC_VAV) i1 = ARABIC_HEH - 0.5;

  if (i2 == FARSI_PEH) i2 = ARABIC_BEH + 0.5;
  else if (i2 == FARSI_TCHEH) i2 = ARABIC_JEEM + 0.5;
  else if (i2 == FARSI_JEH) i2 = ARABIC_ZAIN + 0.5;
  else if (i2 == FARSI_KEHEH) i2 = ARABIC_KAF + 0.5;
  else if (i2 == FARSI_GAF) i2 = ARABIC_KAF + 0.6;
  else if (i2 == ARABIC_HEH) i2 = ARABIC_YEH - 0.5;
  else if (i2 == ARABIC_VAV) i2 = ARABIC_HEH - 0.5;

  return 10 * (i1 - i2);
};

SortableTable.basicCompare = function compare(n1, n2) {
	////alert("27");
  var str1 = n1.value;
  var str2 = n2.value;
  var l1 = str1.length;
  var l2 = str2.length;
  var res = 0;
  for (i = 0; i < l1 && i < l2 && res == 0; i++) {
    res = SortableTable.prototype.cmp(str1.charAt(i), str2.charAt(i));
    if (res != 0)
      return res;
  }
  if (l1 == l2)
    return 0;
  else if (l1 < l2)
    return -1;
  return 1;
/*
  alert(n1.value);
  alert(n2.value);

	if (n1.value < n2.value)
		return -1;
	if (n2.value < n1.value)
		return 1;
	return 0;
*/
};

SortableTable.idFunction = function (x) {
	//alert("28");
  return x;
};

SortableTable.toUpperCase = function (s) {
	//alert("29");
  return s.toUpperCase();
};

SortableTable.toDate = function (s) {
	//alert("30");
	var parts = s.split("-");
	var d = new Date(0);
	d.setFullYear(parts[0]);
	d.setDate(parts[2]);
	d.setMonth(parts[1] - 1);
	return d.valueOf();
};

SortableTable.numberCompare = function compare(n1, n2) {
	//alert("31");
	if (n1.value < n2.value)
		return -1;
	if (n2.value < n1.value)
		return 1;
	return 0;
};

// add sort types
SortableTable.prototype.addSortType("Number", Number, SortableTable.numberCompare);
SortableTable.prototype.addSortType("CaseInsensitiveString", SortableTable.toUpperCase);
SortableTable.prototype.addSortType("Date", SortableTable.toDate);
SortableTable.prototype.addSortType("String");
// None is a special case

/////////////////// Mohsen ///////////////////
/**
 * This function will get a tbody, and sets class="even" and class="odd"
 * to TRs respectively
 */
function rehighlight(tab) {
	//alert("32");
  var tr = tab.getElementsByTagName("TR");
  var i;
  for (i = 0; i < tr.length; i+=2) {
    if (hasClass(tr[i], "odd" ))
      replaceClass(tr[i], 'odd', 'even');
  }
  for (i = 1; i < tr.length; i+=2) {	
    if (hasClass(tr[i], 'even' ))
      replaceClass(tr[i], 'even', 'odd');
  }
}

/** determines if all of a table's column elements are number */
function isNumberCol(tb, colNo, rowIgnored, headerIndex) {
  if (!tb.tBodies[0]) 
	return false;
   
  var rows = tb.tBodies[0].rows;
  var l = rows.length;
  if (l <= 0 || rows[headerIndex].cells.length <= colNo) return;
  for (var i = headerIndex; i < l; i++) {
    col = rows[i].cells[colNo];
    
    if ( hasClass(col, 'sortableColumn')) continue;

    if ( col.innerHTML == null ) continue;
    if (typeof col.innerText != "undefined")
      c = trimString(col.innerText, SortableTable.IGNORE_CHARACTERS);
    else
      c = trimString(SortableTable.getInnerText(col), SortableTable.IGNORE_CHARACTERS);
    
    //if ( c == null ) continue;
    //c = trimString(c, SortableTable.IGNORE_CHARACTERS);

    if ( c == "") continue;
    if (!isNaN(Number(c))) continue;
    return false;
  }
  return true;
}
/*
function installSortableTable(tbElem) {
  if (!tbElem) return null;
//  if (tbElem.tBodies[0].rows.length <= 1) return;
  ths = tbElem.getElementsByTagName("TH");
  if ( ths == null || ths.length == 0 )
    ths = tbElem.getElementsByTagName("TD");
  typeArray = [];
  for (var i = 0; i < ths.length; i++) {
    if (!hasClass(ths[i], 'sortableColumn')) {
      typeArray.push("None");
    }
    else
      if (isNumberCol(tbElem, i))
        typeArray.push("Number");
      else
        typeArray.push("String");
  }
  return new SortableTable(tbElem, typeArray);
}
*/
function installSortableTable(tbElem) {
  if (!tbElem) return null;
//  if (tbElem.tBodies[0].rows.length <= 1) return;
  var hd = tbElem.tHead;
  if ( !hd )
    hd = tbElem.tBodies[0];
  var tr = findChild(hd, 'tr', 'thead');
  var headerIndex = 0;
  if ( tr )
    headerIndex = tr.rowIndex;
  else
	return ;
  ths = tr.cells;
  /*  
  ths = tbElem.getElementsByTagName("TH");
  if ( ths == null || ths.length == 0 )
    ths = tbElem.getElementsByTagName("TD");
  */
  typeArray = [];
  var args = installSortableTable.arguments;
  var rowIgnored = 0;
  if ( args.length > 1 ) 
    rowIgnored = args[1];
	/*  
  var tr = findChild(tbElem.tBodies[0], 'tr', 'thead');
  var headerIndex = 0;
  if ( tr )
    headerIndex = tr.rowIndex;
  */
  for (var i = 0; i < ths.length; i++) {
    if (!hasClass(ths[i], 'sortableColumn')) {
      typeArray.push("None");
    }
    else
      if (isNumberCol(tbElem, i, rowIgnored, headerIndex))
        typeArray.push("Number");
      else
        typeArray.push("String");
  }
  if ( rowIgnored == 0 )
    return new SortableTable(tbElem, typeArray);
  else
    return new SortableTable(tbElem, typeArray, rowIgnored);
}
function applyMyTableScroll(tb, height) {
	if ( !tb )
		 return;
	//var tb1 = tb.tBodies[0];
	var tb1 = tb.tHead;
	var parent = tb.parentNode
	var tr = findChild(tb1, 'tr', 'tscroll');
	if ( tr ) { 
		var div = document.createElement('div');
		div.style.overflow = "auto";
		var args = applyMyTableScroll.arguments;
		var h = 400;
		if ( args.length > 1 )
		  h = args[1];
		if (tb.offsetHeight > h )  {
			for (var i=0;i<tb1.rows.length;i++)
				addClass(tb1.rows[i], 'tscrollStyle');
		
		div.style.height = h + "px";
		var w = tb.offsetWidth + 35;
		div.style.width = w + "px";
		div.id = 'divScroll';
		parent.appendChild(div);
		div.appendChild(tb);
		}
	}
	
}
function applyMyTableStyles(tb) {
	if ( !tb )
	  return;
	var rl = tb.tBodies[0].rows.length;
    for(i=0;i<rl;i=i+1) {
      var cells = tb.tBodies[0].rows[i].cells;
	  var cl = cells.length;
	  for(j=0;j<cl;j=j+1) {
	    var cell = cells[j];
	    if ( hasClass(cell, 'Money') ) {
			var c = trimString(SortableTable.getInnerText(cell), SortableTable.IGNORE_CHARACTERS);
			if ( !isNaN(Number(c)) && Number(c) < 0 ) {
			  cell.innerHTML = '('+cell.innerHTML.replace('-', '')+')'; 
			  addClass(cell, 'negative');  
			 }
		}
	  }
    }
}
function findChildWithID(li, tagname, idChild) {
	if ( li == null )
	  return null;
	for(var i=0;i<li.childNodes.length;i=i+1) {
	  if ( li.childNodes[i].tagName != null &&
		  li.childNodes[i].tagName.toLowerCase() == tagname &&
	      li.childNodes[i].id.indexOf(idChild) != -1 ) 
	  {
	    return li.childNodes[i];
	  }
	}
	return null;
}

