﻿    function fastSortInit() {
        var img = new Image();
        var img2 = new Image();
  //      img.src = '/images/up.gif';
  //      img2.src = '/images/down.gif';
        var fastSort = new fastSortEngine("tableToSort");
    }

function fastSortEngine(id) {
    // получаем объект таблицы
    var tableObj = document.getElementById(id);
	if (tableObj) {
		this.months = { '01': 0, '02': 1,  '03': 2,
						'04': 3, '05': 4,  '06': 5,
						'07': 6, '08': 7,  '09': 8,
						'10': 9, '11': 10, '12': 11};
		this.nullValue = -1000000; // нужно, чтобы помещать пустые значения в самый верх
		var theader = tableObj.rows[0];
		// тело таблицы
		this.tBody = theader.parentNode;
		// число строк
		this.rowsLen = this.tBody.childNodes.length;
		var t = this;
		var colLen = theader.childNodes.length;
		// индексируем столбцы, чтобы позже легко их индектифицировать
		for(var i=0; i<colLen; i++) {
			this.getUniqueID(theader.childNodes[i], i);
		}
		// индексируем строки, чтобы учитывать их при сортировке
		for(var i=0; i<this.rowsLen; i++) {
			this.getUniqueID(this.tBody.childNodes[i], i);
		}
		// вызов обработчика клика по заголовку таблицы
		theader.onclick = function(e) {
			e = e ? e : event; // для FF
			var target = e.target ? e.target : e.srcElement;
			return t.handleRowClick(target);
		}
	}
}

// обработчик клика
fastSortEngine.prototype.handleRowClick = function (target) {
    if(this.sortStarted) return false; // не запускать сортировку, пока предыдущая не закончена
    this.sortStarted = true;

    if(target.tagName == "TD") {
        this.target = target;
        // меняем статус (направление сортировки)
        var cstatus = (!this.target.selected || this.target.selected == 2) ? 1 : 2;
        this.colType = this.target.getAttribute("type"); // тип колонки берем из атрибута
        this.colID = this.target.runiqueID; // идентификатор (порядковый номер) колонки
         // меняем css class для предыдущего выбора
        if(this.prevTarget && this.target != this.prevTarget) {
            this.markRow(this.prevTarget, 0);
        }
        // сама сортировка
        this.processSort(cstatus);
        this.prevTarget = this.target;
        this.markRow(this.target, cstatus);
    }
    this.sortStarted = false;
    return true;
}
// функция для смены css класса
fastSortEngine.prototype.markRow = function (obj, status) {
    obj.selected = status;
    if(status == 1) {
        obj.className = "theaderup";
    } else if(status == 2) {
        obj.className = "theaderdown";
    } else {
        obj.className = "theader";
    }
}
fastSortEngine.prototype.processSort = function (status) {
    if(this.rowsLen > 1) {
        // массив, в который будем записывать значения ячеек
        var dataCol = new Array();
        var val = false;
        // для всех строк таблицы
        for(var i = 1; i<this.rowsLen; i++) {
            var rowObj = this.tBody.childNodes[i];
            if(!rowObj.tagName) continue; // пропускаем текстовые ноды (FF)
            var colObj = rowObj.childNodes[this.colID];
            val = colObj.innerText ? colObj.innerText : colObj.textContent; // текст ячейки (FF)
            // приводим все значения к нужному типу
            switch(this.colType) {
                case "time": // парсим время
                    val = this.parseTime(val);
                    break;
                case "date": // парсим дату
                    val = this.parseDate(val);
                    break;
            }
            // поменяем в объект значение, идектификатор строки и ноду строки, чтобы потом восстановить строку в таблицу
            var obj = [val,
                       rowObj.runiqueID,
                       rowObj];
            dataCol.push(obj);
        }
        // для текстового содержимого вызываем обычную функцию сортировки, для других типов с обработчиком
        if(this.colType == "text") dataCol.sort();
        else dataCol.sort(this.sortNumber);
        // если нужна обратная сортировка
        if( status == 2 ) {
            dataCol.reverse();
        }
        // восстанавливаем строки в таблицу в нужном (отсортированном) порядке
        var l = dataCol.length;
        for(var i = 0; i<l; i++) {
            this.tBody.appendChild(dataCol[i][2]);
        }
    }
}
// индекс объекта
fastSortEngine.prototype.getUniqueID = function(robj, pos) {
    if(!robj.runiqueID) {
        robj.runiqueID = pos;
    }
    return robj.runiqueID;
}
// функция для разбора строки, содержащей время
fastSortEngine.prototype.parseTime = function(tvalue) {
    var ret = tvalue;
    if(!tvalue) {
        ret = this.nullValue;
    } else {
        tvalue = tvalue.split(':');
        if(tvalue.length == 2) {
            ret = parseInt(tvalue[0],10)*60 + parseInt(tvalue[1],10);
        } else {
            ret = this.nullValue;
        }
    }
    return ret;
}
// функция для разбора строки, содержащей дату
fastSortEngine.prototype.parseDate = function(dvalue) {
    var ret = dvalue;
    if(!dvalue) {
        ret = this.nullValue;
    } else {
        dvalue = dvalue.split('.');
        if(dvalue.length == 3) {
            // создаем объект даты и получаем таймстамп
            var d = new Date(dvalue[2], this.months[dvalue[1].toLowerCase()], dvalue[0]);
            ret = d.getTime();
        } else {
            ret = this.nullValue;
        }

    }
    return ret;
}
// обработчик для сортировки по числовым значениям
fastSortEngine.prototype.sortNumber = function(a,b) {
    var a1 = a[0] == '' ? this.nullValue : parseFloat(a[0]);
    var b1 = b[0] == '' ? this.nullValue : parseFloat(b[0]);
    // сравниваем два значения и если они равны, то сортируем по индексу (ID)
    if     (a1 == b1 && a[1] < b[1] ) return -0.0000000001;
    else if(a1 == b1 && a[1] > b[1] ) return  0.0000000001;
    // вычисляем вес
    return a1 - b1;
}
