/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.FilteringTable");

dojo.require("dojo.date.format");
dojo.require("dojo.collections.Store");
dojo.require("dojo.html.*");
dojo.require("dojo.html.util");
dojo.require("dojo.html.style");
dojo.require("dojo.html.selection");
dojo.require("dojo.event.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");

dojo.widget.defineWidget(
	"dojo.widget.FilteringTable",
	dojo.widget.HtmlWidget,
	function(){
		// summary: A basic tabular data widget that supports sorting and filtering mechanisms.
		// description:
		//		FilteringTable is a 2D data view that supports multiple column sorting and filtering
		//		functionality.  It can get its data in one of two ways: via HTML (i.e. degradable
		//		data), or from an external JSON source through widget.store.setData.  Records in
		//		a FilteringTable can be selected as if it were a select list.
		// store: dojo.collections.Store
		//		The underlying Store for all data represented by the widget.
		// valueField: String
		// 		The name of the field used as a unique key for each row, defaults to "Id".
		// multiple: boolean
		//		Allow multiple selections.
		// maxSelect: Integer
		//		Maximum number of rows that can be selected at once.  0 == no limit.
		// maxSortable: Integer
		//		Maximum number of columns allowed for sorting at one time.
		// minRows: Integer
		//		The minimum number of rows to show.  Default is 0.
		// defaultDateFormat: String
		//		The default format for a date column, as used by dojo.date.format.
		// alternateRows: Boolean
		//		Use alternate row CSS classes to show zebra striping.
		// headClass: String
		//		CSS Class name for the head of the table.
		// tbodyClass: String
		//		CSS Class name for the body of the table.
		// headerClass: String
		//		CSS Class name for headers that are not sorted.
		// headerUpClass: String
		//		CSS Class name for headers that are for ascending sorted columns. Default is "selectedUp".
		// headerDownClass: String
		//		CSS Class name for headers that are for descending sorted columns. Default is "selectedDown".
		// rowClass: String
		//		CSS Class name for body rows.
		// rowAlternateClass: String
		//		CSS Class name for alternate rows.  Default is "alt".
		// rowSelectedClass: String
		//		CSS Class name for selected rows.  Default is "selected".
		// columnSelectedClass: String
		//		CSS Class name for any columns being sorted on.  Unimplemented.
		this.store=new dojo.collections.Store();

		//declare per instance changeable widget properties
		this.valueField="Id";
		this.multiple=false;
		this.maxSelect=0;
		this.maxSortable=1;  // how many columns can be sorted at once.
		this.minRows=0;
		this.defaultDateFormat = "%D";
		this.isInitialized=false;
		this.alternateRows=false;

		this.columns=[];
		this.sortInformation=[{
			index:0,
			direction:0
		}];

		// CSS definitions
		this.headClass="";
		this.tbodyClass="";
		this.headerClass="";
		this.headerUpClass="selectedUp";
		this.headerDownClass="selectedDown";
		this.rowClass="";
		this.rowAlternateClass="alt";
		this.rowSelectedClass="selected";
		this.columnSelected="sorted-column";
	},
{
	//	dojo widget properties
	isContainer: false,
	templatePath: null,
	templateCssPath: null,

	//	methods.
	getTypeFromString: function(/* string */s){
		//	summary
		//	Gets a function based on the passed string.
		var parts = s.split("."), i = 0, obj = dj_global;
		do{
			obj = obj[parts[i++]];
		} while (i < parts.length && obj);
		return (obj != dj_global) ? obj : null;	//	function
	},

	//	custom data access.
	getByRow: function(/*HTMLTableRow*/row){
		//	summary
		//	Returns the data object based on the passed row.
		return this.store.getByKey(dojo.html.getAttribute(row, "value"));	//	object
	},
	getDataByRow: function(/*HTMLTableRow*/row){
		//	summary
		//	Returns the source data object based on the passed row.
		return this.store.getDataByKey(dojo.html.getAttribute(row, "value")); // object
	},

	getRow: function(/* Object */ obj){
		//	summary
		//	Finds the row in the table based on the passed data object.
		var rows = this.domNode.tBodies[0].rows;
		for(var i=0; i<rows.length; i++){
			if(this.store.getDataByKey(dojo.html.getAttribute(rows[i], "value")) == obj){
				return rows[i];	//	HTMLTableRow
			}
		}
		return null;	//	HTMLTableRow
	},
	getColumnIndex: function(/* string */fieldPath){
		//	summary
		//	Returns index of the column that represents the passed field path.
		for(var i=0; i<this.columns.length; i++){
			if(this.columns[i].getField() == fieldPath){
				return i;	//	integer
			}
		}
		return -1;	//	integer
	},

	getSelectedData: function(){
		//	summary
		//	returns all objects that are selected.
		var data=this.store.get();
		var a=[];
		for(var i=0; i<data.length; i++){
			if(data[i].isSelected){
				a.push(data[i].src);
			}
		}
		if(this.multiple){
			return a;		//	array
		} else {
			return a[0];	//	object
		}
	},

	isSelected: function(/* object */obj){
		//	summary
		//	Returns whether the passed object is currently selected.
		var data = this.store.get();
		for(var i=0; i<data.length; i++){
			if(data[i].src == obj){
				return true;	//	boolean
			}
		}
		return false;	//	boolean
	},
	isValueSelected: function(/* string */val){
		//	summary
		//	Returns the object represented by key "val" is selected.
		var v = this.store.getByKey(val);
		if(v){
			return v.isSelected;	//	boolean
		}
		return false;	//	boolean
	},
	isIndexSelected: function(/* number */idx){
		//	summary
		//	Returns the object represented by integer "idx" is selected.
		var v = this.store.getByIndex(idx);
		if(v){
			return v.isSelected;	//	boolean
		}
		return false;	//	boolean
	},
	isRowSelected: function(/* HTMLTableRow */row){
		//	summary
		//	Returns if the passed row is selected.
		var v = this.getByRow(row);
		if(v){
			return v.isSelected;	//	boolean
		}
		return false;	//	boolean
	},

	reset: function(){
		//	summary
		//	Resets the widget to its initial internal state.
		this.store.clearData();
		this.columns = [];
		this.sortInformation = [ {index:0, direction:0} ];
		this.resetSelections();
		this.isInitialized = false;
		this.onReset();
	},
	resetSelections: function(){
		//	summary
		//	Unselects all data objects.
		this.store.forEach(function(element){
			element.isSelected = false;
		});
	},
	onReset:function(){
		//	summary
		//	Stub for onReset event.
	},

	//	selection and toggle functions
	select: function(/*object*/ obj){
		//	summary
		//	selects the passed object.
		var data = this.store.get();
		for(var i=0; i<data.length; i++){
			if(data[i].src == obj){
				data[i].isSelected = true;
				break;
			}
		}
		this.onDataSelect(obj);
	},
	selectByValue: function(/*string*/ val){
		//	summary
		//	selects the object represented by key "val".
		this.select(this.store.getDataByKey(val));
	},
	selectByIndex: function(/*number*/ idx){
		//	summary
		//	selects the object represented at index "idx".
		this.select(this.store.getDataByIndex(idx));
	},
	selectByRow: function(/*HTMLTableRow*/ row){
		//	summary
		//	selects the object represented by HTMLTableRow row.
		this.select(this.getDataByRow(row));
	},
	selectAll: function(){
		//	summary
		//	selects all objects.
		this.store.forEach(function(element){
			element.isSelected = true;
		});
	},
	onDataSelect: function(/* object */obj){
		//	summary
		//	Stub for onDataSelect event.
	},

	toggleSelection: function(/*object*/obj){
		//	summary
		//	Flips the selection state of passed obj.
		var data = this.store.get();
		for(var i=0; i<data.length; i++){
			if(data[i].src == obj){
				data[i].isSelected = !data[i].isSelected;
				break;
			}
		}
		this.onDataToggle(obj);
	},
	toggleSelectionByValue: function(/*string*/val){
		//	summary
		//	Flips the selection state of object represented by val.
		this.toggleSelection(this.store.getDataByKey(val));
	},
	toggleSelectionByIndex: function(/*number*/idx){
		//	summary
		//	Flips the selection state of object at index idx.
		this.toggleSelection(this.store.getDataByIndex(idx));
	},
	toggleSelectionByRow: function(/*HTMLTableRow*/row){
		//	summary
		//	Flips the selection state of object represented by row.
		this.toggleSelection(this.getDataByRow(row));
	},
	toggleAll: function(){
		//	summary
		//	Flips the selection state of all objects.
		this.store.forEach(function(element){
			element.isSelected = !element.isSelected;
		});
	},
	onDataToggle: function(/* object */obj){
		//	summary
		//	Stub for onDataToggle event.
	},

	//	parsing functions, from HTML to metadata/SimpleStore
	_meta:{
		field:null,
		format:null,
		filterer:null,
		noSort:false,
		sortType:"String",
		dataType:String,
		sortFunction:null,
		filterFunction:null,
		label:null,
		align:"left",
		valign:"middle",
		getField:function(){
			return this.field || this.label;
		},
		getType:function(){
			return this.dataType;
		}
	},
	createMetaData: function(/* object */obj){
		//	summary
		//	Take a JSON-type structure and make it into a ducktyped metadata object.
		for(var p in this._meta){
			//	rudimentary mixin
			if(!obj[p]){
				obj[p] = this._meta[p];
			}
		}
		if(!obj.label){
			obj.label=obj.field;
		}
		if(!obj.filterFunction){
			obj.filterFunction=this._defaultFilter;
		}
		return obj;	//	object
	},
	parseMetadata: function(/* HTMLTableHead */head){
		//	summary
		//	Parses the passed HTMLTableHead element to create meta data.
		this.columns=[];
		this.sortInformation=[];
		var row = head.getElementsByTagName("tr")[0];
		var cells = row.getElementsByTagName("td");
		if (cells.length == 0){
			cells = row.getElementsByTagName("th");
		}
		for(var i=0; i<cells.length; i++){
			var o = this.createMetaData({ });

			//	presentation attributes
			if(dojo.html.hasAttribute(cells[i], "align")){
				o.align = dojo.html.getAttribute(cells[i],"align");
			}
			if(dojo.html.hasAttribute(cells[i], "valign")){
				o.valign = dojo.html.getAttribute(cells[i],"valign");
			}
			if(dojo.html.hasAttribute(cells[i], "nosort")){
				o.noSort = (dojo.html.getAttribute(cells[i],"nosort")=="true");
			}
			if(dojo.html.hasAttribute(cells[i], "sortusing")){
				var trans = dojo.html.getAttribute(cells[i],"sortusing");
				var f = this.getTypeFromString(trans);
				if (f != null && f != window && typeof(f)=="function"){
					o.sortFunction=f;
				}
			}
			o.label = dojo.html.renderedTextContent(cells[i]);
			if(dojo.html.hasAttribute(cells[i], "field")){
				o.field=dojo.html.getAttribute(cells[i],"field");
			} else if(o.label.length > 0){
				o.field=o.label;
			} else {
				o.field = "field" + i;
			}
			if(dojo.html.hasAttribute(cells[i], "format")){
				o.format=dojo.html.getAttribute(cells[i],"format");
			}
			if(dojo.html.hasAttribute(cells[i], "dataType")){
				var sortType = dojo.html.getAttribute(cells[i],"dataType");
				if(sortType.toLowerCase()=="html" || sortType.toLowerCase()=="markup"){
					o.sortType = "__markup__";	//	always convert to "__markup__"
				}else{
					var type = this.getTypeFromString(sortType);
					if(type){
						o.sortType = sortType;
						o.dataType = type;
					}
				}
			}

			//	TODO: set up filtering mechanisms here.
			if(dojo.html.hasAttribute(cells[i], "filterusing")){
				var trans = dojo.html.getAttribute(cells[i],"filterusing");
				var f = this.getTypeFromString(trans);
				if (f != null && f != window && typeof(f)=="function"){
					o.filterFunction=f;
				}
			}

			this.columns.push(o);

			//	check to see if there's a default sort, and set the properties necessary
			if(dojo.html.hasAttribute(cells[i], "sort")){
				var info = {
					index:i,
					direction:0
				};
				var dir = dojo.html.getAttribute(cells[i], "sort");
				if(!isNaN(parseInt(dir))){
					dir = parseInt(dir);
					info.direction = (dir != 0) ? 1 : 0;
				}else{
					info.direction = (dir.toLowerCase() == "desc") ? 1 : 0;
				}
				this.sortInformation.push(info);
			}
		}
		if(this.sortInformation.length == 0){
			this.sortInformation.push({
				index:0,
				direction:0
			});
		} else if (this.sortInformation.length > this.maxSortable){
			this.sortInformation.length = this.maxSortable;
		}
	},
	parseData: function(/* HTMLTableBody */body){
		//	summary
		//	Parse HTML data into native JSON structure for the store.
		if(body.rows.length == 0 && this.columns.length == 0){
			return;	//	there's no data, ignore me.
		}

		//	create a data constructor based on what we've got for the fields.
		var self=this;
		this["__selected__"] = [];
		var arr = this.store.getFromHtml(this.columns, body, function(obj, row){
			if(typeof(obj[self.valueField])=="undefined" || obj[self.valueField]==null){
				obj[self.valueField] = dojo.html.getAttribute(row, "value");
			}
			if(dojo.html.getAttribute(row, "selected")=="true"){
				self["__selected__"].push(obj);
			}
		});

		this.store.setData(arr, true);
		this.render();

		for(var i=0; i<this["__selected__"].length; i++){
			this.select(this["__selected__"][i]);
		}
		this.renderSelections();

		delete this["__selected__"];

		//	say that we are already initialized so that we don't kill anything
		this.isInitialized=true;
	},

	//	standard events
	onSelect: function(/* HTMLEvent */e){
		//	summary
		//	Handles the onclick event of any element.
		var row = dojo.html.getParentByType(e.target,"tr");
		if(dojo.html.hasAttribute(row,"emptyRow")){
			return;
		}
		var body = dojo.html.getParentByType(row,"tbody");
		if(this.multiple){
			if(e.shiftKey){
				var startRow;
				var rows=body.rows;
				for(var i=0;i<rows.length;i++){
					if(rows[i]==row){
						break;
					}
					if(this.isRowSelected(rows[i])){
						startRow=rows[i];
					}
				}
				if(!startRow){
					startRow = row;
					for(; i<rows.length; i++){
						if(this.isRowSelected(rows[i])){
							row = rows[i];
							break;
						}
					}
				}
				this.resetSelections();
				if(startRow == row){
					this.toggleSelectionByRow(row);
				} else {
					var doSelect = false;
					for(var i=0; i<rows.length; i++){
						if(rows[i] == startRow){
							doSelect=true;
						}
						if(doSelect){
							this.selectByRow(rows[i]);
						}
						if(rows[i] == row){
							doSelect = false;
						}
					}
				}
			} else {
				this.toggleSelectionByRow(row);
			}
		} else {
			this.resetSelections();
			this.toggleSelectionByRow(row);
		}
		this.renderSelections();
	},
	onSort: function(/* HTMLEvent */e){
		//	summary
		//	Sort the table based on the column selected.
		var oldIndex=this.sortIndex;
		var oldDirection=this.sortDirection;

		var source=e.target;
		var row=dojo.html.getParentByType(source,"tr");
		var cellTag="td";
		if(row.getElementsByTagName(cellTag).length==0){
			cellTag="th";
		}

		var headers=row.getElementsByTagName(cellTag);
		var header=dojo.html.getParentByType(source,cellTag);

		for(var i=0; i<headers.length; i++){
			dojo.html.setClass(headers[i], this.headerClass);
			if(headers[i]==header){
				if(this.sortInformation[0].index != i){
					this.sortInformation.unshift({
						index:i,
						direction:0
					});
				} else {
					this.sortInformation[0] = {
						index:i,
						direction:(~this.sortInformation[0].direction)&1
					};
				}
			}
		}

		this.sortInformation.length = Math.min(this.sortInformation.length, this.maxSortable);
		for(var i=0; i<this.sortInformation.length; i++){
			var idx=this.sortInformation[i].index;
			var dir=(~this.sortInformation[i].direction)&1;
			dojo.html.setClass(headers[idx], dir==0?this.headerDownClass:this.headerUpClass);
		}
		this.render();
	},
	onFilter: function(){
		//	summary
		//	show or hide rows based on the parameters of the passed filter.
	},

	//	Filtering methods
	_defaultFilter: function(/* Object */obj){
		//	summary
		//	Always return true as the result of the default filter.
		return true;
	},
	setFilter: function(/* string */field, /* function */fn){
		//	summary
		//	set a filtering function on the passed field.
		for(var i=0; i<this.columns.length; i++){
			if(this.columns[i].getField() == field){
				this.columns[i].filterFunction=fn;
				break;
			}
		}
		this.applyFilters();
	},
	setFilterByIndex: function(/* number */idx, /* function */fn){
		//	summary
		//	set a filtering function on the passed column index.
		this.columns[idx].filterFunction=fn;
		this.applyFilters();
	},
	clearFilter: function(/* string */field){
		//	summary
		//	clear a filtering function on the passed field.
		for(var i=0; i<this.columns.length; i++){
			if(this.columns[i].getField() == field){
				this.columns[i].filterFunction=this._defaultFilter;
				break;
			}
		}
		this.applyFilters();
	},
	clearFilterByIndex: function(/* number */idx){
		//	summary
		//	clear a filtering function on the passed column index.
		this.columns[idx].filterFunction=this._defaultFilter;
		this.applyFilters();
	},
	clearFilters: function(){
		//	summary
		//	clears all filters.
		for(var i=0; i<this.columns.length; i++){
			this.columns[i].filterFunction=this._defaultFilter;
		}
		//	we'll do the clear manually, it will be faster.
		var rows=this.domNode.tBodies[0].rows;
		for(var i=0; i<rows.length; i++){
			rows[i].style.display="";
			if(this.alternateRows){
				dojo.html[((i % 2 == 1)?"addClass":"removeClass")](rows[i], this.rowAlternateClass);
			}
		}
		this.onFilter();
	},
	applyFilters: function(){
		//	summary
		//	apply all filters to the table.
		var alt=0;
		var rows=this.domNode.tBodies[0].rows;
		for(var i=0; i<rows.length; i++){
			var b=true;
			var row=rows[i];
			for(var j=0; j<this.columns.length; j++){
				var value = this.store.getField(this.getDataByRow(row), this.columns[j].getField());
				if(this.columns[j].getType() == Date && value != null && !value.getYear){
					value = new Date(value);
				}
				if(!this.columns[j].filterFunction(value)){
					b=false;
					break;
				}
			}
			row.style.display=(b?"":"none");
			if(b && this.alternateRows){
				dojo.html[((alt++ % 2 == 1)?"addClass":"removeClass")](row, this.rowAlternateClass);
			}
		}
		this.onFilter();
	},

	//	sorting functionality
	createSorter: function(/* array */info){
		//	summary
		//	creates a custom function to be used for sorting.
		var self=this;
		var sortFunctions=[];	//	our function stack.

		function createSortFunction(fieldIndex, dir){
			var meta=self.columns[fieldIndex];
			var field=meta.getField();
			return function(rowA, rowB){
				if(dojo.html.hasAttribute(rowA,"emptyRow")){ return 1; }
				if(dojo.html.hasAttribute(rowB,"emptyRow")){ return -1; }

				//	TODO: check for markup and compare by rendered text.
				var a = self.store.getField(self.getDataByRow(rowA), field);
				var b = self.store.getField(self.getDataByRow(rowB), field);
				var ret = 0;
				if(a > b) ret = 1;
				if(a < b) ret = -1;
				return dir * ret;
			}
		}

		var current=0;
		var max = Math.min(info.length, this.maxSortable, this.columns.length);
		while(current < max){
			var direction = (info[current].direction == 0) ? 1 : -1;
			sortFunctions.push(
				createSortFunction(info[current].index, direction)
			);
			current++;
		}

		return function(rowA, rowB){
			var idx=0;
			while(idx < sortFunctions.length){
				var ret = sortFunctions[idx++](rowA, rowB);
				if(ret != 0) return ret;
			}
			//	if we got here then we must be equal.
			return 0;
		};	//	function
	},

	//	rendering
	createRow: function(/* object */obj){
		//	summary
		//	Create an HTML row based on the passed object
		var row=document.createElement("tr");
		dojo.html.disableSelection(row);
		if(obj.key != null){
			row.setAttribute("value", obj.key);
		}
		for(var j=0; j<this.columns.length; j++){
			var cell=document.createElement("td");
			cell.setAttribute("align", this.columns[j].align);
			cell.setAttribute("valign", this.columns[j].valign);
			dojo.html.disableSelection(cell);
			var val = this.store.getField(obj.src, this.columns[j].getField());
			if(typeof(val)=="undefined"){
				val="";
			}
			this.fillCell(cell, this.columns[j], val);
			row.appendChild(cell);
		}
		return row;	//	HTMLTableRow
	},
	fillCell: function(/* HTMLTableCell */cell, /* object */meta, /* object */val){
		//	summary
		//	Fill the passed cell with value, based on the passed meta object.
		if(meta.sortType=="__markup__"){
			cell.innerHTML=val;
		} else {
			if(meta.getType()==Date) {
				val=new Date(val);
				if(!isNaN(val)){
					var format = this.defaultDateFormat;
					if(meta.format){
						format = meta.format;
					}
					cell.innerHTML = dojo.date.strftime(val, format);
				} else {
					cell.innerHTML = val;
				}
			} else if ("Number number int Integer float Float".indexOf(meta.getType())>-1){
				//	TODO: number formatting
				if(val.length == 0){
					val="0";
				}
				var n = parseFloat(val, 10) + "";
				//	TODO: numeric formatting + rounding :)
				if(n.indexOf(".")>-1){
					n = dojo.math.round(parseFloat(val,10),2);
				}
				cell.innerHTML = n;
			}else{
				cell.innerHTML = val;
			}
		}
	},
	prefill: function(){
		//	summary
		//	if there's no data in the table, then prefill it with this.minRows.
		this.isInitialized = false;
		var body = this.domNode.tBodies[0];
		while (body.childNodes.length > 0){
			body.removeChild(body.childNodes[0]);
		}

		if(this.minRows>0){
			for(var i=0; i < this.minRows; i++){
				var row = document.createElement("tr");
				if(this.alternateRows){
					dojo.html[((i % 2 == 1)?"addClass":"removeClass")](row, this.rowAlternateClass);
				}
				row.setAttribute("emptyRow","true");
				for(var j=0; j<this.columns.length; j++){
					var cell = document.createElement("td");
					cell.innerHTML = "&nbsp;";
					row.appendChild(cell);
				}
				body.appendChild(row);
			}
		}
	},
	init: function(){
		//	summary
		//	initializes the table of data
		this.isInitialized=false;

		//	if there is no thead, create it now.
		var head=this.domNode.getElementsByTagName("thead")[0];
		if(head.getElementsByTagName("tr").length == 0){
			//	render the column code.
			var row=document.createElement("tr");
			for(var i=0; i<this.columns.length; i++){
				var cell=document.createElement("td");
				cell.setAttribute("align", this.columns[i].align);
				cell.setAttribute("valign", this.columns[i].valign);
				dojo.html.disableSelection(cell);
				cell.innerHTML=this.columns[i].label;
				row.appendChild(cell);

				//	attach the events.
				if(!this.columns[i].noSort){
					dojo.event.connect(cell, "onclick", this, "onSort");
				}
			}
			dojo.html.prependChild(row, head);
		}

		if(this.store.get().length == 0){
			return false;
		}

		var idx=this.domNode.tBodies[0].rows.length;
		if(!idx || idx==0 || this.domNode.tBodies[0].rows[0].getAttribute("emptyRow")=="true"){
			idx = 0;
			var body = this.domNode.tBodies[0];
			while(body.childNodes.length>0){
				body.removeChild(body.childNodes[0]);
			}

			var data = this.store.get();
			for(var i=0; i<data.length; i++){
				var row = this.createRow(data[i]);
				body.appendChild(row);
				idx++;
			}
		}

		//	add empty rows
		if(this.minRows > 0 && idx < this.minRows){
			idx = this.minRows - idx;
			for(var i=0; i<idx; i++){
				row=document.createElement("tr");
				row.setAttribute("emptyRow","true");
				for(var j=0; j<this.columns.length; j++){
					cell=document.createElement("td");
					cell.innerHTML="&nbsp;";
					row.appendChild(cell);
				}
				body.appendChild(row);
			}
		}

		//	last but not least, show any columns that have sorting already on them.
		var row=this.domNode.getElementsByTagName("thead")[0].rows[0];
		var cellTag="td";
		if(row.getElementsByTagName(cellTag).length==0) cellTag="th";
		var headers=row.getElementsByTagName(cellTag);
		for(var i=0; i<headers.length; i++){
			dojo.html.setClass(headers[i], this.headerClass);
		}
		for(var i=0; i<this.sortInformation.length; i++){
			var idx=this.sortInformation[i].index;
			var dir=(~this.sortInformation[i].direction)&1;
			dojo.html.setClass(headers[idx], dir==0?this.headerDownClass:this.headerUpClass);
		}

		this.isInitialized=true;
		return this.isInitialized;
	},
	render: function(){
		//	summary
		//	Renders the actual table data.

	/*	The method that should be called once underlying changes
	 *	are made, including sorting, filtering, data changes.
	 *	Rendering the selections themselves are a different method,
	 *	which render() will call as the last step.
	 ****************************************************************/
		if(!this.isInitialized){
			var b = this.init();
			if(!b){
				this.prefill();
				return;
			}
		}

		//	do the sort
		var rows=[];
		var body=this.domNode.tBodies[0];
		var emptyRowIdx=-1;
		for(var i=0; i<body.rows.length; i++){
			rows.push(body.rows[i]);
		}

		//	build the sorting function, and do the sorting.
		var sortFunction = this.createSorter(this.sortInformation);
		if(sortFunction){
			rows.sort(sortFunction);
		}

		//	append the rows without killing them, this should help with the HTML problems.
		for(var i=0; i<rows.length; i++){
			if(this.alternateRows){
				dojo.html[((i%2==1)?"addClass":"removeClass")](rows[i], this.rowAlternateClass);
			}
			dojo.html[(this.isRowSelected(body.rows[i])?"addClass":"removeClass")](body.rows[i], this.rowSelectedClass);
			body.appendChild(rows[i]);
		}
	},
	renderSelections: function(){
		//	summary
		//	Render all selected objects using CSS.
		var body=this.domNode.tBodies[0];
		for(var i=0; i<body.rows.length; i++){
			dojo.html[(this.isRowSelected(body.rows[i])?"addClass":"removeClass")](body.rows[i], this.rowSelectedClass);
		}
	},

	//	widget lifetime handlers
	initialize: function(){
		//	summary
		//	Initializes the widget.
		var self=this;
		//	connect up binding listeners here.
		dojo.event.connect(this.store, "onSetData", function(){
			self.store.forEach(function(element){
				element.isSelected = false;
			});
			self.isInitialized=false;
			var body = self.domNode.tBodies[0];
			if(body){
				while(body.childNodes.length>0){
					body.removeChild(body.childNodes[0]);
				}
			}
			self.render();
		});
		dojo.event.connect(this.store, "onClearData", function(){
			self.isInitialized = false;
			self.render();
		});
		dojo.event.connect(this.store, "onAddData", function(addedObject){
			var row=self.createRow(addedObject);
			self.domNode.tBodies[0].appendChild(row);
			self.render();
		});
		dojo.event.connect(this.store, "onAddDataRange", function(arr){
			for(var i=0; i<arr.length; i++){
				arr[i].isSelected=false;
				var row=self.createRow(arr[i]);
				self.domNode.tBodies[0].appendChild(row);
			};
			self.render();
		});
		dojo.event.connect(this.store, "onRemoveData", function(removedObject){
			var rows = self.domNode.tBodies[0].rows;
			for(var i=0; i<rows.length; i++){
				if(self.getDataByRow(rows[i]) == removedObject.src){
					rows[i].parentNode.removeChild(rows[i]);
					break;
				}
			}
			self.render();
		});
		dojo.event.connect(this.store, "onUpdateField", function(obj, fieldPath, val){
			var row = self.getRow(obj);
			var idx = self.getColumnIndex(fieldPath);
			if(row && row.cells[idx] && self.columns[idx]){
				self.fillCell(row.cells[idx], self.columns[idx], val);
			}
		});
	},
	postCreate: function(){
		//	summary
		//	finish widget initialization.
		this.store.keyField = this.valueField;

		if(this.domNode){
			//	start by making sure domNode is a table element;
			if(this.domNode.nodeName.toLowerCase() != "table"){
			}

			//	see if there is columns set up already
			if(this.domNode.getElementsByTagName("thead")[0]){
				var head=this.domNode.getElementsByTagName("thead")[0];
				if(this.headClass.length > 0){
					head.className = this.headClass;
				}
				dojo.html.disableSelection(this.domNode);
				this.parseMetadata(head);

				var header="td";
				if(head.getElementsByTagName(header).length==0){
					header="th";
				}
				var headers = head.getElementsByTagName(header);
				for(var i=0; i<headers.length; i++){
					if(!this.columns[i].noSort){
						dojo.event.connect(headers[i], "onclick", this, "onSort");
					}
				}
			} else {
				this.domNode.appendChild(document.createElement("thead"));
			}

			// if the table doesn't have a tbody already, add one and grab a reference to it
			if (this.domNode.tBodies.length < 1) {
				var body = document.createElement("tbody");
				this.domNode.appendChild(body);
			} else {
				var body = this.domNode.tBodies[0];
			}

			if (this.tbodyClass.length > 0){
				body.className = this.tbodyClass;
			}
			dojo.event.connect(body, "onclick", this, "onSelect");
			this.parseData(body);
		}
	}
});
