

/**************************************************************

	Script		: Sortable Table
	Version		: 1.4
	Authors		: Samuel Birch
	Desc			: Sorts and filters table elements
	Licence		: Open Source MIT Licence

**************************************************************/

var sortableTable = new Class({
							  
	getOptions: function(){
		return {
			overCls: false,
			onClick: false,
			sortOn: 0,
			sortBy: 'ASC',
			filterHide: true,
			filterHideCls: 'hide',
			filterSelectedCls: 'selected'
		};
	},

	initialize: function(table, options){
		
		if ($defined($(table))) {
			this.setOptions(this.getOptions(), options);
			//this.table = $(table).getElement('table');
			this.table = $(table);
			//console.log($(table).getParent().getParent());
			if ($type($(this.table)) == 'element') {
				this.tHead = this.table.getElement('thead');
				this.tBody = this.table.getElement('tbody');
				this.tFoot = this.table.getElement('tfoot');
				if ($type($(this.tBody)) == 'element') {
					this.elements = this.tBody.getElements('tr');
				} else {
					return false;
				}
				this.filtered = false;
				
				/*for(i=0;i<10;i++){
					this.elements.clone().injectInside(this.tBody);
				}
				this.elements = this.tBody.getElements('tr');*/
				
				this.elements.each(function(el,i){
					if(this.options.overCls){
						el.addEvent('mouseover', function(){
							el.addClass(options.overCls);
						}, this);
						el.addEvent('mouseout', function(){
							el.removeClass(options.overCls);
						});
					}
					if(this.options.onClick){
						el.addEvent('click', options.onClick);
					}
				}, this);
				
				//setup header
				this.tHead.getElements('th').each(function(el,i) {
					if(el.axis) {
						el.addEvent('click', this.sort.bind(this,i));
						el.addEvent('mouseover', function(){
							el.addClass('tableHeaderOver');
						});
						el.addEvent('mouseout', function(){
							el.removeClass('tableHeaderOver');
						});
						el.getdate = function(str){
							// inner util function to convert 2-digit years to 4
							function fixYear(yr) {
								yr = +yr;
								if (yr<50) { yr += 2000; }
								else if (yr<100) { yr += 1900; }
								return yr;
							};
							var ret;
							//
							if (str.length>12){
								strtime = str.substring(str.lastIndexOf(' ')+1);
								strtime = strtime.substring(0,2)+strtime.substr(-2)
							}else{
								strtime = '0000';
							}
							//
							// YYYY-MM-DD
							if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
								return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]) + strtime;
							}
							// DD/MM/YY[YY] or DD-MM-YY[YY]
							if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
								return (fixYear(ret[3])*10000) + (ret[2]*100) + (+ret[1]) + strtime;
							}
							return 999999990000; // So non-parsed dates will be last, not first
						};
						//
						el.findData = function(elem){
							var child = elem.getFirst();
							if(child){
								return el.findData(child);
							}else{
								return elem.innerHTML.trim();
							}
						};
						//
						el.compare = function(a,b){
							var1 = el.findData(a.getChildren()[i]);
							var2 = el.findData(b.getChildren()[i]);
							//var1 = a.getChildren()[i].firstChild.data;
							//var2 = b.getChildren()[i].firstChild.data;
							
							if(el.axis == 'number'){
								var1 = parseFloat(var1);
								var2 = parseFloat(var2);
								
								if(el.sortBy == 'ASC'){
									return var1-var2;
								}else{
									return var2-var1;
								}
								
							}else if(el.axis == 'string'){
								var1 = var1.replace(/<\/?[^>]+>/gi, '').replace(/[^a-zA-Z]/ig,'');
								var2 = var2.replace(/<\/?[^>]+>/gi, '').replace(/[^a-zA-Z]/ig,'');
								
								if(var1==var2){return 0};
								if(el.sortBy == 'ASC'){
									if(var1<var2){return -1};
								}else{
									if(var1>var2){return -1};
								}
								return 1;
								
							}else if(el.axis == 'date'){
								var1 = parseFloat(el.getdate(var1));
								var2 = parseFloat(el.getdate(var2));
								
								if(el.sortBy == 'ASC'){
									return var1-var2;
								}else{
									return var2-var1;
								}
								
							}else if(el.axis == 'currency'){
								var1 = parseFloat(var1.substr(1).replace(',',''));
								var2 = parseFloat(var2.substr(1).replace(',',''));
								
								if(el.sortBy == 'ASC'){
									return var1-var2;
								}else{
									return var2-var1;
								}
								
							}
							
						}
						
						if(i == this.options.sortOn){
							el.fireEvent('click');
						}
					}
				
				}, this);
			}
			
		}
	},
	
	sort: function(index) {
		if(this.options.onStart){
			this.fireEvent('onStart');
		}
		//
		this.options.sortOn = index;
		var header = this.tHead.getElements('th');
		var el = header[index];
		
		header.each(function(e,i){
			if(i != index){
				e.removeClass('sortedASC');
				e.removeClass('sortedDESC');
			}
		});
		
		if(el.hasClass('sortedASC')){
			el.removeClass('sortedASC');
			el.addClass('sortedDESC');
			el.sortBy = 'DESC';
		}else if(el.hasClass('sortedDESC')){
			el.removeClass('sortedDESC');
			el.addClass('sortedASC');
			el.sortBy = 'ASC';
		}else{
			if(this.options.sortBy == 'ASC'){
				el.addClass('sortedASC');
				el.sortBy = 'ASC';
			}else if(this.options.sortBy == 'DESC'){
				el.addClass('sortedDESC');
				el.sortBy = 'DESC';
			}
		}
		//
		this.elements.sort(el.compare);
		this.elements.injectInside(this.tBody);
		//
		if(this.filtered){
			this.filteredeven();
		}else{
			this.even();
		}
		
		//
		if(this.options.onComplete){
			this.fireEvent('onComplete');
		}
	},
	
	even: function(){
		this.elements.each(function(el,i){
			if(i % 2){
				el.removeClass('odd');
				el.addClass('even');
			}else{
				el.removeClass('even');
				el.addClass('odd');
			}
		});
	},
	
	filteredeven: function(){
		this.table.getElements('.'+this.options.filterSelectedCls).each(function(el,i){
			if(i % 2){
				el.removeClass('odd');
				el.addClass('even');
			}else{
				el.removeClass('even');
				el.addClass('odd');
			}
		});
	},
	
	filter: function(col, key){
		
		/*
		if(el.type == 'reset'){
			el.addEvent('click',this.clearFilter.bind(this));
		}
		*/
			
		if(key) {
			if (key !== 'all') {
				this.elements.each(function(el,i){
					if(this.options.filterHide){
						el.removeClass('odd');
						el.addClass('even');
					}
					console.log(el.getChildren()[col].firstChild.innerHTML);
					if(el.getChildren()[col].firstChild.innerHTML.toLowerCase().indexOf(key) > -1){
						el.addClass(this.options.filterSelectedCls);
						if(this.options.filterHide){
							el.removeClass(this.options.filterHideCls);
						}
					}else{
						el.removeClass(this.options.filterSelectedCls);
						if(this.options.filterHide){
							el.addClass(this.options.filterHideCls);
						}
					}
				}, this);
				if(this.options.filterHide){
					this.filteredeven();
					this.filtered = true;
				}
			} else {
				this.clearFilter(col);
			}
		}
	},
	
	clearFilter: function(col){
		this.elements.each(function(el,i){
			el.removeClass(this.options.filterSelectedCls);
			if(this.options.filterHide){
				el.removeClass(this.options.filterHideCls);
			}
		}, this);
		if(this.options.filterHide){
			this.even();
			this.filtered = false;
		}
		
		var header = this.tHead.getElements('th');
		var currentCol = header[col];
		
		$$('.filter select').each(function(selectElm) { 
			if ($(currentCol).getElement('select') !== selectElm) {
				$('codeFilter').value = '';
				$(selectElm).selectedIndex = 0; 
			}
		});
		
		if ($defined($(currentCol))) {
			$$('a.clearLink').each(function(clrLnk) { 
				if ($defined($(currentCol).getElement('a'))) {
					if ($(currentCol).getElement('a') == clrLnk) {
						$(clrLnk).remove(); 
					}
				}
			});
		}
		
	}

});
sortableTable.implement(new Events);
sortableTable.implement(new Options);

/*************************************************************/
