Jump to content

JS: getElement, item() & childNodes[]


tinfanide

Recommended Posts

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>JS: childNodes</title><script type="text/javascript">window.onload = function(){var li = document.getElementsByTagName("ul")[0].childNodes;var i;var list;for (i=0; i<li.length; i++)	{		list = li[i];		if(list.nodeType == 1){		list.style.color = "red";		}	}var ul = document.getElementsByTagName('ul');var li = document.getElementsByTagName('li');ul.item(1).childNodes[1].style.color = 'green';	}</script></head><body><ul><li>List 1</li><li>List 2</li><li>List 3</li><li>List 4</li></ul><ul><li>List 1</li><li>List 2</li><li>List 3</li><li>List 4</li></ul></body></html>

I remember asking similar questions about childNodes here and now I would like to learn more from you guys:I wanted to shorten the way of getting elements:Suppose I want to color green the second ul's List 1,I know I can write something like:

document.getElementsByTagName('ul')[1].getElementsByTagName('li')[0].style.color = 'green';

But I wanted to make it precise and write something like:

var ul = document.getElementsByTagName('ul');ul.item(1).childNodes[1].style.color = 'green';

But in IE, List 2 was greened but in Firefox, List 1 was greened. It seems that IE counts childNodes in a different way from what Firefox does. Is that right? In effect, it seems to convince me. But how can we fix it?

Link to comment
Share on other sites

According to the MDN, childNodes is read-only.https://developer.mozilla.org/En/DOM/Node.childNodesI suppose another way would be to give the <ul> an id, then do something like this:

//given an <ul> with id of "mylist"var items = document.getElementById("mylist").getElementsByTagName("li");items[1].style.color = "green";

or give all the li's a className and take one extra method out of the equationhttps://developer.mozilla.org/en/DOM/docume...entsByClassName

//given a group of <li>'s with a class of "mylist_item"var items = document.getElementsByClassName("mylist_item");items[1].style.color = "green";

Link to comment
Share on other sites

I see. It's bit tricky in JS.TagName seems not very dependable. In many cases I have tried, TagName caused me much trouble when I wanted to get an element.By Id or className is better.How about item()? Is that similar to childNodes[]?

Link to comment
Share on other sites

According to the MDN, childNodes is read-only.
I think what they mean by that is that you can't change the property directly. Like elem.childNodes = [some_value];You can still operate on the elements in the collection.
I see. It's bit tricky in JS.TagName seems not very dependable. In many cases I have tried, TagName caused me much trouble when I wanted to get an element.By Id or className is better.How about item()? Is that similar to childNodes[]?
getElementsByTagName is very dependable. You just need to know how to use it. It isn't the best option if you only need to select a single element, though. For that, you should use an id. getElementsByClassName is not supported in IE 8 or lower so that's not always the greatest way to go either, unless you have a custom defined function.I can't find any documentation on item() so I can't comment on it too much. It looks to me like it just retrieves the item at whatever index is provided, so yeah, I'd say it's similar to childNodes.The reason you are seeing two different elements change to green, though, is because IE does not include text nodes in childNodes while standards compliant browsers do. All those line breaks in your HTML create text nodes. If you put all your HTML on one line, then the other browsers would style the second li, too. The other alternative is to filter out all text nodes using a loop, styling the first element node you encounter. That might look something like this:
var ul = document.getElementsByTagName('ul');var children = ul.item(1).childNodes;var child = null;for (x=0, y=children.length; x<y; x++) {	if (children[x].nodeType == 1) {		child = children[x];		break;	}}child.style.color = 'green';

Link to comment
Share on other sites

According to the MDN, childNodes is read-only.
The childNodes property is read-only because it's a nodelist, but each node in the list is allowed to be modified.
Link to comment
Share on other sites

I argue for going back to the tagName technique. An id technique is precise, but not scalable.(Scalable means the technique can be applied to an arbitrary number of items, rather than a fixed set of items.)I'm working on a project right now that does a thing you've seen before. You click on a label, and that causes a container beneath it to toggle open or closed. I have 6 of these widgets and I might add more. A single function handles them all. The widgets are structured so that the second div returned by getElementsByTagName is always the one to to be toggled.The beauty of the technique is that the function doesn't need some kind of lookup table to find the relationship between the clicked item and the item to be toggled. If I want to add a new widget, all I have to do is add the HTML. The JavaScript doesn't change.

Link to comment
Share on other sites

I think what they mean by that is that you can't change the property directly. Like elem.childNodes = [some_value];You can still operate on the elements in the collection.getElementsByTagName is very dependable. You just need to know how to use it. It isn't the best option if you only need to select a single element, though. For that, you should use an id. getElementsByClassName is not supported in IE 8 or lower so that's not always the greatest way to go either, unless you have a custom defined function.I can't find any documentation on item() so I can't comment on it too much. It looks to me like it just retrieves the item at whatever index is provided, so yeah, I'd say it's similar to childNodes.The reason you are seeing two different elements change to green, though, is because IE does not include text nodes in childNodes while standards compliant browsers do. All those line breaks in your HTML create text nodes. If you put all your HTML on one line, then the other browsers would style the second li, too. The other alternative is to filter out all text nodes using a loop, styling the first element node you encounter. That might look something like this:
var ul = document.getElementsByTagName('ul');var children = ul.item(1).childNodes;var child = null;for (x=0, y=children.length; x<y; x++) {	if (children[x].nodeType == 1) {		child = children[x];		break;	}}child.style.color = 'green';

Yes, I see the points.The ID technique is precise but not scalable. TagName could be of great use if used wisely or skillfully.But it really takes me much time to master the techniques of TagName coz I find I have always been confused by the JS concepts.Anyway, thanks for the scripts and the discussion.
Link to comment
Share on other sites

I argue for going back to the tagName technique. An id technique is precise, but not scalable.(Scalable means the technique can be applied to an arbitrary number of items, rather than a fixed set of items.)I'm working on a project right now that does a thing you've seen before. You click on a label, and that causes a container beneath it to toggle open or closed. I have 6 of these widgets and I might add more. A single function handles them all. The widgets are structured so that the second div returned by getElementsByTagName is always the one to to be toggled.The beauty of the technique is that the function doesn't need some kind of lookup table to find the relationship between the clicked item and the item to be toggled. If I want to add a new widget, all I have to do is add the HTML. The JavaScript doesn't change.
i'm not sure i quite catch your meaning of "second" unless that's the way your program intends it.for that editor i worked on, i used PHP and foreach() to generate a "single" 'id'.$param and a eventHandler=function($param=count(of foreach)) for each container.then, the same function is called but the ($param) keeps track of which container needs to be processed.(hope that made sense, kind of "pseudo-code' ??)this ends up with a lot of HTML being generated though, am wondering if there's a more efficient way to do that. (your "beauty technique" seems to be doing that, if i'm guessing correctly.)
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...