Рубрики
FrontEnd

Сортировка jQuery — таблицы и блоки

Для решения задачи сортировки уже давно применяют JavaScript, вместо того, чтобы заново генерировать код перезагружая страницу.

Задача состоит в том, чтобы сортировать блоки в алфавитном порядке, либо по числам, в обоих направлениях — по убыванию и возрастанию. При этом необходимо, чтобы код корректно работал во всех браузерах, включая Internet Explorer и Safari. Предполагается, что будет использоваться не чистый JavaScript, а именно сортировка jQuery.

HTML — скелет таблицы

Для реализации примера взяты элементы таблицы Менделеева, где есть буквенное обозначение элемента и его порядковый номер.

Сортируемая таблица строится с помощью блочной верстки.

<div class="order">
    <div class="header row">
        <div class="col-md-6" data-orderby="element">Element</div>
        <div class="col-md-6" data-orderby="number">Number</div>
    </div>
    <div class="list">
        <div class="row">
            <div class="col-md-6"><span data-name="element">Be</span></div>
            <div class="col-md-6"><span data-name="number">4</span></div>
        </div>
        <div class="row">
            <div class="col-md-6"><span data-name="element">Ag</span></div>
            <div class="col-md-6"><span data-name="number">47</span></div>
        </div>
        <div class="row">
            <div class="col-md-6"><span data-name="element">C</span></div>
            <div class="col-md-6"><span data-name="number">6</span></div>
        </div>
    </div>
</div>

Элемент с классом header будет являться заголовком таблицы, в которой будут располагаться элементы управления сортировкой. Элементы управления определяются наличием атрибута data-orderby. В данном случае в качестве элемента управления указан блок всей ячейки, для того, чтобы сортировка происходила при щелчке на всем блоке, а не только на слове.

Далее идет блок с классом list, что дает возможность определить контейнер, в котором будут сортироваться блоки. Блоки, которые будут в последствии сортироваться имеют класс row.

Текст, по которому будет определяться порядок сортировки определяется наличием атрибута data-name, и значение этого атрибута должно совпадать со значением управляющего элемента. То есть при щелчке на элементе [data-orderby=element] должна производиться сортировка по элементам [data-name=element].

CSS — определение внешнего вида таблицы и элементов сортировки

Чтобы визуально таблица выглядела хорошо, перед тем, как будет осуществлена сортировка jQuery, следует написать следующий CSS код, при условии, что не используется Bootstrap:

.row {
    width: 100%;
}
.row:begin, .row:after {
    content: " ";
    display: block;
    clear: both;
    width: 100%;
}
.row > div {
    float: left;
    border-bottom: 1px solid #ccc;
}
.col-md-6 {
    width: 50%;
}

Следующие свойства определяют внешний вид стрелочек, указывающих на то, что пользователь может осуществлять сортировку по данному столбцу:

.header > div {
    position: relative;
    background: #eee;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.header > div:after {
    position: absolute;
    content: "";
    display: inline-block;
    border: 5px solid transparent;
    border-top-color: #000;
    width: 0;
    height: 0;
    top: 100%;
    right: 25px;
    margin-top: -10px;
}
.header > div.up:after {
    border-top-color: transparent;
    border-bottom-color: #000;
    margin-top: -15px;
}

JavaScript — функционал, сортировка jQuery

Для корректной работы в IE необходимо правильно создать массив, так как довольно часто при создании массива другим способом данный массив не работает в IE. Поэтому мы применяем способ new Array().

Необходимо создать глобальную переменную orderdirection, которая будет являться массивом и будет хранить текущее направление сортировки для каждого столбца.

var orderdirection = new Array();

Для вызова функции сортировки jQuery необходимо создать обработчик события, например щелчка мыши по управляющему элементу. В обработчике следует вызвать функцию, которая будет иметь входные данные: ключ сортировки, контейнер блоков, блок, флаг, указывающий на то, что данные следует сортировать как числа.

$('[data-orderby]').on('click', function () {
	var orderby = $(this).data( 'orderby' ); // создана локальная переменная, содержащая имя признака сортировки
	switch ( orderby ) // условие, определяющее - нужно ли считать данные сортировки числом
	{
	  case 'number': flag = 1; break; // данные с признаком number надо сортировать как числа
	  default: flag = 0; // по умолчанию сортировка будет по алфавиту
	}
    oi_div_order( orderby, '.list', '.row', flag );
});

Если сортировать числа в алфавитном порядке, то последовательность числе 6,47,4 будет отсортирована как 4, 47, 6, а не как 4, 6, 47.

Чтобы указать на то, что данные следует сортировать как числа, нужно эти данные сделать не строковыми, а числовыми. Для этого используется функция parseFloat, которая преобразует строку в число с плавающей точкой, так как вероятно, что сортировке будут подвергаться не только целые числа.

function is_num( text, flag )
{
    if( flag == 0 )
    {
        return text;
    }else
    {
        return parseFloat( text );
    }
}

Теперь для осуществления сортировки необходимо написать функцию самой сортировки. Для обеспечения корректной работы в браузере Safari необходимо правильно написать условие перестановки, с указанием возвращаемого числа: 1, -1, 0.

function oi_div_order( selector, container, block, flag )
{
    block = container + ' ' + block; // формирование селектора блока, содержащего селектор контейнера
    // создается локальная переменная, хранящая нумерованный список объектов - блоков, осуществляется сортировка
    var ordered_dives = $( block ).sort(function (a, b)
	{
        a = $(a).find( '[data-name=' + selector + ']' ).text(); // текст из 1-го элемента, по которому сортируем
        b = $(b).find( '[data-name=' + selector + ']' ).text(); // текст из 1-го элемента, по которому сортируем
		// если направление сортировки не определено или равно 0, производится соответствующая перестановка элементов
		if( orderdirection[ selector ] == undefined || orderdirection[ selector ] == 0 )
		{
			return ( is_num( a, flag ) > is_num( b, flag ) ) ? 1 : ( is_num( a, flag ) < is_num( b, flag ) ) ? -1 : 0;
		}else{
			return ( is_num( a, flag ) < is_num( b, flag ) ) ? 1 : ( is_num( a, flag ) > is_num( b, flag ) ) ? -1 : 0;
		}
    });
	// выводится массив отсортированных элементов в контейнер
    $( container ).html( ordered_dives );
	// если направление сортировки не определено или равно 0
	if( orderdirection[ selector ] == undefined || orderdirection[ selector ] == 0 )
	{
		orderdirection[ selector ] = 1; // указывается текущее направление сортировки
		$( '[data-orderby=' + selector + ']' ).addClass( 'up' ); // добавляется название класса
	}else{
		orderdirection[ selector ] = 0; // указывается текущее направление сортировки
		$( '[data-orderby=' + selector + ']' ).removeClass( 'up' ); // удаляется название класса
	}
}