A JavaScript Project

Project Introduction

At this point we have learned quite a lot about JavaScript. Hopefully you have read the previous chapters as well as worked through the available practice exercises.

Now it is time to put together everything we have learned into a larger project. This let's us see how everything we have learned fits together in a bigger sense. We will also learn some new techniques for working with JavaScript along the way.

The project we will build is a JavaScript based User Interface library. The library will contain an assortment of static components like headers and grids as well as a number of dynamic components like modals and lightboxes.

Since the project contains an number of smaller parts it will let us reinforce a number of the essential skills so we get more comfortable with them.

This will also serve as a great beginner portfolio piece since you can easily theme the library with CSS and add extra components for a custom library of your own. Employers will be impressed you built a UI library as one of your first JavaScript projects :)

What We Will Build and How

Our User Interface library will consist of two types of UI Components: Static UI Components and Dynamic UI Components.

Static UI Components

Our static components will usually consist of a function that returns a string of markup.

Here is an example of what the Header Component looks like:

function header(text, tag = `h2`) {
return `<${tag}>${text}</${tag}>`;
// Returns <h2>Header</h2>

You can see that our header() component takes some text and an optional tag as a parameter and then returns header markup with the text and tag.

We can then take our header component and load it to the page like this:

// Get the div where we want to load our header
const container = document.querySelector("#app");
// Load our header
container.insertAdjacentHTML(`beforeend`, header(`Header`));

We will build some helpful functions to simplify this process, but in general, that is how our static component will work:

  1. We write a function that returns markup

  2. We call that function and insert the markup to the page

You may be asking, why would be do this when we can just add HTML to the page? Most modern JavaScript applications need to be able to wipe the page and add or update content based on user interactions. Although it may seem like more work as first, ultimately it is faster to have functions with the markup you need so you can easily create and build pages on the fly as needed.

Here is a list of some of the static components we will:

  1. Link

  2. Header

  3. Generic Tag

  4. Hero

  5. Feature

  6. Column Row

  7. Input Field

  8. Button

We are purposefully not creating every component possible. It would take us too long to do so, and the idea is that we get you started and then you add some more components of your own.

Dynamic Components

The second type of component we build, dynamic components, will require similar functions as the static components that get the necessary markup.

Here is the a function for creating the markup for a dynamic accordian:

// Return accordion markup based on data provided
function accordion(data) {
let markup = `<div class="accordion">`;
data.map(section => {
markup += `
<div class="content">
markup += `</div>`;
return markup;
// Add the accordion and pass it data (not visible here)
const container = document.querySelector(`#app`)
container.insertAdjacentHTML(`beforeend`, accordion( data ))

Now we have accordion markup on the page.

Next we have to "initialize" it by setting the first accordion item to "active" and adding event listeners to the accordion titles.

// Sets up the accordion JavaScript
export function initAccordion() {
// Get the accordion we added
const accordion = document.querySelector(`.accordion`);
// Add an "active" class
// Setup event listeners on accordion titles
const sections = Array.from(
accordion.querySelectorAll(".accordion section")
sections.map(section => {
const title = section.querySelector(`h3`);
title.addEventListener("click", handleAccordion.bind(section));
// Call initAccordion once markup is loaded

This two step process for dynamic components will involve similar steps to what we see above:

  1. First we create and add our markup

  2. Then we initialize and add event listeners as needed

The initialization code we write for our components should be fairly reusable. So, if you have a project in the future that requires functionality like what we build here, you should be able to copy and paste our code with very little modifications.

Now, let's get our files setup to start building.

Setting Up The Project