This article was first published on JavaScript in Plain English.
Part 3: Building from Infrastructure to Completed Application
Photo by ThisisEngineering RAEng on Unsplash
Table of Contents
WELCOME BACK!
Completing the Application
Step 7. Coding the Callback Functions
The populateResultBox() Function
The depopulateResultBox() Function
Step 8. Coding the Event Listeners
Add an Event Listener to the Validate Zip Codes Button
Add an Event Listener to the Reset Button
Conclusion
Next Steps
References
WELCOME BACK!
Our moment has arrived. We are now ready to finish our application started in Regular Expressions—a Rite of Passage: From Theory to Practice.
Completing the Application
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:
1. We need to code the callback functions that will be used by the two
event listeners mentioned in Part 2.
2. We need to write the event listeners that will call the callback functions
in order to carry out their work.
Step 7. Coding the Callback Functions
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
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.
The populateResultBox()
Function
populateResultBox()
FunctionSearch 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:
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);
};
Code Listing 1. The populateResultBox() Callback Function
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:
<div id="results"
class="results-data-dimensions default-result">
<p class="default-message" id="message">no match</p>
<!-- Dynamic content lives here. -->
</div>
Code Listing 2. HTML Elements Captured by resultBox
You might recall from Part 2 a code listing that started with the element<div id= “getResults”>
, which contains the entire widget with the two buttons and the <p>
element with the NO MATCH message shown in
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:
.default-result {
background-color: #808080;
}
Code Listing 3. CSS Class Controlling resultBox Background Color
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:
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—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:
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:
resultBox.classList.add(‘custom-scrollbar’);
Here, we are doing something quite different. Here, we add a CSS class
to reasultBox
. Code Listing 4 below shows the code for CSS class .custom-scrollbar
:
.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);
}
Code Listing 4. CSS Class Controlling Scrollbar Styling for resultBox
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.
The depopulateResultBox()
Function
depopulateResultBox()
FunctionNow 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:
const depopulateResultBox = () => {
while (resultBox.firstChild) {
resultBox.removeChild(resultBox.firstChild);
}
resultBox.classList.remove(‘custom-scrollbar’);
resultBox.classList.add(‘default-result’);
resultBox.appendChild(placeholder);
};
Code Listing 5. The depopulateResultBox() Function
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:
1. We start with a while loop that takes a single argument—
resultBox.firstChild
. We already know that resultBox is a
DOM node. As such it exposes properties and methods. The firstChild
property captures the first child of resultBox,
which would be the first paragraph in resultBox.
2. The argument in this while loop is a Boolean that evaluates to
true if there is a firstChild
paragraph node in resultBox. Each
time through the loop,
resultBox.removeChild(resultBox.firstChild);
is executed, it removes one paragraph. On each iteration of the
loop the next paragraph in line becomes the firstChild. Once
there is no firstChild
left, the loop terminates because no
paragraphs remain.
3. Once all paragraphs have been removed the three remaining
lines of code outside of the while loop remove the
.custom-scrollbar
class, thus restoring the gray background,
and finally uses the appendChild() method to restore the
NO MATCH message.
We have now completed our callback functions and are ready to proceed
to the last step—coding the event listeners for the Validate Zip Codes
and Reset buttons.
Step 8. Coding the Event Listeners
Now we approach the ultimate step in completing our application—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:
const resultButton = document.getElementById(‘validate’);
const resetButton = document.getElementById(‘reset’);
Code Listing 6. Nodes in Need of Event Listeners
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<button class=“controlButton” id=“validate”>
element in our index.html file.
resetButton
is the DOM node that captures the<button class=“controlButton” id=“reset”>
element.
With this new information we can begin.
Add an Event Listener to the Validate Zip Codes Button
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:
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
Add an Event Listener to the Reset Button
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:
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
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.
Next Steps
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:
Experiment with further de-coupling of helper functions from the data upon which they operate, as in my example of the
createParagraphs()
function.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!
References
Coyier, Chris. “The Current State of Styling Scrollbars in CSS (2022
Update): CSS-Tricks.” CSS Tricks, 21 Feb. 2022,
https://css-tricks.com/the-current-state-of-styling-scrollbars-in-css/#aa-using-custom-properties-for-styling-scrollbars-in-css.
Top comments (0)