views:

242

answers:

2

Hi, I will try to explain my problem. I have 4 files index.html, event.js, start.js and form.php.

index.html

<head><script type="javascript/text" src="start.js></script></head>
<html>
<button id="bt" type="button">Click</button>
<div id="test"></div>
</html>

start.js

window.onload=init;
function init(){
document.getElementById("bt").onclick=function(){
getFile('form.php?x='+Math.random()*11, getPHP);
getFile('javascripts/event.js?x='+Math.random()*11,getJS);
}
}
function getFile(source,callFunc){
var xmlHttpR=false;
if (window.XMLHttpRequest)
xmlHttpR=new XMLHttpRequest();
else if (window.ActiveXObject)
xmlHttpR=new ActiveXObject("Microsoft.XMLHttp");
else
alert("Error");
if (xmlHttpR){
xmlHttpR.open("GET",source,true);
xmlHttpR.onreadystatechange=function(){
if (xmlHttpR.readyState==4 && xmlHttpR.status==200){
callFunc(xmlHttpR);
delete xmlHttpR;
xmlHttpR=null;
}
}
}
xmlHttpR.send(null);
}

function getPHP(response){
document.getElementById("test").innerHTML=response.responseText;
}

function getJS(response){
eval(response.responseText);
}

event.js

document.getElementById("firstName").onblur=function(){
validate(this.name,this.value);
}

form.php

<html>
<form>
<input type="text" id="firstName" value="">
</form>
</html>

OK, the problem now, when onblur event is triggered on firstName nothing happens but when I refresh the page sometimes once or twice, the event is working as it should be. Maybe I'm getting the response not at the right time?

Is there something wrong with the callback function and the eval and I use to assign onblur event to the firstName field?

is the problem with the AJAX asynchronous call? Should I use synchronous? What am I missing?

I hope I could explain clearly what the problem is.

Thanks in advance for any help.

A: 

Looks to me like your asynchronous calls are the problem.

You're making two getFile() calls. Since getFile() makes an asynchronous request, the browser will continue through the JavaScript code without waiting for a response (There's a way to force the browser to wait for the response, but I can't think of it right now). So, sometimes when you load the page, #firstName doesn't actually exist until AFTER event.js attempts to make the event binding.

I would suggest that you don't recreate the textbox every time someone clicks the button. Instead, it would be "static" on the page, and your JavaScript would simply check the value and make stylistic changes to show the user that their input does or does not validate.

Jeff Rupert
Thanks for the answer. I also think that the asynchronous calls are the problem and the callFunc is not working as it should be.I want to show the user some info on the index page and when the user clicks the button, he/she will get a form without any page refreshing that's why I'm using AJAX and on-demand javascript to append the event to each input fields.
codemaker
That all makes sense, but I'd suggest dynamically creating things with the JavaScript instead of resending this form repeatedly. If you leave the form in there initially, or even update it dynamically (without removing the #firstName object) you won't have to rebind the event over and over. The only reason you're recalling the js file is to recreate the bind, and that's only happening because the object is being recreated in the DOM.
Jeff Rupert
For testing this, if you set the third parameter of xmlHttpR.open() to false the request will be synchronous (i.e. blocking).
Michiel Kalkman
Sure, I'm going to try that
codemaker
@Michiel: True, but then _every_ request would be synchronous, correct? (I mean, at this point, probably not a big deal, but it could certainly cause some problems if you wanted to have multiple things updating at the same time.)
Jeff Rupert
Yes Michiel, I agree with you because I know that in the future, I'm going to need to have multiple asynchronous calls because that's the point when you use AJAX.
codemaker
@codemaker: Setting the third parameter of xmlHttpR.open() to false will set it so you can only have one open send request at a time. This is how a basic page works. It makes one request to the server and does not do anything until the request is returned. If it is set to true, then you can have multiple requests going at the same time. Asynchronous and synchronous have skewed meanings when it comes to when requests are made.
Jeff Rupert
A: 

yeah, it sounds like a race condition between the asynchronous calls. sometimes the JS returns first and sometimes the PHP returns first.

you could try loading the JS as part of the callback for the PHP ajax call.

something like this should work:

EDIT: pass response through anonymous function and down to getPHP

getFile('form.php?x='+Math.random()*11, function(response) {
    getPHP(response);
    getFile('javascripts/event.js?x='+Math.random()*11,getJS);
});
jonnyheadphones
Thanks, I tried it but It didn't work. I got form.php but It's not shown in the test div and I didn't get event.js. Any ideas?
codemaker
oops, forgot that you need to pass the response to getPHP. that should drop the contents of form.php into div#test.
jonnyheadphones
@jonnyheadphones:It works perfectly. Thanks a lot for the help.
codemaker