Kuzma
Kuzma

Reputation: 711

html5 range slider: the output label doesn't reflect chosen value with custom JavaScript code

I've used a code from this answer to style HTML5 input in my GRAV CMS website.

The rendered part of HTML markup:

<div class="form-data" data-grav-field="range" data-grav-disabled="" data-grav-default="40">
  <div class="form-input-wrapper ">
    <input name="data[space]" value="40" type="range" style="display: inline-block;vertical-align: middle;" oninput="space_output.value = space.value" min="40" max="350" step="10" class="form-input " id="space" required="required">
    <output name="data[space]" id="space_output" style="display: inline-block;vertical-align: baseline;padding: 0 0.5em 5px 0.5em;"> 40 </output>
  </div>
</div>

The JS code is taken from the answer above and placed in at the beginning of my custom.js file:

document.getElementById("space").oninput = function() {
  var value = (this.value-this.min)/(this.max-this.min)*100
  this.style.background = 'linear-gradient(to right, #eec170 0%, #eea624 ' + value + '%, #839788 ' + value + '%, #a6d86c 100%)'                           
};

So, this part works without any flaws.

The problem:

With JS code the behaviour of input is incorrect, once the page is loaded background color is not reflecting the ball position of the default position 40, because it's not the center. Once the slider position is changed, the background colors are changed depending on the slider position.

That's the lesser problem, but the major problem is that the <output> field no longer displays the new values. It's has been stuck to 40. How could it be fixed?

enter image description here enter image description here

Upvotes: 1

Views: 77

Answers (1)

Anton
Anton

Reputation: 8538

Try this example. I have added one more (hidden) input for calculate range and wrapped it with a form tag to get the value from the output. I also added styles and refactored the gradient calculation to javascript.

document.addEventListener('DOMContentLoaded', function() {
  const slider = document.getElementById('range');

  // Calculate gradient persent (0% - 100%)
  const calcGradientPersent = value => (100 * value) / 360;

  // Default value when load page
  const initValue = slider.value;
  let persent = calcGradientPersent(initValue);

  // Set default inline style
  slider.style.background = `linear-gradient(to right, #eec170 0%, #eea624 ${persent}%, #839788 ${persent}%, #a6d86c 100%)`;

  // Input Range handler
  slider.addEventListener('input', event => {
    // Get value from input
    const value = event.target.value;
    persent = calcGradientPersent(value);
    // Update inline style
    slider.style.background = `linear-gradient(to right, #eec170 0%, #eea624 ${persent}%, #839788 ${persent}%, #a6d86c 100%)`;
  });
});
*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

input[type='range'] {
  appearance: none;
  border-radius: 1rem;
}

input[type='range']:focus {
  outline: none;
}

input[type='range']::-webkit-slider-runnable-track {
  width: 100%;
  height: 0.4rem;
  cursor: pointer;
  border-radius: 1rem;
  border: 1px solid #eea624;
}

input[type='range']::-webkit-slider-thumb {
  height: 1rem;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 2px solid gray;
  background: #d8d7f3;
  cursor: pointer;
  appearance: none;
  margin-top: -0.35rem;
}
<div class="form-data" data-grav-field="range" data-grav-disabled="" data-grav-default="40">
  <form oninput="result.value=parseInt(range.value)+parseInt(step.value)" class="form-input-wrapper">
    <input name="range" value="40" type="range" style="display: inline-block; vertical-align: middle" min="0" max="350" step="10" class="form-input" id="range" required="required" />
    <input type="number" id="step" value="0" hidden />
    <output name="result" id="space_output" for="range step" style="display: inline-block; vertical-align: baseline; padding: 0 0.5em 5px 0.5em">
          40
     </output>
  </form>
</div>

Upvotes: 1

Related Questions