Advent of JavaScript, Day 9

Advent of JS Homepage

Challenge #9 an image carousel:

Screenshot of app

With the project files downloaded and codesandbox‘d into a live CodeSandbox, I’m ready to get going!


User Requirements

Again, let’s start with the User Requirements and speculate how I can solve these:

  • toggle left and right through the image thumbnails

Alrighty, this seems simple:

  • currentIndex is the index of the current image to replace .feature
  • Event handlers on .left and .right to decrement and increment, respectively, currentIndex
  • click an image to select it manually

This will set the currentIndex to the index of the clicked image.

Wiring it Up

With Vue, this should all be a cinch!

Id like to use transitions, since a quick Google shows that the out-in may work to make this seamless:

https://vuejs.org/v2/guide/transitions.html#Transition-Modes

However, probably not if I’m replacing elements vs. hidding/showing different ones. I’m going to skip transitions for now…

  1. Adding Vue, as usual:

    <script src="https://unpkg.com/vue@next"></script>

    I find wiring up the markup first helps clarify the most semantic API before I start writing imperative (i.e. JavaScript) code.

  2. Making .feature reactive:

    <div class="feature">
      <img :src="'images/' + currentImage.image" alt="Featured" />
      <div class="caption">{{ currentImage.caption }}</div>
    </div>
  3. Making .thumbnails reactive:

    I wanted to make sure the thumbnails continued to scroll into view as .left and .right were clicked. Vue has a ref attribute that allows you to reference an element from the template, just like React:

    https://v3.vuejs.org/guide/migration/array-refs.html#migration-strategy

    <div class="thumbnails">
      <ul>
        <li
          v-for="(item, index) in content"
          :class="{ selected: index === currentIndex }"
          :ref="setThumbnailRef"
        >
          <a @click.prevent="currentIndex = index" href="#">
            <img
              :src="'images/' + item.image"
              :alt="'Thumbnail of ' + item.caption"
            />
          </a>
        </li>
      </ul>
    </div>
  4. Making .left and .right reactive:

    I modeled this after the window.history.go(delta) API:

    <a @click.prevent="go(-1)" href="#" class="left">
      <img src="./images/chevron.svg" alt="" />
    </a>
    <a @click.prevent="go(+1)" href="#" class="right">
      <img src="./images/chevron.svg" alt="" />
    </a>

Demo

I think I need to try something different than Vue for the next one(s). Vue is making things too easy…