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
  • 7,087
  • 11
  • 45
  • 65
  • 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
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 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,148
  • 6
  • 40
  • 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
  • 683,504
  • 96
  • 985
  • 979