Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get href of anchor when the event.target is HTMLImageElement?

I want to get the href of an anchor element when it is clicked. I am using the following javascript code:

document.addEventListener('click', function (event)
{
    event = event || window.event;
    var el = event.target || event.srcElement;

    if (el instanceof HTMLAnchorElement)
    {
        console.log(el.getAttribute('href'));
    }
}, true);

This works perfectly for an embedded anchor such as this:

<div><p><a href='link'></a></p><div>

But it doesn't work when I am working with an anchor and an image:

<div><a href='link'><img></a></div>

The event.target is returning the image instead of the anchor. The javascript code can be amended with the following if case to get around this:

document.addEventListener('click', function (event)
{
    event = event || window.event;
    var el = event.target || event.srcElement;

    if (el instanceof HTMLImageElement)
    {
        // Using parentNode to get the image element parent - the anchor element.
        console.log(el.parentNode.getAttribute('href'));
    }
    else if (el instanceof HTMLAnchorElement)
    {
        console.log(el.getAttribute('href'));
    }
}, true);

But this doesn't seem very elegant and I'm wondering if there is a better way.

!IMPORTANT! NOTE: Keep in mind, I have no access to an ID or class, or any other traditional identifier for that matter. All I know is that there will be an anchor clicked and I need to get its href. I don't even know where it will be, if it exists or will be created later.

EDIT: Please no jQuery or other javascript libraries.

like image 317
Aurelije Aure Avatar asked Mar 24 '15 01:03

Aurelije Aure


People also ask

How do I get a target href event?

To get the value of the href attribute of a clicked link, create an event listener using AddEventListener() and retrieve the value of the href attribute using Element. target() .

What is event target in HTML?

The target event property returns the element that triggered the event. The target property gets the element on which the event originally occurred, opposed to the currentTarget property, which always refers to the element whose event listener triggered the event.


2 Answers

Instead of looping all anchors in the DOM, lookup from the event.target element.
Using JavaScript's .closest() MDN Docs

addEventListener('click', function (event) {
  event.preventDefault();                     // Don't navigate!
  const anchor = event.target.closest("a");   // Find closest Anchor (or self)
  if (!anchor) return;                        // Not found. Exit here.
  console.log( anchor.getAttribute('href'));  // Log to test
});
<a href="http://stackoverflow.com/a/29223576/383904">
  <span>
      <img src="//placehold.it/200x60?text=Click+me">  
  </span>
</a>

<a href="http://stackoverflow.com/a/29223576/383904">
  Or click me
</a>

it basically works like jQuery's .closest() which does

Closest or Self (Find closest parent... else - target me!)

better depicted in the example above.

like image 92
Roko C. Buljan Avatar answered Oct 05 '22 18:10

Roko C. Buljan


Rather than adding a global click handler, why not just target only anchor tags?

var anchors = document.getElementsByTagName("a");
for (var i = 0, length = anchors.length; i < length; i++) {
  var anchor = anchors[i];
  anchor.addEventListener('click', function() {
    // `this` refers to the anchor tag that's been clicked
    console.log(this.getAttribute('href'));
  }, true);
};

If you want to stick with the document-wide click handler then you could crawl upwards to determine if the thing clicked is-or-is-contained-within a link like so:

document.addEventListener('click', function(event) {
    event = event || window.event;
    var target = event.target || event.srcElement;

    while (target) {
      if (target instanceof HTMLAnchorElement) {
        console.log(target.getAttribute('href'));
        break;
      }

      target = target.parentNode;
    }
}, true);

This way at least you'd avoid writing brittle code that has to account for all of the possible types of anchor-children and nested structure.

like image 31
bvaughn Avatar answered Oct 05 '22 20:10

bvaughn