getElementByClass

K

Kameleonten

To make my navigation menu work in IE I have used this script. But it
doesn't work with classes. So when I now want to use a CMS that
genererates the navigation hierarchy that uses class instead of ID it
fails. How do I modify it so it works with CLASS instead of ID?

startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes;
if (node.nodeName=="LI") {
node.onmouseover=function() {
this.className+=" over";
}

node.onmouseout=function() {
this.className=this.className.replace(" over", "");
}
}
}
}
}
window.onload=startList;

----------------------------------------

Here is my experiment that doesn't work:

function getElementbyClass(classname){
var partscollect;

var inc=0
var alltags=document.all? document.all :
document.getElementsByTagName("*")

for (i=0; i<alltags.length; i++){
if (alltags.className==classname)
partscollect=alltags
}
}


startList = function(){

if (document.all && document.getElementByClass) {
navRoot = document.getElementByClass("bulletmenu");

for (i=0; i < navRoot.partscollect.childNodes.length; i++) {
node = navRoot.partscollect.childNodes;
if (node.nodeName=="LI") {
node.onmouseover=function() {
this.className+=" over";
}

node.onmouseout=function() {
this.className=this.className.replace(" over", "");
}
}
}
}
}

I don't have any javascript experience, but with Java I have .
 
R

Randy Webb

Kameleonten said the following on 12/20/2005 8:14 PM:
To make my navigation menu work in IE I have used this script. But it
doesn't work with classes. So when I now want to use a CMS that
genererates the navigation hierarchy that uses class instead of ID it
fails. How do I modify it so it works with CLASS instead of ID?

startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes;
if (node.nodeName=="LI") {
node.onmouseover=function() {
this.className+=" over";


It may or may not be the source of your problem. But, className's can
not contain a space. What you are doing in the onmouseover is adding "
over" to the className. That contains a space and will cause a problem.
might try: this.className+="over";

Also, if your classNames onmouseover will always have over appended to
the end, it might be better to simply remove the last 4 characters from
the className than to remove the sequence "over" from the className. If
the className is "myHoverClass" when you add "over" to it, it becomes
"myHoverClassover" and removing over will remove the first one, not the
last one so it becomes "myHClassover".

Or, change the remove to match the last one, not the first one.
 
T

Thomas 'PointedEars' Lahn

Kameleonten said:
To make my navigation menu work in IE I have used this script. But it
doesn't work with classes. So when I now want to use a CMS that
genererates the navigation hierarchy that uses class instead of ID it
fails. How do I modify it so it works with CLASS instead of ID?

startList = function() {
^^^^^^^^^
Undeclared global variable.
if (document.all && document.getElementById) {

This does not make sense. You are not even using document.all,
yet testing for it. What should that accomplish anyway?

navRoot = document.getElementById("nav"); ^^^^^^^
for (i=0; i<navRoot.childNodes.length; i++) { ^
node = navRoot.childNodes;

^^^^
Undeclared global variables.
if (node.nodeName=="LI") {

Use HTMLElement::tagName instead.
node.onmouseover=function() {
this.className+=" over";

If the `class' attribute value of that element was empty before (default),
the new value could end up to be not Valid. HTML 4.01 defines the `class'
attribute value as a whitespace separated list of non-whitespace CDATA:

<URL:http://www.w3.org/TR/html4/struct/global.html#adef-class>

Also note that the specificity of a previously declared selector defines
whether changing `class' attribute value/className property has any effect
on the stylesheet cascade.

}

node.onmouseout=function() {
this.className=this.className.replace(" over", "");
}
}
}
}
}
window.onload=startList;

Assign event listeners using EventTarget::addEventListener()
[W3C DOM Level 2 Events] or eventTarget.attachEvent() [IE DOM],
if possible.

Indent (especially posted) code using spaces, not tabs.
Corrected and pretty-printed, that is

....
<html>
<head>
...
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
/**
* @author
* (C) 2003, 2004 Thomas Lahn &lt;[email protected]&gt;
* @partof
* http://pointedears.de/scripts/types.js
*/
function dhtml_isMethodType(s)
{
return (s == "function" || s == "object");
}

/*
* @author
* (C) 2004 Thomas Lahn &lt;[email protected]&gt;
* @partof
* http://pointedears.de/scripts/dhtml.js
*/
function registerEvent(o, sEvent, fListener, bUseCapture)
{
var result;

if (o)
{
if (dhtml_isMethodType(typeof o.addEventListener)
&& dhtml_isMethodType(typeof fListener))
{
o.addEventListener(sEvent, fListener, !!bUseCapture);
result = true;
}
else if (dhtml_isMethodType(typeof o.attachEvent)
&& dhtml_isMethodType(typeof fListener))
{
result = o.attachEvent("on" + sEvent, fListener);
}
else
{
o["on" + sEvent] = fListener;
result = (o["on" + sEvent] == fListener);
}
}

return result;
}

function startList()
{
if (isMethodType(typeof document.getElementById))
{
var navRoot = document.getElementById("nav");
if (navRoot && navRoot.childNodes)
{
for (var i = 0; i < navRoot.childNodes.length; i++)
{
var node = navRoot.childNodes;
if (node.tagName.toLowerCase() == "li")
{
node.onmouseover=function()
{
if (this.className)
{
this.className = this.className.replace(/\s*$/, " over");
}
else
{
this.className = "over";
}
}

registerEvent(node, 'mouseout',
function()
{
this.className = this.className.replace(/\s*over/, "");
});
}
}
}
}
}
</script>
</head>

<body onload="startList()">
...
</body>
----------------------------------------

Here is my experiment that doesn't work:

function getElementbyClass(classname){
var partscollect;

var inc=0

Unused variable.
var alltags=document.all? document.all :
document.getElementsByTagName("*")

You want to test whether `document.getElementsByTagName' refers to a
method before you call it. See above.
for (i=0; i<alltags.length; i++){
^ ^^^^^^^^^^^^^^ inefficient
Undeclared global variable.
if (alltags.className==classname)
partscollect=alltags


That would overwrite the previous value of partscollect with a reference
to the object referred to by `alltags', therefore the function does not
return a collection as implied by your use of the method below.

As I said, the value of the `class' attribute, thus the value of the
`className' property, is a whitespace-separated list of non-whitespace
CDATA. The condition above will only apply if that list has only one
element. It should be

var aResult = [];

if (alltags && alltags.length)
{
for (var i = 0, len = alltags.length; i < len; i++)
{
var o = alltags;
if (new RegExp("\\b" + classname + "\\b")
.test(o.className))
{
aResult.push(o);
}
}
}

With the provision that the value of `classname' may not contain unescaped
characters considered special in RegExp. If it does and matching such
"wildcard" attribute values is not desired, the value of `classname' has
to be escaped properly before it can be used in the RegExp() argument.
startList = function(){
^^^^^^^^^
See above.
if (document.all && document.getElementByClass) {

The document.all test is again bogus.

And globally declared functions, such as your `getElementByClass', do not
automatically become properties of the (HTMLDocument) object referred to
by `document'. If you want that, you have to do

document.getElementByClass = functionReference;

before. Test with

if (dhtml_isMethodType(typeof getElementByClass))
{

otherwise.
navRoot = document.getElementByClass("bulletmenu");
^^^^^^^
See above.
for (i=0; i < navRoot.partscollect.childNodes.length; i++) {
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^[1]
See above.

[1] This cannot work. If your getElementByClass() method worked as
intended, `navRoot' would refer to that collection. `partscollect'
is clearly defined locally through the `var' keyword. You are mixing
up contexts.
node = navRoot.partscollect.childNodes; ^^^^
[...]


See above.
I don't have any javascript experience, but with Java I have .

In Java, the concept of execution context is much more strictly implemented
than in J(ava)Script/ECMAScript, so you should have noticed that.


HTH

PointedEars
 
K

Kameleonten

To clarify my problem. This is the code that works with ID, and I got
it from http://www.alistapart.com/articles/hybrid/:

/**************Start of working code **********/
startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes;
if (node.nodeName=="LI") {
node.onmouseover=function() {
this.className+=" over";
}

node.onmouseout=function() {

this.className=this.className.replace(" over", "");
}
}
}
}
}

window.onload=startList;
/**********End off working code ************/

How do I "convert" this script so I can use it with CLASS instead?

Some comments to PointedEars:
In Java, the concept of execution context is much more strictly implemented
than in J(ava)Script/ECMAScript, so you should have noticed that.
"Does not work" is a useless error description. [psf 4.11]

As I said I don't have any JavaScript experience. That means that I
don't know the syntax or "the concept of execution context". It also
means that I don't have a debug tool for JavaScript and thats why I use
the useless error description. I still hope that you can help me with
this problem.
 
V

VK

Randy said:
className's can
not contain a space. What you are doing in the onmouseover is adding "
over" to the className. That contains a space and will cause a problem.
might try: this.className+="over";

Sorry, but not true at all. One can apply any amount of space-separated
classes to a single element:
<li class="class1 class2 class3">
in which case className will be "class1 class2 class3"
This is what the posted code does: atop of existing class it adds extra
class with mouseover styling.

To OP:
DOM doesn't have getElementByClassName or getElementsByClassName. There
are more or less functional emulations of these methods. The best and
the most time-checked is from prototype.js library
<http://prototype.conio.net/>

But much simplier/safer is keep using id's especially with such code
where className will be changed dynamically.
 
T

Thomas 'PointedEars' Lahn

Kameleonten said:
To clarify my problem. This is the code that works with ID,

"works with ID"?

So you should ask _them_, yes?
[...]
How do I "convert" this script so I can use it with CLASS instead?

It is already using the `class' attribute (through the `className'
property), but it is using it wrong or, better put, not reliably.

I already told you how to make it work reliably. If you do not
understand parts of what I posted, you should quote that parts
and ask about them, not post the same nonsense again.

[Repaired quote]
In Java, the concept of execution context is much more strictly
implemented than in J(ava)Script/ECMAScript, so you should have
noticed that. [...]
"Does not work" is a useless error description. [psf 4.11]

As I said I don't have any JavaScript experience. That means that I
don't know the syntax or "the concept of execution context".

If you knew _Java_ (Java != JavaScript), you should have recognized that
the `partscollect' variable was local, without any JavaScript knowledge;
because AFAIK in Java, all variables defined in local context are local.
It also means that I don't have a debug tool for JavaScript
and thats why I use the useless error description.

I pointed you to a description about debugging!
I still hope that you can help me with this problem.

I still hope you are willing to _learn_.

<URL:http://jibbering.com/faq/faq_notes/pots1.html>


PointedEars
 

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

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top