Dropdowns, Modals and Carousels

Our topic for the next class is learning how to do some very common tasks on websites: dropdown menus, modals, and carousel (also called image galleries or slideshows). You'll use dropdown menus and modals in your final project.

There are many solutions for these problems, including fancy transitions between slides and much more. We're going to keep it fairly basic, though.

Furthermore, since we are using Bootstrap 4 in this course, we'll take advantage of the features that Bootstrap provides. If you're curious about how it could be done by hand, we'll cover that as well.

General Outline:

  • BS4 Dropdowns
  • BS4 Modals
  • BS4 Carousels
  • By Hand Dropdowns
  • By Hand Slideshows

Note that all of the Bootstrap features require JavaScript, so the head of our HTML will have to load three Bootstrap JavaScript files along with the Bootstrap CSS. Like this:

<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.js"></script>
</head>

Bootstrap Dropdowns

Take a minute to read the W3Schools tutorial on BS4 Dropdowns. Just the first section is sufficient.

The menu options are clickable, allowing you to trigger some JavaScript. Clicking anywhere else on the page closes the dropdown. A simple dropdown example should suffice.

There's no JavaScript that you have to write; Bootstrap provides all the code. All you have to do is set up the HTML. Here's the HTML for that example:

  <div class="btn-group">
    <button type="button" class="btn btn-primary">Apple</button>
    <button type="button" class="btn btn-primary">Samsung</button>
    <div class="btn-group">
      <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
      Sony
      </button>
      <div class="dropdown-menu">
        <a class="dropdown-item" href="#">Tablet</a>
        <a class="dropdown-item" href="#">Smartphone</a>
      </div>
    </div>
    <div class="btn-group">
      <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
      Platforms
      </button>
      <div class="dropdown-menu">
        <a class="dropdown-item" href="#" id="os-linux">Linux</a>
        <a class="dropdown-item" href="#" id="os-mac">Mac</a>
        <a class="dropdown-item" href="#" id="os-windows">Windows</a>
        <button class="dropdown-item" id="os-android">Android</button>
        <button class="dropdown-item" id="os-ios">IOS</button>
      </div>
    </div>
  </div>

Things to note:

  • The dropdowns are created by the CSS class dropdown-toggle and the data-toggle="dropdown" attribute.
  • The CSS dropdown-menu class builds the dropdown menu.
  • Add the dropdown-item class to each menu item
  • For the menu items, you can use either hyperlinks <a href="#"> or buttons <button type="button">.

I prefer using button because the hyperlinks end up with a # in the URL, which I find ugly, and they mess up the "back" button, because clicking "back" returns you to the page without the # in the URL, instead of to the previous page (this one). Try it!

  • Visit the example, click on "Linux" and then click the back button.
  • Visit the example, click on "Android" and then click the back button.

Of course, if you want the dropdown to have hyperlinks in it, say to other parts of your multi-page site or even external links, then <a> is the way to go. Plus, if you want to use hyperlinks but just to trigger JavaScript, you can use the event.preventDefault() that we learned. So my preference is not the only way to go.

Adding JavaScript

In the example above, I added id attributes to the items on the "Platforms" menu, which allows me to trigger some JavaScript event handlers. I added some simple demo behaviors like this:

      // These event handlers are not necessary for the dropdowns to work. They show that you can
      // add your own event handlers to the buttons above to do whatever you want.

      $("#os-linux").click(function (evt) {
          console.log('I see you are a Linux fan! Bravo!');
      });

      $("#os-mac").click(() => console.log('Oh ho! Another Apple aficionado!'));

      $("#os-windows").click(() => console.log('Interesting! a Windows maverick on a Mac-centric campus!'));

      $("#os-android").click(() => console.log('Nice! Will you learn how to program apps on your phone?'));

      $("#os-ios").click(() => console.log("I'm told these are best for privacy. True?"));

Try them and look in the JS console.

Note that I didn't add my bounds plug-in to check that I had spelled the selectors correctly, which I immediately regretted because I didn't spell them all correctly. My bounds plugin does work with the jQuery that's loaded by Bootstrap, so you could do that. Just add the following to the head, after we load jQuery:

<script src="https://cs.wellesley.edu/~anderson/js/bounds/bounds-plugin.js"></script>

Bootstrap 4 Modal

A modal is a pop-up dialog box. It's very intrusive, so you wouldn't want to use it all the time, but sometimes it's the right thing to do.

Take a minute to read the first section of the W3Schools BS4 Modal.

Here's an example

In that example, the modal is an order form. If you click the red "close" button, the modal closes with no harm done. You can also close it by clicking anywhere outside it.

Modals allow a more extended interaction with the user than just a dropdown menu.

Here, we might want to trigger some JavaScript if the user clicks the "place order" button (which is, in fact, an ordinary button not a submit button). The JS is pretty straightforward:

    // Demo of how to add an event handler to the modal order form.
    $("#place_order").click(function (evt) {
        console.log('order for',
                    $('[name=name]').val(),
                    $('[name=size]').val(),
                    $('[name=crop]').val());
        $('form')[0].reset();
        $('#myModal').modal('hide');
    });

Note, though, that we explicitly have to hide the modal when we are done, using:

        $('#myModal').modal('hide');

Carousels

Carousels is what the Bootstrap developers call this feature. Other people might call them slideshows or image galleries. The markup is a bit more complex than the earlier features.

Please read the first section of the W3Schools BS4 Carousel.

Here's a slideshow example using some pictures of Harry Potter actors.

I won't go into the details of the markup, but I'd be happy to talk to you about it if you need help.

Dropdowns and Carousels By Hand

The following sections discuss how to do dropdowns and carousels "by hand" (meaning not using Bootstrap).

Rather than write up how to do this, I'm going to defer to two descriptions that are on W3Schools, using the links below.

Clickable Dropdowns

We want to be mobile-friendly and old-fashioned dropdown menus typically dropdown when the mouse is hovered over them. But we can't "hover" on a touch-screen device. Instead, we will click to open/close a dropdown menu. Here's one way:

clickable dropdown

Clickable dropdowns are useful in general, and we will use them in the final project, so they are worth learning.

That code is good but has some flaws, which I will address in class. Let's build up to that.

Slideshows

A slideshow displays one of a set of images, rotating through them. It has arrows to advance the slideshow or move it backwards, little buttons to indicate where we are in the set and lots of other eye candy.

slideshow

Again, the W3Schools code is good but has some flaws, which I'll address in class and below.

Automatic Slideshows

To have a slideshow automatically advance, it's sufficient to have a function that will manually advance the slideshow, and then have the browser invoke that function every few seconds. That's easily done with the built-in JavaScript setInterval function.

Learn more about setInterval from MDN: setInterval

The W3Schools example uses setTimeout, but I think setInterval is superior, because it separates the code that advances the slideshow from the automatic advance behavior. That allows us additional flexibility. For example, the W3Schools code doesn't allow us to turn the automatic slideshow off, because the return value from setTimeout is buried in the showSlides function. That return value would allow us to cancel the event.

Turning a Slideshow on/off

Both setTimeout and setInterval return a numeric code or id for that event, allowing us to cancel the event. It's just a small integer with no meaning other than identifying which future event this is, a meaning that is known only to the browser. So our code just stores it and, if we want to cancel the event, passes the ID to clearTimeout or clearInterval.

Here's code that would allow us to turn an automatic slideshow on/off:

<button id="startSlideshow">start slideshow</button>
<button id="stopSlideshow">stop slideshow</button>
// global variable holding the code to cancel the slideshow. 
var intervalId;

$("#startSlideShow").click(function () { intervalId = setInterval(nextSlide, 1000) });
$("#stopSlideShow").click(function () { clearInterval(intervalId) });

To be fair, the W3Schools code could be modified to store the ID in a variable, allowing us to stop the slideshow, but I still like the setInterval modularity better, because we can easily switch between automatic and manual mode slideshows.

Conclusion

The Bootstrap features are relatively simple to use and come with thoroughly debugged JavaScript, so those are a couple of huge points in their favor. Furthermore, the Bootstrap features have thought about accessibility, such as being able to use the dropdowns with the keyboard (tab key, arrows keys, the enter key) for those who can't use a mouse or prefer not to (I'm sometimes in the latter camp). So that's another huge point in its favor.

A small downside is having to load the JavaScript files: not just jQuery, but popper.js and bootstrap.js. Slimming those down is part of the goal of Bootstrap version 5. But that's a minor point, and chances are your browser already has those in cache. Furthermore, if you're already using Bootstrap JavaScript, there's no additional penalty to using these features.

Finally, while Bootstrap is pretty flexible, it's not as flexible as raw CSS and JavaScript, so it might feel confining. You may want slightly different behavior, in which case you should know that it's not magic; it's just JavaScript, which you are capable of figuring out and modifying (or replacing) if you choose.