I want to have a menu, that I can click on to open, and click on to close. Similar to a hover menu, but with clicking, to open, and clicking to close. I have three visible list items, with submenu's under.
These are hidden with css, display:none. I can get them to show, with the keyword "this", and a for loop for checking if any 'ul', have more then 1 item, then list will open when clicked.
As far as I could understand this code, I got some help here earlier. Now I have read, and watched tutorials from buckysroom, and feel I understand a lot more, at least about arrays, and everything in the code, I can now understand, at least. I have this code at the moment.
function showMenu(parentElement){
var uls= parentElement.getElementsByTagName("ul");
if (uls.length > 0)
uls[0].setAttribute("style","display: block");
}
function load(){
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function(){
showMenu(this);
});
}
}
As I understood, finally, the 'for' loop, I see that this code opens any array, or like, any 'li' that has more than 1 ( [0] ) item, as 0 is 1 in array, and loops through to see if it has children. If it does, it opens 'this' 'li's' 'ul'.
Since the load function, contains the showMenu function, and I have learned a little, to use functions inside functions, rather than copy myself, use arrays and variables, and assign them to eachother somehow. Buckysroom tutorials, at least helped me understand as much.
Now.. My problem is I do not know enough Javascript to get my mind around this, and I would rather not use jQuery, but learn how this could be achieved with plain Javascript.
Any pointers would help alot, I have tried the following;
Adding unique Id's to my three ul's, so I know can in fact open them with the above code, and I am able to close them, with another code, setting it back to "display:none".
The problem then, is I do not have the opportunity to open them again, and I understand that I am missing some piece, like stopPropagation or maybe, using addEventListener - Click, for this second part. As you may understand, the addeventListener, is something I got from a code in here.
function Meny1(){
var unorderedList = document.getElementById("ul_1");
var lis = unorderedList.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].setAttribute("style","display: none");
}
}
I figured out, that I can specify each menu-item with numbers, like [23], instead of [i], to target a single menu item, copy that line like this:
lis[23].setAttribute("style","display: none");
lis[24].setAttribute("style","display: none");
But as I understand, that is a bad practice, as it is terrible if I am to add another menu item, or remove one, and also is way to much copy-coding..
My thought, is that I want something like this: html:
<div id ="cssmenu"></div>
<ul id="ul_1"><li>I have many li's in each 'ul'</li></ul>
<ul id="ul_2"><li>I have many li's in each 'ul'</li></ul>
<ul id="ul_3"><li>I have many li's in each 'ul'</li></ul>
css:
#cssmenu{display:block;}
#cssmenu ul li ul{display:none}
My thinking of how the js should be, and I DON'T use CLASSES: (I didn't do this, as w3c validator pointed out that I shouldn't).
function showAndCloseMenu1(){
var ul_1 = document.getElementbyId("ul_1");
if(mouseclicked on ul_2 || mouseclicked on ul_3){
close.ul_1(this)
}
if(mouseClicked ul_1){
style.display = "block";
}
}
And then the same naturally for ul_2 and ul_3, I have not gotten good enough yet to think about implementing all into one code, but I know that it is possible of course, with global variables, and by using attributes.
Is there Anyone who can help me with this?
I have tried to use jQuery, with no success, and as I said, would rather not, as I am eager to learn Javascript to the fullest extend! And I can read Javascript, jQuery is just a bunch of dollarsigns to me, with simplified Javascript inside.
/
Here is a fiddle, but the menu doesn't work as it does in browsers, but you get the idea if you look there, its the menu on the left.
How can I have a show/hide function, in my navigation with Javascript? Am I thinking in the correct path here, as I see it, classes makes little difference, but maybe saves me some coding space thou.
Thanks for any help whatsoever on this, cannot seem to get my head around a working solution for this! I would like to have it like when I click on ul_1 first time, it opens. If I click it again, I want it to close. If ul_1 is open, and I click ul_2, or ul_3, I want to open that one, and close ul_1 again, kinda standard menu navigation in my perspective.
I want to have a menu, that I can click on to open, and click on to close. Similar to a hover menu, but with clicking, to open, and clicking to close. I have three visible list items, with submenu's under.
These are hidden with css, display:none. I can get them to show, with the keyword "this", and a for loop for checking if any 'ul', have more then 1 item, then list will open when clicked.
As far as I could understand this code, I got some help here earlier. Now I have read, and watched tutorials from buckysroom, and feel I understand a lot more, at least about arrays, and everything in the code, I can now understand, at least. I have this code at the moment.
function showMenu(parentElement){
var uls= parentElement.getElementsByTagName("ul");
if (uls.length > 0)
uls[0].setAttribute("style","display: block");
}
function load(){
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function(){
showMenu(this);
});
}
}
As I understood, finally, the 'for' loop, I see that this code opens any array, or like, any 'li' that has more than 1 ( [0] ) item, as 0 is 1 in array, and loops through to see if it has children. If it does, it opens 'this' 'li's' 'ul'.
Since the load function, contains the showMenu function, and I have learned a little, to use functions inside functions, rather than copy myself, use arrays and variables, and assign them to eachother somehow. Buckysroom tutorials, at least helped me understand as much.
Now.. My problem is I do not know enough Javascript to get my mind around this, and I would rather not use jQuery, but learn how this could be achieved with plain Javascript.
Any pointers would help alot, I have tried the following;
Adding unique Id's to my three ul's, so I know can in fact open them with the above code, and I am able to close them, with another code, setting it back to "display:none".
The problem then, is I do not have the opportunity to open them again, and I understand that I am missing some piece, like stopPropagation or maybe, using addEventListener - Click, for this second part. As you may understand, the addeventListener, is something I got from a code in here.
function Meny1(){
var unorderedList = document.getElementById("ul_1");
var lis = unorderedList.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].setAttribute("style","display: none");
}
}
I figured out, that I can specify each menu-item with numbers, like [23], instead of [i], to target a single menu item, copy that line like this:
lis[23].setAttribute("style","display: none");
lis[24].setAttribute("style","display: none");
But as I understand, that is a bad practice, as it is terrible if I am to add another menu item, or remove one, and also is way to much copy-coding..
My thought, is that I want something like this: html:
<div id ="cssmenu"></div>
<ul id="ul_1"><li>I have many li's in each 'ul'</li></ul>
<ul id="ul_2"><li>I have many li's in each 'ul'</li></ul>
<ul id="ul_3"><li>I have many li's in each 'ul'</li></ul>
css:
#cssmenu{display:block;}
#cssmenu ul li ul{display:none}
My thinking of how the js should be, and I DON'T use CLASSES: (I didn't do this, as w3c validator pointed out that I shouldn't).
function showAndCloseMenu1(){
var ul_1 = document.getElementbyId("ul_1");
if(mouseclicked on ul_2 || mouseclicked on ul_3){
close.ul_1(this)
}
if(mouseClicked ul_1){
style.display = "block";
}
}
And then the same naturally for ul_2 and ul_3, I have not gotten good enough yet to think about implementing all into one code, but I know that it is possible of course, with global variables, and by using attributes.
Is there Anyone who can help me with this?
I have tried to use jQuery, with no success, and as I said, would rather not, as I am eager to learn Javascript to the fullest extend! And I can read Javascript, jQuery is just a bunch of dollarsigns to me, with simplified Javascript inside.
http://fiddle.jshell/ufcsccy3/
Here is a fiddle, but the menu doesn't work as it does in browsers, but you get the idea if you look there, its the menu on the left.
How can I have a show/hide function, in my navigation with Javascript? Am I thinking in the correct path here, as I see it, classes makes little difference, but maybe saves me some coding space thou.
Thanks for any help whatsoever on this, cannot seem to get my head around a working solution for this! I would like to have it like when I click on ul_1 first time, it opens. If I click it again, I want it to close. If ul_1 is open, and I click ul_2, or ul_3, I want to open that one, and close ul_1 again, kinda standard menu navigation in my perspective.
Share Improve this question edited Jan 27, 2015 at 9:49 llanato 2,5036 gold badges42 silver badges59 bronze badges asked Jan 27, 2015 at 9:43 suntosunto 871 gold badge1 silver badge11 bronze badges2 Answers
Reset to default 3Just toggle an ID for the open menu. One method, onclick
, which does it all.
function showmenu(elem) {
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu) {
openMenu.removeAttribute("id");
// Stop if we're just closing the current menu
if (openMenu === elem) {
return;
}
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("li").length > 0) {
elem.setAttribute("id", "activeMenu");
}
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul li {
float: left;
padding: 0 10px;
}
ul ul {
display: none;
}
ul ul li {
float: none;
}
#activeMenu ul {
display: block;
}
<ul>
<li onclick="showmenu(this)">Menu Item 1</li>
<li onclick="showmenu(this)">Drop Down 1
<ul>
<li>DD1 Item 1</li>
<li>DD1 Item 2</li>
</ul>
</li>
<li onclick="showmenu(this)">Drop Down 2
<ul>
<li>DD2 Item 1</li>
<li>DD2 Item 2</li>
</ul>
</li>
</ul>
Note that I used onclick
just for simplicity. Adding the click event you did is the right way.
function showMenu(elem) {
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu) {
openMenu.removeAttribute("id");
// Stop if we're just closing the current menu
if (openMenu === elem) {
return;
}
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("ul").length > 0) {
elem.setAttribute("id", "activeMenu");
}
}
function showSubMenu(elem) {
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu)
openMenu.removeAttribute("id");
var openSubMenu = document.getElementById("activeSubMenu");
if (openSubMenu) {
openSubMenu.removeAttribute("id");
// Stop if we're just closing the current menu
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("ul").length > 0) {
elem.setAttribute("id", "activeSubMenu");
}
}
function showLastSubMenu(elem) {
// Clear any currently open menu
var openMenu = document.getElementById("activeMenu");
if (openMenu)
openMenu.removeAttribute("id");
var openSubMenu = document.getElementById("activeSubMenu");
if (openSubMenu)
openSubMenu.removeAttribute("id");
// Stop if we're just closing the current menu
var openLastSubMenu = document.getElementById("activeSubMenu");
if (openLastSubMenu) {
openLastSubMenu.removeAttribute("id");
}
// Only apply it if the element actually has LI child nodes.
// OPTIONAL: Will still work without if statement.
if (elem.getElementsByTagName("ul").length > 0) {
elem.setAttribute("id", "activeLastSubMenu");
}
}
I post the full code, that with much help from @David resultet in a clickable menu solution, Thanks alot :)
the css items #someMenu ul, #somemenu ul li, and #someMenu ul ul had to be changed to classes, so .someMenu ul etc. #activeMenu > ul { display: block; }
#activeSubMenu > ul {
display: block;
}
#activeLastSubMenu > ul {
display: block;
}
And in the html,
<nav id ="someMenu" class="someMenu">
function showMenu on the first level li's,
function showSubMenu for next level
function showLastSubMenu for the last sub's (I had max 3 levels)
Alot of repeating, so I will try and make it into less code, with array and addEventListener, as you stated in you answer that is more correct!