I wrote a little chat plugin that i'll need to use on my site. It works with a simple structure in HTML, like this:
<div id="div_chat">
<ul id="ul_chat">
</ul>
</div>
<div id="div_inputchatline">
<input type="text" id="input_chatline" name="input_chatline" value="">
<span id="span_sendchatline">Send</span>
</div>
There's a 'click' bound event on that Span element, of course. Then, when the user inserts a message and clicks on the "Send" span element, there's a Javascript function with calls an Ajax event that inserts the message into the MySQL database:
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
function_get_newchatlines();
}
});
}
And, in case the message is successfully inserted into DB, it calls a function to read new lines and put them in HTML structure i posted before:
function function_get_newchatlines()
{
$.ajax
({
type: "POST",
url: "ajax-chat-loadnewlines.php", //1: ok, 0: errore
data: '',
dataType: "text",
cache: false,
success: function(ajax_result) //example of returned string: 'message1>+<message2>+<message3'
{
//explode new chat lines from returned string
var chat_rows = ajax_result.split('>+<');
for (id_row in chat_rows)
{
//insert row into html
$('#ul_chat').prepend('<li>' + chat_rows[id_row] + '</li>');
}
$('#span_sendchatline').html('Send');
}
});
}
Note: 'ajax_result' only contains html entities, not special chars, so even if a message contains '>+<', it is encoded by the php script called with Ajax, before being processed from this JS function.
Now, comes the strange behaviour: when posting new messages Opera, Firefox and even IE8 works well, as intended, like this:
But, when i open Chrome window, i see this:
As you can see, in Chrome the messages are shown multiple times (increasing the number each time, up to 8 lines per message). I checked the internal debug viewer and it doesn't seem that the "read new lines" function is called more than one time, so it should be something related to Jquery events, or something else.
Hope i've been clear in my explanation, should you need anything else, let me know :)
Thanks, Erenor.
EDIT
As pointed out by Shusl, i forgot to mention that the function function_get_newchatlines()
is called, periodically, by a setInterval(function_get_newchatlines, 2000)
into Javascript.
EDIT2
Here's is a strip of the code from the PHP file called by Ajax to get new chat lines (i don't think things like "session_start()" or mysql connection stuff are needed here)
//check if there's a value for "last_line", otherwise put current time (usually the first time a user logs into chat)
if (!isset($_SESSION['prove_chat']['time_last_line']) || !is_numeric($_SESSION['prove_chat']['time_last_line']) || ($_SESSION['prove_chat']['time_last_line'] <= 0))
{
$_SESSION['prove_chat']['time_last_line'] = microtime(true);
}
//get new chat lines
$result = mysql_query("select * from chat_module_lines where line_senttime > {$_SESSION['prove_chat']['time_last_line']} order by line_senttime asc; ", $conn['user']);
if(!$result || (mysql_num_rows($result) <= 0))
{
mysql_close($conn['user']); die('2-No new lines');
}
//php stuff to create the string
//....
die($string_with_chat_lines_to_be_used_into_Javascript);
Anyway, i think that, if the problem was this PHP script, i would get similar errors in other browsers, too :)
EDIT4
Here's the code that binds the click event to the "Send" span element:
$('#span_sendchatline').on('click', function()
{
//check if there's already a message being sent
if ($('#span_sendchatline').html() == 'Send')
{
//change html content of the span element (will be changed back to "send"
//when the Ajax request completes)
$('#span_sendchatline').html('Wait..');
//write new line
function_write_newchatline();
}
//else do nothing
});
(Thanks to f_puras for adding the missing tag :)
I would do one of the following:
option 1:
stop the timer just before the ajax call in function_write_newchatline() and start the timer when the ajax call returns.
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
stop_the_timer();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
function_get_newchatlines();
},
complete: function() {
start_the_timer();
}
});
}
option 2:
Not call function_get_newchatlines() at all in the success event of the ajax call. Let only the timer retrieve the chat entries.
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
// do nothing
}
});
}
I think there is some race condition between the function_get_newchatlines() that is called after a chat entry is added by the user and the periodical call of function_get_newchatlines() by the timer.
option 3:
Use setTimeout instead of setInterval. setInterval can mess things up when the browser is busy. So in the end of the setTimeout function call setTimeout again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With