Regular Expressions—a Rite of Passage: Completing the Application
Created with Generative AI

Regular Expressions—a Rite of Passage: Completing the Application

Part 3: Building from Infrastructure to Completed Application

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.

We left off at Step 6 of Part 2 in 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 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() Callback Function

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:

const populateResultBox = () => {
  
  resultBox.classList.remove('default-results');
  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 results paragraph to resultBox.
  appendResults{paragraphs, resultBox);

};        

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 this tutorial. To fully understand these three lines, we will need to take a look at some code snippets from our HTML and CSS.

Figure 1 below shows the HTML element to which resultBox refers:

Fig. 1 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 Figure 1 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 Figure 2 below:

Fig. 2 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 take a 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 Figure 1.

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 the 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.

Now 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 resultBox.

Figure 3 below shows the code for CSS class .custom-scrollbar:

Fig. 3 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.

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 resotre the default message and styling associated therewith.


The depopulateResultBox() Callback Function

Search in the starter code for the line that reads

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

and replace it with the lines of code below:

const depopulateResultBox = () => {
  while (resultBox.firstChild) {
    resultBox.removeChild(resultBox.firstChild);
  }
  resultBox.classList.remove('custom-scrollbar');
  resultBox.classList.add('default-result');
  resultBox.appendChild(placeholder);
};        

Listing 2. The dePopulateResultBox() Callback Function


We met every method seen in this function when we coded populateResultBox() 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 complete 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');        

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.

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 can chain the addEventListener() method to it. This method take two arguments, as you can 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 listen 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 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 4:

Fig. 4 resultBox with Scrollbar and Populated with Valid Zip Codes

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 resetButtomn eent listener.        

and replace it with the following line of code:

resetButton.addEventListener('click', depopulateResultBox);        

This event listener also listens for a click event, but 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 in resultBox.


Conclusion

CONGRATULATIONS! You have complete 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 few 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 the Validate Zip Codes button to get the result(s).

Finally, feel free to fork my repository and create your own version.

Happy coding!


Works Cited

Coyier, Chris. "The Current State of Styling Schollbars in CSS (2022 Update): CSS Tricks, 21 Feb. 2022, https://css-tricks.com/the-current-state-of-styling-scrollbars-incss/#aa-using-custom-properties-for-styling-scrollbars-in-css.


要查看或添加评论,请登录

Robert Hieger的更多文章

社区洞察

其他会员也浏览了