4

I have a list of items which diferent event handlers on it.

...
<li>
   <div class="item" data-id="1234">
     <h3>Item</h3>
     <div class="description">...</div>
     <ul class="lists">
        <li data-list-id="1">Add to list A<li>
        <li data-list-id="2">Add to list B<li>
        <li data-list-id="3">Add to list C<li>
     </ul>
     <button class="delete">delete</button>
   </div>
</li>
...

Every li under .list has a click event registered which looks like this:

function addToList(event){
   var id = event.target.getAttribute('data-id');
   var listId = event.target.parentNode.parentNode.getAttribute('data-id');
   // XHR stuff
}

There is no problem with this code but the parentNode.parentNode seems really fragile. For the button would be only one parentNode and for deeper nested elements parentNode^n

I guess this is a common problem and there are more robust solutions? With jQuery i would use $(target).parentNode('.item')

Whats the best way to do this without jQuery?

Slemgrim
  • 937
  • 2
  • 8
  • 23

1 Answers1

4

As part of my projects, I always write my own toolbox. Sure, I could use jQuery, but I'll stick to my precision toolkit over a sledgehammer, thanks!

With that in mind, have a look at this:

function findParent(source,filter,root) {
    root = root || document.documentElement;
    while(source != root) {
        if( filter(source)) return source;
        source = source.parentNode;
    }
}

In your case, you can now call:

var listId = findParent(
        event.target,
        function(e) {return e.attributes && e.attributes['data-id'];}
    ).getAttribute("data-id");
// note that you should probably break that down, checking if an element
// is found before getting its attribute value... or let the error
// kill your script. Either works.

Now, here it does look a bit more messy than your simple .parentNode.parentNode, but it's much more robust because it doesn't rely on depths being a certain number, which I believe is what you were aiming for.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592