3

Just wondering if there is a way with jquery to intercept a link when clicked. The problem is that some of the links on my page are not loaded when the page is first loaded. I have a vague recollection of hearing that jquery has a way of intercepting all current and future links. Here is the code I have. It works on all links there were there at the start but the links that were loaded onto the page later are not getting intercepted by this function

$('a').trackClick({
        areaClick: function(element) { return getAreaClicked(element); },
        href: function(element) { return getHrefFromElement(element); },
        text: function(element) { return getTextFromElement(element); },
        exceptions: function(element) { return isException(element); }
    });
genesis
  • 50,477
  • 20
  • 96
  • 125
Kaskade
  • 775
  • 4
  • 14
  • 21

5 Answers5

7

[edit: I get the occasional upvote on this answer, so I wanted to update it with more current (as of May 2015) practice]:

Per my original answer, delegating the listener is a better practice. The current "best practice" syntax for jQuery is .on(). It differs only in the order, and to me is more semantically intuitive:

$('#parent').on('click', 'a', function(event) {
  event.preventDefault();
  // do the rest of your stuff
}

The rest of my original answer still applies.


If you don't want the default click behaviour, you also need to stop the event bubbling. I prefer delegate over live, so here's my suggestion:

$('#parent').delegate('a', 'click', function(event) {
  event.preventDefault();
  // do the rest of your stuff
});

The "#parent" is just a sample. You would use any appropriate selector that's going to be a permanent ancestor of your anchor tags. Could even go up as high as "body", but often a wrapper ID of some description works as well.

[edit: I've seen an upvote recently which means this answer is being seen by someone out there. It should be noted that .live() is now deprecated, and although .delegate() is supported, the officially suggested syntax is .on() used as a delegator:

$('#parent').on('click', 'a', function(event) {
  event.preventDefault();
  // do the rest of your stuff
});
Greg Pettit
  • 10,749
  • 5
  • 53
  • 72
  • you can do exactly the same with live(), which is syntactically more correct, as you don't need to use the parent – Mazatec Sep 29 '11 at 15:09
  • @Ash Yes, you can do the same thing with `live()`, however, `live()` is inefficient in that it will first select all anchor tags, then do nothing with them. It is less of a problem though if it is outside of the $(document).ready() and in the header of the page. – Kevin B Sep 29 '11 at 15:39
  • 1
    I'm not sure what you mean by "syntactically more correct." Both functions describe what they are doing. The benefits of .delegate are well documented, and even in the event that the actual performance benefits are less dramatic (per Kevin B), it's not a bad habit to switch to using .delegate() as a go-to click binding function. Besides, I said "I prefer" and provided an alternative. Options can't be a bad thing! – Greg Pettit Sep 29 '11 at 17:15
5

You need jquery Live see here : http://api.jquery.com/live/

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

var element  = $(this);
var data = {areaClick: function(element) { return getAreaClicked(element); },
            href: function(element) { return getHrefFromElement(element); },
            text: function(element) { return getTextFromElement(element); },
            exceptions: function(element) { return isException(element); }
}
    trackClick(data);

    });
Mazatec
  • 11,481
  • 23
  • 72
  • 108
  • will this code do the exact same thing as my code above. When I paste it in I get two javascript errors in other parts of the code that were not there before. This isn't code that I have written so I dont really know whats going on, just need to fix the future link bug! – Kaskade Sep 29 '11 at 15:13
  • 7
    Future readers seeing this as the correct answer should be aware that .live() was already a discouraged choice with `.delegate()` being preferred; but more importantly both are now superseded with `.on()` using delegation syntax. http://api.jquery.com/on/ – Greg Pettit Jun 29 '12 at 13:57
3

Use jQuery's live event handler:

$('a').live('click', function() {
    ...
});
John Keyes
  • 5,479
  • 1
  • 29
  • 48
2

The simplest option is to use jQuery's live() method, although that is fairly expensive. If possible, delegate() is a better option, and there are a couple posts here that describe the difference between the two:

Jquery live() vs delegate()
jQuery: live() vs delegate()

Generally the best option is to simply bind whatever you need to to the new <a> elements that are loaded via AJAX. For example:

$.ajax({
   url: 'http://example.com'
   type: 'GET'
   data: 'whatever'
   success: function(data){
      //after inserting the response somewhere...
      $('.insertedContent').find('a'.trackClick({
        areaClick: function(element) { return getAreaClicked(element); },
        href: function(element) { return getHrefFromElement(element); },
        text: function(element) { return getTextFromElement(element); },
        exceptions: function(element) { return isException(element); }
      });
   }
}
Community
  • 1
  • 1
maxedison
  • 17,243
  • 14
  • 67
  • 114
0

As has been said, the answers recommending .live() and .delegate() are out of date.

I had a similar problem: I had various click handlers in play already on various elements, but I wanted to add an additional click handler to catch everything and to possibly take action before the others.

My use-case for this was wanting various tools in a web-app to "reset" to default state when other tools were clicked.

Here is my solution...

$(document).on("click", function(e){
    // This catches all clicks.
    // It can be suppressed if the target uses e.stopPropagation()
});

// To start the bubbling from an element "higher" than the document,
// then use delegation, e.g.:
// $(document).on("click", ".your_class", function(e){ etc })
// This can be really useful if you only have one sensitive area in the layout,
// or you want different "master" click behaviours for different areas!

$("#my_element").on("click", function(e){
    // prevent the default action, e.g. prevent "#" navigation on <a href="#">
    e.preventDefault();
    // prevent the click bubbling to the $(document) handler
    e.stopPropagation();
    // now do my stuff
    // ...
});

$("#my_other_element").on("click", function(e){
    // prevent the default action, e.g. prevent "#" navigation on <a href="#">
    e.preventDefault();
    // this time I want the "catch all" to fire
    // so I don't do stopPropagation()
    // now do my stuff
    // ...
});
Coder
  • 2,833
  • 2
  • 22
  • 24