Browser coding in general, and Ajax specifically, is fraught with timing issues, and this is one case in which I added some code to allow for them. After setting the contents of the div with the error message, I then check to make sure that the div's contents are actually what I just them to be. On rare occasions, such as when the page hasn't actually finished loading, they aren't! In that case, I just let the cycle continue, hoping things will work the next time through.
Warning! The next line of code is quite important, and before adding it I had people complaining that their entire computer systems were hanging up while editing articles. I couldn't reproduce the problem, but after digging in, I finally figured it out. Internet Explorer doesn't release the memory used by these "req" ActiveX objects, instead letting them pile up, 4K or so at a time. Eventually, Internet Explorer is using so much memory that it hangs, and when Internet Explorer hangs, problems for your Windows system are sure to follow. Bizarrely, you can't just set the event value to null, but must set it to an empty function! With req.onreadystatechange = new function(){}; in place, Internet Explorer manages memory a bit more reasonably, without any growth over time.
PHP
<? require('../includes/connect.php');
$interval=130; # Seconds
$entry_id=$_REQUEST['eid'];
$editor_id=$_REQUEST['aid'];
$checkq="SELECT workflow_created_by,workflow_created_on,
NOW()-INTERVAL $interval SECOND,workflow_closed_on,author_name,NOW()
FROM mt_workflow,mt_author WHERE workflow_created_by=author_id
AND workflow_entry_id=$entry_id AND workflow_type=1";
$clearq="DELETE FROM mt_workflow WHERE workflow_entry_id=$entry_id
AND workflow_type=1";
$reserveq="INSERT INTO mt_workflow VALUES (0,$entry_id,$editor_id,1,NULL,
$editor_id,NOW(),NULL,NOW())";
$refreshq="UPDATE mt_workflow SET workflow_closed_on=NOW(),
workflow_created_by=$editor_id WHERE workflow_entry_id=$entry_id
AND workflow_type=1";
$rslt=mysql_fetch_row(mysql_query($checkq));
if($rslt[0]){
if($rslt[0]==$editor_id){
# Me!
$rslt=mysql_query($refreshq) or die(mysql_error());
echo 'OK';
exit;
}
if(Date("Y-m-d-H-i",strtotime($rslt[3]))>=Date("Y-m-d-H-i",strtotime($rslt[2]))){
# Locked
echo 'This article has been locked by '.$rslt[4].' since '.$rslt[1].'.<br/>
(Server time is now '.$rslt[5].', and '.$rslt[4].
' was last seen at '.$rslt[3].'. Any contact within the last '.
$interval.' seconds is considered current.)<br/>
In order to ensure that editing changes are not lost, you will need to
refresh this page in order to edit this article. And, of course, '.$rslt[4].
' will need to be done with it!';
}else{
# Old, so me!
$rslt=mysql_query($clearq) or die(mysql_error());
$rslt=mysql_query($reserveq) or die(mysql_error());
echo 'OK';
}
}else{
# Nothing, so me!
$rslt=mysql_query($reserveq) or die(mysql_error());
echo 'OK';
}
?>
This is the code called as /mt/keepalive.php from the javascript. After ensuring that I can get to the mysql database and gathering my variable, I build a few queries, not knowing yet which ones I'll need. I then execute one, which is this:
SELECT workflow_created_by,workflow_created_on,NOW()-INTERVAL $interval SECOND,workflow_closed_on,author_name,NOW() FROM mt_workflow,mt_author WHERE workflow_created_by=author_id AND workflow_entry_id=$entry_id AND workflow_type=1
The table 'mt_workflow' is something I created, and tracks a couple of other things in addition to editing concurrency; hency workflow_type. In this case, I should end up with information about the last person seen editing the article, if any.







Article comments
1 - Aaman
I wish that Ajax book was cheaper:)
Incidentally, is this true AJAX, does the reliance on PHP and SQL not mean a new paradigm, not reliant on XML?
2 - Phillip Winn
It's still XMLHttpRequest, so all three elements of AJAX are present. The PHP and Mysql are, I think, incidental. It could as easily be anything else, or an external webservice, on the "back end."