var Sortable = function(id, config){
	var config = config ? config : {};
	var obj = {
		sortIndex : -1,
		sortDesc : false,
		sorts : {
			_default : function(a,b){
				if(a < b) return -1;
				if(a > b) return 1;
				return 0;
			},
			numeric : function(a,b){
				if(!isNaN(a) && !isNaN(b)){
					var na = parseInt(a);
					var nb = parseInt(b);
					return na-nb;
				} else {
					var na = a.replace(/[^0-9\.]/g,'');
					var nb = b.replace(/[^0-9\.]/g,'');
					return na-nb;
				}
			}
		},
		init : function(){
			var obj = $("#"+id);
			if(!obj.is("table")){
				obj = obj.find("table");
			}
			obj.find("th").css("cursor","pointer").bind("click", {that:this}, function(event){
				var that = event.data.that;
				that.sort($(this).prevAll().length);
			});
			this.sortEl = obj;
		},
		sort : function(colIndex){
			if(colIndex == this.sortIndex) this.sortDesc = !this.sortDesc;
			else this.sortDesc = false;
			this.sortIndex = colIndex;
			
			var items = [];
			
			this.sortEl.find("tr").each(function(){
				var rowIndex = $(this).prevAll().length;
				if(rowIndex > 0){
					items.push({
						key: $(this).children("td:eq("+colIndex+")").text().toLowerCase(),
						value: $('<div>').append( $(this).clone() ).html()
					});
					$(this).remove();
				}
			});
			
			var sortCol = $("th:eq("+colIndex+")");
			if(sortCol.attr('class')){
				var m = sortCol.attr('class').match(/.*sort-([a-z0-9]+).*/i);
				var sort = m ? m[1] : "_default";
			}
			
			var self = this;
			items.sort(function(a,b){
				var sortBy = self.sorts[sort] ? self.sorts[sort] : self.sorts["_default"];
				if(self.sortDesc)
					return -1*sortBy(a.key, b.key);
				else
					return sortBy(a.key, b.key);
			});
			
			for(i in items){
				this.sortEl.append(items[i].value);
			}
			
			this.sortEl.find("tr").removeClass("odd");
			this.sortEl.find("tr:has(td):odd").addClass("odd");
			
			this.sortEl.find("tr th.sortAsc").removeClass("sortAsc");
			this.sortEl.find("tr th.sortDesc").removeClass("sortDesc");
			
			if(this.sortDesc)
				this.sortEl.find("tr th:eq("+this.sortIndex+")").addClass("sortDesc");
			else
				this.sortEl.find("tr th:eq("+this.sortIndex+")").addClass("sortAsc");
		}
	};
	
	if(config.sorts){
		for(key in config.sorts){
			obj.sorts[key] = config.sorts[key];
		}
	}
	
	obj.init();
	return obj;
};