<!--
// Lonnie Lee Best
var com;
if (!com) com = {};
if (!com.LonnieBest) com.LonnieBest = {};
com.LonnieBest.Tables = {};
(
	function()
	{
		var cacheImage = new Image();
		cacheImage.src = "http://www.lonniebest.com/FormatCSS/spin.gif";
		function doConcurrently(functionToDo,ms)
		{
			if(!ms){ms=0};			
			var that=this;
			setTimeout(function(){functionToDo.call(that);},ms);				
		}
		function doAlert(obj,times)
		{
			if(!doAlert.set)
			{
				if(!times)
				{
					times = 1;
				}
				doAlert.count = 0;
				doAlert.set = true;
			}
			if(doAlert.count < times)
			{
				alert(obj);
				doAlert.count++;			
			}	
		
		}
		var Table = function Table()
		{
			this.caption = null;
			this.columnCellStyle = null;
			this.columnDataFormat = [];
			this.colStyle = null;
			this.columnStyleAll = null;
			this.data = [];
			this.element = null;
			this.elementId = null;
			this.header = [];
			this.headerCellStyle = null;
			this.headerRowStyle = null;
			this.nextSibling = null;
			this.sortAscending = true;
			this.sortColumn = null;
			this.sortFunctions = null;
			this.summary = null;
			this.tableStyle = null;
			this.toolTipIdle = false;
			this.rowsPerRecurse = 25;
			this.incrementalRendering = {};
			this.incrementalRendering.enabled = false;
			this.incrementalRendering.rowsPerRender = 1;
			this.incrementalRendering.duration = 250;
			this.incrementalRendering.limit = 6;
			return this;
		}
		Table.prototype.AddCommas = function (number)
		{
			var decimalAry = number.toString().split('.');
			if (decimalAry[0].length > 3)
			{
				var didgitAry = decimalAry[0].split('');
				didgitAry.reverse();
				var cnt = 0;
				var aryNew = [];
				for (i = 0; i < didgitAry.length; i++)
				{
					if (cnt < 3)
					{
						aryNew.push(didgitAry[i]);
						cnt++;
					}
					else
					{
						aryNew.push(',');
						aryNew.push(didgitAry[i]);
						cnt = 1;
					}
				}
				aryNew.reverse();
				decimalAry[0] = aryNew.join('');
				return decimalAry.join('.');
			}
			else
			{
				return number;				
			}			
		}
		Table.prototype.getTableWidth = function ()
		{
			if(this.element)
			{
				return (this.element.getElementsByTagName("tr"))[0].offsetWidth;
			}
			else
			{
				return 0;
			}
		}
		Table.prototype.sortNumeric = function (a,b)
		{
			return a - b;
		}
		Table.prototype.SortBy = function (i)
		{
			if(this.isSorting)
			{
				return;
			}
			else
			{
				this.isSorting = true;
			}
			if(this.sortAscending && this.sortColumn == i)
			{
				this.data.reverse();
				this.sortAscending = false;
			}
			else
			{
				if(this.sortFunctions && this.sortFunctions.constructor == Array && i < this.sortFunctions.length && this.sortFunctions[i] && this.sortFunctions[i].constructor == Function)
				{
					var sortFunction = this.sortFunctions[i];
					this.data.sort(function(Lonnie,Best){return sortFunction(Lonnie[i],Best[i]);});
				}
				else
				{
					this.data.reverse();				
				}
				this.sortAscending = true;
			}
			this.sortColumn = i;
			this.isSorting = false;
		}
		Table.prototype.toolTip = function(i,e)
		{
			if(this.toolTipIdle)
			{
				this.toolTipIdle = false;
				var div = document.createElement("div");
				div.oTable = this;
				div.innerHTML = "<div><b>Click to Sort.</b></div>";
				var subTable = new com.LonnieBest.Tables.Table();
				subTable.data = [['a',1],['b',2],['c',3],['d',4]];
				subTable.headerCellStyle = function(e){e.style.border = "solid #333333 1px"};
				subTable.columnCellStyle = function(e){e.style.border = "solid #333333 1px"};
				subTable.Render(div);
				//Oh funny, the tool-tip's table has tool tips! Got to turn that off:
				subTable.toolTipIdle = false;			
				var interval = setInterval(function(){subTable.SortBy(0);subTable.Render(div);},700);
				var timeOut = setTimeout(function(){clearInterval(interval)},2800);
				div.style.backgroundColor = "yellow";
				div.style.border = "solid black 3px";
				div.style.padding = "3px";
				div.style.top = e.clientY + 1 + "px";
				div.style.left = e.clientX + 10 + "px";
				div.style.position = "absolute";
				document.body.appendChild(div);
				var mainTimeout = setTimeout(function(){div.parentNode.removeChild(div);div.oTable.toolTipIdle = true;div=null;this.toolTipIdle = true;},3000);
			}
		}
		Table.prototype.removeTable = function ()
		{
			var tableElement = document.getElementById(this.elementId);
			if(tableElement)
			{
				if(tableElement.parentNode.nextSibling)
				{
					this.nextSibling = tableElement.parentNode.nextSibling;
				}
				else
				{
					this.nextSibling = null;
				}
				(tableElement.parentNode).parentNode.removeChild((tableElement.parentNode));
				tableElement.parentNode.removeChild(tableElement);
				tableElement.o = null;
				tableElement = null;
			}
		}
		Table.prototype.Render = function (parentElement)
		{
			if(this.isRendering)
			{
				return;
			}
			else
			{
				this.isRendering =  true
			}
			var loadingElement = document.createElement("div");
			loadingElement.style.textAlign = "center";
			var loadingImage = document.createElement("img");
			loadingImage.src = cacheImage.src;
			loadingElement.appendChild(loadingImage);
			if(parentElement.firstChild)
			{
				parentElement.insertBefore(loadingElement,parentElement.firstChild);
			}
			else
			{
				parentElement.appendChild(loadingElement);
			}
			doConcurrently.call(this,function()
			{
				var maxRowLength = 0;
				var currentRowLength = 0;
				for (i = 0; i < this.data.length; i++)
				{
					currentRowLength = this.data[i].length;
					if (currentRowLength > maxRowLength)
					{
						maxRowLength = currentRowLength;
					}
				}
				if(this.header.length > maxRowLength)
				{
					maxRowLength = this.header.length;
				}
				var container = document.createElement("div");
				container.style.overflow = "auto";
				container.style.height = "250px";
				container.style.marginLeft = "auto";
				container.style.marginRight = "auto";
				container.style.backgroundColor = "#efebe7";
				container.style.border = "solid black 10px;";
				var table = document.createElement("table");
				container.appendChild(table);
				table.o = this;
				this.element = table;
				if(this.tableStyle && this.tableStyle.constructor == Function)
				{
					this.tableStyle(table);
				}
				if(this.elementId == null)
				{
					this.elementId = "Table";
					while(document.getElementById(this.elementId))
					{
						this.elementId = this.elementId + Math.round(Math.random());
					}
				}
				table.setAttribute("id",this.elementId);
				if(table.summary != null)
				{
					table.setAttribute("summary",this.summary);
				}
				if(this.caption != null)
				{
					var caption = document.createElement("caption");
					caption.innerHTML = this.caption;
					table.appendChild(caption);
				}
				var colgroup = document.createElement("colgroup");
				colgroup.setAttribute("span",maxRowLength.toString());
				if(this.columnStyleAll && this.columnStyleAll.constructor == Function)
				{
					this.columnStyleAll(colgroup);
				}
				var currentColumn = document.createElement("col");
				for (i = 0; i < maxRowLength; i++)
				{
					currentColumn = document.createElement("col");
					if(this.colStyle && this.colStyle.constructor == Array && i < this.colStyle.length && this.colStyle[i].constructor == Function)
					{
						this.colStyle[i](currentColumn);
					}
					colgroup.appendChild(currentColumn);
				}
				table.appendChild(colgroup);
				var thead = document.createElement("thead");
				var currentRow = document.createElement("tr");
				var currentCell;
				if(this.headerRowStyle && this.headerRowStyle.constructor == Function)
				{
					this.headerRowStyle(currentRow);
				}
				for (cell = 0; cell < maxRowLength; cell++)
				{
					currentRowLength = this.header.length;
					currentCell = document.createElement("th");
					currentCell.colId = cell;
					if(this.headerCellStyle && this.headerCellStyle.constructor == Function)
					{
						this.headerCellStyle(currentCell);
					}
					currentCell.oTable = table.o;
					currentCell.onclick = function(){this.oTable.SortBy(this.colId);this.oTable.Render((this.oTable.element.parentNode).parentNode);};
					currentCell.onmouseover = function(e){if(!(e)){e = window.event};this.oTable.toolTip(this.colId,e)};
					currentCell.innerHTML = "Column" + (cell + 1);
					if (cell < currentRowLength)
					{
						if (this.header[cell])
						{
							currentCell.innerHTML = this.header[cell].toString();
						}
					}
					currentRow.appendChild(currentCell);
					thead.appendChild(currentRow);
				}
				table.appendChild(thead)
				var tbody = document.createElement("tbody");
				table.appendChild(tbody);
				if(this.incrementalRendering.enabled)
				{
					this.removeTable();
					if(this.nextSibling)
					{
						parentElement.insertBefore(container,this.nextSibling);
					}
					else
					{
						parentElement.appendChild(container);
					}
				}
				var cellData;
				function recurse()
				{
					if(!recurse.set)
					{
						recurse.count = 0;
						recurse.set = true;
						if(this.incrementalRendering.enabled)
						{
							recurse.rowsPerRecurse = this.incrementalRendering.rowsPerRender;
						}
						else
						{
							recurse.rowsPerRecurse = this.rowsPerRecurse;
						}
						if(recurse.rowsPerRecurse > this.data.length)
						{
							recurse.rowsPerRecurse = this.data.length;
						}
					}
					if(recurse.count < this.data.length)
					{
						if(this.data.length - recurse.count < recurse.rowsPerRecurse)
						{
							recurse.rowsPerRecurse = this.data.length - recurse.count;
						}
						for (z = 0; z < recurse.rowsPerRecurse; z++)
						{
							currentRow = document.createElement("tr");
							for (cell = 0; cell < maxRowLength; cell++)
							{
								currentRowLength = this.data[recurse.count].length;
								currentCell = document.createElement("td");
								if (this.columnCellStyle && this.columnCellStyle.constructor == Function)
								{
									this.columnCellStyle(currentCell);
								}
								if (cell < currentRowLength)
								{
									if (this.data[recurse.count][cell])
									{
										cellData = this.data[recurse.count][cell].toString();
										if(this.columnDataFormat[cell])
										{
											if(this.columnDataFormat[cell].constructor == Function)
											{
												cellData = this.columnDataFormat[cell](cellData);
											}
											else
											{
												if(this.columnDataFormat[cell].constructor == Array)
												{
													for(f = 0; f < this.columnDataFormat[cell].length; f++)
													{
														if(this.columnDataFormat[cell][f].constructor == Function)
														{
															cellData = this.columnDataFormat[cell][f](cellData);
														}
													}
												}
											}
										}
										currentCell.innerHTML = cellData;
									}
								}
								currentRow.appendChild(currentCell);
							}
							tbody.appendChild(currentRow);
							recurse.count++;
							if(this.incrementalRendering.enabled)
							{
								//Firefox doesn't seem to know the offsetWidth of its tables, but does know the offsetWidth of the table's rows
								container.style.width = ((table.getElementsByTagName("tr"))[0].offsetWidth + 25) + "px";
							}
						}
						if(this.incrementalRendering.enabled)
						{
							if (!recurse.limitReached)
							{
								doConcurrently.call(this,recurse,this.incrementalRendering.duration);
							}
							if(recurse.count >= this.incrementalRendering.limit)
							{
								this.incrementalRendering.enabled = false;
								recurse.limitReached = true;
								recurse.rowsPerRecurse = this.rowsPerRecurse;
								if(recurse.rowsPerRecurse > this.data.length)
								{
									recurse.rowsPerRecurse = this.data.length;
								}
							}

						}
						else
						{
							doConcurrently.call(this,recurse);
						}
					}
					else
					{
						if(!this.incrementalRendering.enabled && !recurse.limitReached)
						{
							this.removeTable();
							if(this.nextSibling)
							{

								parentElement.insertBefore(container,this.nextSibling);

							}
							else
							{

								parentElement.appendChild(container);
							}
							container.style.width = (this.getTableWidth() + 25) + "px";
						}		
						loadingElement.parentNode.removeChild(loadingElement);
						if(recurse.limitReached)
						{
							this.incrementalRendering.enabled = true;
						}
								
						this.isRendering = false;
					}
				}
				recurse.call(this);
			});
		}			
		//public
		var ns = com.LonnieBest.Tables;
		ns.Table = Table;
		ns.Author = "Lonnie Lee Best";
	}
)();
// -->