devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
405 lines (402 loc) • 16 kB
JavaScript
/**
* DevExtreme (cjs/__internal/ui/editor/editor.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 _element_data = require("../../../core/element_data");
var _guid = _interopRequireDefault(require("../../../core/guid"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _callbacks = _interopRequireDefault(require("../../../core/utils/callbacks"));
var _extend = require("../../../core/utils/extend");
var _window = require("../../../core/utils/window");
var _validation_engine = _interopRequireDefault(require("../../../ui/validation_engine"));
var _validation_message = _interopRequireDefault(require("../../../ui/validation_message"));
var _widget = _interopRequireDefault(require("../../core/widget/widget"));
var _m_dom = _interopRequireDefault(require("../../core/utils/m_dom"));
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 INVALID_MESSAGE_AUTO = "dx-invalid-message-auto";
const READONLY_STATE_CLASS = "dx-state-readonly";
const INVALID_CLASS = "dx-invalid";
const DX_INVALID_BADGE_CLASS = "dx-show-invalid-badge";
const VALIDATION_TARGET = "dx-validation-target";
const VALIDATION_STATUS_VALID = "valid";
const VALIDATION_STATUS_INVALID = "invalid";
const READONLY_NAMESPACE = "editorReadOnly";
const ALLOWED_STYLING_MODES = ["outlined", "filled", "underlined"];
const VALIDATION_MESSAGE_KEYS_MAP = {
validationMessageMode: "mode",
validationMessagePosition: "positionSide",
validationMessageOffset: "offset",
validationBoundary: "boundary"
};
class Editor extends _widget.default {
ctor(element, options) {
this.showValidationMessageTimeout = void 0;
this.validationRequest = (0, _callbacks.default)();
super.ctor(element, options)
}
_createElement(element) {
super._createElement(element);
const $element = this.$element();
if ($element) {
(0, _element_data.data)($element[0], VALIDATION_TARGET, this)
}
}
_initOptions(options) {
super._initOptions(options);
this.option(_validation_engine.default.initValidationOptions(options))
}
_init() {
this._initialValue = this.option("value");
super._init();
const {
validationTooltipOptions: validationTooltipOptions
} = this.option();
this._options.cache("validationTooltipOptions", validationTooltipOptions);
const $element = this.$element();
$element.addClass(DX_INVALID_BADGE_CLASS)
}
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
value: null,
name: "",
onValueChanged: null,
readOnly: false,
isValid: true,
validationError: null,
validationErrors: null,
validationStatus: "valid",
validationMessageMode: "auto",
validationMessagePosition: "bottom",
validationBoundary: void 0,
validationMessageOffset: {
h: 0,
v: 0
},
validationTooltipOptions: {},
_showValidationMessage: true,
isDirty: false
})
}
_attachKeyboardEvents() {
if (!this.option("readOnly")) {
super._attachKeyboardEvents()
}
}
_setOptionsByReference() {
super._setOptionsByReference();
(0, _extend.extend)(this._optionsByReference, {
validationError: true
})
}
_createValueChangeAction() {
this._valueChangeAction = this._createActionByOption("onValueChanged", {
excludeValidators: ["disabled", "readOnly"]
})
}
_suppressValueChangeAction() {
this._valueChangeActionSuppressed = true
}
_resumeValueChangeAction() {
this._valueChangeActionSuppressed = false
}
_initMarkup() {
this._toggleReadOnlyState();
const {
name: name,
_onMarkupRendered: markupRendered
} = this.option();
this._setSubmitElementName(name);
super._initMarkup();
this._renderValidationState();
null === markupRendered || void 0 === markupRendered || markupRendered()
}
_raiseValueChangeAction(value, previousValue) {
if (!this._valueChangeAction) {
this._createValueChangeAction()
}
this._valueChangeAction(this._valueChangeArgs(value, previousValue))
}
_valueChangeArgs(value, previousValue) {
return {
value: value,
previousValue: previousValue,
event: this._valueChangeEventInstance
}
}
_saveValueChangeEvent(e) {
this._valueChangeEventInstance = e
}
_focusInHandler(e) {
const {
validationMessageMode: validationMessageMode
} = this.option();
const isValidationMessageShownOnFocus = "auto" === validationMessageMode;
if (this._canValueBeChangedByClick() && isValidationMessageShownOnFocus) {
var _this$_validationMess;
const $validationMessageWrapper = null === (_this$_validationMess = this._validationMessage) || void 0 === _this$_validationMess ? void 0 : _this$_validationMess.$wrapper();
null === $validationMessageWrapper || void 0 === $validationMessageWrapper || $validationMessageWrapper.removeClass(INVALID_MESSAGE_AUTO);
clearTimeout(this.showValidationMessageTimeout);
this.showValidationMessageTimeout = setTimeout((() => null === $validationMessageWrapper || void 0 === $validationMessageWrapper ? void 0 : $validationMessageWrapper.addClass(INVALID_MESSAGE_AUTO)), 150)
}
super._focusInHandler(e)
}
_canValueBeChangedByClick() {
return false
}
_getStylingModePrefix() {
return "dx-editor-"
}
_renderStylingMode() {
const {
stylingMode: stylingMode
} = this.option();
const prefix = this._getStylingModePrefix();
const allowedStylingClasses = ALLOWED_STYLING_MODES.map((mode => prefix + mode));
allowedStylingClasses.forEach((className => this.$element().removeClass(className)));
let stylingModeClass = prefix + String(stylingMode);
if (!allowedStylingClasses.includes(stylingModeClass)) {
const optionName = "stylingMode";
const defaultOptionValue = this._getDefaultOptions()[optionName];
const platformOptionValue = this._convertRulesToOptions(this._defaultOptionsRules())[optionName];
stylingModeClass = prefix + (platformOptionValue ?? defaultOptionValue)
}
this.$element().addClass(stylingModeClass)
}
_getValidationErrors() {
let {
validationErrors: validationErrors
} = this.option();
const {
validationError: validationError
} = this.option();
if (!validationErrors && validationError) {
validationErrors = [validationError]
}
return validationErrors
}
_disposeValidationMessage() {
if (this._$validationMessage) {
this._$validationMessage.remove();
this.setAria("describedby", null);
this._$validationMessage = void 0;
this._validationMessage = void 0
}
}
_toggleValidationClasses(isInvalid) {
this.$element().toggleClass("dx-invalid", isInvalid);
this.setAria("invalid", isInvalid || void 0)
}
_renderValidationState() {
const {
validationStatus: validationStatus,
_showValidationMessage: showValidationMessage
} = this.option();
const isValid = this.option("isValid") && "invalid" !== validationStatus;
const validationErrors = this._getValidationErrors();
const $element = this.$element();
this._toggleValidationClasses(!isValid);
if (!(0, _window.hasWindow)() || !showValidationMessage) {
return
}
this._disposeValidationMessage();
if (!isValid && validationErrors) {
const {
validationMessageMode: validationMessageMode,
validationMessageOffset: validationMessageOffset,
validationBoundary: validationBoundary,
rtlEnabled: rtlEnabled
} = this.option();
this._$validationMessage = (0, _renderer.default)("<div>").appendTo($element);
const validationMessageContentId = `dx-${new _guid.default}`;
this.setAria("describedby", validationMessageContentId);
this._validationMessage = new _validation_message.default(this._$validationMessage, (0, _extend.extend)({
validationErrors: validationErrors,
rtlEnabled: rtlEnabled,
target: this._getValidationMessageTarget(),
visualContainer: $element,
mode: validationMessageMode,
positionSide: this._getValidationMessagePosition(),
offset: validationMessageOffset,
boundary: validationBoundary,
contentId: validationMessageContentId
}, this._options.cache("validationTooltipOptions")));
this._bindInnerWidgetOptions(this._validationMessage, "validationTooltipOptions")
}
}
_getValidationMessagePosition() {
const {
validationMessagePosition: validationMessagePosition
} = this.option();
return validationMessagePosition
}
_getValidationMessageTarget() {
return this.$element()
}
_toggleReadOnlyState() {
const {
readOnly: readOnly
} = this.option();
this._toggleBackspaceHandler(readOnly);
this.$element().toggleClass("dx-state-readonly", !!readOnly);
this._setAriaReadonly(readOnly)
}
_setAriaReadonly(readOnly) {
this.setAria("readonly", readOnly || void 0)
}
_toggleBackspaceHandler(isReadOnly) {
const $eventTarget = this._keyboardEventBindingTarget();
const eventName = (0, _index.addNamespace)("keydown", "editorReadOnly");
_events_engine.default.off($eventTarget, eventName);
if (isReadOnly) {
_events_engine.default.on($eventTarget, eventName, (e => {
if ("backspace" === (0, _index.normalizeKeyName)(e)) {
e.preventDefault()
}
}))
}
}
_dispose() {
const element = this.$element()[0];
(0, _element_data.data)(element, VALIDATION_TARGET, null);
clearTimeout(this.showValidationMessageTimeout);
this._disposeValidationMessage();
super._dispose()
}
_setSubmitElementName(name) {
const $submitElement = this._getSubmitElement();
if (!$submitElement) {
return
}
if (name && name.length > 0) {
$submitElement.attr("name", name)
} else {
$submitElement.removeAttr("name")
}
}
_getSubmitElement() {
return null
}
_setValidationMessageOption(_ref) {
var _this$_validationMess2;
let {
name: name,
value: value
} = _ref;
const optionKey = VALIDATION_MESSAGE_KEYS_MAP[String(name)] ? VALIDATION_MESSAGE_KEYS_MAP[String(name)] : name;
null === (_this$_validationMess2 = this._validationMessage) || void 0 === _this$_validationMess2 || _this$_validationMess2.option(optionKey, value)
}
_hasActiveElement() {
return false
}
_optionChanged(args) {
var _this$_validationMess3;
const {
name: name,
value: value,
previousValue: previousValue
} = args;
switch (name) {
case "onValueChanged":
this._createValueChangeAction();
break;
case "readOnly":
this._toggleReadOnlyState();
this._refreshFocusState();
break;
case "value":
if (value != previousValue) {
this.option("isDirty", this._initialValue !== value);
this.validationRequest.fire({
value: value,
editor: this
})
}
if (!this._valueChangeActionSuppressed) {
this._raiseValueChangeAction(value, previousValue);
this._saveValueChangeEvent(void 0)
}
break;
case "width":
super._optionChanged(args);
null === (_this$_validationMess3 = this._validationMessage) || void 0 === _this$_validationMess3 || _this$_validationMess3.updateMaxWidth();
break;
case "name":
this._setSubmitElementName(value);
break;
case "isValid":
case "validationError":
case "validationErrors":
case "validationStatus":
this.option(_validation_engine.default.synchronizeValidationOptions(args, this.option()));
this._renderValidationState();
break;
case "validationBoundary":
case "validationMessageMode":
case "validationMessagePosition":
case "validationMessageOffset":
this._setValidationMessageOption(args);
break;
case "rtlEnabled":
this._setValidationMessageOption(args);
super._optionChanged(args);
break;
case "validationTooltipOptions":
this._innerWidgetOptionChanged(this._validationMessage, args);
break;
case "_showValidationMessage":
case "isDirty":
break;
default:
super._optionChanged(args)
}
}
_resetToInitialValue() {
this.option("value", this._initialValue)
}
blur() {
if (this._hasActiveElement()) {
_m_dom.default.resetActiveElement()
}
}
clear() {
const defaultOptions = this._getDefaultOptions();
this.option("value", defaultOptions.value)
}
reset() {
let value = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : void 0;
if (arguments.length) {
this._initialValue = value
}
this._resetToInitialValue();
this.option("isDirty", false);
this.option("isValid", true)
}
}
Editor.isEditor = instance => instance instanceof Editor;
var _default = exports.default = Editor;