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

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



Друзья, сегодня мы с радостью представляем вам 4-ю часть нашего руководства, посвященного созданию скрипта в стиле Pinterest. Сегодня мы добавим систему комментирования на Ajax, а также страницы профайлов. Теперь у нас есть возможность оставлять комментарии (эта функция доступна только авторизованным пользователям) прямо на "пинах", а также на увеличенных версиях (во всплывающем окне) изображений.
Сегодня мы представим вам все обновленные файлы скрипта, на случай, если вам захочется покопаться в исходниках – вы всегда можете скачать полный набор нашего проекта вместе с исходными файлами.

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

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

Предлагаем вам ознакомиться с демо, и скачать исходники проекта здесь:

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


Этап 1 – HTML

Как мы уже говорили, мы добавили страницы профайлов. Как обычно, мы ужимаем всю html-разметку в один файл шаблона (поэтому вы без труда сможете отредактировать его):

templates/profile.html

<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<meta name="author" content="Script Tutorials" />
<title>How to create Pinterest-like script - step 4 | Script Tutorials</title>

<!-- add styles -->
<link href="css/main.css" rel="stylesheet" type="text/css" />
<link href="css/colorbox.css" rel="stylesheet" type="text/css" />

<!-- 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/script.js"></script>
</head>
<body>

<!-- header panel -->
<div class="header_panel">

<!-- logo -->
<a href="index.php" class="logo"></a>

<!-- search form -->
<form action="" method="get" class="search">
<input autocomplete="off" name="q" size="27" placeholder="Search" type="text" />
<input name="search" type="submit" />
</form>

<!-- navigation menu -->
<ul class="nav">
<li>
<a href="#">About<span></span></a>
<ul>
<li><a href="#">Help</a></li>
<li><a href="#">Pin It Button</a></li>
<li><a href="#" target="_blank">For Businesses</a></li>
<li class="div"><a href="#">Careers</a></li>
<li><a href="#">Team</a></li>
<li><a href="#">Blog</a></li>
<li class="div"><a href="#">Terms of Service</a></li>
<li><a href="#">Privacy Policy</a></li>
<li><a href="#">Copyright</a></li>
<li><a href="#">Trademark</a></li>
</ul>
</li>
{menu_elements}
<li>
<a href="http://www.script-tutorials.com/pinterest-like-script-step-4/">Back to tutorial</a>
</li>
</ul>

</div>

{extra_data}

<h2 class="pname">Profile {profile_name}</h2>

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

Этап 2 – PHP

Теперь, пожалуйста, ознакомьтесь с PHP-кодом нашей страницы профайла:

profile.php

// set warning level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
error_reporting(E_ALL & ~E_NOTICE);

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($_SESSION['member_id']);
if ($aMemberInfo) {

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

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

header('Location: error.php');

Как видно, это очень простой файл. Он чем-то похож на нашу главную страницу, за исключением одного – эта страница отображает имя профайла, и только его фотографии. Теперь, для того, чтобы отобразить фотографии только этого профайла, нам нужно немного подправить функцию CPhotos::getAllPhotos. Давайте рассмотрим обновленную версию:

    function getAllPhotos($iPid = 0) {
$sFilter = ($iPid) ? "WHERE `owner` = '{$iPid}'" : '';
$sSQL = "
SELECT *
FROM `pd_photos`
{$sFilter}
ORDER BY `when` DESC
";
$aPhotos = $GLOBALS['MySQL']->getAll($sSQL);

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

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

$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">
<a href="#" class="button">Repin</a>
<a href="#" class="button">Like</a>
<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>XX likes</span>
<span>XX 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;
}

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

classes/CComments.php

/*
* Comments class
*/
class CComments {

// constructor
function CComments() {
}

// return comments block
function getComments($i) {
// draw last 5 comments
$sComments = '';
$aComments = $GLOBALS['MySQL']->getAll("SELECT * FROM `pd_items_cmts` WHERE `c_item_id` = '{$i}' ORDER BY `c_when` DESC LIMIT 5");
foreach ($aComments as $iCmtId => $aCmtsInfo) {
$sWhen = date('F j, Y H:i', $aCmtsInfo['c_when']);
$sComments .= <<<EOF
<div class="comment" id="{$aCmtsInfo['c_id']}">
<p>Comment from {$aCmtsInfo['c_name']} <span>({$sWhen})</span>:</p>
<p>{$aCmtsInfo['c_text']}</p>
</div>
EOF;
}
return $sComments;
}

function acceptComment() {
$iItemId = (int)$_POST['id']; // prepare necessary information
$sIp = $this->getVisitorIP();

$aMemberInfo = $GLOBALS['CMembers']->getProfileInfo($_SESSION['member_id']);
$sName = $GLOBALS['MySQL']->escape(strip_tags($aMemberInfo['first_name']));
$sText = $GLOBALS['MySQL']->escape(strip_tags($_POST['comment']));

if ($iItemId && $sName && strlen($sText) > 2) {
// check - if there is any recent comment from the same person (IP) or not (for last 5 mins)
$iOldId = $GLOBALS['MySQL']->getOne("SELECT `c_item_id` FROM `pd_items_cmts` WHERE `c_item_id` = '{$iItemId}' AND `c_ip` = '{$sIp}' AND `c_when` >= UNIX_TIMESTAMP() - 300 LIMIT 1");
if (! $iOldId) {
// if everything is fine - allow to add comment
$GLOBALS['MySQL']->res("INSERT INTO `pd_items_cmts` SET `c_item_id` = '{$iItemId}', `c_ip` = '{$sIp}', `c_when` = UNIX_TIMESTAMP(), `c_name` = '{$sName}', `c_text` = '{$sText}'");
$GLOBALS['MySQL']->res("UPDATE `pd_photos` SET `comments_count` = `comments_count` + 1 WHERE `id` = '{$iItemId}'");

// and print out last 5 comments
$sOut = '';
$aComments = $GLOBALS['MySQL']->getAll("SELECT * FROM `pd_items_cmts` WHERE `c_item_id` = '{$iItemId}' ORDER BY `c_when` DESC LIMIT 5");
foreach ($aComments as $i => $aCmtsInfo) {
$sWhen = date('F j, Y H:i', $aCmtsInfo['c_when']);
$sOut .= <<<EOF
<div class="comment" id="{$aCmtsInfo['c_id']}">
<p>Comment from {$aCmtsInfo['c_name']} <span>({$sWhen})</span>:</p>
<p>{$aCmtsInfo['c_text']}</p>
</div>
EOF;
}
return $sOut;
}
}
}

// get visitor IP
function getVisitorIP() {
$ip = "0.0.0.0";
if( ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) && ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif( ( isset( $_SERVER['HTTP_CLIENT_IP'])) && (!empty($_SERVER['HTTP_CLIENT_IP'] ) ) ) {
$ip = explode(".",$_SERVER['HTTP_CLIENT_IP']);
$ip = $ip[3].".".$ip[2].".".$ip[1].".".$ip[0];
} elseif((!isset( $_SERVER['HTTP_X_FORWARDED_FOR'])) || (empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
if ((!isset( $_SERVER['HTTP_CLIENT_IP'])) && (empty($_SERVER['HTTP_CLIENT_IP']))) {
$ip = $_SERVER['REMOTE_ADDR'];
}
}
return $ip;
}
}

$GLOBALS['Comments'] = new CComments();

Здесь у нас всего три функции: getVisitorIP (для определения ip-адресов посетителей), getComments (для возврата комментариев – по умолчанию мы отображаем 5 последних комментариев) и acceptComment (для того, чтобы принимать комментарии и заносить их в базу данных). Наконец, нам нужно отредактировать наш файл service:

service.php

// set warning level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
error_reporting(E_ALL & ~E_NOTICE);

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

if (! isset($_SESSION['member_id']) && $_POST['Join'] == 'Join') {
$GLOBALS['CMembers']->registerProfile();
}

$i = (int)$_GET['id'];

if ($_GET && $_GET['get'] == 'comments') {
header('Content-Type: text/html; charset=utf-8');
echo $GLOBALS['Comments']->getComments($i);
exit;
}
if ($_POST && $_POST['add'] == 'comment') {
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
header('Content-Type: text/html; charset=utf-8');
echo $GLOBALS['Comments']->acceptComment();
exit;
}
header('Content-Type: text/html; charset=utf-8');
echo '<h3>Please login first</h3>';
exit;
}

if (! $i) { // if something is wrong - relocate to error page
header('Location: error.php');
exit;
}

$aPhotoInfo = $GLOBALS['CPhotos']->getPhotoInfo($i);
$aOwnerInfo = $GLOBALS['CMembers']->getProfileInfo($aPhotoInfo['owner']);

$sOwnerName = ($aOwnerInfo['first_name']) ? $aOwnerInfo['first_name'] : $aOwnerInfo['email'];
$sPhotoTitle = $aPhotoInfo['title'];
$sPhotoDate = $GLOBALS['CPhotos']->formatTime($aPhotoInfo['when']);

$sFolder = 'photos/';
$sFullImgPath = $sFolder . 'f_' . $aPhotoInfo['filename'];
$aSize = getimagesize($sFullImgPath); // get image info
$iWidth = $aSize[0];
$iHeight = $aSize[1];

?>
<div class="pin bigpin">
<div class="owner">
<a href="#" class="button follow_button">Follow</a>
<a class="owner_img" href="profile.php?id=<?= $aOwnerInfo['id'] ?>">
<img alt="<?= $sOwnerName ?>" src="images/avatar.jpg" />
</a>
<p class="owner_name"><a href="profile.php?id=<?= $aOwnerInfo['id'] ?>"><?= $sOwnerName ?></a></p>
<p class="owner_when">Uploaded on <?= $sPhotoDate ?></p>
</div>
<div class="holder">
<div class="actions">
<a href="#" class="button">Repin</a>
<a href="#" class="button">Like</a>
</div>
<a class="image" href="#" title="<?= $sPhotoTitle ?>">
<img alt="<?= $sPhotoTitle ?>" src="<?= $sFullImgPath ?>" style="width:<?= $iWidth ?>px;height:<?= $iHeight ?>px;" />
</a>
</div>

<p class="desc"><?= $sPhotoTitle ?></p>

<div class="comments"></div>

<script>
function submitCommentAjx() {
$.ajax({
type: 'POST',
url: 'service.php',
data: 'add=comment&id=' + <?= $i ?> + '&comment=' + $('#pcomment').val(),
cache: false,
success: function(html){
if (html) {
$('.comments').html(html);
$(this).colorbox.resize();
}
}
});
}
</script>
<form class="comment" method="post" action="#">
<textarea placeholder="Add a comment..." maxlength="255" id="pcomment"></textarea>
<button type="button" class="button" onclick="return submitCommentAjx()">Comment</button>
</form>
</div>

Теперь у нас работают комментарии! Мы использовали функцию $.ajax для того, чтобы POST (передавать) комментарии на сервер. Как только мы публикуем новый комментарий – сервер возвращает нам (в ответ) 5 последних комментариев, чтобы мы могли обновить список последних комментариев к объекту ("пину"). Также обратите внимание, что наши профайлы теперь имеют собственные ссылки (profile.php).

Этап 3 – CSS

Для нашей страницы профайла мы добавили лишь небольшой css-параметр (добавьте этот код в конец вашего файла стилей):

css/main.css

/* profile page */
.pname {
font-size: 24px;
margin-bottom: 10px;
margin-top: 20px;
text-align: center;
}

Этап 4 – javascript

Мы обновили основной файл нашего скрипта. Сюда мы внесли несколько следующих изменений: новая функция для подтверждения отправки комментариев на сервер и для загрузки комментариев (при помощи ajax), как только мы открываем большую версию изображения при помощи Colorbox.

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();
location.reload();
}, 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;
}

$(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
$('.main_container').masonry({
// options
itemSelector : '.pin',
isAnimated: true,
isFitWidth: true
});

// 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();
});
});

$('.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(){
}
});
});

Завершение

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

Ключевые тэги: Pinterest, скрипты
Опубликовал Design FactoRy   Прочитано (раз): 8879   |   Нет комментариев
Автор перевода — CoolWebmasters.Com ©   |   Источник материала / оригинал статьи   Распечатать
Другие статьи и новости по теме:
Добавление комментария
Уважаемые пользователи!
При добавлении комментариев на сайт Вам следует учитывать следующее - все комментарии проверяются Администрацией на предмет отсутствия спама. При обнаружении признаков спама, в оставленном Вами комментарии, сам комментарий будет незамедлительно удалён, а Ваш IP-адрес будет забанен без предупреждения! Учётные записи пользователей, рассылающих спам, блокируются/удаляются без права последующего восстановления.

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

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


Популярные публикации


















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