24

I want to attach a function on every link on the site to change a parameter.

How can I do this without jQuery?

How do I traverse every link (it might be a DOM item) and call a function on them?

Ken Kinder
  • 12,654
  • 6
  • 50
  • 70
John Smith
  • 6,129
  • 12
  • 68
  • 123

7 Answers7

97

It's weird that nobody offered an alternative solution that uses event bubbling

function callback(e) {
    var e = window.e || e;

    if (e.target.tagName !== 'A')
        return;

    // Do something
}

if (document.addEventListener)
    document.addEventListener('click', callback, false);
else
    document.attachEvent('onclick', callback);

The pros of this solution is that when you dynamically add another anchor, you don't need to specifically bind an event to it, so all links will always fire this, even if they were added after these lines were executed. This is in contrast to all the other solutions posted so far. This solution is also more optimal when you have a large number of links on your page.

zatatatata
  • 4,761
  • 1
  • 20
  • 41
  • 2
    Someone recently added yet another answer that will add loads of event listeners but won't do anything for anchors added to the dom after the code executes. Such a simple principle but so many people seem to be completely unaware of. – HMR Jul 29 '14 at 14:53
  • 3
    I also think that this solution is better, because it adds only one event, versus potentially adding tens of events. This solution is also better, because if you dynamically add more links, it will work for them too! – Ignas2526 Jun 08 '15 at 14:53
  • 2
    It's great when someone tends to think deeply! – hex494D49 Apr 25 '17 at 09:00
  • 13
    Only works if you don't have elements nested in your A tag – Spoeken Sep 20 '17 at 12:00
  • 3
    IT'S NOT WEIRD, for example Youtube site have a lot of A tag with nested elements and this method won't work – user924 Nov 09 '17 at 21:36
  • @Spoeken If you have elements in your anchor tag, go up the DOM tree looking for a parent anchor tag. – MikeT Jan 22 '23 at 07:07
30

getElementsByTagName is supported by all modern browsers and all the way back to IE 6

var elements = document.getElementsByTagName('a');
for(var i = 0, len = elements.length; i < len; i++) {
    elements[i].onclick = function () {
        // stuff
    }
}
Joe
  • 80,724
  • 18
  • 127
  • 145
9

I wanted to offer an improvement on @zatatatata's answer which also works with links with nested elements.

function findLink(el) {
    if (el.tagName == 'A' && el.href) {
        return el.href;
    } else if (el.parentElement) {
        return findLink(el.parentElement);
    } else {
        return null;
    }
};

function callback(e) {
    const link = findLink(e.target);
    if (link == null) { return; }
    e.preventDefault();
    // Do something here
};

document.addEventListener('click', callback, false);

If the clicked element isn't a link, we search its parents to check for a link element.

jazmit
  • 5,170
  • 1
  • 29
  • 36
4
function linkClickHandler(a) {
  console.log(a.host);
}

var links = document.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) links[i].onclick = function() {
    linkClickHandler(links[i]);
}
Ahmad
  • 69,608
  • 17
  • 111
  • 137
Phil Klein
  • 7,344
  • 3
  • 30
  • 33
2

better way:

const item = document.querySelectorAll(".nav__item");

item.forEach(link => {
  link.addEventListener("click", function () {
    link.classList.add("nav__item--active");
  });
});
Joe RR
  • 262
  • 3
  • 22
  • 1
    How you can sure that all the links will have .nav__item class to bind with every anchor link – Akash Feb 27 '20 at 08:01
1

Something like this should be useful for you:

var elements = document.getElementsByTagName("a"),
    i,
    len,
    el;

for (i = 0, len = elements.length; i < len; i++) {
    el = elements[i];

    // Do what you need on the element 'el'
}
jabclab
  • 14,786
  • 5
  • 54
  • 51
0

Try using getElementsByTagName('a')

Naftali
  • 144,921
  • 39
  • 244
  • 303