PDA

View Full Version : Javascript Error in FF3 and not FF2 (?)



Strangeplant
10-23-2008, 03:40 PM
Hi,

I'm using an Ajax syncronous call, and things work in FF2, but no longer in FF3. The problem is that global variables no longer work inside functions that are returned to onreadystatechange, and only that.

I have this line:
httpRequest.onreadystatechange = function() { imagexists(httpRequest); };
and the imagexists function is this:
function imagexists(httpRequest) {
if(httpRequest.readyState == 4) {
if(httpRequest.status == 200){
// file exists
nB=0;
}
else{
// file doesn't exist
nB=1;
}
}
else {
nB=1;
}
}
Way up at the top of the javascript, clearly outside the functions, I set several global variables, and one of them is nB. When I add an alert statement, the variable nB is changed correctly in FF2, but not in FF3. What gives? Doesn't work with a number, text value, array or boolean. The only thing I have not tried yet is to define a hidden form field so I can assign it to a DOM object. This worked fine in 2006, 2007 but not with FF3 in 2008, but does work with the current FF2 (2.0.0.17) Unfortunately, this is on several secure, password accessed pages. Advice?

jscheuer1
10-23-2008, 04:11 PM
You may need to define:


function imagexists(httpRequest) {
if(httpRequest.readyState == 4) {
if(httpRequest.status == 200){
// file exists
nB=0;
}
else{
// file doesn't exist
nB=1;
}
}
else {
nB=1;
}
}

like (at least within the scope in which it is used - globally would be OK if need be, though not optimal):


var imagexists = function(httpRequest) {
if(httpRequest.readyState == 4) {
if(httpRequest.status == 200){
// file exists
nB=0;
}
else{
// file doesn't exist
nB=1;
}
}
else {
nB=1;
}
}

And you may also need to specifically define nB in the global scope, by doing:


var nB;

somewhere in the global scope, if you haven't already.

However, putting anything in the global scope other than just one hook to your code is rarely required, sometimes nothing is needed in the global scope. In any case, when defining anything, it is best to define it in as limited a scope as possible - so it will be available where needed, but not at any level above that.

Strangeplant
10-23-2008, 07:12 PM
Won't work that way. For the readystatechange function to be registered successfully, it doesn't look like it can be assigned to a variable because then the httprequest variable would have to be global. That can't be done because to avoid a race condition (I'm retrieving a bunch of requests, one after another, and therefore must do it syncronously, not async) the httprequest var must be local. In any case, I've tried to put the var declaration you wrote out in a variety of places, and the httprequest seems to always be undefined, even if I put it in the middle of the higher level function, right after httpRequest = new XMLHttpRequest();

So, Twey, I just solved it a different way, thanks to you triggering something in my thinking while on my way to get lo mein takeout. This whole exercise points out that the function assigned to the readystatechange is practically useless for anything else - all coding involving variable assignment must be done outside this function. The possible exception would be DOM assignments. I have this working to trim an array of links depending on whether or not the files exist:
for (m=imagetotl-1;m>=3;m--) {
nB = testExists(imagelink[m]);
if(nB) {
imagetotl--;
for (n=m;n<=imagetotl+1;n++) {
imagelink[n]=imagelink[n+1];
}
}
}And the file test function is:
function testExists(imagepath) {
var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
if (httpRequest.overrideMimeType) {
httpRequest.overrideMimeType('text/xml');
// See note below about this line
}
}
else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}

if (!httpRequest) {
alert('Oops, major XMLHTTP error');
return false;
}
httpRequest.onreadystatechange = function() { imagexists(httpRequest); };
httpRequest.open("HEAD", imagepath, false);
httpRequest.send(null);
if(httpRequest.status == 200) {
return nB=0;
} else {
return nB=1;
}
}The object open is set to 'false' instead of the usual AJAX 'true' because I must wait until I get a response back from the server, otherwise the requests get mixed up because the browser will fire off another request before the server responds with the status of the current request. I have to test the request status here because I can't pass it from the function below as a variable anymore.

And, finally the important function to register the onreadystatechange property of the request object, but is not useful for assigning variables based on the request object status :
function imagexists(httpRequest) {}

I hope this helps someone else to do the same kind of things that I have to do.....

BTW, the Mozilla man page on this at http://developer.mozilla.org/en/AJAX/Getting_Started
doesn't mention this and implies that you can do what you can't do.

jscheuer1
10-23-2008, 08:43 PM
Er, I think you mistook me for Twey in your response. No matter, I'm glad you've got the thing working for you. However, there is less difference in declaring the function as a variable or as a function than you might think. Other than the scope it may be used in, and that depends upon the scope it was declared in. There may be overlap with some browsers always doing it one way, and others always doing it another when declared (some browsers may not recognise it in any scope if it wasn't done in the global scope) like:


function whatever(argument){
stuff to do
};

When you do:


var whatever = function(argument){
stuff to do
};

It will always be available in the scope in which it is declared. Additionally, if you use argument in the function and it wasn't passed to it, it will be undefined, even if it was defined elsewhere outside of the function.

Anyways, I setup some AJAX request processing code that is object oriented, so it can handle as many requests at once as you like:

http://www.dynamicdrive.com/forums/showpost.php?p=143849&postcount=16