Make progress bar go in reverse

Viewed 31

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>

0 Answers
Related