15

trying to determine a decent, cross browser method for obtaining attributes with javascript? assume javascript library use (jQuery/Mootools/etc.) is not an option.

I've tried the following, but I frequently get "attributes" is null or not an object error when IE tries to use the "else" method. Can anyone assist?

<script type="text/javascript">
//...
    getAttr: function(ele, attr) {
      if (typeof ele.attributes[attr] == 'undefined'){
        return ele.getAttribute(attr);
      } else {
        return ele.attributes[attr].nodeValue;
      }
    },
//...
</script>


<div>
 <a href="http://www.yo.com#foo">Link</a>
</div>

using the above html, in each browser, how do I getAttr(ele, 'href')? (assume selecting the ele node isn't an issue)

tester
  • 22,441
  • 25
  • 88
  • 128

3 Answers3

16

For the vast majority of cases you can simply use the built in getAttribute function.

e.g.

ele.getAttribute(attr)

According to QuirksMode this should work on all major browsers (IE >= 6 included), with a minor exception:

In IE5-7, accessing the style attribute gives an object, and accessing the onclick attribute gives an anonymous function wrapped around the actual content.

Mark Rhodes
  • 10,049
  • 4
  • 48
  • 51
10

With regard to your question's update, you could try this.

It may be overkill, but if getAttribute() and the dot notation don't return a result, it iterates through the attributes object to try to find a match.

Example: http://jsfiddle.net/4ZwNs/

var funcs = {
    getAttr: function(ele, attr) {
        var result = (ele.getAttribute && ele.getAttribute(attr)) || null;
        if( !result ) {
            var attrs = ele.attributes;
            var length = attrs.length;
            for(var i = 0; i < length; i++)
                if(attrs[i].nodeName === attr)
                    result = attrs[i].nodeValue;
        }
        return result;
    }
};

var result = funcs.getAttr(el, 'hash');

It's up to you to do some cross-browser testing, though. :o)


Using ele.attributes, you need to access them by index, as in:

ele.attributes[0].nodeName;   // "id" (for example)
ele.attributes[0].nodeValue;  // "my_id" (for example)

Trying to pass attributes an attribute name appears to return a value whose typeof is object, so your else code is running even though ele.attributes[attr] doesn't give you the value you want.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
user113716
  • 318,772
  • 63
  • 451
  • 440
  • I updated the question to be a little more specific. How would I specify that I want the attr "href" or "hash" using your method? – tester Sep 20 '10 at 20:51
  • works great in Chrome/FF, testing in IE8, I get: Object doesn't support this property or method on this line: var result = ele.getAttribute(attr) || ele[attr] || null; – tester Sep 20 '10 at 21:05
  • eh starting to think it's the selector I'm passing to it causing the issue – tester Sep 20 '10 at 21:16
  • @tester - Works for me in IE7 and IE8. Maybe try replacing `ele.getAttribute(attr)` with `(ele.getAttribute && ele.getAttribute(attr))`. EDIT: Let me know if it was the selector. – user113716 Sep 20 '10 at 21:18
  • @patrick dw, so it appears it's how I'm going about using this. What you've done works perfectly.. Having some trouble debugging ie's issue with how I'm doing this: http://jsfiddle.net/N8CxL/ would appreciate any assistance you can further provide. – tester Sep 20 '10 at 21:35
  • @tester - Not sure. At first it was showing that `obj` in `bind` method was null, then it stopped. Maybe there's an issue with your DOMReady? – user113716 Sep 20 '10 at 21:49
  • it's something up with my bind method.. something about how 'this' doesn't properly represent the current object, so I can't use your getAttr method properly.. – tester Sep 20 '10 at 22:11
  • ah I figured it out.. it was the bind method.. I was going if (obj[i].addEventListener) {... instead of if (obj.addEventListener) {... – tester Sep 20 '10 at 22:30
  • @tester - Glad you got it figured out. :o) – user113716 Sep 20 '10 at 22:42
  • Attributes are not the same as properties. Please do not mix them up and treat them as being equivalent. – Tim Down Sep 20 '10 at 23:49
  • @tester - Updated the answer. See comment above from @Tim Down. – user113716 Sep 21 '10 at 00:04
  • Patrick: my comment was a bit aggressive. Sorry. The general confusion among developers over properties and attributes (largely the fault of jQuery and its confusing `attr()` method) is something of bugbear for me. – Tim Down Sep 21 '10 at 08:44
  • 1
    Perhaps I'm a little late to chime in here, but I think there is a typo. I think you mean to use `attrs[i].nodeName` and `attrs[i].nodeValue` in the loop. – Craig Apr 01 '12 at 21:20
  • Doesn't testing if( !result ) mean that a false-y result, like empty string, will cause the loop to run? Suggest using if (result !== null) instead. – enigment Apr 10 '13 at 13:35
  • 1
    @enigment you're right and also, there's no need to loop if the getAttribute method is present, but the attribute is not set. So I'd change the if condition to be (result !== null && !ele.getAttribute) – gigaDIE Dec 04 '14 at 16:07
5

You are trying to access properties of ele before you've established if those properties exist. Try this kind of evidence chain:

if (ele.attributes && ele.attributes[attr] && typeof ele.attributes[attr] == 'undefined')

etc.

Robusto
  • 31,447
  • 8
  • 56
  • 77