—»     —»   Мощная система для организации чата – Часть 6
  Раздел: Чаты   Нет комментариев  

Мощная система для организации чата – Часть 6



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

Сегодня мы выложим для вас обновленные исходники нашего растущего проекта. Весь проект разложен по полочкам: системные классы будут в папке «classes», javascript-файлы в папке «js», таблицы стилей в папке «css», файлы шаблона в папке «templates», а все пользовательские аватары будут помещены в папку под названием «data».

Скачивайте исходники, и давайте приступать к разработке!

Мощная система для организации чата – Часть 6

Этап 1 – SQL

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

ALTER TABLE `cs_profiles` ADD `date_nav` datetime NOT NULL default '0000-00-00 00:00:00' AFTER `date_reg`;

Этап 2 – HTML

Мы также обновили шаблон нашей основной страницы. Теперь она содержит новый блок со списком онлайн-пользователей:

templates/main_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
<title>Powerful Chat System - Lesson 6</title>
<link href="css/main.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<header>
<h2>Powerful Chat System - Lesson 6</h2>
<a href="http://www.script-tutorials.com/powerful-chat-system-lesson-6/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
</header>
<div class="clear"></div>
<div class="container" id="con1">
{form}
{avatar}
</div>
<div class="container" id="con2">
<h2>Main Chat Block</h2>
<div class="chat_messages">
{chat}
</div>
{input}
</div>

<div class="sidebar">
<div>
<h2>Online Members Block</h2>
{online_members}
</div>
<div>
<h2>Last Members</h2>
{profiles}
</div>
</div>
</body>
</html>

Обновлениям подверглась и страница профайла (теперь она содержит правую боковую панель со списком пользователей):

templates/profile_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
<title>Powerful Chat System - Lesson 6</title>
<link href="css/main.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js/customizer.js"></script>
<style>
.container {
&#123;custom_styles}
}
</style>
</head>
<body>
<header>
<h2>Powerful Chat System - Lesson 6</h2>
<a href="http://www.script-tutorials.com/powerful-chat-system-lesson-6/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
</header>
<div class="clear"></div>
<div class="container">
<div class="column">
<h3>Name: {name}</h3>
<h3>First name: {fname}</h3>
<h3>Last name: {lname}</h3>
<h3>About: {about}</h3>
<h3>Date Reg: {datereg}</h3>
<h3>Role: {role}</h3>
<h3>Avatar: <img src="{avatar}" style="vertical-align:middle" /></h3>
</div>
<div class="column">
<p><a href="index.php">Back to chat</a></p>
</div>
</div>
<div class="container" {cust_visible}>
<h2>You can customize your profile page</h2>
<div class="column">
<canvas id="color_canvas" width="370" height="60"></canvas>
</div>
<div class="column">
<div class="customizer_buttons">
<div id="preview"></div>
</div>

<form action="profile.php" method="GET" target="change_color_result">
<input type="hidden" value="{id}" name="id">
<input type="hidden" value="color" name="color" id="color">
<input type="hidden" value="change_color" name="action">
<input id="submit" type="submit" name="submit" value="Apply">
</form>
<iframe class="avatar_iframe" name="change_color_result"></iframe>
</div>
</div>

<div class="sidebar">
<div>
<h2>Online Members Block</h2>
{online_members}
</div>
<div>
<h2>Last Members</h2>
{profiles}
</div>
</div>
</body>
</html>

Небольшие визуальные изменения в данном файле:

templates/logout_form.html

<div class="column">
<span style="float:right"><a href="index.php?logout">Log Out</a></span>
<h3>Hello {name}</h3>
<h3>Your status:</h3>
<div>{status}</div>
<h3>Your role:</h3>
<div>{role}</div>
</div>

Этап 3 - CSS

Многие стили были обновлены, и теперь нам нужно обновить файл стилей:

css/main.css

/* page layout */
*{
margin:0;
padding:0;
}
body {
background-color:#eee;
color:#fff;
font:14px/1.3 Arial,sans-serif;
}
header {
background-color:#212121;
box-shadow: 0 -1px 2px #111111;
display:block;
height:70px;
position:relative;
width:100%;
z-index:100;
}
header h2{
float: left;
font-size:22px;
font-weight:normal;
margin-left:10px;
margin-right:20px;
padding:22px 0;
}
header a.stuts,a.stuts:visited{
float: left;
text-decoration:none;
color:#fcfcfc;
font-size:14px;
height:70px;
line-height:70px;
}
header .stuts span {
font-size:22px;
font-weight:bold;
margin-left:5px;
}

/* main styles */
a {
color: #333;
outline: none;
text-decoration: none;
}
a:hover,a:active {
outline: 0;
text-decoration: none;
}
.container {
background-color: #F2F4F8;
border: 1px solid rgba(0, 0, 0, 0.4);
box-shadow: 2px 0 2px -2px #B2B9C9 inset;
color: #333333;
margin: 20px;
overflow: hidden;
padding: 20px;
position: relative;
width: 400px;
float:left;
}
#con1.container {
width: 300px;
}
#con2.container {
width: 500px;
}
.container h2 {
margin-bottom: 10px;
}
.column {
}
.column:first-child {
}
.column > * {
margin-bottom: 10px;
}
.clear {
clear: both;
font-size: 1px;
}
.sidebar {
background-color: #F2F4F8;
border-left: 1px solid rgba(0, 0, 0, 0.4);
box-shadow: 2px 0 2px -2px #B2B9C9 inset;
color: #333333;
display: block;
height: 100%;
padding: 10px;
position: fixed;
right: 0;
top: 0;
width: 250px;
z-index: 101;
}
.sidebar > div {
margin-bottom: 30px;
}

/* tabs section */
.tabs_container {
margin: 0;
}
.tabs {
overflow: hidden;
}
.tabs li {
float: left;
list-style: none;
}
.tabs li h3:first-child {
margin-left: 10px
}
.tabs li h3 {
border: 1px solid #ddd;
border-bottom-width: 0;
display: block;
margin: 0 2px 0 0;
padding: 6px 10px 4px
}
.tabs li.active h3 {
background-color: #ccc;
border: 1px solid #ddd;
border-bottom-width: 0;

-moz-border-radius: 4px 4px 0 0;
-ms-border-radius: 4px 4px 0 0;
-o-border-radius: 4px 4px 0 0;
-webkit-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
}
.tabs li h3:hover {
background-color: #bbb;
cursor: pointer;
}
.tabs li.active h3:hover {
background-color: #ccc;
cursor: normal;
}
.nav_container form {
background-color: #ccc;
display: block;
padding: 15px;
}
.login_form input,.login_form label,
.join_form input,.join_form label {
display: block;
margin-bottom: 10px;
}
input[type=text], input[type=password], input[type=submit] {
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
border-style: groove;
}
input[type=text], input[type=password] {
border-style: groove;
font-size: 16px;
height: 25px;
margin-right: 10px;
width: 200px;
}
input[type=submit],
input[type=file]{
cursor: pointer;
font-size: 16px;
font-weight: bold;
height: 35px;
padding: 5px;
}
.avatar_iframe {
border: 2px dashed #000;
margin-top: 25px;
}

/* chat block */
.chat_messages {
border: 1px solid #888;
color: #000;
padding: 10px;
}
.chat_messages a {
color: #000;
}
.chat_messages a img {
margin-right: 10px;
vertical-align: middle;
width: 22px;
}
.chat_messages .message {
background-color: #fff;
margin: 5px;
padding: 5px;

-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.chat_messages .message span {
color: #444;
font-size: 10px;
margin-left: 10px;
}
.chat_submit_form {
margin: 10px 0px;
overflow: hidden;
}
.chat_submit_form .error, .chat_submit_form .success, .chat_submit_form .protect {
display: none;
}
.chat_submit_form .error {
color: #f55;
}
.chat_submit_form .success {
color: #5f5;
}
.chat_submit_form .protect {
color: #55f;
}

/* profiles */
.profiles {
overflow: hidden;
}
.profiles a {
display: block;
}
.profiles div {
overflow: hidden;
}
.profiles div a {
color: #333333;
display: block;
padding: 2px 22px 2px 10px;
position: relative;
}
.profiles div a:hover {
background-color: #E0E4EE;
box-shadow: 2px 0 2px -2px #B2B9C9 inset;
}

.profiles div img {
float: left;
height: 48px;
margin-right: 8px;
width: 48px;
}
.profiles div p {
display: block;
line-height: 48px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.profiles div img.status_img {
display: block;
height: 7px;
margin-top: -6px;
position: absolute;
right: 5px;
top: 50%;
width: 7px;
}

/* customize profile page */
.customizer_buttons #preview, .customizer_buttons #pick {
border: 1px solid #888;
border-radius: 3px 3px 3px 3px;
box-shadow: 2px 3px 3px #888;
height: 40px;
margin-bottom: 10px;
width: 80px;
}

Этап 4 - PHP

Теперь, давайте рассмотрим наш исходный код php. Наш файл index.php был обновлен, и теперь он содержит интересную вещь – скрипт, который периодически обновляет время последнего пребывания авторизованных пользователей (каждые 3 минуты). Это позволит нам узнавать, находится ли пользователь на линии или нет.

Index.php

<?php

// set error reporting 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/Services_JSON.php');
require_once('classes/CMySQL.php'); // including service class to work with database
require_once('classes/CLogin.php'); // including service class to work with login processing
require_once('classes/CProfiles.php'); // including service class to work with profiles

$sErrors = '';
// join processing
if (! isset($_SESSION['member_id']) && $_POST['Join'] == 'Join') {
$GLOBALS['CProfiles']->registerProfile();
}

// login system init and generation code
$sLoginForm = $GLOBALS['CLogin']->getLoginBox();

$sChat = '<h2>You do not have rights to use chat</h2>';
$sInput = '';
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
if ($_GET['action'] == 'update_last_nav') { // update last navigate time
$iPid = (int)$_SESSION['member_id'];
if ($iPid) {
$GLOBALS['MySQL']->res("UPDATE `cs_profiles` SET `date_nav` = NOW() WHERE `id` = '{$iPid}'");
}
exit;
}

require_once('classes/CChat.php'); // including service class to work with chat

// get last messages
$sChat = $GLOBALS['MainChat']->getMessages();
if ($_GET['action'] == 'get_last_messages') { // regular updating of messages in chat
$oJson = new Services_JSON();
header('Content-type: application/json');
echo $oJson->encode(array('messages' => $sChat));
exit;
}

// add avatar
if ($_POST['action'] == 'add_avatar') {
$iAvRes = $GLOBALS['CProfiles']->addAvatar();
header('Content-Type: text/html; charset=utf-8');
echo ($iAvRes == 1) ? '<h2 style="text-align:center">New avatar has been accepted, refresh main window to see it</h2>' : '';
exit;
}

// get input form
$sInput = $GLOBALS['MainChat']->getInputForm();

if ($_POST['message']) { // POST-ing of message
$iRes = $GLOBALS['MainChat']->acceptMessage();

$oJson = new Services_JSON();
header('Content-type: application/json');
echo $oJson->encode(array('result' => $iRes));
exit;
}
}

// get profiles lists
$sProfiles = $GLOBALS['CProfiles']->getProfilesBlock();
$sOnlineMembers = $GLOBALS['CProfiles']->getProfilesBlock(10, true);

// get profile avatar
$sAvatar = $GLOBALS['CProfiles']->getProfileAvatarBlock();

// draw common page
$aKeys = array(
'{form}' => $sLoginForm . $sErrors,
'{chat}' => $sChat,
'{input}' => $sInput,
'{profiles}' => $sProfiles,
'{online_members}' => $sOnlineMembers,
'{avatar}' => $sAvatar
);
echo strtr(file_get_contents('templates/main_page.html'), $aKeys);

Наш следующий обновленный файл – файл просмотра профайла (куда мы добавили код для отображения пользователей в правой боковой панели):

profile.php

<?php

// set error reporting 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/CLogin.php');
require_once('classes/CProfiles.php');

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

if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
if ($_GET['action'] == 'change_color') {
$iRes = $GLOBALS['CProfiles']->changeColor($_GET['color']);
header('Content-Type: text/html; charset=utf-8');
echo ($iRes == 1) ? '<h2 style="text-align:center">New color has been accepted, refresh main window to see it</h2>' : '';
exit;
}
}

$aInfo = $GLOBALS['CProfiles']->getProfileInfo($iPid);

$sName = $aInfo['name'];
$sFName = $aInfo['first_name'];
$sLName = $aInfo['last_name'];
$sAbout = $aInfo['about'];
$sDate = $aInfo['date_reg'];
$sRole = $GLOBALS['CProfiles']->getRoleName($aInfo['role']);
$sAvatar = $GLOBALS['CProfiles']->getProfileAvatar($iPid);
$sCustomBG = ($aInfo['color']) ? 'background-color:#'.$aInfo['color'] : '';

// get profiles lists
$sProfiles = $GLOBALS['CProfiles']->getProfilesBlock();
$sOnlineMembers = $GLOBALS['CProfiles']->getProfilesBlock(10, true);

// draw common page
$aKeys = array(
'{id}' => $iPid,
'{name}' => $sName,
'{fname}' => $sFName,
'{lname}' => $sLName,
'{about}' => $sAbout,
'{datereg}' => $sDate,
'{role}' => $sRole,
'{avatar}' => $sAvatar,
'&#123;custom_styles}' => $sCustomBG,
'{cust_visible}' => ($_SESSION['member_id'] == $iPid) ? '' : 'style="display:none"',
'{profiles}' => $sProfiles,
'{online_members}' => $sOnlineMembers,
);
echo strtr(file_get_contents('templates/profile_page.html'), $aKeys);

Это наш следующий обновленный файл:

classes/CProfiles.php

<?php

define('PROFILE_TIMEOUT', 5); // 5 mins

// Profiles class
class CProfiles {

// constructor
function CProfiles() {
}

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

if ($sUsername && $sEmail && $sPassword) {
// check if already exist
$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `email`='{$sEmail}'");
if ($aProfile['id'] > 0) {
$sErrors = '<h2>Another profile with same email already exist</h2>';
} else {
// generate Salt and Cached password
$sSalt = $this->getRandCode();
$sPass = sha1(md5($sPassword) . $sSalt);

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

// autologin
$GLOBALS['CLogin']->performLogin($sUsername, $sPassword);
}
}
}

// get random code (for salt)
function getRandCode($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 profiles block
function getProfilesBlock($iLim = 10, $bOnlineOnly = false) {
$iPLimit = PROFILE_TIMEOUT;
$sOnlineSQL = ($bOnlineOnly) ? 'AND (`date_nav` > SUBDATE(NOW(), INTERVAL ' . $iPLimit . ' MINUTE))' : '';
$sSQL = "
SELECT `cs_profiles`.*,
if (`date_nav` > SUBDATE(NOW(), INTERVAL {$iPLimit} MINUTE ), 1, 0) AS `is_online`
FROM `cs_profiles`
WHERE `status` = 'active'
{$sOnlineSQL}
ORDER BY `date_reg` DESC
LIMIT {$iLim}
";
$aProfiles = $GLOBALS['MySQL']->getAll($sSQL);

// create list of messages
$sCode = '';
foreach ($aProfiles as $i => $aProfile) {
$sName = ($aProfile['first_name'] && $aProfile['last_name']) ? $aProfile['first_name'] . ' ' . $aProfile['last_name'] : $aProfile['name'];
$sSName = (strlen($sName) > 32) ? mb_substr($sName, 0, 28) . '...' : $sName;
$iPid = $aProfile['id'];
$sAvatar = $this->getProfileAvatar($iPid);

$sOnline = ($aProfile['is_online'] == 1) ? '<img alt="" src="images/online.png" class="status_img" />' : '';
$sCode .= '<div id="'.$iPid.'" title="'.$sName.'"><a href="profile.php?id='.$iPid.'"><img src="'.$sAvatar.'" alt="'.$sName.'"><p>'.$sSName.'</p>'.$sOnline.'</a></div>';
}

$sClass = ($bOnlineOnly) ? 'profiles online_profiles' : 'profiles';
return '<div class="'.$sClass.'">' . $sCode . '</div>';
}

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

// get role name
function getRoleName($i) {
$sRet = 'Ordinary member';
switch ($i) {
case 4:
$sRet = 'Moderator';
break;
case 5:
$sRet = 'Administrator';
break;
}
return $sRet;
}

// get profile avatar block
function getProfileAvatarBlock() {
if ($_SESSION['member_id']) {
$aInfo = $this->getProfileInfo((int)$_SESSION['member_id']);
if (is_array($aInfo) && count($aInfo)) {
$sName = ($aInfo['first_name'] && $aInfo['last_name']) ? $aInfo['first_name'] . ' ' . $aInfo['last_name'] : $aInfo['name'];

$aKeys = array(
'{id}' => $aInfo['id'],
'{image}' => $this->getProfileAvatar($aInfo['id']),
'{name}' => $sName
);
return strtr(file_get_contents('templates/avatar.html'), $aKeys);
}
}
}

function getProfileAvatar($i) {
$sPath = 'data/' . $i . '.jpg';
return (file_exists($sPath)) ? $sPath : 'images/member.png';
}

// add avatar (upload image)
function addAvatar() {
$iPid = (int)$_SESSION['member_id'];
if ($iPid) {
$sFileTmpName = $_FILES['avatar']['tmp_name'];
$sDstFilename = 'data/' . $iPid . '.jpg';

if (file_exists($sFileTmpName) && filesize($sFileTmpName) > 0) {
$aSize = getimagesize($sFileTmpName);
if (! $aSize) {
@unlink($sFileTmpName);
return;
}

$bGDInstalled = extension_loaded('gd');

// resize if GD is installed
if (! $bGDInstalled)
return;

$iWidth = $iHeight = 48; // width and height for avatar image
define('IMAGE_TYPE_GIF', 1);
define('IMAGE_TYPE_JPG', 2);
define('IMAGE_TYPE_PNG', 3);

$gdInfoArray = gd_info();
switch($aSize[2]) {
case IMAGE_TYPE_GIF:
if (! $gdInfoArray['GIF Read Support'] || ! $gdInfoArray['GIF Create Support'])
return;
$vSrcImage = @imagecreatefromgif($sFileTmpName);
break;
case IMAGE_TYPE_JPG:
if (! $gdInfoArray['JPG Support'] && ! $gdInfoArray['JPEG Support'])
return;
$vSrcImage = @imagecreatefromjpeg($sFileTmpName);
break;
case IMAGE_TYPE_PNG:
if (! $gdInfoArray['PNG Support'])
return;
$vSrcImage = @imagecreatefrompng($sFileTmpName);
break;
default:
return;
}
if (! $vSrcImage)
return;

// calculate destination rate and sizes
$fSrcRate = (float)($aSize[0] / $aSize[1]);
$fDstRate = (float)($iWidth / $iHeight);
$fResizeRate = ($fSrcRate > $fDstRate) ? (float)($iWidth / $aSize[0]) : (float)($iHeight / $aSize[1]);
$iDstWidth = (int)($fResizeRate * $aSize[0]);
$iDstHeight = (int)($fResizeRate * $aSize[1]);

if (function_exists('imagecreatetruecolor') && $aSize[2] != IMAGE_TYPE_GIF) {
// resize if need (if size is larger than needed)
if ($aSize[0] > $iWidth || $aSize[1] > $iHeight) {
$vDstImage = imagecreatetruecolor($iDstWidth, $iDstHeight);
$vConvRes = imagecopyresampled($vDstImage, $vSrcImage, 0, 0, 0, 0, $iDstWidth, $iDstHeight, $aSize[0], $aSize[1]);
} else {
$vDstImage = $vSrcImage;
$vConvRes = true;
}
} else { // for old GD versions and for GIF images
if ($aSize[0] > $iWidth || $aSize[1] > $iHeight) {
$vDstImage = imagecreate( $iDstWidth, $iDstHeight );
$vConvRes = imagecopyresized($vDstImage, $vSrcImage, 0, 0, 0, 0, $iDstWidth, $iDstHeight, $aSize[0], $aSize[1]);
} else {
$vDstImage = $vSrcImage;
$vConvRes = true;
}
}

if (! $vConvRes)
return;

$bRes = imagejpeg($vDstImage, $sDstFilename);

// memory cleanup
if ($vDstImage != $vSrcImage) {
imagedestroy($vSrcImage);
imagedestroy($vDstImage);
} else {
imagedestroy($vSrcImage);
}
return ($bRes && file_exists($sDstFilename)) ? 1 : '';
}
}
}

function changeColor($sColor = '') {
$iPid = (int)$_SESSION['member_id'];
$sColor = $GLOBALS['MySQL']->escape($sColor);
if ($iPid && $sColor) {
if (strlen($sColor) == 4) {
$sColor = '00' . $sColor;
}
$sSQL = "
UPDATE `cs_profiles` SET
`color` = '{$sColor}'
WHERE `id` = '{$iPid}'
";
$GLOBALS['MySQL']->res($sSQL);
return 1;
}
return;
}
}

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

Здесь мы обновили функцию getProfilesBlock. Теперь она позволит нам отображать список онлайн-пользователей.

Этап 5 - javascript

js/chat.js

Мы добавили периодическую функцию (для периодического обновления списка пользователей):

updateLastNav = function() {
$.getJSON('index.php?action=update_last_nav', function() {

// refresh last nav time
setTimeout(function(){
updateLastNav();
}, 180000); // 3 mins
});
}
updateLastNav();

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


Завершение

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

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

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

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




















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Январь 2017    »
ПнВтСрЧтПтСбВс
 1
2345678
9101112131415
16171819202122
23242526272829
3031