// 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 )
  {
    var st_i = 0;
    for( i=0; i<this.headCells.length; i++ )
    {
      if( this.getSelector( this.headCells[i], this.SORTABLE ) )
      {
        this.headCells[i].st_Index = st_i;
        st_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)
    {
      var childs = this.headCells[i].childNodes;
      for(var j = 0; j < childs.length; j++){
        if(childs[j].nodeName == 'DIV'){
          var div = childs[j];
        }
      }

      if( !this.getSelector(this.headCells[i], this.SORTED) )
      {
    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)
        div.innerHTML = "↓"; //
      }
      else
      {
        this.deleteSelector(this.headCells[i], this.SORTED_DESC)
        this.setSelector(this.headCells[i], this.SORTED_ASC)
        div.innerHTML = "↑"; //
      }
    }
    else
    {
      this.deleteSelector(this.headCells[i], this.SORTED, this.SORTED_ASC, this.SORTED_DESC);
      var childs = this.headCells[i].childNodes;
      for(var j = 0; j < childs.length; j++){
        if(childs[j].nodeName == 'DIV'){
          var div = childs[j];
        }
      }
      if (this.getSelector (this.headCells[i], this.SORTABLE)) {
        div.innerHTML = " ";
      }
    }
  }
}
