Regular Expressions—a Rite of Passage: Completing the Application
Tags: regex, javascript, dom
Published: 2023-02-28 01:04:19

![JavaScript in Plain English logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18l7uah4jdiyqik5wbge.png)
<h6>This article was first published on <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a>.</h6>

---

<p><b>Part 3: Building from Infrastructure to Completed Application</b></p>


![Woman with Computer Code Superimposed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nvomi2lenwle8l86fdwk.jpg)
<h6><center>Photo by <a href="https://unsplash.com/@thisisengineering?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">ThisisEngineering RAEng</a> on <a href="https://unsplash.com/s/photos/software?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></center></h6>

---

<h2>Table of Contents</h2>

#### _<a href="#welcome">WELCOME BACK!</a>_
#### <a href="#completeApp">Completing the Application</a>
#### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#codeCallback">Step 7. Coding the Callback Functions</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#populateResult">The populateResultBox() Function</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#depopulateResult">The depopulateResultBox() Function</a>_
#### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#eventListeners">Step 8. Coding the Event Listeners</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#validateZip">Add an Event Listener to the Validate Zip Codes Button</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#reset">Add an Event Listener to the Reset Button</a>_
#### _<a href="#conclusion">Conclusion</a>_
#### <a href="#next">Next Steps</a></li>
#### <a href="#references">References</a>

---

## _WELCOME BACK!_<a id="welcome"></a>

Our moment has arrived. We are now ready to finish our application started in **_Regular Expressions&mdash;a Rite of Passage: From Theory to Practice_**.

## _Completing the Application_<a id="completeApp"></a>

We left off at Step 6 in Part 2 of this tutorial, in which we built out the infrastructure of our application, providing all necessary data structures and helper functions.

Two steps remain to complete the application:

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. We need to code the callback functions that will be used by the two<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event listeners mentioned in Part 2.</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. We need to write the event listeners that will call the callback functions<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in order to carry out their work.

---

<h3><center>Step 7. Coding the Callback Functions</center></h3><a id="codeCallback"></a>

Let’s think for a moment about what these callback functions need to accomplish. We know that they are attached as arguments to two event listeners, one listening for a **click event** on the **Validate Zip Codes** button and the other listening for a click event on the **Reset** button.

We will be picking up exactly where you left off in your code at the end of<br>Part 2.

For the **Validate Zip Codes** button, we need a callback function that will swap contents with the default message of **NO MATCH** and populate its parent instead with a **scrolling window** of valid zip code matches.

---

### <center>The `populateResultBox()` <i>Function</i></center><a id="populateResult"></a>

**Search in the starter code** for the line that reads:

`// TO BE DONE: Code populateResultBox() callback function.`
 
and replace it with the following lines of code:

```javascript
const populateResultBox = () => {

  resultBox.classList.remove(‘default-result’);
  resultBox.removeChild(‘placeHolder’);
  resultBox.classList.add(‘custom-scrollbar’);

  createParagraphText();

  // Create paragraphs and set textContent only
  // if not already created. Prevents doubling
  // of result data if old paragraphs have not
  // yet been garbage collected.

  if (paragraphs.length === 0) {
    createParagraphs();
  }
  // Append all result paragraphs to resultBox.

  appendParagraphs(resultBox, paragraphs);

};

```
<h6><center>Code Listing 1. The populateResultBox() Callback Function</center></h6>

---

A lot is happening in this function, though much of it has been broken down in our discussion of the helper functions. Nonetheless, there are still a few remaining new concepts here.

The first three lines of code are manipulation of the DOM as we have not seen before in this tutorial. To fully understand these three lines, we will need to look at some code snippets from our HTML and CSS.

**Code Listing 2** below shows the HTML element to which **resultBox** refers:

&lt;div id="results"
class="results-data-dimensions default-result"&gt;
&nbsp;&nbsp;&lt;p class="default-message" id="message"&gt;no match&lt;/p&gt;
&nbsp;&nbsp;&lt;!-- Dynamic content lives here. --&gt;
&lt;/div&gt;
<h6><center>Code Listing 2. HTML Elements Captured by resultBox</center></h6>

---

You might recall from Part 2 a code listing that started with the element<br>`<div id= “getResults”>`, which contains the entire widget with the two buttons and the `<p>` element with the **NO MATCH** message shown in<br>**Code Listing 2** above.

We need to take a brief dip into the **CSS** code to understand fully what is being changed by `populateResultBox()`.

Take a look at **Code Listing 3** below:

```css
.default-result {
  background-color: #808080;
}
```
<h6><center>Code Listing 3. CSS Class Controlling resultBox Background Color</center></h6>

---

As you can see, the `.default-result` class specifies a gray background. As this background is part of a placeholder for the results about to populate `resultBox`, we want to clear it.

Now let’s look at the first line of code in the `populateResultBox()` callback function:

```javascript
resultBox.classList.remove(‘default-result’);
```
---

As we know, the `resultBox` object captures `<div id=“results”>` shown in **Code Listing 2**.

In the **Document Object Model (DOM)**, HTML elements have the `classList` property, which keeps track of all CSS classes associated with them.

The `remove()` method chained to the classList property does exactly what it says&mdash;it removes the class passed to it from the classList. This does _not_ mean the class is deleted from the linked CSS file. What it _does_ mean is that the web page displayed in your browser will no longer show a gray background in the scrolling window of results.

Now let’s review our second line of code:

```javascript
resultBox.removeChild(placeHolder);
```

---

This line of code is concerned with nodes in the **DOM tree**. As you
might recall from earlier, `placeHolder` is the DOM node that captures
`<p class=“default-message” id=“message”>no match</p>.`

This paragraph is the **NO MATCH** message shown on the opening screen of our application. Obviously, we need to remove this from our display.

The `removeChild()` method removes a **child node** from a **parent node**. `placeHolder` is a child node of `resultBox`. As in the case of the `remove()` method above, `removeChild()` leaves the paragraph in the HTML untouched. It is merely removed from our live display.

Next let’s review our third line of code:

```javascript
resultBox.classList.add(‘custom-scrollbar’);
```
Here, we are doing something quite different. Here, we add a CSS class<br>to `reasultBox`. **Code Listing 4** below shows the code for CSS class `.custom-scrollbar`:

```css
.custom-scrollbar {
  --scrollbar-foreground: #a239ca;
  --scrollbar-background: rgba(162, 57, 202, 0.25);
  /* Foreground and Background Colors */
  scrollbar-color: var(--scrollbar-foreground)
  var(--scrollbar-background);
}
```
<h6><center>Code Listing 4. CSS Class Controlling Scrollbar Styling for resultBox</center></h6>

---

Without diving deeply into the above code, all we need to know is that this class sets foreground and background styling for the scrollbar in `resultBox` once it has been populated. For those who are interested in delving deeper into the styling, the above style was informed by the work of _CSS Tricks_ (Coyier, _“Using Custom Properties for Styling Scrollbars in CSS”_).

The `add()` method chained to the `classList` property, in contrast to the `remove()` method we saw moments ago, adds a CSS class to `resultBox`.

The remaining code in the `populateResultBox()` callback function has already been covered in **Part 2, Step 6** of this tutorial.

---

### <center>The `depopulateResultBox()` <i>Function</i></center><a id="depopulateResult"></a>

Now we can turn our attention to coding the `depopulateResultBox()` callback function. As you might guess, the purpose of this function is to remove the paragraphs that populated `resultBox` and restore the default message and styling associated therewith.

**Search in the starter code** for the line that reads:

`// TO BE DONE: Code depopulateResultBox() callback function.`

and replace it with the following lines of code:

```javascript
const depopulateResultBox = () => {
  while (resultBox.firstChild) {
   resultBox.removeChild(resultBox.firstChild); 
  }
  resultBox.classList.remove(‘custom-scrollbar’);
  resultBox.classList.add(‘default-result’);
  resultBox.appendChild(placeholder);
};
```
<h6><center>Code Listing 5. The depopulateResultBox() Function</center></h6>

We've met every method seen in this function when we coded the `depopulateResultBox()` helper function above. So here is a quick breakdown of what is happening in this code:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. We start with a while loop that takes a single argument&mdash;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`resultBox.firstChild`. We already know that resultBox is a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DOM node. As such it exposes properties and methods. The &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`firstChild` property captures the first child of resultBox,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;which would be the first paragraph in resultBox.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. The argument in this while loop  is a Boolean that evaluates to<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;true if there is a `firstChild` paragraph node in resultBox. Each<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time through the loop,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`resultBox.removeChild(resultBox.firstChild);`

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is executed, it removes one paragraph. On each iteration of the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop the next paragraph in line becomes the firstChild. Once<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;there is no `firstChild` left, the loop terminates because no<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paragraphs remain.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Once all paragraphs have been removed the three remaining<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lines of code outside of the while loop remove the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`.custom-scrollbar` class, thus restoring the gray background,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and finally uses the appendChild() method to restore the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**NO MATCH** message.

We have now completed our callback functions and are ready to proceed<br>to the last step&mdash;coding the event listeners for the **Validate Zip Codes**<br>and **Reset** buttons.

---

<h3><center>Step 8. Coding the Event Listeners</center></h3><a id="eventListeners"></a>

Now we approach the ultimate step in completing our application&mdash;that of coding the event listeners
for our buttons.

To start, I would like to recall two declared node objects that we created at the beginning of **_Part 2, Regular Expressions—a Rite of Passage: From Theory to Practice_**:


```javascript
const resultButton = document.getElementById(‘validate’);
const resetButton = document.getElementById(‘reset’);
```
<h6><center>Code Listing 6. Nodes in Need of Event Listeners</center></h6>

---

These two lines of code are our starting point as we will need them to build our event listeners.

`resultButton` is the DOM node that captures the<br>`<button class=“controlButton” id=“validate”>`  element in our **index.html** file.

`resetButton` is the DOM node that captures the<br>`<button class=“controlButton” id=“reset”>` element.

With this new information we can begin.

---

### Add an Event Listener to the Validate Zip Codes Button<a id="validateZip"></a>

**Search in the starter code** for the line that reads:

`// TO BE DONE: Code resultButton event listener.`

and replace it with the following line of code:

```javascript
resultButton.addEventListener(‘click’, populateResultBox);
```

---

Using the `resultButton` DOM node, we chain the `addEventListener()` method to it. This method takes two arguments, as you see.

The first specifies what type of event to be listened for (there are a number of different kinds). Ours is a **click event**, which means that JavaScript will listen for any mouse clicks on `resultButton`.

The second is the callback function  to be executed when the click event is detected. The callback function can be an anonymous function included as the second argument. In our case, the callback function is `populateResultBox()`.

With this event listener in place, we should now be able to populate the `resultBox` with valid zip code matches when we click the **Validate Zip Codes button**. Let’s test this.

If you have not already done so, open the **index.html** file in your favorite browser. If you have the file open already, make sure to refresh your browser.

Click on the **Validate Zip Codes** button.

Your screen should look much like that shown below in **Figure 1**:


![Fig. 1. resultBox with Scrollbar and Populated with Valid Zip Codes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3y2c7ob9pz5ezr1x30f.png)
<h6><center>Fig. 1. resultBox with Scrollbar and Populated with Valid Zip Codes</center></h6>

---

### Add an Event Listener to the Reset Button<a id="reset"></a>

Now let’s code the event listener for the Reset button.

**Search in the starter code** for the line that reads:

`// TO BE DONE: CODE resetButton event listener.`

and replace it with the following line of code:

```javascript
resetButton.addEventListener(‘click’, depopulateResultBox);
```

---

This event listener also listens for a click event, this time on our **Reset** button, and calls the `depopulateResultBox()` callback function to reset our page to its beginning state.

To test this out, refresh your browser. Now click the **Validate Zip Codes** button. Once you see that the resultBox has been populated with the zip code matches, click on the **Reset** button.

If all goes according to plan, your screen should reset to its initial state with the message **NO MATCH** displayed where the scrolling list of zip code matches were.

---

## _Conclusion_<a id="conclusion"></a>

**_CONGRATULATIONS!_** You have completed the demo zip code validation Single Page Application (SPA).

**_If your code is not working and you are not sure why_**, _you can download my completed code and compare yours with it to find any errors._

You can also view the live application here on [codepen.io](https://codepen.io/RHieger/full/yLvLJPO).

---

## Next Steps<a id="next"></a>

Now that you have a functional demo web app that returns valid zip codes from a test string, **_where might you go from here?_**

Play around with the finished code you have. Here are a couple suggestions:

1. **Experiment with further de-coupling of helper functions from the data upon which they operate**, as in my example of the `createParagraphs()` function.

2. **Think about how you might make this a truly interactive application** in which a user would simply input a test string and click on the **Validate Zip Codes** button to get the result(s).

Finally, feel free to fork [my repository(https://github.com/RHieger/regex-zip-code-tutorial) and create your own version.

**_Happy coding!_**

---

### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;References<a id="references"></a>

Coyier, Chris. _“The Current State of Styling Scrollbars in CSS (2022<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Update): CSS-Tricks.”_ CSS Tricks, 21 Feb. 2022,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://css-tricks.com/the-current-state-of-styling-scrollbars-in-css/#aa-using-custom-properties-for-styling-scrollbars-in-css">https://css-tricks.com/the-current-state-of-styling-scrollbars-in-css/#aa-using-custom-properties-for-styling-scrollbars-in-css</a>.