Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > DOM element selectors

Reply
Thread Tools

DOM element selectors

 
 
Derek Basch
Guest
Posts: n/a
 
      02-09-2005
I have a simple XHTML document that I would like to apply javascript
functionality to:

<body>
<div class="length">9</div>
<div class="sequence">AAAAAAATTTAAA</div>
<div class="prediction">1.68509 1.60743 1.32631 1.38815 1.24905</div>

<div class="length">5</div>
<div class="sequence">TTTAAAAAA</div>
<div class="prediction">2.4898</div>

<div class="length">7</div>
<div class="sequence">TTTAAASSSSAAA</div>
<div class="prediction">2.4898 5.625 2.589 5.287</div>
</body>

Say that I wanted to select all of the <div> tags of class "length" and
operate on them. My options are limited.

1)
If I wanted to use document.getElementsByTagName() I could make each
"length" class <div> tag into a different, distinct, tag. <h1> for
"length", <h2> for "sequence", etc.. This seems rigid and
non-descriptive of the nature of the element. Also, what happens when I
run out of <h*> tags to utilize?

2)
If I want to use document.getElementById() I need to ensure that each
"length" <div> has a unique "id" attribute (length_1, length_2, etc..).
Then, create an array of these elements and operate on them.
(ref.
http://groups-beta.google.com/group/...2854908132dea?.
)
This seems cumbersome and failure prone.

3)
Finally, I could give each "length" <div> tag an "id" attribute of
"length" and select them using document.getElementsByName(). This is
not valid XHTML. Quote from W3 validator:

"An "id" is a unique identifier. Each time this attribute is used in a
document it must have a different value. If you are using this
attribute as a hock for style sheets it may be more appropriate to use
classes (which group elements) than id (which are used to identify
exactly one element)."

Why is there no DOM method for selecting a class of elements? What is
my best strategy for dealing with this issue? Thanks everyone.

 
Reply With Quote
 
 
 
 
Spats30
Guest
Posts: n/a
 
      02-09-2005
If you truly write XHTML code and have the <xml> declaration at the,
sounds to me like you would be better off saving this as an XML
document. Then create a PHP, ASP, JSP or whatever page to use a
server-side language to pull in the data (XML file) where you can
better programatically convert things to their proper H tag.

 
Reply With Quote
 
 
 
 
Michael Winter
Guest
Posts: n/a
 
      02-09-2005
Derek Basch wrote:

[snip]

> 1) If I wanted to use document.getElementsByTagName() [...]


You'd do something like

var divs = document.getElementsByTagName('div'),
type = 'length',
re = new RegExp('(^|\\s+)' + type + '(\\s+|$)');

for(var i = 0, n = divs.length; i < n; ++i) {
if(re.test(divs[i].className)) {
/* Have DIV of class 'type' */
}
}

[snip]

> 3) Finally, I could give each "length" <div> tag an "id" attribute
> of "length" and select them using document.getElementsByName().
> This is not valid XHTML. [...]


It wouldn't work, either. Unsurprisingly, the getElementsByName method
only returns elements which have a matching name attribute. With
XHTML, this is further restricted to only *form controls* which have a
matching name attribute.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
 
Reply With Quote
 
Derek Basch
Guest
Posts: n/a
 
      02-09-2005
Thanks for the solution Mike.

Spats30, that is the type of thing that I am trying to avoid. The data
actually does start out as a XML document transformed to XHTML using
XSL. Using <h*> tags would be sloppy for the reasons I previously
stated.

Seeing that you have to create a less that elegant RegExp to solve this
problem am I correct in assuming that the DOM is in need of something
like document.getElementsByClassName() ?

 
Reply With Quote
 
Michael Winter
Guest
Posts: n/a
 
      02-09-2005
Derek Basch wrote:

[snip]

> Seeing that you have to create a less that elegant RegExp to solve
> this problem [...]


You don't /have/ to. The regular expression, /(^|\s+)<class
name>(\s+|$)/, is just the safe way of doing it: it ensures that you
don't get partial matches (as you would with the indexOf method), and
it's more flexible than a simple comparison. However, if you can
guarantee that a simpler approach is possible, then use it.

> am I correct in assuming that the DOM is in need of something like
> document.getElementsByClassName() ?


It might be useful in some cases, but it's trivial to implement. The
only advantage to a defined method that I can think of (at the moment)
is that it would be implemented natively so it would execute faster.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      02-10-2005
Derek Basch wrote:
[...]
> Seeing that you have to create a less that elegant RegExp to solve this
> problem am I correct in assuming that the DOM is in need of something
> like document.getElementsByClassName() ?
>


What you are trying to do is create a group of elements that you
can access with a single identifier, much how tag name can be
used to return a collection of elements with a particular tag.

Using the class attribute is a bit if a hack, as class is meant
for applying style attributes, not creating a collection of
elements.

What is "missing" is a way of creating a group - "groupid"?
Then a method such as "document.getElementsByGroupId('aGroup')"
might return a collection of the group so identified.

Perhaps you might suggest it to the XHTML working group, or
discuss it here:

<URL:http://lists.w3.org/Archives/Public/www-html-editor/2005JanMar/>
<URL:http://lists.w3.org/Archives/Public/www-html/>

--
Rob
 
Reply With Quote
 
Derek Basch
Guest
Posts: n/a
 
      02-10-2005
Thanks! That answers my question. I ran into this idea a few years ago
and had given up on it.

RobG wrote:
> Derek Basch wrote:
> [...]
> > Seeing that you have to create a less that elegant RegExp to solve

this
> > problem am I correct in assuming that the DOM is in need of

something
> > like document.getElementsByClassName() ?
> >

>
> What you are trying to do is create a group of elements that you
> can access with a single identifier, much how tag name can be
> used to return a collection of elements with a particular tag.
>
> Using the class attribute is a bit if a hack, as class is meant
> for applying style attributes, not creating a collection of
> elements.


I more or less realized that when I grouped the tags by using a class
attribute. I actually thought about writing something like:

For this example the XHTML class attribute does not refer to the class
selector functionality of CSS.

> What is "missing" is a way of creating a group - "groupid"?
> Then a method such as "document.getElementsByGroupId('aGroup')"
> might return a collection of the group so identified.


A groupid attribute would be ideal. It would be nice to have an array
returned with one line of code like
document.getElementsByGroupId('aGroup').

Crazy second thought....

Why couldnt the class attribute be used as the selector? The id
attribute is already used as a selector in both the DOM and CSS
contexts. And isnt the idea of a class:

a collection of things sharing a common attribute; "there are two
classes of detergents"
http://www.cogsci.princeton.edu/cgi-...e=1&word=class

 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      02-10-2005
Derek Basch wrote:
[...]
> Crazy second thought....
>
> Why couldnt the class attribute be used as the selector? The id
> attribute is already used as a selector in both the DOM and CSS
> contexts. And isnt the idea of a class:
>
> a collection of things sharing a common attribute; "there are two
> classes of detergents"
> http://www.cogsci.princeton.edu/cgi-...e=1&word=class
>


Not really so crazy. the HTML 4.01 spec says:

Quote:
class = list
This attribute assigns a class name or set of class names to
an element. Any number of elements may be assigned the same
class name or names. Multiple class names must be separated
by white space characters.
Animatable: yes.

The class attribute assigns one or more class names to an
element. The element may be said to belong to these classes.
A class name may be shared by several element instances. The
class attribute has several roles:

* As a style sheet selector (when an author wishes to assign
style information to a set of elements).
* For general purpose processing by user agents.
Which would seem to suggest that class should be able to be used
exactly as you have described.

I understand Mike's point that it is fairly trivial to use
getElementsByTagName then process them to roll-your-own
collection (actually by building an array you get something more
versatile than a collection anyway), but it gets more complex if
you have to get different element tags so you may have to
recurse down all the children of the body tag to get what you
want.

As an interim measure, why not write your own
getElementByClassName() that does exactly that? Here's a start
below. It should be possible to declare the cArray in the
initial function, then make the recursion routine an internal
function (gets away from global array).

Also when testing the match of the class name, it needs to use a
regular expression to match the class as part of a
space-delimited string (i.e. the element may have multiple class
names).

I'll leave that up to you (or Mike, if he's still watching).

Uncomment the debug to watch the nodes being processed.

No doubt this can be optimised further, but I think you get the
idea. Properly optimised, it is perhaps 6 or 7 lines of code.

<html><head>
<title>getElementsByClassName</title>
<script type="text/javascript">

function getElementsByClassName(c) {
cArray = []; // Global scope intentional
var n = document.getElementsByTagName('body')[0];
doTree(n,c);
return cArray;
}

function doTree(n,c) {
if (n.className && n.className == c)
cArray.push(n);

// Some debug...
// var ct = (n.className)? n.className : 'no class';
// alert(n.nodeName + ' : ' + ct);

for (var i=0; i<n.childNodes.length; i++) {
doTree(n.childNodes[i],c);
}
}
</script>
</head>
<body>

<input type="button" value="Click me" onclick="
var robArray = getElementsByClassName('rob');
alert(robArray.join('\n'));
">

<p class="rob">rob para</p>
<p class="rob">rob para2</p>
<div class="rob">rob div</div>
<div class="rob">rob div2</div>

</body>
</html>


--
Rob
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      02-10-2005
RobG wrote:
[...]
> Also when testing the match of the class name, it needs to use a
> regular expression to match the class as part of a
> space-delimited string (i.e. the element may have multiple class
> names).

[...]

replace:

> if (n.className && n.className == c)


with:

var z = new RegExp('\\b' + c + '\\b');
if (n.className && z.test(n.className))

Here's the full script - OK, it's 14 lines not 7, but there you
go. Also made doTree internal so no globals. It is a little
slow, it takes about 0.5ms per element so for large documents
with say 1,000 elements, it will be quite slow.

Better to narrow the scope by enclosing the elements you want to
group in a div, then start there rather than with the body tag.

<script type="text/javascript">

function getElementsByClassName(c) {
var cArray = [];
var n = document.getElementsByTagName('body')[0];
var z = new RegExp('\\b' + c + '\\b');

function doTree(n) {
if (n.className && z.test(n.className))
cArray.push(n);
for (var i=0, len=n.childNodes.length; i<len; i++) {
doTree(n.childNodes[i]);
}
}
doTree(n);
return cArray;
}

</script>



--
Rob
 
Reply With Quote
 
Derek Basch
Guest
Posts: n/a
 
      02-11-2005
Thanks Rob! That answers all my questions and then some! I will let you
know how that implementation goes. I will use getElementsByClassName to
dynamically build some tables.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to Update/insert an xml element's text----> (<element>text</element>) HANM XML 2 01-29-2008 03:31 PM
set dom element class (if element was dynamically created) ted benedict Javascript 3 01-27-2006 01:29 AM
IE on attribute selectors tshad ASP .Net 1 11-12-2004 11:05 PM
CSS background competing selectors question Derek Clarkson HTML 3 11-07-2003 12:08 AM
Class and ID Selectors (CSS question) Matt Beckwith HTML 3 07-13-2003 08:39 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57