S3.Blog

30 Октября 2024
A A A   RSS-лента
"Я знаю, что ничего не знаю, но многие не знают и этого". Сократ [?].

JavaScript: Сортировка столбцов в таблице без перезагрузки

Дата последнего изменения: 3 Ноября 2009
Метки статьи: Готовые решения, HTML, JavaScript

Иногда перед разработчиком стоит задача обеспечить сортировку столбцов в таблице с данными. Классическим решением является использование какого-нибудь серверного языка программирования, который бы сортировал данные по определённому столбцу и отдавал полученную страницу клиенту.
 

 

Я хочу вам предложить альтернативное решение, работающее в W3C DOM-совместимых браузерах: Internet Explorer 5+, Netscape Navigator 6+/Mozilla и Opera 7+.

Первым алгоритм сортировки предложил Пол Соуден (Paul Sowden), я же внёс в скрипт существенные коррективы: на странице может быть несколько таблиц, в которых должна происходить сортировка; возможны разные алгоритмы сортировки, что позволяет, например, корректно сортировать числа; можно задать начальный отсортированный столбец; были также добавлены некоторые украшательства (стрелочки) и т. д.

Вот, что мы получаем в итоге (нажмите на заголовок, чтобы отсортировать колонку):

ID Имя Фамилия Сайт Переключалка стилей
1 Александр Шуркаев htmlcoder.visions.ru Не-а
123 Пол Соуден idontsmoke.co.uk Угу
3 Джеффри Зельдман zeldman.com Угу
44 Аарон Будман youngpup.net Не-а
11 Глен Мерфи glenmurphy.com Не-а
15 Даниель Боган waferbaby.com Не-а
33 Ден Бенджамин hivelogic.com Угу

В других браузерах (например, Opera 6) таблица просто останется не отсортированная, в первозданном виде.

Теперь же о том, всё это дело реализуется. Буду объяснять по пунктам (изменения в плане HTML, CSS и JavaScript), чтобы легче было проследить логику.

HTML

Прежде всего, необходимо особым образом отформатировать таблицу, к которой вы собираетесь подключить возможность сортировки. Обратите внимание на код:

<table class="sort" align="center">
<thead>
<tr>
<td>ID</td>
<td>Имя</td>
<td>Фамилия</td>
<td>Сайт</td>
<td>Переключалка стилей</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Александр</td>
<td>Шуркаев</td>
<td><a href="http://htmlcoder.visions.ru/">htmlcoder.visions.ru</a></td>
<td>Не-а</td>
</tr>

<tr>
<td>33</td>
<td>Ден</td>
<td>Бенджамин</td>
<td><a href="http://hivelogic.com/">hivelogic.com</a></td>
<td>Угу</td>
</tr>
</tbody>
</table>

Как вы видите, необходимо указать теги thead (шапка таблицы) и tbody (основная часть). Обычно их мало кто использует, но здесь эти теги весьма кстати.


CSS

Задаём следующие классы в таблице стилей:

<style>
/* наша HTML таблица */
table.sort{
border-spacing:0.1em;
margin-bottom:1em;
margin-top:1em
}

/* ячейки таблицы */
table.sort td{
border:1px solid #CCCCCC;
padding:0.3em 1em
}

/* заголовки таблицы */
table.sort thead td{
cursor:pointer;
cursor:hand;
font-weight:bold;
text-align:center;
vertical-align:middle
}

/* заголовок отсортированного столбца */
table.sort thead td.curcol{
background-color:#999999;
color:#FFFFFF
}
</style>

Затем не забудьте указать у HTML таблицы класс sort (<table class="sort" align="center">).

JavaScript

Итак, мы подошли к «начинке» всего этого дела. Пропишите на странице следующий фрагмент:

<script type="text/javascript">
<!--
initial_sort_id = 0;
initial_sort_up = 0;
-->
</script> <script type="text/javascript">
<!--
/*
originally written by paul sowden <paul@idontsmoke.co.uk> | http://idontsmoke.co.uk
modified and localized by alexander shurkayev <alshur@narod.ru> | http://htmlcoder.visions.ru
*/

var sort_case_sensitive = false;

function _sort(a, b) {
	var a = a[0];
	var b = b[0];
	var _a = (a + '').replace(/,/, '.');
	var _b = (b + '').replace(/,/, '.');
	if (parseInt(_a) && parseInt(_b)) return sort_numbers(parseInt(_a), parseInt(_b));
	else if (!sort_case_sensitive) return sort_insensitive(a, b);
	else return sort_sensitive(a, b);
}

function sort_numbers(a, b) {
	return a - b;
}

function sort_insensitive(a, b) {
	var anew = a.toLowerCase();
	var bnew = b.toLowerCase();
	if (anew < bnew) return -1;
	if (anew > bnew) return 1;
	return 0;
}

function sort_sensitive(a, b) {
	if (a < b) return -1;
	if (a > b) return 1;
	return 0;
}

function getConcatenedTextContent(node) {
	var _result = "";
	if (node == null) {
		return _result;
	}
	var childrens = node.childNodes;
	var i = 0;
	while (i < childrens.length) {
		var child = childrens.item(i);
		switch (child.nodeType) {
			case 1: // ELEMENT_NODE
			case 5: // ENTITY_REFERENCE_NODE
				_result += getConcatenedTextContent(child);
				break;
			case 3: // TEXT_NODE
			case 2: // ATTRIBUTE_NODE
			case 4: // CDATA_SECTION_NODE
				_result += child.nodeValue;
				break;
			case 6: // ENTITY_NODE
			case 7: // PROCESSING_INSTRUCTION_NODE
			case 8: // COMMENT_NODE
			case 9: // DOCUMENT_NODE
			case 10: // DOCUMENT_TYPE_NODE
			case 11: // DOCUMENT_FRAGMENT_NODE
			case 12: // NOTATION_NODE
			// skip
			break;
		}
		i++;
	}
	return _result;
}

function sort(e) {
	var el = window.event ? window.event.srcElement : e.currentTarget;

	while (el.tagName.toLowerCase() != "td") el = el.parentNode;

	var a = new Array();
	var name = el.lastChild.nodeValue;
	var dad = el.parentNode;
	var table = dad.parentNode.parentNode;
	var up = table.up; // no set/getAttribute!

	var node, arrow, curcol;
	for (var i = 0; (node = dad.getElementsByTagName("td").item(i)); i++) {
		if (node.lastChild.nodeValue == name){
			curcol = i;
			if (node.className == "curcol"){
				arrow = node.firstChild;
				table.up = Number(!up);
			}else{
				node.className = "curcol";
				arrow = node.insertBefore(document.createElement("span"),node.firstChild);
				table.up = 0;
			}
			arrow.innerHTML = (table.up) ? '&#9650;&nbsp;' : '&#9660;&nbsp;';
		}else{
			if (node.className == "curcol"){
				node.className = "";
				if (node.firstChild) node.removeChild(node.firstChild);
			}
		}
	}

	var tbody = table.getElementsByTagName("tbody").item(0);
	for (var i = 0; (node = tbody.getElementsByTagName("tr").item(i)); i++) {
		a[i] = new Array();
		a[i][0] = getConcatenedTextContent(node.getElementsByTagName("td").item(curcol));
		a[i][1] = getConcatenedTextContent(node.getElementsByTagName("td").item(1));
		a[i][2] = getConcatenedTextContent(node.getElementsByTagName("td").item(0));
		a[i][3] = node;
	}

	a.sort(_sort);

	if (table.up) a.reverse();

	for (var i = 0; i < a.length; i++) {
		tbody.appendChild(a[i][3]);
	}
}

function init(e) {
	if (!document.getElementsByTagName) return;

	if (document.createEvent) function click_elem(elem){
		var evt = document.createEvent("MouseEvents");
		evt.initMouseEvent("click", false, false, window, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, elem);
		elem.dispatchEvent(evt);
	}

	for (var j = 0; (thead = document.getElementsByTagName("thead").item(j)); j++) {
		var node;
		for (var i = 0; (node = thead.getElementsByTagName("td").item(i)); i++) {
			if (node.addEventListener) node.addEventListener("click", sort, false);
			else if (node.attachEvent) node.attachEvent("onclick", sort);
			node.title = "Нажмите на заголовок, чтобы отсортировать колонку";
		}
		thead.parentNode.up = 0;

		if (typeof(initial_sort_id) != "undefined"){
			td_for_event = thead.getElementsByTagName("td").item(initial_sort_id);
			if (td_for_event.dispatchEvent) click_elem(td_for_event);
			else if (td_for_event.fireEvent) td_for_event.fireEvent("onclick");
			if (typeof(initial_sort_up) != "undefined" && initial_sort_up){
				if (td_for_event.dispatchEvent) click_elem(td_for_event);
				else if (td_for_event.fireEvent) td_for_event.fireEvent("onclick");
			}
		}
	}
}

var root = window.addEventListener || window.attachEvent ? window : document.addEventListener ? document : null;
if (root){
	if (root.addEventListener) root.addEventListener("load", init, false);
	else if (root.attachEvent) root.attachEvent("onload", init);
}
//-->

</script>

Я решил не разбирать детально сам скрипт. Кому интересно, как всё работает, думаю, сам сможет понять.

Засим откланиваюсь. До встречи!

P. S. Добавлена возможность указания начального отсортированного столбца. Для этого нужно определить переменные initial_sort_id (номер столбца, начиная с нуля) и initial_sort_up (0 или 1, сортировка вниз или вверх). Для таблицы в данной статье значения следующие:

<script type="text/javascript">
<!--
initial_sort_id = 0;
initial_sort_up = 1;
-->
</script>

Взято отсюда: Сортировка столбцов в таблице без перезагрузки



Похожие материалы:




Cmit (гость) • ответить
Добрый день. Каким образом сделать сортировку только по одному столбцу?
К примеру нужно сортировать только по ID, а не по имении/фамилии/ и т.д.
Александрответить
Подправьте функцию function init(e) что бы события на клик мыши вешались только на нужный столбец (столбец с ID)

 
 
  Имя *:   Решите пример *: =
 
Полужирный Курсив Подчеркнутый Перечеркнутый
 
Вставить изображение Сделать цитатой Вставить ссылку Вставить код

Вставить смайл
 
 

 



© S3.Blog: Если критикуешь, не предлагая решения проблемы, то ты становишься частью этой проблемы.