<span onClick='makeClickRequest();'><a href='http://www.google.com'>Text Here</a></span>
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(); }
[Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"
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); }
<span onClick='makeClickRequest();' onMouseOver='makeHoverRequest();'><a href='http://www.google.com'>Text Here</a></span>
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(); }
Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)"
<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>
<?php if ( $_REQUEST ) { sleep(2); print 'test response'; 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"> 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>
<?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>
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.
@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.
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..
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); }
| DaniWeb Message | |
| Cancel Changes | |