
Всем вам должны быть хорошо известны интерфейсы просмотра лент новостей, записей блогов, в которых новые записи подгружаются по мере чтения. Новые данные подгружаются в тот момент, когда полоса прокрутки достигает самого низа. Хорошим примером такого интерфейса является Google Reader, а также сайт DZone. Сегодня я покажу, как можно сделать такой интерфейс при помощи jQuery. Приложение будет имитировать работу блога, в котором при загрузке страницы, посредством AJAX будут загружаться первые 10 записей, а остальные будут подгружаться по мере чтения.
Начнем с создания простой HTML страницы, в теле которой имеется всего лишь один div – в него будут подгружаться записи. В этот div добавим элемент <div id=”loader”>, для того, чтобы использовать его как индикатора ожидания.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<style type="text/css">
#blog {border:1px solid #aaf;background:#f9f9f9;padding:4px}
.post {border:1px solid #aaa;background:#fff;padding:4px;margin: 2px 0}
#loading {height: 40px}
</style>
</head>
<body id="hello_body">
<div id="blog">
<div id="loading" style="display:none">Loading....</div>
</div>
</body>
</html>
Здесь также подключаем скрипт jquery.js, а также стили для блога и записей.
Далее переходим к созданию скрипта, вся функциональность которого будет заключена в объект engine:
var engine = {
posts : [],
target : null,
busy : false,
count : 5
}
В переменных объекта engine хранятся различные параметры работы скрипта – количество подгружаемых за один раз записей (count), элемент, в который эти записи должны добавляться (target), состояние скрипта (busy), и массив записей (post).
Инициализация скрипта будет производиться функцией init:
init : function(posts, target){
if (!target)
return;
this.target = $(target);
this.append(posts);
var that = this;
$(window).scroll(function(){
if ($(document).height() - $(window).height() <= $(window).scrollTop() + 50) {
that.scrollPosition = $(window).scrollTop();
that.get();
}
});
}
Функция принимает два параметра - массив записей и элемент, в который записи должны быть добавлены. В конце функции добавляется обработчик события onscroll для объекта window. Его задача - определять положение полосы прокрутки, и если она находится в крайнем нижнем положении, то вызывать функцию подгрузки записей get(). Фунция get() отправляет AJAX запрос на сервер и, получая в ответ записи блога, добавляет их в элемент target:
get : function() {
if (!this.target || this.busy) return;
if (this.posts && this.posts.length) {
var lastId = this.posts[this.posts.length-1].id;
} else {
var lastId = 0;
}
this.setBusy(true);
var that = this;
$.getJSON('getposts.php', {count:this.count, last:lastId},
function(data){
if (data.length > 0) {
that.append(data);
}
that.setBusy(false);
}
);
}
Данные о всех записях, которые загружаются с сервера, хранятся в переменной engine.posts. Перед отправкой очередного запроса на сервер, функция get() получает id последнего элемента в этом списке (lastId), для того чтобы передать его в параметрах запроса. Это нужно для того, чтобы серверный скрипт знал, какие записи уже получены, и какие элементы нужно отправить.
Как в функции init(), так и в функции get(), для отображения записей используется функция append(), которая в связке с render() создает HTML код записи и добавляет его в целевой элемент (target):
append : function(posts){
posts = (posts instanceof Array) ? posts : [];
this.posts = this.posts.concat(posts);
for (var i=0, len = posts.length; i < len; i++) {
this.target.append(this.render(posts[i]));
}
if (this.scrollPosition !== undefined && this.scrollPosition !== null) {
$(window).scrollTop(this.scrollPosition);
}
},
render : function(obj){
var xhtml = '<div class="post" id=post_'+obj.id+'>';
if (obj.title) {
xhtml += '<h2>'+obj.title+'</h2>';
}
if (obj.posted_at) {
xhtml += '<div class="posted_at">Posted on: '+obj.posted_at+'</div>';
}
if (obj.comments_count) {
xhtml += '<div class="comments_count">Comments: ' + obj.comments_count + '</div>';
}
xhtml += '<div class="content">' + obj.content + '</div>';
xhtml += '</div>';
return xhtml;
}
Еще стоит упомянуть одну небольшую деталь: в обработчике события onscroll я сохраняя позицию полосы прокрутки, чтобы потом, после добавления новых записей, восстановить её. Это нужно для того, чтобы положение полосы прокрутки не изменялось, при добавлении новых записей в конец списка:
// сохраняем значение в обработчике onscroll
that.scrollPosition = $(window).scrollTop();
.......
// восстанавливаем значение в функции append
if (this.scrollPosition !== undefined && this.scrollPosition !== null) {
$(window).scrollTop(this.scrollPosition);
}
Теперь, после того, как скрипт создан, можно использовать его. Так же как и для большинства скриптов jQuery, добавляем код инициализации в фукнцию ready():
$(document).ready(function(){
engine.init(null, $("#blog"));
engine.get();
});
Вот пожалуй и все описание скрипта, как видите он совсем не сложный. Демо приложения можно посмотреть здесь: смотреть демо. Полностью скрипт доступен на github.
