Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

if($("+ul", this).css("display")=="none"){..}

Hello,

this is fully functioning code that I am trying to understand.

1) Can you please explain to me why the if() statement, has "+ul", this? I would think this below is enough, why do we need "+ul" in front of 'this'? if($(this).css("display")=="none"){...}

2) If you look at the CSS, you will not find display:'none', so I am assuming that none of the elements have display:none. why does the above statement compare to "none"?

Thanks!

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
ul.navi{
width:220px;
margin:0;
}
ul.navi, ul.menu{
margin:0;
padding:0;
list-style:none;


}
div.category{
margin-top:5px;
height:40px;
background-color:#B9DDE8;
line-height:40px;
cursor:pointer;

}
ul.menu a{
display:block;
height:35px;
line-height:35px;
color:#164158;
background: lightblue;


}

</style>

</head>

<body>
<script>

</script>

<ul class="navi">
<li>
    <div class="category"> Fashion </div>
    <ul class="menu">
        <li> <a href="#"> One </a></li>
        <li> <a href="#"> Two </a></li>
        <li> <a href="#"> Three </a></li>
        <li> <a href="#"> Four </a></li>
        <li> <a href="#"> Five </a></li>
        <li> <a href="#"> Six </a></li>

    </ul>
</li>
<li>
    <div class="category"> Furniture </div>
    <ul class="menu">
        <li> <a href="#"> Seven </a></li>
        <li> <a href="#"> Eight </a></li>
        <li> <a href="#"> Nine </a></li>
        <li> <a href="#"> Ten </a></li>
        <li> <a href="#"> Eleven </a></li>
        <li> <a href="#"> Twelve </a></li>

    </ul>
</li>
<li>
    <div class="category"> Stationery </div>
    <ul class="menu">
        <li> <a href="#"> Thirteen </a></li>
        <li> <a href="#"> Fourteen </a></li>
        <li> <a href="#"> Fifteen </a></li>
        <li> <a href="#"> Sixteen </a></li>
        <li> <a href="#"> Seventeen </a></li>
        <li> <a href="#"> Eighteen </a></li>

    </ul>
</li>
<li>
    <div class="category"> Necessities </div>
    <ul class="menu">
        <li> <a href="#"> Nineteen </a></li>
        <li> <a href="#"> Twenty </a></li>
        <li> <a href="#"> Twenty one </a></li>
        <li> <a href="#"> Twenty two </a></li>
        <li> <a href="#"> Twenty two </a></li>
        <li> <a href="#"> Twenty three </a></li>

    </ul>
</li>



</ul>
<script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
<script>

$(document).ready(function(){
     $(function(){
         $("ul.menu").hide();
         $("div.category").click(function(){
          $("ul.menu").hide();
         if($("+ul", this).css("display")=="none"){

         $("+ul", this).show();
         }

         });
     });
 });
</script>

</body>
</html>

7 Answers

Brandon Barrette
Brandon Barrette
20,485 Points

So the +ul here actually doesn't mean + as in concatenate (or add together). It is a CSS selector that says find the element directly after the first:

$("<div> + <ul>")

This means select the ul that immediately follows a div. Here in your code, you are clicking on a div with the class category. So it is saying that if the ul after this div has the property of display none, show it. If is is already shown, it would be ignored.

Here's a better way to write this code:

$(document).ready(function(){
    $("div.category").click(function(){
          $("ul.menu").hide(); //hide all ul.menu
          $(this).next().show(); //show the next sibling of the div that was clicked (which is the ul)
     });
 });
Brandon Barrette
Brandon Barrette
20,485 Points

Here's some answers to your questions.

  1. Yes. See here for all selectors: http://www.w3schools.com/cssref/css_selectors.asp (Note that your ul here is not a child of the div because the div tag is closed before the ul starts)

  2. Here the order is important. next() and show() are not equivalent. next() is used to traverse the DOM. So the code $("div.category").next().show(); would mean start at div.category, find it's next sibling, then show it. This would mean: $("div.category").show().next(); Show div.category, then find it's next sibling (but don't do anything to it). Now you can mix the order of show(), addClass(), etc because those are all properties that you are changing on the jQuery Object.

  3. The reason they use $("ul.menu").hide() is because one of those may be already open (meaning the display is block), so first hide them all, then show the one that's being clicked.

  4. If you want them to close when you click them, then you have to go back to what your original jQuery was, although I'd write it this way:

$(document).ready(function(){
    $("div.category").click(function(){
          $("ul.menu").hide(); //hide all ul.menu
          $menu = $(this).next(); 
          if ( $menu.hasClass("selected") ) {
               $menu.hide().removeClass("selected");
          } else {
               $menu.show().addClass("selected"); 
          }
     });
 });

So you can see I create a variable $menu to hold the ul.menu. (Note here it is not a child of div.category, but a sibling).

Then I check if $menu has a class called selected (meaning it's open). If it does, then that means the click wants to close it, so I hide the menu and remove the class selected. (here's an example where hide() and removeClass() could go in any order).

If it doesn't have the class selected, that means it's not open and you want to show it, so I show the menu and add the class selected.

Hope that helps explain things! Check out http://api.jquery.com/ to learn more about using jQuery. Or take the jQuery course on here!

Hello Brandon,

That was well explained; I am understanding it a lot better.

$("+ul", this).show();

Based on your explanation, the parameter "this" refers to the "div with class category" that we clicked on. And the "+" in front of the 'ul' means to find the direc ul sibbling of the div with class category. This is a code that I found and I could possibly learn it and apply it.

1) Ok, in CSS, pointing to a direct child would be something like this: div.category >ul, right? Are they (below) the equivalent of each other:

$("+ul", this).show(); && div.category >ul

2) In your code, you suggested this statement: $(this).next().show();

a) I have always wondered in a statement like that, does the order of the methods matter. Could you have written it like this: $(this).show().next(); When chaining, how do you know which method to place first?

if($("+ul", this).css("display")=="none"){...} 3)In my code above, the author uses the above statement, even though in the stylesheet, the ul with class menu does not say display:none. Should I assume that $("ul.menu").hide(); means display:none?

4) What statement can I add to this code to make "ul.menu" hide, when you click it again. Right now, when you click each one once, they stay open forever.

Thanks!!

Hello Brandon,

Thank you so much for pointing me to the comprehensive CSS Selector Reference list. It is clearing a lot of consusion :)

if ( $menu.hasClass("selected") ) if($("+ul", this).css("display")=="none"){

In the CSS, ul.menu does not have the class selected or display:none, how does the browser give it these classes?

a) I am thinking the property 'selected' gets automatically added to the ul.menu when we click on it, thus it does not have to be mentionned in the stylesheet, right?

b) Same logic perhaps applies to our ul.menu, even though in the css we don't mention that it display:none, the browser automatically give it a display:none, and thus our if() evaluates to true, right?

Thanks!

Hello Brandon,

Thank you for the easy to understand code you have suggested.

Cheers!

Brandon Barrette
Brandon Barrette
20,485 Points

.selected is going to just be a flag for jQuery, so it doesn't need to be defined in the CSS unless you want it to have some properties.

.hide() in jQuery automatically adds display: none;

.show() in jQuery automatically adds display: block;

I suggest you look at the jQuery API (which i linked in my last answer) and look at the methods .hasClass(), .addClass(), and .removeClass();

Oh, hide() and show () automatically... that is something I would have never picked up on my own, even after reading this documentation.

In fact, many of these documentations are not really that easy for beginners to make sense of. I guess I will eventually make sense of things.

Thanks a lot of your patience, easy to understand explanations and code suggestions. I will have a look at .hasClass(), .addClass(), and .removeClass();

Again, thank you!!!!

Hello Brandon,

May I ask for your help with this post, particularly the very last post of the url below. when , for example $(".slider#1').show("fade", 500); $(".slider#1").delay(5500).hide("slide", {direction:"left", 500); is used I cant understand when does one end and the next method begins. I am wondering if the show() with a fade of 500ms, mean fade the element "at the end" of 1/2 second or fade "for" 1/second. The same confusion goes for the others.

If you can, please look, at the very very last post:

https://teamtreehouse.com/forum/how-to-read-these-jquery-lines

Thank you so much!

Brandon Barrette
Brandon Barrette
20,485 Points

I'm going to suggest you look at the API for jquery. If you don't understand the documentation scroll down to the examples. Then if you are still confused I suggest google.

Part of becoming a programmer requires you to learn to read documentation and play around. You will fail many times (I for sure have). It's how you recover from those failures that will have you learning proper techniques.

If you are still confused then open a new question on the forum since this is out of the scope of your original question.

Thanks Brandon!