Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Html Range slider with Javascript

So I have recently been playing around with styling the html range slider.

I came across a pen on CodePen that has some really great designs.

This is the source code from one.

HTML:

<input type="range" data-idx="1">

CSS:

html {
  background: #393939;
}

input[type='range'] {
  display: block;
  margin: 2.5em auto;
  border: solid .5em transparent;
  padding: 0;
  width: 15.5em;
  height: 1em;
  border-radius: .25em;
  background: transparent;
  font-size: 1em;
  cursor: pointer;
}
input[type='range'], input[type='range']::-webkit-slider-runnable-track, input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
}
.js input[type='range']::-webkit-slider-runnable-track {
  background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-moz-range-track {
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
}
.js input[type='range']::-moz-range-track {
  background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-ms-track {
  border: none;
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
  color: transparent;
}
input[type='range']::-ms-fill-lower {
  border-radius: 0.25em;
  background: #e44e4f;
}
input[type='range']:nth-of-type(1)::-webkit-slider-runnable-track {
  background-size: 50% 100%;
}
input[type='range']:nth-of-type(1)::-moz-range-track {
  background-size: 50% 100%;
}
input[type='range']:nth-of-type(1)::-webkit-slider-thumb {
  margin-top: -0.125em;
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']:nth-of-type(1)::-moz-range-thumb {
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']:nth-of-type(1)::-ms-thumb {
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']:nth-of-type(1)::-ms-tooltip {
  display: none;
}
input[type='range']:focus {
  outline: none;
  box-shadow: 0 0 0.25em #e44e4f;
}

Javascript:

var s = document.createElement('style'), 
    r = document.querySelectorAll('input[type=range]'), 
    prefs = ['webkit-slider-runnable', 'moz-range'], 
    styles = [], 
    l = prefs.length
    n = r.length;

document.body.appendChild(s);

var getTrackStyleStr = function(el) {
  var str = '', 
      j = el.dataset.idx, 
      min = el.min || 0, 
      perc = (el.max) ? ~~(100*(el.value - min)/(el.max - min)) : el.value, 
      val = perc + '% 100%';

  for(var i = 0; i < l; i++) {
    str += '.js input[type=range]:nth-of-type(' + j + ')::-' + prefs[i] + '-track{background-size:' + val + '}';
  }

  return str;
};

var getTipStyleStr = function(el) {
  var str = '.js input[type=range]:nth-of-type(' + el.dataset.idx + ') /deep/ #thumb:after{content:"' + el.value + '%"}';

  return str;
};

for(var i = 0; i < n; i++) {
  styles.push('');

  r[i].addEventListener('input', function() {    
    styles[this.dataset.idx] = getTrackStyleStr(this);
    if(this.classList.contains('tip')) {
      styles[this.dataset.idx] += getTipStyleStr(this);
    }

    s.textContent = styles.join('');
  }, false);
}

This works great for one range element but if I try adding more range elements on the same page, and change the data attribute to data-idx="2" it will not work, the first range will control them all.

How can I adjust the code to make each range work independently?

Here is a JSFiddle of the code I'm using, for some reason the javascript isn't working on there at all, but it's works fine on codepen? Hmm...

Here is the original Codepen

like image 424
Jordan Avatar asked Jun 01 '15 17:06

Jordan


People also ask

How do you set a range value in html?

The <input type="range"> defines a control for entering a number whose exact value is not important (like a slider control). Default range is 0 to 100. However, you can set restrictions on what numbers are accepted with the attributes below. Tip: Always add the <label> tag for best accessibility practices!

How do I create a vertical range slider in html?

For Chrome, use -webkit-appearance: slider-vertical . For IE, use writing-mode: bt-lr . For Firefox, add an orient="vertical" attribute to the html.


1 Answers

SOLUTION

var r = document.querySelectorAll('input[type=range]'), 
    prefs = ['webkit-slider-runnable', 'moz-range'], 
    styles = [], 
    l = prefs.length,
    n = r.length;

var getTrackStyleStr = function(el, j) {
  var str = '', 
      min = el.min || 0, 
      perc = (el.max) ? ~~(100*(el.value - min)/(el.max - min)) : el.value, 
      val = perc + '% 100%';

  el.previousElementSibling.textContent = el.value;
  
  for(var i = 0; i < l; i++) {
    str += "input[type=range][data-rangeId='" + j + "']::-" + prefs[i] + '-track{background-size:' + val + '} ';
  }
  return str;
};

var setDragStyleStr = function(evt) {
  var trackStyle = getTrackStyleStr(evt.target, this); 
  styles[this].textContent = trackStyle;
};

for(var i = 0; i < n; i++) {
  var s = document.createElement('style');
  document.body.appendChild(s);
  styles.push(s);
  r[i].setAttribute('data-rangeId', i);
  r[i].addEventListener('input', setDragStyleStr.bind(i));
}
html {
  background: #393939;
}

div {
  margin: 2.5em auto;
}

input[type='range'] {
  display: block;
  margin: 0.2em auto;
  border: solid .5em transparent;
  padding: 0;
  width: 15.5em;
  height: 1em;
  border-radius: .25em;
  background: transparent;
  font-size: 1em;
  cursor: pointer;
}
input[type='range'], 
input[type='range']::-webkit-slider-runnable-track, 
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
}
input[type='range']::-webkit-slider-runnable-track {
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
}
input[type='range']::-webkit-slider-runnable-track {
  background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-moz-range-track {
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
}
input[type='range']::-moz-range-track {
  background: linear-gradient(#e44e4f, #e44e4f) no-repeat #fff;
}
input[type='range']::-ms-track {
  border: none;
  width: 15.5em;
  height: 0.5em;
  border-radius: 0.25em;
  background: #fff;
  color: transparent;
}
input[type='range']::-ms-fill-lower {
  border-radius: 0.25em;
  background: #e44e4f;
}
input[type='range']::-webkit-slider-runnable-track {
  background-size: 0% 100%;
}
input[type='range']::-moz-range-track {
  background-size: 0% 100%;
}
input[type='range']::-webkit-slider-thumb {
  margin-top: -0.125em;
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']::-moz-range-thumb {
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']::-ms-thumb {
  border: none;
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  box-shadow: 0 0 0.125em #333;
  background: #fff;
}
input[type='range']::-ms-tooltip {
  display: none;
}
input[type='range']:focus {
  outline: none;
  box-shadow: 0 0 0.25em #e44e4f;
}

output[for='range'] {
  font-family: "Lucida Grande","Lucida Sans Unicode", Tahoma, Sans-Serif;
  font-size: 13px;
  color: white;
  display: block;
  text-align: center;
}
<div>
  <output for="range">0</output>
  <input type="range" value="0">
</div>
<div>
  <output for="range">0</output>
  <input type="range" value="0">
</div>
<div>
  <output for="range">0</output>
  <input type="range" value="0">
</div>
like image 67
rafaelcastrocouto Avatar answered Oct 15 '22 14:10

rafaelcastrocouto