UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

332 lines (331 loc) • 13.1 kB
/** * DevExtreme (esm/ui/editor/editor.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../core/renderer"; import { data } from "../../core/element_data"; import Callbacks from "../../core/utils/callbacks"; import { hasWindow } from "../../core/utils/window"; import { addNamespace, normalizeKeyName } from "../../events/utils/index"; import { extend } from "../../core/utils/extend"; import Widget from "../widget/ui.widget"; import ValidationEngine from "../validation_engine"; import EventsEngine from "../../events/core/events_engine"; import ValidationMessage from "../validation_message"; import Guid from "../../core/guid"; import { noop } from "../../core/utils/common"; import { resetActiveElement } from "../../core/utils/dom"; var INVALID_MESSAGE_AUTO = "dx-invalid-message-auto"; var READONLY_STATE_CLASS = "dx-state-readonly"; var INVALID_CLASS = "dx-invalid"; var DX_INVALID_BADGE_CLASS = "dx-show-invalid-badge"; var VALIDATION_TARGET = "dx-validation-target"; var VALIDATION_STATUS_VALID = "valid"; var VALIDATION_STATUS_INVALID = "invalid"; var READONLY_NAMESPACE = "editorReadOnly"; var ALLOWED_STYLING_MODES = ["outlined", "filled", "underlined"]; var VALIDATION_MESSAGE_KEYS_MAP = { validationMessageMode: "mode", validationMessageOffset: "offset", validationBoundary: "boundary" }; var Editor = Widget.inherit({ ctor: function() { this.showValidationMessageTimeout = null; this.validationRequest = Callbacks(); this.callBase.apply(this, arguments) }, _createElement: function(element) { this.callBase(element); var $element = this.$element(); if ($element) { data($element[0], VALIDATION_TARGET, this) } }, _initOptions: function(options) { this.callBase.apply(this, arguments); this.option(ValidationEngine.initValidationOptions(options)) }, _init: function() { this.callBase(); this._options.cache("validationTooltipOptions", this.option("validationTooltipOptions")); var $element = this.$element(); $element.addClass(DX_INVALID_BADGE_CLASS) }, _getDefaultOptions: function() { return extend(this.callBase(), { value: null, name: "", onValueChanged: null, readOnly: false, isValid: true, validationError: null, validationErrors: null, validationStatus: VALIDATION_STATUS_VALID, validationMessageMode: "auto", validationBoundary: void 0, validationMessageOffset: { h: 0, v: 0 }, validationTooltipOptions: {} }) }, _attachKeyboardEvents: function() { if (!this.option("readOnly")) { this.callBase() } }, _setOptionsByReference: function() { this.callBase(); extend(this._optionsByReference, { validationError: true }) }, _createValueChangeAction: function() { this._valueChangeAction = this._createActionByOption("onValueChanged", { excludeValidators: ["disabled", "readOnly"] }) }, _suppressValueChangeAction: function() { this._valueChangeActionSuppressed = true }, _resumeValueChangeAction: function() { this._valueChangeActionSuppressed = false }, _initMarkup: function() { this._toggleReadOnlyState(); this._setSubmitElementName(this.option("name")); this.callBase(); this._renderValidationState() }, _raiseValueChangeAction: function(value, previousValue) { if (!this._valueChangeAction) { this._createValueChangeAction() } this._valueChangeAction(this._valueChangeArgs(value, previousValue)) }, _valueChangeArgs: function(value, previousValue) { return { value: value, previousValue: previousValue, event: this._valueChangeEventInstance } }, _saveValueChangeEvent: function(e) { this._valueChangeEventInstance = e }, _focusInHandler: function(e) { var isValidationMessageShownOnFocus = "auto" === this.option("validationMessageMode"); if (this._canValueBeChangedByClick() && isValidationMessageShownOnFocus) { var _this$_validationMess; var $validationMessageWrapper = null === (_this$_validationMess = this._validationMessage) || void 0 === _this$_validationMess ? void 0 : _this$_validationMess.$wrapper(); null === $validationMessageWrapper || void 0 === $validationMessageWrapper ? void 0 : $validationMessageWrapper.removeClass(INVALID_MESSAGE_AUTO); clearTimeout(this.showValidationMessageTimeout); this.showValidationMessageTimeout = setTimeout(() => null === $validationMessageWrapper || void 0 === $validationMessageWrapper ? void 0 : $validationMessageWrapper.addClass(INVALID_MESSAGE_AUTO), 150) } return this.callBase(e) }, _canValueBeChangedByClick: function() { return false }, _getStylingModePrefix: function() { return "dx-editor-" }, _renderStylingMode: function() { var optionValue = this.option("stylingMode"); var prefix = this._getStylingModePrefix(); var allowedStylingClasses = ALLOWED_STYLING_MODES.map(mode => prefix + mode); allowedStylingClasses.forEach(className => this.$element().removeClass(className)); var stylingModeClass = prefix + optionValue; if (-1 === allowedStylingClasses.indexOf(stylingModeClass)) { var defaultOptionValue = this._getDefaultOptions().stylingMode; var platformOptionValue = this._convertRulesToOptions(this._defaultOptionsRules()).stylingMode; stylingModeClass = prefix + (platformOptionValue || defaultOptionValue) } this.$element().addClass(stylingModeClass) }, _getValidationErrors: function() { var validationErrors = this.option("validationErrors"); if (!validationErrors && this.option("validationError")) { validationErrors = [this.option("validationError")] } return validationErrors }, _disposeValidationMessage: function() { if (this._$validationMessage) { this._$validationMessage.remove(); this.setAria("describedby", null); this._$validationMessage = void 0; this._validationMessage = void 0 } }, _toggleValidationClasses: function(isInvalid) { this.$element().toggleClass(INVALID_CLASS, isInvalid); this.setAria(VALIDATION_STATUS_INVALID, isInvalid || void 0) }, _renderValidationState: function() { var isValid = this.option("isValid") && this.option("validationStatus") !== VALIDATION_STATUS_INVALID; var validationErrors = this._getValidationErrors(); var $element = this.$element(); this._toggleValidationClasses(!isValid); if (!hasWindow()) { return } this._disposeValidationMessage(); if (!isValid && validationErrors) { var { validationMessageMode: validationMessageMode, validationMessageOffset: validationMessageOffset, validationBoundary: validationBoundary, rtlEnabled: rtlEnabled } = this.option(); this._$validationMessage = $("<div>").appendTo($element); this.setAria("describedby", "dx-" + new Guid); this._validationMessage = new ValidationMessage(this._$validationMessage, extend({ validationErrors: validationErrors, rtlEnabled: rtlEnabled, target: this._getValidationMessageTarget(), container: $element, mode: validationMessageMode, positionRequest: "below", offset: validationMessageOffset, boundary: validationBoundary, describedElement: this._focusTarget() }, this._options.cache("validationTooltipOptions"))); this._bindInnerWidgetOptions(this._validationMessage, "validationTooltipOptions") } }, _getValidationMessageTarget: function() { return this.$element() }, _toggleReadOnlyState: function() { var readOnly = this.option("readOnly"); this._toggleBackspaceHandler(readOnly); this.$element().toggleClass(READONLY_STATE_CLASS, !!readOnly); this.setAria("readonly", readOnly || void 0) }, _toggleBackspaceHandler: function(isReadOnly) { var $eventTarget = this._keyboardEventBindingTarget(); var eventName = addNamespace("keydown", READONLY_NAMESPACE); EventsEngine.off($eventTarget, eventName); if (isReadOnly) { EventsEngine.on($eventTarget, eventName, e => { if ("backspace" === normalizeKeyName(e)) { e.preventDefault() } }) } }, _dispose: function() { var element = this.$element()[0]; data(element, VALIDATION_TARGET, null); clearTimeout(this.showValidationMessageTimeout); this._disposeValidationMessage(); this.callBase() }, _setSubmitElementName: function(name) { var $submitElement = this._getSubmitElement(); if (!$submitElement) { return } if (name.length > 0) { $submitElement.attr("name", name) } else { $submitElement.removeAttr("name") } }, _getSubmitElement: function() { return null }, _setValidationMessageOption: function(_ref) { var _this$_validationMess2; var { name: name, value: value } = _ref; var optionKey = VALIDATION_MESSAGE_KEYS_MAP[name] ? VALIDATION_MESSAGE_KEYS_MAP[name] : name; null === (_this$_validationMess2 = this._validationMessage) || void 0 === _this$_validationMess2 ? void 0 : _this$_validationMess2.option(optionKey, value) }, _hasActiveElement: noop, _optionChanged: function(args) { var _this$_validationMess3; switch (args.name) { case "onValueChanged": this._createValueChangeAction(); break; case "readOnly": this._toggleReadOnlyState(); this._refreshFocusState(); break; case "value": if (args.value != args.previousValue) { this.validationRequest.fire({ value: args.value, editor: this }) } if (!this._valueChangeActionSuppressed) { this._raiseValueChangeAction(args.value, args.previousValue); this._saveValueChangeEvent(void 0) } break; case "width": this.callBase(args); null === (_this$_validationMess3 = this._validationMessage) || void 0 === _this$_validationMess3 ? void 0 : _this$_validationMess3.updateMaxWidth(); break; case "name": this._setSubmitElementName(args.value); break; case "isValid": case "validationError": case "validationErrors": case "validationStatus": this.option(ValidationEngine.synchronizeValidationOptions(args, this.option())); this._renderValidationState(); break; case "validationBoundary": case "validationMessageMode": case "validationMessageOffset": this._setValidationMessageOption(args); break; case "rtlEnabled": this._setValidationMessageOption(args); this.callBase(args); break; case "validationTooltipOptions": this._innerWidgetOptionChanged(this._validationMessage, args); break; default: this.callBase(args) } }, blur: function() { if (this._hasActiveElement()) { resetActiveElement() } }, reset: function() { var defaultOptions = this._getDefaultOptions(); this.option("value", defaultOptions.value) } }); Editor.isEditor = instance => instance instanceof Editor; export default Editor;