В последнее время мне пришлось столкнуться с проблемой постраничной навигации (pagination), и, дабы не изобретать велосипед, я сразу же решил поискать готовые решения. Как оказалось, их не так уж и много. В конце концов, я остановил свой выбор на приемлемом для меня решении, о котором и пойдет речь в этой статье. Сие решение представляет собой скрипт, использующий jQuery и способный обеспечивать быструю и простую навигацию используя AJAX. Я несколько изменил исходный скрипт, чтобы получить таблицу с одинаковым количеством строк (в исходном варианте таблица всегда имела размер в зависимости от количества получаемых данных), плюс я добавил эффекты затухания при прорисовке.

Чтобы получить представление о конечном результате этого туториала, предлагаю вам взглянуть на демо.
Создание постраничной навигации начнем собственно с таблицы, которую мы будем заполнять данными:
<table id="list" width="100%" cellspacing="0"> <caption>Таблица 1: Некоторые произвольные данные</caption> <thead> <tr> <th scope="col">Название</th> <th scope="col">Автор</th> <th scope="col">Дата</th> <th scope="col">ID</th> </tr> </thead> <tbody> <tr><td scope="row" class="spec"><span></span></td><td><span></span></td><td><span></span></td><td><span></span></td></tr> <!-- еще девять таких же строк --> </tbody> <tfoot> <tr> <td colspan="4"> <ul class="paginator"></ul> </td> </tr> </tfoot> </table>
Как видите, это самая обыкновенная пустая таблица, внутри каждой ячейки которой находится элемент <span>. Сразу же после загрузки страницы, эта таблица будет заполняться данными получаемыми из AJAX запроса. Пустой контейнер ul с классом paginator будет использоваться для хранения ссылок навигации. Эти ссылки будут обновляться после каждого обновления таблицы.
Далее подключаем скрипт пагинатора:
jQuery.fn.pageinate = function (settings) {
// Настройки по умолчанию
var settings = jQuery.extend({
row: function (container, item, i) {},
page: function (i) {},
url: "",
show: 10,
start_page:1
}, settings);
// элемент, который будет использоваться для пагинатора
settings.pagelist_selector = jQuery(settings.pagelist_selector);
return this.each(function(_, element){
// jQuery-wrap element
element = $(element);
var page_link_callback_creator = function(i) {
return function() {
$(this).html(' ');
$(this).attr('class','waiting');
update(i);
}
};
var update = function (page) {
jQuery.getJSON(settings.url, {page:page, show:settings.show}, function(data){
// Обрабатываем результаты JSON запроса
pages = data['pages'];
posts = data['posts'];
// прорисовка строк таблицы
for (var i=0; i < settings.show; i++) {
if (posts[i])
settings.row(element, posts[i], i);
else
settings.row(element, false, i);
}
settings.pagelist_selector.fadeOut(100, function(){
settings.pagelist_selector.html("");
// создание пагинатора
for (i=1; i <= pages; i++) {
selected = page==i
page_link = settings.page(i, selected);
settings.pagelist_selector.append(page_link);
if(!selected) {
page_link.click(page_link_callback_creator(i));
}
}
settings.pagelist_selector.fadeIn(100);
});
});
};
// Первоначальное получение данных
update(settings.start_page);
});
}
Код пагинатора реализован в виде jQuery плагина. В самом начале определяются настройки пагинатора - количество строк на странице (show), с какой страницы начинать просмотр (start_page), url для AJAX запросов (url). Однако основными параметрами в этих опциях являются обработчики row и page, которые нужны для прорисовки строк таблицы и пагинатора.
Плагин работает следующим образом: в самом последней строке плагина вызывается функция update(), которая выполняет AJAX запрос к серверу (адрес указан в опции url). Полученные от сервера данные в формате JSON обрабатываются и добавляются в таблицу:
// прорисовка строк таблицы
for (var i=0; i < settings.show; i++) {
if (posts[i])
settings.row(element, posts[i], i);
else
settings.row(element, false, i);
}
После этого происходит прорисовка пагинатора, используя эффекты затухания (fadeOut и fadeIn).
Теперь рассмотрим скрипт в котором мы будем использвать созданный нами плагин:
$(document).ready(function(){
$("#list tbody").pageinate({
url: "server.php",
pagelist_selector: "#list ul",
start_page: 1,
row:function(container, item, i){
$("#list tbody tr:eq("+i+") td").each(function(i){
if (!item)
$(this).html('<span> </span>');
else {
switch (i){
case 0:
$(this).html('<span>'+item['title']+'</span>');
break;
case 1:
$(this).html('<span>'+item['author']+'</span>');
break;
case 2:
$(this).html('<span>'+item['date']+'</span>');
break;
case 3:
$(this).html('<span>'+item['id']+'</span>');
break;
}
}
});
},
page:function(id, selected) {
return $('<li class="'+(selected?"selected":"")+'">'+id+'</li>');
}
});
});
Вызывается он обычным для jQuery образом, указывая все перечисленные выше опции - url, pagelist_selector и т.п.:
$("#list tbody").pageinate({});
В качестве обработчиков row() и page() указываем функции, рисующие строку и пагинатор. Как видите, функции несложные, в особенности page(), где просто создается новый элемент li с номером страницы. Если страница текущая, то для созданного элемента указывается класс selected. Обработчик row() несколько сложнее - он целиком и полностью зависит от получаемых от сервера данных. В самом начале функция получает указатели на все ячейки строки (аргумент i указывает на строку таблицы), в которую нужно поместить значение:
$("#list tbody tr:eq("+i+") td").each(function(i){})
Затем, используя функцию each() поочередно добавляем нужные нам данные в соответствующие ячейки используя конструкцию switch. Если в функцию передан пустой аргумент item (пустая ячейка), то в содержимое ячейки очищается (визуально - span там нужен, чтобы пустая ячейка имела те же размеры что и заполненая):
if (!item)
$(this).html('<span> </span>');
Конечно же, это не полнофункциональный пагинатор, как мы его привыкли видеть в обычных приложениях, но я думаю недостающие функции, как ссылки “Вперед” и “Назад”, несложно написать самостоятельно.
На сегодня это все.
До встречи!