UNPKG

r-range-slider

Version:

all in one range slider, single range , double range , multi range

932 lines (804 loc) 24.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _jquery = _interopRequireDefault(require("jquery")); require("./index.css"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var RRangeSliderContext = /*#__PURE__*/(0, _react.createContext)(); class RRangeSlider extends _react.Component { constructor(props) { super(props); var { direction } = this.props; this.touch = 'ontouchstart' in document.documentElement; if (direction === 'left') { this.getDiff = function (x, y, client) { return x - client.x; }; this.oriention = 'horizontal'; } else if (direction === 'right') { this.getDiff = function (x, y, client) { return client.x - x; }; this.oriention = 'horizontal'; } else if (direction === 'top') { this.getDiff = function (x, y, client) { return y - client.y; }; this.oriention = 'vertical'; this.flexDirection = 'column-reverse'; } else { this.getDiff = function (x, y, client) { return client.y - y; }; this.oriention = 'vertical'; this.flexDirection = 'column'; } this.dom = /*#__PURE__*/(0, _react.createRef)(); this.state = { isDown: false }; } getClient(e) { return this.touch ? { x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientY } : { x: e.clientX, y: e.clientY }; } getPercentByValue(value, start, end) { return 100 * (value - start) / (end - start); } //getPercentByValue fix(number) { let dotPos = this.props.step.toString().indexOf('.'); let a = dotPos === -1 ? 0 : this.props.step.toString().length - dotPos - 1; return parseFloat(number.toFixed(a)); } getStartByStep(start, step) { var a = Math.round((start - step) / step) * step; while (a < start) { a += step; } return a; } eventHandler(selector, event, action, type = 'bind') { var me = { mousedown: "touchstart", mousemove: "touchmove", mouseup: "touchend" }; event = this.touch ? me[event] : event; var element = typeof selector === "string" ? selector === "window" ? (0, _jquery.default)(window) : (0, _jquery.default)(selector) : selector; element.unbind(event, action); if (type === 'bind') { element.bind(event, action); } } getValidPoints() { let { points, start, end, min = start, max = end, step } = this.props; for (var i = 0; i < points.length; i++) { var point = points[i]; point = Math.round((point - start) / step) * step + start; if (point < min) { point = min; } if (point > max) { point = max; } points[i] = point; } return points; } getOffset(x, y, size, e) { var { start, end, step } = this.props, client = this.getClient(e); return Math.round((end - start) * this.getDiff(x, y, client) / size / step) * step; } getValue(value, param = this.props) { return typeof value === 'function' ? value(param) : value; } getPercents() { var { start, end } = this.props; var percents = this.points.map((o, i) => [this.getPercentByValue(i ? this.points[i - 1] : start, start, end), this.getPercentByValue(o, start, end)]); percents.push([percents[percents.length - 1][1], 100]); return percents; } decreaseAll(step = this.props.step) { var start = this.props.start; var { min = start } = this.props; var offset = Math.min(step, this.points[0] - this.getValue(min)); for (var i = 0; i < this.points.length; i++) { this.points[i] -= offset; this.points[i] = this.fix(this.points[i]); } this.moved = true; } increaseAll(step = this.props.step) { var end = this.props.end; var { max = end } = this.props; var offset = Math.min(step, this.getValue(max) - this.points[this.points.length - 1]); for (var i = 0; i < this.points.length; i++) { this.points[i] += offset; this.points[i] = this.fix(this.points[i]); } this.moved = true; } mouseDown(e, index, type) { e.preventDefault(); var { start, end, min = start, max = end, onChange, disabled } = this.props; if (!onChange || disabled) { return; } var { x, y } = this.getClient(e), dom = (0, _jquery.default)(this.dom.current); var pointContainers = dom.find('.r-range-slider-point-container'); var size = dom.find('.r-range-slider-line')[this.oriention === 'horizontal' ? 'width' : 'height'](); var length = this.points.length; this.eventHandler('window', 'mousemove', _jquery.default.proxy(this.mouseMove, this)); this.eventHandler('window', 'mouseup', _jquery.default.proxy(this.mouseUp, this)); this.moved = false; this.setState({ isDown: true }); pointContainers.css({ zIndex: 10 }); if (type === 'point') { let pointContainer = pointContainers.eq(index); pointContainer.css({ zIndex: 100 }); pointContainer.find('.r-range-slider-point').addClass('active'); var current = this.points[index]; var before = index === 0 ? min : this.points[index - 1]; var after = index === this.points.length - 1 ? max : this.points[index + 1]; this.startOffset = { x, y, size, index: [index], value: [current], startLimit: before - current, endLimit: after - current }; } else { let pointContainer1 = pointContainers.eq(index - 1); let pointContainer2 = pointContainers.eq(index); pointContainer1.css({ zIndex: 100 }); pointContainer2.css({ zIndex: 100 }); let p1 = pointContainer1.find('.r-range-slider-point'); let p2 = pointContainer2.find('.r-range-slider-point'); p1.addClass('active'); p2.addClass('active'); if (index === 0) { this.decreaseAll(); } else if (index === length) { this.increaseAll(); } if (index === 0 || index === length) { this.startOffset = { x, y, size, index: this.points.map((o, i) => i), value: this.points.map(o => o), startLimit: min - this.points[0], endLimit: max - this.points[length - 1] }; } else { var point1 = this.points[index - 1], point2 = this.points[index]; var before = index === 1 ? min : this.points[index - 2]; //مقدار قبلی رنج var after = index === length - 1 ? max : this.points[index + 1]; //مقدار بعدی رنج this.startOffset = { x, y, size, index: [index - 1, index], value: [point1, point2], startLimit: before - point1, endLimit: after - point2 }; } } } mouseMove(e) { let { onChange } = this.props; var { x, y, size, value, startLimit, endLimit, index } = this.startOffset; var offset = this.getOffset(x, y, size, e); if (offset < startLimit) { offset = startLimit; } else if (offset > endLimit) { offset = endLimit; } for (var i = 0; i < value.length; i++) { let Index = index[i], Value = value[i], newValue = parseFloat(Value) + offset; if (this.points[Index] === newValue) { return; } this.points[Index] = this.fix(newValue); } this.moved = true; onChange(this.points, true); } mouseUp() { this.eventHandler('window', 'mousemove', this.mouseMove, 'unbind'); this.eventHandler('window', 'mouseup', this.mouseUp, 'unbind'); let { onChange } = this.props; var points = (0, _jquery.default)(this.dom.current).find('.r-range-slider-point'); points.removeClass('active'); this.setState({ isDown: false }); if (this.moved) { onChange(this.points, false); } } getContext() { var context = { ...this.props }; context.touch = this.touch; context.fix = this.fix.bind(this); context.oriention = this.oriention; context.getValue = this.getValue.bind(this); context.isDown = this.state.isDown; context.mouseDown = this.mouseDown.bind(this); context.getStartByStep = this.getStartByStep.bind(this); context.getPercentByValue = this.getPercentByValue.bind(this); context.points = this.points; return context; } getStyle() { let { attrs } = this.props; let { style = {} } = attrs; var obj = { ...style }; obj = { ...obj }; obj.direction = 'ltr'; obj.flexDirection = this.flexDirection; return obj; } getClassName() { let { attrs } = this.props; let { className } = attrs; return `r-range-slider ${this.context.oriention}${className ? ' ' + className : ''}`; } render() { this.points = this.getValidPoints(); this.context = this.getContext(); var { labelStep, scaleStep, attrs } = this.props; var percents = this.getPercents(); return /*#__PURE__*/_react.default.createElement(RRangeSliderContext.Provider, { value: this.context }, /*#__PURE__*/_react.default.createElement("div", _extends({ ref: this.dom }, attrs, { style: this.getStyle(), className: this.getClassName() }), /*#__PURE__*/_react.default.createElement("div", { style: { display: 'flex', height: '100%', width: '100%', alignItems: 'center', justifyContent: 'center', position: 'relative' } }, /*#__PURE__*/_react.default.createElement(RRangeSliderLine, null), labelStep && /*#__PURE__*/_react.default.createElement(RRangeSliderLabels, null), scaleStep && /*#__PURE__*/_react.default.createElement(RRangeSliderScales, null), this.points.map((o, i) => /*#__PURE__*/_react.default.createElement(RRangeSliderFill, { key: i, index: i, percent: percents[i] })), /*#__PURE__*/_react.default.createElement(RRangeSliderFill, { key: this.points.length, index: this.points.length, percent: percents[this.points.length] }), this.points.map((o, i) => /*#__PURE__*/_react.default.createElement(RRangeSliderPoint, { key: i, index: i, percent: percents[i] }))))); } } exports.default = RRangeSlider; RRangeSlider.defaultProps = { direction: 'right', editLabel: a => a, labelStyle: () => { return {}; }, labelRotate: () => { return 0; }, points: [0], scaleStyle: () => { return {}; }, getPointHTML: () => '', style: () => {}, start: 0, end: 100, step: 1, activegetPointStyle: {}, getText: () => { return ''; }, attrs: {}, pointStyle: () => { return {}; }, lineStyle: () => { return {}; }, fillStyle: () => { return {}; }, valueStyle: () => { return {}; }, textStyle: {}, editValue: (value, index) => value, textStyle: () => {} }; class RRangeSliderLine extends _react.Component { render() { var { lineStyle } = this.context; return /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-line", style: lineStyle(this.context) }); } } _defineProperty(RRangeSliderLine, "contextType", RRangeSliderContext); class RRangeSliderFill extends _react.Component { getContainerStyle() { var { oriention, direction } = this.context, { percent } = this.props; var obj = {}; obj[{ right: 'left', left: 'right', top: 'bottom', bottom: 'top' }[direction]] = percent[0] + '%'; if (oriention === 'horizontal') { obj.width = percent[1] - percent[0] + '%'; } else { obj.height = percent[1] - percent[0] + '%'; } return obj; } render() { var { mouseDown, rangeEvents = {}, fillStyle, getText, textStyle, touch } = this.context; var { index } = this.props; var containerProps = { 'data-index': index, className: 'r-range-slider-fill-container', [touch ? 'onTouchStart' : 'onMouseDown']: e => { mouseDown(e, index, 'fill'); }, style: this.getContainerStyle() }; for (let prop in rangeEvents) { containerProps[prop] = () => rangeEvents[prop](index); } let text = getText(index, this.context); return /*#__PURE__*/_react.default.createElement("div", containerProps, /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-fill", style: fillStyle(index, this.context), "data-index": index }), text !== undefined && /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-text", style: textStyle(index) }, text)); } } _defineProperty(RRangeSliderFill, "contextType", RRangeSliderContext); class RRangeSliderPoint extends _react.Component { getContainerStyle() { var { direction } = this.context, { percent } = this.props; return { [{ right: 'left', left: 'right', top: 'bottom', bottom: 'top' }[direction]]: percent[1] + '%' }; } getValueStyle() { var { showValue, isDown, valueStyle } = this.context; var { index } = this.props; if (showValue === false) { return { display: 'none' }; } if (showValue === true || isDown) { return valueStyle(index, this.context); } return { display: 'none' }; } render() { var { points, mouseDown, editValue, pointEvents, getPointHTML, pointStyle, touch, fix } = this.context; var { index } = this.props; var point = points[index]; var props = { style: this.getContainerStyle(), 'data-index': index, className: 'r-range-slider-point-container', [touch ? 'onTouchStart' : 'onMouseDown']: e => { mouseDown(e, index, 'point'); } }; for (let prop in pointEvents) { props[prop] = () => pointEvents[prop](index); } var pointProps = { className: 'r-range-slider-point', style: pointStyle(index, this.context), 'data-index': index }; var valueProps = { style: this.getValueStyle(), className: 'r-range-slider-value' }; let html = getPointHTML(index, this.context); return /*#__PURE__*/_react.default.createElement("div", props, /*#__PURE__*/_react.default.createElement("div", pointProps, html), /*#__PURE__*/_react.default.createElement("div", valueProps, editValue(fix(point), index))); } } _defineProperty(RRangeSliderPoint, "contextType", RRangeSliderContext); class RRangeSliderLabels extends _react.Component { constructor(props) { super(props); this.dom = /*#__PURE__*/(0, _react.createRef)(); (0, _jquery.default)(window).on('resize', this.update.bind(this)); } getLabelsByStep(labelStep) { var { start, label = {}, end, getStartByStep } = this.context; var Labels = []; var value = getStartByStep(start, labelStep); var key = 0; while (value <= end) { Labels.push( /*#__PURE__*/_react.default.createElement(RRangeSliderLabel, { key: key, value: value })); value += labelStep; value = parseFloat(value.toFixed(6)); key++; } return Labels; } getLabels(labelStep) { return labelStep.map(o => /*#__PURE__*/_react.default.createElement(RRangeSliderLabel, { key: o, value: o })); } update() { var container = (0, _jquery.default)(this.dom.current); var labels = container.find('.r-range-slider-label div'); if (!labels.length) { return; } var { direction, label = {} } = this.context; var firstLabel = labels.eq(0); var firstLabelThickness = firstLabel.attr('datarotated') === 'yes' ? 'height' : 'width'; if (direction === 'right') { var end = firstLabel.offset().left + firstLabel[firstLabelThickness](); for (var i = 1; i < labels.length; i++) { var label = labels.eq(i); let thickness = label.attr('datarotated') === 'yes' ? 'height' : 'width'; label.css({ display: 'block' }); var left = label.offset().left; var width = label[thickness](); if (left < end + 5) { label.css({ display: 'none' }); } else { end = left + width; } } } else if (direction === 'left') { var end = firstLabel.offset().left; for (var i = 1; i < labels.length; i++) { var label = labels.eq(i); let thickness = label.attr('datarotated') === 'yes' ? 'height' : 'width'; label.css({ display: 'block' }); var left = label.offset().left; var width = label[thickness](); var right = left + width; if (right > end - 5) { label.css({ display: 'none' }); } else { end = left; } } } } componentDidMount() { this.update(); } componentDidUpdate() { this.update(); } render() { let { labelStep } = this.context; return /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-labels", ref: this.dom }, Array.isArray(labelStep) ? this.getLabels(labelStep) : this.getLabelsByStep(labelStep)); } } _defineProperty(RRangeSliderLabels, "contextType", RRangeSliderContext); class RRangeSliderLabel extends _react.Component { getStyle() { var { start, end, getPercentByValue, direction, labelStyle, labelRotate } = this.context; var { value } = this.props; var obj = labelStyle(value, this.context); if (!obj) { obj = {}; } obj[{ right: 'left', left: 'right', top: 'bottom', bottom: 'top' }[direction]] = getPercentByValue(value, start, end) + '%'; let rotate = labelRotate(value); if (rotate) { obj.transform = `rotate(${rotate + 'deg'})`; obj.justifyContent = rotate > 0 ? 'flex-start' : 'flex-end'; } return obj; } click(e) { var { onLabelClick } = this.context; e.stopPropagation(); if (!onLabelClick) { return; } var { value } = this.props; onLabelClick(value); } render() { let { editLabel, labelRotate } = this.context; let { value } = this.props; let rotate = labelRotate(value); let text; try { text = editLabel(value); } catch { text = ''; } return /*#__PURE__*/_react.default.createElement("div", { onClick: this.click.bind(this), style: this.getStyle(), className: `r-range-slider-label` }, /*#__PURE__*/_react.default.createElement("div", { datarotated: rotate ? 'yes' : 'no', className: "r-range-slider-label-text" }, text)); } } _defineProperty(RRangeSliderLabel, "contextType", RRangeSliderContext); class RRangeSliderScales extends _react.Component { getScalesByStep(scaleStep) { var { start, end, getStartByStep } = this.context; var value = getStartByStep(start, scaleStep); var key = 0, scales = []; while (value <= end) { scales.push( /*#__PURE__*/_react.default.createElement(RRangeSliderScale, { value: value, key: key })); value += scaleStep; key++; } return scales; } getScales(scaleStep) { return scaleStep.map(o => /*#__PURE__*/_react.default.createElement(RRangeSliderScale, { value: o, key: o })); } render() { let { scaleStep } = this.context; return /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-scales" }, Array.isArray(scaleStep) ? this.getScales(scaleStep) : this.getScalesByStep(scaleStep)); } } _defineProperty(RRangeSliderScales, "contextType", RRangeSliderContext); class RRangeSliderScale extends _react.Component { getStyle() { var { scaleStyle } = this.context; var { start, end, direction, getPercentByValue } = this.context, { value } = this.props; var obj = scaleStyle(value, this.context); if (!obj) { obj = {}; } obj[{ right: 'left', left: 'right', top: 'bottom', bottom: 'top' }[direction]] = getPercentByValue(value, start, end) + '%'; return obj; } render() { let { getScaleHTML } = this.context; let { value } = this.props; return /*#__PURE__*/_react.default.createElement("div", { className: "r-range-slider-scale", style: this.getStyle() }, getScaleHTML && getScaleHTML(value)); } } _defineProperty(RRangeSliderScale, "contextType", RRangeSliderContext);