phpBB Part: Forum
[style].container {width:450px;}[/style]
MOD Name: AJAX Chat
MOD Version: 2.0.0 Beta 8
Author: Handyman
MOD Description: This Mod Adds AJAX Chat to your forum.
Users can chat without ever needing to reload the page.
Works with:
- RC7 (install instructions are for prosilver, but subsilver2 is included)
Features:
- AJAX Technology
- No page re-loading required
- Ability for Admins to delete posts in the Chat
- Shows who's online in the Chat
Licence: GNU General Public License v2
Screenshots: See the chat page or index page to see what it looks like.
Installation Level: Easy
Installation Time: ~3 Minutes
Format: MODX
Download File: See File Editor notes below before installing - http://startrekguide.bountysource.com/downloads
File Editor Notes
Make sure, when you edit the language file, that your text editor saves the language file as Unicode (UTF8) and WITHOUT a BOM signature.
If your text editor saves the language file with a BOM signature, you will see an error on your forums.
List of text editors that are capable of saving without BOM signature (this list is small since I just started compiling it)
note: if you are using a Mac, you can use almost any file editor available to you.
- ZEND
- Dreamweaver
- Rapid PHP 2007
Troubleshooting:
- Can't post bbcode or smilies in the chat -- Run the sql statement in the upgrade from beta 7 below.
- Forum header is included in the chat box when I make a post -- this is a problem with a few portals which annoyingly add their header/footer automatically to the template engine.
To fix it, replace the chat_body.html with this (subsilver2 style)Spoiler:- Code: Select all
<!-- IF S_GET_CHAT -->
<!-- IF S_READ or S_ADD -->
--!--
<!-- BEGIN chatrow -->
<div id="p{chatrow.MESSAGE_ID}">
<table class="tablebg" cellspacing="1" width="100%">
<tr>
<td class="<!-- IF chatrow.CLASS is even -->row2<!-- ELSEIF chatrow.CLASS is odd -->row1<!-- ENDIF -->" width="100%" align="left"><!-- IF U_ACP or U_MCP --> <a href="javascript:void({chatrow.MESSAGE_ID})" title="{L_DELETE_POST}" onClick="delete_post('{chatrow.MESSAGE_ID}')"><img src="{T_IMAGESET_LANG_PATH}/icon_post_delete.gif" /></a> <!-- ENDIF --> <b class="postauthor">{chatrow.USERNAME_FULL}</b> « {chatrow.TIME} » <span class="postbody">{chatrow.MESSAGE}</span> </td>
</tr>
</table>
</div>
<!-- END chatrow -->--!--{LAST_ID}
<!-- IF S_WHOISONLINE -->--!--
<!-- BEGIN whoisrow -->
<div><img src="{T_IMAGESET_PATH}/{whoisrow.USER_STATUS}.png" class="online_img" /> {whoisrow.USERNAME_FULL}</div>
<!-- END whoisrow -->--!--{LAST_TIME}--!--{DELAY}--!--{LAST_POST}
<!-- ENDIF -->
<!-- ENDIF -->
<!-- ELSE -->
<!-- IF S_CHAT -->
<!-- INCLUDE overall_header.html -->
<!-- ENDIF -->
<script type="text/javascript">
<!--
var fieldname = 'chat';
var last_time = 0;
var xmlHttp = http_object();
var last_id = {LAST_ID};
var type = 'receive';
var post_time = {TIME};
var read_interval = 15000;
var interval = setInterval('handle_send("read", last_id);', read_interval);
function handle_send(mode, f)
{
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
indicator_switch('on');
type = 'receive';
param = 'mode=' + mode;
param += '&last_id=' + last_id;
param += '&last_time=' + last_time;
param += '&last_post=' + post_time;
param += '&read_interval=' + read_interval;
if (mode == 'add' && document.text.message.value != '')
{
type = 'send';
for(var i = 0; i < f.elements.length; i++)
{
elem = f.elements[i];
param += '&' + elem.name + '=' + encodeURIComponent(elem.value);
}
document.text.message.value = '';
}
else if (mode == 'delete')
{
type = 'delete';
param += '&chat_id=' + f;
}
xmlHttp.open("POST", '{FILENAME}', true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.onreadystatechange = handle_return;
xmlHttp.send(param);
}
}
function handle_return()
{
if (xmlHttp.readyState == 4)
{
if (type != 'delete')
{
results = xmlHttp.responseText.split('--!--');
if (results[2])
{
if (last_id == 0)
{
document.getElementById(fieldname).innerHTML = results[1];
}
else
{
document.getElementById(fieldname).innerHTML = results[1] + document.getElementById(fieldname).innerHTML;
}
last_id = results[2];
if (results[3])
{
document.getElementById('whois_online').innerHTML = results[3];
last_time = results[4];
if (results[5] != read_interval * 1000)
{
window.clearInterval(interval);
read_interval = results[5] * 1000;
interval = setInterval('handle_send("read", last_id);', read_interval);
document.getElementById('update_seconds').innerHTML = results[5];
}
post_time = results[6];
}
}
}
indicator_switch('off');
}
}
function delete_post(chatid)
{
document.getElementById('p' + chatid).style.display = 'none';
handle_send('delete', chatid);
}
function indicator_switch(mode)
{
if(document.getElementById("act_indicator"))
{
var img = document.getElementById("act_indicator");
if(img.style.visibility == "hidden" && mode == 'on')
{
img.style.visibility = "visible";
}
else if (mode == 'off')
{
img.style.visibility = "hidden"
}
}
}
function http_object()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
return new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
document.getElementById('p_status').innerHTML = 'Status: Cound not create XmlHttpRequest Object. Consider upgrading your browser.';
}
}
-->
</script>
<style type="text/css">
<!--
.box
{
width: 100%;
margin-left: auto;
margin-right: auto;
}
.shouts {
width: 100%;
height:300px;
overflow:auto;
}
#chat {
width: 99%;
text-align:left;
}
#message {
width: 65%;
}
#whois_online{
vertical-align:text-top;
text-align:left;
}
.online_img {
vertical-align:middle;
}
#act_indicator {
visibility:hidden;
}
-->
</style>
<div class="box">
<br />
<table class="tablebg" cellspacing="1" width="100%">
<tr>
<td class="cat" width="100%" height="28" nowrap="nowrap">
<h4 align="center">{SITENAME} {L_CHAT_EXPLAIN}</h4>
</td>
</tr>
</table>
<table class="tablebg" cellspacing="1" width="100%">
<tr>
<th align="center" width="85%">
<!-- IF S_USER_LOGGED_IN -->
<form name="text" id="text" method="post" action="javascript:void(0);" onSubmit="handle_send('add', this)" autocomplete="off">{L_MESSAGE}:
<input type="text" tabindex="1" name="message" id="message" class="inputbox" size="28" />
<input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />
</form>
<!-- ENDIF -->
</th>
<th align="center" width="15%" nowrap="nowrap">
{L_ONLINE_LIST}
</th>
</tr>
<tr>
<td class="row3" style="text-align:left;" height="220">
<div class="shouts">
<div id="chat">
<!-- BEGIN chatrow -->
<div id="p{chatrow.MESSAGE_ID}">
<table class="tablebg" cellspacing="1" width="100%">
<tr>
<td class="<!-- IF chatrow.CLASS is even -->row2<!-- ELSE -->row1<!-- ENDIF -->" align="left">
<!-- IF U_ACP or U_MCP -->
<a href="javascript:void({chatrow.MESSAGE_ID})" title="{L_DELETE_POST}" onClick="delete_post('{chatrow.MESSAGE_ID}')"><img src="{T_IMAGESET_LANG_PATH}/icon_post_delete.gif" /></a>
<!-- ENDIF -->
<b class="postauthor">{chatrow.USERNAME_FULL}</b> « {chatrow.TIME} » <span class="postbody">{chatrow.MESSAGE}</span>
</td>
</tr>
</table>
</div>
<!-- END chatrow -->
</div>
</div>
</td>
<td class="row1" width="15%" nowrap="nowrap">
<div class="shouts">
<div id="whois_online">
<!-- BEGIN whoisrow -->
<div>
<img src="{T_IMAGESET_PATH}/{whoisrow.USER_STATUS}.png" class="online_img" /> {whoisrow.USERNAME_FULL}
</div>
<!-- END whoisrow -->
</div>
</div>
</td>
</tr>
<tr>
<td class="cat" colspan="2" width="100%" height="28">
<div style="float: left;"> <img src="{T_THEME_PATH}/images/icon_mini_chat.png"> <a href="http://startrekguide.com/community/viewtopic.php?p=16364#p16364"><strong>AJAX Chat</strong></a> © 2007 <strong style="color: #7B95B2;">StarTrek</strong><strong style="color: #D98303;">Guide</strong></div><div style="float: right;"><img src="{T_IMAGESET_PATH}/act_indicator.gif" id="act_indicator" /> <strong>{L_UPDATES} <span id="update_seconds"> {DELAY} </span> {L_UNIT}</strong> </div>
</td>
</tr>
</table>
</div>
<!-- IF S_CHAT -->
<!-- ENDIF -->
<!-- ENDIF -->
Now for prosilver chat_body fix:Spoiler:<!-- IF S_GET_CHAT -->
<!-- IF S_READ or S_ADD -->
--!--
<!-- BEGIN chatrow -->
<div id="p{chatrow.MESSAGE_ID}" class="post bg{chatrow.CLASS}">
<div class="inner"><span class="corners-top"><span></span></span>
<div class="postbody">
<!-- IF U_ACP or U_MCP -->
<ul class="profile-icons">
<li class="delete-icon"><a href="javascript:void({chatrow.MESSAGE_ID})" title="{L_DELETE_POST}" onClick="delete_post('{chatrow.MESSAGE_ID}')"><span>{L_DELETE_POST}</span></a></li>
</ul>
<!-- ENDIF -->
<div class="content">{chatrow.MESSAGE}</div></div>
<dl class="postprofile" id="profile{postrow.POST_ID}">
<dt>{chatrow.USERNAME_FULL}<br /><b style="font-size: 0.9em;">{chatrow.TIME}</b></dt>
</dl>
<span class="corners-bottom"><span></span></span>
</div>
</div>
<!-- END chatrow -->--!--{LAST_ID}
<!-- IF S_WHOISONLINE -->--!--
<!-- BEGIN whoisrow -->
<div>
<div class="inner">
<div class="user"><img src="{T_IMAGESET_PATH}/{whoisrow.USER_STATUS}.png" class="online_img" /> <span nowrap="nowrap">{whoisrow.USERNAME_FULL}</span></div>
</div>
</div>
<!-- END whoisrow -->--!--{LAST_TIME}--!--{DELAY}--!--{LAST_POST}
<!-- ENDIF -->
<!-- ENDIF -->
<!-- ELSE -->
<!-- IF S_CHAT -->
<!-- INCLUDE overall_header.html -->
<!-- IF S_DISPLAY_SEARCH or (S_USER_LOGGED_IN and not S_IS_BOT) -->
<ul class="forumlinklist">
<!-- IF S_DISPLAY_SEARCH -->
<li><img src="{T_THEME_PATH}/images/icon_pages.gif" alt="" /> <a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a><!-- IF S_USER_LOGGED_IN --> • <img src="{T_THEME_PATH}/images/icon_pages.gif" alt="" /> <a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a><!-- ENDIF --> • <img src="{T_THEME_PATH}/images/icon_topics.gif" alt="" /> <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></li>
<!-- ENDIF -->
</ul>
<!-- ENDIF -->
<!-- ENDIF -->
<script type="text/javascript">
<!--
var fieldname = 'chat';
var last_time = 0;
var xmlHttp = http_object();
var last_id = {LAST_ID};
var type = 'receive';
var post_time = {TIME};
var read_interval = 15000;
var interval = setInterval('handle_send("read", last_id);', read_interval);
function handle_send(mode, f)
{
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
{
indicator_switch('on');
type = 'receive';
param = 'mode=' + mode;
param += '&last_id=' + last_id;
param += '&last_time=' + last_time;
param += '&last_post=' + post_time;
param += '&read_interval=' + read_interval;
if (mode == 'add' && document.text.message.value != '')
{
type = 'send';
for(var i = 0; i < f.elements.length; i++)
{
elem = f.elements[i];
param += '&' + elem.name + '=' + encodeURIComponent(elem.value);
}
document.text.message.value = '';
}
else if (mode == 'delete')
{
type = 'delete';
param += '&chat_id=' + f;
}
xmlHttp.open("POST", '{FILENAME}', true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.onreadystatechange = handle_return;
xmlHttp.send(param);
}
}
function handle_return()
{
if (xmlHttp.readyState == 4)
{
if (type != 'delete')
{
results = xmlHttp.responseText.split('--!--');
if (results[2])
{
if (last_id == 0)
{
document.getElementById(fieldname).innerHTML = results[1];
}
else
{
document.getElementById(fieldname).innerHTML = results[1] + document.getElementById(fieldname).innerHTML;
}
last_id = results[2];
if (results[3])
{
document.getElementById('whois_online').innerHTML = results[3];
last_time = results[4];
if (results[5] != read_interval * 1000)
{
window.clearInterval(interval);
read_interval = results[5] * 1000;
interval = setInterval('handle_send("read", last_id);', read_interval);
document.getElementById('update_seconds').innerHTML = results[5];
}
post_time = results[6];
}
}
}
indicator_switch('off');
}
}
function delete_post(chatid)
{
document.getElementById('p' + chatid).style.display = 'none';
handle_send('delete', chatid);
}
function indicator_switch(mode)
{
if(document.getElementById("act_indicator"))
{
var img = document.getElementById("act_indicator");
if(img.style.visibility == "hidden" && mode == 'on')
{
img.style.visibility = "visible";
}
else if (mode == 'off')
{
img.style.visibility = "hidden"
}
}
}
function http_object()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else if(window.ActiveXObject)
{
return new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
document.getElementById('p_status').innerHTML = 'Status: Cound not create XmlHttpRequest Object. Consider upgrading your browser.';
}
}
-->
</script>
<style type="text/css">
<!--
#act_indicator {
visibility:hidden;
}
.shouts {
width: 84%;
height:328px;
overflow:auto;
float:left;
margin: 8px 0;
}
#chat {
width: 99%;
text-align:left;
}
.postprofile {
min-height: 5px !important;
}
.chatform {
color: white;
width: 96%;
text-align:center;
}
.onlinelist {
width: 16%;
overflow:auto;
height:300px;
}
.users {
width: 90%;
text-align: left;
margin-left:auto;
margin-right:auto;
}
.user {
width: 95%;
font-size: 1.1em;
font-family:Verdana, Arial, Helvetica, sans-serif;
}
#act_indicator {
visibility: hidden;
}
.chatinput {width: 60% !important;}
.online_img {
vertical-align:middle;
}
-->
</style>
<div class="forabg" style="margin-top: 8px;margin-bottom: 0;">
<div class="inner">
<span class="corners-top"><span></span></span>
<div class="header" style="float: left;">
<h4 style="color:white;"> <img src="{T_THEME_PATH}/images/icon_chat.gif" alt="" /> <!-- IF not S_CHAT --><a href="{U_CHAT_LINK}" alt="{L_CHAT_EXPLAIN}" title="{L_CHAT_EXPLAIN}" />{L_CHAT_EXPLAIN}</a><!-- ELSE -->{L_CHAT_EXPLAIN}<!-- ENDIF --></h4>
</div>
<div style="text-align: center;">
<!-- IF S_USER_LOGGED_IN -->
<form name="text" id="text" method="post" action="javascript:void(0);" onSubmit="handle_send('add', this)" autocomplete="off">
<strong style="color: white;">{L_MESSAGE}:</strong> <input type="text" tabindex="1" name="message" id="message" class="inputbox chatinput" />
<input type="submit" class="button1" value="{L_SUBMIT}" name="submit" tabindex="6" accesskey="s"/><br />
</form>
<!-- ELSE -->
<b style="color: white;">You must register to chat and registration is by invite only.</b>
<!-- ENDIF -->
</div>
<span class="corners-bottom"><span></span></span>
</div>
</div>
<div align="left">
<div class="shouts">
<div id="chat">
<!-- BEGIN chatrow -->
<div id="p{chatrow.MESSAGE_ID}" class="post bg{chatrow.CLASS}">
<div class="inner"><span class="corners-top"><span></span></span>
<div class="postbody">
<!-- IF U_ACP or U_MCP -->
<ul class="profile-icons">
<li class="delete-icon">
<a href="javascript:void({chatrow.MESSAGE_ID})" title="{L_DELETE_POST}" onClick="delete_post('{chatrow.MESSAGE_ID}')"><span>{L_DELETE_POST}</span></a>
</li>
</ul>
<!-- ENDIF -->
<div class="content">{chatrow.MESSAGE}</div>
</div>
<dl class="postprofile" id="profile{postrow.POST_ID}">
<dt>{chatrow.USERNAME_FULL}<br /><b style="font-size: 0.9em;">{chatrow.TIME}</b></dt>
</dl>
<span class="corners-bottom"><span></span></span>
</div>
</div>
<!-- END chatrow -->
</div>
</div>
<h4> {L_ONLINE_LIST}:</h4>
<div class="onlinelist">
<div class="users" id="whois_online">
<!-- BEGIN whoisrow -->
<div>
<div class="inner">
<div class="user"><img src="{T_IMAGESET_PATH}/{whoisrow.USER_STATUS}.png" class="online_img" /> <span nowrap="nowrap">{whoisrow.USERNAME_FULL}</span></div>
</div>
</div>
<!-- END whoisrow -->
</div>
</div>
</div>
<div class="forabg">
<div class="inner">
<span class="corners-top"><span></span></span>
<div class="chatform" align="center">
{L_DETAILS} <img src="{T_IMAGESET_PATH}/act_indicator.gif" id="act_indicator" /> <strong>{L_UPDATES} <span id="update_seconds">{DELAY}</span> {L_UNIT}</strong>
</div>
<span class="corners-bottom"><span></span></span>
</div>
</div>
<!-- IF S_CHAT -->
<!-- IF S_DISPLAY_ONLINE_LIST -->
<div style="float: left;"><img src="{T_THEME_PATH}/images/whosonline.gif" alt="" /> </div><!-- IF U_VIEWONLINE --><h3><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h3><!-- ELSE --><h3>{L_WHO_IS_ONLINE}</h3><!-- ENDIF -->
<p style="margin-bottom:4px;">{TOTAL_USERS_ONLINE}<br />{LOGGED_IN_USER_LIST}
<!-- IF LEGEND --><br /><em>{L_LEGEND}: {LEGEND}</em><!-- ENDIF --></p>
<!-- ENDIF -->
<!-- INCLUDE overall_footer.html --> <!-- ENDIF -->
<!-- ENDIF -->
Updated to Beta 8.
To upgrade from Beta 7, copy- Code: Select all
root/adm/mods/ajax_chat_version.php to adm/mods/ajax_chat_version.php
and replace files with new ones from the zip- Code: Select all
root/chat.php to chat.php
root/language/en/chat.php to language/en/chat.php
Database change (run this query)- Code: Select all
ALTER TABLE phpbb_chat CHANGE bbcode_uid bbcode_uid varchar(8) NOT NULL default '';
Notes: this version fixes the issue where you can post if you're not logged in.
Added MOD Version Check file so you can see when the next version is available (also available through the download link)
Roadmap- Add smilies button
- Show smilies in chat room
- Multiple Rooms (Progress = 25%)
- Report Post/Users
- Add Quote Button
- Enable Author Delete
- Private Rooms
- Send Chat Requests
- Reset Chat button
- Avatar Thumbnails with Fullsize Rollovers.
- Chat Logs
Extra languages
Spoiler:
French Translation provided by Dace
Dutch Translation provided by eFantasy
http://startrekguide.com/forum/download.php?id=1564
Swedish Translation provided by [b]KJell
http://startrekguide.com/forum/f27-misc ... tml#p32498
french.txt
Dutch Translation provided by eFantasy
http://startrekguide.com/forum/download.php?id=1564
Swedish Translation provided by [b]KJell
http://startrekguide.com/forum/f27-misc ... tml#p32498
Here's a small add-on to redirect users to the login page if they get logged out during a conversation.
Spoiler:
open chat.php
FIND case 'add':
After, add
save and upload
FIND case 'add':
After, add
- Code: Select all
if (!$user->data['is_registered'])
{
redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'));
}
save and upload
Beta 7 downloaded 7485 times.





