Progress Bar

An interview question that tests a good mix of HTML, CSS3, JavaScript. Note there are two routes people can go down -- one is to use the animate() function in jQuery but the route I opted for uses CSS3 transitions/animations. If people opt for the animate() route, be sure to let them know about this route as that will lead into creating unique id's or using promises to fill the next progress bars. This can still be elegant and you should be open to accepting that as a possible solution, but it makes a lot more sense to keep view related code in CSS and HTML if possible.

HTML

<!-- Create a progress bar that's 50% full -->
<!-- Create a button that adds multiple progress bars to the page -->
<!-- Make the progress bar advance from 0-100% full over the course of 3 seconds -->

<!-- Allow any number of progress bars, but only allow 1 progress bars to run at any one time -->

<!-- Verify that after adding a bunch of progress bars and having them all filled, new ones added will still fill accordingly -->

<button class="progress-btn">Create Progress Bar</button>
<button class="clear-btn">Clear</button>
<div class="progress-bar-area"></div>

CSS

.progress-container {
    width: 500px;
    border: 1px solid black;
    margin-top: 10px;
}

.progress {
    width: 0%;
    background: red;
    height: 50px;
}

.js-fill {
    width: 100%;  
    
    -webkit-transition: width 3s ease-in-out 0s; 
    transition: width 3s ease-in-out 0s;
}

button {
  margin-top: 10px;   
}

JavaScript

$(document).ready(function(e) {
     var prevProgress = null;
     var transitionEndedTimer;
    
    $('.progress-btn').on('click', function(e) {
       var progressBar = createProgressBar();
       // clear setTimeout in case all animations have filled already
       // so we don't unnecessarily clear prevProgress
       	clearTimeout(transitionEndedTimer);
        // if there is no previous progress bar
        if (!prevProgress) {
            prevProgress = progressBar;
            // wait a bit before adding the class
            setTimeout(function() {
               progressBar.find('.progress').addClass('js-fill');
            }, 100);    
           
        } else {
            // if we are the previous progress bar we want to add
            // a transition end event listener
            prevProgress.on('transitionend', function(e) {
               progressBar.find('.progress').addClass('js-fill');
               // after time has ended, set prevProgress to null
               transitionEndedTimer = setTimeout(function() {
               	prevProgress = null;
               }, 7100);
            }); 
            
        }

        $('.progress-bar-area').append(progressBar);
        
        prevProgress = progressBar;
    });
    
    function createProgressBar() {
        return $('<div class="progress-container"><div class="progress"></div></div>');
    }
    
    $('.clear-btn').on('click', function(e) {
      clearTimeout(transitionEndedTimer);
    	$('.progress-bar-area').empty();
      prevProgress = null;
    })
});