—»     —»   Создаем скрипт в стиле Pinterest – Часть 6
  Раздел: Скрипты и коды   Комментариев: 1  

Создаем скрипт в стиле Pinterest – Часть 6



Некоторые наши читатели попросили внедрить в наш скрипт в стиле Pinterest бесконечный скроллинг, поэтому мы решили заняться этим прямо сегодня. Мы провели некоторое исследование, и пришли к http://www.infinite-scroll.com/. Нам кажется, что данная библиотека идеально подходит для реализации нашей задачи. Она позволяет нам создавать бесконечные страницы. Это значит, что мы можем изначально сгенерировать некоторое количество изображений, а когда нам понадобится больше изображений, мы просто прокручиваем страницу вниз, и они подгружаются при помощи ajax. Если вы готовы начать, давайте приступим!

Предыдущие части данной серии:

* Создаем скрипт в стиле Pinterest – Часть 1
* Создаем скрипт в стиле Pinterest – Часть 2
* Создаем скрипт в стиле Pinterest – Часть 3
* Создаем скрипт в стиле Pinterest – Часть 4
* Создаем скрипт в стиле Pinterest – Часть 5

Создаем скрипт в стиле Pinterest – Часть 6

Мы предлагаем вам опробовать обновленный демо-файл, а также скачать обновленные исходники нашего скрипта.

Посмотреть демо | Скачать архивом
Внимание! У вас нет прав для просмотра скрытого текста.


Этап 1 – HTML

Самое первое, что вам нужно сделать, это скачать плагин jquery.infinitescroll.min.js, и поместите его в вашу директорию js. Теперь мы можем указать ссылку эту новую библиотеку в головной секции нашего файла templates/index.html. Теперь полный список привязанных библиотек выглядит следующим образом:

templates/index.html

<!-- add scripts -->
<script src="js/jquery.min.js"></script>
<script src="js/jquery.colorbox-min.js"></script>
<script src="js/jquery.masonry.min.js"></script>
<script src="js/jquery.infinitescroll.min.js"></script>
<script src="js/script.js"></script>

Еще одно незначительное изменение в данном файле заключается в новом ключе шаблона (в конце основного контейнера) – {infinite}

<!-- main container -->
<div class="main_container">
{images_set}
</div>
{infinite}

Примерно те же действия нам нужно повторить в файле templates/profile.html (в наших планах добавить бесконечную прокрутку как для страниц профиля, так и в основную страницу).

Этап 2 – PHP

Итак, в предыдущем этапе мы подготовили наши файлы шаблона. Теперь нам нужно изменить наш ключ {infinite} на конкретное значение. Первым будем файл главной страницы. Пожалуйста, замените наш предыдущий набор ключей шаблона.

index.php

// draw common page
$aKeys = array(
'{menu_elements}' => $sLoginMenu,
'{extra_data}' => $sExtra,
'{images_set}' => $sPhotos
);

На следующий код:

// infinite scroll
$sPerpage = 20;

if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
if($sPhotos) {
$sPage = (int)$_GET['page'] + 1;
echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
<a href="index.php?page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
}
exit;
}

$sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
<a href="index.php?page=2&per_page={$sPerpage}"></a>
</nav>
EOF;

// draw common page
$aKeys = array(
'{menu_elements}' => $sLoginMenu,
'{extra_data}' => $sExtra,
'{images_set}' => $sPhotos,
'{infinite}' => $sInfinite
);

Главная идея заключается в том, чтобы получать свежие данные каждый раз, когда к странице делается запрос (конечно же, это зависит от следующих параметров GET: page и per_page. Примерно такие же изменения мы подготовили для нашей страницы профиля. Взгляните на свежую версию:

profile.php

require_once('classes/CMySQL.php');
require_once('classes/CMembers.php');
require_once('classes/CPhotos.php');

// get login data
list ($sLoginMenu, $sExtra) = $GLOBALS['CMembers']->getLoginData();

// profile id
$i = (int)$_GET['id'];
if ($i) {
$aMemberInfo = $GLOBALS['CMembers']->getProfileInfo($i);
if ($aMemberInfo) {

// get all photos by profile
$sPhotos = $GLOBALS['CPhotos']->getAllPhotos($i);

// infinite scroll
$sPerpage = 20;

if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
if($sPhotos) {
$sPage = (int)$_GET['page'] + 1;
echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
<a href="profile.php?id={$i}&page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
}
exit;
}

$sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
<a href="profile.php?id={$i}&page=2&per_page={$sPerpage}"></a>
</nav>
EOF;

// draw profile page
$aKeys = array(
'{menu_elements}' => $sLoginMenu,
'{extra_data}' => $sExtra,
'{images_set}' => $sPhotos,
'{profile_name}' => $aMemberInfo['first_name'],
'{infinite}' => $sInfinite
);
echo strtr(file_get_contents('templates/profile.html'), $aKeys);
exit;
}
}

header('Location: error.php');

Обратите внимание, что по умолчанию мы отображаем 20 изображений на страницу. Наши финальные изменения были внесены в класс photos (CPhotos.php). Как вы, наверное, помните, нам нужно поработать с двумя новыми GET-параметрами для пагинации: page и per_page. Мы добавили обработку данных для обоих параметров в функцию getAllPhotos:

classes/CPhotos.php

    function getAllPhotos($iPid = 0, $sKeyPar = '') {

// prepare WHERE filter
$aWhere = array();
if ($iPid) {
$aWhere[] = "`owner` = '{$iPid}'";
}
if ($sKeyPar != '') {
$sKeyword = $GLOBALS['MySQL']->escape($sKeyPar);
$aWhere[] = "`title` LIKE '%{$sKeyword}%'";
}
$sFilter = (count($aWhere)) ? 'WHERE ' . implode(' AND ', $aWhere) : '';

// pagination
$iPage = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$iPerPage = (isset($_GET['per_page'])) ? (int)$_GET['per_page'] : 20;
$iPage = ($iPage < 1) ? 1 : $iPage;
$iFrom = ($iPage - 1) * $iPerPage;
$iFrom = ($iFrom < 1) ? 0 : $iFrom;
$sLimit = "LIMIT {$iFrom}, {$iPerPage}";

$sSQL = "
SELECT *
FROM `pd_photos`
{$sFilter}
ORDER BY `when` DESC
{$sLimit}
";

$aPhotos = $GLOBALS['MySQL']->getAll($sSQL);

$sImages = '';
$sFolder = 'photos/';
foreach ($aPhotos as $i => $aPhoto) {

$iPhotoId = (int)$aPhoto['id'];
$sFile = $aPhoto['filename'];
$sTitle = $aPhoto['title'];
$iCmts = (int)$aPhoto['comments_count'];

$iLoggId = (int)$_SESSION['member_id'];
$iOwner = (int)$aPhoto['owner'];
$iRepins = (int)$aPhoto['repin_count'];
$iLikes = (int)$aPhoto['like_count'];
$sActions = ($iLoggId && $iOwner != $iLoggId) ? '<a href="#" class="button repinbutton">Repin</a><a href="#" class="button likebutton">Like</a>' : '';

// display a blank image for not existing photos
$sFile = (file_exists($sFolder . $sFile)) ? $sFile : 'blank_photo.jpg';

$aPathInfo = pathinfo($sFolder . $sFile);
$sExt = strtolower($aPathInfo['extension']);

$sImages .= <<<EOL
<!-- pin element {$iPhotoId} -->
<div class="pin" pin_id="{$iPhotoId}">
<div class="holder">
<div class="actions">
{$sActions}
<a href="#" class="button comment_tr">Comment</a>
</div>
<a class="image ajax" href="service.php?id={$iPhotoId}" title="{$sTitle}">
<img alt="{$sTitle}" src="{$sFolder}{$sFile}">
</a>
</div>
<p class="desc">{$sTitle}</p>
<p class="info">
<span class="LikesCount"><strong>{$iLikes}</strong> likes</span>
<span>{$iRepins} repins</span>
<span>{$iCmts} comments</span>
</p>
<form class="comment" method="post" action="" style="display: none" onsubmit="return submitComment(this, {$iPhotoId})">
<textarea placeholder="Add a comment..." maxlength="255" name="comment"></textarea>
<input type="submit" class="button" value="Comment" />
</form>
</div>
EOL;
}
return $sImages;
}

Как видно, оба параметра влияют только на ограничения SQL.

Этап 3 – javascript

Финальные изменения мы внести в файл javascript. Здесь всего два новых оператора событий:

js/script.js

function fileSelectHandler() {
// get selected file
var oFile = $('#image_file')[0].files[0];

// html5 file upload
var formData = new FormData($('#upload_form')[0]);
$.ajax({
url: 'upload.php', //server script to process data
type: 'POST',
// ajax events
beforeSend: function() {
},
success: function(e) {
$('#upload_result').html('Thank you for your photo').show();

setTimeout(function() {
$("#upload_result").hide().empty();
window.location.href = 'index.php';
}, 4000);
},
error: function(e) {
$('#upload_result').html('Error while processing uploaded image');
},
// form data
data: formData,
// options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false
});
}

function submitComment(form, id) {
$.ajax({
type: 'POST',
url: 'service.php',
data: 'add=comment&id=' + id + '&comment=' + $(form).find('textarea').val(),
cache: false,
success: function(html){
if (html) {
location.reload();
}
}
});
return false;
}

function initiateColorboxHandler() {
$('.ajax').colorbox({
onOpen:function(){
},
onload:function(){
},
onComplete:function(){
$(this).colorbox.resize();
var iPinId = $(this).parent().parent().attr('pin_id');
$.ajax({
url: 'service.php',
data: 'get=comments&id=' + iPinId,
cache: false,
success: function(html){
$('.comments').append(html);

$(this).colorbox.resize();
}
});

},
onCleanup:function(){
},
onClosed:function(){
}
});
}

$(document).ready(function(){

// file field change handler
$('#image_file').change(function(){
var file = this.files[0];
name = file.name;
size = file.size;
type = file.type;

// extra validation
if (name && size) {
if (! file.type.match('image.*')) {
alert("Select image please");
} else {
fileSelectHandler();
}
}
});

// masonry initialization
var $container = $('.main_container');

$container.imagesLoaded(function(){
// options
$container.masonry({
itemSelector: '.pin',
isAnimated: true,
isFitWidth: true,
isAnimatedFromBottom: true
});
});

$container.infinitescroll({
navSelector : '#page-nav', // selector for the paged navigation
nextSelector : '#page-nav a', // selector for the NEXT link (to page 2)
itemSelector : '.pin', // selector for all items you'll retrieve
loading: {
finishedMsg: 'No more pages to load.'
}
},
// trigger Masonry as a callback
function( newElements ) {
// hide new items while they are loading
var $newElems = $( newElements ).css({ opacity: 0 });
// ensure that images load before adding to masonry layout
$newElems.imagesLoaded(function(){
// show elems now they're ready
$newElems.animate({ opacity: 1 });
$container.masonry( 'appended', $newElems, true );

// initiate colorbox
initiateColorboxHandler();
});
}
);

// onclick event handler (for comments)
$('.comment_tr').click(function () {
$(this).toggleClass('disabled');
$(this).parent().parent().parent().find('form.comment').slideToggle(400, function () {
$('.main_container').masonry();
});
});

// initiate colorbox
initiateColorboxHandler();

// onclick event handler (for like button)
$('.pin .actions .likebutton').click(function () {
$(this).attr('disabled', 'disabled');

var iPinId = $(this).parent().parent().parent().attr('pin_id');
$.ajax({
url: 'service.php',
type: 'POST',
data: 'add=like&id=' + iPinId,
cache: false,
success: function(res){
$('.pin[pin_id='+iPinId+'] .info .LikesCount strong').text(res);
}
});
return false;
});

// onclick event handler (for repin button)
$('.pin .actions .repinbutton').click(function () {
var iPinId = $(this).parent().parent().parent().attr('pin_id');
$.ajax({
url: 'service.php',
type: 'POST',
data: 'add=repin&id=' + iPinId,
cache: false,
success: function(res){
window.location.href = 'profile.php?id=' + res;
}
});
return false;
});
});

Как вы помните, в первом этапе мы добавили новую jQuery-библиотеку: infinitescroll. Сюда мы добавили инициализацию библиотеки infinitescroll (необходимую для бесконечной прокрутки), а также изменили инициализацию для masonry. Это из-за того, что нам нужно сортировать новые изображения, а также обрабатывать событие onclick для всех новых изображений (colorbox).

Завершение

Только что мы завершили 6-ю часть нашего руководства, посвященного разработке скрипта в стиле Pinterest. Мы надеемся, что вам понравилась эта статья. Также надеемся, что вы поделитесь этими материалами со своими друзьями. Желаем вам удачи, и не забывайте следить за новостями!
Обнаружили ошибку или мёртвую ссылку?
Выделите проблемный фрагмент мышкой и нажмите CTRL+ENTER.
В появившемся окне опишите проблему и отправьте уведомление Администрации ресурса.
Нужна органическая вечная ссылка из данной статьи? Постовой?
Подробности здесь
Вам понравился материал? Поблагодарить легко!
Будем весьма признательны, если поделитесь этой статьей в социальных сетях:

Ключевые тэги: Pinterest, скрипты
Опубликовал Design FactoRy   Прочитано (раз): 8082   |   Оставлено комментариев: 1
Автор перевода — CoolWebmasters.Com ©   |   Источник материала / оригинал статьи   Распечатать
Другие статьи и новости по теме:
Комментарий #1: 26 апреля 2013 @ 19:15
Написал: Oleg — группа: Гости  
На сайте с: --   |   Публикаций: 0   |   Комментариев: 0
ICQ: --- не указано ---
Не сочтите за оффтоп, а как будут индексироваться поисковыми роботами подгружаемые скриптом блоки и ссылки в них?
Добавление комментария
Уважаемые пользователи!
При добавлении комментариев на сайт Вам следует учитывать следующее - все комментарии проверяются Администрацией на предмет отсутствия спама. При обнаружении признаков спама, в оставленном Вами комментарии, сам комментарий будет незамедлительно удалён, а Ваш IP-адрес будет забанен без предупреждения! Учётные записи пользователей, рассылающих спам, блокируются/удаляются без права последующего восстановления.

С уважением, Администрация сайта.
* = поля обязательны к заполнению
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Вопрос : Назовите месяц February по-русски
Подтверждение кода безопасности :

Включите эту картинку для отображения кода безопасности
обновить, если не виден код


Сделай заказ Дизайн интерьера Алматы Лучшие дизайнеры Алматы
home-design.kz
Популярные публикации


















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Сентябрь 2017    »
ПнВтСрЧтПтСбВс
 123
45678910
11121314151617
18192021222324
252627282930