Nickolay.info. 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 Кб)
Файлы в архиве могут несколько меняться по отношению к тексту статьи, например, если "всплывут" какие-то исправления или дополнения.
гостевая; E-mail |