// SortableTable Class v1.0
// Author:	Золотухин Сергей ( serge@design.ru, http://serge.design.ru/ )
// Updated:	2003-12-24

/*
	CSS селекторы:

		st_Sortable
		st_Sorted

		st_Asc
		st_Desc

		st_TypeNumber
		st_TypeMoney

	Events:

		OnSortBegin
		OnSortEnd
*/

function SortableTable( htmlTableID, sortedColumnIndex )
{
	var i
	var thisCopy = this

	//	CSS селекторы
	this.SORTED = 'st_Sorted'
	this.SORTABLE = 'st_Sortable'
	this.SORTED_ASC = 'st_Asc'
	this.SORTED_DESC = 'st_Desc'

	this.TYPE_NUMBER = 'st_TypeNumber'
	this.TYPE_MONEY = 'st_TypeMoney'

	this.SortedColumnIndex = ( sortedColumnIndex == null ) ? -1 : sortedColumnIndex

	this.table = document.getElementById( htmlTableID )
	this.head = this.table.getElementsByTagName('thead')[0]
	this.headCells = this.head.getElementsByTagName('td')

	// Посмотрим есть ли колонки, по которым будем сортировать
	if( this.head )
	{
		for( i=0; i<this.headCells.length; i++ )
		{
			if( this.getSelector( this.headCells[i], this.SORTABLE ) )
			{
				this.headCells[i].st_Index = i

				if( this.getSelector( this.headCells[i], this.TYPE_NUMBER ) )
				{
					this.headCells[i].st_SortkeyType = this.TYPE_NUMBER
				}

				if( this.headCells[i].attachEvent )
				{
					this.headCells[i].attachEvent( 'onclick', function(){thisCopy.sort()} )
					this.headCells[i].unselectable = true
				}
				if( this.headCells[i].addEventListener )
				{
					this.headCells[i].addEventListener( 'click', function(e){thisCopy.sort(e)}, false )
					this.headCells[i].onmousedown = function() {return false}
				}
			}
		}
	}

	this.body = this.table.getElementsByTagName('tbody')[0]
	this.rows = this.body.getElementsByTagName('tr')
	this.rowsCount = this.rows.length
	this.cache = new Array()

	// наверное не дурно было бы сделать индексы
	var cells = this.body.getElementsByTagName('td')
	var cellsCount = cells.length
		
	var abbr

	for( i=0; i<cellsCount; i++ )
	{
		abbr = cells[i].getAttribute('abbr')
		this.setCellSortkey(cells[i], ( abbr != null && abbr != '' ) ? abbr : cells[i].firstChild.nodeValue)
	}

	for( i=0; i<this.rowsCount; i++ )
	{
		this.cache[i] = this.rows[i].cloneNode(true)
	}

	return this
}


// Сортировка
SortableTable.prototype.sort = function(e)
{
	var thisCopy = this
	var headCell =  window.event ? window.event.srcElement : e.currentTarget

	if (headCell.tagName != 'TD' && headCell.tagName != 'td')
	{
		var c = 0
		while (headCell.tagName != 'TD' && headCell.tagName != 'td' && c < 10)
		{
			headCell = headCell.parentNode
			c++
		}
	}			

	if( this.OnSortBegin )
	{
		// Вызов пользовательского обработчика события с передачей события
		this.OnSortBegin( window.event ? window.event : e )
	}

	// Нужно поставить правильный селектор
	this.applySelectors(headCell)		
	

	if( headCell.st_Index == this.SortedColumnIndex )
	{
		this.cache.reverse(headCell)
	}
	else
	{
		this.SortedColumnIndex = headCell.st_Index;

		switch( headCell.st_SortkeyType )
		{
			// Сравнение чисел
			case this.TYPE_NUMBER :
			this.cache.sort(
				function( a, b )
				{
					var aVal = parseInt( thisCopy.getCellSortkey( a.getElementsByTagName('td')[thisCopy.SortedColumnIndex] ).replace (',', '.') )
					var bVal = parseInt( thisCopy.getCellSortkey( b.getElementsByTagName('td')[thisCopy.SortedColumnIndex] ).replace (',', '.') )
					
					var aValSort = a.getElementsByTagName('td')[thisCopy.SortedColumnIndex].getAttribute ("sort_order");
					var bValSort = b.getElementsByTagName('td')[thisCopy.SortedColumnIndex].getAttribute ("sort_order");
					
					if (aValSort && bValSort) return aValSort - bValSort

					return  ( aVal - bVal )
				}
			)
			break

			// Сравнение денежных величин (откусывается первый знак, типа $1 и $10)
			case this.TYPE_MONEY :
			this.cache.sort(
				function( a, b )
				{
					var aVal = parseFloat( thisCopy.getCellSortkey( a.getElementsByTagName('td')[thisCopy.SortedColumnIndex].firstChild.nodeValue).substr(1) )
					var bVal = parseFloat( thisCopy.getCellSortkey( b.getElementsByTagName('td')[thisCopy.SortedColumnIndex].firstChild.nodeValue).substr(1) )
					return ( aVal - bVal )
				}
			)
			break

			// Сравнение всего остального
			default:
			this.cache.sort(
				function( a, b )
				{
					var aVal = thisCopy.getCellSortkey( a.getElementsByTagName('td')[thisCopy.SortedColumnIndex] )
					var bVal = thisCopy.getCellSortkey( b.getElementsByTagName('td')[thisCopy.SortedColumnIndex] )
					return ( aVal == bVal ? 0 : ( aVal > bVal ? 1 : -1 ) )
				}
			)
		}
	}

	var body = document.createElement('tbody')
	for( var i=0; i<this.rowsCount; i++ )
	{
		body.appendChild( this.cache[i] )
	}
	this.table.replaceChild(body, this.body)
	this.body = body
	
	if( this.OnSortEnd )
	{
		// Вызов пользовательского обработчика события с передачей "нажатого" header'а
		this.OnSortEnd( window.event ? window.event : e )
	}
}


// Получение ключа сортировки ячейки
SortableTable.prototype.getCellSortkey = function( cell )
{
	return cell.getAttribute('Sortkey')
}

// Установка ключа сортировки ячейки
SortableTable.prototype.setCellSortkey = function( cell, val )
{
	cell.setAttribute('Sortkey', val)
}

// Проверка селектора у элемента
SortableTable.prototype.getSelector = function( elem, selector )
{
	return ( elem && elem.className.indexOf(selector) != -1 )
}

// Установка селектора у элемента
SortableTable.prototype.setSelector = function( elem, selector )
{
	for( var i=1; i<arguments.length; i++ )
	{
		elem.className += ' ' + arguments[i]
	}
}

// Удаление селектора у элемента
SortableTable.prototype.deleteSelector = function( elem, selector )
{
	for( var i=1; i<arguments.length; i++ )
	{
		elem.className = elem.className.replace( new RegExp(arguments[i], 'g'), '' )
	}
	
}


// Установка правильных селекторов у заголовков
SortableTable.prototype.applySelectors = function( headCell )
{
	for( var i=0; i<this.headCells.length; i++ )
	{
		if( headCell.st_Index == this.headCells[i].st_Index )
		{
			this.setSelector(this.headCells[i], this.SORTED)
	
			if( this.getSelector(this.headCells[i], this.SORTED_ASC) )
			{
				this.deleteSelector(this.headCells[i], this.SORTED_ASC)
				this.setSelector(this.headCells[i], this.SORTED_DESC)
			}
			else
			{
				this.deleteSelector(this.headCells[i], this.SORTED_DESC)
				this.setSelector(this.headCells[i], this.SORTED_ASC)
			}
		}
		else
		{
			this.deleteSelector(this.headCells[i], this.SORTED, this.SORTED_ASC, this.SORTED_DESC)
		}
	}
}