# range-slider-widget
A range slider that reacts to a range slider and changes images.
Dependencies needed: node-sass, sass-loader and nouislider.
# props
sliderBackgroundColor String (optional) background color of slider
slides Array (required) Image slides.
Example: {
active: true,
src: '/assets/modules/brain-1.svg',
message: 'This is the message'
}
resetButtonOnComplete Boolean (optional) Show refresh button on widget completion. default: false
debug Boolean (optional) Show outline around the widget for CSS debugging. default: false
# Events
@onComplete emits when last slide shows
# Example
<template>
<div>
<RangeSliderWidget
:slides="[
{
active: true,
src: '/assets/modules/brain-1.svg',
message: 'Slide to see the health harms that have been connected to vape use.'
},
{
active: false,
src: '/assets/modules/brain-2.svg',
message: 'Nicotine salts make it easier to take bigger hits.'
},
{
active: false,
src: '/assets/modules/brain-3.svg',
message: ' This puts vapers at risk for extremely high doses of nicotine with every hit.'
},
{
active: false,
src: '/assets/modules/brain-4.svg',
message: 'It also makes it easier to hit a vape more frequently.'
},
{
active: false,
src: '/assets/modules/brain-5.svg',
message: 'Putting vapers at high risk for nicotine addiction.'
}
]" />
</div>
</template>
<script>
import { RangeSliderWidget } from '@rescue/vue-modules';
export default {
components: {
RangeSliderWidget
}
};
</script>
# Source Code
<template>
<div
:class="[{ debug }]"
class="range-slider-widget">
<div class="grid">
<div class="slides">
<img
v-for="(slide, i) in slides"
v-show="slide.active"
:key="i"
:src="slide.src" />
</div>
<div class="progress-bar">
<div class="horizontal">
<div
ref="no-ui-slider"
class="no-ui-slider">
</div>
</div>
</div>
</div>
<div
v-if="typeof activeSlide.message === 'string'"
v-html="activeSlide.message"
class="message">
</div>
<!-- <button
v-show="resetButtonOnComplete && showResetButton"
@click="reset"
class="reset-button">
<i class="fas fa-redo"></i>
</button>
<div
v-if="typeof activeSlide.message === 'string'"
v-html="activeSlide.message"
class="message">
</div>
<div
v-if="typeof activeSlide.instructions === 'string'"
v-html="activeSlide.instructions"
class="instructions">
</div> -->
</div>
</template>
<script>
import "nouislider/distribute/nouislider.css";
export default {
props: {
sliderBackgroundColor: {
default: "white",
type: String
},
slides: {
default: [],
type: Array
},
resetButtonOnComplete: {
default: true,
type: Boolean
},
debug: {
default: false,
type: Boolean
}
},
computed: {
activeSlide() {
return this.slides[this.activeIndex];
}
},
data() {
return {
activeIndex: 0,
showResetButton: false,
noUiSlider: null
}
},
mounted() {
import("nouislider").then(noUiSlider => {
this.noUiSlider = noUiSlider.create(this.$refs["no-ui-slider"], {
range: {
"min": 1,
"max": this.slides.length
},
start: [1],
step: 1,
connect: [true, false]
});
this.noUiSlider.on("update", value => {
this.activeIndex = parseFloat(value[0]) - 1;
this.actifySlide(parseFloat(value[0]) - 1);
});
});
},
methods: {
actifySlide(index) {
this.slides.forEach(slide => {
slide.active = false;
});
this.slides[index].active = true;
if (index >= this.slides.length - 1) {
this.$emit("onComplete");
}
this.$forceUpdate();
}
}
}
</script>
<style lang="scss" scoped>
.range-slider-widget {
position : relative;
&.debug * {
outline : 1px solid red;
}
.grid {
.slides {
button {
background : none;
border : none;
cursor : pointer;
&:focus,
&:hover,
&:active {
outline : none;
}
&:active {
transform : scale(0.975);
}
}
}
.progress-bar {
.horizontal {
margin-top : 15px;
width : 100%;
}
}
}
.reset-button {
position : absolute;
bottom : 0px;
left : 0px;
width : 30px;
height : 30px;
border-radius : 15px;
background : white;
font-size : 0.8em;
box-shadow : 0px 4px 10px rgba(0, 0, 0, 0.1);
cursor : pointer;
&:focus,
&:hover,
&:active {
outline : none;
}
&:active {
transform : scale(0.975);
}
i {
top : 1px;
position : relative;
}
}
.message {
position : absolute;
top : 105%;
}
.instructions {
position : absolute;
top : 105%;
}
}
</style>