Session 18: Responding to Button Clicks with JavaScript

Download this starter code to use for the opening exercise and the rest of the session.

Opening Exercise: Change the Text and Style of a Page

The reading for this week shows us how we can access and change an element's content and styling, perhaps in response to a user action. Consider these applying these JavaScript statements to our demo page from last time:

myMain = document.body.querySelector('p');
myMain.innerHTML = '<main>Smile 2 tops the box office.</main>';
myMain.style.height = '200px';
myMain.style.backgroundColor = 'lightgreen';
myMain.style.width = '200px';

document.body.style.backgroundColor = 'slategray';

Let's practice.

Write a JavaScript script that fixes the content and styling of the demo page.
In particular:
  • The h1 heading is smaller than the h2 heading, because the style sheet sets the size of h1 but leaves h2 at the default size.
    Change the size of h2, or the size of h1.
  • The text in the .infobox element crowds right up to the edge of the border box.
    Add padding to the element. The bottom padding should be a bit larger than the top.
Bonus challenge: Change the font family for the link to serif, like the rest of the document.

Put your code in the file script.js, which is loaded by the web page.

Solution

Here is a possible solution.

Recall that JavaScript uses different naming conventions than CSS, so we have to use camelCase instead of hyphens. JavaScript also use string values for all name/value pairs.

Reviewing Functions

Last time, we learned about JavaScript functions. A function

We define functions and call them.

function soundAlarm() {
  alert("Wake up before you go-go!");
}

soundAlarm();

Recall the evolution of our code on the Road to St. Ives in Session 17:

You will get more practice writing functions in Homework 8. If functions are new to you, then you may be fuzzy on how calling a function and passing arguments to it works. There will be a section in the read for Week 10 that walks through the process.

Adding Dynamic Behavior with a Button

The web is an event-driven medium. The browser displays some initial content and then essentially enters an infinite loop, known as the event loop, waiting for events to occur. When an event occurs, the browser responds and then waits again.

We will learn more about events and event-driven programming over the next few weeks. For now, let's add some dynamic behavior to our pages by responding to one of the simplest events on the web: the user clicking on a button.

Consider this simple web page. It contains a heading and a button. When we click the button, it generates an event. By default, nothing happens.

Let's write a script to respond to the event:

<script type="text/javascript">
  function respondToClick(e) {
    document.body.style.backgroundColor = "lightblue";
    document.body.innerText = "I am a little blue today";
  }

  let button = document.querySelector('button');
  button.onclick = respondToClick;
</script>

Now consider the code:

We say that the function is an event handler, and and the code after the function registers the function with the button.

The event handler we write for a button can do anything any other script. Up to now, we've done one of two things with our scripts:

Dynamic web pages often do something more: they change one of the attributes of an element.

Working with Elements in the DOM

Each element in the DOM contains a large number of properties and methods. Once we have a reference to an element, we can use these properties and methods to manipulate it.

Element Properties

We have already worked with two properties of HTML elements. element.innerText holds the text content of the element. element.innerHTML holds the markup content of the element, which could be text, but could also include other HTML tags.

Other useful properties include:

Element Methods

In addition to querySelector() and querySelectorAll(), there are a several other methods that are useful for accessing and working with an element's attributes:

Let's use setAttribute() and removeAttribute() to implement a common dynamic behavior on the web: revealing hidden content.

Revealing Hidden Content with a Button

Consider this web page. It contains a button and a 'hidden' paragraph:

<p id="answer" hidden>
    42
</p>

As before, when we click the button, nothing happens. We have not told the browser how to respond to the event.

We can use the removeAttribute() method to remove the paragraph's hidden attribute:

<script type="text/javascript">
  let answer = document.body.querySelector('#answer');
  answer.removeAttribute('hidden');
</script>

But that code runs when the page loads, revealing the answer immediately. Instead, we need a function to give to the button as its event handler:

function respondToClick(e) {
  let answer = document.body.querySelector('#answer');
  answer.removeAttribute('hidden');
}

let button = document.body.querySelector('button');
button.onclick = respondToClick;

Exercise: Adding a Hide Button

Once the use clicks the button, the only way to hide the answer is to reload the page. But now that we know how to write a function that responds to a button, we can put control on the page itself.

Add a 'hide' button to the web page.

Add code to the script that hides the answer when the new button is clicked.

Use the setAttribute() method put 'hidden' back on the paragraph. Use 'true' as its value.

Here's a solution. We need a way to select the second button, so I gave it an id. The code is a copy-and-paste of the 'reveal' button's code, with a changes:

Revealing and Hiding Content with One Button

That's dandy, but it uses two buttons.

How can we modify the page so that the user can re-hide the answer?

We still need two handler functions. But we can access the button from within one event handler and change its event handler to the other function!

let button = e.target;
button.innerText = 'Hide the Answer';
button.onclick = hideAnswer;       // the other function

Do something similar in the other function, and we are set.

That's quite nice! You have just implemented your first dynamic web page.