This course will extend what was learned in the HTML & CSS Basics series, venturing further into modern best-practices in HTML and CSS and introducing basic javascript.
Front-end Series →

Part three of learning jQuery extends the last tutorial. This time, we’re going to add multiple methods inside a single function, and learn about conditional statements.

At the end of the last tutorial, we built some pretty solid looking tooltips (and that same method can be used to make a whole bunch of pop-up-type devices, like modals, mega menus, form helpers—really it’s all just a matter of CSS styling changes). They look like this:

See the Pen jQuery Tooltip (Part 5) by Alex Turnwall (@alturnwall) on CodePen.0

Those are pretty good—and a really simple way to achieve some functionality that can make your page designs very nice. But, they definitely have some limitations.

Limitations with the previous tutorial’s pop-ups

#1: Interacting with the actual pop-up box

Click one of the buttons in the above CodePen example to reveal the grey popup box. Now, try to click inside of the grey pop-up box. What happened?

The grey box should have closed. This is a major limitation of these pop-ups because at this point, we can’t put anything in them that our users can interact with, without the box closing. So this simple method is great for simple tooltips that only show simple content for users to read or see. But, they’re not great for adding additional content to the pages that we need users to interact with. (Don’t worry, we’ll fix this below.)

But first, why did it happen?

Well… we told it to. Since we made each my_target box a child of each my_button (see HTML below)…

<span class="my_button">Test Button
  <div class="my_target">Test Target</div>
</span>

…in order to target only one specific target at a time, technically when we click on the grey my_target box, we’re actually clicking on the parent my_button too—even though visually, it looks like it’s outside of the button (because we moved it with our CSS).

When you click on an element, you’re also essentially clicking on every parent or ancestor of that element.

That’s an important concept to wrap your head around! Examine the HTML and play with the buttons a few times so that sinks in.

#2: Multiple boxes open at once (causing overlap)

Now, go back to the same CodePen example above, and click on both buttons. Both target pop-ups should open.

While this functionality may be okay (even desirable) in some applications, this is obviously problematic in this example, because one box overlaps the other.

Solutions

So what we want to do is make it possible to click inside the grey pop-up boxes (to access links, multimedia, etc), and also force all open pop-ups on the page to close, if we click to open a different pop-up. Let’s do it.

Making the pop-up content clickable

Step 1

First things first, let’s make it possible to click the content in the pop-ups. Looking back at the original problem above, this happened because each my_target is a child of each my_button . Well, fixing that is pretty simple, we’ll just remove that relationship in the HTML by moving the target outside of the button.

<span class="my_button">Test Button 1</span>
<div class="my_target">Test Target 1</div>

<span class="my_button">Test Button 2</span>
<div class="my_target">Test Target 2</div>

Note that I added numbers “1” and “2” to each button and target, so I know which corresponds to which. And also note that each target immediately follows each button.

That’s fine, but now, our buttons no longer work. Because previously, in our javascript, we specifically targeted the children using the .children() method (as seen below).

$(".my_button").click(function(){
   $(this).children(".my_target").toggle();
});

Now we need to find a way to target each button’s corresponding target, without that parent/child, or ancestral relationship.

Step 2

That’s where the .next() method comes in handy. The jQuery API reference tells us that the next method gets “the immediately following sibling of each element”. So we’re going to swap that into our javascript, like this:

$(".my_button").click(function(){
   $(this).next(".my_target").toggle();
});

This should be correctly targeting the new HTML we wrote in step 1. But, we might not be able to see it working correctly just yet because our CSS is working off of the old parent/child relationship.

Step 3

If you remember in the last tutorial, we absolutely positioned the target relative to the relatively positioned button, so that it would appear directly above it. Since we no longer have that parent/child relationship, we need to add back a relatively positioned container (parent element) for our targets. So I’m going to add a new element in the HTML, as a parent of each set of button and target, like so:

<span class="button_container">
  <span class="my_button">Test Button 1</span>
  <div class="my_target">Test Target 1</div>
</span>
      
<span class="button_container">
  <span class="my_button">Test Button 2</span>
  <div class="my_target">Test Target 2</div>
</span>

Step 4

Of course, the HTML is nothing without some CSS to tell it what to do, so let’s add some style to our CSS. (I’ll add this whole block to my CSS file directly above the .my_button  rule set.)

.button_container {
    padding: 0.2em;
    background-color: #383838;
    display: inline-block;
    position: relative;
}

(Note: The two highlighted lines above add a dark grey line around the buttons, just so you can conceptually see where button_container  is placed on the page. You don’t actually need these in practice to make the whole thing work, and are removed in subsequent steps below.)

Here’s what it should all look like together:

See the Pen jQuery Tooltip (Part 6) by Alex Turnwall (@alturnwall) on CodePen.0

Okay, problem #1 solved. Now, we should be able to open each pop-up, and we’re still able to click within the pop-up without having it close. At this point, we can easily add whatever media we want to these boxes, and our users will still be able to interact with it.

On to the next issue—multiple pop-ups being open simultaneously. This one is a bit more involved… but we’ll go step-by-step.

Step 5

So the first problem is trying to hide any other my_target elements on the page, other than the specific one we’re trying to open.

That’s easy enough. We can add another method to our javascript click function:

$(".my_button").click(function(){
  $(".my_target").hide();
  $(this).next(".my_target").toggle();
});

Now, when we click on my_button, we’re calling two methods, in order.

First, we hide all elements with a my_target class (highlighted line, #2).

Second, we’re still toggling the my_target elements that appears immediately after the my_button element that was clicked, thanks to the $(this)  keyword (line #3).

See the Pen jQuery Tooltip (Part 7) by Alex Turnwall (@alturnwall) on CodePen.0

Importantly, this works because of the order in which is was written! Line #2 is processed before line #3, so even though we’re hiding ALL my_button elements in line #2, we’re then showing only the “next” target in line #3.

This works to ensure that only one pop-up can be opened at a time, but now we have another problem—we can’t actually close the pop-up again by clicking on the corresponding button!

It’s a little bit hard to understand why this is the case, because the whole thing happens in milliseconds, so we can’t even see it. But let’s look at how this works.

  1. When we click on the button, we first hide ALL visible pop-up boxes.
  2. After that processes, we’re toggling the pop-up that corresponds to the button we clicked.

Therefore, if a pop-up is already open, when we click on the button again, expecting to hide it, what we’re actually doing is closing it (#1 above), and then immediately toggling it back open (#2 above). This all happens so fast, you can’t really tell.

Here’s where conditional statements come in handy.

Step 6

What we want to do is to check whether or not the pop-up is open, or rather “visible”, and then do something based on that information. We’ll use an “if” statement, combined with the jQuery :visible  selector (documentation here), to achieve this.

Here’s what the code looks like:

$(".my_button").click(function() {
  if ( $(this).next(".my_target").is(":visible") ) {
    $(this).next(".my_target").hide();
    return;
  }
  $(".my_target").hide();
  $(this).next(".my_target").toggle();
});

Now this should be working properly (see below CodePen). Let’s examine why, below.

See the Pen jQuery Tooltip (Part 8) by Alex Turnwall (@alturnwall) on CodePen.0

The added (highlighted) code, is our first conditional statement. It checks whether or not some condition is true, and only processes the code in between the curly braces if it is true.

Thanks to Max for pointing out that we only need return; here—not return false;.

For reference, return false; does some other important stuff in jQuery too, but for the purposes of this specific demo, it’s not immediately pertinent. If you’d like to learn more, check out this great writeup: jQuery Events: Stop (Mis)using return false.

In addition to that, it’s utilizing an important statement—return;. Here, in the context of our jQuery function, that line is basically telling the browser NOT to process any additional code in the function. More info on the return  statement here.

So the conditional statement is basically saying “if the my_target  related to this button is visible (line #2), then, hide that my_target (line #3), AND stop processing the rest of the code within the click event (line #4).”

So if this conditional is true, the last two lines of code outside of the conditional #5-6, do not get processed.

But, if the conditional is false (so, if the target on the button that you clicked is hidden), then the browser skips over the conditional code (lines #3-4) and only processes lines #5-6. This is essentially the exact same thing that was happening in step #5, before we added the conditional code.

Wrap up

Lot’s of stuff is happening in chorus to make all of this work, but you should focus on three important concepts that this tutorial covers:

  1. The order of your jQuery statements matters.
  2. Conditional (“if”) statements can be used to check if a condition is true.
  3. The :visible  selector in jQuery is useful when combined with a conditional statement to find out if something is visible.
  4. A return;  statement can stop the rest of your event from processing.

We’ll finally wrap up the intro jQuery tutorials about pop-ups with a few small tweaks in the next tutorial—check it out.