Яндекс.Метрика

    Песочница

    Javascript. Сортировка таблицы

    Доброго времени суток, Хабровчане.

    Может для большинства здешних обитателей моя статья покажется слишком скучной и «и так понятно», но думаю новичкам будет в чем-то полезной.
    Стояла передо мной как-то задача сделать сортировку таблицы по разным колонкам. Данный брались из базы, каждый раз их вытаскивать — накладно, решил задействовать JavaScript.
    Были небольшие трудности из-за использования различной стилистики строк в таблице, а именно был разный цвет фона, в зависимости от данных самой таблицы.
    Стилистику нарушать было нельзя. Кого заинтересовало, прошу под кат.

    Подсветка фона выбрана так:
    1) если время < 2012 год — подсветка красным
    2) если расстояние > 9000 — подсветка желтым.
    *) остальное чередование белого с серым.

    Данные талицы берутся из БД, рисуется php, последняя колонка скрыта, это время в UNIX-формате, по ней сортировать колонку «Время» проще.

    Подключаем такой класс:

    var TableSort = function (idTbl, defSortCol, firstRow, classes) {
    	// номер колонки, по которой выполнена текущая сортировка, считаем с 0
    	var curSortCol = defSortCol;
    	// номер колонки, у которой отрисовать картинку, показывающая направление сортировки, считаем с 0
    	var curImgCol = defSortCol;
    	// направление сортировки вверх
    	var curSortUp = true;
    	// id таблицы, в которой производим сортировку
    	var curIdTbl = idTbl;
    
    	// номер строки, с которой идут данные, считаем с 0
    	var numColTr = (firstRow == null) ? 1 : firstRow;
    
    	// нужно ли учитывать классы для строк
    	if (classes == null) {	
    		var style = false;
    	} else {
    		var style = true;
    		// список классов, которые нужно сохранить
    		var needClasses = classes[0];	
    		// список классов, которые чередуются
    		var listClasses = classes[1];
    	}
    
        var tbl = document.getElementById(curIdTbl);
        var allImgs = new Array(); // all imgs-arrow
    	allThs = tbl.getElementsByTagName('tr').item(0).getElementsByTagName('th');
    	for (i=0; i<allThs.length; i++){
    		if (allThs.item(i).getElementsByTagName('img') != null) {
    			allImgs[i] = allThs.item(i).getElementsByTagName('img').item(0);
    		} else {
    			allImgs[i] = null;
    		}
    	}
    
    	var tblData = new Array(); // current data in table
    
    	// начинаем сортировку по колонке newCol, картинку рисуем у колонки imgCol
    	this.initSort = function (newCol, imgCol) {
    		if (newCol == curSortCol) {
    			// кликнули на отсортированную колонку, меняем сортировку на обратную
    			curSortUp = !curSortUp;
    		} else {
    			// сортируем по новой колонке
    			curSortCol = newCol;
    			curImgCol = (imgCol == null) ? newCol : imgCol;
    			curSortUp = true;
    		}
    		showArrow();
    		getDataTable();
    		showSortTable();
    		if (style) {
    			doStyle();
    		}
    		
    	};
    
    	// show/change arrow
    	function showArrow(){
    		for (i=0; i<allImgs.length; i++){
    			if (allImgs[i] != null) {
    				if (i == curImgCol) {
    					allImgs[i].style.visibility = "visible";
    					if (curSortUp) {
    						allImgs[i].src = "./img/up.png";
    					} else {
    						allImgs[i].src = "./img/down.png";
    					}
    				} else {
    					allImgs[i].style.visibility = "hidden";
    				}
    			}
    		}
    	}
    
    	// get new data from table
    	function getDataTable() {
    		allTrs = tbl.getElementsByTagName('tr');
    		for (i=numColTr; i<allTrs.length; i++){
    			tblData[i-numColTr] = new Array();
    			for (j=0; j<allTrs[i].getElementsByTagName('td').length; j++) {
    				tblData[i-numColTr][j] = allTrs[i].getElementsByTagName('td').item(j).innerHTML;
    			}
    			if (style) {
    				tblData[i-numColTr][allTrs[i].getElementsByTagName('td').length]=allTrs[i].className;
    			}
    		}
    		tblData.sort(_sort);
    		if (!curSortUp) {
    			tblData.reverse();
    		}
    	}
    
    	// rules for sorting
    	function _sort(a1, b1) {
    		var a = a1[curSortCol];
    		var b = b1[curSortCol];
    		if (parseFloat(a) && parseFloat(b)) {
    			return parseFloat(a) - parseFloat(b);
    		} else {
    			if (a.toLowerCase() < b.toLowerCase()) {
    				return -1;
    			} else if (a.toLowerCase() > b.toLowerCase()) {
    				return 1;
    			} else {
    				return 0;
    			}
    		}
    	}
    
    	function showSortTable() {
    		allTrs = tbl.getElementsByTagName('tr');
    		for (i=numColTr; i<allTrs.length; i++){
    			for (j=0; j<allTrs[i].getElementsByTagName('td').length; j++) {
    				allTrs[i].getElementsByTagName('td').item(j).innerHTML = tblData[i-numColTr][j];
    			}
    			if (style) {
    				allTrs[i].className=tblData[i-numColTr][allTrs[i].getElementsByTagName('td').length];
    			}
    		}
    	}
    	function doStyle(){
    		allTrs = tbl.getElementsByTagName('tr');
    		for (i=numColTr; i<allTrs.length; i++){
    			if (allTrs[i] == null) {
    				continue;
    			}
    			if(needClasses.indexOf(allTrs[i].className) != -1) {
    				continue;
    			}
    			allTrs[i].className = listClasses[(i % listClasses.length)];
    		}
    	}
    
    }
    

    Создаем объект так:
    var infoTblSort = new TableSort("idTbl", 0, 1, [['add', 'edd'],['odd', '']] );
    

    Для работы в заголовке нужной колонки дописываем что-то похожее на:
    onclick="infoTblSort.initSort(4,3);"
    

    В этом примере передается 2 параметра, первый — по которому будет идти сортировка (в данном случае — это скрытая колонка UNIX-время), вторая — колонка, у которой будет стоять картинка, указывающая направление текста.

    Пример тут.

    На этом все, надеюсь мой опыт будет кому-то полезен. Прошу пощения за несколько сумбурный рассказ, впервые пишу статью.
    Спасибо за внимание.