I have a navMenu of which some items should open & close straight down, onclick. Because of that straight down opening, I thought it would be semantic enough if I would not put those items in a sub menu, but leave them in the main menu.
But although I do not get any error or even just a warning in IE9 (with debugger) and FF7 (Firebug 1.8.4), the subLevel items won’t open or close.
The code contains quite a lot of seemingly irrelevant matters, but this way you will have nicer menu to play with :). And it is a one-action copy & paste code.
Ancillary problem, maybe what’s actually going wrong for you: When the user clicks on the link, there’s no JS that disables the default action. So nothing happens, and the page reloads. The quick solution is to change the onclick handler to also return false:
<a ... onclick="openSubLevel();return false;">
Now, the real problem is that in your loop, you’re checking the style.display property of each child:
if (children[c].style.display == 'none')
{
// ...
}
else return;
But you’re only setting the display to “none” in the CSS. And the JS style object doesn’t reflect stylesheet styles! So the first time you check the style.display on the first child, it’s going to be false!
There is no fix as easy as the “return false” thing from above. If it were me, I’d combine the openSubLevel and closeSubLevel functions into one. Then, instead of checking for a display of none, check for a display of block. Then, when it fails the first time because style.display returns undefined, it’s still doing the right action:
function openCloseSubLevel() {
var parent = document.getElementById('hasSubLevel');
var children = document.getElementsByClassName('subLevel');
var currentlyShowing = children[0].style.display === 'block';
var newDisplay = currentlyShowing ? 'none' : 'block';
var newBackground = currentlyShowing ? 'plus' : 'min';
newBackground = 'url(images/vakje_' + newBackground + '.gif)';
for (var c = 0; c<children.length; c++) {
children[c].style.display = newDisplay;
children[c].style.backgroundImage = newBackground;
}
}
Now that’s a speedy reply, for a Friday night! Unfortunately however, inserting return false; doesn’t do the trick. For your convenience, I’m reposting the code, in which the only I changed is the insertion (and the correct code tags around it):
Regarding combining the two functions: I deliberately didn’t do that because I only want the subLevel to open when the ‘parent item’ is clicked, and only closed when the other main menu items are clicked.
Bear in mind that just because you don’t get any errors or warning, that doesn’t mean there is nothing wrong with your code.
No errors/warnings just means there are no syntax errors in your code, nothing more. If the output is still not what you want then that means you have logic errors in your code.
A really simple example
var a = 2 * 3;
if(a > 10){
alert('got here');
}
No errors or warnings will be generated with the above code, but the alert() will never be triggered because of the logic error in that a is a constant and <= 10. Most debuggers will not detect that the alert() will never be triggered.
So if your code is not working, you need to do some basic debugging and step through your code and check values of variables using either a debugger or alert()'s. When a variable is not the expected value, then back track through your code to find the source of the error and fix it.
If you develop sound debugging skills you can save a lot of time in the future by not having to wait around in forums for people to help you fix what a lot of the times are simple problems that can be fixed with some basic debugging.
Hey Webdev, nice to see you again! Our posts crossed, and when I hit the ‘Post’ button I had to get something to eat and some sleep, so I’m only reading your replies now. Thanks for the alert debugging trick. I just solved the matter by taking the if lines out completely, but I still have a few questions.
If javascript cannot retrieve CSS values the way I thought it could, then why does this example work like a charm:
The second question is: do you know a good javascript course for intermediate students? This issue wasn’t mentioned in the W3 Schools beginners course, including the DHTML course.
Thanks in advance. (I still owe you a reporting back on that particular increment/decrement question, and I will report back.)
And the JS style object doesn’t reflect stylesheet styles! So the first time you check the style.display on the first child, it’s going to be false!
I read that, but my brain seemingly couldn’t accept that because of the last example I gave, in which the style block values were read out by the Javascript. Also because (s)he gave another tip, a quick fix, I wanted to try that first.
Yes and no. I do get the concept now of javascript in principle not being able to read out style blocks and sheets, but the author doesn’t explain why my last example does work. Why are ID style declarations returned, and class style declarations not?
…it looks like everything’s working. But the first time through, you’re comparing undefined to “block”. So you get the outcome you were expecting, but not for the reason you thought.
OK, my explanation that it depends on the use of an ID versus a class is not correct. I just changed my last example to getElementsByClassName, and then it works just as well.
But your explanation that Javascript doesn’t reflect style sheet (i.e. block) declarations, if that is what you are saying, is not correct either. Otherwise my last example wouldn’t work – I’m not using inline styles.
If I understand your last message correctly, it would all about the first-time comparison. And indeed, if I swap “block” and “none” in the Javascript in my last example, I have to click twice for the sub menu to appear, and then furthermore just once. And if I swap “block” and “none” in the Javascript in my first example, it does work.
So it seems as if the first-time comparison has to check a condition that is opposite of what is declared in the style block. I could very well live with that, but if I click the ‘parent link’ Werkwijze in my first example more than once, nothing happens. Why is that then, considering the successful two-click action described in the above paragraph?
Also, why is it that the use of inline styles solves all the problems? I don’t have to swap anything in my first example, just apply inline styles, and everything works. So apparently the algorithm is much more complicated then just the first-time comparison?
So the thesis is: “Javascript doesn’t reflect style block or style sheet declarations, unless you first assign the style with javascript.”? But why does my second example (third message) work then? How did I assign the style with javascript there, which I did not do or do incorrectly in the first example?
When JavaScript sets and retrieves styles, they are the inline styles on the element that it works with. Those inline styles override stylesheet styles that may also affect the same element.
Normally when working with HTML we stay far away from using inline styles on an element, and use an external stylesheet for styles instead.
I’m not using any inline styles in my examples. Yet, my second example (third message) works. So the question remains: Why does my second example (third message) work? How did I assign the style with javascript there, that I did not do or do incorrectly in my first example?