devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
338 lines (335 loc) • 14.6 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/m_range_slider.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _events_engine = _interopRequireDefault(require("../../common/core/events/core/events_engine"));
var _index = require("../../common/core/events/utils/index");
var _message = _interopRequireDefault(require("../../common/core/localization/message"));
var _component_registrator = _interopRequireDefault(require("../../core/component_registrator"));
var _renderer = _interopRequireDefault(require("../../core/renderer"));
var _common = require("../../core/utils/common");
var _size = require("../../core/utils/size");
var _m_slider = _interopRequireDefault(require("../ui/slider/m_slider"));
var _m_slider_handle = _interopRequireDefault(require("./slider/m_slider_handle"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function(n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) {
({}).hasOwnProperty.call(t, r) && (n[r] = t[r])
}
}
return n
}, _extends.apply(null, arguments)
}
const RANGE_SLIDER_CLASS = "dx-rangeslider";
const RANGE_SLIDER_START_HANDLE_CLASS = "dx-rangeslider-start-handle";
const RANGE_SLIDER_END_HANDLE_CLASS = "dx-rangeslider-end-handle";
class RangeSlider extends _m_slider.default {
_supportedKeys() {
const {
rtlEnabled: rtlEnabled
} = this.option();
const that = this;
const _changeHandle = function(e, capturedHandle) {
if (that.option("start") === that.option("end")) {
that._capturedHandle = capturedHandle;
e.target = that._capturedHandle;
_events_engine.default.trigger(that._capturedHandle, "focus")
}
};
const _setHandleValue = function(e, step, sign) {
const isStart = (0, _renderer.default)(e.target).hasClass("dx-rangeslider-start-handle");
const valueOption = isStart ? "start" : "end";
let val = that.option(valueOption);
step = that._valueStep(step);
val += sign * (rtlEnabled ? -step : step);
that.option(valueOption, val)
};
const moveHandleRight = function(e, step) {
_changeHandle(e, rtlEnabled ? that._$handleStart : that._$handleEnd);
_setHandleValue(e, step, 1)
};
const moveHandleLeft = function(e, step) {
_changeHandle(e, rtlEnabled ? that._$handleEnd : that._$handleStart);
_setHandleValue(e, step, -1)
};
return _extends({}, super._supportedKeys(), {
leftArrow(e) {
this._processKeyboardEvent(e);
moveHandleLeft(e, this.option("step"))
},
rightArrow(e) {
this._processKeyboardEvent(e);
moveHandleRight(e, this.option("step"))
},
pageUp(e) {
this._processKeyboardEvent(e);
moveHandleRight(e, this.option("step") * this.option("keyStep"))
},
pageDown(e) {
this._processKeyboardEvent(e);
moveHandleLeft(e, this.option("step") * this.option("keyStep"))
},
home(e) {
this._processKeyboardEvent(e);
const isStart = (0, _renderer.default)(e.target).hasClass("dx-rangeslider-start-handle");
const valueOption = isStart ? "start" : "end";
const startOption = isStart ? "min" : "start";
const val = this.option(startOption);
this.option(valueOption, val)
},
end(e) {
this._processKeyboardEvent(e);
const isStart = (0, _renderer.default)(e.target).hasClass("dx-rangeslider-start-handle");
const valueOption = isStart ? "start" : "end";
const endOption = isStart ? "end" : "max";
const val = this.option(endOption);
this.option(valueOption, val)
}
})
}
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
start: 40,
end: 60,
value: [40, 60],
startName: "",
endName: ""
})
}
_renderSubmitElement() {
const {
startName: startName,
endName: endName
} = this.option();
const $element = this.$element();
this._$submitStartElement = (0, _renderer.default)("<input>").attr("type", "hidden").attr("name", startName).appendTo($element);
this._$submitEndElement = (0, _renderer.default)("<input>").attr("type", "hidden").attr("name", endName).appendTo($element)
}
_initOptions(options) {
super._initOptions(options);
const initialValue = this.initialOption("value");
const {
value: value = []
} = this.option();
if (value[0] === initialValue[0] && value[1] === initialValue[1]) {
this.option("value", [this.option("start"), this.option("end")])
} else {
this.option({
start: value[0],
end: value[1]
})
}
}
_initMarkup() {
this.$element().addClass("dx-rangeslider");
super._initMarkup()
}
_renderContentImpl() {
this._callHandlerMethod("repaint");
super._renderContentImpl()
}
_renderHandle() {
const {
start: start,
end: end
} = this.option();
this._$handleStart = this._renderHandleImpl(start, this._$handleStart);
this._$handleStart.addClass("dx-rangeslider-start-handle");
this._$handleEnd = this._renderHandleImpl(end, this._$handleEnd);
this._$handleEnd.addClass("dx-rangeslider-end-handle");
this._updateHandleAriaLabels()
}
_startHandler(args) {
const e = args.event;
const $range = this._$range;
const rangeWidth = (0, _size.getWidth)($range);
const eventOffsetX = (0, _index.eventData)(e).x - this._$bar.offset().left;
const startHandleX = $range.position().left;
const endHandleX = $range.position().left + rangeWidth;
const rtlEnabled = this.option("rtlEnabled");
const startHandleIsClosest = (rtlEnabled ? -1 : 1) * ((startHandleX + endHandleX) / 2 - eventOffsetX) > 0;
this._capturedHandle = startHandleIsClosest ? this._$handleStart : this._$handleEnd;
super._startHandler(args)
}
_updateHandleAriaLabels() {
this.setAria("label", _message.default.getFormatter("dxRangeSlider-ariaFrom")(this.option("dxRangeSlider-ariaFrom")), this._$handleStart);
this.setAria("label", _message.default.getFormatter("dxRangeSlider-ariaTill")(this.option("dxRangeSlider-ariaTill")), this._$handleEnd)
}
_activeHandle() {
return this._capturedHandle
}
_updateHandlePosition(e) {
const rtlEnabled = this.option("rtlEnabled");
const offsetDirection = rtlEnabled ? -1 : 1;
const max = this.option("max");
const min = this.option("min");
let newRatio = this._startOffset + offsetDirection * e.event.offset / this._swipePixelRatio();
newRatio = newRatio.toPrecision(12);
const newValue = newRatio * (max - min) + min;
this._updateSelectedRangePosition(newRatio, newRatio);
_m_slider_handle.default.getInstance(this._activeHandle()).fitTooltipPosition;
this._changeValueOnSwipe(newRatio);
const [startValue, endValue] = this._getActualValue();
if (startValue === endValue) {
let $nextHandle = (0, _renderer.default)();
if (newValue < startValue) {
$nextHandle = this._$handleStart
} else {
$nextHandle = this._$handleEnd
}
_events_engine.default.trigger($nextHandle, "focus");
if ($nextHandle && $nextHandle !== this._capturedHandle) {
const leftRatio = (startValue - min) / (max - min);
const rightRatio = (endValue - min) / (max - min);
this._updateSelectedRangePosition(leftRatio, rightRatio);
this._toggleActiveState(this._activeHandle(), false);
this._toggleActiveState($nextHandle, true);
this._capturedHandle = $nextHandle
}
this._updateSelectedRangePosition(newRatio, newRatio);
this._changeValueOnSwipe(newRatio)
}
}
_updateSelectedRangePosition(leftRatio, rightRatio) {
const {
rtlEnabled: rtlEnabled
} = this.option();
const moveRight = this._capturedHandle === this._$handleStart && rtlEnabled || this._capturedHandle === this._$handleEnd && !rtlEnabled;
const prop = moveRight ? "right" : "left";
if (rtlEnabled ^ moveRight) {
this._$range.css(prop, 100 - 100 * rightRatio + "%")
} else {
this._$range.css(prop, 100 * leftRatio + "%")
}
}
_setValueOnSwipe(value) {
const option = this._capturedHandle === this._$handleStart ? "start" : "end";
let [start, end] = this._getActualValue();
const {
max: max,
min: min
} = this.option();
start = Math.min(Math.max(start, min), max);
end = Math.min(Math.max(end, min), max);
if ("start" === option) {
start = value > end ? end : value
} else {
end = value < start ? start : value
}
const {
valueChangeMode: valueChangeMode
} = this.option();
if ("onHandleMove" === valueChangeMode) {
this.option("value", [start, end])
} else {
this._actualValue = [start, end];
this._renderValue()
}
}
_renderValue() {
let [valStart, valEnd] = this._getActualValue();
const {
min: min,
max: max
} = this.option();
const rtlEnabled = this.option("rtlEnabled");
valStart = Math.max(min, Math.min(valStart, max));
valEnd = Math.max(valStart, Math.min(valEnd, max));
const {
valueChangeMode: valueChangeMode
} = this.option();
if ("onHandleMove" === valueChangeMode) {
this._setOptionWithoutOptionChange("start", valStart);
this._setOptionWithoutOptionChange("end", valEnd);
this._setOptionWithoutOptionChange("value", [valStart, valEnd])
}
this._$submitStartElement.val((0, _common.applyServerDecimalSeparator)(valStart));
this._$submitEndElement.val((0, _common.applyServerDecimalSeparator)(valEnd));
const ratio1 = max === min ? 0 : (valStart - min) / (max - min);
const ratio2 = max === min ? 0 : (valEnd - min) / (max - min);
const startOffset = `${parseFloat((100*ratio1).toPrecision(12))}%`;
const endOffset = `${parseFloat((100*(1-ratio2)).toPrecision(12))}%`;
if (!this._needPreventAnimation) {
this._setRangeStyles({
right: rtlEnabled ? startOffset : endOffset,
left: rtlEnabled ? endOffset : startOffset
})
}
_m_slider_handle.default.getInstance(this._$handleStart).option("value", valStart);
_m_slider_handle.default.getInstance(this._$handleEnd).option("value", valEnd)
}
_callHandlerMethod(name, args) {
_m_slider_handle.default.getInstance(this._$handleStart)[name](args);
_m_slider_handle.default.getInstance(this._$handleEnd)[name](args)
}
_setValueOption() {
const start = this.option("start");
const end = this.option("end");
this.option("value", [start, end])
}
_rangesAreEqual(firstRange, secondRange) {
return firstRange[0] === secondRange[0] && firstRange[1] === secondRange[1]
}
_optionChanged(args) {
switch (args.name) {
case "value": {
if (this._rangesAreEqual(args.value, args.previousValue)) {
break
}
this._setOptionWithoutOptionChange("start", args.value[0]);
this._setOptionWithoutOptionChange("end", args.value[1]);
this._renderValue();
const start = this.option("start");
const end = this.option("end");
const isDirty = !this._rangesAreEqual(this._initialValue, args.value);
this.option("isDirty", isDirty);
this._createActionByOption("onValueChanged", {
excludeValidators: ["disabled", "readOnly"]
})({
start: start,
end: end,
value: [start, end],
event: this._valueChangeEventInstance,
previousValue: args.previousValue
});
this.validationRequest.fire({
value: [start, end],
editor: this
});
this._saveValueChangeEvent(void 0);
break
}
case "start":
case "end":
this._setValueOption();
break;
case "startName":
this._$submitStartElement.attr("name", args.value);
break;
case "endName":
this._$submitEndElement.attr("name", args.value);
break;
case "name":
break;
default:
super._optionChanged(args)
}
}
}(0, _component_registrator.default)("dxRangeSlider", RangeSlider);
var _default = exports.default = RangeSlider;