Forum Moderators: open
<SCRIPT type="text/javascript">
function toggleChild(node)
{
var parent = node.parentNode;
if(parent.hasChildNodes && parent.childNodes) {
var tmp = parent.getElementsByTagName("UL");
if(tmp.length > 0) {
child = tmp[0]
var displayValue = child.style.getPropertyValue("display");
if(displayValue == "none") {
child.style.setProperty("display", "block", "");
} else {
child.style.setProperty("display", "none", "");
}
return false;
}
}
return true;
}
</SCRIPT>
and the HTML:
<UL>
<li><A href="#1" onClick="return toggleChild(this);"><B>Contact Details</B></A>
<UL style="display: none;">
<li><A href="#1.1" onClick="return toggleChild(this);"><B>Working Groups</B></A></li>
<li><A href="#1.2" onClick="return toggleChild(this);"><B>Reference Group</B></A>
<UL style="display: none;">
<li><A href="#1.2.1" onClick="return toggleChild(this);">Test Subcategory</A></li>
</UL></li>
</UL></li>
</UL>
IE (AFIAK) doesn't support these methods on elements.
At the moment, I can't see a reason(*) not to use:
element.style.backgroundColor = "#008000"
instead of:
element.style.setPropertyValue("background-color","#008000","")
The same with 'getting' properties. So in answer, don't use:
var prop = element.style.getPropertyValue("display")
but:
var prop = element.style.display
...which works across the board (NS4 etc excluded)
(*: That doesn't mean that there isn't one!)
--------------------------------------------------------
As far as I can make out, these methods are part of a more general W3C DOM interface for use not necessarily in the context of browsers/Javscript. The use of properties as setters & getters (and the intercapped property forms) isn't applicable to Java et al.
--------------------------------------------------------
P.S.
I have a comment about the testing for childNodes. It's not critical, so I'll only go into it if you're interested.
I've settled on this which hopefully works in everything:
if(child.currentStyle) {
var displayValue = child.currentStyle["display"];
if(displayValue == "none") {
child.style.display = "block";
} else {
child.style.display = "none";
}
} else {
var displayValue = child.style.getPropertyValue("display");
if(displayValue == "none") {
child.style.setProperty("display", "block", "");
} else {
child.style.setProperty("display", "none", "");
}
} I'm testing in six different browsers on Mac - IE supports both methods but the others jump straight to the second one. Not sure what the picture is like in the Windows-world.
I'd be interested in comments on testing for childNodes - it's hard to work out what's right/needed w/o a Windows machine to test on.
[edited by: dcrombie at 12:26 pm (utc) on July 2, 2004]
(1) = node.style.property
(2) = node.currentStyle.property
(3) = node.style.getPropertyValue(property)
Mac browsers:
Opera (1, 3)
Safari (1, 3)
Firefox (1, 3)
Internet Explorer (1, 2, 3)
Netscape (1, 3)
Camino (1, 3)
I abandoned DHTML when Netscape introduced layers
Then I bow deeply to your webdesign experience, which is infinitely greater than mine! It does look though, that you have "a little" catching up to do :). The thing is, it looks like you have caught up too much. Here, you are using more advanced (but arguably, not any 'better') methods that IE doesn't support.
Now, assuming we forget 'Jurassic' browsers (your code has done this already):
var displayValue = child.style.display
if(displayValue == "none")
child.style.display = "block"
else
child.style.display = "none";
This will suffice for the whole block. No branching needed. This could be shortened, by using a terniary operator, but no need to take this too far.
currentStyle
This is a non-standard, IE-only, property that get's the actual, cascaded style properties of the element. It will pick up on properties that are defined in a stylesheet. The style property (all browsers) only returns properties defined inline (on the element's own individual
style object). In some sense, the IE branch of your code was asking a slightly different question, to the other branch, although in this, and most circumstances, the result will be the same.
The standards equivalent of currentStyle is the object returned by the global method, getComputedStyle(elmRef), on which you then use the method getPropertyValue(), putting the required property in its intercapped CSS form.
If you put the necessary properties inline, you won't need to worry about using these things.
I've noticed that your IE supports setPropertyValue. I mess around with IE5 (since I don't like surprises later). I doesn't support them. If you consider IE5 "out of range", then it's probably the testing for childNodes that is causing the problem. I still consider using the 'normal' technique preferable, as it's tried & tested, and works all round.
function toggleChild(node)
{
var parent = node.parentNode;
if(!parent) // largely, a test for 'old' browsers
return true
var tmp = parent.getElementsByTagName("UL");
var child = tmp[0]
if(!child)
return true
var displayValue = child.style.display
if(displayValue == "none")
child.style.display = "block";
else
child.style.display = "none";return false;
}
No need for checking childNodes explicitly, relying on methods/properties, hasChildNodes; childNodes
This should work everywhere (incl IE5). If it doesn't, then I'd like to know, so I can "get my facts right".
function toggleChild(node)
{
var parent = node.parentNode;
if(!parent) return true;
var child = parent.getElementsByTagName("UL")[0];
if(!child) return true;
if(child.currentStyle) {
// applies to msie only
var displayValue = child.currentStyle["display"];
child.style.display = (displayValue == "none")? "block" : "none";
} else {
var displayValue = child.style.getPropertyValue("display");
var newValue = (displayValue == "none")? "block" : "none";
child.style.setProperty("display", newValue, "");
}
return false;
}
Flanagan's "Javscript: The definitive Guide" says:
....For example, these two lines of code accomplish the same thing:
element.style.fontFamily = "sans-serif";
element.style.setProperty("font-family", "sans-serif", "");
That said, the function looks fine to me now.
The only possible reasons I can think of at the moment, is if some bright spark somewhere is thinking of deprecating the simpler approach (which everybody is using right now), or possibly to make functions easier to port to, say, Java, which would involve much more than this anyway.
Remember that using .currentStyle is different from using .style . If you have set the display properties via stylesheet, then the function will work in IE, but not in others.
-------------------
On another topic:
The hrefs: #1.1 etc suggest that you are setting element ids with leading numerical chars, which is apparently illegal. (larceny)
The hrefs: #1.1 etc suggest that you are setting element ids with leading numerical chars
Actually the menu is part of a file-management system. The '#'-links are where the links to the actual file-lists go (separate pages).
Funny, I was debating whether to replace .currentStyle with .style in the first branch for that very reason - but doing so might be confusing later ;)
I'm exploring the whole JavaScript/CSS interface which opens up a whole world of possibilities. That's were I think the standards functions will be more useful than the may-be-one-day-deprecated ones.
Thanks for your help.
the may-be-one-day-deprecated
I was clutching at straws there. I very much doubt they won't be supported in the future. It would make 99% of the DHTML made in the last 5 years into legacy code at a stroke.
I think the main issue is that the XML DOM is offering a language neutral interface (blah etc).
I see you're a QuirksMode fan. I reckon PPK will generally sort you out on all issues like this.