Hi All,


I have been desperately trying to solve a serious ajax issue and decided to try asking it here.

I have simplified the problem and will illustrate it with an example.

First of all, please consider;

<span  onClick='makeClickRequest();'><a href='http://www.google.com'>Text Here</a></span>

where the javascript is about

function makeClickRequest()
{
   	
      
	var req = new AsyncRequest();
	req.setUrl("requestPage.php?task=click");
	req.setVariables("foo=hede");
	req.setMethod("POST");
	req.setSuccessCallback( function(o) { alert(o.responseText); } ); 
	req.makeRequest();
	
}

PS : You don't need to worry about AsyncRequest type, this simply directs AJAX requests by encapsulating an instance of XMLHTTPRequest type. I have used AsyncRequest class widely (and safely) in many applications and I am pretty sure that it works fine, so I don't think that it is necessary to put AsyncRequest's code here.


Now, if you open the page and click there, (assuming requestPage.php exists at the server)
in firefox you'll get the exception :

[Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"

Although nothing seems wrong with the code above, it wasn't working. I have tried to modify makeClickRequest as;

function makeClickRequest()
{

	var callback = function()
	{
		var req = new AsyncRequest();
		req.setUrl("requestPage.php?task=click");
		req.setVariables("foo=hede");
		req.setMethod("POST");
		req.setSuccessCallback( function(o) { alert(o.responseText); } ); 
		req.makeRequest();
		
	}
	window.setTimeout(callback, 0);	
	
}

And it worked ! (strange, eh? )

However, I also need to make a request when the user hovers the anchor. So, consider that I modify the HTML (of anchor) at top of the page as;

<span  onClick='makeClickRequest();' onMouseOver='makeHoverRequest();'><a href='http://www.google.com'>Text Here</a></span>

Where makeHoverRequest is

function makeHoverRequest()
{
		var req = new AsyncRequest();
		req.setSuccessCallback( function(o) {  } );
		req.setUrl("requestPage.php?task=hover");
		req.setVariables("foo=hede");
		req.setMethod("POST");
		req.makeRequest();
	
}

Again, nothing seems wrong with that. However, if user clicks the link before request in mouseOver phase is completed, firefox throws an exception;

Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"

The only solution I was able to come up with was changing HTML as;

<span  onClick='makeClickRequest(); var instance = this; var callback = function() { location.replace(instance.firstChild); } window.setTimeout(callback, 3000); return false;' onMouseOver='makeHoverRequest();'><a href='http://www.google.com'>Text Here</a></span>

Which is ugly, and waits 3 seconds to open link.. I guess I'm stuck.

Thanks in advance.

Member Avatar for langsor

Hello,

I hope I understand what your situation is here ... but why not simply disable the link and submit the page href with a script when the ajax is done doing its thing?

This isn't a perfect example and still needs some tuning, but it might help with some different ideas how to do it :-/

test_script.php

<?php
if ( $_REQUEST ) {
  sleep(2);
  print 'test response';
  exit;
}
?>


ajax_send.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="agent.js"></script>
<script type="text/javascript">

function makeSomeRequest ( target, click ) {
  var req = new Agent(); // my Ajax class
  var url = target.href;
  var args = 'foo=hede&task=any';
  req.set_action('test_script.php');
  req.set_method('POST');
  req.set_format('text');
  req.set_async(true);
  req.success = function ( response ) {
    alert( response );
    if ( click ) { // also needs redundancy check for hover-click ...
      window.location = url;
    }
  };
  req.request(args);
  return false;
}
</script>
</head>
<body>
<span><a href='http://www.google.com' onmouseover="makeSomeRequest(this,false)" onclick="return makeSomeRequest(this,true)">Hover or Click Here</a></span><br /><br />
<span><a href='http://www.google.com' onclick="return makeSomeRequest(this,true)">Click Here</a></span>
</body>
</html>

Hope it helps

Hi and thank you,

But the problem is I am writing a module to a community, thus, some part of the code (anchors) already exist. But span tags and javascript there belongs to me. Thus, I don't want to interfere with the anchors in case they might be changed in future. This is also the reason why I have encapsulated them in <span> tags instead of adding onClick and onMouseOver events directly to the <a> tags. If I return something in onMouseOver event, then I interfere with the code that doesn't belong to me and if it changes, I may have serious problems in future.

One another solution I have come up with was tracking the AJAX requests and cancel the incomplete ones when user clicks the link. However, this may not only risk efficiency but also it would be totally inconsistent with the semantics of AJAX which is about making requests in such a way that no one actually knows when a request is completed and no request should be aware of another one -- so requests are async..

However, due to that bug in firefox (I call it bug because nothing seems wrong with my code at all !), I guess I'll follow this solution, which is ugly.

I would really appreciate if someone comes up with a sensible solution so I neither have to modify the code that doesn't belong to me nor interfere with semantics of AJAX.

The error makes proper sense; think about it, the page which made an Ajax request in the first place is no longer there and hence a NS_ERROR_NOT_AVAILABLE. You have two options here:

• Redirect the user to the Google home page once the Ajax request is complete and you have the status with you; analyze the status and redirect accordingly based on whether the async request was success or a failure.
• On the link click, navigate the user to another page on your domain, e.g. handleThis.php which performs the same job as that performed by the async request and navigates the user to Google home page. Pretty simple, no Ajax needed.

Member Avatar for langsor

Hey,

This new idea of mine might not seem more elegant than your setTimout idea, but it is another approach to consider, and doesn't mess with your existing tags -- just the <span>s you put in.

test_script.php

<?php
if ( $_REQUEST ) {
  sleep(2);
  print $_REQUEST['task'].'::'.$_REQUEST['foo'];
  exit;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="agent.js"></script>
<script type="text/javascript">

window.onload = register_triggers;

function register_triggers () {
  // onmouseover triggers
  document.getElementsByTagName('html').item(0).onmouseover = function ( event ) {
    var action = ( typeof event == 'undefined' ) ? window.event : event;
    var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;
    if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
      target = target.parentNode;
    }
    // custom handlers here ...
    if ( /hover-ajax/.test( target.parentNode.className ) ) {
      makeAjaxRequest(target,'hover');
    }
  };
  // onclick triggers
  document.getElementsByTagName('html').item(0).onclick = function ( event ) {
    var action = ( typeof event == 'undefined' ) ? window.event : event;
    var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;
    if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
      target = target.parentNode;
    }
    // custom handlers here ...
    if ( /click-ajax/.test( target.parentNode.className ) ) {
      makeAjaxRequest(target,'click');
      return false;
      //cancelDefaultAction(action); // the formalized approach
    }
    // SOME TESTING OUTPUT
    // alert( ( /^\s+$/.test( target.firstChild.nodeValue ) || target.firstChild.nodeValue == null ) ? '<' + target.nodeName.toLowerCase() + '> tag' : 'data: ' + target.firstChild.nodeValue );
  };
}

function makeAjaxRequest ( target, type ) {
  var url = target.href;
  var args = 'foo=hede';
  switch ( type ) {
    case 'click': args += '&task=click'; break;
    case 'hover': args += '&task=hover'; break;
  }
  var req = new Agent(); // my Ajax class
  req.set_action('test_script.php');
  req.set_method('POST');
  req.set_format('text');
  req.set_async(true);
  req.success = function ( response ) {
    alert( response );
    if ( type == 'click' ) { // needs redundancy check for hover then click ...
      window.location = url;
    }
  };
  req.request(args);
}

function cancelDefaultAction ( event ) {
  var action = ( typeof event == 'undefined' ) ? window.event : event;
  action.returnValue = false;
  if ( typeof action.preventDefault != "undefined" ) {
    action.preventDefault();
  }
  return true;
}

</script>
</head>
<body>
<span class="hover-ajax"><a href='http://www.google.com'>Hover Here</a></span>
<br /><br />
<span class="click-ajax"><a href='http://www.google.com'>Click Here</a></span>
</body>
</html>

Hi again,

The error makes proper sense; think about it, the page which made an Ajax request in the first place is no longer there and hence a NS_ERROR_NOT_AVAILABLE. You have two options here:

• Redirect the user to the Google home page once the Ajax request is complete and you have the status with you; analyze the status and redirect accordingly based on whether the async request was success or a failure.
• On the link click, navigate the user to another page on your domain, e.g. handleThis.php which performs the same job as that performed by the async request and navigates the user to Google home page. Pretty simple, no Ajax needed.

Thank you for the description of error, I guess I'm beginning to understand, but I still have a doubt that it is sensible.

What I'm doing is, triggering two requests before page is redirected, which means their destination is not undefined. When request is triggered, the page actually exists. What's more; if I wait for the request in hover phase to be completed and then I click, it certainly works without any error. This is the part that doesn't make sense in fact. Since page is redirected, according to your understanding of error, it must have thrown the same exception there. But it didn't, it works fine if I wait for hover request to complete and then click the link. Moreover, the code I've posted here works perfectly in IE as it is. I'm a bit confused now.

About your suggestions; the reason why I wouldn't do either of these solutions was I didn't want to interfere the current principles of the system. Which means I wouldn't change the way how page is redirected, since the developers of the community may change this part so I would certainly need to modify that, too. However, if it turns out that I have no other choice, certainly I would do something like that.. At least I can postpone the redirection until requests are complete.

@langsor: Thanks, I have glanced your code a little bit, it seems a little complicated. Thus, I want to confirm that I have got it correct, what you've done there is instead of adding onclick and onmouseover eventhandlers in HTML, you specify them in javascript so that they are binded in runtime. And after request is complete, you make the redirection, I suppose. By this way, you'll ensure that redirection happens after request. Correct me if I am wrong ?

Thanks to all.

Member Avatar for langsor

@langsor: Thanks, I have glanced your code a little bit, it seems a little complicated. Thus, I want to confirm that I have got it correct, what you've done there is instead of adding onclick and onmouseover eventhandlers in HTML, you specify them in javascript so that they are binded in runtime. And after request is complete, you make the redirection, I suppose. By this way, you'll ensure that redirection happens after request. Correct me if I am wrong ?

You are correct, and this way you don't interfere with the existing code at all. You just need some hook for the javascript to grab onto, like a class-name, id, name or href attribute (almost anything really).

I know this is a bit confusing code, but it is also incredibly flexible for almost any javascript event capturing ... let me break it down a little.

window.onload = register_triggers;
could also be an inline function, or using event handlers (ask if you want to know more about these), here's an inline example
window.onload = function () {
// script that executes after the window loads
};
and it's important to wait until the entire window-document has loaded since we are working with html elements, and if they haven't loaded yet we will get errors.

This make the entire html document a mouseover hotspot
document.getElementsByTagName('html').item(0).onmouseover = function ( event ) {
// onmouesover code for all elements inside <html> tags
};

In mozilla-DOM browsers you receive the event-object passed to the handler function
function ( event )
but IE makes the event a global or window-level object
window.event
so we end up with this branching code -- I renamed event into action
var action = ( typeof event == 'undefined' ) ? window.event : event;

In mozilla-DOM browser the element where the event originated is a property of the event called target, in IE it's called srcElement
so again we have branching code
var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;

Safari will register a text-node (the textual content of an element) to trigger an event, we don't really want this since a text-node can't contain any ID or other useful attributes, so we handle this by calling it's parent-element
if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
target = target.parentNode;
}

At this point we know that an event has occurred, we know what element on the page caused the event, and we just need to know if that element is one of the ones we care about

Using a regular-expression test, we take a quick look at the (in this case) className of the target or originating element. If it matches up we execute our desired code
Since we don't want to change the attributes of the anchor links, instead we wrap them in a <span> and give that span a unique class that we can grab onto.
// custom handlers here ...
if ( /hover-ajax/.test( target.parentNode.className ) ) {
makeAjaxRequest(target,'hover');
}

For the onclick version of this we want to keep the link from actually executing and taking us off the page until we get our Ajax response.
// onclick triggers ... redundant code omitted
// custom handlers here ...
if ( /click-ajax/.test( target.parentNode.className ) ) {
makeAjaxRequest(target,'click');
so we return false to our target link, thus nullifying the link-action
return false;
we could instead use the more formalized approach and cancel the event object's action
//cancelDefaultAction(action); // the formalized approach

If you end up playing around with this approach some, you might want to uncomment the following line and just click-around the page some to see what output you get.
// SOME TESTING OUTPUT
// alert( ( /^\s+$/.test( target.firstChild.nodeValue ) || target.firstChild.nodeValue == null ) ? '<' + target.nodeName.toLowerCase() + '> tag' : 'data: ' + target.firstChild.nodeValue );

This should be familiar to you, it's just using my ajax class and using a switch statement to combine the two hover/click functions you had
function makeAjaxRequest ( target, type ) {
var url = target.href;
var args = 'foo=hede';
switch ( type ) {
case 'click': args += '&task=click'; break;
case 'hover': args += '&task=hover'; break;
}
var req = new Agent(); // my Ajax class
req.set_action('test_script.php');
req.set_method('POST');
req.set_format('text');
req.set_async(true);
req.success = function ( response ) {
alert( response );

This, of course, checks if it's a click action, and loads the original link URL after the response is received.
if ( type == 'click' ) { // needs redundancy check for hover then click ...
window.location = url;
}
what it does not do is find out if that request has already been made from a hover action before the person clicked the link ...

This is the formalized event cancellation method.
I forget which one uses action.preventDefault() and which one uses action.returnValue, but one is mozilla-DOM and one is IE.

function cancelDefaultAction ( event ) {
var action = ( typeof event == 'undefined' ) ? window.event : event;
action.returnValue = false;
if ( typeof action.preventDefault != "undefined" ) {
action.preventDefault();
}
return true; // seems counter-intuitive to our return false above
}

Hope this helps clarify a little but, let me know if you have any questions.

You are correct, and this way you don't interfere with the existing code at all. You just need some hook for the javascript to grab onto, like a class-name, id, name or href attribute (almost anything really).

I know this is a bit confusing code, but it is also incredibly flexible for almost any javascript event capturing ... let me break it down a little.

window.onload = register_triggers;
could also be an inline function, or using event handlers (ask if you want to know more about these), here's an inline example
window.onload = function () {
// script that executes after the window loads
};
and it's important to wait until the entire window-document has loaded since we are working with html elements, and if they haven't loaded yet we will get errors.

This make the entire html document a mouseover hotspot
document.getElementsByTagName('html').item(0).onmouseover = function ( event ) {
// onmouesover code for all elements inside <html> tags
};

In mozilla-DOM browsers you receive the event-object passed to the handler function
function ( event )
but IE makes the event a global or window-level object
window.event
so we end up with this branching code -- I renamed event into action
var action = ( typeof event == 'undefined' ) ? window.event : event;

In mozilla-DOM browser the element where the event originated is a property of the event called target, in IE it's called srcElement
so again we have branching code
var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;

Safari will register a text-node (the textual content of an element) to trigger an event, we don't really want this since a text-node can't contain any ID or other useful attributes, so we handle this by calling it's parent-element
if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
target = target.parentNode;
}

At this point we know that an event has occurred, we know what element on the page caused the event, and we just need to know if that element is one of the ones we care about

Using a regular-expression test, we take a quick look at the (in this case) className of the target or originating element. If it matches up we execute our desired code
Since we don't want to change the attributes of the anchor links, instead we wrap them in a <span> and give that span a unique class that we can grab onto.
// custom handlers here ...
if ( /hover-ajax/.test( target.parentNode.className ) ) {
makeAjaxRequest(target,'hover');
}

For the onclick version of this we want to keep the link from actually executing and taking us off the page until we get our Ajax response.
// onclick triggers ... redundant code omitted
// custom handlers here ...
if ( /click-ajax/.test( target.parentNode.className ) ) {
makeAjaxRequest(target,'click');
so we return false to our target link, thus nullifying the link-action
return false;
we could instead use the more formalized approach and cancel the event object's action
//cancelDefaultAction(action); // the formalized approach

If you end up playing around with this approach some, you might want to uncomment the following line and just click-around the page some to see what output you get.
// SOME TESTING OUTPUT
// alert( ( /^\s+$/.test( target.firstChild.nodeValue ) || target.firstChild.nodeValue == null ) ? '<' + target.nodeName.toLowerCase() + '> tag' : 'data: ' + target.firstChild.nodeValue );

This should be familiar to you, it's just using my ajax class and using a switch statement to combine the two hover/click functions you had
function makeAjaxRequest ( target, type ) {
var url = target.href;
var args = 'foo=hede';
switch ( type ) {
case 'click': args += '&task=click'; break;
case 'hover': args += '&task=hover'; break;
}
var req = new Agent(); // my Ajax class
req.set_action('test_script.php');
req.set_method('POST');
req.set_format('text');
req.set_async(true);
req.success = function ( response ) {
alert( response );

This, of course, checks if it's a click action, and loads the original link URL after the response is received.
if ( type == 'click' ) { // needs redundancy check for hover then click ...
window.location = url;
}
what it does not do is find out if that request has already been made from a hover action before the person clicked the link ...

This is the formalized event cancellation method.
I forget which one uses action.preventDefault() and which one uses action.returnValue, but one is mozilla-DOM and one is IE.

function cancelDefaultAction ( event ) {
var action = ( typeof event == 'undefined' ) ? window.event : event;
action.returnValue = false;
if ( typeof action.preventDefault != "undefined" ) {
action.preventDefault();
}
return true; // seems counter-intuitive to our return false above
}

Hope this helps clarify a little but, let me know if you have any questions.

That makes perfect sense, take you for the clarification. I'll try it.

Member Avatar for langsor

One another solution I have come up with was tracking the AJAX requests and cancel the incomplete ones when user clicks the link. However, this may not only risk efficiency but also it would be totally inconsistent with the semantics of AJAX which is about making requests in such a way that no one actually knows when a request is completed and no request should be aware of another one -- so requests are async..

One last thought, I suspect the easiest (but not necessarily most reliable) way to track if a request is already active, is using cookies ... either in the JavaScript or on the server-side.

Just my two-cents

PHP:
http://us2.php.net/setcookie

JS:
http://www.quirksmode.org/js/cookies.html

Cheers

Hmmn, on second thought, you would need to see if the cookie is readable without a page-reload. I think it is if it's set with JavaScript but probably not if set on the server...

I'm not certain if this is what you are looking for. It works in both IE and FF. AJAX requests are made several times in quick succession (before the previous request can be completed) from the onload event of this page: http://mmpp.com/mcweb200.nsf/formYieldSearch?Openform. Section 2. and section 4. on the page show 'Loading' in the listboxes until the AJAX request has been completed. You can also click on section 1. Municipalities radiobutton before the others are loaded. I hope this helps.

I should also mention that it is essential that the request_via_http variable and the triggered onreadystatechange function must remain within this function, or it doesn't work.

function getRequestViaHTTP(url, parameters, listName)
{	var request_via_http = false;
     if (window.ActiveXObject)
	{	// IE6 and previous.
		try
		{	request_via_http = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e)
		{	try
			{	request_via_http = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e) {}
		}
	} else if (window.XMLHttpRequest)
	{	// IE7, Firefox, Opera, Safari, etc.
		request_via_http = new XMLHttpRequest();
		if (request_via_http.overrideMimeType)
		{	request_via_http.overrideMimeType('text/plain');
		}
	}
	if (! request_via_http)
	{	alert('This XMLHTTP request has failed. IE (PC only), Firefox (Mac and PC), Safari (Mac only), & Opera (PC Only) have successfully tested this code.');
		return false;
	}
	
	request_via_http.onreadystatechange = function()
	{	if (request_via_http.readyState == 4)
		{	if (request_via_http.status == 200)
			{	populateList(listName, request_via_http.responseText);
			} else
			{	alert('This XMLHTTP request has failed upon return. (readyState: ' + request_via_http.readyState + ')');
			}
		}
	}
	request_via_http.open('GET', url + parameters, true);
	request_via_http.send(null);
}

I'm not certain if this is what you are looking for. It works in both IE and FF. AJAX requests are made several times in quick succession (before the previous request can be completed) from the onload event of this page: http://mmpp.com/mcweb200.nsf/formYieldSearch?Openform. Section 2. and section 4. on the page show 'Loading' in the listboxes until the AJAX request has been completed. You can also click on section 1. Municipalities radiobutton before the others are loaded. I hope this helps.

I should also mention that it is essential that the request_via_http variable and the triggered onreadystatechange function must remain within this function, or it doesn't work.

Hi,
I have tried to change href of anchor to javascript:void(0) and in this case it works in both IE and FF even if I don't wait hover request to complete. No problem. But when I change anchor's href to something else, say, http://www.google.com, this is where the problem begins. Thank you anyway.

Member Avatar for langsor

@ximath

Apparently I really like working on this puzzle ... I thought of this early this morning but have been away from my computer until now.

This is likely the way it should be done -- do you see what is different?

test_script.php (this is the same)

<?php
if ( $_REQUEST ) {
  sleep(2);
  print $_REQUEST['task'].'::'.$_REQUEST['foo'];
  exit;
}
?>

main.html (this is changed)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="agent.js"></script>
<script type="text/javascript">

window.onload = register_triggers;

function register_triggers () {
  // onmouseover triggers
  document.getElementsByTagName('html').item(0).onmouseover = function ( event ) {
    var action = ( typeof event == 'undefined' ) ? window.event : event;
    var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;
    if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
      target = target.parentNode;
    }
    // custom handlers here ...
    if ( /hover-ajax/.test( target.parentNode.className ) ) {
      makeAjaxRequest(target,'hover');
    }
  };
  // onclick triggers
  document.getElementsByTagName('html').item(0).onclick = function ( event ) {
    var action = ( typeof event == 'undefined' ) ? window.event : event;
    var target = ( typeof action.target == 'undefined' ) ? action.srcElement : action.target;
    if ( target.nodeName == '#text' ) { // Safari nodeType 3 work-around
      target = target.parentNode;
    }
    // custom handlers here ...
    if ( /click-ajax/.test( target.parentNode.className ) ) {
      makeAjaxRequest(target,'click');
      // no return value or cancel default action !!!
    }
  };
}

function makeAjaxRequest ( target, type ) {
  var url = target.href;
  var args = 'foo=hede';
  switch ( type ) {
    case 'click': args += '&task=click'; break;
    case 'hover': args += '&task=hover'; break;
  }
  var req = new Agent();
  req.set_action('test_script.php');
  req.set_method('POST');
  req.set_format('text');
  // make the request synchronous and everything works
  req.set_async(false);
  if ( resp = req.request(args) ) {
    // now we get the result as a return value of the synchronous request
    // and the link doesn't execute until we get the return value ...
    alert( resp );
  }
}
</script>
</head>
<body>
<span class="hover-ajax"><a href='http://www.google.com'>Hover Here</a></span><br /><br />
<span class="click-ajax"><a href='http://www.google.com'>Click Here</a></span>
</body>
</html>

Okay, I'm done now :-)

> What I'm doing is, triggering two requests before page is redirected, which means their
> destination is not undefined. When request is triggered, the page actually exists.

Of course the destination exists and so does the source when making the request, but clicking on the link loads a new page and hence the context in which the request was made is destroyed. Remember, Javascript is a client side scripting language in this case and hence its lifetime is the lifetime of the client session.

> What's more; if I wait for the request in hover phase to be completed and then I click, it
> certainly works without any error.

Because enough time is given for the request to complete and to process the response when you hover on the link. This isn't the case when you *click* on it since the browser attempts to load a new context.

> Moreover, the code I've posted here works perfectly in IE as it is.

Because what FF is showing in the Error console is not an error at all. Think about it, if you plan on ignoring the return status of your Ajax request, should it even matter to any browser? Does the same code run fine in Opera? Is this so called error hampering your functionality.

> About your suggestions; the reason why I wouldn't do either of these solutions was I
> didn't want to interfere the current principles of the system.

What kind of a system mandates you to forcefully use Ajax when the problem can be very easily solved with redirecting to a PHP page and performing navigating to your page of choice? Also, there are a lot many ways in which your current approach can be modified to work in a more predictable manner. One would be to navigate to the destination page after the Ajax requests are complete.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.