Wrapping winners (wrappers)

The story so far

Let's change the team score example. You can try the new version.

It opens like this:

Start

When the Show winner button is clicked, it shows some new output:

Winner

The entire output region is shown as one block:

Output region

Everything in the output region shows at once.

Here's the HTML for the output region.

<h3>The Winner!</h3>
<p>And the winner is... <span id="winner"></span>.</p>

We'll write JS to figure out who the winner is, and inject that into the <span> winner. But how to show everything at once?

The wrapper pattern

The easiest way to do it is to wrap all of the output region's tags in a <div>.

<div id="winner-container" class="hide-on-load">
    <h3>The Winner!</h3>
    <p>And the winner is... <span id="winner"></span>.</p>
</div>

The <div> contains or wraps all of the HTML for the region. Change the div, and you effect all of the tags in the region.

The container has a class:

<div id="winner-container" class="hide-on-load">

The class hide-on-load isn't built-in to CSS. I created the class, and added it to the project's CSS file, project-styles.css.

/*
  Use this class on elements that are to be hidden when the page loads.
*/
.hide-on-load {
    display: none;
}

Notice the comment. It explains what the class is for. Elements with the class are hidden when the page loads.

Showing the output region

So there's a new button. Clicking it shows the entire output region:

Output region

Here's the new button's HTML:

<button onclick="TeamScores.showWinner()"
    type="button" class="btn btn-primary"
>Show winner</button>

When the button is clicked, it runs the code:

TeamScores.showWinner()

Here's the code:

  1. /**
  2. * User wants to know who won.
  3. */
  4. TeamScores.showWinner = function() {
  5.     //Compute the output message.
  6.     var winnerMessage = "";
  7.     if ( team1 > team2 ) {
  8.         winnerMessage = "team 1";
  9.     }
  10.     else if ( team1 < team2 ) {
  11.         winnerMessage = "team 2";
  12.     }
  13.     else {
  14.         winnerMessage = "nobody";
  15.     }
  16.     //Inject winner message.
  17.     $("#winner").html(winnerMessage);
  18.     //Show container, with message.
  19.     $("#winner-container").show("slow");
  20. };
The first three lines are a comment, explaining what the function does.

Lines 6 to 15 compute an message, to inject in the output. The message is put into a string variable. This is a common approach.

Line 6 creates a variable, and initializes it to an empty string.

var winnerMessage = "";

Lines 7 to 15 change the variable, depending on who won. For example:

if ( team1 > team2 ) {
    winnerMessage = "team 1";
}

What do we do with the variable winnerMessage? Here' some HTML from before:

<p>And the winner is... <span id="winner"></span>.</p>

The <span> is a placeholder for the output. Our JS injects winnerMessage into it (line 17):

$("#winner").html(winnerMessage);

This line says, "Hey, browser! Find an element with an id of winner, then set its HTML to the value of winnerMessage."

There's one line left run:

  1. /**
  2. * User wants to know who won.
  3. */
  4. TeamScores.showWinner = function() {
  5.     //Compute the output message.
  6.     var winnerMessage = "";
  7.     if ( team1 > team2 ) {
  8.         winnerMessage = "team 1";
  9.     }
  10.     else if ( team1 < team2 ) {
  11.         winnerMessage = "team 2";
  12.     }
  13.     else {
  14.         winnerMessage = "nobody";
  15.     }
  16.     //Inject winner message.
  17.     $("#winner").html(winnerMessage);
  18.     //Show container, with message.
  19.     $("#winner-container").show("slow");
  20. };
winner-container was hidden, remember, because we gave it the class hide-on-load:

<div id="winner-container" class="hide-on-load">
    <h3>The Winner!</h3>
    <p>And the winner is... <span id="winner"></span>.</p>
</div>

The code $("#winner-container").show("slow") shows winner-container. Since winner-container wraps other HTML tags, all of those tags show together.

show("slow") gives an animated effect.

Here's the wrapping again:

<div id="winner-container" class="hide-on-load">
    <h3>The Winner!</h3>
    <p>And the winner is... <span id="winner"></span>.</p>
</div>

The element winner-container wraps other HTML. It's such a common way to do things, that we should capture it in a pattern:

Pattern

Wrapper

Situation:
You want to apply an effect to a group of HTML elements.
Actions:
Wrap them in a container tag. Give the wrapper an id.

Wrapping in CSS

Wrappers are used for CSS styling, as well. Here's another example.

<div id="bracelet-container">
    <p>I have a bracelet. It says:</p>
    <p>What would Scooby Doo?</p>
</div>

The <div> wraps the two <p> tags. Let's add some CSS to a style sheet:

#bracelet-container {
    color: green;
    font-size: 150%;
}

It would change the color and size of the text in both <p> tags:

Green text

Suppose we added a border:

#bracelet-container {
    color: green;
    font-size: 150%;
    border: thin solid magenta;
}

We'd get:

Border

The border is applied to the container:

#bracelet-container {
    ...
    border: thin solid magenta;
}
...
<div id="bracelet-container">...<div>

So it is around all of the elements in the container.

Adela
Adela
I don't like the look of that. The border is right up against the text.
You're right. Let's add some padding:

#bracelet-container{
    color: green;
    font-size: 150%;
    border: thin solid magenta;
    padding: 1rem;
}

Remember that padding adds space between the border and content of an element.

Padding

Wrapping in JS

The braces wrap JS code, similar to wrapping in HTML. The wrapped code is a code block. Check out this example:

if ( snowWhite == "happy" ) {
    //Code block A
    happy = "happy";
    doc = "happy";
    dopey = "happy";
    sleepy = "happy";
    bashful = "happy";
    sneezy = "happy";
    grumpy = "grumpy";
}
else {
    //Code block B
    happy = "happy";
    doc = "grumpy";
    dopey = "grumpy";
    sleepy = "grumpy";
    bashful = "grumpy";
    sneezy = "grumpy";
    grumpy = "grumpy";
}

In…

if ( snowWhite == "happy" ) {

== means "is equal to."

Either code block A or code block B will run. They will never both run. If A runs, all of the statements in A will run. If B runs, all of the statements in B will run.

A function is basically a code block with a name. You saw this earlier:

/**
* User wants to know who won.
*/
TeamScores.showWinner = function() {
    //Compute the output message.
    var winnerMessage = "";
    ....
};

The function is all of the code between the braces.

So, braces wrap JS code, making a block. The block is treated as one chunk.

Summary

  • A wrapper or container is an HTML element that surrounds other elements.
  • Usually a <div> tag with an id is used to create a wrapper.
  • Elements in a wrapper are treated as one block.
  • JS code can work on wrappers: $("#wrapper").show("slow")
  • CSS can style wrappers: #wrapper {...