1

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

Kuzma
  • 679
  • 1
  • 12
  • 36

1 Answers1

1

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>
Anton
  • 8,058
  • 1
  • 9
  • 27
  • 1
    Thank you very much! I will try to implement it on a Grav rewriting the layout (it's a bit complicated). Is the `form oninput` mandatory? There is no way to omit it and solely use the `hidden` input field? – Kuzma Dec 13 '22 at 19:59
  • 1
    @Kuzma This is my example. Of course you can wrap a div instead of form tag, remove the second input and update the value in output tag with javascript. You decide what is convenient for you. ^_^ – Anton Dec 13 '22 at 20:13
  • 1
    Thank you so much! I will try to make it work in my specific layout :) – Kuzma Dec 13 '22 at 20:14