# 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>
Slide to see the health harms that have been connected to vape use.



# 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>