UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

378 lines (376 loc) • 14.2 kB
/** * DevExtreme (cjs/ui/number_box/number_box.base.js) * Version: 23.2.6 * Build date: Wed May 01 2024 * * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; exports.default = void 0; var _renderer = _interopRequireDefault(require("../../core/renderer")); var _dom_adapter = _interopRequireDefault(require("../../core/dom_adapter")); var _events_engine = _interopRequireDefault(require("../../events/core/events_engine")); var _common = require("../../core/utils/common"); var _type = require("../../core/utils/type"); var _math = require("../../core/utils/math"); var _extend = require("../../core/utils/extend"); var _devices = _interopRequireDefault(require("../../core/devices")); var _browser = _interopRequireDefault(require("../../core/utils/browser")); var _ui = _interopRequireDefault(require("../text_box/ui.text_editor")); var _index = require("../../events/utils/index"); var _number_box = _interopRequireDefault(require("./number_box.spins")); var _message = _interopRequireDefault(require("../../localization/message")); var _deferred = require("../../core/utils/deferred"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } } const math = Math; const WIDGET_CLASS = "dx-numberbox"; const FIREFOX_CONTROL_KEYS = ["tab", "del", "backspace", "leftArrow", "rightArrow", "home", "end", "enter"]; const FORCE_VALUECHANGE_EVENT_NAMESPACE = "NumberBoxForceValueChange"; const NumberBoxBase = _ui.default.inherit({ _supportedKeys: function() { return (0, _extend.extend)(this.callBase(), { upArrow: function(e) { if (!(0, _index.isCommandKeyPressed)(e)) { e.preventDefault(); e.stopPropagation(); this._spinUpChangeHandler(e) } }, downArrow: function(e) { if (!(0, _index.isCommandKeyPressed)(e)) { e.preventDefault(); e.stopPropagation(); this._spinDownChangeHandler(e) } }, enter: function() {} }) }, _getDefaultOptions: function() { return (0, _extend.extend)(this.callBase(), { value: 0, min: void 0, max: void 0, step: 1, showSpinButtons: false, useLargeSpinButtons: true, mode: "text", invalidValueMessage: _message.default.format("dxNumberBox-invalidValueMessage"), buttons: void 0 }) }, _useTemplates: function() { return false }, _getDefaultButtons: function() { return this.callBase().concat([{ name: "spins", Ctor: _number_box.default }]) }, _isSupportInputMode: function() { const version = parseFloat(_browser.default.version); return _browser.default.chrome && version >= 66 || _browser.default.safari && version >= 12 }, _defaultOptionsRules: function() { return this.callBase().concat([{ device: function() { return _devices.default.real().generic && !_devices.default.isSimulator() }, options: { useLargeSpinButtons: false } }, { device: function() { return "desktop" !== _devices.default.real().deviceType && !this._isSupportInputMode() }.bind(this), options: { mode: "number" } }]) }, _initMarkup: function() { this._renderSubmitElement(); this.$element().addClass(WIDGET_CLASS); this.callBase() }, _getDefaultAttributes: function() { const attributes = this.callBase(); attributes.inputmode = "decimal"; return attributes }, _renderContentImpl: function() { this.option("isValid") && this._validateValue(this.option("value")); this.setAria("role", "spinbutton") }, _renderSubmitElement: function() { this._$submitElement = (0, _renderer.default)("<input>").attr("type", "hidden").appendTo(this.$element()); this._setSubmitValue(this.option("value")) }, _setSubmitValue: function(value) { this._getSubmitElement().val((0, _common.applyServerDecimalSeparator)(value)) }, _getSubmitElement: function() { return this._$submitElement }, _keyPressHandler: function(e) { this.callBase(e); const char = (0, _index.getChar)(e); const isInputCharValid = /[\d.,eE\-+]/.test(char); if (!isInputCharValid) { const keyName = (0, _index.normalizeKeyName)(e); if ((0, _index.isCommandKeyPressed)(e) || keyName && FIREFOX_CONTROL_KEYS.includes(keyName)) { return } e.preventDefault(); return false } this._keyPressed = true }, _onMouseWheel: function(dxEvent) { dxEvent.delta > 0 ? this._spinValueChange(1, dxEvent) : this._spinValueChange(-1, dxEvent) }, _renderValue: function() { const inputValue = this._input().val(); const value = this.option("value"); if (!inputValue.length || Number(inputValue) !== value) { this._forceValueRender(); this._toggleEmptinessEventHandler() } const valueText = (0, _type.isDefined)(value) ? null : _message.default.format("dxNumberBox-noDataText"); this.setAria({ valuenow: (0, _common.ensureDefined)(value, ""), valuetext: valueText }); this.option("text", this._input().val()); this._updateButtons(); return (new _deferred.Deferred).resolve() }, _forceValueRender: function() { const value = this.option("value"); const number = Number(value); const formattedValue = isNaN(number) ? "" : this._applyDisplayValueFormatter(value); this._renderDisplayText(formattedValue) }, _applyDisplayValueFormatter: function(value) { return this.option("displayValueFormatter")(value) }, _renderProps: function() { this._input().prop({ min: this.option("min"), max: this.option("max"), step: this.option("step") }); this.setAria({ valuemin: (0, _common.ensureDefined)(this.option("min"), ""), valuemax: (0, _common.ensureDefined)(this.option("max"), "") }) }, _spinButtonsPointerDownHandler: function() { const $input = this._input(); if (!this.option("useLargeSpinButtons") && _dom_adapter.default.getActiveElement() !== $input[0]) { _events_engine.default.trigger($input, "focus") } }, _spinUpChangeHandler: function(e) { if (!this.option("readOnly")) { this._spinValueChange(1, e.event || e) } }, _spinDownChangeHandler: function(e) { if (!this.option("readOnly")) { this._spinValueChange(-1, e.event || e) } }, _spinValueChange: function(sign, dxEvent) { const step = parseFloat(this.option("step")); if (0 === step) { return } let value = parseFloat(this._normalizeInputValue()) || 0; value = this._correctRounding(value, step * sign); const min = this.option("min"); const max = this.option("max"); if ((0, _type.isDefined)(min)) { value = Math.max(min, value) } if ((0, _type.isDefined)(max)) { value = Math.min(max, value) } this._saveValueChangeEvent(dxEvent); this.option("value", value) }, _correctRounding: function(value, step) { const regex = /[,.](.*)/; const isFloatValue = regex.test(value); const isFloatStep = regex.test(step); if (isFloatValue || isFloatStep) { const valueAccuracy = isFloatValue ? regex.exec(value)[0].length : 0; const stepAccuracy = isFloatStep ? regex.exec(step)[0].length : 0; const accuracy = math.max(valueAccuracy, stepAccuracy); value = this._round(value + step, accuracy); return value } return value + step }, _round: function(value, precision) { precision = precision || 0; const multiplier = Math.pow(10, precision); value *= multiplier; value = Math.round(value) / multiplier; return value }, _renderValueChangeEvent: function() { this.callBase(); const forceValueChangeEvent = (0, _index.addNamespace)("focusout", "NumberBoxForceValueChange"); _events_engine.default.off(this.element(), forceValueChangeEvent); _events_engine.default.on(this.element(), forceValueChangeEvent, this._forceRefreshInputValue.bind(this)) }, _forceRefreshInputValue: function() { if ("number" === this.option("mode")) { return } const $input = this._input(); const formattedValue = this._applyDisplayValueFormatter(this.option("value")); $input.val(null); $input.val(formattedValue) }, _valueChangeEventHandler: function(e) { const $input = this._input(); const inputValue = this._normalizeText(); const value = this._parseValue(inputValue); const valueHasDigits = "." !== inputValue && "-" !== inputValue; if (this._isValueValid() && !this._validateValue(value)) { $input.val(this._applyDisplayValueFormatter(value)); return } if (valueHasDigits) { this.callBase(e, isNaN(value) ? null : value) } this._applyValueBoundaries(inputValue, value); this.validationRequest.fire({ value: value, editor: this }) }, _applyValueBoundaries: function(inputValue, parsedValue) { const isValueIncomplete = this._isValueIncomplete(inputValue); const isValueCorrect = this._isValueInRange(inputValue); if (!isValueIncomplete && !isValueCorrect && null !== parsedValue) { if (Number(inputValue) !== parsedValue) { this._input().val(this._applyDisplayValueFormatter(parsedValue)) } } }, _replaceCommaWithPoint: function(value) { return value.replace(",", ".") }, _inputIsInvalid: function() { const isNumberMode = "number" === this.option("mode"); const validityState = this._input().get(0).validity; return isNumberMode && validityState && validityState.badInput }, _renderDisplayText: function(text) { if (this._inputIsInvalid()) { return } this.callBase(text) }, _isValueIncomplete: function(value) { return /(^-$)|(^-?\d*\.$)|(\d+e-?$)/i.test(value) }, _isValueInRange: function(value) { return (0, _math.inRange)(value, this.option("min"), this.option("max")) }, _isNumber: function(value) { return null !== this._parseValue(value) }, _validateValue: function(value) { const inputValue = this._normalizeText(); const isValueValid = this._isValueValid(); let isValid = true; const isNumber = this._isNumber(inputValue); if (isNaN(Number(value))) { isValid = false } if (!value && isValueValid) { isValid = true } else if (!isNumber && !isValueValid) { isValid = false } this.option({ isValid: isValid, validationError: isValid ? null : { editorSpecific: true, message: this.option("invalidValueMessage") } }); return isValid }, _normalizeInputValue: function() { return this._parseValue(this._normalizeText()) }, _normalizeText: function() { const value = this._input().val().trim(); return this._replaceCommaWithPoint(value) }, _parseValue: function(value) { const number = parseFloat(value); if (isNaN(number)) { return null } return (0, _math.fitIntoRange)(number, this.option("min"), this.option("max")) }, _clearValue: function() { if (this._inputIsInvalid()) { this._input().val(""); this._validateValue() } this.callBase() }, clear: function() { if (null === this.option("value")) { this.option("text", ""); if (this._input().length) { this._renderValue() } } else { this.option("value", null) } }, _optionChanged: function(args) { switch (args.name) { case "value": this._validateValue(args.value); this._setSubmitValue(args.value); this.callBase(args); this._resumeValueChangeAction(); break; case "step": this._renderProps(); break; case "min": case "max": this._renderProps(); this.option("value", this._parseValue(this.option("value"))); break; case "showSpinButtons": case "useLargeSpinButtons": this._updateButtons(["spins"]); break; case "invalidValueMessage": break; default: this.callBase(args) } } }); var _default = NumberBoxBase; exports.default = _default; module.exports = exports.default; module.exports.default = exports.default;