Element.getElementsByClassName() IE and Opera Bugs

L

Lachlan Hunt

Hi,
I'm trying to implement getElementsByClass() for the document object
and the Element interface, that supposed to work for HTML, XHTML, SVG
and MathML class attributes (including mixed namespace documents) and I
have it working perfectly in Gecko (tested in Firefox 1.0.6 and Deer
Park Alpha 2). I'm just having some serious problems with IE and a bug
in Opera.

The test [1] is supposed to get a NodeList (an Array() with an item()
method added) of elements by class name and then output an alert()
containing the tagNames of the selected elements.

After a fair bit of testing, I believe the problem is occuring with the
way I'm trying to attach the getElementsByClassName() and hasClassName()
functions to elements in IE using an HTC. It seems to be breaking at
the point within document.getElementsByClassName() where I call
element.hasClassName (line 34 of the script [2]) but my understanding of
this workaround using HTCs [3]] that I'm trying to use is very limited
and I don't understand why it's breaking.

The bug I'm finding in Opera is with hasAttributeNS() and
getAttributeNS(). For some reason, opera seems to ignore the
namespaceURI and return the attribute if the localName matches. This
isn't really a serious problem, since it would only have side effects if
an author wrote:
<x foo:class="bar">
where foo is defined as any namespace URI where class should not be
treated like the XHTML, SVG, etc. class attributes.

eg.
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:foo="http://www.example.org/foo" xml:lang="en">
<head>
<script type="text/javascript"><![CDATA[
window.onload = function() {
var e = document.getElementsByTagName("p").item(0)
if (e.hasAttributeNS("http://www.w3.org/1999/xhtml", "class")) {
alert(e.getAttributeNS("http://www.w3.org/1999/xhtml", "class"));
} else {
alert("PASS");
}
}
]]></script>
</head>
<body>
<p foo:class="FAIL">test</p>
</body>
</html>

Lastly, if anyone finds bugs with other browsers I haven't been able to
test (Mac and Linux browsers) and can suggest a solution, or has any
other improvements to the code in general, that would be greatly
appreciated.

[1]
http://lachy.id.au/dev/script/examples/DOM/getElementsByClassName/tests/001.html
[2]
http://lachy.id.au/dev/script/examples/DOM/getElementsByClassName/getElementsByClassName.js
[3] http://delete.me.uk/2004/09/ieproto.html
 
M

Martin Honnen

Lachlan Hunt wrote:

I'm trying to implement getElementsByClass() for the document object
and the Element interface, that supposed to work for HTML, XHTML, SVG
and MathML class attributes (including mixed namespace documents) and I
have it working perfectly in Gecko (tested in Firefox 1.0.6 and Deer
Park Alpha 2).

I don't think the check
new RegExp("\\b" + className + "\\b", flags).test(classNames)
is anything like perfect, consider
<http://home.arcor.de/martin.honnen/javascript/2005/08/test2005082101.html>
as an example where your check for class name "class" returns (run with
Mozilla 1.7) several elements which are not in the class with that name
but simply belong to a class where "class" is a substring of the class name.
So that regular expression is not a good check, works in some cases,
yes, but for code which is some kind of library it needs to be improved.
 
L

Lachlan Hunt

Martin said:
I don't think the check
new RegExp("\\b" + className + "\\b", flags).test(classNames)
is anything like perfect, consider
<http://home.arcor.de/martin.honnen/javascript/2005/08/test2005082101.html>
as an example where your check for class name "class" returns (run with
Mozilla 1.7) several elements which are not in the class with that name
but simply belong to a class where "class" is a substring of the class
name.
So that regular expression is not a good check, works in some cases,
yes, but for code which is some kind of library it needs to be improved.

Thanks, I should have got more information about what \b matches. The
JavaScript 1.5 Reference only states [1]:

| Matches a word boundary, such as a space. (Not to be confused with
| [\b].)

So I thought it only matched white space or the start/end of the line, I
didn't realise it also matched a hyphen and probably other characters
too. I replaced the regex with

new RegExp("(^|\\s)" + className + "(\\s|$)", flags).test(classNames);

It now passes your test cases and all of mine.

[1]
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:RegExp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top