🛠️ Datepicker: Building the datepicker with JavaScript

Hey ,

I'm thrilled to help you learn JavaScript. Unfortunately, you've landed on a page where you cannot access with your current purchase.

Please upgrade (use this link) access this content.

I'm super eager to help you learn more!

🛠️ Datepicker: Building the datepicker with JavaScript

The Datepicker can’t work without JavaScript. We need to use JavaScript to make the date grid for the Datepicker. Since JavaScript is mandatory, it makes sense to make the entire Datepicker with JavaScript.

(Please comment all the JavaScript code from the previous lesson before moving on. You’ll have to make quite a lot of edits).

Creating the Datepicker

Let’s create a function called createDatepicker to start.

const createDatepicker = _ => {
  const datepicker = document.createElement('div')
  datepicker.classList.add('datepicker')
}

createDatepicker needs a date. We can pass this date into the function.

const createDatepicker = date => {
  // ...
}

We know the Datepicker has the following HTML Structure:

<div class="datepicker">
  <div class="datepicker__buttons"> ... </div>
  <div class="datepicker__calendar"> ...</div>
</div>

We can build the structure like this:

const createDatepicker = date => {
  datepicker.innerHTML = `
    <div class="datepicker__buttons"> <!--- ... ---> </div>
    <div class="datepicker__calendar"> <!-- ... --> </div>
  `
}

It helps to separate the .datepicker__buttons and .datepicker__calendar into two separate variables because they’re both quite big.

const createDatepicker = date => {
  const previousNextMonthButtons = `
    <div class="datepicker__buttons"> <!--- ... ---> </div>
  `

  const calendar = `
    <div class="datepicker__calendar"> <!-- ... --> </div>
  `

  datepicker.innerHTML = `
    ${previousNextMonthButtons}
    ${calendar}
  `
}

The buttons

It’s straightforward to create the buttons. We can copy-paste them from the HTML.

const createDatepicker = _ => {
  // ...

  const previousNextMonthButtons = `
    <div class="datepicker__buttons">
      <button class="datepicker__previous">
        <svg viewBox="0 0 20 20">
          <path fill="currentColor" d="M7.05 9.293L6.343 10 12 15.657l1.414-1.414L9.172 10l4.242-4.243L12 4.343z" /></svg>
        </svg>
      </button>

      <button class="datepicker__next">
        <svg viewBox="0 0 20 20">
          <path fill="currentColor" d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z" />
        </svg>
      </button>
    </div>
  `
}

Building the calendar

The calendar contains three parts:

  1. The month/year indicator
  2. The weekday/weekend indicator
  3. The date grid

It looks like this:

const calendar = `
  <div class="datepicker__calendar">
    <div class="datepicker__year-month"> <!-- ... --> </div>
    <div class="datepicker__day-of-week"> <!-- ... --> </div>
    <div class="datepicker__date-grid"> <!-- ... --> </div>
  </div>
`

The day-of-week portion is straightforward. We can copy-paste the code we had from the HTML.

const calendar = `
  <div class="datepicker__calendar">
    <!-- ... -->
    <div class="datepicker__day-of-week">
      <div>Su</div>
      <div>Mo</div>
      <div>Tu</div>
      <div>We</div>
      <div>Th</div>
      <div>Fr</div>
      <div>Sa</div>
    </div>
    <!-- ... -->
  </div>
`

The month/year indicator

We have to create a <time> element for the year-month indicator. You already learned how to do this last lesson.

const createDatepicker = date => {
  const year = date.getFullYear()
  const month = date.getMonth()
  const monthName = monthsInAYear[month]
  const datetimeMonth = (month + 1).toString().padStart(2, '0')

  // ...
  const calendar = `
    <div class="datepicker__calendar">
      <div class="datepicker__year-month">
        <time datetime="${year}-${datetimeMonth}">${monthName} ${year}</time>
      <!-- ... -->
      <!-- ... -->
    </div>
  `

  // ...
}

The date grid

We want to create the date grid in the calendar string. The easiest way is to use a function like createDateGrid.

const calendar = `
  <div class="datepicker__calendar">
    <!-- ... -->
    <!-- ... -->
    <div class="datepicker__date-grid">
      ${createDateGridHTML(date)}
    </div>
  </div>
`

createDateGrid should take in a date so it knows the dates to create. It should return a HTML string so we can use it to create the calendar string.

const createDateGridHTML = date => {
  // ...
  return 'HTML string that contains all date buttons'
}

You learned how to create the date grid from the previous lesson. Here’s the code we wrote:

// Code from previous lesson
const year = date.getFullYear()
const month = date.getMonth()
const firstDayOfMonth = new Date(date.setDate(1)).getDay()
const lastDayInMonth = new Date(year, month + 1, 0)
const daysInMonth = lastDayInMonth.getDate()
const datetimeMonth = (month + 1).toString().padStart(2, '0')

for (let day = 1; day <= daysInMonth; day++) {
  const button = document.createElement('button')
  if (day === 1) button.style.setProperty('--firstDayOfMonth', firstDayOfMonth + 1)

  const datetimeDay = day.toString().padStart(2, '0')
  button.innerHTML = `
    <time datetime="${year}-${datetimeMonth}-${datetimeDay}">${day}</time>
  `

  dategrid.appendChild(button)
}

There are two problems with the previous code:

  1. We don’t have a dategrid element this time.
  2. We can’t use appendChild without a dategrid element.

To fix this, we can create a dategrid element inside createDateGrid.

const createDateGridHTML = date => {
  const dategrid = document.createElement('div')
  const year = date.getFullYear()
  const month = date.getMonth()
  const firstDayOfMonth = new Date(date.setDate(1)).getDay()
  const lastDayInMonth = new Date(year, month + 1, 0)
  const daysInMonth = lastDayInMonth.getDate()

  for (let day = 1; day <= daysInMonth; day++) {
    const button = document.createElement('button')
    if (day === 1) button.style.setProperty('--firstDayOfMonth', firstDayOfMonth + 1)

    const datetimeDay = day.toString().padStart(2, '0')
    button.innerHTML = `
      <time datetime="${year}-${datetimeMonth}-${datetimeDay}">${day}</time>
    `

    dategrid.appendChild(button)
  }
  // ...
}

Since we need the HTML string, we can return dategrid's innerHTML.

const createDateGridHTML = date => {
  // ...
  return dategrid.innerHTML
}

Inserting the Datepicker to the DOM

We can create the Datepicker with createDatepicker(date). But we need to let users insert the Datepicker into the DOM. To let users insert the Datepicker into the DOM, we need to return the datepicker.

const createDatepicker = date => {
  // ...
  return datepicker
}

We can now add the Datepicker anywhere we want. For now, let’s add the Datepicker in the <form> element.

// Create datepicker
const date = new Date(2019, 1, 13)

// Add the datepicker into the DOM
const form = document.querySelector('form')
form.appendChild(createDatepicker(date))

That’s it!