PHP / JS / AJAX help required please

Hi all,
I’m pretty new to this coding lark but managed to wangle some code together (copy & paste for the win!) however, I’ve discovered something strange I was hoping some JS guru could help with?

If you visit my webpage http://badgerfruit.homeip.net/test.php you will see two links “Home Page” and “Album”.

Hovering the mouse over these links should draw up a 300x300px “preview” of the page you’re hovering over.

You will notice that the first time you hover over a link, you get a blank, grey preview box. Hover over another link and the ORIGINALLY hovered preview will be displayed.

I guess this is because the <span> tag I have populated updates when it should but the code is displaying what was in there BEFORE it loads the new content into it.

I apologise as it’s a bit difficult to explain but if you follow the URL above, you will be able to see for yourself.

I have tried

  • adding a delay in AFTER the “showHint” function is run, this did not work, instead, it just delayed the rest of the functions called onmouseover
  • adding multiple <span>s but the behaviour repeats (as in, first mouseover shows nothing but subsequent ones do)

The code was swiped from w3schools’ AJAX tutorial and the popup “preview” was found at Web Development, JavaScripts for Download

The code for test.php is shown below


<html>
<head>
<LINK REL=stylesheet HREF="/style.css" TYPE="text/css">
<script language=javascript>
<!--

function GetXmlHttpObject()
{
var xmlHttp=null;
try
  {
  xmlHttp=new XMLHttpRequest();
  }
catch (e)
  {
  try
    {
    xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
  catch (e)
    {
    xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
return xmlHttp;
}

function showHint(str)
{
if (str.length==0)
  { 
  document.getElementById("txtHint").innerHTML="";
  return;
  }
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null)
  {
  alert ("Your browser does not support AJAX!");
  return;
  } 
var url=str;
xmlHttp.onreadystatechange=stateChanged;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}

function stateChanged() 
{ 
if (xmlHttp.readyState==4)
{ 
document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
}

}

//-->
</script>
</head>
<body>
<script type="text/javascript" src="wz_tooltip.js"></script>
<span id="txtHint"></span>
<a href="index.php" onmouseover="showHint('index.php'); TagToTip('txtHint',FADEIN,000,DELAY,000,WIDTH,300,HEIGHT,300,BORDERCOLOR,'#FF0000',TITLE,'Page preview') " onmouseout="UnTip()">Home page </a><br>
<a href="/album/index.php" onmouseover="showHint('/album/index.php'); TagToTip('txtHint',FADEIN,000,DELAY,000,WIDTH,300,HEIGHT,300,BORDERCOLOR,'#FF0000',TITLE,'Page preview'); return; " onmouseout="UnTip()">Photo Album</a>
</body>
</html>

If anyone can help I will be eternally grateful!

You are sending an asynchronous HTTP request but if you expect the element to be populated by the returned data, you have to wait for it to complete. I don’t see where in your JS code you wait for this to happen while the mouse is on the link.

Is that not taken care of with the last function


function stateChanged() 
{ 
if (xmlHttp.readyState==4)
{ 
document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
}

?

As far as I can see that callback function does is fill in the element, but you may have already called TagToTip, no? Shouldn’t you hold off calling TagToTip until the element has been filled in?

Well, herin lies the problem.
HOW?!

Like I said, I tried adding a crude ‘wait(numofsecs)’ function but it just delayed the whole script :\

ie

showHint(‘index.php’); waiton(numofsecs); TagToTip …

It seems as if after the JS has run (and displayed the TagToTip) but the <SPAN> is only populating AFTER the TagToTip has run?

Well you’ll have to not return from the function until the reply has come back. I believe for example JS has a function for executing a function every so often so you could use something like that to poll and see if the reply has come in.

ha har, thanks for the effort ken, just managed to figure it out (all on my own, yay!)

it was a lot simpler then i first thought; move the TagToTip function call into the stateChanged function!

New code is now


function stateChanged() 
{ 
if (xmlHttp.readyState==4)
{ 
document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
TagToTip('txtHint',FADEIN,4000,DELAY,2000,WIDTH,300,HEIGHT,300,BORDERCOLOR,'#FF0000',TITLE,'Page preview');
document.getElementById("txtHint").innerHTML="";
}
}

Bish bash bosh, works as i’d hoped :smiley:

Silly boy. You wrote something in JS to do background HTTP requests a few months ago and you’ve forgotten already.

The simplest way is just to make a synchronous request.

req.open('GET', url + "?" + params, false);

It’s that last parameter. False means not asynchronous, i.e. synchronous. When sychronous, the send will not return until the reply has been received. At that point you can then copy the data into the element and call TagToTip.