4

Scenario: I have an unordered list of list items's. In each list item is a span and in each span is an img tag. So my html structure looks like this.

<ul class="slider-controls">
    <li data-preview1="./images/1.1.jpeg" data-preview2="./images/1.2.jpeg"><span><img src="./images/color1.jpeg"></img></span></li>
    <li data-preview1="./images/2.1.jpeg" data-preview2="./images/2.2.jpeg"><span><img src="./images/color2.jpeg"></img></span></li>
    <li data-preview1="./images/3.1.jpeg" data-preview2="./images/3.2.jpeg"><span><img src="./images/color3.jpeg"></img></span></li>
  </ul>

The img tags are just tiny square colour swatches, and the spans are styled into circles so what you have is basically a colour picker of three coloured dots for the user to click on.

When a user clicks on the li, I'm using javascript to grab the data-previews so that I can use that information to change a picture. This works perfectly if the user clicks slightly outside the circle. However, if they click inside the circle, they end up click on the img tag. But the data I need is two parent nodes up in the li tag!

So I wrote a recursive function to address this.

function findUpTag(el, tag) {
  console.log(el.tagName, tag);
    if (el.tagName === tag) {
      console.log("success!", el);
      return el;
    } else {
      findUpTag(el.parentNode, tag);
    }
}

I use it like so findUpTag(el, "LI");

I know my recursive search is working because I always get the console.log("success") output when the current element === "LI".

However, my return value when I click on the image tag is always undefined! Even when my method finds the LI!

What am I doing wrong?

Seanyboy Lee
  • 165
  • 1
  • 12
  • 2
    If they are clicking the `img` tag, the event should just be allowed to bubble up to the parent `li`. How are you attaching to the event in the first place? – Matt Burland Apr 28 '17 at 18:06

1 Answers1

5

It's because you're not returning the result of the recursive call. You also need to handle the case of el.parentNode being null:

function findUpTag(el, tag) {
  console.log(el.tagName, tag);
    if (el.tagName === tag) {
      console.log("success!", el);
      return el;
    } else {
      return el.parentNode ? findUpTag(el.parentNode, tag) : null; // <====
    }
}

FWIW, while you can use recursion for this, there's no need to; there's only one path up the tree. So it could just be a simple loop:

function findUpTag(el, tag) {
  while (el) {
    if (el.tagName === tag) {
      console.log("success!", el);
      return el;
    }
    el = el.parentNode;
  }
  return null;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875