3

I'm trying to iterate "up" through the DOM nodes from a given element to get the first parent element which has the attribute 'animated'.

var el = evt.target;
    console.log(el);
while (!el.hasAttribute('animated'))
   { el = el.parentNode; }
return el;
    console.log(el);

Throws error:

>>>Uncaught TypeError: Object #<HTMLDocument> has no method 'hasAttribute'

How is this possible? I've clearly declared the variable el and the first log is correct .

jenswirf
  • 6,607
  • 9
  • 44
  • 64
  • Why are you doing `console.log(el)` AFTER you do `return el;`? The `console.log(el)` will never be executed. – jfriend00 May 30 '12 at 15:28

3 Answers3

7

The document object:

  • Is a node
  • Is the parentNode of the root element (if you were using HTML that would be the <html> element)
  • Is not an element.

Only elements have attributes, so only element objects have a hasAttribute method.

You need to stop testing when you reach the document object (or when you aren't testing an element any longer).

while (
    el.nodeType === 1 && 
    (!el.hasAttribute('animated'))
) {
Quentin
  • 857,932
  • 118
  • 1,152
  • 1,264
  • Can we also use `hasOwnProperty`? [More details over here](http://stackoverflow.com/questions/135448/how-do-i-check-to-see-if-an-object-has-an-attribute-in-javascript). – approxiblue May 30 '12 at 15:20
  • I've no idea if the DOMs for arbitrary markup documents map attributes directly onto properties or not. – Quentin May 30 '12 at 15:22
  • 1
    I would check `el.nodeType == 1` (which is guaranteed to work) instead of `el.hasAttribute` (which is not). – Tim Down May 30 '12 at 15:35
  • It fixed a strange behaviour on my (probably inefficient, since I classify myself as an noob) script. `getAttribute` returned a error on the second time which I was using it, but the first did work. I performed the `nodeType === 1` check and now it executes beautifully. +1 – Fusseldieb Aug 25 '17 at 12:23
1

var el = evt.target is a document object and therefore does not have a hasAttribute attribute.

Farhan Ahmad
  • 5,100
  • 5
  • 37
  • 69
1

You could also make it into a function that returns either null or the ancestor node that has that attribute:

function findNodeWithAttribute(el, attr) {
    while (true) {
        if (!el || !el.hasAttribute) {
            return null;
        } else if (el.hasAttribute(attr)) {
            return el;
        }
        el = el.parentNode;
    }
}
jfriend00
  • 637,040
  • 88
  • 896
  • 906