четверг, 29 ноября 2012 г.

Пагинация для Backbone.js

Всем привет! Недавно писал пагинацию для Backbone.js, вот хотел бы поделиться с вами, может кому-то пригодится.

Моя статья на хабре: http://habrahabr.ru/post/160651/.



Пускай нам надо сделать пагинацию вида:

 1 ... 3 4 5 6 7 ... 12

Для реализации понадобится вид PaginationView и шаблон pagination-view.

Вид - PaginationView

window.PaginationView = Backbone.View.extend({
	template: _.template($("#pagination-view").html()), // шаблон
	link: "", // ссылка
	page_count: null, // кол-во страниц
	page_active: null, // активная страница
	page_show: 5, // кол-во страниц в блоке видимости
	attributes: { // атрибуты элемента
		"class": "pagination"
	},
        initialize: function(params) { // конструктор
		this.link = params.link;
		this.page_count = params.page_count;
		if (this.page_count <= this.page_show) {
			this.page_show = this.page_count;
		}
		this.page_active = params.page_active;
	},
 
       render: function(eventName) { // выдача
		...
	}
});

Имеем такое описание вида. В конструкторе принимаем параметры, params - объект параметров.

Теперь рассмотрим логику выдачи. Для выдачи пагинации, а точнее блока видимых страниц, нам надо найти индекс начала и конца этих страниц. Ищем кол-во элементов до активного и после. То есть делим пополам.

var range = Math.floor(this.page_show / 2);
var nav_begin = this.page_active - range;
if (this.page_show % 2 == 0) { // Если четное кол-во
    nav_begin++;
}
var nav_end = this.page_active + range;

Дальше нам нужно узнать или надо нам выдавать "..." с каждой из сторон. Заводим две переменные, которые покажут, нужны ли:

var left_dots = true;
var right_dots = true;

И так, когда нам нужны "...", когда начало больше 2 (слева) и когда меньше конца - 1 (справа). Для этого пишем две проверки, в которых разберем еще один частный случай. Он состоит в том, что если у нас активный второй, то блок выдачи имеет на один больше элемент.

 1 2 3 4 5 6 ... 12

 И так же в конце.

 1 ... 7 8 9 10 11 12

if (nav_begin <= 2) {
	nav_end = this.page_show;
	if (nav_begin == 2) {
             nav_end++;
        } 
	nav_begin = 1;
	left_dots = false;
}
 
if (nav_end >= this.page_count - 1 ) {
	nav_begin = this.page_count - this.page_show + 1;
	if (nav_end == this.page_count - 1) {
               nav_begin--;
        }
	nav_end = this.page_count;
	right_dots = false;
}

И в конце концов отправляем шаблону:

$(this.el).html( this.template({
	link: this.link,
	page_count: this.page_count,
	page_active: this.page_active,
	nav_begin: nav_begin,
	nav_end: nav_end,
	left_dots: left_dots,
	right_dots: right_dots
}) );

Шаблон pagination-view

Шаблон написан с использованием Twitter Bootstrap. Тривиальная выдача.

<ul>
 
<% if (page_active > 1) { %>
    <li><a href="<%= link %><%= page_active-1 %>">«</a></li>
<% } %>
<% if (left_dots) {%>
    <li><a href="<%= link %>1">1</a></li>
    <li class="disabled"><a href="#">...</a></li>
<% } %>
 
<% for (var i = nav_begin; i <= nav_end; i++) { %> 
    <li <% if (page_active == i) print('class="active"') %> ><a href="<%= link %><%= i %>"><%= i %></a></li> 
<% } %>
 
<% if (right_dots) {%>
    <li class="disabled"><a href="#">...</a></li>
    <li><a href="<%= link %><%= page_count %>"><%= page_count %></a></li>
<% } %>
 
<% if (page_active < page_count) { %>
    <li><a  href="<%= link %><%= page_active+1 %>">»</a></li>
<% } %>
</ul>

Использование

Когда нам нужна пагинация на странице, создаем вид и выдаем :) Вызвать на вывод пагинацию так:

var pagination = new PaginationView({
    link: "#countries/",
    page_count: this.model.pages,
    page_active: this.model.page
});
$(this.el).find("#pagination").html(pagination.render().el);

Route: "countries/:page": "countries".

Внутри метода countries идет вызов коллекции с параметром активной страницы, что и передается серверу.

P.S. Все очень просто, берите и пользуйтесь :).
P.P.S. В последние время много пишу на Backbone.js с вашего позволения буду выкладывать похожие вещи.

0 комментариев:

Отправить комментарий