JSFiddle - React, Tailwind, and code Playground
by jstoudt
HTML
<div class="container">
<h1>Operation Progress</h1>
<div class="progress-wrapper">
<progress id="progress-bar" max="100" value="0"></progress>
<span id="percentage" class="percentage"></span>
</div>
<button id="start-progress">Start Progress</button>
<button id="cancel-progress" hidden>Cancel</button>
<div id="message" class="message"></div>
</div>
CSS
html, body {
height: 100%;
color: #333;
background-color: #ccc;
font: 13px/1.25 sans-serif;
margin: 0;
padding: 0;
}
.container {
position: absolute;
top: 20%;
left: 50%;
width: 480px;
height: 75px;
background: #fff;
margin-left: -240px;
border: 1px solid #333;
border-radius: 0.5em;
box-shadow: 3px 3px 6px 2px rgba(0, 0, 0, 0.4);
padding: 1em;
}
h1 {
font-size: 15px;
padding: 0.25em 0;
margin: 0;
}
.message {
margin-top: 0.25em;
font-style: italic;
}
#progress-bar {
-webkit-appearance: none;
appearance: none;
width: 350px;
height: 1.5em;
vertical-align: middle;
}
#progress-bar[value]::-webkit-progress-bar {
position: relative;
background-color: #eee;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3) inset;
border-radius: 2px;
}
#progress-bar[value]::-webkit-progress-value {
background: -webkit-linear-gradient(left, #090 , #1d1);
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3) inset;
border-radius: 2px;
}
#progress-bar:not([value])::-webkit-progress-bar {
position: relative;
background-color: #eee;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3) inset;
}
#progress-bar:not([value])::-webkit-progress-bar::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 10%;
height: 95%;
background: -webkit-radial-gradient(center center, ellipse farthest-corner, #0b0 0%, #1d1 100%);
background: radial-gradient(center center, ellipse farthest-corner, #0b0 0%, #1d1 100%);
border-radius: 2px;
-webkit-animation: indeterminate 3.5s linear infinite;
animation: indeterminate 3.5s linear infinite;
}
@-webkit-keyframes indeterminate {
50% { -webkit-transform: translateX(900%); }
}
@keyframes indeterminate {
50% { transform: translateX(900%); }
}
.progress-wrapper {
display: inline-block;
position: relative;
}
.percentage {
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
text-align: center;
font: bold 13px/1.5em sans-serif;
}
button {
cursor: pointer;
vertical-align: middle;
}
JavaScript
(function() {
var progressBar = document.getElementById('progress-bar'),
startBtn = document.getElementById('start-progress'),
cancelBtn = document.getElementById('cancel-progress'),
message = document.getElementById('message'),
percentage = document.getElementById('percentage'),
timeoutId = null;
function doProgress() {
if (progressBar.value >= progressBar.max) {
cancelBtn.setAttribute('hidden', 'hidden');
startBtn.removeAttribute('hidden');
message.innerHTML = 'The operation has completed successfully.';
return;
}
progressBar.value++;
percentage.innerHTML = progressBar.value + '%';
timeoutId = setTimeout(doProgress, 60);
}
startBtn.addEventListener('click', function() {
this.setAttribute('hidden', 'hidden');
cancelBtn.removeAttribute('hidden');
progressBar.removeAttribute('max');
progressBar.removeAttribute('value');
percentage.innerHTML = '';
message.innerHTML = 'Doing a task for an indeterminate amount of time...';
timeoutId = setTimeout(function() {
progressBar.max = 100;
progressBar.value = 0;
message.innerHTML = 'Doing a task for a determinate amount of time...';
doProgress();
}, 3000);
}, false);
cancelBtn.addEventListener('click', function() {
if (timeoutId) {
clearTimeout(timeoutId);
message.innerHTML = 'Operation has been cancelled by the user.';
progressBar.max = 100;
progressBar.value = 0;
cancelBtn.setAttribute('hidden', 'hidden');
startBtn.removeAttribute('hidden');
}
}, false);
}());