5

I have a website, where I allow other developers to host content. My aim is to log clicks on every hyperlink (even the content that is hosted by other developers) ,which exists on the page.

My initial approach was as follows:

$('a').click(function(event)
             {
                //do my logging
                return true;
             }
);

Now with the above approach , I am facing the following issues:

  • Developers may have images inside the anchor link, so the events target is an image rather than href
  • Many developers have their own way of handling an href click , using an onclick event rather than a simply href='' attr
  • Some developers add their custom attr , to the tag, and have custom functions to handle the clicks

so basically , the issue is , there is a huge variety of anchor tags available, and logging clicks is not as simple.
Many cases allowed me to log the data I wanted, but a few cases , broke the code badly.

My aim to post on this forum was:

  • to discuss what is the right approach to do hyperlink clicks logging in a dynamic environment
  • is there a plugin out there , which allows a functionality like this.

I know facebook and google have this , but they have a totol control, on what is being hosted in their environments.

Any help is greatly appreciated.

Neeraj
  • 8,408
  • 8
  • 41
  • 69

2 Answers2

9

Adding a click handler to every link is not a good idea. You should make use of event delegation (which will only attach one event handler at the root of the document):

$(document).delegate('a', 'click', function(event) {
    // logging
});

Update (17.12.2011):

Since jQuery 1.7, one would use .on() [docs]:

$(document).on('click', 'a', function(event) {
    // logging
});

Regarding your problems:

Developers may have images inside the anchor link, so the events target is an image rather than href

Events bubble up as long as propagation is not canceled. It depends on what you want to log. With delegate the event.target property will point to the image, but this (inside the handler) will point to the a element.
So you should have no problems here (example: http://jsfiddle.net/cR4DE/).

But that also means to you will miss clicks if the developers cancel the propagation.

(Side note: You could solve this letting the event handler fire in the capturing phase, but IE does not support this (hence jQuery does not either).)

Many developers have their own way of handling an href click , using an onclick event rather than a simply href='' attr

This will not touch existing event handlers.

Some developers add their custom attr , to the tag, and have custom functions to handle the clicks

Not sure what you mean here.


It also depends on how the other content is included. E.g. the above code won't track clicks in iframes.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Isint event delegation the same as $(element).bind? – Neeraj Jan 13 '11 at 06:51
  • @Neeraj: It depends. It is always event delegation if you a listener listens for events that bubble up from the descendants. But `$(element).bind('click',...)` is just the same as `$(element).click(...)`, i.e. binding a click event handler to elements selected by `element`. `delegate` makes it easier to listen to events of *certain* descendants. – Felix Kling Jan 13 '11 at 09:48
  • @Neeraj: Imagine you have 1000 links. `$('a').click(....)` (or `$('a').bind('click', ...)`) would create 1000 event handlers. But `$(document).delegate('a', 'click',...)` just creates one. – Felix Kling Jan 13 '11 at 09:55
  • also, what if I want to filter and then add listeners to all links, rather than adding links, and logging after the click has happened? – Neeraj Jan 13 '11 at 10:55
  • @Neeraj: I don't understand what you mean. What do you want to filter? I thought your ultimate goal was to log clicks on links, what do you want to do now? – Felix Kling Jan 13 '11 at 11:04
  • @Felix: The issue is that I do not want to event listeners to all links, I want to add event listeners to links , which conform to a specific standard, e.g a link with an onclick property set may not be a part of the links I want to log, hence I dont want to add an event listener to them , rather than going through this logic , inside the click handler. – Neeraj Jan 13 '11 at 12:59
  • @Neeraj: I see. You could filter those with the `onlick` set by: `a:not([onlick])` instead of `a`. Try to create an selector for your needs. Or listen for all links and filter them in the event handler like `if(typeof this.onclick !== "undefined")`. You don't have to add an extra event handler to every link for that. You have decide: Either filtering beforehand and add a lot of handlers (with the high probability that most of the links are not even clicked) or filter "on demand" which adds a slight (probably unnoticeable) overhead but saves memory and pre-computation. – Felix Kling Jan 13 '11 at 13:27
  • @Felix: Thanks felix this was really useful.Also, it would be nice if you could take a look at http://stackoverflow.com/questions/4711280/jquery-stops-event-propagation-in-ie-by-default-even-when-true-is-returned-in – Neeraj Jan 17 '11 at 09:35
1

In your logging code you should check for the bad cases and deal accordingly.

For example in your first case i you get the image and walk the dom up until i would find an a tag and log the href from there.

There will be some cases in which you will not be able to do the logging but if they are small compared with the cases you can do that you will be fine :).

Mihai Toader
  • 12,041
  • 1
  • 29
  • 33