views:

533

answers:

5

Hello, my question is the following:

I want to track users that are online at the moment.

The definition of being online is when they are on the index page of the website which has the chat function.

So far, all I can think of is setting a cookie for the user and, when the cookie is found on the next visit, an ajax call is made to update a table with their username, their status online and the time.

Now my actual question is, how can I reliably turn their status to off when they leave the website? The only thing I can think of is to set a predetermined amount of time of no user interaction and then set the status to off.

But what I really want is to keep the status on as long as they are on the site, with or without interaction, and only go to off when they leave the site.

Thanks, Richard

A: 

In the general case, there's no way to know when a user leaves your page.

But you can do things behind the scenes such that they load something from your server frequently while they're on the page, eg. by loading an <iframe> with some content that reloads every minute:

<meta http-equiv="refresh" content="60">

That will cause some small extra server load, but it will do what you want (if not to the second).

RichieHindle
I never used Iframe. So then I would make an update to mysql every minute in the Iframe. And the I frame would I set to hide in the indexpage??
And the user does not see the page refresh off the Iframe??
You could make it show something useful, like "N users online". Then it would be correct that it visibly updated itself.
RichieHindle
A: 

Well, how does the chat function work? Is it an ajax-based chat system?

Ajax-based chat systems work by the clients consistently hitting the chat server to see if there are any new messages in queue. If this is the case, you can update the user's online status either in a cookie or a PHP Session (assuming you are using PHP, of course). Then you can set the online timeout to be something slightly longer than the update frequency.

That is, if your chat system typically requests new messages from the server every 5 seconds, then you can assume that any user who hasn't sent a request for 10-15 seconds is no longer on the chat page.

If you are not using an ajax-based chat system (maybe Java or something), then you can still accomplish the same thing by adding an ajax request that goes out to the server periodically to establish whether or not the user is online.

I would not suggest storing this online status information in a database. Querying the database every couple of seconds to see who is online and who isn't is very resource intensive, especially if this is a large site. You should cache this information and operate on the cache (very fast) vs. the database (very slow by comparison).

Mike
A: 

The question is tagged as "jquery" - what about a javascript solution? Instead of meta/refresh you could use window.setInterval(), perform an ajax-request and provide something "useful" like e.g. an updated "who's online" list (if you consider that useful ;-))

VolkerK
+5  A: 

Full Solution. Start-to-finish.

If you only want this working on the index.php page, you could send updates to the server asynchronously (AJAX-style) alerting the server that $_SESSION["userid"] is still online.

setInterval("update()", 10000); // Update every 10 seconds

function update() {
  $.post("update.php"); // Sends request to update.php
}

Your update.php file would have a bit of code like this:

session_start();
if ($_SESSION["userid"])
  updateUserStatus($_SESSION["userid"]);

This all assumes that you store your userid as a session-variable when users login to your website. The updateUserStatus() function is just a simple query, like the following:

UPDATE users 
SET lastActiveTime = NOW()
WHERE userid = $userid

So that takes care of your storage. Now to retrieve the list of users who are "online." For this, you'll want another jQuery-call, and another setInterval() call:

setInterval("getList()", 10000) // Get users-online every 10 seconds

function getList() {
  $.post("getList.php", function(list) {
    $("listBox").html(list);
  });
}

This function requests a bit of HTML form the server every 10 seconds. The getList.php page would look like this:

session_start();
if (!$_SESSION["userid"])
  die; // Don't give the list to anybody not logged in

$users = getOnlineUsers(); /* Gets all users with lastActiveTime within the
                              last 1 minute */

$output = "<ul>";
foreach ($users as $user) {
  $output .= "<li>".$user["userName"]."</li>";
}
$output .= "</ul>";

print $output;

That would output the following HTML:

<ul>
  <li>Jonathan Sampson</li>
  <li>Paolo Bergantino</li>
  <li>John Skeet</li>
</ul>

That list is included in your jQuery variable named "list." Look back up into our last jQuery block and you'll see it there.

jQuery will take this list, and place it within a div having the classname of "listBox."

<div class="listBox"></div>

Hope this gets you going.

Jonathan Sampson
Great answer !
RichieHindle
Thanks, Richie.
Jonathan Sampson
+1 for using my name as an example and getting it right ;) Only complaint here is setInterval("update()", 10000); would be better written as setInterval(update, 10000); and the same goes for getList.
Paolo Bergantino
(Obviously you'd have to declare the function before hand, though)
Paolo Bergantino
Thanks for the comments, Paolo. What's the benefit over calling "update()" to "update"?
Jonathan Sampson
There's no *benefit* per-se, it's just considered bad practice to use the quote functionality of timeout/interval. It is best to either create an anon function like setTimeout(function() { ... }) or simply pass the function name you want to be called. It's really not a big deal but a few "big names" (Resig, Crockford) don't like it and I agree with them.
Paolo Bergantino
For more, check out this question: http://stackoverflow.com/questions/797115/javascript-settimeout-without-putting-code-into-a-string and this link: https://developer.mozilla.org/en/DOM/window.setTimeout where it says "code in the alternate syntax, is a string of code you want to execute after delay milliseconds. *(not recommended)*"
Paolo Bergantino
Duly-noted. Thanks Paolo.
Jonathan Sampson
A: 

I have not tried this, so take it with a grain of salt: Set an event handler for window.onunload that notifies the server when the user leaves the page. Some problems with this are 1.) the event won't fire if the browser or computer crashes, and 2.) if the user has two instances of the index page open and closes one, they will appear to logout unless you implement reference counting. On its own this is not robust, but combined with Jonathan's polling method, should allow you to have pretty good response time and larger intervals between updates.

James M.