Просмотр списка сообщений чата (файл Text.asp)

Теперь нам нужно разработать страничку, содержащую все пользовательские сообщения. Она, по сути, должна отображать содержимое соответствующей таблицы нашей базы данных (таблицы Chat). Страничка должна самообновляться каждые Session("RefreshTime") секунд:

 
  <!--#include file="utils.asp"-->
 <html>
 <%
  Response. Write "<META http-equiv='refresh' content='" & CInt(Session("RefreshTime")) & "'>"
 %>
 
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 </head>
 <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
 <%
   Dim MaxLines, Str
   MaxLines = CInt(Session("LNum"))  
  Call Connect  
  sSQL = "SELECT TOP " & CStr (MaxLines) & " * FROM Chat Order By DateSaid DESC"  
   
  Rs.open sSQL, Conn  
   
  Do While Not Rs.Eof  
   Str = Rs.Fields("Said").value  
   Response.Write  Str  
   Rs.MoveNext  
  Loop      
   
  Response.Write "<br>"  
   
  Call Close  
%>  
   
</body>  
</html>  
В начало В начало

Посылка сообщения в чат (файл Chat.asp)

Теперь нам потребуется страничка посылки сообщений в чат. Для этого понадобится HTML-форма с текстовым полем ввода сообщения, парой кнопок и «радиопереключателем» смайликов к сообщениям. Последние лежат в каталоге Images к исходникам настоящей статьи. После нажатия пользователем на кнопку «Сказать» необходимое сообщение, обрамленное соответствующими тэгами (цвет, смайлик) попадет в базу данных.

<!--#include file="utils.asp"-->
 <SCRIPT LANGUAGE = VBScript RUNAT=Server>
  <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->  
</SCRIPT>
 <%
  Dim TextStr, ImageFileName
  Session.TimeOut = 1
   If Session("UserName") <> "" Then
     Response.Write "Пользователь: " & Session("UserName") & "<br>"
   Else
     Response.Write "Вы покинули чат. <br>"
   End If
   If Request("go") = "Войти" Then
    Response.Redirect("Entrance.asp")
   End If
   If Request("exit") = "Выйти" Then
     TextStr = "<table><tr><td><b><font color='" & Session("UserColor") &_
               "'>" & Session("UserName") & "</font></B> : " &_
               "покинул чат - " & date & " " & time & "</td></tr></table>"
     Call Connect()
     sSQL = "SELECT * FROM Chat"
     RS.Open sSQL, Conn, 3, adLockOptimistic
 
     rs.AddNew
     rs("UserID") = 0
     rs("DateSaid") = Now()
     rs("Said") = TextStr
     rs.Update
     Call Close()
 
     Call Connect()
     sSQL = "UPDATE ChatUsers Set IsOnLine = 0 WHERE UserID = " & Session("UserID")
     Conn.Execute(sSQL)
     Conn.close
     set Conn = nothing
     Session("UserName") = ""
     Session("UserID") = 0
     End If
 %>
 
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 </head>
 <script>
 function ReEnter()
 {
  window.navigate("Entrance.asp");
 }
 </script>
 
 <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
 <%
  TextStr = Trim (Request.Form("txtbox"))
  If InStr(TextStr, "<") < 1 Then
    If TextStr <> "" Then
       Select Case CInt(Request.Form("MsgIcon"))
         Case 0  'Smile
           ImageFileName = ""
         Case 7  'Smile
           ImageFileName = "Images\icon7.gif"
         Case 2  'Smile
           ImageFileName = "Images\icon2.gif"
         Case 3  'Smile
           ImageFileName = "Images\icon3.gif"
         Case 4  'Smile
           ImageFileName = "Images\icon4.gif"
         Case 5  'Smile
           ImageFileName = "Images\icon5.gif"
         Case 6  'Smile
           ImageFileName = "Images\icon6.gif"
         Case 8  'Smile
           ImageFileName = "Images\icon8.gif"
         Case 9  'Smile
           ImageFileName = "Images\icon9.gif"
         Case 10  'Smile
           ImageFileName = "Images\icon10.gif"
         Case 11  'Smile
           ImageFileName = "Images\icon11.gif"
         Case 12  'Smile
           ImageFileName = "Images\icon12.gif"
         Case 13  'Smile
           ImageFileName = "Images\icon13.gif"
         Case 14  'Smile
           ImageFileName = "Images\icon14.gif"
       End Select
 
       TextStr = Replace(TextStr, vbCrLf, "<br>")
       If (ImageFileName <> "") Then
          TextStr = "<table><tr><td width=15 valign='top'><img src = '" & _
                         ImageFileName & "'></td>" &_
                    "<td width=70 valign='top'><B><font color = '" & Session("UserColor") &_
                    "'>" & Session("UserName") & "</td><td>" &_
                    "</font></B>" & " : " & TextStr & "</td></tr></table>"
       Else
          TextStr = "<table><tr><td width=15 valign='top'></td>" &_
                    "<td width=70 valign='top'><B><font color = '" & Session("UserColor") &_
                    "'>" & Session("UserName") & "</td><td>" &_
                    "</font></B>" & " : " & TextStr & "</td></tr></table>"
       End If
 
      Call Connect()
       sSQL = "SELECT * FROM Chat"
       RS.Open sSQL, Conn, 3, adLockOptimistic
       rs.AddNew
       rs("UserID") = Session("UserID")
       rs("DateSaid") = Now()
       rs("Said") = TextStr
       rs.Update
       Call Close()   
       Application("IsRefresh") = True
    End If
  End If
 %>
 
 <FORM name= "ChatForm" method="post" action="chat.asp">
  <table>
   <tr>
  <td valign="top" align="right">
    <INPUT type="radio" name="MsgIcon" value="0" CHECKED>нет&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="10"><IMG SRC="Images/icon10.gif" alt="улыбка" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="11"><IMG SRC="Images/icon11.gif" alt="возмущение" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="12"><IMG SRC="Images/icon12.gif" alt="подмигивание" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="13"><IMG SRC="Images/icon13.gif" alt="плохо" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="14"><IMG SRC="Images/icon14.gif" alt="хорошо" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="2" ><IMG SRC="Images/icon2.gif"  alt="поговорим" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
   <BR>
    <INPUT type="radio" name="MsgIcon" value="3" ><IMG SRC="Images/icon3.gif"  alt="лампочка" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="4" ><IMG SRC="Images/icon4.gif"  alt="внимание" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="5" ><IMG SRC="Images/icon5.gif"  alt="вопрос" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="6" ><IMG SRC="Images/icon6.gif"  alt="радость" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="7" ><IMG SRC="Images/icon7.gif"  alt="одобрение" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="8" ><IMG SRC="Images/icon8.gif"  alt="раздражение" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <INPUT type="radio" name="MsgIcon" value="9" ><IMG SRC="Images/icon9.gif"  alt="грусть" HEIGHT=15 WIDTH=15 ALIGN=ABSCENTER>&nbsp;&nbsp;
    <BR>
   </td>
   <td>
     <textarea cols="56" rows="5" style="font: 8pt 'Verdana'; background-color: #FCFBE8;" value="" name="txtbox"></textarea>
   </td>
   <td valign="top">
     <table><tr><td>
 <%  If Session("UserName") <> "" Then %>
      <Input type = Submit Style="font: 8pt 'Verdana'; Width: 65" value="Сказать" name="go">
      </td></tr>
      <tr><td>
      <Input type = Submit Style="font: 8pt 'Verdana'; Width: 65" value="Шепнуть" name="whisper">
      </td></tr>
      <tr><td>
      <Input type = Submit Style="font: 8pt 'Verdana'; Width: 65" value="Выйти" name="exit">          
     </form>
 <%  Else %>
      </form>
      <form method="post" action="chat.asp" target="_top">
       <Input type = Submit Style="font: 8pt 'Verdana'; Width: 55" value="Войти" name="go" Onclick="ReEnter()";>
 
  </form>
 <%  End If %>
  </td></tr></table>
  </td>  </tr> </table>
 </body>
 </html>  

Как видите, все довольно просто; в результате у нас получился инструмент ввода сообщений в чат. Нам осталось только разработать страничку, аналогичную Text.asp, но показывающую не текстовые сообщения, а список псевдонимов (кто в чате), и упорядочить все страницы проекта с помощью фреймов.

В начало В начало

Показ псевдонимов (кто в чате) — файл Nicks.asp

Все делается аналогично страничке Text.asp: самообновление страницы, показ списка пользователей. Здесь нет ничего сложного, и нам необходимо просто извлечь из таблицы пользователей список имен-псевдонимов тех, кто в чате, и показать его:

 
 <!--#include file="utils.asp"-->
 <html>
 <%
  Response. Write "<META http-equiv='refresh' content='" & CInt(Session("RefreshTime")) & "'>"
 %>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 </head>
 
 <body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
 <p><b>Сейчас в чате:</b></p>
 
 <%
  Dim CurUser, Odd, Str, Who, Umail
   CurUser = 0
   Odd = 0
   Call Connect  
  sSQL = "SELECT * FROM ChatUsers WHERE IsOnline = 1"  
   
  Response.Write "<table>"  
   
  Rs.open sSQL, Conn  
   
  Do While Not rs.EOF  
    If Odd = 0 Then  
      If Rs.Fields("UserNickName").value <> "" Then  
        Who = Rs.Fields("UserName").value   
        UMail = Rs.Fields("UserMail").value   
        Str = "<tr><td><font color=" & Session("UserColor") & ">["  
        Str = Str & "<A HREF='mailto:" &  UMail & "'>"  
        Str = Str & "<font color=" & Session("UserColor") & ">" & Rs.Fields("UserNickName").value & "</font>"  
        Str = Str & "</a>]</font></td></tr>"    
          
        Response.Write Str  
        Odd = 1  
        CurUser = CurUser + 1  
      End If  
    Else  
      Odd = 0  
      Rs.MoveNext  
    End If  
  Loop      
   
  Response.Write "</table>"  
   
  If CurUser = 0 Then  
    Response.Write "<p>нет пользователей</p>"  
  Else  
    Response.Write "<p>Всего " & CurUser & "</p>"  
  End If  
   
  Call Close  
%>  
   
</body>  
</html>  
В начало В начало

Немного об оформлении

Теперь нам надлежит оформить одну страницу из трех (Chat.asp, Nicks.asp и Text.asp) с помощью фреймов. Для начала создадим вертикальный фрейм:

<%@ LANGUAGE = VBScript%>
 <%
  If Session("UserName") = "" Then
   Response.Redirect("Entrance.asp")
  End If
 %>
 
 <HTML>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 <TITLE> Чат</TITLE>
 </head>
 
 <Frameset frameborder="NO" border="0" framespacing="0" rows="80%, 19%, 1%">
  <frame name="textFrame" src="RightFS.asp">
  <frame name="chatFrame" src="chat.asp">
  <frame name="FalseFrame" src="FF.asp">
 </Frameset>
 </HTML>  

затем представим горизонтальный фрейм следующим образом:

<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 </head>
 
 <frameset cols="85%,15%" frameborder="YES" border="1" framespacing="0">
   <frame name="mainFrame" src="text.asp">
   <frame name="rightFrame" src="Nicks.asp">
 </frameset>
 
 <noframes>
 <body bgcolor="#FFFFFF" text="#000000">
 </body>
 </noframes>
 </html>  
В начало В начало

И еще об одной немаловажной проблеме…

Если помните, в предыдущей версии чата (в его файл-основанной версии) задача перевода пользователя в режим офлайн не была решена. Точнее, была предпринята попытка ее решения с использованием соответствующей функции файла global.asa. Теперь мы будем делать это гарантированно, ведь пользователь может покинуть чат, не нажав кнпоку выхода (в этом случае система получает сигнал о том, что необходимо выставить соответствующее значение флажка режима пользователя). В случае же непредсказуемого  выхода (переход по другому адресу или закрытие окна браузера) таким сигналом может служить лишь сообщение, получаемое при наступлении соответствующего события непосредственно в браузере. Для этой цели в тэг <body> html-документа можно вставить следующий код:

<body onunload="open('term.asp');self.close()"> 

который, как вы видите, во-первых, инициализует выполнение функций выхода в модуле “term.asp”, а во-вторых — приводит к закрытию окна, породившего само событие (директива self.close()).

Однако в нашем случае ситуация несколько усложняется наличием фреймов. Поэтому, как вы, наверное, заметили, при оформлении набора фреймов умышленно был создан скрытый фрейм «FalseFrame», который специально предназначен для решения этой проблемы и исходный текст модуля которого выглядит следующим образом:

<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
 </head>
 
 <script Language="JavaScript">
 var timerID = null;
 var timerRunning = false;
 
 function stopclock () {
 if (timerRunning)
                 clearTimeout(timerID);
                 timerRunning = false;
 }
 
 function showtime () {
                 var now = new Date();
                 var hours = now.getHours();
                 var minutes = now.getMinutes();
                 var seconds = now.getSeconds()
                 var timeValue = "" + ((hours >12) ? hours -12 :hours)
                 timeValue += ((minutes < 10) ? ":0" : ":") + minutes
                 timeValue += ((seconds < 10) ? ":0" : ":") + seconds
                 timeValue += (hours >= 12) ? " дня" : " утра"
                 window.status = "Время на сервере: " + timeValue;
                 timerID = setTimeout("showtime()",1000);
                 timerRunning = true;
 }
 
 function startclock () {
                 stopclock();
                 showtime();
 }
 </script>
 
 <body onLoad="startclock()" onunload="open('term.asp');self.close()" bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">
 </body>
 </html>  

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

Завершение сеанса работы при выходе пользователя (файл term.asp)

Теперь нам осталось разобраться с действиями, которые должен выполнять пользователь, покидая чат-систему, если он не воспользовался кнопкой выхода:

<!--#include file="utils.asp"-->
 <SCRIPT LANGUAGE = VBScript RUNAT=Server>
  <!-- Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->
 </SCRIPT>
 <html>
 <body onLoad = "self.close()">
 <%
    Dim TextStr
    TextStr = "<table><tr><td><b><font color='" & Session("UserColor") &_
               "'>" & Session("UserName") & "</font></B> : " &_
               "вышел из чата - " & date & " " & time & "</td></tr></table>"
 
     Call Connect()
     sSQL = "SELECT * FROM Chat"
     RS.Open sSQL, Conn, 3, adLockOptimistic
 
     rs.AddNew
     rs("UserID") = 0
     rs("DateSaid") = Now()
     rs("Said") = TextStr
     rs.Update
 
     Call Close()
     Call Connect()
     sSQL = "UPDATE ChatUsers Set IsOnLine = 0 WHERE UserID = " & _
                     Session("UserID")
     Conn.Execute(sSQL)
     Conn.close
     set Conn = nothing
 %>
 </body>
 </html>  
В начало В начало

Заключение

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

 

С автором статьи можно связаться по следующему адресу: rouben@iname.com

КомпьютерПресс 8'2001