views:

457

answers:

4

Hi,

I don't know if what I'm trying to accomplish is possible at all. I would like to override the default behaviour for all the anchor objects ('a' tag) for a given HTML page. I know I can loop through all the 'a' elements and dynamically add an 'onclick' call to each one of them from the body element 'onload' method, but I'm looking for a more absolute solution. What I need is that all 'a' elements get assigned an 'onclick' action which calls a method that passes the element 'href' property as an argument, so the following:

<a href="http://domain.tld/page.html"&gt;

Dynamically becomes:

<a href="http://domain.tld/page.html" onclick="someMethodName('http://domain.tld/page.html'); return false;">

Like I said, the ideal way to do this would be to somehow override the Anchor class altogether when the document loads. If it's not possible then I'll resort to the loop-through-all 'a' elements method (which I already know how to do).

Best regards,

A: 
window.onload = function() {
    var anchorElements = document.getElementsByTagName('a');
    for (var i in anchorElements)
        anchorElements[i].onclick = function() {
            alert(this.href);
            return false;
        }
}

This is about the simplest way to do it. Wrap in <script type="text/javascript">...</script> in the document head and it will run on page load.

Benji XVI
+5  A: 

If you don't want to iterate over all your anchor elements, you can simply use event delegation, for example:

document.onclick = function (e) {
  e = e ||  window.event;
  var element = e.target || e.srcElement;

  if (element.tagName == 'A') {
    someFunction(element.href);
    return false; // prevent default action and stop event propagation
  }
};

Check the above example here.

CMS
What’d you say is the advantage of not iterating over the anchor elements? In a certain way this is the more obtrusive method, since it means redirecting *all* clicks in the document!
Benji XVI
The question explicitly mentions not iterating over the anchor elements.
Ben
And it's also more efficient when you don't have to go through the elements first.
jtbandes
@Ben Sure, but gives no valid reason: it’s certainly not in any sense informative to say that setting the onclick property of each anchor tag is un-“absolute”. Just wondering if there was a genuine reason to consider? Apart from performance, which is going to be negligible.
Benji XVI
@Benji XVI: One of the advantages of this method is that if more anchor elements are added programmatically (i.e.: content loaded with Ajax) after this event is binded, it will continue to work for those new anchors.
CMS
As you said above, Ben, “if your page is complex you could run into quite a lot of problems with event delegation.” In my view this, while clever, is actually a *less* robust method, requires a cross-browser hack, and has no particular advantages. It is quite syntactically elegant, but only for the trivial case.
Benji XVI
@CMS Good point. If that behaviour is required this could definitely be the superior option.
Benji XVI
As usual, the answer on what's best is "it depends." If you have many, many items, all intended to run essentially the same code, delegation is great. If you're going to drop into a switch statement and have a list of different things to do for each id, terrible.
Nosredna
CMS: Thanks, your method works perfectly, it's short and sweet, and like you said in one of your comments it fulfills the purpose of applying to all 'A' elements, not only those that were on the page when it was initially rendered - the goal of this was to allow for new 'A' tags from content loaded through AJAX to keep working. Great work!
boliva
A: 

There is no way to override all anchor elements onlick event. You could add an onclick to the document body and have logic to see if the even propagated up from an anchor element, and perform the event in that case, but this solution could cause problems if your page is complex, and isn't propagating clicks in some cases.

I would stick with the getElementsByTagName solution if its feasible.

Ben
+3  A: 

Using jQuery:

$(function() {
    $("a").click(function() {
     return someMethodName($(this).attr('href'));
    });
});

function someMethodName(href)
{
    console.log(href);
    return false;
}
cxfx