On 1 sep, 18:46, "Joel Webber" <
j...@google.com> wrote:
> All,
> There is certainly a possibility that this change was a mistake, but it does
> *not* appear cut-and-dried from reading the spec. Here is the actual text
> from the DOM spec:
>
> ---
> getAttribute
> Return Value
> DOMString The Attr value as a string, or the empty string if that
> attribute does not have a specified or default value.
> ---
>
> Depending upon how you interpret that (especially the definition of the
> phrase 'does not have a specified or default value'), you could see it
> either way.
Given that the DOM explicitly calls out nulls everywhere, I think it's
pretty clear what the intended reading is here.
Add to that some definitions taken from elsewhere in the same doc:
---
Interface Attr
[...]
The attribute's effective value is determined as follows: if this
attribute has been explicitly assigned any value, that value is the
attribute's effective value; otherwise, if there is a declaration for
this attribute, and that declaration includes a default value, then
that default value is the attribute's effective value; otherwise, the
attribute does not exist on this element in the structure model until
it has been explicitly added.
---
i.e. an attribute's value cannot be 'null'.
document.createAttribute("foo") for instance creates an attribute with
an empty-string value, not null.
Some more quoting:
---
getAttributeNode
Return Value
Attr The Attr node with the specified name (nodeName) or null if
there is no such attribute.
---
Given that getAttribute is defined in term of "Attr", there must be an
Attr returned for getAttributeNode with the same parameter. It follows
that getAttribute() returns an empty string when getAttributeNode()
would return null.
> It certainly doesn't specify that you *can* depend upon a null
> return value to determine that an attribute doesn't exist. In fact, it
> doesn't even address the definition of a 'non-existent' attribute. You could
> make the argument that it enumerates the valid types for the return value as
> "a string, or the empty string", specifically excluding 'null'. Or you could
> reasonably argue that all browsers *do* return null for undefined
> attributes.
What do mean "non-existent attribute" and "undefined attributes"? Are
you talking about attributes that aren't valid on an element per some
DTD or schema? The DOM doesn't deal with validation (but it deals with
attribute declarations and thus default values).
Otherwise, either an Element contains some Attr with a given name in
its 'attributes' NamedNodeMap property, or it doesn't. Such an Attr
can either exist because it has been "specified" (present in the
markup when parsed, or added later by setAttribute/setAttributeNS or a
combination of createAttribute/createAttributeNS and either
setAttributeNode/setAttributeNodes or attributes.setNamedItem/
setNamedItemNS) orbecause there's a declaration assigning it a default
value.
> But the reality is that it's not entirely dependable. Let me
> demonstrate by example:
>
> <div id='foo'>
>
> var foo = document.getElementById('foo');
> getAttribute('id')
> IE7: foo
> Firefox3: foo
> getAttribute('className')
> IE7: ""
> Firefox3: null
> getAttribute('tabIndex')
> IE7: 0
> Firefox3: null
> getAttribute('xxx')
> IE7: null
> Firefox3: null
Try this:
<!DOCTYPE html>
<script src="
http://json.org/json2.js"></script>
<script>
function test() {
var foo = document.getElementById("foo");
var attrNames = ["id", "ID", "className", "class", "tabIndex",
"tabindex", "xxx", "x", "href", "target"];
for (var i=0,l=attrNames.length; i < l; i++) {
var attrName = attrNames[i];
w(attrName + ": "
+ JSON.stringify(foo[attrName]) + ", "
+ JSON.stringify(foo.getAttribute(attrName)) + ", "
+ JSON.stringify(foo.getAttribute(attrName, 1)) + ", "
+ JSON.stringify(foo.getAttribute(attrName, 2)) + ", "
+ JSON.stringify((foo.getAttributeNode(attrName) ||
{nodeValue:""}).nodeValue));
}
}
</script>
<body onload="test()">
<a id="foo" href="document" x="" class="bar"></a>
IE7:
log: id: "foo", "foo", "foo", "foo", "foo"
log: ID: undefined, "foo", null, "foo", "foo"
log: className: "bar", "bar", "bar", "bar", ""
log: class: undefined, null, null, null, "bar"
log: tabIndex: 0, 0, 0, 32768, 0
log: tabindex: undefined, 0, null, 32768, 0
log: xxx: undefined, null, null, null, ""
log: x: "", "", "", "", ""
log: href: "
http://software.hixie.ch/utilities/js/live-dom-viewer/
document", "
http://software.hixie.ch/utilities/js/live-dom-viewer/
document", "
http://software.hixie.ch/utilities/js/live-dom-viewer/
document", "document", "
http://software.hixie.ch/utilities/js/live-dom-
viewer/document"
log: target: "", "", "", "", ""
FF3:
log: id: "foo", "foo", "foo", "foo", "foo"
log: ID: undefined, "foo", "foo", "foo", "foo"
log: className: "bar", null, null, null, ""
log: class: undefined, "bar", "bar", "bar", "bar"
log: tabIndex: 0, null, null, null, ""
log: tabindex: undefined, null, null, null, ""
log: xxx: undefined, null, null, null, ""
log: x: undefined, "", "", "", ""
log: href: "
http://software.hixie.ch/utilities/js/live-dom-viewer/
document", "document", "document", "document", "document"
log: target: "", null, null, null, ""
Particularly, compare:
- the first and second column on IE7 results
- the fourth column in IE7 results with the second column in FF3
results
The last column is my interpretation of the the DOM.
Net results:
As I previously said, IE's getAttribute(..., 2) is equivalent to FF3's
getAttribute, except for tabIndex and className (these are known IE
quirks).
IE's getAttributeNode() is known to return null only for attributes
that would be invalid (for valid attributes, it returns an Attr,
whether or not the attribute has a default value per HTML's DTD).
Found on
http://fluidproject.org/blog/page/2/ here's a workaround for
hasAttribute():
var attr = elem.getAttributeNode("tabindex");
return attr ? attr.specified : false;
...well, except for those cases where the Attr has a default value...
Maybe this would work (untested):
var attr = elem.getAttributeNode("tabindex");
return attr ? attr.specified || !!attr.value : false;
(except for cases where the default value is the empty string...)
See also
http://tobielangel.com/2007/1/11/attribute-nightmare-in-ie