@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 somehook 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 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 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.