problem addressing objects using childNodes

A

adam

i'm working on a portion of a CMS that allows content-admins to browse
a product list, and add individual products into the taxonomy by
clicking checkboxes next to categories they might belong in.

since the taxonomy is a rather long list, i'm hiding and showing divs
for the secondary and tertiary links, so when a user clicks on the
checkbox for the parent category, the children appear in a second (and
third) div, with checkboxes of their own.

however, i'd like for the secondary and third level checkboxes to
become unchecked when the parent is. i've tried addressing them in
numerous ways, but something consistently gets lost, in that i keep
getting "x doesn't have any properties" errors.


ie:
var parentnode = document.getElementById(divName);
var allMyChildren = parentnode.childNodes.getElementsByName("INPUT");
alert(allMyChildren.length);

this returns the proper length, but then

for (var i=0;i < allMyChildren.length;i++) {
var chklist = allMyChildren;
if (chklist.type == "checkbox") {
// uncheck it
}
}

this consistently returns that chklist has no properties.


i'm clearly just not understanding how to properly manage the
childNodes array i'm guessing. any thoughts?
 
R

RobG

adam said:
i'm working on a portion of a CMS that allows content-admins to browse
a product list, and add individual products into the taxonomy by
clicking checkboxes next to categories they might belong in.

since the taxonomy is a rather long list, i'm hiding and showing divs
for the secondary and tertiary links, so when a user clicks on the
checkbox for the parent category, the children appear in a second (and
third) div, with checkboxes of their own.

however, i'd like for the secondary and third level checkboxes to
become unchecked when the parent is. i've tried addressing them in
numerous ways, but something consistently gets lost, in that i keep
getting "x doesn't have any properties" errors.


ie:
var parentnode = document.getElementById(divName);
var allMyChildren = parentnode.childNodes.getElementsByName("INPUT");

Not quite sure what this evaluates to. parentnode appears to be a DIV.
At a guess, you are trying to get all the input elements inside the DIV
using getElementsByTagName, so:

var allMyChildren = parentnode.getElementsByTagName("INPUT");
alert(allMyChildren.length);

this returns the proper length, but then

Probably pure luck. The above should fix the error, the rest seems OK.
for (var i=0;i < allMyChildren.length;i++) {
var chklist = allMyChildren;
if (chklist.type == "checkbox") {
// uncheck it
}
}
 
A

adam

getElementsByTagName reports itself as not being a function in firefox
1.0. is this an IE only DOM thing? getElementsByName reports no other
error than the addressed object having no properties.

thanks for the input though. there's definitely something screwy goin
on.


here's a rough version of the messy, test-riddled code i've got:

function showChildren(chkBoxName,divName) {
if((boxName.checked) == (true)) {
document.getElementById(divName).style.visibility = "visible";
document.getElementById(divName).style.height = "100%";
document.getElementById(divName).style.width = "100%";
} else {
document.getElementById(divName).style.visibility = "hidden";
document.getElementById(divName).style.height = "0";
document.getElementById(divName).style.width = "0";

var parentNode = document.getElementById(divName);
var allMyChildren= parentNode.childNodes;
var divChildren =
allMyChildren.getElementsByTagName("DIV");
divChildren.style.visibility = "hidden"; // doesn't work
whatsoever, returns no error

var inputChildren =
parentNode.childNodes.getElementsByTagName("INPUT");
alert(inputChildren.length); // this test returns
correctly

for (var i=0;i < allMyChildren.length;i++) { //loops proper number of
times but for the code within breaking it.
var test =
document.getElementById(divName).item;

if (test.type == "checkbox") {
test.checked = chk.unchecked;
}
}

etc

html:
an average php generated div:

<div ID="'.$PROD_EDP.'_'.$Sections_ID{$D}[$S].'"
style="visibility:hidden; overflow:show; position:relative; height:5;
background-color:FCFCCF;">


an average checkbox above it:

<input type="checkbox"
onclick="showChildren(this,\''.$PROD_EDP.'_'.$Sections_ID{$D}[$S].'\')"
ID="'.$PROD_EDP.'_'.$Sections{$D}[$S].'_'.$D.'-'.$S.'">
 
M

Mick White

adam said:
getElementsByTagName reports itself as not being a function in firefox
1.0. is this an IE only DOM thing? getElementsByName reports no other
error than the addressed object having no properties.

thanks for the input though. there's definitely something screwy goin
on.


here's a rough version of the messy, test-riddled code i've got:

function showChildren(chkBoxName,divName) {
if((boxName.checked) == (true))

function showChildren(chkBoxName,divName) {
var d=document.getElementById(divName);

d.style.visibility =boxName.checked?"visible":"hidden";
d.style.height = boxName.checked?"100%":"0";
d.style.width = boxName.checked?"100%";:"0";

{
document.getElementById(divName).style ;
document.getElementById(divName).style.height = "100%";
document.getElementById(divName).style.width = "100%";
} else {
document.getElementById(divName).style.visibility = "hidden";
document.getElementById(divName).style.height = "0";
document.getElementById(divName).style.width = "0";

var parentNode = document.getElementById(divName);

//I would not use "parentNode" as a variable. use d (see above)

var allMyChildren= parentNode.childNodes;
var divChildren =
allMyChildren.getElementsByTagName("DIV");
// I think what you want is:
var divChildren = d.getElementsByTagName("DIV");
// divs nested in d.

divChildren.style.visibility = "hidden"; // doesn't work
whatsoever, returns no error

//divChildren is a collection, to hide them,
//iterate through the collection:

var z=divChildren.length;
while(z--) divChildren[z].style.visibility = "hidden";

// but if you hide the parent, then the nested divs will inherit the
style, no?

[snip]

Mick
 
R

RobG

adam said:
getElementsByTagName reports itself as not being a function in firefox
1.0. is this an IE only DOM thing? getElementsByName reports no other
error than the addressed object having no properties.

getElementsByTagName is a method of a DOM element object. It works
(AFAIK)[1] in any browser that supports getElementById. You need to
use it with an element, e.g.

// Using the 'document' object
var allTheInputs = document.getElementsByTagName('INPUT');

// Using an element
var divRef = document.getElementById('someDiv');
var allTheInputsInTheDiv = divRef.getElementsByTagName('INPUT');
thanks for the input though. there's definitely something screwy goin
on.


here's a rough version of the messy, test-riddled code i've got:

Pleas don't post code with tabs, replace with 2 spaces for indents.
function showChildren(chkBoxName,divName) {
if((boxName.checked) == (true)) {

'boxName' is not defined, I guess you meant 'chkBoxName'. It seems to
be a reference to a checkbox, so the test can be:

if( chkBoxName.checked ) {
...

If it's checked, the above will return true.
document.getElementById(divName).style.visibility = "visible";
document.getElementById(divName).style.height = "100%";
document.getElementById(divName).style.width = "100%";
} else {
document.getElementById(divName).style.visibility = "hidden";
document.getElementById(divName).style.height = "0";
document.getElementById(divName).style.width = "0";

All this seems to be hiding/showing an element with the same behaviour
as the display property. You can replace all of the above with:

var parentNode = document.getElementById(divName);

if ( chkBoxName.checked ) {
div.style.display = '';
} else {
div.style.display = 'none';

It could be trimmed down even further if the following is not
necessary.
var parentNode = document.getElementById(divName);

Already done this, so delete it.
var allMyChildren= parentNode.childNodes;

childNodes returns an HTML collection, so 'allMyChildren' is a
collection.
var divChildren =
allMyChildren.getElementsByTagName("DIV");

Collections (like arrays) do not have the getElementsByTagName method,
so 'divChildren' will be undefined - your script likely goes no
further, certainly anything dependending upon divChildren to have a
value will not work.
divChildren.style.visibility = "hidden"; // doesn't work
whatsoever, returns no error

var inputChildren =
parentNode.childNodes.getElementsByTagName("INPUT");

parentNode.childNodes is a collection, so no getElementsByTagName
method...
alert(inputChildren.length); // this test returns
correctly

Dependind on what 'correctly' means to you :)

If you hide the parent, all the decendents will be hidden too, there is
no need to hide them individually - unless you want them to be
displayed one by one when clicked on.
for (var i=0;i < allMyChildren.length;i++) { //loops proper number of
times but for the code within breaking it.
var test = document.getElementById(divName).item;


If you are after the first child of the element (which seems to be
'parentNode' again), then you can find using:

var test = parentNode.firstChild;
if (test.type == "checkbox") {
test.checked = chk.unchecked;

if ( test.type && 'checkbox' == test.type ) {
test.checked = false;

[...]

When I read your first post, I thought you wanted to uncheck checkboxes
that were decendants of other checkboxes, however the above code seems
to be also hiding and showing elements. Below is some code that just
does the checkbox thing - it also checks all the parents of a
checkbox so you can just check some lower class and all the parents are
done too.


[1] Completely unsupported opinion, but I'd be very surprised if any
browser in common use that supported getElementById did not also
support getElementsByTagName.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html><head><title> Trees </title>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">
<style type="text/css">
..treeTrunk, .treeBranch {font-family: arial, verdana, sans-serif;}
..treeTrunk {
color: #3333ee; background-color: #DDDDDD; font-weight: bold;
}
..treeBranch {
border: 1px solid red; font-weight: normal; margin-left: 2em;
}
</style>
<script type="text/javascript">

function doChecks(x) {
// if this one is unchecked, uncheck all decendents
if ( ! x.checked ) {
var cbs = x.parentNode.getElementsByTagName('INPUT');
for (var i=0, len=cbs.length; i<len; i++){
cbs.checked = false;
}
}
// if this one is checked, check all ancestors
if ( x.checked ) {
while ( ( x = x.parentNode ) ) {
if ( 'DIV' == x.nodeName && x.firstChild ) {
if ( 'checkbox' == x.firstChild.type ) {
x.firstChild.checked = true;
}
}
}
}
}

function initTree(t){
if (document.getElementById && document.getElementsByTagName ) {
t = document.getElementById(t);
var cbs = t.getElementsByTagName('INPUT');
var i, x, j = cbs.length;
for ( i=0; i<j; i++ ) {
x = cbs;
if ( 'checkbox' == x.type ) {
x.onclick = function () {doChecks(this);};
}
}
}
}
</script>
</head><body onload="initTree('tree');">

<div id="tree">
<div class="treeTrunk"><input type="checkbox">
Main branch 1<br>
<div class="treeBranch"><input type="checkbox">
Sub branch 1 1<br>
<div class="treeBranch"><input type="checkbox">
Sub sub branch 1 1 1
</div>
</div>
</div>
<div class="treeTrunk"><input type="checkbox">
Main branch 2<br>
<div class="treeBranch"><input type="checkbox">
Sub branch 2 1<br>
<div class="treeBranch"><input type="checkbox">
Sub sub branch 2 1 1
</div>
<div class="treeBranch"><input type="checkbox">
Sub sub branch 2 1 2
</div>
</div>
<div class="treeBranch"><input type="checkbox">
Sub branch 2 2<br>
<div class="treeBranch"><input type="checkbox">
Sub sub branch 2 2 1
</div>
<div class="treeBranch"><input type="checkbox">
Sub sub branch 2 2 2
</div>
</div>
</div>
</div>

</body>
</html>
 
A

adam

cheers, i'll give it a whirl.

<i>[1] Completely unsupported opinion, but I'd be very surprised if any
browser in common use that supported getElementById did not also
support getElementsByTagName. </i>

afaik it's getElementsByName() is the only stipulation, not ByTagName.
ByName parses fine, TagName results in the JS debugger saying it's not
a function.
 
R

RobG

adam said:
cheers, i'll give it a whirl.

<i>[1] Completely unsupported opinion, but I'd be very surprised if any
browser in common use that supported getElementById did not also
support getElementsByTagName. </i>

afaik it's getElementsByName() is the only stipulation, not ByTagName.

There are both getElementsByName and getElementsByTagName methods
defined in the W3C DOM:

<URL:http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html>

document.getElementsByName('someName') will return a collection of all
the elements in the document with a name 'someName'. The collection
may be empty.

document.getElementsByTagName('P') will return a collection of all
the P elements in the document. The collection may be empty.

ByName parses fine, TagName results in the JS debugger saying it's not
a function.

It is not a function of the object that you are trying to call it with.
Your original post had:

var parentnode = document.getElementById(divName);
var allMyChildren = parentnode.childNodes.getElementsByName("INPUT");

Assuming that an element reference is successfully assigned to
parentnode, then in the following line the snippet:

parentnode.childNodes

will return a collection (which may well be empty) that is the child
node(s) of parentnode. If you attempt the getElementsByName() method:

parentnode.childNodes.getElementsByName("INPUT")

you will get an error: "parentnode.childNodes.getElementsByName is not
a function" because collections don't support that method. Using
getElementsByTagName will return exactly the same error. It will
'work' if modified to:

parentnode.getElementsByName("INPUT");

because parentnode (a DOM HTML element), supports getElementsByName()
as well as getElementsByTagName().

Try the code I supplied. It uses getElementsByTagName and works in IE
and Firefox (and any browser that supports the W3C DOM). A simple test:

<input type="button" value="test methods" onclick="
alert('document.getElementsByTagName :'
+ ( (document.getElementsByTagName)? '\tWORKS':'doesn\'t work')
+ '\n\n'
+ 'document.getElementsByName :'
+ ( (document.getElementsByName)? '\tWORKS':'doesn\'t work')
);
">
 
A

adam

ah cool, thanks for the info, i hadn't heard of getElementsByTagName
before :]

in the end i just worked around it:

------------------------------------------------------
function showChildren(boxName,divName,secID,gD,gS,gSs,rank) {
if((boxName.checked) == (true)) {
remoteRequest(divName,secID,gD,gS,gSs,rank);
} else {
document.getElementById(divName).innerHTML = " ";
document.getElementById(divName).style.visibility = "hidden";
}
}

function remoteRequest(sDivName,sID,getD,getS,getSs,rank) {

if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("GET","{$baseurl}/getsub.php?Sec=" + sID+ "&Di=" + getD +
"&Se=" + getS + "&getSub=" + getSs + "&action=" + rank);
xhr.setRequestHeader('Content-Type','text/plain');
xhr.send(null);
xhr.onreadystatechange=function() {
if (xhr.readyState==4) {
RetrieveXML = xhr.responseText;
document.getElementById(sDivName).style.visibility =
"visible";
document.getElementById(sDivName).style.width = "100%";
document.getElementById(sDivName).style.height = "100%";
document.getElementById(sDivName).innerHTML = RetrieveXML;
}

}
}
------------------------------------------------------



------------------------------------------------------
// example request:
<input type="checkbox"
onclick="showChildren(this,\''.$PROD_EDP.'_'.$Sections_ID{$D}[$S].'\',\''.$Sections_ID{$D}[$S].'\',\''.$D.'\',\''.$S.'\',0,3)"
ID="'.$PROD_EDP.'_'.$Sections{$D}[$S].'_'.$D.'-'.$S.'">
------------------------------------------------------



------------------------------------------------------
// getsub.php:
include_once('inc/connect.php');
include_once('inc/prefs.php');


$gDivisions = $_GET[Div];
$gD = $_GET[Di];
$gSections = $_GET[Sec];
$gS = $_GET[Se];
$subSec = $_GET[getSs];
$lType = $_GET[action];

$connection = new connection;
$connection->queryString("SELECT NAMEID, Name, belongs, vieworder FROM
names WHERE lType = '$lType' AND belongs = $gSections ORDER BY
vieworder");

while ($data=mysql_fetch_array($connection->result)) {
$subSections{$gD}{$gS}[] = $data[Name];
$subSections_ID{$gD}{$gS}[] = $data[NAMEID];
$subSections_Parent{$gD}{$gS}[] = $data[belongs];
}

if (!count($subSections{$gD}{$gS})) {
echo '<small>no subcategories for this category</small>';
}
for ($Sub = 0; $Sub < count($subSections{$gD}{$gS}); $Sub++) {
echo '<input type="checkbox"
onclick="showChildren(this,\''.$PROD_EDP.'_'.$subSections_ID{$gD}{$gS}[$Sub].'\')"
ID="'.$PROD_EDP.'_'.$subSections_ID{$gD}{$gS}[$Sub].'_'.$gD.'-'.$gS.'-'.$Sub.'">
<small><B>'.$subSections{$gD}{$gS}[$Sub].'</B></small>
<BR /><div
ID="'.$PROD_EDP.'_'.$subSections_ID{$gD}{$gS}[$Sub].'"
style="visibility:hidden; overflow:show; position:relative; height:5;
background-color:FCFCFC;">
</div>';
} // end sub
 

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,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top