|
Pers.narod.ru. PHP. Простой чат на JQuery |
Мы хотим написать очень простой чат, которому для работы достаточно нескольких килобайт кода и одного файла с данными. Сначала сформулируем требования.
Чего в нашем чате не будет точно:
Тем не менее, вот что нужно даже самому простому чату, как мне кажется:
Всё это нам обеспечит библиотека JQuery, так что необходимости изобретать велосипед нет.
Кратко опишем весь процесс и нужные файлы, начав с менее важных.
Скачав JQuery (не обязательно самый новый, хватит и версии 1.3) положим его в папку чата под именем jquery.js.
Все наши файлы будем сохранять в Юникоде (UTF-8) без BOM, это важно, иначе рискуем получить трудноуловимые ошибки.
Пример такой ошибки -session_start() [function.session-start]: Cannot send session cache limiter - headers already sent
вылезающей, даже если оператор session_start() стоит первым в файле.
А всё банально - файл Юникода с BOM, например, отредактированный Блокнотом Вындоус
Так что для редактирования нам подойдёт Notepad++ (меню Кодировки - Преобразовать в UTF-8 без BOM) ну или встроенный текстовый редактор из Far Manager 2, а вот Блокнот Windows, лепящий BOM куда ни попадя, не подойдёт.
Стиль традиционно будет называться style.css, в общем-то, всё равно, что там, но все размеры для простоты укажем в пикселах, а окно чата (раздел div с именем chatbox) опишем так, чтобы при необходимости обеспечивалась вертикальная прокрутка внутри раздела:
#chatbox {
height:400px;
width:700px;
overflow-x:auto;
overflow-y:scroll;
}
Все сообщения файла будут "лежать" в файле log.html, пока что он пуст и имеет размер 0 байт.
Файл functions.php будет содержать обычные функции для
удаления лишних пробелов и борьбы с кавычками,
а также метод add_in_file для записи в чат нового сообщения,
вызов функции session_start - так как мы собираемся хранить имя пользователя в его сессии,
и код, исполняемый один раз при старте системы.
Вот реализация add_in_file, по правде говоря, ей недостаёт безопасности при работе с "плоским" файлом чата.
function add_in_file ($newstr) {
define ("LOGSIZE","100");
$msgs = file ("log.html");
if ($msgs===false) die ("Нет файла лога, обратитесь к администратору");
else {
if (count($msgs)>0 and $newstr==$msgs[count($msgs)-1]);
else if (count($msgs)>=LOGSIZE) {
$msgs=array_slice ($msgs,-(LOGSIZE-1));
array_push ($msgs, $newstr);
$i=file_put_contents ("log.html",$msgs);
if (!$i) die ("Не могу записать файл лога, обратитесь к администратору");
}
else {
$fp = fopen("log.html", 'a');
fwrite($fp, $newstr);
fclose($fp);
}
}
}
Тем не менее, примитивная защита от флуда тут есть, новая строка сравнивается с последней из лога. Так как строки лежат
в файле уже с меткой времени вида ЧЧ:ММ (это будет видно ниже), то флудить будет таки можно - но только разок в минуту :)
Файл index.php - это весь наш чат. В нём будут следующие разделы:
wrapper - обрамление всего остального;
menu - верх с Вашим именем и ссылкой для выхода;
logout с id="exit" - по ней мы сможем выйти из чата;
chatbox - сообщения чата;
message - для отправки сообщения;
loginform - для входа в чат, выводится вместо всего остального, если мы не в чате.Всё вместе выглядит так:
<?php
if(isset($_POST['name'])){ //Если пользователь вошел в чат
if (trimall($_POST['name'])!='') {
$_SESSION['name']=magic(htmlspecialchars(trimall($_POST['name'])));
add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <i>Пользователь ".
$_SESSION['name']." вошёл в чат</i><br></div>\n");
}
else {
echo '<span class="error">Пожалуйста, введите непустое имя</span>';
}
}
if(!isset($_SESSION['name'])) { //Если не вошли в чат - форма для входа
echo'
<div id="loginform">
<form action="index.php" method="post">
<p>Введите имя, под которым хотите войти:</p>
<label for="name">Имя:</label>
<input type="text" name="name" id="name" maxlength="32"/>
<input type="submit" name="enter" id="enter" value="Войти!" />
</form>
</div>';
}
else { //Иначе - элементы чата
?>
<div id="wrapper">
<div id="menu">
<p class="welcome">Вы вошли как <b><?php echo $_SESSION['name']; ?></b></p>
<p class="logout" align="right"><a id="exit" href="#">Выйти</a></p>
<div style="clear:both"></div>
</div>
<div id="chatbox">
<?php
if (file_exists("log.html") && filesize("log.html")>0) { //Вывести содержимое, если оно есть
$handle = fopen("log.html", "r");
$contents = fread($handle, filesize("log.html"));
fclose($handle);
echo $contents;
}
?>
</div>
<form name="message" id="message" action="" method="post">
<input name="usermsg" type="text" id="usermsg" size="63" maxlength="1024" />
<input name="submitmsg" type="submit" id="submitmsg" value="Сказать" />
</form>
</div>
<?php
}
?>
Сама реализация чата будет включать всего несколько несложных функций на JQuery, вот они целиком:
<script type="text/javascript">
//Собственно чат
$(document).ready(function() {
$("#exit").click(function() { //Если пользователь хочет выйти
if (confirm("Выйти из чата?")==true) { window.location = 'index.php?logout=true'; }
});
$('#message').submit(function(e) { //Если пользователь отправил сообщение
var clientmsg = $("#usermsg").val();
$.post("post.php", {text: clientmsg});
$("#usermsg").attr("value", "");
return false;
});
function loadLog() { //Загрузить лог чата
var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20;
$.ajax ({
url: "log.html",
cache: false,
success: function(html) {
$("#chatbox").html(html); //Автопрокрутка
var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20;
if (newscrollHeight > oldscrollHeight) {
$("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal');
}
}
});
}
//Обновление каждые 2.5с
setInterval (loadLog, 2500);
});
</script>
Здесь тоже есть пара нюансов, например, если написать
$("#submitmsg").click(function()
вместо
$('#message').submit(function(e)
(как часто и делают), то форма не будет отправляться в IE по нажатию Enter, кстати,
если не указать атрибут
id="message"
в теге <form>, а только name="message", скорей всего, тоже не будет. IE "строже" относится к DOM, чем альтернативные браузеры.
Для контроля за выходом юзера добавим блок в самое начало файла - чтобы сообщение о его выходе записалось прежде, чем удалится его сессия.
<?php
require_once ("functions.php");
if (isset($_GET['logout'])) { //Если пользователь покинул чат
add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <i>Пользователь ".
$_SESSION['name']." покинул чат</i><br></div>\n");
session_destroy();
header("Location: index.php");
}
?>
Потом уже выведем заголовок HTML-документа и подключим скрипты.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Simple JQuery Chat</title>
<link type="text/css" rel="stylesheet" href="style.css"/>
<script type="text/javascript">
function copyNick (name) {
document.message.usermsg.value+=name+', ';
document.message.usermsg.focus();
}
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
Маленький скрипт copyNick, думаю, не нуждается в JQuery - он просто будет копировать ник, по которому мы щёлкнули, в строку ввода сообщения.
Остаётся дописать в конце
</body></html>
и обратить внимание, что самая суть чата - вызов из яваскрипта файла post.php, который отвечает за добавление очередного
сообщения:
<?php
require_once ("functions.php");
if (isset($_SESSION['name'])) {
add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <b><a href=\"#\" onClick=\"copyNick('".
$_SESSION['name']."')\">".$_SESSION['name']."</a></b>: ".magic(htmlspecialchars(trimall($_POST['text']))).
"<br></div>\n");
}
?>
Собственно, это всё, осталось посмотреть, что получилось.
Никаких особенных настроек прав мне не потребовалось, просто скопировал файлы на хостинг, права на файл log.html остались 644.
Проверил в текущих версиях Firefox, Opera, Chrome, Internet Explorer 6-7-8 и встроенном браузере на коммуникаторе под Android 2.2.2, вроде бы, работает, и глюков не выявлено. Для работы чата, разумеется, нужен включённый JavaScript, в браузерах, альтернативных ИЕ, работа сессий предполагает также, что включена настройка "Разрешить cookie".
Скачать исходники Simple JQuery Chat в архиве ZIP (23 Кб)
Файлы в архиве могут несколько меняться по отношению к тексту статьи, например, если "всплывут" какие-то исправления или дополнения.
|
|