UNPKG

@creenv/slider

Version:
223 lines (194 loc) 5.78 kB
"use strict"; var injectCss = require('@creenv/inject-css'); function ___noop() {} var ___styleId = "creenv-slider-style"; var ___css = '.creenv-slider-container {\ position: relative;\ width: 100%;\ height: 23px;\ background: black;\ cursor: e-resize;\ border-radius: 30px;\ user-select: none;\ }\ \ .creenv-slider-progress {\ position: absolute;\ width: 0;\ height: 100%;\ top: 0; left: 0;\ background: #c0d6e0;\ border-radius: 30px;\ border-top-right-radius: 0;\ border-bottom-right-radius: 0;\ z-index: 10\ }\ \ .creenv-slider-cursor {\ position: absolute;\ width: 13px; height: 30px;\ background: white;\ left: 0; top: 50%;\ transform: translate(-50%,-50%);\ border-radius: 30px;\ z-index: 20;\ }\ \ .creenv-slider-container.vertical {\ height: 100%;\ width: 23px;\ min-height: 40px;\ cursor: s-resize;\ }\ \ .creenv-slider-container.vertical .creenv-slider-progress {\ width: 100%;\ height: 0;\ bottom: 0; top: auto;\ border-radius: 30px;\ border-top-left-radius: 0;\ border-top-right-radius: 0;\ }\ \ .creenv-slider-container.vertical .creenv-slider-cursor {\ height: 13px; width: 30px;\ background: white;\ bottom: 0; left: 50%;\ transform: translate(-50%,50%);\ top: auto;\ }'; /** * Generates a dom element that trigger events * * @param {?number} min The min of the range covered by the slider (=0) * @param {?number} max the max of the range covered by the slider (=100) * @param {?number} step the step between each ticks of the slider (=0.5) * @param {?number} value the original valeu taken by the slider (=10) * @param {?function} onChange callback called on property value changing * @param {?function} onChangeFinished callback when property value is done changing * @param {?boolean} vertical weither the slider needs to be rendered vertically */ function Slider (min, max, step, value, onChange, onChangeFinished, vertical) { if (min === undefined) min = 0; if (max === undefined) max = 100; if (step === undefined) step = 0.5; if (value === undefined) value = 10; if (vertical === undefined) vertical = false; // we first inject the css into the dom injectCss(___css, ___styleId); /** * Callback function called when slider value changes * @type {function} * @public */ this.onChange = onChange; /** * Callback function called when user releases the click after changing the * slider value * @type {function} * @public */ this.onChangeFinished = onChangeFinished; this.min = min; this.max = max; this.step = step; this.value = value; /** * Contains the elements that can be added to the DOM of the document * @type {HTMLElement} * @public */ this.dom = null; /** * Set to true if the element is clicked * @type {boolean} * @private */ this.clicked = false; /** * Left offset in pixels of the slide container * @type {number} * @private */ this.x = 0; /** * Width of the slider container, in px * @type {number} * @private */ this.width = 0; /** * if the slider is vertical or not * @type {boolean} * @private */ this.vertical = vertical; this.onChange = onChange; this.onChangeFinished = onChangeFinished; this.container = document.createElement("div"); this.container.classList.add("creenv-slider-container"); if (vertical) this.container.classList.add("vertical"); this.progress = document.createElement("div"); this.progress.classList.add("creenv-slider-progress"); this.cursor = document.createElement("div"); this.cursor.classList.add("creenv-slider-cursor"); this.container.appendChild(this.progress); this.container.appendChild(this.cursor); this.dom = this.container; var that = this; this.updateGraphics(); this.dom.addEventListener("mousedown", function(event) { // small optimisation, we consider that sliders won't move during the slide process var rect = that.dom.getBoundingClientRect(); that.x = that.vertical ? rect.y : rect.x; that.width = that.vertical ? rect.height : rect.width; that.clicked = true; that.updateValue(that.vertical ? event.pageY : event.pageX); }); document.addEventListener("mouseup", function() { if (that.clicked) { that.clicked = false; (that.onChangeFinished || ___noop)(that.value); } }); document.addEventListener("mousemove", function (event) { if (that.clicked) { that.updateValue(that.vertical ? event.pageY : event.pageX); } }); } /** * Updates the value of the slider given the mouse position * @param {number} mousePos x position of the mouse relative to the page * @private */ Slider.prototype.updateValue = function (mousePos) { var relativePosition = (mousePos-this.x)/this.width; var relativeValue = relativePosition*(this.max-this.min) + this.min; var rounded = Math.max(Math.min(this.max, Math.round(relativeValue/this.step)*this.step), this.min); var changed = this.value != rounded; this.value = rounded; if (changed) { this.updateGraphics(); (this.onChange || ___noop)(this.value); } }; /** * Updates the graphics of the slider given the current value - called * after updateValue() is called and a change is detected * @private */ Slider.prototype.updateGraphics = function () { // we clamp the value jic var value = Math.max(Math.min(this.max,(this.value),this.min)); var width = (this.value-this.min)/(this.max-this.min)*100; if (this.vertical) width = 100-width; if (this.vertical) { this.progress.style.height = width+"%"; this.cursor.style.bottom = width+"%"; } else { this.progress.style.width = width+"%"; this.cursor.style.left = width+"%"; } }; module.exports = Slider;