[whatwg] getElementsByClassName()

On 2/3/06, Jim Ley <jim.ley at gmail.com> wrote:
> On 2/3/06, Gervase Markham <gerv at mozilla.org> wrote:
> > Jim Ley wrote:
> > > Yes, but they're all using it to attach events to every one of the
> > > class, which is why you have to look at use cases, the reason they're
> > > doing it is not because getElementsByClassName is missing, but because
> > > addEventListenerToClass or -moz-binding etc. are missing.
> >
> > But why implement addEventListenerToClass() when you could implement
> > getElementsByClassName(), which has a far more general utility? As soon
> > as a single non-event-listener-related application comes along, you find
> > you've implemented the wrong thing.
> Er, no the use case people have is that they want everything that has
> class X to respond to a particular event, if you model that with
> getElementsByClassName then you cannot change a class on an element
> and have it respond, without re-running the attachment, and manage the
> fact you've already attached it to some classes etc.

I can't believe that you're so insistent upon this extremely narrow
set of use cases and that there aren't any other popular use cases for

If there are no use cases for this function then what are the use
cases for getElementById()? I suppose this should be
addEventToElementById()? How about getElementsByTagName()? That one
too, eh?

The point of getElementsByClassName() is superior control over the
DOM. Where getElementById() falls short by only returning one element
and getElementsByTagName() falls short by only returning one,
document-mandated type of element, getElementsByClassName() gives the
author the control to collect arbitrary sets of elements which all
share the same class or set of classes.

> It does not simplify the situation at all.  It can also only happen
> once the element with the class is available, that fails the
> consistency of UI axiom, since your element will respond differently
> after the function has run.

Completely irrelevant. See getElementById() or getElementsByTagName().
The requirement for a loaded document is to be expected when one
wishes to manipulate the constructed DOM from that document.

> > Here's a use case, then: the about:license document I just checked into
> > the Mozilla codebase. When the page is called with the spelling
> > "about:licence" instead of "about:license", I use
> > getElementsByClassName() to search for elements with the class
> > "correctme", and do a search and replace within them to correct the
> > spelling. However, I can't correct it everywhere as I shouldn't be
> > mutating legal documents. But I can do it in commentary, titles,
> > contents and so on.
> What an extremely odd use case, but it is at least a use case,
> thankyou.  I'm not sure it's really one significant enough to warrant
> implementing it given the large number of other methods of achieving
> the same spelling correction.  Especially as the majority of them can
> be done without requiring javascript at all.
> Jim.

So here's a shiny use case for us all:

I want my designer to be able to specify an arbitrary set of elements
in the markup for a web app that are to be "widgets". Now if the web
app is sent out to a client that supports function X, I want to
construct this X-widget around each of the elements in the set
previously defined.

The construction of each X-widget also depends on various other
rendered states of the web app as well as the support level of the
client. In order to support sane and graceful degradation, the markup
for the app will be sent down in its barest form and the widgets will
be added via JS on the client side, taking the constraints into
consideration and acting accordingly.

It is obvious here that getElementsByClassName() is a perfect fit for
the NodeList that I want to manipulate and much better than iterating
over every node in the document or something else to that effect.

This case is not restricted to event-driven behavior in the least, yet
leverages the power of getElementsByClassName() superbly.

Now that we can get past "why" we're specifying such a function, I
feel the need to reiterate the constraints on its specification, as
some have apparently forgotten them or neglected to read the
discussion in its entirety:

1. getElementsByClassName() must be host language agnostic. That is,
it must work with HTML, XHTML, SVG, MathML, and any other markup
languages which are approved for its use. Assumptions like "class
names cannot contain a space" may be ones that we can't make in light
of this requirement (IMHO).

2. getElementsByClassName() must be *binding language* agnostic. That
is, we cannot assume that it will only be used in JS. It should be
designed, as with all of the other DOM functions to my knowledge,
without special features which are specific to any one binding
language. That said, I believe a variable number of arguments is
completely out.

3. getElementsByClassName() should succeed as expected in the simplest
use case. From our use case above, this means calling
document.getElementsByClassName("x-widget") returns all elements
containing the class "x-widget" -- never mind which other classes
those elements have.

Taking all of these constrains in mind and the further desire to
aggregate multiple sets in a terse and powerful fashion, I recommend
the array-based approach.

If getElementsByClassName() receives a string, it is to treat that
string as a class name and match all elements which contain that class

If getElementsByClassName() receives an array (synonymous with list),
which all binding languages I am aware of are capable of supplying, it
treats each entry of the array as a string and matches all elements
containing *all class names* specified in the array, regardless of
which other class names each element might have.

So in HTML + JS, this behavior would play out as follows:

<a class="Z" id="e1" />
<a class="Y Z Q" id="e2" />
<a class="A B C" id="e3" />
<a class="Q P C" id="e4" />

document.getElementsByClassName("Z") gives e1, e2
document.getElementsByClassName("P") gives e4
document.getElementsByClassName("F") gives nothing (null/nil/etc.)
document.getElementsByClassName(["Z", "Q"]) gives e2
document.getElementsByClassName(["P", "B"]) gives nothing (null/nil/etc.)

Sorry for the length, but I believe this is a fair summary of a valid
use case, the constraints on design, and a design candidate which
satisfies those constraints well.

Thank you.

Brad Fults

Received on Friday, 3 February 2006 17:49:23 UTC