7

I want to achieve the following behavior in a page link.

When the link is clicked, I want to:

  • First, send (POST) some data back to the server
  • Second, allow the browser to navigate to the url that the link was pointing to.

I am relatively new to JQuery, and here is my first attempt below. I will be grateful to any jQuery gurus in here to fillin the blanks (and maybe point out how the snippet below may be improved).

<html>
<head>test page</head>
<body>
<div><a id="hotlink" href="http://www.example.com">Clik and see</a></div>
<script type="text/javascript">
$(document).ready(function(){
  $('hotlink').click(function(){
     //AJAX Post data here ...
     //follow the link url (i.e. navigate/browse to the link) ...
  });
});
</script>
</body>
</html>
morpheous
  • 16,270
  • 32
  • 89
  • 120
  • Check http://api.jquery.com/id-selector and http://api.jquery.com/jQuery.post. Lot of examples :) – BalusC Apr 22 '10 at 22:11

5 Answers5

9

You might want to see my answer to a similar question. Basically, an ajax post would be asynchronous by default and may not make it to the server before completing. In order to ensure completion, you can make it synchronous but this will lock up the browser until the request has returned. This can be very problematic if your server is having trouble, it could take a while and the user is waiting to follow the link. Nevertheless, the code is:

$('#hotlink').click( function () { 
    $.ajax({ 
      async: false,
      type: "POST", 
      url: "http://myurl.com/mypage.php", 
      data: "param1=value&param2=value",  // &param3=value... etc. 
    }); 
}); 

Upon completion, the default action of the link will be honoured.

Community
  • 1
  • 1
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • Andy: thanks for the explanation (and with useful code I can get started with). A couple of things though, from the other answers/comments I have read so far, it seems safer to return true from the function. Also, someone made a valid point of disabling the link whilst waiting for the server ACK response. Seems like a brilliant idea, but how do I disable a link (using the above code example?) – morpheous Apr 22 '10 at 23:05
  • @morpheous: You very rarely need to `return true;` from an event handler to allow default actions, you usually only need to `return false;` to prevent default actions. Disabling the link would be pointless in this case - a synchronous ajax call would not allow a further click on the link anyway. – Andy E Apr 23 '10 at 00:00
5

You can set the window.location call in the ajax callback.

Here is some quick, untested code:

<script type="text/javascript>
$(document).ready(function(){
  $('hotlink').click(function(){
     var link = $(this);
     $.post(url, {'data': 'value'}, function() {
       window.location = link.attr('href');
     });
     return false;
  });
});
</script>

Note that you should probably do something to make it clear that the page is doing an ajax call, like putting in a spinner graphic, and disabling the link so that they don't click it a bunch of times.

--edit--

The other way to solve this problem is to do a synchronous ajax call, but then the browser will lock up while it is in progress.

To answer the comment, you need to return false so that the link isn't followed until after the ajax call is successfully completed.

zaius
  • 6,409
  • 4
  • 28
  • 50
  • It's more or less pointless to `return false` if you're just going to navigate the browser to the `link.attr('href')` anyways. Just `return true;` and the browser will do that for you. – dlamotte Apr 22 '10 at 22:15
  • +1 for only navigating if the post is a success - but - been having some problems with window.location and IE asking the user for permission when not as a result of direct click event - this may occur if the result of the callback on the ajax. – James Westgate Apr 22 '10 at 22:16
1

Try this:

$('#hotlink').click(function() {
    $.post(...);
    return true;
});

The process of returning true from .click(function(){...}) will instruct the browser to follow the link. If you return false, the browser will not follow the link.

Also, make sure you use #hotlink instead of hotlink (or a similar selector).

Obviously, you'll want to fill in the $.post(...) with the proper usage from jquery's documentation. Documentation here: http://api.jquery.com/jQuery.post/

dlamotte
  • 6,145
  • 4
  • 31
  • 40
  • Psssh.. The selector is wrong. I'd include links to documentation as well. – BalusC Apr 22 '10 at 22:14
  • That doesn't guarantee the ajax call will go through. The only way to do that is with a synchronous ajax call, or with a callback. – zaius Apr 22 '10 at 22:59
1

Check out the documentation for the ajax method. Other methods (like post) are just shortcuts to ajax.

$(document).ready(function(){
  $('#hotlink').click(function(){
     //AJAX Post data here ...
     $.ajax({
         async: false,
         data: 'can be a string or object, read docs',
         url: 'http://example.com/whatever.html',
         type: 'post'
     });

     //follow the link url (i.e. navigate/browse to the link) ...
     //(it happens naturally by clicking a link, no need for extra code)
  });
});

Note that I specified that this call should occur synchronously. That way you can be sure that the server receives the data before the browser navigates to a new page.

Ken Browning
  • 28,693
  • 6
  • 56
  • 68
  • You probably want to guarantee you `return true;` or it may not "happen naturally". – dlamotte Apr 22 '10 at 22:16
  • @xyld, `return true` is not necessary. – nickf Apr 22 '10 at 23:01
  • @Ken: Synchronous requests are very rarely called-for, and aren't the right answer here. It locks up the browser while the request is being processed. – nickf Apr 22 '10 at 23:04
  • I agree that they're usually indicative of the wrong approach. I suspect that he's trying to implement a "how many times has this link been clicked" feature via javascript which would qualify, in my judgement, as the wrong approach. Either way, I specifically called it out so that he could make his own decision. – Ken Browning Apr 22 '10 at 23:06
  • Ken: interesting that you thing this is the wrong approach (I AM trying to implement something similar to 'how many times has this link been clicked'). What do you recommend is the correct way of going about this? – morpheous Apr 23 '10 at 13:53
  • morpheous: I would use jQuery to change all links to external websites to something like http://mysite.com/mytracker.php?url=. And do a redirect from the server after updating the database. – Ken Browning Apr 23 '10 at 14:26
0

Nearly perfect ;)

<script type="text/javascript">
$(document).ready(function(){
  $('#hotlink').click(function(event){
     //AJAX Post data here
  });
});
</script>

You forgot the # sign for finding your link element. The link will be automatically followed as long as you don't call event.preventDefault().

If you wan't to send an AJAX request i would suggest you to send a synchronous one, otherwise you won't be able to figure out if it was successful or not.

Florian Gutmann
  • 2,666
  • 2
  • 20
  • 28