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

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



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

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

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

Сейчас предлагаем вам проверить наше демо, и скачать исходные файлы:

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


Этап 1 – SQL

Для того чтобы лучше понять, как это работает, давайте рассмотрим таблицы нашей новой базы данных:

CREATE TABLE `pd_profiles` (
`id` int(10) unsigned NOT NULL auto_increment,
`first_name` varchar(255) NOT NULL default '',
`last_name` varchar(255) NOT NULL default '',
`email` varchar(255) NOT NULL default '',
`password` varchar(40) NOT NULL default '',
`salt` varchar(10) NOT NULL default '',
`status` enum('active','passive') NOT NULL default 'active',
`role` tinyint(4) unsigned NOT NULL default '1',
`date_reg` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `pd_profiles` (`first_name`, `last_name`, `email`, `password`, `salt`, `status`, `role`, `date_reg`) VALUES
('test user first name', 'test user last name', 'user@user.com', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 1, NOW()),
('moderator first name', 'moderator last name', 'moderator@moderator.com', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 2, NOW()),
('admin first name', 'admin last name', 'admin@admin.com', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 3, NOW()),
('test user 2 first name', 'test user 2 last name', 'user2@user.com', 'b88c654d6c68fc37f4dda1d29935235eea9a845b', 'testing', 'active', 1, NOW());

CREATE TABLE IF NOT EXISTS `pd_photos` (
`id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(255) default '',
`filename` varchar(255) default '',
`owner` int(11) NOT NULL,
`when` int(11) NOT NULL default '0',
`comments_count` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `pd_photos` (`title`, `filename`, `owner`, `when`) VALUES
('Item #1', 'pic1.jpg', 1, UNIX_TIMESTAMP()),
('Item #2', 'pic2.jpg', 2, UNIX_TIMESTAMP()+1),
('Item #3', 'pic3.jpg', 3, UNIX_TIMESTAMP()+2),
('Item #4', 'pic4.jpg', 4, UNIX_TIMESTAMP()+3);

CREATE TABLE IF NOT EXISTS `pd_items_cmts` (
`c_id` int(11) NOT NULL AUTO_INCREMENT ,
`c_item_id` int(12) NOT NULL default '0',
`c_ip` varchar(20) default NULL,
`c_name` varchar(64) default '',
`c_text` text NOT NULL ,
`c_when` int(11) NOT NULL default '0',
PRIMARY KEY (`c_id`),
KEY `c_item_id` (`c_item_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8;

Здесь есть три таблицы: первая (pd_profiles) содержит информацию о пользователях, вторая (pd_photos) – о фотографиях, а третья предназначена для комментариев. Пожалуйста, обратите внимание, что все пользователи имеют одинаковый пароль «password». Для авторизации в систему вам нужно воспользоваться email-адресом и паролем.

Этап 2 – HTML

Мы внесли небольшие исправления в файл шаблона index.html. Как вы знаете, нам не нужно отображаться форму загрузки обычным посетителям, она должна отображаться только зарегистрированным и авторизованным пользователям. Но, нам нужно отображать форму авторизации и регистрации для посетителей. Пожалуйста, посмотрите на обновленный код нашей главной страницы:

templates/index.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 3 | 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="#" 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-3/">Back to tutorial</a>
</li>
</ul>

</div>

{extra_data}

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

Как видно, мы добавили два новых ключа шаблона: {menu_elements} – они будет содержать дополнительные формы авторизации и регистрации для посетителей, а также элементы загрузки файлов, профайла и выхода из системы – для зарегистрированных и авторизованных пользователей. Наш новый ключ {extra_data} содерит формы авторизации и регистрации для посетителей, и форму загрузки для авторизованных пользователей. Все эти формы полностью управляются посредством CSS.

Этап 3 – PHP

Как вы, наверное, уже предположили, все наши php-файлы также были обновлены. Давайте начнем с основного файла главной страницы:

index.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();

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

// draw common page
$aKeys = array(
'{menu_elements}' => $sLoginMenu,
'{extra_data}' => $sExtra,
'{images_set}' => $sPhotos
);
echo strtr(file_get_contents('templates/index.html'), $aKeys);

Как видно, он стал гораздо меньше. Но в то же время, вы можете видеть, что мы добавили три новых класса: CMySQL (для работы с базой данных), CMembers (для работы с пользователями) и CPhotos (для работы с фотографиями). Итак, этот файл отображает формы авторизации и регистрации для посетителей, и форму загрузки для активных пользователей. На этой странице мы также отображаем фотографии. Следующий обновленный файл:

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');

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

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

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'];

?>
<div class="pin bigpin">
<div class="owner">
<a href="#" class="button follow_button">Follow</a>
<a target="_blank" class="owner_img" href="#">
<img alt="<?= $sOwnerName ?>" src="images/avatar.jpg" />
</a>
<p class="owner_name"><a target="_blank" href="#"><?= $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 ?>">
</a>
</div>

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

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

<form class="comment" method="post" action="#">
<input type="hidden" name="id" value="0" />
<textarea placeholder="Add a comment..." maxlength="1000"></textarea>
<button type="button" class="button">Comment</button>
</form>
</div>

Мы добавили возможность зарегистрироваться. Вдобавок, нам не нужно вводить полное имя файла для того, чтобы увидеть его увеличенную версию. Вместо этого, мы вводим Id изображения. Следующий обновленный файл отвечает за наш загрузчик:

upload.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');

function uploadImageFile() { // Note: GD library is required for this upload function

$iDefWidth = 192; // default photos width (in case of resize)
$iFDefWidth = 556; // full default photos width (in case of resize)

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$iWidth = $iHeight = $iFDefWidth; // desired image dimensions
$iJpgQuality = 75;

if ($_FILES) {

// if there are no errors and filesize less than 400kb
if (! $_FILES['image_file']['error'] && $_FILES['image_file']['size'] < 400 * 1024) {
if (is_uploaded_file($_FILES['image_file']['tmp_name'])) {

// new unique filename
$sTempFileName = 'photos/' . md5(time().rand());

// move uploaded file into cache folder
move_uploaded_file($_FILES['image_file']['tmp_name'], $sTempFileName);

// change file permission to 644
@chmod($sTempFileName, 0644);

// if temp file exists
if (file_exists($sTempFileName) && filesize($sTempFileName) > 0) {
$aSize = getimagesize($sTempFileName); // obtain image info
if (!$aSize) {
@unlink($sTempFileName);
return;
}

// check for image type and create a new image from file
switch($aSize[2]) {
case IMAGETYPE_JPEG:
$sExt = '.jpg';
$vImg = @imagecreatefromjpeg($sTempFileName);
break;
case IMAGETYPE_PNG:
$sExt = '.png';
$vImg = @imagecreatefrompng($sTempFileName);
break;
default:
@unlink($sTempFileName);
return;
}

// get source image width and height
$iSrcWidth = imagesx($vImg);
$iSrcHeight = imagesy($vImg);

// recalculate height (depends on width)
$iHeight = $iSrcHeight * $iWidth / $iSrcWidth;

// create a new true color image
$vDstImg = @imagecreatetruecolor($iWidth, $iHeight);

// copy and resize
imagecopyresampled($vDstImg, $vImg, 0, 0, 0, 0, $iWidth, $iHeight, $iSrcWidth, $iSrcHeight);

// add a blank image object into DB
$iLastId = $GLOBALS['CPhotos']->insertBlankPhoto($_FILES['image_file']['name'], $_SESSION['member_id']);

// define a result image filename
$sResultFileName = 'photos/f_pic' . $iLastId . $sExt;

// update filename for our object
$GLOBALS['CPhotos']->updateFilename($iLastId, 'pic' . $iLastId . $sExt);

// output image to file and set permission 644
imagejpeg($vDstImg, $sResultFileName, $iJpgQuality);
@chmod($sResultFileName, 0644);

// and, prepare a thumbnail as well
$iWidth = $iDefWidth;
$iHeight = $iSrcHeight * $iWidth / $iSrcWidth;
$vDstThImg = @imagecreatetruecolor($iWidth, $iHeight);
imagecopyresampled($vDstThImg, $vImg, 0, 0, 0, 0, $iWidth, $iHeight, $iSrcWidth, $iSrcHeight);
$sResultThumnName = 'photos/pic' . $iLastId . $sExt;
imagejpeg($vDstThImg, $sResultThumnName, $iJpgQuality);
@chmod($sResultThumnName, 0644);

// unlink temp file
@unlink($sTempFileName);
return $sResultFileName;
}
}
}
}
}
}

// upload available only for logged in members
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
$sImage = uploadImageFile();
echo '1';
}

Теперь только зарегистрированные и авторизованные пользователи смогут загружать фотографии (как мы и говорили в самом начале). Итак, нам кажется, что сейчас важно рассказать вам о наших новых классах:

classes/CMembers.php

/*
* Members class
*/
class CMembers {

// constructor
function CMembers() {
session_start();
}

// get login box function
function getLoginData() {
if (isset($_GET['logout'])) { // logout process
if (isset($_SESSION['member_email']) && isset($_SESSION['member_pass']))
$this->performLogout();
}

if ($_POST && $_POST['email'] && $_POST['password']) { // login process
if ($this->checkLogin($_POST['email'], $_POST['password'], false)) { // successful login
$this->performLogin($_POST['email'], $_POST['password']);
header('Location: index.php');
exit;
}
} else { // in case if we are already logged in
if (isset($_SESSION['member_email']) && $_SESSION['member_email'] && $_SESSION['member_pass']) {
$aReplaces = array(
'{name}' => $_SESSION['member_email'],
'{status}' => $_SESSION['member_status'],
'{role}' => $_SESSION['member_role'],
);

// display Profiles menu and Logout
$sLoginMenu = <<<EOF
<li><a href="#add_form" id="add_pop">Add +</a></li>
<li>
<a href="#">Profile<span></span></a>
<ul>
<li><a href="#">Invite Friends</a></li>
<li><a href="#">Find Friends</a></li>
<li class="div"><a href="#">Boards</a></li>
<li><a href="#">Pins</a></li>
<li><a href="#">Likes</a></li>
<li class="div"><a href="#">Settings</a></li>
<li><a href="#">Logout</a></li>
</ul>
</li>
<li><a href="index.php?logout">Logout</a></li>
EOF;
$sExtra = <<<EOF
<!-- upload form -->
<a href="#x" class="overlay" id="add_form"></a>
<div class="popup">
<div class="header">
<a class="close" href="#close">x</a>
<h2>Upload a Pin</h2>
</div>
<form id="upload_form">
<input type="file" name="image_file" id="image_file" onchange="" />
</form>
<div id="upload_result"></div>
</div>
EOF;
return array($sLoginMenu, $sExtra);
}
}

// display Join and Login menu buttons
$sLoginMenu = <<<EOF
<li><a href="#join_form" id="join_pop">Join</a></li>
<li><a href="#login_form" id="login_pop">Login</a></li>
EOF;
$sExtra = <<<EOF
<!-- join form -->
<a href="#x" class="overlay2" id="join_form"></a>
<div class="popup">
<div class="header">
<a class="close" href="#close">x</a>
<h2>Create your account</h2>
</div>

<form method="POST" action="service.php">
<ul class="ctrl_grp">
<li>
<input type="text" name="email" />
<label>Email Address</label>
<span class="fff"></span>
</li>
<li>
<input type="password" name="password" />
<label>Password</label>
<span class="fff"></span>
</li>
<li>
<input type="text" name="first_name" />
<label>First Name</label>
<span class="fff"></span>
</li>
<li>
<input type="text" name="last_name" />
<label>Last Name</label>
<span class="fff"></span>
</li>
</ul>
<div>
<input type="hidden" name="Join" value="Join" />
<button class="submit_button" type="submit">Create Account</button>
</div>
</form>
</div>

<!-- login form -->
<a href="#x" class="overlay3" id="login_form"></a>
<div class="popup">
<div class="header">
<a class="close" href="#close">x</a>
<h2>Login</h2>
</div>

<form method="POST" action="index.php">
<ul class="ctrl_grp">
<li>
<input type="text" name="email" id="id_email">
<label>Email</label>
<span class="fff"></span>
</li>
<li>
<input type="password" name="password" id="id_password">
<label>Password</label>
<span class="fff"></span>
</li>
</ul>
<div>
<button class="submit_button" type="submit">Login</button>
</div>
</form>
</div>
EOF;
return array($sLoginMenu, $sExtra);
}

// perform login
function performLogin($sEmail, $sPass) {
$this->performLogout();

// make variables safe
$sEmail = $GLOBALS['MySQL']->escape($sEmail);

$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'");
// $sPassEn = $aProfile['password'];
$iPid = $aProfile['id'];
$sSalt = $aProfile['salt'];
$sStatus = $aProfile['status'];
$sRole = $aProfile['role'];

$sPass = sha1(md5($sPass) . $sSalt);

$_SESSION['member_id'] = $iPid;
$_SESSION['member_email'] = $sEmail;
$_SESSION['member_pass'] = $sPass;
$_SESSION['member_status'] = $sStatus;
$_SESSION['member_role'] = $sRole;
}

// perform logout
function performLogout() {
unset($_SESSION['member_id']);
unset($_SESSION['member_email']);
unset($_SESSION['member_pass']);
unset($_SESSION['member_status']);
unset($_SESSION['member_role']);
}

// check login
function checkLogin($sEmail, $sPass, $isHash = true) {
// escape variables to make them self
$sEmail = $GLOBALS['MySQL']->escape($sEmail);
$sPass = $GLOBALS['MySQL']->escape($sPass);

$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'");
$sPassEn = $aProfile['password'];

if ($sEmail && $sPass && $sPassEn) {
if (! $isHash) {
$sSalt = $aProfile['salt'];
$sPass = sha1(md5($sPass) . $sSalt);
}
return ($sPass == $sPassEn);
}
return false;
}

// profile registration
function registerProfile() {
$sFirstname = $GLOBALS['MySQL']->escape($_POST['first_name']);
$sLastname = $GLOBALS['MySQL']->escape($_POST['last_name']);
$sEmail = $GLOBALS['MySQL']->escape($_POST['email']);
$sPassword = $GLOBALS['MySQL']->escape($_POST['password']);

if ($sEmail && $sPassword) {
// check if email is already exists
$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `pd_profiles` WHERE `email`='{$sEmail}'");
if ($aProfile['id'] > 0) {
// relocate to 'error' page
header('Location: error.php');
} else {
// generate Salt and Cached password
$sSalt = $this->getRandSaltCode();
$sPass = sha1(md5($sPassword) . $sSalt);

// add new member into database
$sSQL = "
INSERT INTO `pd_profiles` SET
`first_name` = '{$sFirstname}',
`last_name` = '{$sLastname}',
`email` = '{$sEmail}',
`password` = '{$sPass}',
`salt` = '{$sSalt}',
`status` = 'active',
`role` = '1',
`date_reg` = NOW();
";
$GLOBALS['MySQL']->res($sSQL);

// autologin
$this->performLogin($sEmail, $sPassword);

// relocate back to index page
header('Location: index.php');
}
} else {
// otherwise - relocate to error page
header('Location: error.php');
}
}

// get random salt code
function getRandSaltCode($iLen = <img src="http://www.script-tutorials.com/wp-includes/images/smilies/icon_cool.gif" alt="8)" class="wp-smiley"> {
$sRes = '';

$sChars = '23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
for ($i = 0; $i < $iLen; $i++) {
$z = rand(0, strlen($sChars) -1);
$sRes .= $sChars[$z];
}
return $sRes;
}

// get certain member info
function getProfileInfo($i) {
$sSQL = "
SELECT *
FROM `pd_profiles`
WHERE `id` = '{$i}'
";
$aInfos = $GLOBALS['MySQL']->getAll($sSQL);
return $aInfos[0];
}
}

$GLOBALS['CMembers'] = new CMembers();

Основной класс members содержит следующие функции: getLoginData (эти функции выполняют несколько действий: обработка авторизации и выхода из системы, а также отображение кнопок меню Join и Login (с формами) и кнопок Upload & Logout (с формами) для пользователей), performLogin (для авторизации), performLogout (для выхода из системы), checkLogin (для проверки введенных данных), registerProfile (для регистрации нового пользователя), getRandSaltCode (для получения случайного кода), getProfileInfo (для получения информации о конкретном пользователе). Нам кажется, что для пользователей такого количества функций достаточно. Как вы уже заметили, мы использовали новый php-файл: error.php – для генерации ошибок. Это очень простой файл:

error.php

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

// login system init and generation code
list ($sLoginMenu, $sExtra) = $GLOBALS['CMembers']->getLoginData();

// draw common page
$aKeys = array(
'{menu_elements}' => $sLoginMenu,
'{extra_data}' => $sExtra,
'{images_set}' => '<center><h1>Error Occurred, please try again</h1></center>'
);
echo strtr(file_get_contents('templates/index.html'), $aKeys);

Наконец, наш последний на сегодня класс:

classes/CPhotos.php

/*
* Photos class
*/
class CPhotos {

// constructor
function CPhotos() {
}

// get all photos
function getAllPhotos() {
$sSQL = "
SELECT *
FROM `pd_photos`
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'];

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

$sImages .= <<<EOL
<!-- pin element {$iPhotoId} -->
<div class="pin">
<div class="holder">
<div class="actions" pin_id="{$iPhotoId}">
<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>
</p>
<form class="comment" method="post" action="" style="display: none">
<input type="hidden" name="id" value="0" />
<textarea placeholder="Add a comment..." maxlength="1000"></textarea>
<button type="button" class="button">Comment</button>
</form>
</div>
EOL;
}
return $sImages;
}

// get certain photo info
function getPhotoInfo($i) {
$sSQL = "SELECT * FROM `pd_photos` WHERE `id` = '{$i}'";
$aInfos = $GLOBALS['MySQL']->getAll($sSQL);
return $aInfos[0];
}

// format time by timestamp
function formatTime($iSec) {
$sFormat = 'j F Y';
return gmdate($sFormat, $iSec);
}

// insert a new blank photo into DB
function insertBlankPhoto($sTitle, $iOwner) {
$sTitle = $GLOBALS['MySQL']->escape($sTitle);
$iOwner = (int)$iOwner;

$sSQL = "INSERT INTO `pd_photos` SET `title` = '{$sTitle}', `owner` = '{$iOwner}', `when` = UNIX_TIMESTAMP()";
$GLOBALS['MySQL']->res($sSQL);
return $GLOBALS['MySQL']->lastId();
}

// update filename
function updateFilename($i, $sFilename) {
$sFilename = $GLOBALS['MySQL']->escape($sFilename);

$sSQL = "UPDATE `pd_photos` SET `filename` = '{$sFilename}' WHERE `id`='{$i}'";
return $GLOBALS['MySQL']->res($sSQL);
}
}

$GLOBALS['CPhotos'] = new CPhotos();

Здесь есть еще несколько функций вроде: getAllPhotos (для отображения всего набора фотографий на главной странице), getPhotoInfo (для получения информации о конкретных фотографиях), formatTime (форматирование времени для всплывающего окна), insertBlankPhoto и updateFilename (для добавления нового изображения в базу данных и обновления имени файла данного изображения).

Этап 4 – CSS-код

Для того чтобы управлять двумя новыми формами (авторизации и регистрации), мы обновили стили всплывающих окон:

css/main.css

/* upload form styles */
.overlay, .overlay2, .overlay3 {
background-color: #FFFFFF;
bottom: 0;
display: none;
left: 0;
opacity: 0.8;
position: fixed;
right: 0;
top: 0;
z-index: 9;
}
.overlay:target, .overlay2:target, .overlay3:target {
display: block;
}
.popup {
background: none repeat scroll 0 0 #FCF9F9;
border: 1px solid #F7F5F5;
box-shadow: 0 2px 5px rgba(34, 25, 25, 0.5);
display: inline-block;
left: 50%;
padding: 30px 30px 20px;
position: fixed;
top: 40%;
visibility: hidden;
width: 550px;
z-index: 10;

-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);

-webkit-transition: all 0.3s ease-in-out 0s;
-moz-transition: all 0.3s ease-in-out 0s;
-ms-transition: all 0.3s ease-in-out 0s;
-o-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
.overlay:target+.popup, .overlay2:target+.popup, .overlay3:target+.popup {
top: 50%;
opacity: 1 ;
visibility: visible;
}

Мы также добавили новые стили для обеих новых форм:

/* login & join form styles */
.ctrl_grp li {
display: block;
font-size: 21px;
list-style: none outside none;
margin-bottom: 18px;
position: relative;
}
.ctrl_grp input[type="text"], .ctrl_grp input[type="password"] {
background-color: transparent;
border: 1px solid #AD9C9C;
border-radius: 6px 6px 6px 6px;
box-shadow: 0 1px rgba(34, 25, 25, 0.15) inset, 0 1px #FFFFFF;
color: #221919;
display: block;
font-size: 18px;
line-height: 1.4em;
padding: 6px 12px;
position: relative;
transition: all 0.08s ease-in-out 0s;
width: 95%;
z-index: 3;
}
.ctrl_grp input[type="text"]:focus, .ctrl_grp input[type="password"]:focus {
border-color: ##993300;
box-shadow: 0 1px rgba(34, 25, 25, 0.15) inset, 0 1px rgba(255, 255, 255, 0.8), 0 0 14px rgba(235, 82, 82, 0.35);

}
.ctrl_grp label {
-moz-user-select: none;
color: #EFEFEF;
display: block;
font-size: 18px;
left: 13px;
line-height: 1.4em;
position: absolute;
top: 5px;
transition: all 0.16s ease-in-out 0s;
z-index: 2;
}
.ctrl_grp .fff {
background-color: #FFFFFF;
border-radius: 8px 8px 8px 8px;
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
.submit_button {
background-image: -moz-linear-gradient(center top , #FDFAFB, #F9F7F7 50%, #F6F3F4 50%, #F0EDED);
border: 1px solid #BBBBBB;
border-radius: 6px 6px 6px 6px;
box-shadow: 0 1px rgba(255, 255, 255, 0.8), 0 1px rgba(255, 255, 255, 0.35) inset;
color: #524D4D;
cursor: pointer;
display: inline-block;
font-family: "helvetica neue",arial,sans-serif;
font-size: 18px;
font-weight: bold;
line-height: 1em;
margin: 0;
padding: 0.45em 0.825em;
text-align: center;
text-shadow: 0 1px rgba(255, 255, 255, 0.9);
transition: all 0.05s ease-in-out 0s;
}
.submit_button:hover {
box-shadow: 0 1px rgba(255, 255, 255, 0.8), 0 1px rgba(255, 255, 255, 0.35) inset, 0 0 10px rgba(232, 230, 230, 0.75);
}

Завершение

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

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

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

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


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


















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Ноябрь 2017    »
ПнВтСрЧтПтСбВс
 12345
6789101112
13141516171819
20212223242526
27282930