0

I've got this menu I'm working on...

Initially, "level-2" would appear below "level-1". I've been able to make move it to a 2nd column always sticking to the top. As far as I can see it's working!

The issue I've run into is adding more columns as I need at least another level, possibly two.

I think I’ve handled the HTML part (see Item 2 - Item 2-1 - Item 2-1-1), the issue now is the script. I tried replicating the current one, but just couldn't make it work...

Any help would be highly appreciated. Thanks

Fiddle

HTML:

<div class="wrapper">
<ul>
    <li class="level-1"><a href="#">Item 1</a>
        <ul class="level-2">
        <li><a href="#">Item 1-1</a></li>
        <li><a href="#">Item 1-2</a></li>
        </ul>
    </li>
    <li class="level-1"><a href="#">Item 2</a>
        <ul class="level-2">
        <li><a href="#">Item 2-1</a>
            <ul class="level-3">
            <li><a href="#">Item 2-1-1</a></li>
            </ul>
        </li>
        </ul>
    </li>
    <li class="level-1"><a href="#">Item 3</a>
        <ul class="level-2">
        <li><a href="#">Item 3-1</a></li>
        <li><a href="#">Item 3-2</a></li>
        <li><a href="#">Item 3-3</a></li>
        </ul>
    </li>
    <li class="level-1"><a href="#">Item 4</a>
        <ul class="level-2">
        <li><a href="#">Item 4-1</a></li>
        <li><a href="#">Item 4-2</a></li>
        </ul>
    </li>
    </ul>
</div>

JS:

$('.level-2').hide();
  $('.level-1').on('click', function(){
    if(!($(this).children('.level-2').is(':visible'))){
      $('.level-2').slideUp();
      $(this).children('.level-2').slideDown();
    } else {
    $('.level-2').slideUp();
  }
});
$('.level-2').on('click', function(e){
  e.stopPropagation();
});

CSS:

body{
    margin: 0px;
    border: 0;
    overflow: hidden;
}

ul {
    list-style: none;
    margin: 0;
    padding: 0;
    color: #000000;
}

ul li {
    position: relative;
}

li ul {
    position: absolute;
    left: 120px;
    top: 0;
    display: none;
}

ul li a {
    text-decoration: none;
    color: #000000;
}

.level-1 {
    position: relative;
    top: 20px;
    left: 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    font-weight: normal;
    line-height: 15px;
    letter-spacing: 0em;
    text-transform: uppercase;
}

.level-2 {
    position: fixed;
    top: 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    font-weight: normal;
    line-height: 15px;
    letter-spacing: 0em;
    text-transform: uppercase;
}

.level-3 {
    position: fixed;
    top: 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    font-weight: normal;
    line-height: 15px;
    letter-spacing: 0em;
    text-transform: uppercase;
}
Candlejack
  • 448
  • 10
  • 23
Cheng Zhaa
  • 61
  • 1
  • 10
  • So if I'm reading your question correctly it sounds like you are looking for help with the JS specifically? If so, could you elaborate on what problems you've encountered? – Candlejack Feb 12 '15 at 10:47
  • @Candlejack I'm trying to make it work with more levels... at least one more, ideally two. I think the HTML part (item2) is correct, but I just couldn't add .level-3 to the script and make it work... I'm self-taught so I'm probably making some very n00b mistake or just approaching it the wrong way... – Cheng Zhaa Feb 12 '15 at 11:16

2 Answers2

0

I have updated the CSS, Please try this. It will help you.

body{
 margin: 0px;
 border: 0;
  overflow: hidden;
}

ul {
 list-style: none;
 margin: 0;
 padding: 0;
 color: #000000;
}

ul li {
 position: relative;
}

li ul {
 position: absolute;
 left: 120px;
 top: 0px;
 display: none;
}

ul li a {
 text-decoration: none;
 color: #000000;
}

.level-1 {
 position: relative;
 top: 20px;
 left: 20px;
 font-family: Arial, Helvetica, sans-serif;
 font-size: 11px;
 font-weight: normal;
 line-height: 15px;
 letter-spacing: 0em;
 text-transform: uppercase;
    background:#f5f5f5;
    width:220px;
}

.level-2, .level-3 {
 top: 20px;
 font-family: Arial, Helvetica, sans-serif;
 font-size: 11px;
 font-weight: normal;
 line-height: 15px;
 letter-spacing: 0em;
 text-transform: uppercase;
}

.level-1 > .level-2, .level-1 .level-2 > .level-3{position:absolute; right:10px; top:0px; left:220px; width:220px; background:#f8f8f8;}

Thanks

0

Looking through your fiddle, I can see two issues:

  1. you are checking for :visible in your JS but your CSS is setting display:none on your li ul rule
  2. When visible, the third menu level will appear underneath the second level (this is more of a UX/design issue than a problem with the JS)

The second issue is easily addressed with some CSS, eg:

.level-3 { left: 200px; }

The first issue, I believe, is because you are setting an element to hidden using 'display' in the CSS, but trying to toggle it in the JS checking for :visible rather than the value of the display rule. This stackoverflow answer explains why this can cause problems probably better than I can, but I think the problem is that the JS can't find objects set to display:none with CSS.

I've created a fiddle which gives an example of how you can avoid this problem by replacing this line in your JS:

if(!($(this).children('.level-2').is(':visible'))){

with this:

if($('.level-3').css('display') === 'none'){ 

(I have left the logic for clicking .level-1 as it was, but changed the logic for clicking .level-2 to facilitate comparisons.)

In my example I've also added coloured backgrounds to the different list items to aid visibility - it is much easier to see if items are appearing on top of each other this way. I hope some of this is helpful!

Community
  • 1
  • 1
Candlejack
  • 448
  • 10
  • 23
  • Another possible alternative to the example fiddle I provided, is that you could avoid setting display:none on any elements in your CSS and instead dynamically set their visiblity using javascript when your page loads. Whether this is a better idea or not depends on the wider context of what you are making. – Candlejack Feb 12 '15 at 16:46
  • It is definitely helpful! The issue I see with that is that I lose slideUp and slideDown which I really can't. – Cheng Zhaa Feb 12 '15 at 17:24
  • You don't necessarily have to lose them, you can put them in alongside the CSS changes. I took the slideUp/slideDown out to make the example more clear as to where the problem was coming from. the slideUp/slideDown stuff can be added back in :) – Candlejack Feb 12 '15 at 17:33
  • How so? Sorry if this is dumb question, but I'm self-taught in JS. I'm still crawling... :) – Cheng Zhaa Feb 12 '15 at 17:42
  • I've made another fiddle giving an example of how you might do it: http://jsfiddle.net/Candlejack/ojyezyrn/ However, I don't want to include this version in the official answer as I don't think the slideup/slidedown functionality is quite right. In my view the animated side of things is part of the UX design rather than part of a functionality problem. If this was my project, I would make sure the menu 'works', ie functions as a navigable menu, then add the animation afterwards. That's just an opinion rather than a technical point, though :) – Candlejack Feb 13 '15 at 11:03
  • Addendum: I honestly can't seem to figure out what is wrong with 'slideup' here. If it can't be resolved to your satisfaction I would suggest posting a separate question about it, as it seems unrelated to the original problems of not being able to display the third menu level. – Candlejack Feb 13 '15 at 11:06
  • yeah, I see the issue... in the meantime I've found another menu already with several levels working. It's got a few issues and I just posted a question regarding those. If wanna give it a look: http://bit.ly/1zRkUUV it might be easier than this one. Hopefully... :) – Cheng Zhaa Feb 13 '15 at 11:31