Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to track registered user activity, specifically, when they click a link to a file for download. The filesystem plugin is WP-Filebase.

I found that when I added a click() handler through jQuery, it wasn't happening, so I switched to a mousedown() handler for my Ajax-based tracking.

What appears to be occurring (based on Firebug's Network activity monitor) is that if I press the mouse (mousedown) and then release, the resulting file download dialog box that occurs cancels the mousedown activity (Network tab shows the mousedown Ajax call as "cancelled"). The Ajax call therefore never makes it to the server and so I don't get my tracking.

On the other hand, if I press the mouse and DON'T release for a while, I do get to see my test Ajax response, (an alert()).

This is not viable for obvious reasons. Is there another solution? Can both the mousedown and the anchor click work together, or will one always cancel the other?

EDIT, here's some code that's behaving as I described (linkx.js):

(function($) {
    $(document).ready(function(){
        $('.wpfilebase-attachment a').mousedown(function(){
            var postParams = {};
            postParams['action'] = ZGAjax.TRACKING_ACTION;
            postParams[ZGAjax.FILE_ID_PARAM] = this.id;

            $.post(
                ZGAjax.ajaxurl, 
                postParams,
                function( response ) {
                    alert( response );
                }
            );

            return true;
        });

    });
})(jQuery);

And the handler on the php side...

// Add AJAX tracking of file downloads.
// First, add the link tracking script and create a global namespace to hold the admin_url() for the AJAX call
if (!is_admin()) add_action('wp_enqueue_scripts', 'gsn_add_tracking_script');
function gsn_add_tracking_script(){
    wp_enqueue_script( 'zg-link-tracker', SCRIPTS_URI . '/linkx.js', array('jquery'), '1.0' );
    wp_localize_script( 'zg-link-tracker', 'ZGAjax', array( 
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
        'TRACKING_ACTION' => TRACKING_ACTION,
        'FILE_ID_PARAM' => FILE_ID_PARAM
    ) );
} 

 // Works in conjunction with linkx.js
 add_action( 'wp_ajax_' . TRACKING_ACTION, 'gsn_track_downloads' );

function gsn_track_downloads() {
    // get the submitted parameters
    $file_id = $_POST[FILE_ID_PARAM];

    // generate the response
    $response = json_encode( array( 'success' => true, 'file_id' => $file_id ) );

    // response output
    header( "Content-Type: application/json" );
    echo $response;

    // IMPORTANT: don't forget to "exit"
    exit;
}

The PHP side is pretty textbook, and really just sends me back a confirmation that it worked.

And it DOES work, if I keep my mouse button held down long enough for the entire transaction to complete. If I release, and thus allows the download to begin, I never get the confirmation. Firebug tells me that the Ajax request is "cancelled" so it's not even a matter of the transaction piggy-backing on top of the download transaction (which was a wild theory in the first place).

share|improve this question
    
Do you have a code example or live demo? In general, when dealing with problems that seem to not work as they should, it's helpful to have something to debug and tweak. (Because as far as I can tell, a mousedown event works fine on an anchor click, and a mouseup event shouldn't be canceling a mousedown event) –  Jared Cobb Sep 12 '11 at 20:16
    
@JaredCobb done. –  Tom Auger Sep 12 '11 at 21:36
1  
Try switching to a .live() bind. Anyway, I'd say it's def. no wp question. You should ask that on SO. –  kaiser Sep 12 '11 at 21:46
    
@kaiser - yeah, you're right, it's almost certainly not a WP issue. I wanted to post here in case anyone knew something specific regarding the WP-Filebase plugin or some quirk of WP. –  Tom Auger Sep 13 '11 at 12:30
add comment

1 Answer

up vote 1 down vote accepted

It's a good idea to prevent mixing your click/mouse handling. In the past when faced with the same problem, I've used one of two approaches (depending on my mood at the time):

Mouseup

Rather than use mousedown, use jQuery's mouseup event. Mousedown is typically stepped on by click. By using mouseup instead, you fire your event after the mouse is released (typically at the same time as click or just after) and shouldn't run in to the same problem.

Bind directly to click

This is the one I use the most often. Loop through the anchor tags on your page and change their event binding. You can set the click event of each link to first fire your AJAX call and then (after completion) it will fire the original event.

For example:

jQuery(document).ready(function($) {

    $('a').bind('click', function(e) {

        // Do your AJAX stuff

        return true;
    });

});

Since you're using jQuery, make sure you set async: false when you use AJAX. This will force the browser to execute the request before moving on to loading the link.

If you're using forms, you can easily unbind/rebind the submit handler ... unfortunately click is a little less cooperative.

share|improve this answer
    
Holy crap @EAMann, that's a lot of good info. The only comment I'd have is that I would bet that mouseup gets swallowed by the File Save dialog box. Since the click on the anchor starts a download and then invokes a dialog box, I"m sure the DB flushes the rest of the mouse events on that object. Besides, you have to click on the "SAVE" button, and that in itself will swallow the mouseup right there. –  Tom Auger Sep 13 '11 at 12:32
1  
Thaks @EAMann, switching async = false sorted me right out, while leaving the Ajax onMousedown. Note, though this should be obvious: if you're testing your Ajax to see if it works by having an alert() to display the Ajax success results, you WILL cancel the click and the download / link will not take place. This only makes sense because you consume the mouse event by dismissing the alert dialog box. –  Tom Auger Sep 13 '11 at 13:21
    
@Tom Auger Just use console.log(); instead of alert();. This doesn't interrupt normally. –  kaiser Sep 14 '11 at 9:36
1  
@kaiser right you are. I have to start remembering to do that! –  Tom Auger Sep 14 '11 at 13:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.