JSFiddle - React, Tailwind, and code Playground

by Martin Renvoize

HTML

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="exercise">
  <!-- 1) Start the Effect with the Button. The Effect should alternate the "highlight" or "shrink" class on each new setInterval tick (attach respective class to the div with id "effect" below) -->
  <div>
    <button @click="startEffect">Start Effect</button>
    <div id="effect" :class="effectStyle"></div>
  </div>

  <!-- 2) Create a couple of CSS classes and attach them via the array syntax -->
  <div :class="[{loud: bool1}, colourEffect]">I got no class :(</div>

  <!-- 3) Let the user enter a class (create some example classes) and attach it -->
  <div>
    <input type="text" v-model="myClass">
    <div :class="myClass">Class me?</div>
  </div>

  <!-- 4) Let the user enter a class and enter true/ false for another class (create some example classes) and attach the classes -->
  <div>
    <input type="text" v-model="pickClass">
    <input type="text" v-model="bool2">
    <div id="rectangle" :class="[pickClass, {highlight: bool2}]"></div>
  </div>

  <!-- 5) Repeat 3) but now with values for styles (instead of class names). Attach the respective styles.  -->
  <div>
    <input type="text" v-model="myStyle">
    <div :style="myStyle"></div>
  </div>

  <!-- 6) Create a simple progress bar with setInterval and style bindings. Start it by hitting the below button. -->
  <div>
    <button v-on:click="startProgress">Start Progress</button>
    <div v-bind:style="[baseStyle, progress]"></div>
  </div>
</div>

CSS

#effect {
  width: 100px;
  height: 100px;
  border: 1px solid black;
}

.highlight {
  background-color: red;
  width: 200px !important;
}

.shrink {
  background-color: gray;
  width: 50px !important;
}

.loud {
  text-transform: uppercase;
  font-weight: bold;
}

.colourful {
  color: green;
}

#rectangle {
  width: 50px;
  height: 50px;
  border: 2px solid black;
}

JavaScript

new Vue({
  el: '#exercise',
  data: {
    bool1: true,
    bool2: false,
    effectStyle: {
      highlight: this.bool1,
      shrink: !this.bool1
    },
    colourEffect: 'colourful',
    myClass: 'loud',
    pickClass: 'loud',
    myStyle: '',
    baseStyle: {
      width: '2px',
      height: '25px',
      backgroundColor: 'red'
    },
    progress: ''
  },
  watch: {
    bool1: function() {
      this.effectStyle = {
        highlight: this.bool1,
        shrink: !this.bool1
      }
    },
  },
  methods: {
    startEffect: function() {
      var vm = this;

      /* Using setInterval */
      /*
      setInterval(function() {
        vm.bool1 = !vm.bool1;
      }, 2000)
      */

      /* Using setTimeout and limiting to 10 iterations */
      var count = 0;
      var toggle = function() {
        console.log("Inside toggle");
        vm.bool1 = !vm.bool1;
        if (count <= 10) {
          count++;
          console.log("Calling setTimeout " + count)
          setTimeout(toggle, 1000)
        }
      };
      toggle();
    },
    startProgress: function() {
      var vm = this;
      var count = 2;
      var interval = setInterval(function() {
        count = count + 4;
        vm.progress = {
          width: count + 'px',
          backgroundColor: (count <= 100) ? 'red' : (count <= 150) ? 'orange' : 'green'
        };
        if (count >= 200) {
          clearInterval(interval)
        }
      }, 500)
    }
  }
});