πŸ§‘πŸΎβ€πŸ’» prep

πŸ’» User interfaces

Learning Objectives

User interfaces provide the gateway between a user and a complex application. When navigating the internet, we continually interact with web pages to access data and interact with complex web applications.

A web browser 🧢 🧢 web browser provides a user interface to interact with web pages. is capable of fetching HTML documents from a server, and then rendering the document to create a user interface. If a user visits a website and gets a plain HTML document back, we say this content is static.

By static, we mean that the server’s job was just to hand over the HTML document, and then the browser takes over. A user may interact with the browser’s interface, e.g. to scroll, type in a text field, or drag-and-drop an image around, but this is done purely by interacting with the browser - the browser won’t talk to the server about this.

πŸ›‘ Character limit

Learning Objectives

Let’s define a problem.

Suppose we’re working on a website where users will need to comment on articles. In the user interface, they’ll be provided with a textarea element where they can type their comment. However, there is a character limit of 200 characters on their comment. As users type in to the textarea they should get feedback on how many characters they’ve got left for their comment.

Try typing in the character limit box above and observing the behaviour as you type.

We can define acceptance criteria for this component:

Given an textarea and a character limit of 200
When a user types characters into the textarea
Then the interface should update with how many characters they’ve got left

🏁 Starting point

In the user interface, we will start off with some static html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <section>
      <h3>Example character limit comment component</h3>
      <label for="comment-input"
        >Please enter your comment in the text area below
      </label>
      <textarea
        id="comment-input"
        name="comment-input"
        rows="5"
        maxlength="200"
      ></textarea>
      <p id="character-limit-info">You have 200 characters remaining</p>
    </section>
  </body>
</html>

To implement the acceptance criterion, we’ll need to interact with the elements on the page. We’ll need a way to access and update elements based off user interactions.

🧭 Breaking down the strategy

Learning Objectives

To implement the character limit component, we need to update the interface as the user types in the text area. We can outline a strategy as follows:

flowchart TD A[Step 1: Define the character limit of 200] --> B[Step 2: Access the textarea element] --> C[Step 3: Calculate the number of characters left] --> D[Step 4: Update the interface with the number of characters left]

This strategy gives us a rough guide for the road ahead. However, as we learn more about this problem, we may need to update our strategy.

🌲 Interacting with the page

Learning Objectives

Let’s consider the starting html. We need a way of interacting with the elements of this page once it is rendered.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <section>
      <h3>Character limit</h3>
      <label for="comment-input"
        >Please enter your comment in the text area below
      </label>
      <textarea id="comment-input" name="comment-input" rows="5"></textarea>
      <p id="character-limit-info">You have 200 characters remaining</p>
    </section>
  </body>
</html>

🌳 HTML tree

HTML documents form a tree-like structure. We start at the top html element and from there other html elements are nested inside.

html tree

When we use a web browser, it takes this HTML document, and provides us with an interface - a visual representation of the document, which we can read, and interact with (e.g. with a keyboard and mouse).

Document Object Model

When the browser first renders a web page it also creates the DOM - short for Document Object Model 🧢 🧢 Document Object Model The Document Object Model is a data representation of the content in a web page. All html elements are represented as objects that can be accessed, modified and deleted. .

Just like a web browser provides us a visual interface, the DOM is an interface. But it is not an interface for humans to see and interact with, it is an interface for JavaScript to interact with. We can write JavaScript programs to interact with the Document Object Model so we can make the page interactive.

We can use Dev Tools to inspect the DOM and look at the elements on the page. Use Dev Tools to inspect the character limit component from earlier.

πŸ”Ž Querying the DOM

Learning Objectives

Inside the body of the html document, we start with the following html:

<section>
  <h3>Character limit</h3>
  <label for="comment-input"
    >Please enter your comment in the text area below
  </label>
  <textarea
    id="comment-input"
    name="comment-input"
    rows="5"
    maxlength="200"
  ></textarea>
  <p id="character-limit-info">You have 200 characters remaining</p>
</section>

querySelector()

πŸ’‘ recall

In the plan defined earlier, we had the following step: Step 2: Access the textarea element

The DOM is an interface. It represents html elements as objects and provides functions to access these objects. Let’s start by accessing the textarea element and its value. To access DOM elements, we can use a method on the DOM API - document.querySelector

We can create a javascript file, script.js, and link it to the html document using a script element:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script defer src="script.js"></script>
  </head>
  <body>
    <section>
      <h3>Character limit</h3>
      <label for="comment-input"
        >Please enter your comment in the text area below
      </label>
      <textarea id="comment-input" name="comment-input" rows="5"></textarea>
      <p id="character-limit-info">You have 200 characters remaining</p>
    </section>
  </body>
</html>

Inside script.js, we can call document.querySelector:

const textarea = document.querySelector("textarea");

document.querySelector takes a single argument a string containing a CSS selector (just like we use when defining what elements a CSS rule should apply to).

document.querySelector returns an element object representing the first element in the page which matches that CSS selector. This element object lets us inspect and modify the element in the page.

Here we have given it the string "textarea", which is the CSS selector used to look up the elements with tag name textarea. The function returns an element object, which represents the first textarea in the web page. Once we can access the textarea object, we can access its properties. In particular we want to access the value a user types into the textarea box. We can do this by accessing the value property:

const textarea = document.querySelector("textarea");
console.log(textarea.value); // evaluates to the value typed by the user
  1. On your local machine, set up a new directory with an index.html and script.js.
  2. Make sure you start with the same static html as the example above.
  3. Double check your script file is linked to your html file.
  4. Try querying the DOM and accessing various elements like the textarea element.

🎬 Events

Learning Objectives

In the case of the textarea element, we want to update the p element text every time the user types inside the textarea. In other words, we want our application to react to the user typing on the keyboard. Currently our plan looks like this:

flowchart TD A[Step 1: Define the character limit] --> B[Step 2: Access the textarea element] --> C[Step 3: Calculate the number of characters left] --> D[Step 4: Update the interface with the number of characters left]

However, we’re missing a step in our plan. We need to find a way of running some code in response to an event.

Definition: events

An event is something that occurs in a programming environment.

Events are things that happen in the browser, which your code can ask to be told about, so that your code can react to them. In a browser context, an event could be a user clicking on a button, a user typing something into a textarea box, a user submitting a form etc. Not all events are in response to user actions, for instance there is an event for the browser finished initially rendering the page. You can find a complete reference all the different event types on MDN.

When a user presses a key in our textarea, the browser will create an event. If we asked the browser to tell us about it, we can respond to it. So we can update our plan as follows:

flowchart TD A[Step 1: Define the character limit] --> B[Step 2: Access the textarea element] --> C["`**Step 3: Ask to be notified when a user presses a key**`"] D["`**Step 4: When the browser tells us a user has pressed a key**`"] --> E[Step 5: Calculate the number of characters left] --> F[Step 6: Update the interface with the number of characters left]

Notice a few things here:

  • There’s no arrow between Step 3 and Step 4. The trigger for Step 4 is a user doing something - if the user doesn’t type anything in the textarea, Step 4 will never run (and neither will Step 5 and Step 6).
  • We don’t run Step 4. The browser runs Step 4. In Step 3 we asked the browser to do something for us in the future. This is something new - up until now, we have always been the ones telling JavaScript what to do next.

πŸ“€ Reacting to events

Learning Objectives

As a user, we interact with the elements on a web page. We click on buttons, input text, submit forms etc.

To react to an event, we can declare a function that we want to run whenever a certain event occurs. We call this function an event handler. In the example below, we name this function updateCharacterLimit:

1
2
3
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {}

We need to tell the browser to call updateCharacterLimit whenever a keyup event fires 🧢 🧢 fires “fires” means “an event is triggered” . We do this using addEventListener:

1
2
3
4
5
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {}

textarea.addEventListener("keyup", updateCharacterLimit);

Let’s break down the arguments that are passed to addEventListener.

  • "keyup" - this is the type of event we want to be notified about
  • updateCharacterLimit - the second argument is a function. It is a function that is called when an event occurs.

In JavaScript, we can pass functions as arguments to other functions. In this case, we’re passing a function updateCharacterLimit to addEventListener as an input. We can think of this as saying: whenever a key is released on the textarea element, then the browser will call the function updateCharacterLimit. Any code we want to run in response to the keyup event will need to be inside the updateCharacterLimit function.

We can add a log to updateCharacterLimit to check it is called every time the "keyup" event fires.

const characterLimit = 200;
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {
  console.log(
    "keyup event has fired... The browser called updateCharacterLimit..."
  );
}

textarea.addEventListener("keyup", updateCharacterLimit);
<section>
  <h3>Character limit</h3>
  <label for="comment-input"
    >Please enter your comment in the text area below
  </label>
  <textarea
    id="comment-input"
    name="comment-input"
    rows="5"
    maxlength="200"
  ></textarea>
  <p id="character-limit-info">You have 200 characters remaining</p>
</section>
In your local project, define your own event handler and then use addEventListener to register that event handler for a keyup event. Add a console.log to the event handler and check the event handler is being called when the event fires. Check the console tab in dev tools to see the log appear in the console.

πŸ“ˆ Check progress

Learning Objectives

Let’s use the plan from earlier to check our progress.

flowchart TD A[Step 1: Define the character limit] --> B[Step 2: Access the textarea element] --> C["`**Step 3: Ask to be notified when a user presses a key**`"] D["`**Step 4: When the browser tells us a user has pressed a key**`"] --> E[Step 5: Calculate the number of characters left] --> F[Step 6: Update the interface with the number of characters left]

Let’s consider our code at the moment:

const characterLimit = 200;
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {
  console.log(
    "keyup event has fired... The browser called updateCharacterLimit..."
  );
}

textarea.addEventListener("keyup", updateCharacterLimit);

We’ve done the following:

  • Step 1: Defined a characterLimit
  • Step 2: Accessed the textarea element
  • Step 3: Registered an event handler updateCharacterLimit

The browser will do the following for us:

  • Step 4: The browser will tell us when a user has pressed a key

We must still complete the following steps:

  • Step 5: Calculate the number of characters left
  • Step 6: Update the user interface with the number of characters left

To obtain the characters left, we can calculate the difference between characterLimit and the number of characters in the textarea element:

const characterLimit = 200;
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {
  const charactersLeft = characterLimit - textarea.value.length;
  console.log(`You have ${charactersLeft} characters remaining`);
}

textarea.addEventListener("keyup", updateCharacterLimit);
<section>
  <h1>Character limit</h1>
  <textarea id="comment-input" rows="5" maxlength="200"></textarea>
  <label for="comment-input"
    >Please enter a comment in fewer than 200 characters
  </label>
  <p id="character-limit-info">You have 200 characters remaining</p>
</section>

Typing in to the textarea element, we should see a string like "You have 118 characters left" printed to the console each time a key is released. However, we have one final step: we must now update the DOM label with the information about how many characters are left.

🏷️ Updating the interface

Learning Objectives

We can calculate the remaining characters available every time a user’s key is released from the keyboard in the textarea. Finally, we must update the p element in the user interface with the number of characters remaining.

Step 5: Update the interface with the number of characters left

To achieve this goal, we’ll need to access the p element with id "character-limit-info" and then update its text content. As before, we can use document.querySelector to access an element in the DOM using an appropriate CSS selector:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const characterLimit = 200;
const textarea = document.querySelector("textarea");

function updateCharacterLimit() {
  const charactersLeft = characterLimit - textarea.value.length;
  console.log(`${charactersLeft} characters remaining`);

  const charactersLeftP = document.querySelector("#character-limit-info");
  charactersLeftP.textContent = `You have ${charactersLeft} characters remaining`;
}

textarea.addEventListener("keyup", updateCharacterLimit);
Explain why the code to access the p element is written inside the scope of updateCharacterLimit.