So I found this range slider and I am attempting to make it dynamic. Currently, there is some hardcoded content in the JS directly adressing specific HTML elements and I would like to have 10 of those sliders on my HTML site all working independently. I am using the following Code: https://codepen.io/mukealicious/pen/jWoeZY (also below)
const $element = $('input[type="range"]');
const $tooltip = $('#range-tooltip');
const sliderStates = [
{name: "low", tooltip: "Good.", range: _.range(80, 100) },
{name: "med", tooltip: "Okay.", range: _.range(101, 149)},
{name: "high", tooltip: "Bad.", range: [150] },
];
var currentState;
var $handle;
$element
.rangeslider({
polyfill: false,
onInit: function() {
$handle = $('.rangeslider__handle', this.$range);
updateHandle($handle[0], this.value);
updateState($handle[0], this.value);
}
})
.on('input', function() {
updateHandle($handle[0], this.value);
checkState($handle[0], this.value);
});
// Update the value inside the slider handle
function updateHandle(el, val) {
el.textContent = Math.round(0.25*val) + "€";
}
// Check if the slider state has changed
function checkState(el, val) {
// if the value does not fall in the range of the current state, update that shit.
if (!_.contains(currentState.range, parseInt(val))) {
updateState(el, val);
}
}
// Change the state of the slider
function updateState(el, val) {
for (var j = 0; j < sliderStates.length; j++){
if (_.contains(sliderStates[j].range, parseInt(val))) {
currentState = sliderStates[j];
// updateSlider();
}
}
// If the state is high, update the handle count to read 50+
if (currentState.name == "high") {
updateHandle($handle[0], "150");
}
// Update handle color
$handle
.removeClass (function (index, css) {
return (css.match (/(^|\s)js-\S+/g) || []).join(' ');
})
.addClass("js-" + currentState.name);
// Update tooltip
$tooltip.html(currentState.tooltip);
}
label {
display: block;
margin-bottom: 2.5em;
font-size: 13px;
font-weight: bold;
}
.rangeslider__tooltip {
display: block;
margin-top: 2.5em;
font-size: 12px;
color: #a59eb5;
max-width: max-content;
}
.rangeslider,
input[type=range] {
max-width: 400px;
}
.rangeslider__handle {
border-radius: 22px;
line-height: 42px;
text-align: center;
font-weight: bold;
}
.rangeslider__handle:after {
background: 0;
}
.rangeslider,
.rangeslider__fill {
display: block;
border-radius: 10px;
}
.rangeslider {
background: white;
background-image: linear-gradient(to right, #4bc67d 30%, #f1c40f 45%, #b94a48 99%);
position: relative;
}
.rangeslider--horizontal {
height: 7px;
width: 100%;
}
.rangeslider--vertical {
width: 20px;
min-height: 150px;
max-height: 100%;
}
.rangeslider--disabled {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
opacity: 0.4;
}
.rangeslider__fill {
position: absolute;
}
.rangeslider--horizontal .rangeslider__fill {
top: 0;
height: 100%;
}
.rangeslider--vertical .rangeslider__fill {
bottom: 0;
width: 100%;
}
.rangeslider__handle {
background: #e6e7ee;
border: 6px solid #4bc67d;
cursor: pointer;
display: inline-block;
width: 42px;
height: 42px;
position: absolute;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
font-size: small;
}
.rangeslider__handle.js-low {
border-color: #4bc67d;
}
.rangeslider__handle.js-med {
border-color: #f1c40f;
}
.rangeslider__handle.js-high {
border-color: #b94a48;
}
.rangeslider__handle:after {
content: "";
display: block;
width: 18px;
height: 18px;
margin: auto;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
.rangeslider--horizontal .rangeslider__handle {
top: -20px;
touch-action: pan-y;
-ms-touch-action: pan-y;
}
.rangeslider--vertical .rangeslider__handle {
left: -10px;
touch-action: pan-x;
-ms-touch-action: pan-x;
}
input[type=range]:focus + .rangeslider .rangeslider__handle {
-moz-box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
-webkit-box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
}
<!DOCTYPE html>
<html lang="en" >
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
</head>
<body>
<div class="main">
<input
type="range"
name="participants"
min="80"
max="150"
value="99"
oninput="showVal(this.value)"
onchange="showVal(this.value)"
>
<span class="rangeslider__tooltip" id ="range-tooltip"></span>
<div class="main">
<input
type="range"
name="participants"
min="80"
max="150"
value="99"
oninput="showVal(this.value)"
onchange="showVal(this.value)"
>
<span class="rangeslider__tooltip" id ="range-tooltip"></span>
<script>
function showVal(newVal){
console.log("updated");
</script>
<!-- partial -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://andreruffert.github.io/rangeslider.js/assets/rangeslider.js/dist/rangeslider.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js'></script>
</body>
</html>
I've done many changes to the JS but my Code keeps changing the color of the same rangeslider because I am doing it wrong. Could you please help with any hints? Thanks so much
Since $element
now has more than one input
element... You have to use an .each()
loop to instanciate the function on each of them.
So... I just moved the whole thing inside in a .each()
loop. No more change.
For the tooltips, remove const $tooltip = $("#range-tooltip");
from the globals... And use a .siblings()
to target the right tooltip span
.
const $element = $('input[type="range"]');
const sliderStates = [
{ name: "low", tooltip: "Good.", range: _.range(80, 100) },
{ name: "med", tooltip: "Okay.", range: _.range(101, 149) },
{ name: "high", tooltip: "Bad.", range: [150] }
];
// Loop every input elements
$element.each(function (index, element) {
var currentState;
var $handle;
// Instanciate on the element
$(element)
.rangeslider({
polyfill: false,
onInit: function () {
$handle = $(".rangeslider__handle", this.$range);
updateHandle($handle[0], this.value);
updateState($handle[0], this.value);
}
})
.on("input", function () {
updateHandle($handle[0], this.value);
checkState($handle[0], this.value);
});
// Update the value inside the slider handle
function updateHandle(el, val) {
el.textContent = Math.round(0.25 * val) + "€";
}
// Check if the slider state has changed
function checkState(el, val) {
// if the value does not fall in the range of the current state, update that shit.
if (!_.contains(currentState.range, parseInt(val))) {
updateState(el, val);
}
}
// Change the state of the slider
function updateState(el, val) {
for (var j = 0; j < sliderStates.length; j++) {
if (_.contains(sliderStates[j].range, parseInt(val))) {
currentState = sliderStates[j];
// updateSlider();
}
}
// If the state is high, update the handle count to read 50+
if (currentState.name == "high") {
updateHandle($handle[0], "150");
}
// Update handle color
$handle
.removeClass(function (index, css) {
return (css.match(/(^|\s)js-\S+/g) || []).join(" ");
})
.addClass("js-" + currentState.name);
// Update tooltip
$(element).siblings(".rangeslider__tooltip").html(currentState.tooltip);
}
});
label {
display: block;
margin-bottom: 2.5em;
font-size: 13px;
font-weight: bold;
}
.rangeslider__tooltip {
display: block;
margin-top: 2.5em;
font-size: 12px;
color: #a59eb5;
max-width: max-content;
}
.rangeslider,
input[type=range] {
max-width: 400px;
}
.rangeslider__handle {
border-radius: 22px;
line-height: 42px;
text-align: center;
font-weight: bold;
}
.rangeslider__handle:after {
background: 0;
}
.rangeslider,
.rangeslider__fill {
display: block;
border-radius: 10px;
}
.rangeslider {
background: white;
background-image: linear-gradient(to right, #4bc67d 30%, #f1c40f 45%, #b94a48 99%);
position: relative;
}
.rangeslider--horizontal {
height: 7px;
width: 100%;
}
.rangeslider--vertical {
width: 20px;
min-height: 150px;
max-height: 100%;
}
.rangeslider--disabled {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
opacity: 0.4;
}
.rangeslider__fill {
position: absolute;
}
.rangeslider--horizontal .rangeslider__fill {
top: 0;
height: 100%;
}
.rangeslider--vertical .rangeslider__fill {
bottom: 0;
width: 100%;
}
.rangeslider__handle {
background: #e6e7ee;
border: 6px solid #4bc67d;
cursor: pointer;
display: inline-block;
width: 42px;
height: 42px;
position: absolute;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
font-size: small;
}
.rangeslider__handle.js-low {
border-color: #4bc67d;
}
.rangeslider__handle.js-med {
border-color: #f1c40f;
}
.rangeslider__handle.js-high {
border-color: #b94a48;
}
.rangeslider__handle:after {
content: "";
display: block;
width: 18px;
height: 18px;
margin: auto;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
.rangeslider--horizontal .rangeslider__handle {
top: -20px;
touch-action: pan-y;
-ms-touch-action: pan-y;
}
.rangeslider--vertical .rangeslider__handle {
left: -10px;
touch-action: pan-x;
-ms-touch-action: pan-x;
}
input[type=range]:focus + .rangeslider .rangeslider__handle {
-moz-box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
-webkit-box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
box-shadow: 0 0 8px rgba(255, 0, 255, 0.9);
}
<!DOCTYPE html>
<html lang="en" >
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
</head>
<body>
<div class="main">
<input
type="range"
name="participants"
min="80"
max="150"
value="99"
oninput="showVal(this.value)"
onchange="showVal(this.value)"
>
<span class="rangeslider__tooltip" id ="range-tooltip"></span>
<div class="main">
<input
type="range"
name="participants"
min="80"
max="150"
value="99"
oninput="showVal(this.value)"
onchange="showVal(this.value)"
>
<span class="rangeslider__tooltip" id ="range-tooltip"></span>
<script>
function showVal(newVal){
//console.log("updated");
}
</script>
<!-- partial -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='https://andreruffert.github.io/rangeslider.js/assets/rangeslider.js/dist/rangeslider.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js'></script>
</body>
</html>