var currentTableSorting = null;

function tableSorting()
{
  this.tDragObject = null;
  this.tMouseOffset = null;
  this.tTable = null;
  this.tOldY = 0;
  this.tInit = function(_table)
  {
    var tTable = _table
    this.tTable = tTable;
    var tRows = tTable.tBodies[0].rows;
    for (var ti = 0; ti < tRows.length; ti ++)
    {
      var tNodrag = tRows[ti].getAttribute('noDrag')
      if (tNodrag == null || tNodrag == 'undefined') this.tMakeDraggable(tRows[ti]);
    };
  };
  this.tOnDrop = function(_table, _droppedRow) {};
  this.tGetPosition = function(_e)
  {
    var te = _e;
    var tTop = 0;
    var tLeft = 0;
    if (te.offsetHeight == 0) te = te.firstChild;
    while (te.offsetParent)
    {
      tTop += te.offsetTop;
      tLeft += te.offsetLeft;
      te = te.offsetParent;
    };
    tTop += te.offsetTop;
    tLeft += te.offsetLeft;
    return {x: tLeft, y: tTop};
  };
  this.tMouseCoords = function(_event)
  {
    var tXy = null;
    var tevent = _event;
    if(tevent.pageX || tevent.pageY) tXy = {x: tevent.pageX, y: tevent.pageY};
    else tXy =  {x: tevent.clientX + document.body.scrollLeft - document.body.clientLeft, y: tevent.clientY + document.body.scrollTop  - document.body.clientTop};
    return tXy;
  };
  this.tGetMouseOffset = function(_target, _event)
  {
    var tevent = _event;
    var ttarget = _target;
    tevent = tevent || window.event;
    var tDocPos = this.tGetPosition(ttarget);
    var tMousePos = this.tMouseCoords(tevent);
    return {x: tMousePos.x - tDocPos.x, y: tMousePos.y - tDocPos.y};
  };
  this.tMakeDraggable = function(_item)
  {
    var tbool = false;
    var titem = _item;
    if (titem)
    {
      var tSelf = this;
      titem.onmousedown = function(_event)
      {
        var tevent = _event;
        var ttarget = window.event? window.event.srcElement: tevent.target;
        if (ttarget.tagName == 'INPUT' || ttarget.tagName == 'SELECT') tbool = true;
        else
        {
          currentTableSorting = tSelf;
          tSelf.tDragObject  = this;
          tSelf.tMouseOffset = tSelf.tGetMouseOffset(this, tevent);
        };
      };
      titem.style.cursor = 'move';
    };
  };
  this.tFindDropTargetRow = function(_y)
  {
    var tY = _y;
    var tReturnRow = null;
    var tRows = this.tTable.tBodies[0].rows;
    for (var ti = 0; ti < tRows.length; ti ++)
    {
      var tRow = tRows[ti];
      var tNodrop = tRow.getAttribute('noDrop');
      if (tNodrop == null || tNodrop == 'undefined')
      {
        var tRowY = this.tGetPosition(tRow).y;
        var tRowHeight = parseInt(tRow.offsetHeight) / 2;
        if (tRow.offsetHeight == 0)
        {
          tRowY = this.tGetPosition(tRow.firstChild).y;
          tRowHeight = parseInt(tRow.firstChild.offsetHeight) / 2;
        };
        if ((tY > tRowY - tRowHeight) && (tY < (tRowY + tRowHeight))) tReturnRow = tRow;
      };
    };
    return tReturnRow;
  };
};

function tableSortingMouseMove(_event)
{
  var tevent = _event;
  if (currentTableSorting && currentTableSorting.tDragObject)
  {
    tevent = tevent || window.event;
    currentTableSorting.tTable.className = currentTableSorting.tTable.getAttribute('primalclass') + ' noselect';
    currentTableSorting.tTable.onselectstart = function() { return false; };
    var tMousePos = currentTableSorting.tMouseCoords(tevent);
    var tCurrentY = tMousePos.y - currentTableSorting.tMouseOffset.y;
    if (tCurrentY != currentTableSorting.tOldY)
    {
      var tMovingDown = tCurrentY > currentTableSorting.tOldY;
      currentTableSorting.tOldY = tCurrentY;
      currentTableSorting.tDragObject.style.backgroundColor = '#eeeeee';
      var tDragObjectTds = currentTableSorting.tDragObject.getElementsByTagName('td');
      for (var ti = 0; ti < tDragObjectTds.length; ti ++) tDragObjectTds[ti].style.backgroundColor = '#eeeeee';
      var tCurrentRow = currentTableSorting.tFindDropTargetRow(tCurrentY);
      if (tCurrentRow)
      {
        if (tMovingDown && currentTableSorting.tDragObject != tCurrentRow) currentTableSorting.tDragObject.parentNode.insertBefore(currentTableSorting.tDragObject, tCurrentRow.nextSibling);
        else if (!tMovingDown && currentTableSorting.tDragObject != tCurrentRow) currentTableSorting.tDragObject.parentNode.insertBefore(currentTableSorting.tDragObject, tCurrentRow);
      };
    };
    return false;
  };
};

function tableSortingMouseUp(_event)
{
  var tevent = _event;
  if (currentTableSorting && currentTableSorting.tDragObject)
  {
    currentTableSorting.tTable.className = currentTableSorting.tTable.getAttribute('primalclass');
    currentTableSorting.tTable.onselectstart = function() { return true; };
    var tDroppedRow = currentTableSorting.tDragObject;
    tDroppedRow.style.backgroundColor = '';
    var tDroppedRowTds = tDroppedRow.getElementsByTagName('td');
    for (var ti = 0; ti < tDroppedRowTds.length; ti ++) tDroppedRowTds[ti].style.backgroundColor = '';
    currentTableSorting.tDragObject = null;
    currentTableSorting.tOnDrop(currentTableSorting.tTable, tDroppedRow);
    currentTableSorting = null;
  };
};

attachElementEvent(document, 'mouseup', tableSortingMouseUp);
attachElementEvent(document, 'mousemove', tableSortingMouseMove);