JSFiddle - React, Tailwind, and code Playground

by fullyslick

HTML

<!doctype html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Image Loader</title>
  </head>

  <body>
    <div class="gallery">
      <img src="https://farm2.staticflickr.com/1580/25180703901_8d151b1260_b.jpg" alt="Image 1" />
      <img src="https://farm2.staticflickr.com/1569/25155568712_d2b27e77ef_b.jpg" alt="Image 2" />
      <img src="https://farm2.staticflickr.com/1627/25247562596_a50669cfcf_b.jpg" alt="Image 3" />
      <img src="https://farm2.staticflickr.com/1477/24646709583_2b92bf54fc_b.jpg" alt="Image 4" />
      <img src="https://farm2.staticflickr.com/1487/25150013172_e441eaaec5_b.jpg" alt="Image 5" />
      <img src="https://farm2.staticflickr.com/1492/25177356661_55e3566d3c_b.jpg" alt="Image 6" />
      <img src="https://wrong.url" alt="Image 7" />
      <img src="https://farm2.staticflickr.com/1590/25271889895_eeaf184aac_b.jpg" alt="Image 7" />
      <img src="https://farm2.staticflickr.com/1658/24975801290_003c57971c_b.jpg" alt="Image 8" />
      <img src="https://farm2.staticflickr.com/1573/25247680076_78043a280f_b.jpg" alt="Image 9" />
      <img src="https://farm2.staticflickr.com/1631/24905972199_a40bdb940c_b.jpg" alt="Image 10" />
      <img src="https://farm2.staticflickr.com/1600/24904620579_cbffb8ed99_b.jpg" alt="Image 11" />
      <img src="https://farm2.staticflickr.com/1555/25177772161_c173a390c0_b.jpg" alt="Image 12" />
    </div>
    <div id="loader" class="loader">
      <div class="loader-progress">
        <div id="loaderProgressBar" class="loader-progress-bar"></div>
        <span id="loaderPercent" class="loader-percent">0%</span>
      </div>
    </div>
    <script>
      Loader.init();
    </script>
  </body>

</html>

CSS

.gallery img {
    height: 150px;
    display: inline-block;
    margin: 2px;
    vertical-align: top;
}
.gallery div{
    display: inline-block;
    width: 150px;
    height: 150px;
    background: grey;
}
.loader {
    display: flex;
    align-items: center;
    justify-content: center;
}
.loader.loaded {
    opacity: 0;
    transition: all .3s linear;
}
.loader {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: rgba(255, 255, 255, .9);
}
.loader-progress {
    width: 80%;
    height: 50px;
    margin: auto;
    background: #f1f1f1;
    position: relative;
}
.loader-progress-bar {
    height: 100%;
    width: 0;
    background: #c7efb3;
    transition: all .3s linear;
}
.loader-percent {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    text-align: center;
    font: 20px/50px sans-serif;
}

JavaScript

// Task url: https://confluence.ontrq.com/display/KB/Easy+level+-+native+JS/#Easylevel-nativeJS-#2:Imageloader

    var Loader = (function() {
        'use strict';

        return {
            init: function() {
                // get elements
                this.loader = document.getElementById('loader');
                this.progressBar = document.getElementById('loaderProgressBar');
                this.loaderPercent = document.getElementById('loaderPercent');
                this.images = document.getElementsByTagName('img');
                // additional properties
                this.progress = 0;
                this.incrementStep = 100 / this.images.length;
                this.greyPlaceholder = document.createElement('div');
                this.gallery = document.querySelector('.gallery');

                this.events();
            },

            events: function() {
                var self = this;

                var loadImage = function() {
                        return self.loadImage();
                    },
                    images = this.images;

                for (var i = 0; i < images.length; i++) {
                    var image = this.images[i];
                    image.addEventListener('load', loadImage);
                    image.addEventListener('error', function (){

                        self.gallery.replaceChild(self.greyPlaceholder, this);

                        loadImage();
                    });
                }
            },
            // call this function on image load or error event
            loadImage: function() {

                this.progress += this.incrementStep;

                this.increaseProgressBar();
            },
            increaseProgressBar: function() {

                var percentageLoad = Math.round(this.progress) + '%';
                // increase this.progress bar percentage and color filling
                this.loaderPercent.innerText = percentageLoad;
               ...