I am having problem, checkpoints for the progress bar are generated through the object called checkpoints. First checkpoint is 35% and second is 45% and for them the label is filling as it should, but in the third checkpoint there is decrease in percentage, third checkpoint is 15%, my question is now how can I recreate that if the next value is smaller than the previous value, to actually return the progress of the progress bar to 15 percent, and then next to 65% etc.
const checkpoints = [{
perc: 35,
label: "35%\n<b>2018</b>"
},
{
perc: 45,
label: "45%\n<b>2019</b>"
},
{
perc: 15,
label: "15%\n<b>2020</b>"
},
{
perc: 65,
label: "65%\n<b>2021</b>"
},
{
perc: 30,
label: "30%\n<b>2022</b>"
},
{
perc: 100,
label: "100%\n<b>2022</b>"
}
];
const step = 1;
const timeInterval = 100;
const playLabel = 'PLAY';
const pauseLabel = 'PAUSE';
//on document ready..
$(document).ready(() => {
//shows checkpoints under the progressbar
for (checkpoint of checkpoints) {
$('#rulers')
.append(`<p class='ruler' style='width:${checkpoint.perc}%;'>${checkpoint.label}</p>`);
}
//attaches click event handler to #playpause button
$('#playpause').on('click', (event) => {
toggleButton($(event.currentTarget))
});
});
function toggleButton(playPauseButton) {
const status = $(playPauseButton).attr('data-status');
//if the button was in pause state (and having the Play label)
if (status == "pausing") {
$(playPauseButton)
//toggles it to status 'playing'
.attr('data-status', 'playing')
//toggles it to "Pause" label
.text(pauseLabel);
//begins incrementing the progressbar
const intervals = checkpoints.map(cp => cp.perc);
setProgressWithCheckpoints(intervals, step, timeInterval);
}
//if the button was in playing state (and having the Pause label)
else if (status == 'playing') {
$(playPauseButton)
//toggles it to status 'pausing'
.attr('data-status', 'pausing')
//toggles it to "Play" label
.text(playLabel);
//if the progressbar is still running to complete its task,
if (isStillRunning() === true) {
//sets the playpause button as disabled so that you can't click it
$(playPauseButton).prop('disabled', true);
}
}
}
//set the progressbar at perc
function setProgress(perc) {
$(".progress .progress-bar")
.css('width', `${perc}%`)
.attr('aria-valuenow', perc)
$(".progress .progress-bar span")
.text(`${perc}%`);
}
//get progressbar %
function getProgress() {
const valueNow = $(".progress .progress-bar")
.attr('aria-valuenow');
return parseInt(valueNow);
}
//return true/false if the progress is still running
function isStillRunning() {
if ($('#playpause').attr('data-stillrunning') == 'yes')
return true;
return false;
}
//sets the state stillrunning to yes
function setStillRunning() {
$('#playpause').attr('data-stillrunning', 'yes');
}
//sets the state stillrunning to no and enables the button (in case it was disabled)
function setNotStillRunning() {
$('#playpause')
.attr('data-stillrunning', 'no')
.prop('disabled', false);
if ($('#playpause').attr('data-status') == 'playing')
toggleButton($('#playpause'));
}
function setProgressWithCheckpoints(intervals, step, ms) {
setStillRunning();
const valueNow = getProgress();
const nextIntervals =
intervals.filter((interval) => interval > valueNow);
const nextInterval =
(nextIntervals.length > 0) ? nextIntervals[0] : null;
const newValue = Math.min(nextInterval, valueNow + step);
setProgress(newValue);
const playpauseStatus = $('#playpause').attr('data-status');
//if progress got to 100% OR
// nextInterval got reached while the play button is in pause state
if (newValue >= 100 || (nextInterval == newValue && playpauseStatus == 'pausing')) {
//ends the calling and set the button as notStillRunning
setNotStillRunning();
}
//else
else
//call again the progress function
setTimeout(() => {
setProgressWithCheckpoints(intervals, step, ms)
}, ms);
}
.progress {
margin: 50px 20px 20px 0;
}
.progress {
display: flex;
width: 100%;
height: 2rem;
overflow: hidden;
border: solid 1px lightgray;
width: 100%;
}
.progress-bar {
color: white;
vertical-align: middle;
font-weight: 600;
padding-top: 6px;
}
.progress-bar span {
padding-left: 10px;
}
#rulers {
position: relative;
height: 3em;
border-bottom: solid 1px lightgray;
}
#rulers .ruler {
position: absolute;
text-align: right;
margin-top: 0;
white-space: pre-line;
border-right: solid 2px darkgray;
padding-right: 4px;
box-sizing: border-box;
}
#playpause {
display: block;
cursor: pointer;
margin-top: 20px;
padding: 2px 10px;
font-size: 18px;
}
#playpause:disabled {
cursor: not-allowed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;background: green;">
<span></span>
</div>
</div>
<div id="rulers">
</div>
<button id="playpause" data-status="pausing">PLAY</button>